<commit_before>package assets

import (
	"bytes"
	"compress/gzip"
	"crypto/sha1"
	"fmt"
	"go/format"
	"io"
	"io/ioutil"
	"os"
	"path"
	"strings"
)

// An asset generator. The generator can be used to generate an asset go file
// with all the assets that were added to the generator embedded into it.
// The generated assets are made available by the specified go variable
// VariableName which is of type assets.FileSystem.
type Generator struct {
	// The package name to generate assets in,
	PackageName string

	// The variable name containing the asset filesystem (defaults to Assets),
	VariableName string

	// Whether the assets will be compressed using gzip (defaults to false),
	Compressed bool

	// Strip the specified prefix from all paths,
	StripPrefix string

	fsDirsMap  map[string][]string
	fsFilesMap map[string]os.FileInfo
}

func (x *Generator) addPath(parent string, info os.FileInfo) error {
	p := path.Join(parent, info.Name())

	if x.fsFilesMap == nil {
		x.fsFilesMap = make(map[string]os.FileInfo)
	}

	if x.fsDirsMap == nil {
		x.fsDirsMap = make(map[string][]string)
	}

	x.fsFilesMap[p] = info

	if info.IsDir() {
		f, err := os.Open(p)
		fi, err := f.Readdir(-1)

		if err != nil {
			return err
		}

		x.fsDirsMap[p] = make([]string, 0, len(fi))

		for _, f := range fi {
			if err := x.addPath(p, f); err != nil {
				return err
			}
		}
	} else {
		x.fsDirsMap[parent] = append(x.fsDirsMap[parent], info.Name())
	}

	return nil
}

// Add a file or directory asset to the generator. Added directories will be
// recursed automatically.
func (x *Generator) Add(p string) error {
	info, err := os.Stat(p)

	if err != nil {
		return err
	}

	return x.addPath(path.Dir(p), info)
}

// Write the asset tree specified in the generator to the given writer. The
// written asset tree is a valid, standalone go file with the assets
// embedded into it.
func (x *Generator) Write(wr io.Writer) error {
	p := x.PackageName

	if len(p) == 0 {
		p = "main"
	}

	variableName := x.VariableName

	if len(variableName) == 0 {
		variableName = "Assets"
	}

	writer := &bytes.Buffer{}

	// Write package and import
	fmt.Fprintf(writer, "package %s\n\n", p)
	fmt.Fprintln(writer, "import (")
	fmt.Fprintln(writer, "\t\"github.com/jessevdk/go-assets\"")
	fmt.Fprintln(writer, "\t\"time\"")
	fmt.Fprintln(writer, ")")
	fmt.Fprintln(writer)

	vnames := make(map[string]string)

	// Write file contents as const strings
	if x.fsFilesMap != nil {
		// Create mapping from full file path to asset variable name.
		// This also reads the file and writes the contents as a const
		// string
		for k, v := range x.fsFilesMap {
			if v.IsDir() {
				continue
			}

			f, err := os.Open(k)

			if err != nil {
				return err
			}

			defer f.Close()

			var data []byte

			if x.Compressed {
				buf := &bytes.Buffer{}
				gw := gzip.NewWriter(buf)

				if _, err := io.Copy(gw, f); err != nil {
					gw.Close()
					return err
				}

				gw.Close()
				data = buf.Bytes()
			} else {
				data, err = ioutil.ReadAll(f)

				if err != nil {
					return err
				}
			}

			s := sha1.New()
			io.WriteString(s, k)

			vname := fmt.Sprintf("__%s%x", variableName, s.Sum(nil))
			vnames[k] = vname

			fmt.Fprintf(writer, "var %s = []byte(%#v)\n", vname, string(data))
		}

		fmt.Fprintln(writer)
	}

	fmt.Fprintf(writer, "var %s assets.FileSystem\n\n", variableName)

	fmt.Fprintln(writer, "func init() {")
	fmt.Fprintf(writer, "\t%s = assets.FileSystem{\n", variableName)

	if x.fsDirsMap == nil {
		x.fsDirsMap = make(map[string][]string)
	}

	if x.fsFilesMap == nil {
		x.fsFilesMap = make(map[string]os.FileInfo)
	}

	dirmap := make(map[string][]string)

	for k, v := range x.fsDirsMap {
		vv := make([]string, len(v))

		for i, vi := range v {
			vv[i] = strings.TrimPrefix(vi, x.StripPrefix)

			if len(vv[i]) == 0 {
				vv[i] = "/"
			}
		}

		kk := strings.TrimPrefix(k, x.StripPrefix)

		if len(kk) == 0 {
			kk = "/"
		}

		dirmap[kk] = vv
	}

	fmt.Fprintf(writer, "\t\tDirs: %#v,\n", dirmap)
	fmt.Fprintln(writer, "\t\tFiles: map[string]*assets.File{")

	// Write files
	for k, v := range x.fsFilesMap {
		kk := strings.TrimPrefix(k, x.StripPrefix)

		if len(kk) == 0 {
			kk = "/"
		}

		fmt.Fprintf(writer, "\t\t\t%#v: &assets.File{\n", kk)
		fmt.Fprintf(writer, "\t\t\t\tPath:     %#v,\n", kk)
		fmt.Fprintf(writer, "\t\t\t\tFileMode: %#v,\n", v.Mode())

		mt := v.ModTime()

		fmt.Fprintf(writer, "\t\t\t\tMTime:    time.Unix(%#v, %#v),\n", mt.Unix(), mt.UnixNano())

		if !v.IsDir() {
			fmt.Fprintf(writer, "\t\t\t\tData:     %s,\n", vnames[k])
		}

		fmt.Fprintln(writer, "\t\t\t},")
	}

	fmt.Fprintln(writer, "\t\t},")
	fmt.Fprintf(writer, "\t\tCompressed: %#v,\n", x.Compressed)
	fmt.Fprintf(writer, "\t}\n")
	fmt.Fprintln(writer, "}")

	ret, err := format.Source(writer.Bytes())

	if err != nil {
		return err
	}

	wr.Write(ret)
	return nil
}
<commit_msg>Clean paths<commit_after>package assets

import (
	"bytes"
	"compress/gzip"
	"crypto/sha1"
	"fmt"
	"go/format"
	"io"
	"io/ioutil"
	"os"
	"path"
	"strings"
)

// An asset generator. The generator can be used to generate an asset go file
// with all the assets that were added to the generator embedded into it.
// The generated assets are made available by the specified go variable
// VariableName which is of type assets.FileSystem.
type Generator struct {
	// The package name to generate assets in,
	PackageName string

	// The variable name containing the asset filesystem (defaults to Assets),
	VariableName string

	// Whether the assets will be compressed using gzip (defaults to false),
	Compressed bool

	// Strip the specified prefix from all paths,
	StripPrefix string

	fsDirsMap  map[string][]string
	fsFilesMap map[string]os.FileInfo
}

func (x *Generator) addPath(parent string, info os.FileInfo) error {
	p := path.Join(parent, info.Name())

	if x.fsFilesMap == nil {
		x.fsFilesMap = make(map[string]os.FileInfo)
	}

	if x.fsDirsMap == nil {
		x.fsDirsMap = make(map[string][]string)
	}

	x.fsFilesMap[p] = info

	if info.IsDir() {
		f, err := os.Open(p)
		fi, err := f.Readdir(-1)

		if err != nil {
			return err
		}

		x.fsDirsMap[p] = make([]string, 0, len(fi))

		for _, f := range fi {
			if err := x.addPath(p, f); err != nil {
				return err
			}
		}
	} else {
		x.fsDirsMap[parent] = append(x.fsDirsMap[parent], info.Name())
	}

	return nil
}

// Add a file or directory asset to the generator. Added directories will be
// recursed automatically.
func (x *Generator) Add(p string) error {
	p = path.Clean(p)

	info, err := os.Stat(p)

	if err != nil {
		return err
	}

	return x.addPath(path.Dir(p), info)
}

// Write the asset tree specified in the generator to the given writer. The
// written asset tree is a valid, standalone go file with the assets
// embedded into it.
func (x *Generator) Write(wr io.Writer) error {
	p := x.PackageName

	if len(p) == 0 {
		p = "main"
	}

	variableName := x.VariableName

	if len(variableName) == 0 {
		variableName = "Assets"
	}

	writer := &bytes.Buffer{}

	// Write package and import
	fmt.Fprintf(writer, "package %s\n\n", p)
	fmt.Fprintln(writer, "import (")
	fmt.Fprintln(writer, "\t\"github.com/jessevdk/go-assets\"")
	fmt.Fprintln(writer, "\t\"time\"")
	fmt.Fprintln(writer, ")")
	fmt.Fprintln(writer)

	vnames := make(map[string]string)

	// Write file contents as const strings
	if x.fsFilesMap != nil {
		// Create mapping from full file path to asset variable name.
		// This also reads the file and writes the contents as a const
		// string
		for k, v := range x.fsFilesMap {
			if v.IsDir() {
				continue
			}

			f, err := os.Open(k)

			if err != nil {
				return err
			}

			defer f.Close()

			var data []byte

			if x.Compressed {
				buf := &bytes.Buffer{}
				gw := gzip.NewWriter(buf)

				if _, err := io.Copy(gw, f); err != nil {
					gw.Close()
					return err
				}

				gw.Close()
				data = buf.Bytes()
			} else {
				data, err = ioutil.ReadAll(f)

				if err != nil {
					return err
				}
			}

			s := sha1.New()
			io.WriteString(s, k)

			vname := fmt.Sprintf("__%s%x", variableName, s.Sum(nil))
			vnames[k] = vname

			fmt.Fprintf(writer, "var %s = []byte(%#v)\n", vname, string(data))
		}

		fmt.Fprintln(writer)
	}

	fmt.Fprintf(writer, "var %s assets.FileSystem\n\n", variableName)

	fmt.Fprintln(writer, "func init() {")
	fmt.Fprintf(writer, "\t%s = assets.FileSystem{\n", variableName)

	if x.fsDirsMap == nil {
		x.fsDirsMap = make(map[string][]string)
	}

	if x.fsFilesMap == nil {
		x.fsFilesMap = make(map[string]os.FileInfo)
	}

	dirmap := make(map[string][]string)

	for k, v := range x.fsDirsMap {
		vv := make([]string, len(v))

		for i, vi := range v {
			vv[i] = strings.TrimPrefix(vi, x.StripPrefix)

			if len(vv[i]) == 0 {
				vv[i] = "/"
			}
		}

		kk := strings.TrimPrefix(k, x.StripPrefix)

		if len(kk) == 0 {
			kk = "/"
		}

		dirmap[kk] = vv
	}

	fmt.Fprintf(writer, "\t\tDirs: %#v,\n", dirmap)
	fmt.Fprintln(writer, "\t\tFiles: map[string]*assets.File{")

	// Write files
	for k, v := range x.fsFilesMap {
		kk := strings.TrimPrefix(k, x.StripPrefix)

		if len(kk) == 0 {
			kk = "/"
		}

		fmt.Fprintf(writer, "\t\t\t%#v: &assets.File{\n", kk)
		fmt.Fprintf(writer, "\t\t\t\tPath:     %#v,\n", kk)
		fmt.Fprintf(writer, "\t\t\t\tFileMode: %#v,\n", v.Mode())

		mt := v.ModTime()

		fmt.Fprintf(writer, "\t\t\t\tMTime:    time.Unix(%#v, %#v),\n", mt.Unix(), mt.UnixNano())

		if !v.IsDir() {
			fmt.Fprintf(writer, "\t\t\t\tData:     %s,\n", vnames[k])
		}

		fmt.Fprintln(writer, "\t\t\t},")
	}

	fmt.Fprintln(writer, "\t\t},")
	fmt.Fprintf(writer, "\t\tCompressed: %#v,\n", x.Compressed)
	fmt.Fprintf(writer, "\t}\n")
	fmt.Fprintln(writer, "}")

	ret, err := format.Source(writer.Bytes())

	if err != nil {
		return err
	}

	wr.Write(ret)
	return nil
}
<|endoftext|>


<commit_before>package appui

import (
	"io"

	"github.com/moncho/dry/ui"
	"github.com/nsf/termbox-go"
)

//Stream shows the content of the given stream on screen
func Stream(screen *ui.Screen, stream io.ReadCloser, keyboardQueue chan termbox.Event, closeView chan<- struct{}) {
	defer func() {
		closeView <- struct{}{}
	}()
	screen.Clear()
	screen.Sync()
	v := ui.NewLess(DryTheme)
	//TODO make sure that io errors can be safely ignored
	go io.Copy(v, stream)
	if err := v.Focus(keyboardQueue); err != nil {
		ui.ShowErrorMessage(screen, keyboardQueue, closeView, err)
	}

	stream.Close()
	termbox.HideCursor()
	screen.Clear()
	screen.Sync()
}
<commit_msg>Use StdCopy to write logs to buffer<commit_after>package appui

import (
	"io"

	"github.com/docker/docker/pkg/stdcopy"
	"github.com/moncho/dry/ui"
	"github.com/nsf/termbox-go"
)

//Stream shows the content of the given stream on screen
func Stream(screen *ui.Screen, stream io.ReadCloser, keyboardQueue chan termbox.Event, closeView chan<- struct{}) {
	defer func() {
		closeView <- struct{}{}
	}()
	screen.Clear()
	screen.Sync()
	v := ui.NewLess(DryTheme)
	//TODO make sure that io errors can be safely ignored
	go stdcopy.StdCopy(v, v, stream)
	if err := v.Focus(keyboardQueue); err != nil {
		ui.ShowErrorMessage(screen, keyboardQueue, closeView, err)
	}

	stream.Close()
	termbox.HideCursor()
	screen.Clear()
	screen.Sync()
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"math/rand"
	"strings"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/autoscaling"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSLaunchConfiguration_basic(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationNoNameConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
						"aws_launch_configuration.bar", "terraform-"),
				),
			},
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationPrefixNameConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf),
					testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
						"aws_launch_configuration.baz", "baz-"),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withBlockDevices(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					testAccCheckAWSLaunchConfigurationAttributes(&conf),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "image_id", "ami-21f78e11"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "instance_type", "m1.small"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "associate_public_ip_address", "true"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "spot_price", ""),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withSpotPrice(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationWithSpotPriceConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "spot_price", "0.01"),
				),
			},
		},
	})
}

func testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
	resource, prefix string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		r, ok := s.RootModule().Resources[resource]
		if !ok {
			return fmt.Errorf("Resource not found")
		}
		name, ok := r.Primary.Attributes["name"]
		if !ok {
			return fmt.Errorf("Name attr not found: %#v", r.Primary.Attributes)
		}
		if !strings.HasPrefix(name, prefix) {
			return fmt.Errorf("Name: %q, does not have prefix: %q", name, prefix)
		}
		return nil
	}
}

func testAccCheckAWSLaunchConfigurationDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).autoscalingconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_launch_configuration" {
			continue
		}

		describe, err := conn.DescribeLaunchConfigurations(
			&autoscaling.DescribeLaunchConfigurationsInput{
				LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)},
			})

		if err == nil {
			if len(describe.LaunchConfigurations) != 0 &&
				*describe.LaunchConfigurations[0].LaunchConfigurationName == rs.Primary.ID {
				return fmt.Errorf("Launch Configuration still exists")
			}
		}

		// Verify the error
		providerErr, ok := err.(awserr.Error)
		if !ok {
			return err
		}
		if providerErr.Code() != "InvalidLaunchConfiguration.NotFound" {
			return err
		}
	}

	return nil
}

func testAccCheckAWSLaunchConfigurationAttributes(conf *autoscaling.LaunchConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *conf.ImageId != "ami-21f78e11" {
			return fmt.Errorf("Bad image_id: %s", *conf.ImageId)
		}

		if !strings.HasPrefix(*conf.LaunchConfigurationName, "terraform-") {
			return fmt.Errorf("Bad name: %s", *conf.LaunchConfigurationName)
		}

		if *conf.InstanceType != "m1.small" {
			return fmt.Errorf("Bad instance_type: %s", *conf.InstanceType)
		}

		// Map out the block devices by name, which should be unique.
		blockDevices := make(map[string]*autoscaling.BlockDeviceMapping)
		for _, blockDevice := range conf.BlockDeviceMappings {
			blockDevices[*blockDevice.DeviceName] = blockDevice
		}

		// Check if the root block device exists.
		if _, ok := blockDevices["/dev/sda1"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sda1")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		}

		// Check if the third block device exists.
		if _, ok := blockDevices["/dev/sdc"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdc")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		}

		return nil
	}
}

func testAccCheckAWSLaunchConfigurationExists(n string, res *autoscaling.LaunchConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No Launch Configuration ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).autoscalingconn

		describeOpts := autoscaling.DescribeLaunchConfigurationsInput{
			LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)},
		}
		describe, err := conn.DescribeLaunchConfigurations(&describeOpts)

		if err != nil {
			return err
		}

		if len(describe.LaunchConfigurations) != 1 ||
			*describe.LaunchConfigurations[0].LaunchConfigurationName != rs.Primary.ID {
			return fmt.Errorf("Launch Configuration Group not found")
		}

		*res = *describe.LaunchConfigurations[0]

		return nil
	}
}

var testAccAWSLaunchConfigurationConfig = fmt.Sprintf(`
resource "aws_launch_configuration" "bar" {
  name = "terraform-test-%d"
  image_id = "ami-21f78e11"
  instance_type = "m1.small"
  user_data = "foobar-user-data"
  associate_public_ip_address = true

	root_block_device {
		volume_type = "gp2"
		volume_size = 11
	}
	ebs_block_device {
		device_name = "/dev/sdb"
		volume_size = 9
	}
	ebs_block_device {
		device_name = "/dev/sdc"
		volume_size = 10
		volume_type = "io1"
		iops = 100
	}
	ephemeral_block_device {
		device_name = "/dev/sde"
		virtual_name = "ephemeral0"
	}
}
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())

var testAccAWSLaunchConfigurationWithSpotPriceConfig = fmt.Sprintf(`
resource "aws_launch_configuration" "bar" {
  name = "terraform-test-%d"
  image_id = "ami-21f78e11"
  instance_type = "t1.micro"
  spot_price = "0.01"
}
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())

const testAccAWSLaunchConfigurationNoNameConfig = `
resource "aws_launch_configuration" "bar" {
   image_id = "ami-21f78e11"
   instance_type = "t1.micro"
   user_data = "foobar-user-data-change"
   associate_public_ip_address = false
}
`

const testAccAWSLaunchConfigurationPrefixNameConfig = `
resource "aws_launch_configuration" "baz" {
   name_prefix = "baz-"
   image_id = "ami-21f78e11"
   instance_type = "t1.micro"
   user_data = "foobar-user-data-change"
   associate_public_ip_address = false
}
`
<commit_msg>Added an acceptance test<commit_after>package aws

import (
	"fmt"
	"math/rand"
	"strings"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/autoscaling"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSLaunchConfiguration_basic(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationNoNameConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
						"aws_launch_configuration.bar", "terraform-"),
				),
			},
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationPrefixNameConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf),
					testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
						"aws_launch_configuration.baz", "baz-"),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withBlockDevices(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					testAccCheckAWSLaunchConfigurationAttributes(&conf),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "image_id", "ami-21f78e11"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "instance_type", "m1.small"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "associate_public_ip_address", "true"),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "spot_price", ""),
				),
			},
		},
	})
}

func TestAccAWSLaunchConfiguration_withSpotPrice(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationWithSpotPriceConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
					resource.TestCheckResourceAttr(
						"aws_launch_configuration.bar", "spot_price", "0.01"),
				),
			},
		},
	})
}

func testAccCheckAWSLaunchConfigurationWithEncryption(conf *autoscaling.LaunchConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Map out the block devices by name, which should be unique.
		blockDevices := make(map[string]*autoscaling.BlockDeviceMapping)
		for _, blockDevice := range conf.BlockDeviceMappings {
			blockDevices[*blockDevice.DeviceName] = blockDevice
		}

		// Check if the root block device exists.
		if _, ok := blockDevices["/dev/sda1"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sda1")
		} else if blockDevices["/dev/sda1"].Ebs.Encrypted != nil {
			return fmt.Errorf("root device should not include value for Encrypted")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		} else if !*blockDevices["/dev/sdb"].Ebs.Encrypted {
			return fmt.Errorf("block device isn't encrypted as expected: /dev/sdb")
		}

		return nil
	}
}

func TestAccAWSLaunchConfiguration_withEncryption(t *testing.T) {
	var conf autoscaling.LaunchConfiguration

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSLaunchConfigurationWithEncryption,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf),

					testAccCheckAWSLaunchConfigurationWithEncryption(&conf),
				),
			},
		},
	})
}

func testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
	resource, prefix string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		r, ok := s.RootModule().Resources[resource]
		if !ok {
			return fmt.Errorf("Resource not found")
		}
		name, ok := r.Primary.Attributes["name"]
		if !ok {
			return fmt.Errorf("Name attr not found: %#v", r.Primary.Attributes)
		}
		if !strings.HasPrefix(name, prefix) {
			return fmt.Errorf("Name: %q, does not have prefix: %q", name, prefix)
		}
		return nil
	}
}

func testAccCheckAWSLaunchConfigurationDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).autoscalingconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_launch_configuration" {
			continue
		}

		describe, err := conn.DescribeLaunchConfigurations(
			&autoscaling.DescribeLaunchConfigurationsInput{
				LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)},
			})

		if err == nil {
			if len(describe.LaunchConfigurations) != 0 &&
				*describe.LaunchConfigurations[0].LaunchConfigurationName == rs.Primary.ID {
				return fmt.Errorf("Launch Configuration still exists")
			}
		}

		// Verify the error
		providerErr, ok := err.(awserr.Error)
		if !ok {
			return err
		}
		if providerErr.Code() != "InvalidLaunchConfiguration.NotFound" {
			return err
		}
	}

	return nil
}

func testAccCheckAWSLaunchConfigurationAttributes(conf *autoscaling.LaunchConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *conf.ImageId != "ami-21f78e11" {
			return fmt.Errorf("Bad image_id: %s", *conf.ImageId)
		}

		if !strings.HasPrefix(*conf.LaunchConfigurationName, "terraform-") {
			return fmt.Errorf("Bad name: %s", *conf.LaunchConfigurationName)
		}

		if *conf.InstanceType != "m1.small" {
			return fmt.Errorf("Bad instance_type: %s", *conf.InstanceType)
		}

		// Map out the block devices by name, which should be unique.
		blockDevices := make(map[string]*autoscaling.BlockDeviceMapping)
		for _, blockDevice := range conf.BlockDeviceMappings {
			blockDevices[*blockDevice.DeviceName] = blockDevice
		}

		// Check if the root block device exists.
		if _, ok := blockDevices["/dev/sda1"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sda1")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		}

		// Check if the third block device exists.
		if _, ok := blockDevices["/dev/sdc"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdc")
		}

		// Check if the secondary block device exists.
		if _, ok := blockDevices["/dev/sdb"]; !ok {
			return fmt.Errorf("block device doesn't exist: /dev/sdb")
		}

		return nil
	}
}

func testAccCheckAWSLaunchConfigurationExists(n string, res *autoscaling.LaunchConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No Launch Configuration ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).autoscalingconn

		describeOpts := autoscaling.DescribeLaunchConfigurationsInput{
			LaunchConfigurationNames: []*string{aws.String(rs.Primary.ID)},
		}
		describe, err := conn.DescribeLaunchConfigurations(&describeOpts)

		if err != nil {
			return err
		}

		if len(describe.LaunchConfigurations) != 1 ||
			*describe.LaunchConfigurations[0].LaunchConfigurationName != rs.Primary.ID {
			return fmt.Errorf("Launch Configuration Group not found")
		}

		*res = *describe.LaunchConfigurations[0]

		return nil
	}
}

var testAccAWSLaunchConfigurationConfig = fmt.Sprintf(`
resource "aws_launch_configuration" "bar" {
  name = "terraform-test-%d"
  image_id = "ami-21f78e11"
  instance_type = "m1.small"
  user_data = "foobar-user-data"
  associate_public_ip_address = true

	root_block_device {
		volume_type = "gp2"
		volume_size = 11
	}
	ebs_block_device {
		device_name = "/dev/sdb"
		volume_size = 9
	}
	ebs_block_device {
		device_name = "/dev/sdc"
		volume_size = 10
		volume_type = "io1"
		iops = 100
	}
	ephemeral_block_device {
		device_name = "/dev/sde"
		virtual_name = "ephemeral0"
	}
}
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())

var testAccAWSLaunchConfigurationWithSpotPriceConfig = fmt.Sprintf(`
resource "aws_launch_configuration" "bar" {
  name = "terraform-test-%d"
  image_id = "ami-21f78e11"
  instance_type = "t1.micro"
  spot_price = "0.01"
}
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())

const testAccAWSLaunchConfigurationNoNameConfig = `
resource "aws_launch_configuration" "bar" {
   image_id = "ami-21f78e11"
   instance_type = "t1.micro"
   user_data = "foobar-user-data-change"
   associate_public_ip_address = false
}
`

const testAccAWSLaunchConfigurationPrefixNameConfig = `
resource "aws_launch_configuration" "baz" {
   name_prefix = "baz-"
   image_id = "ami-21f78e11"
   instance_type = "t1.micro"
   user_data = "foobar-user-data-change"
   associate_public_ip_address = false
}
`

const testAccAWSLaunchConfigurationWithEncryption = `
resource "aws_launch_configuration" "baz" {
   image_id = "ami-5189a661"
   instance_type = "t2.micro"
   associate_public_ip_address = false

   	root_block_device {
   		volume_type = "gp2"
		volume_size = 11
	}
	ebs_block_device {
		device_name = "/dev/sdb"
		volume_size = 9
		encrypted = true
	}
}
`
<|endoftext|>


<commit_before>package conf

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/otiai10/curr"
	"github.com/revel/revel"
)

const (
	configfile = "configs.json"
)

type configures struct {
	Whitelist    []string `json:"whitelist"`
	Blacklist    []string `json:"blacklist"`
	AllowDefault bool     `json:"allow_default"`
}

var configs = configures{
	Whitelist:    []string{},
	Blacklist:    []string{},
	AllowDefault: true,
}

func init() {
	if err := Load(); err != nil {
		revel.WARN.Println(err)
	}
}

// Load 設定ファイルを読み込んでメモリに載せる
func Load() error {
	f, err := os.Open(filepath.Join(curr.Dir(), configfile))
	if err != nil {
		return err
	}
	if err := json.NewDecoder(f).Decode(&configs); err != nil {
		return err
	}
	return nil
}

// Apply メモリに載ってる設定structをファイルに書き出す
func Apply() error {
	fname := filepath.Join(curr.Dir(), configfile)
	if _, err := os.Stat(fname); err != nil {
		os.Create(fname)
	}

	b, err := json.MarshalIndent(configs, "", "    ")
	if err != nil {
		return fmt.Errorf("marshal: %v", err)
	}
	if err := ioutil.WriteFile(fname, b, os.ModePerm); err != nil {
		return fmt.Errorf("write: %v", err)
	}
	return nil
}

// Kick ...
func Kick(name string) error {
	configs.Whitelist = removefromlist(configs.Whitelist, name)
	configs.Blacklist = removefromlist(configs.Blacklist, name)
	configs.Blacklist = append(configs.Blacklist, name)
	return Apply()
}

// Invite ...
func Invite(name string) error {
	configs.Whitelist = removefromlist(configs.Whitelist, name)
	configs.Blacklist = removefromlist(configs.Blacklist, name)
	configs.Whitelist = append(configs.Whitelist, name)
	return Apply()
}

// Reload ...
func Reload() error {
	return Load()
}

// Whitelist ...
func Whitelist() []string {
	return configs.Whitelist
}

// InWhitelist ...
func InWhitelist(name string) bool {
	return inlist(configs.Whitelist, name)
}

// Blacklist ...
func Blacklist() []string {
	return configs.Blacklist
}

// InBlacklist ...
func InBlacklist(name string) bool {
	return inlist(configs.Blacklist, name)
}

// AllowDefault ...
func AllowDefault() bool {
	return configs.AllowDefault
}

func inlist(list []string, name string) bool {
	for _, n := range list {
		if n == name {
			return true
		}
	}
	return false
}

func removefromlist(list []string, name string) []string {
	newlist := []string{}
	for _, v := range list {
		if v != name {
			newlist = append(newlist, v)
		}
	}
	return newlist
}
<commit_msg>Allow default control<commit_after>package conf

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/otiai10/curr"
	"github.com/revel/revel"
)

const (
	configfile = "configs.json"
)

type configures struct {
	Whitelist    []string `json:"whitelist"`
	Blacklist    []string `json:"blacklist"`
	AllowDefault bool     `json:"allow_default"`
}

var configs = configures{
	Whitelist:    []string{},
	Blacklist:    []string{},
	AllowDefault: true,
}

func init() {
	if err := Load(); err != nil {
		revel.WARN.Println(err)
	}
}

// Load 設定ファイルを読み込んでメモリに載せる
func Load() error {
	f, err := os.Open(filepath.Join(curr.Dir(), configfile))
	if err != nil {
		return err
	}
	if err := json.NewDecoder(f).Decode(&configs); err != nil {
		return err
	}
	return nil
}

// Apply メモリに載ってる設定structをファイルに書き出す
func Apply() error {
	fname := filepath.Join(curr.Dir(), configfile)
	if _, err := os.Stat(fname); err != nil {
		os.Create(fname)
	}

	b, err := json.MarshalIndent(configs, "", "    ")
	if err != nil {
		return fmt.Errorf("marshal: %v", err)
	}
	if err := ioutil.WriteFile(fname, b, os.ModePerm); err != nil {
		return fmt.Errorf("write: %v", err)
	}
	return nil
}

// Kick ...
func Kick(name string) error {
	if name == "default" {
		configs.AllowDefault = false
		return Apply()
	}
	configs.Whitelist = removefromlist(configs.Whitelist, name)
	configs.Blacklist = removefromlist(configs.Blacklist, name)
	configs.Blacklist = append(configs.Blacklist, name)
	return Apply()
}

// Invite ...
func Invite(name string) error {
	if name == "default" {
		configs.AllowDefault = true
		return Apply()
	}
	configs.Whitelist = removefromlist(configs.Whitelist, name)
	configs.Blacklist = removefromlist(configs.Blacklist, name)
	configs.Whitelist = append(configs.Whitelist, name)
	return Apply()
}

// Reload ...
func Reload() error {
	return Load()
}

// Whitelist ...
func Whitelist() []string {
	return configs.Whitelist
}

// InWhitelist ...
func InWhitelist(name string) bool {
	return inlist(configs.Whitelist, name)
}

// Blacklist ...
func Blacklist() []string {
	return configs.Blacklist
}

// InBlacklist ...
func InBlacklist(name string) bool {
	return inlist(configs.Blacklist, name)
}

// AllowDefault ...
func AllowDefault() bool {
	return configs.AllowDefault
}

func inlist(list []string, name string) bool {
	for _, n := range list {
		if n == name {
			return true
		}
	}
	return false
}

func removefromlist(list []string, name string) []string {
	newlist := []string{}
	for _, v := range list {
		if v != name {
			newlist = append(newlist, v)
		}
	}
	return newlist
}
<|endoftext|>


<commit_before>package configeur

import "fmt"

// Checker is the interface which external "checkers" must comply to. If a
// retrieval fails the next Checker in the Configeur.stack stack will be called. Checker's are added to the stack through the configeur.Use method.
type Checker interface {
	// Int finds and retrieves an integer by name. If it finds the value it will
	// return it, and if it doesn't an error will be returned and the next Checker
	// in the stack will be called.
	Int(name string) (int, error)

	// String finds and retrieves an string by name. If it finds the value it will
	// return it, and if it doesn't an error will be returned and the next Checker
	// in the stack will be called.
	String(name string) (string, error)

	// Bool finds and retrieves a boolean value by name.
	Bool(name string) (bool, error)
}

// Configeur is a stack of Checkers which are used to retrieve configuration values. It aims
// to have a similar API as the flag package in the standard library. Checker's are evaluated
// in the same order they are added through the initalization and Configeur.Use functions.
type Configeur struct {
	options map[string]*option // A map of all of the provided options
	stack   []Checker          // A list of all the "middlewear" which is used to find a value
}

// Int declares an int value. A pointer is returned that will
// point to the value after c.Parse() has been called.
func (c *Configeur) Int(name string, def int, description string) *int {
	v := c.option(name, def, description, intType)
	i, ok := v.(*int)

	if !ok {
		fmt.Printf("could not retrieve pointer to value for name %v\n", name)
		return nil
	}

	return i
}

// String declares a string value. A pointer is returned that will
// point to the value after c.Parse() has been called.
func (c *Configeur) String(name, def, description string) *string {
	v := c.option(name, def, description, stringType)
	s, ok := v.(*string)

	if !ok {
		fmt.Printf("could not retrieve pointer to value for name %v\n", name)
		return nil
	}

	return s
}

// Bool declares a new boolean option. A pointer is returned to this
// value that will be filled after Configeur.Parse() has been called.
func (c *Configeur) Bool(name string, def bool, description string) *bool {
	v := c.option(name, def, description, boolType)
	b, ok := v.(*bool)

	if !ok {
		fmt.Printf("could not retrieve pointer to that value\n")
		return nil
	}

	return b
}

// option returns a pointer of a type specified through the valueType parameter.
//
// note: You could potentially find the value to be pointed to through the def
// parameter, but this would pose an issue when one is not provided.
func (c *Configeur) option(name string, def interface{}, description string, typ valueType) interface{} {
	opt := &option{
		name:        name,
		def:         def,
		description: description,
		typ:         typ,
	}

	c.options[name] = opt

	switch opt.typ {
	case stringType:
		var s string
		opt.value = &s
	case intType:
		var i int
		opt.value = &i
	case boolType:
		var b bool
		opt.value = &b
	}

	return opt.value
}

// Use adds a variable amounts of new Checkers to the stack.
func (c *Configeur) Use(checkers ...Checker) {
	c.stack = append(c.stack, checkers...)
}

// Parse populates the pointers returned through the Configeur.Int and Configeur.String
// methods.
func (c *Configeur) Parse() {
	for _, opt := range c.options {
		changed := false
		for _, checker := range c.stack {
			// TODO undupe
			switch opt.typ {
			case stringType:
				s, err := checker.String(opt.name)
				if err != nil {
					fmt.Println(err)
					continue
				}

				z, ok := opt.value.(*string)
				if !ok {
					fmt.Println("that variable does not fit the value")
				}

				*z = s
			case intType:
				i, err := checker.Int(opt.name)
				if err != nil {
					fmt.Println(err)
					continue
				}

				z, ok := opt.value.(*int)
				if !ok {
					fmt.Println("that variable does not fit the value")
				}

				*z = i
			case boolType:
				b, err := checker.Bool(opt.name)
				if err != nil {
					fmt.Println(err)
					continue
				}

				z, ok := opt.value.(*bool)
				if !ok {
					fmt.Println("that var doesnt fit thy value")
				}

				*z = b
			}

			changed = true
			fmt.Println("changed", opt.value)
			break
		}

		if !changed {
			fmt.Printf("set %v to default[%v]\n", opt.name, opt.def)
			opt.value = opt.def
		}
	}
}

// New returns a pointer to a new Configeur instance with a stack
// provided through the variadic stack variable.
func New(stack ...Checker) *Configeur {
	c := &Configeur{
		options: make(map[string]*option),
		stack:   stack,
	}

	return c
}

type valueType int

func (vt valueType) String() string {
	name := ""
	switch vt {
	case intType:
		name = "Integer"
	case stringType:
		name = "String"
	case boolType:
		name = "Boolean"
	default:
		return "NOT A valueType"
	}

	return name
}

const (
	intType valueType = iota + 1
	stringType
	boolType
)

type option struct {
	name        string
	description string
	def         interface{}
	value       interface{}
	typ         valueType
}

func (o option) String() string {
	return fmt.Sprintf("%v(%v)[%v]", o.name, o.description, o.typ)
}
<commit_msg>Fix defaults system<commit_after>package configeur

import "fmt"

// Checker is the interface which external "checkers" must comply to. If a
// retrieval fails the next Checker in the Configeur.stack stack will be called. Checker's are added to the stack through the configeur.Use method.
type Checker interface {
	// Int finds and retrieves an integer by name. If it finds the value it will
	// return it, and if it doesn't an error will be returned and the next Checker
	// in the stack will be called.
	Int(name string) (int, error)

	// String finds and retrieves an string by name. If it finds the value it will
	// return it, and if it doesn't an error will be returned and the next Checker
	// in the stack will be called.
	String(name string) (string, error)

	// Bool finds and retrieves a boolean value by name.
	Bool(name string) (bool, error)
}

// Configeur is a stack of Checkers which are used to retrieve configuration values. It aims
// to have a similar API as the flag package in the standard library. Checker's are evaluated
// in the same order they are added through the initalization and Configeur.Use functions.
type Configeur struct {
	options map[string]*option // A map of all of the provided options
	stack   []Checker          // A list of all the "middlewear" which is used to find a value
}

// Int declares an int value. A pointer is returned that will
// point to the value after c.Parse() has been called.
func (c *Configeur) Int(name string, def int, description string) *int {
	v := c.option(name, def, description, intType)
	i, ok := v.(*int)

	if !ok {
		fmt.Printf("could not retrieve pointer to value for name %v\n", name)
		return nil
	}

	return i
}

// String declares a string value. A pointer is returned that will
// point to the value after c.Parse() has been called.
func (c *Configeur) String(name, def, description string) *string {
	v := c.option(name, def, description, stringType)
	s, ok := v.(*string)

	if !ok {
		fmt.Printf("could not retrieve pointer to value for name %v\n", name)
		return nil
	}

	return s
}

// Bool declares a new boolean option. A pointer is returned to this
// value that will be filled after Configeur.Parse() has been called.
func (c *Configeur) Bool(name string, def bool, description string) *bool {
	v := c.option(name, def, description, boolType)
	b, ok := v.(*bool)

	if !ok {
		fmt.Printf("could not retrieve pointer to that value\n")
		return nil
	}

	return b
}

// option returns a pointer of a type specified through the valueType parameter.
//
// note: You could potentially find the value to be pointed to through the def
// parameter, but this would pose an issue when one is not provided.
func (c *Configeur) option(name string, def interface{}, description string, typ valueType) interface{} {
	opt := &option{
		name:        name,
		def:         def,
		description: description,
		typ:         typ,
	}

	c.options[name] = opt

	switch opt.typ {
	case stringType:
		var s string
		opt.value = &s
	case intType:
		var i int
		opt.value = &i
	case boolType:
		var b bool
		opt.value = &b
	}

	return opt.value
}

// Use adds a variable amounts of new Checkers to the stack.
func (c *Configeur) Use(checkers ...Checker) {
	c.stack = append(c.stack, checkers...)
}

// Parse populates the pointers returned through the Configeur.Int and Configeur.String
// methods.
func (c *Configeur) Parse() {
	for _, opt := range c.options {
		changed := false
		for _, checker := range c.stack {
			// TODO undupe
			switch opt.typ {
			case stringType:
				s, err := checker.String(opt.name)
				if err != nil {
					fmt.Println(err)
					continue
				}

				opt.set(s)
			case intType:
				i, err := checker.Int(opt.name)
				if err != nil {
					fmt.Println(err)
					continue
				}

				opt.set(i)
			case boolType:
				b, err := checker.Bool(opt.name)
				if err != nil {
					fmt.Println(err)
					continue
				}

				opt.set(b)
			}

			changed = true
			break
		}

		if !changed {
			opt.set(opt.def)

			opt.value = opt.def
		}
	}
}

// New returns a pointer to a new Configeur instance with a stack
// provided through the variadic stack variable.
func New(stack ...Checker) *Configeur {
	c := &Configeur{
		options: make(map[string]*option),
		stack:   stack,
	}

	return c
}

type valueType int

func (vt valueType) String() string {
	name := ""
	switch vt {
	case intType:
		name = "Integer"
	case stringType:
		name = "String"
	case boolType:
		name = "Boolean"
	default:
		return "NOT A valueType"
	}

	return name
}

const (
	intType valueType = iota + 1
	stringType
	boolType
)

type option struct {
	name        string
	description string
	def         interface{}
	value       interface{}
	typ         valueType
}

func (o option) String() string {
	return fmt.Sprintf("%v(%v)[%v]", o.name, o.description, o.typ)
}

func (o *option) set(value interface{}) {
	switch value.(type) {
	case bool:
		z, ok := o.value.(*bool)
		if !ok {
			fmt.Println("that var doesnt fit thy value")
		}

		*z = value.(bool)
	case int:
		z, ok := o.value.(*int)
		if !ok {
			fmt.Println("that var doesnt fit thy value")
		}

		*z = value.(int)

	case string:
		z, ok := o.value.(*string)
		if !ok {
			fmt.Println("that var doesnt fit thy value")
		}

		*z = value.(string)
	}
}
<|endoftext|>


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

package resource

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/pkg/errors"
	"github.com/satori/go.uuid"

	"github.com/diegobernardes/flare"
)

type pagination flare.Pagination

func (p *pagination) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Limit  int `json:"limit"`
		Offset int `json:"offset"`
		Total  int `json:"total"`
	}{
		Limit:  p.Limit,
		Total:  p.Total,
		Offset: p.Offset,
	})
}

type resource flare.Resource

func (r *resource) MarshalJSON() ([]byte, error) {
	change := map[string]string{
		"kind":  r.Change.Kind,
		"field": r.Change.Field,
	}

	if r.Change.DateFormat != "" {
		change["dateFormat"] = r.Change.DateFormat
	}

	return json.Marshal(&struct {
		Id        string            `json:"id"`
		Addresses []string          `json:"addresses"`
		Path      string            `json:"path"`
		Change    map[string]string `json:"change"`
		CreatedAt string            `json:"createdAt"`
	}{
		Id:        r.Id,
		Addresses: r.Addresses,
		Path:      r.Path,
		Change:    change,
		CreatedAt: r.CreatedAt.Format(time.RFC3339),
	})
}

type resourceCreateChange struct {
	Kind       string `json:"kind"`
	Field      string `json:"field"`
	DateFormat string `json:"dateFormat"`
}

type resourceCreate struct {
	Path      string               `json:"path"`
	Addresses []string             `json:"addresses"`
	Change    resourceCreateChange `json:"change"`
}

func (r *resourceCreate) valid() error {
	if err := r.validAddresses(); err != nil {
		return err
	}

	if r.Path == "" {
		return errors.New("missing path")
	}

	if r.Path[0] != '/' {
		return errors.New("path should start with a slash")
	}

	if r.Path[len(r.Path)-1] == '/' {
		return errors.New("path should not end with a slash")
	}

	if err := r.validWildcard(); err != nil {
		return err
	}

	if r.Change.Field == "" {
		return errors.New("missing change")
	}

	switch r.Change.Kind {
	case flare.ResourceChangeInteger, flare.ResourceChangeString:
	case flare.ResourceChangeDate:
		if r.Change.DateFormat == "" {
			return errors.New("missing change.dateFormat")
		}
	default:
		return errors.New("invalid change.kind")
	}

	return nil
}

func (r *resourceCreate) validWildcard() error {
	var hasWildcard bool
	for _, value := range strings.Split(r.Path, "/") {
		if value == "" {
			continue
		}

		if value[0] == '{' && value[len(value)-1] == '}' {
			hasWildcard = true
		}

		if strings.Count(value, "{") > 1 || strings.Count(value, "}") > 1 {
			return errors.New("could not use brackets inside a wildcard or next to another wildcard")
		}
	}

	if !hasWildcard {
		return errors.New("missing wildcard")
	}
	return nil
}

func (r *resourceCreate) validAddresses() error {
	if len(r.Addresses) == 0 {
		return errors.New("missing addresses")
	}

	for _, address := range r.Addresses {
		d, err := url.Parse(address)
		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("error during address parse '%s'", address))
		}

		if d.Path != "" {
			return fmt.Errorf("address is invalid because it has a path '%s'", d.Path)
		}

		if d.RawQuery != "" {
			return fmt.Errorf("address is invalid because it has query string '%s'", d.RawQuery)
		}

		if d.Fragment != "" {
			return fmt.Errorf("address is invalid because it has fragment '%s'", d.Fragment)
		}

		switch d.Scheme {
		case "http", "https":
			continue
		case "":
			return errors.Errorf("missing scheme on address '%s'", address)
		default:
			return errors.Errorf("invalid scheme on address '%s'", address)
		}
	}

	return nil
}

func (r *resourceCreate) toFlareResource() *flare.Resource {
	return &flare.Resource{
		Id:        uuid.NewV4().String(),
		Addresses: r.Addresses,
		Path:      r.Path,
		Change: flare.ResourceChange{
			Kind:       r.Change.Kind,
			Field:      r.Change.Field,
			DateFormat: r.Change.DateFormat,
		},
	}
}

func transformResources(r []flare.Resource) []resource {
	result := make([]resource, len(r))
	for i := 0; i < len(r); i++ {
		result[i] = (resource)(r[i])
	}
	return result
}

func transformResource(r *flare.Resource) *resource { return (*resource)(r) }

func transformPagination(p *flare.Pagination) *pagination { return (*pagination)(p) }

type response struct {
	Pagination *pagination
	Error      *responseError
	Resources  []resource
	Resource   *resource
}

func (r *response) MarshalJSON() ([]byte, error) {
	var result interface{}

	if r.Error != nil {
		result = map[string]*responseError{"error": r.Error}
	} else if r.Resource != nil {
		result = r.Resource
	} else {
		result = map[string]interface{}{
			"pagination": r.Pagination,
			"resources":  r.Resources,
		}
	}

	return json.Marshal(result)
}

type responseError struct {
	Status int    `json:"status"`
	Title  string `json:"title"`
	Detail string `json:"detail,omitempty"`
}

func (s *Service) writeError(w http.ResponseWriter, err error, title string, status int) {
	resp := &response{Error: &responseError{Status: status}}

	if err != nil {
		resp.Error.Detail = err.Error()
	}

	if title != "" {
		resp.Error.Title = title
	}

	s.writeResponse(w, resp, status, nil)
}
<commit_msg>resource: fix cyclomatic complexity function<commit_after>// Copyright 2017 Diego Bernardes. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package resource

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/pkg/errors"
	"github.com/satori/go.uuid"

	"github.com/diegobernardes/flare"
)

type pagination flare.Pagination

func (p *pagination) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Limit  int `json:"limit"`
		Offset int `json:"offset"`
		Total  int `json:"total"`
	}{
		Limit:  p.Limit,
		Total:  p.Total,
		Offset: p.Offset,
	})
}

type resource flare.Resource

func (r *resource) MarshalJSON() ([]byte, error) {
	change := map[string]string{
		"kind":  r.Change.Kind,
		"field": r.Change.Field,
	}

	if r.Change.DateFormat != "" {
		change["dateFormat"] = r.Change.DateFormat
	}

	return json.Marshal(&struct {
		Id        string            `json:"id"`
		Addresses []string          `json:"addresses"`
		Path      string            `json:"path"`
		Change    map[string]string `json:"change"`
		CreatedAt string            `json:"createdAt"`
	}{
		Id:        r.Id,
		Addresses: r.Addresses,
		Path:      r.Path,
		Change:    change,
		CreatedAt: r.CreatedAt.Format(time.RFC3339),
	})
}

type resourceCreateChange struct {
	Kind       string `json:"kind"`
	Field      string `json:"field"`
	DateFormat string `json:"dateFormat"`
}

type resourceCreate struct {
	Path      string               `json:"path"`
	Addresses []string             `json:"addresses"`
	Change    resourceCreateChange `json:"change"`
}

func (r *resourceCreate) valid() error {
	if err := r.validAddresses(); err != nil {
		return err
	}

	if err := r.validPath(); err != nil {
		return err
	}

	if r.Change.Field == "" {
		return errors.New("missing change")
	}

	switch r.Change.Kind {
	case flare.ResourceChangeInteger, flare.ResourceChangeString:
	case flare.ResourceChangeDate:
		if r.Change.DateFormat == "" {
			return errors.New("missing change.dateFormat")
		}
	default:
		return errors.New("invalid change.kind")
	}

	return nil
}

func (r *resourceCreate) validPath() error {
	if r.Path == "" {
		return errors.New("missing path")
	}

	if r.Path[0] != '/' {
		return errors.New("path should start with a slash")
	}

	if r.Path[len(r.Path)-1] == '/' {
		return errors.New("path should not end with a slash")
	}

	if err := r.validWildcard(); err != nil {
		return err
	}

	return nil
}

func (r *resourceCreate) validWildcard() error {
	var hasWildcard bool
	for _, value := range strings.Split(r.Path, "/") {
		if value == "" {
			continue
		}

		if value[0] == '{' && value[len(value)-1] == '}' {
			hasWildcard = true
		}

		if strings.Count(value, "{") > 1 || strings.Count(value, "}") > 1 {
			return errors.New("could not use brackets inside a wildcard or next to another wildcard")
		}
	}

	if !hasWildcard {
		return errors.New("missing wildcard")
	}
	return nil
}

func (r *resourceCreate) validAddresses() error {
	if len(r.Addresses) == 0 {
		return errors.New("missing addresses")
	}

	for _, address := range r.Addresses {
		d, err := url.Parse(address)
		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("error during address parse '%s'", address))
		}

		if d.Path != "" {
			return fmt.Errorf("address is invalid because it has a path '%s'", d.Path)
		}

		if d.RawQuery != "" {
			return fmt.Errorf("address is invalid because it has query string '%s'", d.RawQuery)
		}

		if d.Fragment != "" {
			return fmt.Errorf("address is invalid because it has fragment '%s'", d.Fragment)
		}

		switch d.Scheme {
		case "http", "https":
			continue
		case "":
			return errors.Errorf("missing scheme on address '%s'", address)
		default:
			return errors.Errorf("invalid scheme on address '%s'", address)
		}
	}

	return nil
}

func (r *resourceCreate) toFlareResource() *flare.Resource {
	return &flare.Resource{
		Id:        uuid.NewV4().String(),
		Addresses: r.Addresses,
		Path:      r.Path,
		Change: flare.ResourceChange{
			Kind:       r.Change.Kind,
			Field:      r.Change.Field,
			DateFormat: r.Change.DateFormat,
		},
	}
}

func transformResources(r []flare.Resource) []resource {
	result := make([]resource, len(r))
	for i := 0; i < len(r); i++ {
		result[i] = (resource)(r[i])
	}
	return result
}

func transformResource(r *flare.Resource) *resource { return (*resource)(r) }

func transformPagination(p *flare.Pagination) *pagination { return (*pagination)(p) }

type response struct {
	Pagination *pagination
	Error      *responseError
	Resources  []resource
	Resource   *resource
}

func (r *response) MarshalJSON() ([]byte, error) {
	var result interface{}

	if r.Error != nil {
		result = map[string]*responseError{"error": r.Error}
	} else if r.Resource != nil {
		result = r.Resource
	} else {
		result = map[string]interface{}{
			"pagination": r.Pagination,
			"resources":  r.Resources,
		}
	}

	return json.Marshal(result)
}

type responseError struct {
	Status int    `json:"status"`
	Title  string `json:"title"`
	Detail string `json:"detail,omitempty"`
}

func (s *Service) writeError(w http.ResponseWriter, err error, title string, status int) {
	resp := &response{Error: &responseError{Status: status}}

	if err != nil {
		resp.Error.Detail = err.Error()
	}

	if title != "" {
		resp.Error.Title = title
	}

	s.writeResponse(w, resp, status, nil)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceDataflow() *schema.Resource {
	return &schema.Resource{
		Create: resourceDataflowCreate,
		Read:   resourceDataflowRead,
		Delete: resourceDataflowDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"classpath": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"class": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"optional_args": &schema.Schema{
				Type:     schema.TypeMap,
				Optional: true,
				ForceNew: true,
				Elem:	  schema.TypeString,
			},

			"jobids": &schema.Schema{
				Type:     schema.TypeList,
				Computed: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},

			"job_states": &schema.Schema{
				Type:     schema.TypeList,
				Computed: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},
		},
	}
}

func resourceDataflowCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	optional_args := cleanAdditionalArgs(d.Get("optional_args").(map[string]interface{}))

	jobids, err := CreateDataflow(d.Get("name").(string), d.Get("classpath").(string), d.Get("class").(string), config.Project, optional_args)
	if err != nil && len(jobids) == 0 {
		// call failed, abort
		return err
	} else if err != nil {
		// we're updating, check and make sure all jobs found have been cancelled, if not, quit
		for _, jobid := range jobids {
			jobdesc, err := ReadDataflow(jobid, config.Project)
			if err != nil {
				return err
			}
			if jobdesc.RequestedState == "JOB_STATE_RUNNING" || jobdesc.RequestedState == "JOB_STATE_UPDATED" {
				return fmt.Errorf("Attempting to create existing job name %s but prior job of same name with id %s still exists and is in state %s which we won't blindly overwrite.", d.Get("name").(string),  jobid, jobdesc.CurrentState)
			}
		}

		// wait for 10 minutes or all jobs cancelled/dead/unknown
		not_all_toast := true
		for i := 0; i < (10 * 6) && not_all_toast; i++ {
			time.Sleep(10 * time.Second)
			not_all_toast = false
			//  check all jobs, if not in a cancelled state, set state flag
			for _, jobid := range jobids {
				jobdesc, err := ReadDataflow(jobid, config.Project)
				if err != nil {
					return err
				}
				if jobdesc.RequestedState == "JOB_STATE_RUNNING" || jobdesc.RequestedState == "JOB_STATE_UPDATED" {
					not_all_toast = true
				}
			}
		}

		if not_all_toast {
			return fmt.Errorf("Not all jobs entered into a cancelled/dead/unknown state but all jobs have been requested to be cancelled.  Please wait a few minutes and try again.")
		}

		//  retry the job creation, any errors here and abort
		//  dataflow won't let us reuse job names so at this point gen a timestamp as a string and append
		//    to the supplied name and go with god.  we use jobids for all the work anyway.
		nameTimestamp := time.Now().Format("2006-01-02T15-04-05Z07-00")
		jobids, err = CreateDataflow(d.Get("name").(string) + "." + nameTimestamp, d.Get("classpath").(string), d.Get("class").(string), config.Project, optional_args)
		if err != nil {
			return fmt.Errorf("Failed to createa job named %q with error: %q", nameTimestamp,err)
		}
	}

	d.Set("jobids", jobids)
	d.SetId(d.Get("name").(string))

	err = resourceDataflowRead(d, meta)
	if err != nil {
		return err
	}

	return nil
}

func resourceDataflowRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	job_states := make([]string, 0)
	job_cnt := d.Get("jobids.#")
	if job_cnt != nil {
		for i := 0; i < job_cnt.(int); i++ {
			jobidkey:= fmt.Sprintf("jobids.%d", i)
			job_desc, err := ReadDataflow(d.Get(jobidkey).(string), config.Project)
			if err != nil {
				return err
			}
			job_states = append(job_states, job_desc.CurrentState)
		}
	}

	d.Set("job_states", job_states)

	return nil
}

func resourceDataflowDelete(d *schema.ResourceData, meta interface{}) error {

	config := meta.(*Config)
	err := resourceDataflowRead(d, meta)
	if err != nil {
		return err
	}

	failedCancel := make([]string, 0)
	job_cnt := d.Get("jobids.#")
	if job_cnt != nil {
		for i := 0; i < job_cnt.(int); i++ {
			jobidkey:= fmt.Sprintf("jobids.%d", i)
			jobstatekey := fmt.Sprintf("job_states.%d", i)
			failedjob, err := CancelDataflow(d.Get(jobidkey).(string), d.Get(jobstatekey).(string), config.Project)
			if err != nil {
				return err
			}
			if failedjob {
				failedCancel = append(failedCancel, d.Get(jobidkey).(string))
			}
		}
	}

	if len(failedCancel) > 0 {
		return fmt.Errorf("Failed to cancel the following jobs: %v", failedCancel)
	}

	d.SetId("")
	return nil
}
<commit_msg>add 'resource-hash' config item<commit_after>package main

import (
	"fmt"
	"time"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceDataflow() *schema.Resource {
	return &schema.Resource{
		Create: resourceDataflowCreate,
		Read:   resourceDataflowRead,
		Delete: resourceDataflowDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"classpath": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"class": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"optional_args": &schema.Schema{
				Type:     schema.TypeMap,
				Optional: true,
				ForceNew: true,
				Elem:	  schema.TypeString,
			},

			"resource-hash": &schema.Schema{
				Type:     schema.TypeList,
				ForceNew: true,
				Optional: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},

			"jobids": &schema.Schema{
				Type:     schema.TypeList,
				Computed: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},

			"job_states": &schema.Schema{
				Type:     schema.TypeList,
				Computed: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},
		},
	}
}

func resourceDataflowCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	optional_args := cleanAdditionalArgs(d.Get("optional_args").(map[string]interface{}))

	jobids, err := CreateDataflow(d.Get("name").(string), d.Get("classpath").(string), d.Get("class").(string), config.Project, optional_args)
	if err != nil && len(jobids) == 0 {
		// call failed, abort
		return err
	} else if err != nil {
		// we're updating, check and make sure all jobs found have been cancelled, if not, quit
		for _, jobid := range jobids {
			jobdesc, err := ReadDataflow(jobid, config.Project)
			if err != nil {
				return err
			}
			if jobdesc.RequestedState == "JOB_STATE_RUNNING" || jobdesc.RequestedState == "JOB_STATE_UPDATED" {
				return fmt.Errorf("Attempting to create existing job name %s but prior job of same name with id %s still exists and is in state %s which we won't blindly overwrite.", d.Get("name").(string),  jobid, jobdesc.CurrentState)
			}
		}

		// wait for 10 minutes or all jobs cancelled/dead/unknown
		not_all_toast := true
		for i := 0; i < (10 * 6) && not_all_toast; i++ {
			time.Sleep(10 * time.Second)
			not_all_toast = false
			//  check all jobs, if not in a cancelled state, set state flag
			for _, jobid := range jobids {
				jobdesc, err := ReadDataflow(jobid, config.Project)
				if err != nil {
					return err
				}
				if jobdesc.RequestedState == "JOB_STATE_RUNNING" || jobdesc.RequestedState == "JOB_STATE_UPDATED" {
					not_all_toast = true
				}
			}
		}

		if not_all_toast {
			return fmt.Errorf("Not all jobs entered into a cancelled/dead/unknown state but all jobs have been requested to be cancelled.  Please wait a few minutes and try again.")
		}

		//  retry the job creation, any errors here and abort
		//  dataflow won't let us reuse job names so at this point gen a timestamp as a string and append
		//    to the supplied name and go with god.  we use jobids for all the work anyway.
		nameTimestamp := time.Now().Format("2006-01-02T15-04-05Z07-00")
		jobids, err = CreateDataflow(d.Get("name").(string) + "." + nameTimestamp, d.Get("classpath").(string), d.Get("class").(string), config.Project, optional_args)
		if err != nil {
			return fmt.Errorf("Failed to createa job named %q with error: %q", nameTimestamp,err)
		}
	}

	d.Set("jobids", jobids)
	d.SetId(d.Get("name").(string))

	err = resourceDataflowRead(d, meta)
	if err != nil {
		return err
	}

	return nil
}

func resourceDataflowRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	job_states := make([]string, 0)
	job_cnt := d.Get("jobids.#")
	if job_cnt != nil {
		for i := 0; i < job_cnt.(int); i++ {
			jobidkey:= fmt.Sprintf("jobids.%d", i)
			job_desc, err := ReadDataflow(d.Get(jobidkey).(string), config.Project)
			if err != nil {
				return err
			}
			job_states = append(job_states, job_desc.CurrentState)
		}
	}

	d.Set("job_states", job_states)

	return nil
}

func resourceDataflowDelete(d *schema.ResourceData, meta interface{}) error {

	config := meta.(*Config)
	err := resourceDataflowRead(d, meta)
	if err != nil {
		return err
	}

	failedCancel := make([]string, 0)
	job_cnt := d.Get("jobids.#")
	if job_cnt != nil {
		for i := 0; i < job_cnt.(int); i++ {
			jobidkey:= fmt.Sprintf("jobids.%d", i)
			jobstatekey := fmt.Sprintf("job_states.%d", i)
			failedjob, err := CancelDataflow(d.Get(jobidkey).(string), d.Get(jobstatekey).(string), config.Project)
			if err != nil {
				return err
			}
			if failedjob {
				failedCancel = append(failedCancel, d.Get(jobidkey).(string))
			}
		}
	}

	if len(failedCancel) > 0 {
		return fmt.Errorf("Failed to cancel the following jobs: %v", failedCancel)
	}

	d.SetId("")
	return nil
}
<|endoftext|>


<commit_before><commit_msg>Add RTUUint64ToFloat64 (#123)<commit_after><|endoftext|>


<commit_before>package main

import (
	"bytes"
	"context"
	"encoding/hex"
	"fmt"
	"io"
	"os"
	"strconv"

	"chain/core"
	"chain/core/accesstoken"
	"chain/core/mockhsm"
	"chain/crypto/ed25519"
	"chain/database/pg"
	"chain/database/sql"
	"chain/env"
	"chain/log"
)

// config vars
var (
	dbURL = env.String("DATABASE_URL", "postgres:///core?sslmode=disable")
)

// We collect log output in this buffer,
// and display it only when there's an error.
var logbuf bytes.Buffer

type command struct {
	f func(*sql.DB, []string)
}

var commands = map[string]*command{
	"config-generator":     {configGenerator},
	"create-block-keypair": {createBlockKeyPair},
	"create-token":         {createToken},
	"config":               {configNongenerator},
	"reset":                {reset},
}

func main() {
	log.SetOutput(&logbuf)
	env.Parse()
	db, err := sql.Open("hapg", *dbURL)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(2)
	}

	if len(os.Args) < 2 {
		help(os.Stdout)
		os.Exit(0)
	}
	cmd := commands[os.Args[1]]
	if cmd == nil {
		fmt.Fprintln(os.Stderr, "unknown command:", os.Args[1])
		help(os.Stderr)
		os.Exit(1)
	}
	cmd.f(db, os.Args[2:])
}

func configGenerator(db *sql.DB, args []string) {
	const usage = "error: corectl config-generator [-s] [<quorum> <<pubkey> <url>...>]"
	var (
		isSigner bool
		quorum   int
		signers  []core.ConfigSigner
		err      error
	)

	if len(args) > 0 && args[0] == "-s" {
		isSigner = true
		args = args[1:]
	}

	if len(args) == 0 {
		if isSigner {
			quorum = 1
		}
	} else if len(args)%2 != 1 {
		fatalln(usage)
	} else {
		quorum, err = strconv.Atoi(args[0])
		if err != nil {
			fatalln(usage)
		}

		for i := 1; i < len(args); i += 2 {
			pubkey, err := hex.DecodeString(args[i])
			if err != nil {
				fatalln(usage)
			}
			url := args[i+1]
			signers = append(signers, core.ConfigSigner{
				// Silently truncate the input (which is likely to be an xpub
				// produced by the create-block-keypair subcommand) to
				// bare-pubkey size.
				// TODO(bobg): When the mockhsm can produce bare pubkeys,
				// treat xpubs on input as an error instead.
				Pubkey: pubkey[:ed25519.PublicKeySize],
				URL:    url,
			})
		}
	}

	config := &core.Config{
		IsGenerator: true,
		IsSigner:    isSigner,
		Quorum:      quorum,
		Signers:     signers,
	}

	err = initSchema(db)
	if err != nil {
		fatalln("error: init schema", err)
	}
	ctx := context.Background()
	err = core.Configure(ctx, db, config)
	if err != nil {
		fatalln("error:", err)
	}

	fmt.Println("blockchain id", config.BlockchainID)
}

func createBlockKeyPair(db *sql.DB, args []string) {
	if len(args) != 0 {
		fatalln("error: create-block-keypair takes no args")
	}

	hsm := mockhsm.New(db)
	ctx := context.Background()
	xpub, err := hsm.CreateKey(ctx, "block_key")
	if err != nil {
		fatalln("error:", err)
	}

	fmt.Println("block xpub:", xpub.XPub.String())
}

func createToken(db *sql.DB, args []string) {
	var id, typ string
	if len(args) == 1 {
		id, typ = args[0], "client"
	} else if len(args) == 2 && args[0] == "-net" {
		id, typ = args[1], "network"
	} else {
		fatalln("usage: corectl create-token [-net] [id]")
	}

	tok, err := accesstoken.Create(pg.NewContext(context.Background(), db), id, typ)
	if err != nil {
		fatalln("error:", err)
	}
	fmt.Print(tok.Token)
}

func configNongenerator(db *sql.DB, args []string) {
	errUsage := "error: corectl config <blockchain-id> <generator-url> [-t <generator-access-token>] [-k <block-pubkey>]"
	if len(args) < 2 {
		fatalln(errUsage)
	}

	var config core.Config
	err := config.BlockchainID.UnmarshalText([]byte(args[0]))
	if err != nil {
		fatalln("error: invalid blockchain ID:", err)
	}
	config.GeneratorURL = args[1]

	for args = args[2:]; len(args) > 0; args = args[2:] {
		if len(args) < 2 {
			fatalln(errUsage)
		}

		switch args[0] {
		case "-t":
			config.GeneratorAccessToken = args[1]
		case "-k":
			config.IsSigner = true
			config.BlockXPub = args[1]
		default:
			fatalln(errUsage)
		}
	}

	err = initSchema(db)
	if err != nil {
		fatalln("error: init schema", err)
	}
	ctx := context.Background()
	err = core.Configure(ctx, db, &config)
	if err != nil {
		fatalln("error:", err)
	}
}

func reset(db *sql.DB, args []string) {
	if len(args) != 0 {
		fatalln("error: reset takes no args")
	}

	ctx := context.Background()
	err := core.Reset(ctx, db)
	if err != nil {
		fatalln("error:", err)
	}
}

func initSchema(db *sql.DB) error {
	ctx := context.Background()
	const q = `
		SELECT count(*) FROM pg_tables
		WHERE schemaname='public' AND tablename='migrations'
	`
	var n int
	err := db.QueryRow(ctx, q).Scan(&n)
	if err != nil {
		return err
	} else if n > 0 {
		return nil // already initialized
	}
	_, err = db.Exec(ctx, core.Schema())
	return err
}

func fatalln(v ...interface{}) {
	io.Copy(os.Stderr, &logbuf)
	fmt.Fprintln(os.Stderr, v...)
	os.Exit(2)
}

func help(w io.Writer) {
	fmt.Fprintln(w, "usage: corectl [command] [arguments]")
	fmt.Fprint(w, "\nThe commands are:\n\n")
	for name := range commands {
		fmt.Fprintln(w, "\t", name)
	}
	fmt.Fprintln(w)
}
<commit_msg>cmd/corectl: init schema always<commit_after>package main

import (
	"bytes"
	"context"
	"encoding/hex"
	"fmt"
	"io"
	"os"
	"strconv"

	"chain/core"
	"chain/core/accesstoken"
	"chain/core/mockhsm"
	"chain/crypto/ed25519"
	"chain/database/pg"
	"chain/database/sql"
	"chain/env"
	"chain/log"
)

// config vars
var (
	dbURL = env.String("DATABASE_URL", "postgres:///core?sslmode=disable")
)

// We collect log output in this buffer,
// and display it only when there's an error.
var logbuf bytes.Buffer

type command struct {
	f func(*sql.DB, []string)
}

var commands = map[string]*command{
	"config-generator":     {configGenerator},
	"create-block-keypair": {createBlockKeyPair},
	"create-token":         {createToken},
	"config":               {configNongenerator},
	"reset":                {reset},
}

func main() {
	log.SetOutput(&logbuf)
	env.Parse()
	db, err := sql.Open("hapg", *dbURL)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(2)
	}

	if len(os.Args) < 2 {
		help(os.Stdout)
		os.Exit(0)
	}
	cmd := commands[os.Args[1]]
	if cmd == nil {
		fmt.Fprintln(os.Stderr, "unknown command:", os.Args[1])
		help(os.Stderr)
		os.Exit(1)
	}
	err = initSchema(db)
	if err != nil {
		fatalln("error: init schema", err)
	}
	cmd.f(db, os.Args[2:])
}

func configGenerator(db *sql.DB, args []string) {
	const usage = "error: corectl config-generator [-s] [<quorum> <<pubkey> <url>...>]"
	var (
		isSigner bool
		quorum   int
		signers  []core.ConfigSigner
		err      error
	)

	if len(args) > 0 && args[0] == "-s" {
		isSigner = true
		args = args[1:]
	}

	if len(args) == 0 {
		if isSigner {
			quorum = 1
		}
	} else if len(args)%2 != 1 {
		fatalln(usage)
	} else {
		quorum, err = strconv.Atoi(args[0])
		if err != nil {
			fatalln(usage)
		}

		for i := 1; i < len(args); i += 2 {
			pubkey, err := hex.DecodeString(args[i])
			if err != nil {
				fatalln(usage)
			}
			url := args[i+1]
			signers = append(signers, core.ConfigSigner{
				// Silently truncate the input (which is likely to be an xpub
				// produced by the create-block-keypair subcommand) to
				// bare-pubkey size.
				// TODO(bobg): When the mockhsm can produce bare pubkeys,
				// treat xpubs on input as an error instead.
				Pubkey: pubkey[:ed25519.PublicKeySize],
				URL:    url,
			})
		}
	}

	config := &core.Config{
		IsGenerator: true,
		IsSigner:    isSigner,
		Quorum:      quorum,
		Signers:     signers,
	}

	ctx := context.Background()
	err = core.Configure(ctx, db, config)
	if err != nil {
		fatalln("error:", err)
	}

	fmt.Println("blockchain id", config.BlockchainID)
}

func createBlockKeyPair(db *sql.DB, args []string) {
	if len(args) != 0 {
		fatalln("error: create-block-keypair takes no args")
	}

	hsm := mockhsm.New(db)
	ctx := context.Background()
	xpub, err := hsm.CreateKey(ctx, "block_key")
	if err != nil {
		fatalln("error:", err)
	}

	fmt.Println("block xpub:", xpub.XPub.String())
}

func createToken(db *sql.DB, args []string) {
	var id, typ string
	if len(args) == 1 {
		id, typ = args[0], "client"
	} else if len(args) == 2 && args[0] == "-net" {
		id, typ = args[1], "network"
	} else {
		fatalln("usage: corectl create-token [-net] [id]")
	}

	tok, err := accesstoken.Create(pg.NewContext(context.Background(), db), id, typ)
	if err != nil {
		fatalln("error:", err)
	}
	fmt.Print(tok.Token)
}

func configNongenerator(db *sql.DB, args []string) {
	errUsage := "error: corectl config <blockchain-id> <generator-url> [-t <generator-access-token>] [-k <block-pubkey>]"
	if len(args) < 2 {
		fatalln(errUsage)
	}

	var config core.Config
	err := config.BlockchainID.UnmarshalText([]byte(args[0]))
	if err != nil {
		fatalln("error: invalid blockchain ID:", err)
	}
	config.GeneratorURL = args[1]

	for args = args[2:]; len(args) > 0; args = args[2:] {
		if len(args) < 2 {
			fatalln(errUsage)
		}

		switch args[0] {
		case "-t":
			config.GeneratorAccessToken = args[1]
		case "-k":
			config.IsSigner = true
			config.BlockXPub = args[1]
		default:
			fatalln(errUsage)
		}
	}

	ctx := context.Background()
	err = core.Configure(ctx, db, &config)
	if err != nil {
		fatalln("error:", err)
	}
}

func reset(db *sql.DB, args []string) {
	if len(args) != 0 {
		fatalln("error: reset takes no args")
	}

	ctx := context.Background()
	err := core.Reset(ctx, db)
	if err != nil {
		fatalln("error:", err)
	}
}

func initSchema(db *sql.DB) error {
	ctx := context.Background()
	const q = `
		SELECT count(*) FROM pg_tables
		WHERE schemaname='public' AND tablename='migrations'
	`
	var n int
	err := db.QueryRow(ctx, q).Scan(&n)
	if err != nil {
		return err
	} else if n > 0 {
		return nil // already initialized
	}
	_, err = db.Exec(ctx, core.Schema())
	return err
}

func fatalln(v ...interface{}) {
	io.Copy(os.Stderr, &logbuf)
	fmt.Fprintln(os.Stderr, v...)
	os.Exit(2)
}

func help(w io.Writer) {
	fmt.Fprintln(w, "usage: corectl [command] [arguments]")
	fmt.Fprint(w, "\nThe commands are:\n\n")
	for name := range commands {
		fmt.Fprintln(w, "\t", name)
	}
	fmt.Fprintln(w)
}
<|endoftext|>


<commit_before>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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 pzse

import (
	"bytes"
	"errors"
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"time"

	"github.com/venicegeo/pzsvc-lib"
)

type inpStruct struct {
	Command    string   `json:"cmd"`
	InPzFiles  []string `json:"inPzFiles"`    // slice: Pz dataIds
	InExtFiles []string `json:"inExtFiles"`   // slice: external URL
	InPzNames  []string `json:"inPzNames"`    // slice: name for the InPzFile of the same index
	InExtNames []string `json:"inExtNames"`   // slice: name for the InExtFile of the same index
	OutTiffs   []string `json:"outTiffs"`     // slice: filenames of GeoTIFFs to be ingested
	OutTxts    []string `json:"outTxts"`      // slice: filenames of text files to be ingested
	OutGeoJs   []string `json:"outGeoJson"`   // slice: filenames of GeoJSON files to be ingested
	ExtAuth    string   `json:"inExtAuthKey"` // string: auth key for accessing external files
	PzAuth     string   `json:"pzAuthKey"`    // string: suth key for accessing Piazza
}

// ParseConfig parses the config file on starting up
func ParseConfig(configObj *ConfigType) ConfigParseOut {

	canReg, canFile, hasAuth := CheckConfig(configObj)

	var authKey string
	if hasAuth {
		authKey = os.Getenv(configObj.AuthEnVar)
		if authKey == "" {
			fmt.Println("Error: no auth key at AuthEnVar.  Registration disabled, and client will have to provide authKey.")
			hasAuth = false
			canReg = false
		}
	}

	if configObj.Port <= 0 {
		configObj.Port = 8080
	}
	portStr := ":" + strconv.Itoa(configObj.Port)

	version := GetVersion(configObj)

	if canReg {
		fmt.Println("About to manage registration.")
		err := pzsvc.ManageRegistration(configObj.SvcName,
			configObj.Description,
			configObj.URL+"/execute",
			configObj.PzAddr,
			version,
			authKey,
			configObj.Attributes)
		if err != nil {
			fmt.Println("pzsvc-exec error in managing registration: ", err.Error())
		}
		fmt.Println("Registration managed.")
	}

	var procPool = pzsvc.Semaphore(nil)
	if configObj.NumProcs > 0 {
		procPool = make(pzsvc.Semaphore, configObj.NumProcs)
	}

	return ConfigParseOut{authKey, portStr, version, canFile, procPool}
}

// Execute does the primary work for pzsvc-exec.  Given a request and various
// blocks of config data, it creates a temporary folder to work in, downloads
// any files indicated in the request (if the configs support it), executes
// the command indicated by the combination of request and configs, uploads
// any files indicated by the request (if the configs support it) and cleans
// up after itself
func Execute(w http.ResponseWriter, r *http.Request, configObj ConfigType, pzAuth, version string, canFile bool, procPool pzsvc.Semaphore) OutStruct {

	// Makes sure that you only have a certain number of execution tasks firing at once.
	// pzsvc-exec calls can get pretty resource-intensive, and this keeps them from
	// trampling each other into messy deadlock
	procPool.Lock()
	defer procPool.Unlock()

	var output OutStruct
	output.InFiles = make(map[string]string)
	output.OutFiles = make(map[string]string)
	output.HTTPStatus = http.StatusOK

	if r.Method != "POST" {
		handleError(&output, "", fmt.Errorf(r.Method+" not supported.  Please us POST."), w, http.StatusMethodNotAllowed)
		return output
	}

	var inpObj inpStruct

	if _, err := pzsvc.ReadBodyJSON(&inpObj, r.Body); err != nil {
		handleError(&output, "could not interpret body as json: ", err, w, 200)
		inpObj.Command = r.FormValue("cmd")
		inpObj.InPzFiles = splitOrNil(r.FormValue("inFiles"), ",")
		inpObj.InExtFiles = splitOrNil(r.FormValue("inFileURLs"), ",")
		inpObj.InPzNames = splitOrNil(r.FormValue("inPzFileNames"), ",")
		inpObj.InExtNames = splitOrNil(r.FormValue("inExtFileNames"), ",")
		inpObj.OutTiffs = splitOrNil(r.FormValue("outTiffs"), ",")
		inpObj.OutTxts = splitOrNil(r.FormValue("outTxts"), ",")
		inpObj.OutGeoJs = splitOrNil(r.FormValue("outGeoJson"), ",")
		inpObj.ExtAuth = r.FormValue("inUrlAuthKey")
		inpObj.PzAuth = r.FormValue("authKey")
	}

	cmdParamSlice := splitOrNil(inpObj.Command, " ")
	cmdConfigSlice := splitOrNil(configObj.CliCmd, " ")
	cmdSlice := append(cmdConfigSlice, cmdParamSlice...)

	if inpObj.PzAuth != "" {
		pzAuth = inpObj.PzAuth
	}

	if !canFile && (len(inpObj.InPzFiles)+len(inpObj.OutTiffs)+len(inpObj.OutTxts)+len(inpObj.OutGeoJs) != 0) {
		handleError(&output, "", fmt.Errorf("Cannot complete.  File up/download not enabled in config file."), w, http.StatusForbidden)
		return output
	}

	if pzAuth == "" && (len(inpObj.InPzFiles)+len(inpObj.OutTiffs)+len(inpObj.OutTxts)+len(inpObj.OutGeoJs) != 0) {
		handleError(&output, "", fmt.Errorf("Cannot complete.  Auth Key not available."), w, http.StatusForbidden)
		return output
	}

	runID, err := pzsvc.PsuUUID()
	handleError(&output, "psuUUID error: ", err, w, http.StatusInternalServerError)

	err = os.Mkdir("./"+runID, 0777)
	handleError(&output, "os.Mkdir error: ", err, w, http.StatusInternalServerError)
	defer os.RemoveAll("./" + runID)

	err = os.Chmod("./"+runID, 0777)
	handleError(&output, "os.Chmod error: ", err, w, http.StatusInternalServerError)

	// this is done to enable use of handleFList, which lets us
	// reduce a fair bit of code duplication in plowing through
	// our upload/download lists.  handleFList gets used a fair
	// bit more after the execute call.
	pzDownlFunc := func(dataID, fname, fType string) (string, error) {
		return pzsvc.DownloadByID(dataID, fname, runID, configObj.PzAddr, pzAuth)
	}
	handleFList(inpObj.InPzFiles, inpObj.InPzNames, pzDownlFunc, "", &output, output.InFiles, w)

	extDownlFunc := func(url, fname, fType string) (string, error) {
		return pzsvc.DownloadByURL(url, fname, runID, inpObj.ExtAuth)
	}
	handleFList(inpObj.InExtFiles, inpObj.InExtNames, extDownlFunc, "", &output, output.InFiles, w)

	if len(cmdSlice) == 0 {
		handleError(&output, "", errors.New(`No cmd or CliCmd.  Please provide "cmd" param.`), w, http.StatusBadRequest)
		return output
	}

	fmt.Println(`Executing "` + configObj.CliCmd + ` ` + inpObj.Command + `".`)

	// we're calling this from inside a temporary subfolder.  If the
	// program called exists inside the initial pzsvc-exec folder, that's
	// probably where it's called from, and we need to acccess it directly.
	_, err = os.Stat(fmt.Sprintf("./%s", cmdSlice[0]))
	if err == nil || !(os.IsNotExist(err)) {
		// ie, if there's a file in the start folder named the same thing
		// as the base command
		cmdSlice[0] = ("../" + cmdSlice[0])
	}

	clc := exec.Command(cmdSlice[0], cmdSlice[1:]...)
	clc.Dir = runID

	var stdout bytes.Buffer
	var stderr bytes.Buffer
	clc.Stdout = &stdout
	clc.Stderr = &stderr

	err = clc.Run()
	handleError(&output, "clc.Run error: ", err, w, http.StatusBadRequest)

	output.ProgStdOut = stdout.String()
	output.ProgStdErr = stderr.String()

	fmt.Println(`Program stdout: ` + output.ProgStdOut)
	fmt.Println(`Program stderr: ` + output.ProgStdErr)

	attMap := make(map[string]string)
	attMap["algoName"] = configObj.SvcName
	attMap["algoVersion"] = version
	attMap["algoCmd"] = configObj.CliCmd + " " + inpObj.Command
	attMap["algoProcTime"] = time.Now().UTC().Format("20060102.150405.99999")

	// this is the other spot that handleFlist gets used, and works on the
	// same principles.

	ingFunc := func(fName, dummy, fType string) (string, error) {
		return pzsvc.IngestFile(fName, runID, fType, configObj.PzAddr, configObj.SvcName, version, pzAuth, attMap)
	}

	handleFList(inpObj.OutTiffs, nil, ingFunc, "raster", &output, output.OutFiles, w)
	handleFList(inpObj.OutTxts, nil, ingFunc, "text", &output, output.OutFiles, w)
	handleFList(inpObj.OutGeoJs, nil, ingFunc, "geojson", &output, output.OutFiles, w)

	return output
}
<commit_msg>another bit of debug<commit_after>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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 pzse

import (
	"bytes"
	"errors"
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"time"

	"github.com/venicegeo/pzsvc-lib"
)

type inpStruct struct {
	Command    string   `json:"cmd"`
	InPzFiles  []string `json:"inPzFiles"`    // slice: Pz dataIds
	InExtFiles []string `json:"inExtFiles"`   // slice: external URL
	InPzNames  []string `json:"inPzNames"`    // slice: name for the InPzFile of the same index
	InExtNames []string `json:"inExtNames"`   // slice: name for the InExtFile of the same index
	OutTiffs   []string `json:"outTiffs"`     // slice: filenames of GeoTIFFs to be ingested
	OutTxts    []string `json:"outTxts"`      // slice: filenames of text files to be ingested
	OutGeoJs   []string `json:"outGeoJson"`   // slice: filenames of GeoJSON files to be ingested
	ExtAuth    string   `json:"inExtAuthKey"` // string: auth key for accessing external files
	PzAuth     string   `json:"pzAuthKey"`    // string: suth key for accessing Piazza
}

// ParseConfig parses the config file on starting up
func ParseConfig(configObj *ConfigType) ConfigParseOut {

	canReg, canFile, hasAuth := CheckConfig(configObj)

	var authKey string
	if hasAuth {
		authKey = os.Getenv(configObj.AuthEnVar)
		if authKey == "" {
			fmt.Println("Error: no auth key at AuthEnVar.  Registration disabled, and client will have to provide authKey.")
			hasAuth = false
			canReg = false
		}
	}

	if configObj.Port <= 0 {
		configObj.Port = 8080
	}
	portStr := ":" + strconv.Itoa(configObj.Port)

	version := GetVersion(configObj)

	if canReg {
		fmt.Println("About to manage registration.")
		err := pzsvc.ManageRegistration(configObj.SvcName,
			configObj.Description,
			configObj.URL+"/execute",
			configObj.PzAddr,
			version,
			authKey,
			configObj.Attributes)
		if err != nil {
			fmt.Println("pzsvc-exec error in managing registration: ", err.Error())
		}
		fmt.Println("Registration managed.")
	}

	var procPool = pzsvc.Semaphore(nil)
	if configObj.NumProcs > 0 {
		procPool = make(pzsvc.Semaphore, configObj.NumProcs)
	}

	return ConfigParseOut{authKey, portStr, version, canFile, procPool}
}

// Execute does the primary work for pzsvc-exec.  Given a request and various
// blocks of config data, it creates a temporary folder to work in, downloads
// any files indicated in the request (if the configs support it), executes
// the command indicated by the combination of request and configs, uploads
// any files indicated by the request (if the configs support it) and cleans
// up after itself
func Execute(w http.ResponseWriter, r *http.Request, configObj ConfigType, pzAuth, version string, canFile bool, procPool pzsvc.Semaphore) OutStruct {

	// Makes sure that you only have a certain number of execution tasks firing at once.
	// pzsvc-exec calls can get pretty resource-intensive, and this keeps them from
	// trampling each other into messy deadlock
	procPool.Lock()
	defer procPool.Unlock()

	var output OutStruct
	output.InFiles = make(map[string]string)
	output.OutFiles = make(map[string]string)
	output.HTTPStatus = http.StatusOK

	if r.Method != "POST" {
		handleError(&output, "", fmt.Errorf(r.Method+" not supported.  Please us POST."), w, http.StatusMethodNotAllowed)
		return output
	}

	var inpObj inpStruct

	if _, err := pzsvc.ReadBodyJSON(&inpObj, r.Body); err != nil {
		handleError(&output, "could not interpret body as json: ", err, w, 200)
		inpObj.Command = r.FormValue("cmd")
		inpObj.InPzFiles = splitOrNil(r.FormValue("inFiles"), ",")
		inpObj.InExtFiles = splitOrNil(r.FormValue("inFileURLs"), ",")
		inpObj.InPzNames = splitOrNil(r.FormValue("inPzFileNames"), ",")
		inpObj.InExtNames = splitOrNil(r.FormValue("inExtFileNames"), ",")
		inpObj.OutTiffs = splitOrNil(r.FormValue("outTiffs"), ",")
		inpObj.OutTxts = splitOrNil(r.FormValue("outTxts"), ",")
		inpObj.OutGeoJs = splitOrNil(r.FormValue("outGeoJson"), ",")
		inpObj.ExtAuth = r.FormValue("inUrlAuthKey")
		inpObj.PzAuth = r.FormValue("authKey")
	}

	cmdParamSlice := splitOrNil(inpObj.Command, " ")
	cmdConfigSlice := splitOrNil(configObj.CliCmd, " ")
	cmdSlice := append(cmdConfigSlice, cmdParamSlice...)
	fmt.Println(configObj.CliCmd + inpObj.Command)

	if inpObj.PzAuth != "" {
		pzAuth = inpObj.PzAuth
	}

	if !canFile && (len(inpObj.InPzFiles)+len(inpObj.OutTiffs)+len(inpObj.OutTxts)+len(inpObj.OutGeoJs) != 0) {
		handleError(&output, "", fmt.Errorf("Cannot complete.  File up/download not enabled in config file."), w, http.StatusForbidden)
		return output
	}

	if pzAuth == "" && (len(inpObj.InPzFiles)+len(inpObj.OutTiffs)+len(inpObj.OutTxts)+len(inpObj.OutGeoJs) != 0) {
		handleError(&output, "", fmt.Errorf("Cannot complete.  Auth Key not available."), w, http.StatusForbidden)
		return output
	}

	runID, err := pzsvc.PsuUUID()
	handleError(&output, "psuUUID error: ", err, w, http.StatusInternalServerError)

	err = os.Mkdir("./"+runID, 0777)
	handleError(&output, "os.Mkdir error: ", err, w, http.StatusInternalServerError)
	defer os.RemoveAll("./" + runID)

	err = os.Chmod("./"+runID, 0777)
	handleError(&output, "os.Chmod error: ", err, w, http.StatusInternalServerError)

	// this is done to enable use of handleFList, which lets us
	// reduce a fair bit of code duplication in plowing through
	// our upload/download lists.  handleFList gets used a fair
	// bit more after the execute call.
	pzDownlFunc := func(dataID, fname, fType string) (string, error) {
		return pzsvc.DownloadByID(dataID, fname, runID, configObj.PzAddr, pzAuth)
	}
	handleFList(inpObj.InPzFiles, inpObj.InPzNames, pzDownlFunc, "", &output, output.InFiles, w)

	extDownlFunc := func(url, fname, fType string) (string, error) {
		return pzsvc.DownloadByURL(url, fname, runID, inpObj.ExtAuth)
	}
	handleFList(inpObj.InExtFiles, inpObj.InExtNames, extDownlFunc, "", &output, output.InFiles, w)

	if len(cmdSlice) == 0 {
		handleError(&output, "", errors.New(`No cmd or CliCmd.  Please provide "cmd" param.`), w, http.StatusBadRequest)
		return output
	}

	fmt.Println(`Executing "` + configObj.CliCmd + ` ` + inpObj.Command + `".`)

	// we're calling this from inside a temporary subfolder.  If the
	// program called exists inside the initial pzsvc-exec folder, that's
	// probably where it's called from, and we need to acccess it directly.
	_, err = os.Stat(fmt.Sprintf("./%s", cmdSlice[0]))
	if err == nil || !(os.IsNotExist(err)) {
		// ie, if there's a file in the start folder named the same thing
		// as the base command
		cmdSlice[0] = ("../" + cmdSlice[0])
	}

	clc := exec.Command(cmdSlice[0], cmdSlice[1:]...)
	clc.Dir = runID

	var stdout bytes.Buffer
	var stderr bytes.Buffer
	clc.Stdout = &stdout
	clc.Stderr = &stderr

	err = clc.Run()
	handleError(&output, "clc.Run error: ", err, w, http.StatusBadRequest)

	output.ProgStdOut = stdout.String()
	output.ProgStdErr = stderr.String()

	fmt.Println(`Program stdout: ` + output.ProgStdOut)
	fmt.Println(`Program stderr: ` + output.ProgStdErr)

	attMap := make(map[string]string)
	attMap["algoName"] = configObj.SvcName
	attMap["algoVersion"] = version
	attMap["algoCmd"] = configObj.CliCmd + " " + inpObj.Command
	attMap["algoProcTime"] = time.Now().UTC().Format("20060102.150405.99999")

	// this is the other spot that handleFlist gets used, and works on the
	// same principles.

	ingFunc := func(fName, dummy, fType string) (string, error) {
		return pzsvc.IngestFile(fName, runID, fType, configObj.PzAddr, configObj.SvcName, version, pzAuth, attMap)
	}

	handleFList(inpObj.OutTiffs, nil, ingFunc, "raster", &output, output.OutFiles, w)
	handleFList(inpObj.OutTxts, nil, ingFunc, "text", &output, output.OutFiles, w)
	handleFList(inpObj.OutGeoJs, nil, ingFunc, "geojson", &output, output.OutFiles, w)

	return output
}
<|endoftext|>


<commit_before>package avltree

import (
    "fmt"
)

type AVLNode struct {
    key int
    value int
    // height counts nodes (not edges)
    height int
    left *AVLNode
    right *AVLNode
}

func max(a int, b int) int {
    if a > b {
        return a
    }
    return b
}

func height(node *AVLNode) int {
    if node == nil {
        return 0
    }
    return node.height
}

func recalculateHeight(node *AVLNode) {
    node.height = 1 + max(height(node.left), height(node.right))
}

func add(node *AVLNode, key int, value int) *AVLNode {
    if node == nil {
        return &AVLNode{key, value, 1, nil, nil}
    }

    if key < node.key {
        node.left = add(node.left, key, value)
    } else if key > node.key {
        node.right = add(node.right, key, value)
    } else {
        // if same key exists update value
        node.value = value
    }
    return rebalanceTree(node)
}

func rebalanceTree(node *AVLNode) *AVLNode {
    if node == nil {
        return node
    }
    recalculateHeight(node)

    // check balance factor and rotateLeft if right-heavy and rotateRight if left-heavy
    balanceFactor := height(node.left) - height(node.right)
    if balanceFactor == -2 {
        // check if child is left-heavy and rotateRight first
        if height(node.right.left) > height(node.right.right) {
            node.right = rotateRight(node.right)
        }
        return rotateLeft(node)
    } else if balanceFactor == 2 {
        // check if child is right-heavy and rotateLeft first
        if height(node.left.right) > height(node.left.left) {
            node.left = rotateLeft(node.left)
        }
        return rotateRight(node)
    }
    return node
}

func rotateLeft(node *AVLNode) *AVLNode {
    newRoot := node.right
    node.right = newRoot.left
    newRoot.left = node

    recalculateHeight(node)
    recalculateHeight(newRoot)
    return newRoot
}

func rotateRight(node *AVLNode) *AVLNode {
    newRoot := node.left
    node.left = newRoot.right
    newRoot.right = node

    recalculateHeight(node)
    recalculateHeight(newRoot)
    return newRoot
}

func search(node *AVLNode, key int) *AVLNode {
    if node == nil {
        return nil
    }
    if key < node.key {
        return search(node.left, key)
    } else if key > node.key {
        return search(node.right, key)
    } else {
        return node
    }
}

func remove(node *AVLNode, key int) *AVLNode {
    if node == nil {
        return nil
    }
    if key < node.key {
        node.left = remove(node.left, key)
    } else if key > node.key {
        node.right = remove(node.right, key)
    } else {
        if node.left != nil && node.right != nil {
           // node to delete found with both children;
           // replace values with smallest node of the right sub-tree
           rightMinNode := findSmallest(node.right)
           node.key = rightMinNode.key
           node.value = rightMinNode.value
           // delete smallest node that we replaced
           //node.right = remove(node.right, rightMinNode.key)
           node.right = remove(node.right, rightMinNode.key)
        } else if node.left != nil {
           // node only has left child
           node = node.left
        } else if node.right != nil {
           // node only has right child
           node = node.right
        } else {
           // node has no children
           node = nil
           return node
        }

    }
    return rebalanceTree(node)
}

func findSmallest(node *AVLNode) *AVLNode {
    if node.left != nil {
        return findSmallest(node.left)
    } else {
        return node
    }
}

func displayTreeInOrder(node *AVLNode) {
    if node.left != nil {
        displayTreeInOrder(node.left)
    }
    fmt.Print(node.key, " ")
    if node.right != nil {
        displayTreeInOrder(node.right)
    }
}

<commit_msg>change 'public' methods to begin with uppercase to be used from other packages<commit_after>package avltree

import (
    "fmt"
)

type AVLNode struct {
    key int
    value int
    // height counts nodes (not edges)
    height int
    left *AVLNode
    right *AVLNode
}

func max(a int, b int) int {
    if a > b {
        return a
    }
    return b
}

func height(node *AVLNode) int {
    if node == nil {
        return 0
    }
    return node.height
}

func recalculateHeight(node *AVLNode) {
    node.height = 1 + max(height(node.left), height(node.right))
}

func Add(node *AVLNode, key int, value int) *AVLNode {
    if node == nil {
        return &AVLNode{key, value, 1, nil, nil}
    }

    if key < node.key {
        node.left = Add(node.left, key, value)
    } else if key > node.key {
        node.right = Add(node.right, key, value)
    } else {
        // if same key exists update value
        node.value = value
    }
    return rebalanceTree(node)
}

func rebalanceTree(node *AVLNode) *AVLNode {
    if node == nil {
        return node
    }
    recalculateHeight(node)

    // check balance factor and rotateLeft if right-heavy and rotateRight if left-heavy
    balanceFactor := height(node.left) - height(node.right)
    if balanceFactor == -2 {
        // check if child is left-heavy and rotateRight first
        if height(node.right.left) > height(node.right.right) {
            node.right = rotateRight(node.right)
        }
        return rotateLeft(node)
    } else if balanceFactor == 2 {
        // check if child is right-heavy and rotateLeft first
        if height(node.left.right) > height(node.left.left) {
            node.left = rotateLeft(node.left)
        }
        return rotateRight(node)
    }
    return node
}

func rotateLeft(node *AVLNode) *AVLNode {
    newRoot := node.right
    node.right = newRoot.left
    newRoot.left = node

    recalculateHeight(node)
    recalculateHeight(newRoot)
    return newRoot
}

func rotateRight(node *AVLNode) *AVLNode {
    newRoot := node.left
    node.left = newRoot.right
    newRoot.right = node

    recalculateHeight(node)
    recalculateHeight(newRoot)
    return newRoot
}

func Search(node *AVLNode, key int) *AVLNode {
    if node == nil {
        return nil
    }
    if key < node.key {
        return Search(node.left, key)
    } else if key > node.key {
        return Search(node.right, key)
    } else {
        return node
    }
}

func Remove(node *AVLNode, key int) *AVLNode {
    if node == nil {
        return nil
    }
    if key < node.key {
        node.left = Remove(node.left, key)
    } else if key > node.key {
        node.right = Remove(node.right, key)
    } else {
        if node.left != nil && node.right != nil {
           // node to delete found with both children;
           // replace values with smallest node of the right sub-tree
           rightMinNode := findSmallest(node.right)
           node.key = rightMinNode.key
           node.value = rightMinNode.value
           // delete smallest node that we replaced
           node.right = Remove(node.right, rightMinNode.key)
        } else if node.left != nil {
           // node only has left child
           node = node.left
        } else if node.right != nil {
           // node only has right child
           node = node.right
        } else {
           // node has no children
           node = nil
           return node
        }

    }
    return rebalanceTree(node)
}

func findSmallest(node *AVLNode) *AVLNode {
    if node.left != nil {
        return findSmallest(node.left)
    } else {
        return node
    }
}

func DisplayTreeInOrder(node *AVLNode) {
    if node.left != nil {
        DisplayTreeInOrder(node.left)
    }
    fmt.Print(node.key, " ")
    if node.right != nil {
        DisplayTreeInOrder(node.right)
    }
}

<|endoftext|>