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

package current

import (
	"encoding/json"
	"fmt"
	"io"
	"net"
	"os"

	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/types/020"
)

const ImplementedSpecVersion string = "0.4.0"

var SupportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}

func NewResult(data []byte) (types.Result, error) {
	result := &Result{}
	if err := json.Unmarshal(data, result); err != nil {
		return nil, err
	}
	return result, nil
}

func GetResult(r types.Result) (*Result, error) {
	resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
	if err != nil {
		return nil, err
	}
	result, ok := resultCurrent.(*Result)
	if !ok {
		return nil, fmt.Errorf("failed to convert result")
	}
	return result, nil
}

var resultConverters = []struct {
	versions []string
	convert  func(types.Result) (*Result, error)
}{
	{types020.SupportedVersions, convertFrom020},
	{SupportedVersions, convertFrom030},
}

func convertFrom020(result types.Result) (*Result, error) {
	oldResult, err := types020.GetResult(result)
	if err != nil {
		return nil, err
	}

	newResult := &Result{
		CNIVersion: ImplementedSpecVersion,
		DNS:        oldResult.DNS,
		Routes:     []*types.Route{},
	}

	if oldResult.IP4 != nil {
		newResult.IPs = append(newResult.IPs, &IPConfig{
			Version: "4",
			Address: oldResult.IP4.IP,
			Gateway: oldResult.IP4.Gateway,
		})
		for _, route := range oldResult.IP4.Routes {
			newResult.Routes = append(newResult.Routes, &types.Route{
				Dst: route.Dst,
				GW:  route.GW,
			})
		}
	}

	if oldResult.IP6 != nil {
		newResult.IPs = append(newResult.IPs, &IPConfig{
			Version: "6",
			Address: oldResult.IP6.IP,
			Gateway: oldResult.IP6.Gateway,
		})
		for _, route := range oldResult.IP6.Routes {
			newResult.Routes = append(newResult.Routes, &types.Route{
				Dst: route.Dst,
				GW:  route.GW,
			})
		}
	}

	return newResult, nil
}

func convertFrom030(result types.Result) (*Result, error) {
	newResult, ok := result.(*Result)
	if !ok {
		return nil, fmt.Errorf("failed to convert result")
	}
	newResult.CNIVersion = ImplementedSpecVersion
	return newResult, nil
}

func NewResultFromResult(result types.Result) (*Result, error) {
	version := result.Version()
	for _, converter := range resultConverters {
		for _, supportedVersion := range converter.versions {
			if version == supportedVersion {
				return converter.convert(result)
			}
		}
	}
	return nil, fmt.Errorf("unsupported CNI result22 version %q", version)
}

// Result is what gets returned from the plugin (via stdout) to the caller
type Result struct {
	CNIVersion string         `json:"cniVersion,omitempty"`
	Interfaces []*Interface   `json:"interfaces,omitempty"`
	IPs        []*IPConfig    `json:"ips,omitempty"`
	Routes     []*types.Route `json:"routes,omitempty"`
	DNS        types.DNS      `json:"dns,omitempty"`
}

// Convert to the older 0.2.0 CNI spec Result type
func (r *Result) convertTo020() (*types020.Result, error) {
	oldResult := &types020.Result{
		CNIVersion: types020.ImplementedSpecVersion,
		DNS:        r.DNS,
	}

	for _, ip := range r.IPs {
		// Only convert the first IP address of each version as 0.2.0
		// and earlier cannot handle multiple IP addresses
		if ip.Version == "4" && oldResult.IP4 == nil {
			oldResult.IP4 = &types020.IPConfig{
				IP:      ip.Address,
				Gateway: ip.Gateway,
			}
		} else if ip.Version == "6" && oldResult.IP6 == nil {
			oldResult.IP6 = &types020.IPConfig{
				IP:      ip.Address,
				Gateway: ip.Gateway,
			}
		}

		if oldResult.IP4 != nil && oldResult.IP6 != nil {
			break
		}
	}

	for _, route := range r.Routes {
		is4 := route.Dst.IP.To4() != nil
		if is4 && oldResult.IP4 != nil {
			oldResult.IP4.Routes = append(oldResult.IP4.Routes, types.Route{
				Dst: route.Dst,
				GW:  route.GW,
			})
		} else if !is4 && oldResult.IP6 != nil {
			oldResult.IP6.Routes = append(oldResult.IP6.Routes, types.Route{
				Dst: route.Dst,
				GW:  route.GW,
			})
		}
	}

	if oldResult.IP4 == nil && oldResult.IP6 == nil {
		return nil, fmt.Errorf("cannot convert: no valid IP addresses")
	}

	return oldResult, nil
}

func (r *Result) Version() string {
	return ImplementedSpecVersion
}

func (r *Result) GetAsVersion(version string) (types.Result, error) {
	switch version {
	case "0.3.0", "0.3.1", ImplementedSpecVersion:
		r.CNIVersion = version
		return r, nil
	case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]:
		return r.convertTo020()
	}
	return nil, fmt.Errorf("cannot convert version 0.3.x to %q", version)
}

func (r *Result) Print() error {
	return r.PrintTo(os.Stdout)
}

func (r *Result) PrintTo(writer io.Writer) error {
	data, err := json.MarshalIndent(r, "", "    ")
	if err != nil {
		return err
	}
	_, err = writer.Write(data)
	return err
}

// String returns a formatted string in the form of "[Interfaces: $1,][ IP: $2,] DNS: $3" where
// $1 represents the receiver's Interfaces, $2 represents the receiver's IP addresses and $3 the
// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string.
func (r *Result) String() string {
	var str string
	if len(r.Interfaces) > 0 {
		str += fmt.Sprintf("Interfaces:%+v, ", r.Interfaces)
	}
	if len(r.IPs) > 0 {
		str += fmt.Sprintf("IP:%+v, ", r.IPs)
	}
	if len(r.Routes) > 0 {
		str += fmt.Sprintf("Routes:%+v, ", r.Routes)
	}
	return fmt.Sprintf("%sDNS:%+v", str, r.DNS)
}

// Convert this old version result to the current CNI version result
func (r *Result) Convert() (*Result, error) {
	return r, nil
}

// Interface contains values about the created interfaces
type Interface struct {
	Name    string `json:"name"`
	Mac     string `json:"mac,omitempty"`
	Sandbox string `json:"sandbox,omitempty"`
}

func (i *Interface) String() string {
	return fmt.Sprintf("%+v", *i)
}

// Int returns a pointer to the int value passed in.  Used to
// set the IPConfig.Interface field.
func Int(v int) *int {
	return &v
}

// IPConfig contains values necessary to configure an IP address on an interface
type IPConfig struct {
	// IP version, either "4" or "6"
	Version string
	// Index into Result structs Interfaces list
	Interface *int
	Address   net.IPNet
	Gateway   net.IP
}

func (i *IPConfig) String() string {
	return fmt.Sprintf("%+v", *i)
}

// JSON (un)marshallable types
type ipConfig struct {
	Version   string      `json:"version"`
	Interface *int        `json:"interface,omitempty"`
	Address   types.IPNet `json:"address"`
	Gateway   net.IP      `json:"gateway,omitempty"`
}

func (c *IPConfig) MarshalJSON() ([]byte, error) {
	ipc := ipConfig{
		Version:   c.Version,
		Interface: c.Interface,
		Address:   types.IPNet(c.Address),
		Gateway:   c.Gateway,
	}

	return json.Marshal(ipc)
}

func (c *IPConfig) UnmarshalJSON(data []byte) error {
	ipc := ipConfig{}
	if err := json.Unmarshal(data, &ipc); err != nil {
		return err
	}

	c.Version = ipc.Version
	c.Interface = ipc.Interface
	c.Address = net.IPNet(ipc.Address)
	c.Gateway = ipc.Gateway
	return nil
}
<commit_msg>hopefully resolved merge conflicts<commit_after>// Copyright 2016 CNI authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package current

import (
	"encoding/json"
	"fmt"
	"io"
	"net"
	"os"

	"github.com/containernetworking/cni/pkg/types"
	types020 "github.com/containernetworking/cni/pkg/types/020"
)

const ImplementedSpecVersion string = "0.4.0"

var SupportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}

func NewResult(data []byte) (types.Result, error) {
	result := &Result{}
	if err := json.Unmarshal(data, result); err != nil {
		return nil, err
	}
	return result, nil
}

func GetResult(r types.Result) (*Result, error) {
	resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
	if err != nil {
		return nil, err
	}
	result, ok := resultCurrent.(*Result)
	if !ok {
		return nil, fmt.Errorf("failed to convert result")
	}
	return result, nil
}

var resultConverters = []struct {
	versions []string
	convert  func(types.Result) (*Result, error)
}{
	{types020.SupportedVersions, convertFrom020},
	{SupportedVersions, convertFrom030},
}

func convertFrom020(result types.Result) (*Result, error) {
	oldResult, err := types020.GetResult(result)
	if err != nil {
		return nil, err
	}

	newResult := &Result{
		CNIVersion: ImplementedSpecVersion,
		DNS:        oldResult.DNS,
		Routes:     []*types.Route{},
	}

	if oldResult.IP4 != nil {
		newResult.IPs = append(newResult.IPs, &IPConfig{
			Version: "4",
			Address: oldResult.IP4.IP,
			Gateway: oldResult.IP4.Gateway,
		})
		for _, route := range oldResult.IP4.Routes {
			newResult.Routes = append(newResult.Routes, &types.Route{
				Dst: route.Dst,
				GW:  route.GW,
			})
		}
	}

	if oldResult.IP6 != nil {
		newResult.IPs = append(newResult.IPs, &IPConfig{
			Version: "6",
			Address: oldResult.IP6.IP,
			Gateway: oldResult.IP6.Gateway,
		})
		for _, route := range oldResult.IP6.Routes {
			newResult.Routes = append(newResult.Routes, &types.Route{
				Dst: route.Dst,
				GW:  route.GW,
			})
		}
	}

	return newResult, nil
}

func convertFrom030(result types.Result) (*Result, error) {
	newResult, ok := result.(*Result)
	if !ok {
		return nil, fmt.Errorf("failed to convert result")
	}
	newResult.CNIVersion = ImplementedSpecVersion
	return newResult, nil
}

func NewResultFromResult(result types.Result) (*Result, error) {
	version := result.Version()
	for _, converter := range resultConverters {
		for _, supportedVersion := range converter.versions {
			if version == supportedVersion {
				return converter.convert(result)
			}
		}
	}
	return nil, fmt.Errorf("unsupported CNI result22 version %q", version)
}

// Result is what gets returned from the plugin (via stdout) to the caller
type Result struct {
	CNIVersion string         `json:"cniVersion,omitempty"`
	Interfaces []*Interface   `json:"interfaces,omitempty"`
	IPs        []*IPConfig    `json:"ips,omitempty"`
	Routes     []*types.Route `json:"routes,omitempty"`
	DNS        types.DNS      `json:"dns,omitempty"`
}

// Convert to the older 0.2.0 CNI spec Result type
func (r *Result) convertTo020() (*types020.Result, error) {
	oldResult := &types020.Result{
		CNIVersion: types020.ImplementedSpecVersion,
		DNS:        r.DNS,
	}

	for _, ip := range r.IPs {
		// Only convert the first IP address of each version as 0.2.0
		// and earlier cannot handle multiple IP addresses
		if ip.Version == "4" && oldResult.IP4 == nil {
			oldResult.IP4 = &types020.IPConfig{
				IP:      ip.Address,
				Gateway: ip.Gateway,
			}
		} else if ip.Version == "6" && oldResult.IP6 == nil {
			oldResult.IP6 = &types020.IPConfig{
				IP:      ip.Address,
				Gateway: ip.Gateway,
			}
		}

		if oldResult.IP4 != nil && oldResult.IP6 != nil {
			break
		}
	}

	for _, route := range r.Routes {
		is4 := route.Dst.IP.To4() != nil
		if is4 && oldResult.IP4 != nil {
			oldResult.IP4.Routes = append(oldResult.IP4.Routes, types.Route{
				Dst: route.Dst,
				GW:  route.GW,
			})
		} else if !is4 && oldResult.IP6 != nil {
			oldResult.IP6.Routes = append(oldResult.IP6.Routes, types.Route{
				Dst: route.Dst,
				GW:  route.GW,
			})
		}
	}

	if oldResult.IP4 == nil && oldResult.IP6 == nil {
		return nil, fmt.Errorf("cannot convert: no valid IP addresses")
	}

	return oldResult, nil
}

func (r *Result) Version() string {
	return ImplementedSpecVersion
}

func (r *Result) GetAsVersion(version string) (types.Result, error) {
	switch version {
	case "0.3.0", "0.3.1", ImplementedSpecVersion:
		r.CNIVersion = version
		return r, nil
	case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]:
		return r.convertTo020()
	}
	return nil, fmt.Errorf("cannot convert version 0.3.x to %q", version)
}

func (r *Result) Print() error {
	return r.PrintTo(os.Stdout)
}

func (r *Result) PrintTo(writer io.Writer) error {
	data, err := json.MarshalIndent(r, "", "    ")
	if err != nil {
		return err
	}
	_, err = writer.Write(data)
	return err
}

// String returns a formatted string in the form of "[Interfaces: $1,][ IP: $2,] DNS: $3" where
// $1 represents the receiver's Interfaces, $2 represents the receiver's IP addresses and $3 the
// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string.
func (r *Result) String() string {
	var str string
	if len(r.Interfaces) > 0 {
		str += fmt.Sprintf("Interfaces:%+v, ", r.Interfaces)
	}
	if len(r.IPs) > 0 {
		str += fmt.Sprintf("IP:%+v, ", r.IPs)
	}
	if len(r.Routes) > 0 {
		str += fmt.Sprintf("Routes:%+v, ", r.Routes)
	}
	return fmt.Sprintf("%sDNS:%+v", str, r.DNS)
}

// Convert this old version result to the current CNI version result
func (r *Result) Convert() (*Result, error) {
	return r, nil
}

// Interface contains values about the created interfaces
type Interface struct {
	Name    string `json:"name"`
	Mac     string `json:"mac,omitempty"`
	Sandbox string `json:"sandbox,omitempty"`
}

func (i *Interface) String() string {
	return fmt.Sprintf("%+v", *i)
}

// Int returns a pointer to the int value passed in.  Used to
// set the IPConfig.Interface field.
func Int(v int) *int {
	return &v
}

// IPConfig contains values necessary to configure an IP address on an interface
type IPConfig struct {
	// IP version, either "4" or "6"
	Version string
	// Index into Result structs Interfaces list
	Interface *int
	Address   net.IPNet
	Gateway   net.IP
}

func (i *IPConfig) String() string {
	return fmt.Sprintf("%+v", *i)
}

// JSON (un)marshallable types
type ipConfig struct {
	Version   string      `json:"version"`
	Interface *int        `json:"interface,omitempty"`
	Address   types.IPNet `json:"address"`
	Gateway   net.IP      `json:"gateway,omitempty"`
}

func (c *IPConfig) MarshalJSON() ([]byte, error) {
	ipc := ipConfig{
		Version:   c.Version,
		Interface: c.Interface,
		Address:   types.IPNet(c.Address),
		Gateway:   c.Gateway,
	}

	return json.Marshal(ipc)
}

func (c *IPConfig) UnmarshalJSON(data []byte) error {
	ipc := ipConfig{}
	if err := json.Unmarshal(data, &ipc); err != nil {
		return err
	}

	c.Version = ipc.Version
	c.Interface = ipc.Interface
	c.Address = net.IPNet(ipc.Address)
	c.Gateway = ipc.Gateway
	return nil
}
<|endoftext|>


<commit_before>package fuse

import (
	"os"
	"sync"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	pfsclient "github.com/pachyderm/pachyderm/src/client/pfs"
)

const (
	namePrefix = "pfs://"
	subtype    = "pfs"
)

type mounter struct {
	address   string
	apiClient pfsclient.APIClient
}

func newMounter(address string, apiClient pfsclient.APIClient) Mounter {
	return &mounter{
		address,
		apiClient,
	}
}

func (m *mounter) Mount(
	mountPoint string,
	shard *pfsclient.Shard,
	commitMounts []*CommitMount,
	ready chan bool,
) (retErr error) {
	var once sync.Once
	defer once.Do(func() {
		if ready != nil {
			close(ready)
		}
	})
	// TODO: should we make the caller do this?
	if err := os.MkdirAll(mountPoint, 0777); err != nil {
		return err
	}
	name := namePrefix + m.address
	conn, err := fuse.Mount(
		mountPoint,
		fuse.FSName(name),
		fuse.VolumeName(name),
		fuse.Subtype(subtype),
		fuse.AllowOther(),
		fuse.WritebackCache(),
		fuse.MaxReadahead(1<<32-1),
	)
	if err != nil {
		return err
	}
	defer func() {
		if err := conn.Close(); err != nil && retErr == nil {
			retErr = err
		}
	}()
	once.Do(func() {
		if ready != nil {
			close(ready)
		}
	})
	if err := fs.Serve(conn, newFilesystem(m.apiClient, shard, commitMounts)); err != nil {
		return err
	}
	<-conn.Ready
	return conn.MountError
}

func (m *mounter) Unmount(mountPoint string) error {
	return fuse.Unmount(mountPoint)
}
<commit_msg>add a handler for SIGINT to unmount the filesystem<commit_after>package fuse

import (
	"os"
	"os/signal"
	"sync"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	pfsclient "github.com/pachyderm/pachyderm/src/client/pfs"
)

const (
	namePrefix = "pfs://"
	subtype    = "pfs"
)

type mounter struct {
	address   string
	apiClient pfsclient.APIClient
}

func newMounter(address string, apiClient pfsclient.APIClient) Mounter {
	return &mounter{
		address,
		apiClient,
	}
}

func (m *mounter) Mount(
	mountPoint string,
	shard *pfsclient.Shard,
	commitMounts []*CommitMount,
	ready chan bool,
) (retErr error) {
	var once sync.Once
	defer once.Do(func() {
		if ready != nil {
			close(ready)
		}
	})
	// TODO: should we make the caller do this?
	if err := os.MkdirAll(mountPoint, 0777); err != nil {
		return err
	}
	name := namePrefix + m.address
	conn, err := fuse.Mount(
		mountPoint,
		fuse.FSName(name),
		fuse.VolumeName(name),
		fuse.Subtype(subtype),
		fuse.AllowOther(),
		fuse.WritebackCache(),
		fuse.MaxReadahead(1<<32-1),
	)
	if err != nil {
		return err
	}
	defer func() {
		if err := conn.Close(); err != nil && retErr == nil {
			retErr = err
		}
	}()

	sigChan := make(chan os.Signal,1)
	signal.Notify(sigChan, os.Interrupt)
	go func() {
		<-sigChan
		m.Unmount(mountPoint)
	}()

	once.Do(func() {
		if ready != nil {
			close(ready)
		}
	})
	if err := fs.Serve(conn, newFilesystem(m.apiClient, shard, commitMounts)); err != nil {
		return err
	}
	<-conn.Ready
	return conn.MountError
}

func (m *mounter) Unmount(mountPoint string) error {
	return fuse.Unmount(mountPoint)
}
<|endoftext|>


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

// +build linux

package syscall_test

import (
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"testing"
)

func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd {
	if _, err := os.Stat("/proc/self/ns/user"); err != nil {
		if os.IsNotExist(err) {
			t.Skip("kernel doesn't support user namespaces")
		}
		t.Fatalf("Failed to stat /proc/self/ns/user: %v", err)
	}
	cmd := exec.Command("whoami")
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWUSER,
		UidMappings: []syscall.SysProcIDMap{
			{ContainerID: 0, HostID: uid, Size: 1},
		},
		GidMappings: []syscall.SysProcIDMap{
			{ContainerID: 0, HostID: gid, Size: 1},
		},
		GidMappingsEnableSetgroups: setgroups,
	}
	return cmd
}

func testNEWUSERRemap(t *testing.T, uid, gid int, setgroups bool) {
	cmd := whoamiCmd(t, uid, gid, setgroups)
	out, err := cmd.CombinedOutput()
	if err != nil {
		// On some systems, there is a sysctl setting.
		if os.IsPermission(err) && os.Getuid() != 0 {
			data, errRead := ioutil.ReadFile("/proc/sys/kernel/unprivileged_userns_clone")
			if errRead == nil && data[0] == '0' {
				t.Skip("kernel prohibits user namespace in unprivileged process")
			}
		}

		t.Fatalf("Cmd failed with err %v, output: %s", err, out)
	}
	sout := strings.TrimSpace(string(out))
	want := "root"
	if sout != want {
		t.Fatalf("whoami = %q; want %q", out, want)
	}
}

func TestCloneNEWUSERAndRemapRootDisableSetgroups(t *testing.T) {
	if os.Getuid() != 0 {
		t.Skip("skipping root only test")
	}
	testNEWUSERRemap(t, 0, 0, false)
}

func TestCloneNEWUSERAndRemapRootEnableSetgroups(t *testing.T) {
	if os.Getuid() != 0 {
		t.Skip("skipping root only test")
	}
	testNEWUSERRemap(t, 0, 0, false)
}

// kernelVersion returns the major and minor versions of the Linux
// kernel version.  It calls t.Skip if it can't figure it out.
func kernelVersion(t *testing.T) (int, int) {
	bytes, err := ioutil.ReadFile("/proc/version")
	if err != nil {
		t.Skipf("can't get kernel version: %v", err)
	}
	matches := regexp.MustCompile("([0-9]+).([0-9]+)").FindSubmatch(bytes)
	if len(matches) < 3 {
		t.Skipf("can't get kernel version from %s", bytes)
	}
	major, _ := strconv.Atoi(string(matches[1]))
	minor, _ := strconv.Atoi(string(matches[2]))
	return major, minor
}

func TestCloneNEWUSERAndRemapNoRootDisableSetgroups(t *testing.T) {
	if os.Getuid() == 0 {
		t.Skip("skipping unprivileged user only test")
	}
	testNEWUSERRemap(t, os.Getuid(), os.Getgid(), false)
}

func TestCloneNEWUSERAndRemapNoRootSetgroupsEnableSetgroups(t *testing.T) {
	if os.Getuid() == 0 {
		t.Skip("skipping unprivileged user only test")
	}
	cmd := whoamiCmd(t, os.Getuid(), os.Getgid(), true)
	err := cmd.Run()
	if err == nil {
		t.Skip("probably old kernel without security fix")
	}
	if !os.IsPermission(err) {
		t.Fatalf("Unprivileged gid_map rewriting with GidMappingsEnableSetgroups must fail")
	}
}

func TestEmptyCredGroupsDisableSetgroups(t *testing.T) {
	cmd := whoamiCmd(t, os.Getuid(), os.Getgid(), false)
	cmd.SysProcAttr.Credential = &syscall.Credential{}
	if err := cmd.Run(); err != nil {
		t.Fatal(err)
	}
}
<commit_msg>syscall: move check of unprivileged_userns_clone to whoamiCmd<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux

package syscall_test

import (
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"testing"
)

func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd {
	if _, err := os.Stat("/proc/self/ns/user"); err != nil {
		if os.IsNotExist(err) {
			t.Skip("kernel doesn't support user namespaces")
		}
		t.Fatalf("Failed to stat /proc/self/ns/user: %v", err)
	}
	// On some systems, there is a sysctl setting.
	if os.Getuid() != 0 {
		data, errRead := ioutil.ReadFile("/proc/sys/kernel/unprivileged_userns_clone")
		if errRead == nil && data[0] == '0' {
			t.Skip("kernel prohibits user namespace in unprivileged process")
		}
	}
	cmd := exec.Command("whoami")
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWUSER,
		UidMappings: []syscall.SysProcIDMap{
			{ContainerID: 0, HostID: uid, Size: 1},
		},
		GidMappings: []syscall.SysProcIDMap{
			{ContainerID: 0, HostID: gid, Size: 1},
		},
		GidMappingsEnableSetgroups: setgroups,
	}
	return cmd
}

func testNEWUSERRemap(t *testing.T, uid, gid int, setgroups bool) {
	cmd := whoamiCmd(t, uid, gid, setgroups)
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("Cmd failed with err %v, output: %s", err, out)
	}
	sout := strings.TrimSpace(string(out))
	want := "root"
	if sout != want {
		t.Fatalf("whoami = %q; want %q", out, want)
	}
}

func TestCloneNEWUSERAndRemapRootDisableSetgroups(t *testing.T) {
	if os.Getuid() != 0 {
		t.Skip("skipping root only test")
	}
	testNEWUSERRemap(t, 0, 0, false)
}

func TestCloneNEWUSERAndRemapRootEnableSetgroups(t *testing.T) {
	if os.Getuid() != 0 {
		t.Skip("skipping root only test")
	}
	testNEWUSERRemap(t, 0, 0, false)
}

// kernelVersion returns the major and minor versions of the Linux
// kernel version.  It calls t.Skip if it can't figure it out.
func kernelVersion(t *testing.T) (int, int) {
	bytes, err := ioutil.ReadFile("/proc/version")
	if err != nil {
		t.Skipf("can't get kernel version: %v", err)
	}
	matches := regexp.MustCompile("([0-9]+).([0-9]+)").FindSubmatch(bytes)
	if len(matches) < 3 {
		t.Skipf("can't get kernel version from %s", bytes)
	}
	major, _ := strconv.Atoi(string(matches[1]))
	minor, _ := strconv.Atoi(string(matches[2]))
	return major, minor
}

func TestCloneNEWUSERAndRemapNoRootDisableSetgroups(t *testing.T) {
	if os.Getuid() == 0 {
		t.Skip("skipping unprivileged user only test")
	}
	testNEWUSERRemap(t, os.Getuid(), os.Getgid(), false)
}

func TestCloneNEWUSERAndRemapNoRootSetgroupsEnableSetgroups(t *testing.T) {
	if os.Getuid() == 0 {
		t.Skip("skipping unprivileged user only test")
	}
	cmd := whoamiCmd(t, os.Getuid(), os.Getgid(), true)
	err := cmd.Run()
	if err == nil {
		t.Skip("probably old kernel without security fix")
	}
	if !os.IsPermission(err) {
		t.Fatalf("Unprivileged gid_map rewriting with GidMappingsEnableSetgroups must fail")
	}
}

func TestEmptyCredGroupsDisableSetgroups(t *testing.T) {
	cmd := whoamiCmd(t, os.Getuid(), os.Getgid(), false)
	cmd.SysProcAttr.Credential = &syscall.Credential{}
	if err := cmd.Run(); err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

//go:generate stringer -type=Action

// The Actor struct holds info about an actor I.E the Lad or a Rock
type Actor struct {
	Type       int
	Y          int
	X          int
	Ch         byte
	Dir        Action
	DirRequest Action
	JumpStep   int
}

type Action int

// The Action constans define what the Actor currently is, or is requested to be, doing
const (
	STOPPED Action = iota
	UP
	UPRIGHT
	RIGHT
	DOWNRIGHT
	DOWN
	DOWNLEFT
	LEFT
	UPLEFT
	FALLING
	JUMP // Generic jump set by keyhandler
	JUMPRIGHT
	JUMPUP
	JUMPLEFT
)

var jumpLeft = []Action{UPLEFT, UPLEFT, LEFT, LEFT, DOWNLEFT, DOWNLEFT}
var jumpRight = []Action{UPRIGHT, UPRIGHT, RIGHT, RIGHT, DOWNRIGHT, DOWNRIGHT}
var jumpUp = []Action{UP, UP, STOPPED, DOWN, DOWN}

var jumpPaths = map[Action][]Action{
	JUMPUP:    jumpUp,
	JUMPLEFT:  jumpLeft,
	JUMPRIGHT: jumpRight,
}

var dirs = map[Action]struct {
	x, y int
}{
	STOPPED:   {0, 0},
	UP:        {0, -1},
	UPRIGHT:   {1, -1},
	RIGHT:     {1, 0},
	DOWNRIGHT: {1, 1},
	DOWN:      {0, 1},
	DOWNLEFT:  {-1, 1},
	LEFT:      {-1, 0},
	UPLEFT:    {-1, -1},
	FALLING:   {0, 1},
	JUMP:      {0, 0},
	JUMPRIGHT: {0, 0},
	JUMPLEFT:  {0, 0},
	JUMPUP:    {0, 0},
}

//
// A moving jummp is UR/UR/R/R/DR/DR
// or                UL/UL/L/L/DL/DL
// A standing jump is U/U/-/D/D
//
// 	 ====================
//   ----234-----23------
//   ---1---5----14------
//   --0-----6---05------
//   ====================
//

//
//
//
func MoveActor(a Actor, m MapData) Actor {

loopAgain: // If just started falling we need to retest all conditions

	// If stopped or going left or going right and requst to do something else, then try to do it
	if (a.Dir == STOPPED && a.DirRequest == LEFT) ||
		(a.Dir == STOPPED && a.DirRequest == RIGHT) ||
		(a.Dir == LEFT && a.DirRequest == RIGHT) ||
		(a.Dir == RIGHT && a.DirRequest == LEFT) {
		a.Dir = a.DirRequest
		a.DirRequest = STOPPED

	}

	// Handle starting of jumps
	if a.DirRequest == JUMP {
		switch a.Dir {
		case STOPPED:
			a.DirRequest = a.Dir
			a.Dir = JUMPUP
			a.JumpStep = 0
		case LEFT:
			a.DirRequest = a.Dir
			a.Dir = JUMPLEFT
			a.JumpStep = 0
		case RIGHT:
			a.DirRequest = a.Dir
			a.Dir = JUMPRIGHT
			a.JumpStep = 0
		}
	}

	// Do the jumping
	if a.Dir == JUMPUP || a.Dir == JUMPLEFT || a.Dir == JUMPRIGHT {
		jd := jumpPaths[a.Dir][a.JumpStep]
		if m.Field[a.Y+dirs[jd].y][a.X+dirs[jd].x] == ' ' {
			a.X += dirs[jd].x
			a.Y += dirs[jd].y
			a.JumpStep++
			if a.JumpStep >= len(jumpPaths[a.Dir]) {
				a.Dir = a.DirRequest
			}
		} else {
			// If bumped into something try falling
			a.Dir = FALLING
		}
	}

	// If at the edige of the playfield stop and exit
	if (a.Dir == LEFT && a.X == 0) ||
		(a.Dir == RIGHT && a.X >= 78) {
		a.Dir = STOPPED
	}

	// If at a ladder and want to go up
	if (a.DirRequest == UP && m.Field[a.Y][a.X] == 'H') ||
		(a.DirRequest == DOWN && m.Field[a.Y][a.X] == 'H') {
		a.Dir = a.DirRequest
		a.DirRequest = STOPPED
	}

	// If falling then continue doing that until not in free space anymore,
	// then continue the previous direction (if any)
	if a.Dir == FALLING {
		if m.Field[a.Y+1][a.X] == ' ' {
			a.Y++
			return a
		}
		a.Dir = a.DirRequest
	}

	// Climb up until ladder is no more
	if a.Dir == UP {
		if m.Field[a.Y-1][a.X] == 'H' {
			a.Y--
		} else {
			a.Dir = STOPPED
		}
	}

	// Climb down until ladder is no more
	if a.Dir == DOWN {
		if m.Field[a.Y+1][a.X] == 'H' {
			a.Y++
		} else {
			a.Dir = STOPPED
		}
	}

	if a.Dir == LEFT && (m.Field[a.Y][a.X] == ' ' || m.Field[a.Y][a.X] == 'H' || m.Field[a.Y][a.X] == '*') {
		// Stepped out into the void?, the start falling, but remember the previous direction
		if m.Field[a.Y+1][a.X] == ' ' {
			a.DirRequest = a.Dir
			a.Dir = FALLING
			goto loopAgain
		}
		a.X--
	}

	if a.Dir == RIGHT && (m.Field[a.Y][a.X] == ' ' || m.Field[a.Y][a.X] == 'H' || m.Field[a.Y][a.X] == '*') {
		// Stepped out into the void?, the start falling, but remember the previous direction
		if m.Field[a.Y+1][a.X] == ' ' {
			a.DirRequest = a.Dir
			a.Dir = FALLING
			goto loopAgain
		}
		a.X++
	}

	return a
}
<commit_msg>Fixed playfield edge detector. Fixes #1<commit_after>package main

//go:generate stringer -type=Action

// The Actor struct holds info about an actor I.E the Lad or a Rock
type Actor struct {
	Type       int
	Y          int
	X          int
	Ch         byte
	Dir        Action
	DirRequest Action
	JumpStep   int
}

type Action int

// The Action constans define what the Actor currently is, or is requested to be, doing
const (
	STOPPED Action = iota
	UP
	UPRIGHT
	RIGHT
	DOWNRIGHT
	DOWN
	DOWNLEFT
	LEFT
	UPLEFT
	FALLING
	JUMP // Generic jump set by keyhandler
	JUMPRIGHT
	JUMPUP
	JUMPLEFT
)

var jumpLeft = []Action{UPLEFT, UPLEFT, LEFT, LEFT, DOWNLEFT, DOWNLEFT}
var jumpRight = []Action{UPRIGHT, UPRIGHT, RIGHT, RIGHT, DOWNRIGHT, DOWNRIGHT}
var jumpUp = []Action{UP, UP, STOPPED, DOWN, DOWN}

var jumpPaths = map[Action][]Action{
	JUMPUP:    jumpUp,
	JUMPLEFT:  jumpLeft,
	JUMPRIGHT: jumpRight,
}

var dirs = map[Action]struct {
	x, y int
}{
	STOPPED:   {0, 0},
	UP:        {0, -1},
	UPRIGHT:   {1, -1},
	RIGHT:     {1, 0},
	DOWNRIGHT: {1, 1},
	DOWN:      {0, 1},
	DOWNLEFT:  {-1, 1},
	LEFT:      {-1, 0},
	UPLEFT:    {-1, -1},
	FALLING:   {0, 1},
	JUMP:      {0, 0},
	JUMPRIGHT: {0, 0},
	JUMPLEFT:  {0, 0},
	JUMPUP:    {0, 0},
}

//
// A moving jummp is UR/UR/R/R/DR/DR
// or                UL/UL/L/L/DL/DL
// A standing jump is U/U/-/D/D
//
// 	 ====================
//   ----234-----23------
//   ---1---5----14------
//   --0-----6---05------
//   ====================
//

//
//
//
func MoveActor(a Actor, m MapData) Actor {

loopAgain: // If just started falling we need to retest all conditions

	// If stopped or going left or going right and requst to do something else, then try to do it
	if (a.Dir == STOPPED && a.DirRequest == LEFT) ||
		(a.Dir == STOPPED && a.DirRequest == RIGHT) ||
		(a.Dir == LEFT && a.DirRequest == RIGHT) ||
		(a.Dir == RIGHT && a.DirRequest == LEFT) {
		a.Dir = a.DirRequest
		a.DirRequest = STOPPED

	}

	// Handle starting of jumps
	if a.DirRequest == JUMP {
		switch a.Dir {
		case STOPPED:
			a.DirRequest = a.Dir
			a.Dir = JUMPUP
			a.JumpStep = 0
		case LEFT:
			a.DirRequest = a.Dir
			a.Dir = JUMPLEFT
			a.JumpStep = 0
		case RIGHT:
			a.DirRequest = a.Dir
			a.Dir = JUMPRIGHT
			a.JumpStep = 0
		}
	}

	// Do the jumping
	if a.Dir == JUMPUP || a.Dir == JUMPLEFT || a.Dir == JUMPRIGHT {
		jd := jumpPaths[a.Dir][a.JumpStep]
		if m.Field[a.Y+dirs[jd].y][a.X+dirs[jd].x] == ' ' {
			a.X += dirs[jd].x
			a.Y += dirs[jd].y
			a.JumpStep++
			if a.JumpStep >= len(jumpPaths[a.Dir]) {
				a.Dir = a.DirRequest
			}
		} else {
			// If bumped into something try falling
			a.Dir = FALLING
		}
	}

	// Don't allow player to end up outside of the playfeild
	ClampToPlayfield(&a)

	// If at a ladder and want to go up
	if (a.DirRequest == UP && m.Field[a.Y][a.X] == 'H') ||
		(a.DirRequest == DOWN && m.Field[a.Y][a.X] == 'H') {
		a.Dir = a.DirRequest
		a.DirRequest = STOPPED
	}

	// If falling then continue doing that until not in free space anymore,
	// then continue the previous direction (if any)
	if a.Dir == FALLING {
		if m.Field[a.Y+1][a.X] == ' ' {
			a.Y++
			return a
		}
		a.Dir = a.DirRequest
	}

	// Climb up until ladder is no more
	if a.Dir == UP {
		if m.Field[a.Y-1][a.X] == 'H' {
			a.Y--
		} else {
			a.Dir = STOPPED
		}
	}

	// Climb down until ladder is no more
	if a.Dir == DOWN {
		if m.Field[a.Y+1][a.X] == 'H' {
			a.Y++
		} else {
			a.Dir = STOPPED
		}
	}

	if a.Dir == LEFT && (m.Field[a.Y][a.X] == ' ' || m.Field[a.Y][a.X] == 'H' || m.Field[a.Y][a.X] == '*') {
		// Stepped out into the void?, the start falling, but remember the previous direction
		if m.Field[a.Y+1][a.X] == ' ' {
			a.DirRequest = a.Dir
			a.Dir = FALLING
			goto loopAgain
		}
		a.X--
	}

	if a.Dir == RIGHT && (m.Field[a.Y][a.X] == ' ' || m.Field[a.Y][a.X] == 'H' || m.Field[a.Y][a.X] == '*') {
		// Stepped out into the void?, the start falling, but remember the previous direction
		if m.Field[a.Y+1][a.X] == ' ' {
			a.DirRequest = a.Dir
			a.Dir = FALLING
			goto loopAgain
		}
		a.X++
	}

	// Don't allow player to end up outside of the playfeild
	ClampToPlayfield(&a)

	return a
}

//
// If walking or jumping of the playfield edges then set actor mode to FALLING
// and make sure the actor stays inside the playfield
//
func ClampToPlayfield(a *Actor) {
	if a.X <= 0 && (a.Dir == LEFT || a.Dir == JUMPLEFT) {
		a.X = 0
		a.Dir = FALLING
		a.DirRequest = STOPPED
	}

	if a.X >= 78 && (a.Dir == RIGHT || a.Dir == JUMPRIGHT) {
		a.X = 78
		a.Dir = FALLING
		a.DirRequest = STOPPED
	}

}
<|endoftext|>


<commit_before>package slack

import (
	"errors"
	"fmt"
	"net/url"
)

type adminResponse struct {
	OK    bool   `json:"ok"`
	Error string `json:"error"`
}

func adminRequest(method string, teamName string, values url.Values, debug bool) (*adminResponse, error) {
	adminResponse := &adminResponse{}
	err := parseAdminResponse(method, teamName, values, adminResponse, debug)
	if err != nil {
		return nil, err
	}

	if !adminResponse.OK {
		return nil, errors.New(adminResponse.Error)
	}

	return adminResponse, nil
}

// DisableUser disables a user account, given a user ID
func (api *Slack) DisableUser(teamName string, uid string) error {
	values := url.Values{
		"user":       {uid},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setInactive", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to disable user with id '%s': %s", uid, err)
	}

	return nil
}

// InviteGuest invites a user to Slack as a single-channel guest
func (api *Slack) InviteGuest(
	teamName string,
	channel string,
	firstName string,
	lastName string,
	emailAddress string,
) error {
	values := url.Values{
		"email":            {emailAddress},
		"channels":         {channel},
		"first_name":       {firstName},
		"last_name":        {lastName},
		"ultra_restricted": {"1"},
		"token":            {api.config.token},
		"set_active":       {"true"},
		"_attempts":        {"1"},
	}

	_, err := adminRequest("invite", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to invite single-channel guest: %s", err)
	}

	return nil
}

// InviteRestricted invites a user to Slack as a restricted account
func (api *Slack) InviteRestricted(
	teamName string,
	channel string,
	firstName string,
	lastName string,
	emailAddress string,
) error {
	values := url.Values{
		"email":      {emailAddress},
		"channels":   {channel},
		"first_name": {firstName},
		"last_name":  {lastName},
		"restricted": {"1"},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("invite", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to restricted account: %s", err)
	}

	return nil
}

// SetRegular enables the specified user
func (api *Slack) SetRegular(teamName string, user string) error {
	values := url.Values{
		"user":       {user},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setRegular", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to change the user (%s) to a regular user: %s", user, err)
	}

	return nil
}

// SendSSOBindingEmail sends an SSO binding email to the specified user
func (api *Slack) SendSSOBindingEmail(teamName string, user string) error {
	values := url.Values{
		"user":       {user},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("sendSSOBind", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to send SSO binding email for user (%s): %s", user, err)
	}

	return nil
}

// SetUltraRestricted converts a user into a single-channel guest
func (api *Slack) SetUltraRestricted(
	teamName string,
	uid string,
	channel string,
) error {
	values := url.Values{
		"user":       {uid},
		"channel":    {channel},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setUltraRestricted", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to ultra-restrict account: %s", err)
	}

	return nil
}
<commit_msg>Add SetRestricted<commit_after>package slack

import (
	"errors"
	"fmt"
	"net/url"
)

type adminResponse struct {
	OK    bool   `json:"ok"`
	Error string `json:"error"`
}

func adminRequest(method string, teamName string, values url.Values, debug bool) (*adminResponse, error) {
	adminResponse := &adminResponse{}
	err := parseAdminResponse(method, teamName, values, adminResponse, debug)
	if err != nil {
		return nil, err
	}

	if !adminResponse.OK {
		return nil, errors.New(adminResponse.Error)
	}

	return adminResponse, nil
}

// DisableUser disables a user account, given a user ID
func (api *Slack) DisableUser(teamName string, uid string) error {
	values := url.Values{
		"user":       {uid},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setInactive", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to disable user with id '%s': %s", uid, err)
	}

	return nil
}

// InviteGuest invites a user to Slack as a single-channel guest
func (api *Slack) InviteGuest(
	teamName string,
	channel string,
	firstName string,
	lastName string,
	emailAddress string,
) error {
	values := url.Values{
		"email":            {emailAddress},
		"channels":         {channel},
		"first_name":       {firstName},
		"last_name":        {lastName},
		"ultra_restricted": {"1"},
		"token":            {api.config.token},
		"set_active":       {"true"},
		"_attempts":        {"1"},
	}

	_, err := adminRequest("invite", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to invite single-channel guest: %s", err)
	}

	return nil
}

// InviteRestricted invites a user to Slack as a restricted account
func (api *Slack) InviteRestricted(
	teamName string,
	channel string,
	firstName string,
	lastName string,
	emailAddress string,
) error {
	values := url.Values{
		"email":      {emailAddress},
		"channels":   {channel},
		"first_name": {firstName},
		"last_name":  {lastName},
		"restricted": {"1"},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("invite", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to restricted account: %s", err)
	}

	return nil
}

// SetRegular enables the specified user
func (api *Slack) SetRegular(teamName string, user string) error {
	values := url.Values{
		"user":       {user},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setRegular", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to change the user (%s) to a regular user: %s", user, err)
	}

	return nil
}

// SendSSOBindingEmail sends an SSO binding email to the specified user
func (api *Slack) SendSSOBindingEmail(teamName string, user string) error {
	values := url.Values{
		"user":       {user},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("sendSSOBind", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to send SSO binding email for user (%s): %s", user, err)
	}

	return nil
}

// SetUltraRestricted converts a user into a single-channel guest
func (api *Slack) SetUltraRestricted(
	teamName string,
	uid string,
	channel string,
) error {
	values := url.Values{
		"user":       {uid},
		"channel":    {channel},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setUltraRestricted", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to ultra-restrict account: %s", err)
	}

	return nil
}

// SetRestricted converts a user into a restricted account
func (api *Slack) SetRestricted(
	teamName string,
	uid string,
) error {
	values := url.Values{
		"user":       {uid},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setRestricted", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to restrict account: %s", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package value

import (
	"errors"
	"fmt"
	"html/template"
	"net/http"
	"time"

	"appengine"
	"appengine/datastore"
	"appengine/memcache"
	"appengine/user"
)

func init() {
	http.HandleFunc("/_ah/value/admin", adminHandler)
	http.HandleFunc("/_ah/value/update", updateHandler)
}

var adminTmpl = template.Must(template.New("admin").Parse(`

Admin

{{range $key, $val := .}}
  <form action="/_ah/value/update" method="POST">

    <input type="hidden" name="delete_key" value="{{$key}}"></input>
    {{$key}}
    {{$val}}
    <input type="submit" value="Delete"></input>

  </form>
{{else}}

no values currently configured

{{end}}
<form action="/_ah/value/update" method="POST">

  <input type="text" name="key"></input>
  <input type="text" name="val"></input>
  <input type="submit" value="Add"></input>

</form>

`))

func adminHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	if !user.IsAdmin(c) {
		if user.Current(c) == nil {
			loginURL, _ := user.LoginURL(c, "/_ah/value/admin")
			fmt.Fprintf(w, "Log in", loginURL)
		} else {
			http.Error(w, "Forbidden", http.StatusForbidden)
		}
		return
	}
	if r.Method != "GET" {
		return
	}
	v := map[string]string{}
	q := datastore.NewQuery(Kind)
	for t := q.Run(c); ; {
		var e e
		k, err := t.Next(&e)
		if err == datastore.Done {
			break
		} else if err != nil {
			c.Errorf("%v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		v[k.StringID()] = e.Value
	}
	if err := adminTmpl.Execute(w, v); err != nil {
		c.Warningf("error executing template: %v", err)
	}
}

func updateHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Redirect(w, r, "/_ah/value/admin", http.StatusSeeOther)
		return
	}
	c := appengine.NewContext(r)
	if !user.IsAdmin(c) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	deleteKey := r.FormValue("delete_key")
	if deleteKey != "" {
		if err := memcache.Delete(c, deleteKey); err != nil && err != memcache.ErrCacheMiss {
			c.Errorf("error deleting %q from memcache: %v", deleteKey, err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		k := datastore.NewKey(c, Kind, deleteKey, 0, nil)
		if err := datastore.Delete(c, k); err != nil {
			c.Errorf("error deleting %q from datastore: %v", deleteKey, err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	} else {
		key := r.FormValue("key")
		val := r.FormValue("val")
		if err := set(c, key, val); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
	// TODO: remove this hack.
	time.Sleep(time.Millisecond * 500)
	http.Redirect(w, r, "/_ah/value/admin", http.StatusSeeOther)
}

func set(c appengine.Context, key string, val string) error {
	if _, err := memcache.Get(c, key); err != memcache.ErrCacheMiss {
		return errors.New("key found in memcache")
	}
	return datastore.RunInTransaction(c, func(tc appengine.Context) error {
		// Fail if the value is already stored.
		k := datastore.NewKey(c, Kind, key, 0, nil)
		if err := datastore.Get(tc, k, nil); err == nil {
			return errors.New("key found in datastore")
		} else if err == datastore.ErrNoSuchEntity {
			// Okay, good. Keep going.
		} else if err != nil {
			return err
		}

		// Put the value in the datastore.
		_, err := datastore.Put(tc, k, &e{Value: val})
		return err
	}, nil)
}
<commit_msg>build-tag admin.go<commit_after>// +build appengine

package value

import (
	"errors"
	"fmt"
	"html/template"
	"net/http"
	"time"

	"appengine"
	"appengine/datastore"
	"appengine/memcache"
	"appengine/user"
)

func init() {
	http.HandleFunc("/_ah/value/admin", adminHandler)
	http.HandleFunc("/_ah/value/update", updateHandler)
}

var adminTmpl = template.Must(template.New("admin").Parse(`

Admin

{{range $key, $val := .}}
  <form action="/_ah/value/update" method="POST">

    <input type="hidden" name="delete_key" value="{{$key}}"></input>
    {{$key}}
    {{$val}}
    <input type="submit" value="Delete"></input>

  </form>
{{else}}

no values currently configured

{{end}}
<form action="/_ah/value/update" method="POST">

  <input type="text" name="key"></input>
  <input type="text" name="val"></input>
  <input type="submit" value="Add"></input>

</form>

`))

func adminHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	if !user.IsAdmin(c) {
		if user.Current(c) == nil {
			loginURL, _ := user.LoginURL(c, "/_ah/value/admin")
			fmt.Fprintf(w, "Log in", loginURL)
		} else {
			http.Error(w, "Forbidden", http.StatusForbidden)
		}
		return
	}
	if r.Method != "GET" {
		return
	}
	v := map[string]string{}
	q := datastore.NewQuery(Kind)
	for t := q.Run(c); ; {
		var e e
		k, err := t.Next(&e)
		if err == datastore.Done {
			break
		} else if err != nil {
			c.Errorf("%v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		v[k.StringID()] = e.Value
	}
	if err := adminTmpl.Execute(w, v); err != nil {
		c.Warningf("error executing template: %v", err)
	}
}

func updateHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Redirect(w, r, "/_ah/value/admin", http.StatusSeeOther)
		return
	}
	c := appengine.NewContext(r)
	if !user.IsAdmin(c) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	deleteKey := r.FormValue("delete_key")
	if deleteKey != "" {
		if err := memcache.Delete(c, deleteKey); err != nil && err != memcache.ErrCacheMiss {
			c.Errorf("error deleting %q from memcache: %v", deleteKey, err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		k := datastore.NewKey(c, Kind, deleteKey, 0, nil)
		if err := datastore.Delete(c, k); err != nil {
			c.Errorf("error deleting %q from datastore: %v", deleteKey, err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	} else {
		key := r.FormValue("key")
		val := r.FormValue("val")
		if err := set(c, key, val); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
	// TODO: remove this hack.
	time.Sleep(time.Millisecond * 500)
	http.Redirect(w, r, "/_ah/value/admin", http.StatusSeeOther)
}

func set(c appengine.Context, key string, val string) error {
	if _, err := memcache.Get(c, key); err != memcache.ErrCacheMiss {
		return errors.New("key found in memcache")
	}
	return datastore.RunInTransaction(c, func(tc appengine.Context) error {
		// Fail if the value is already stored.
		k := datastore.NewKey(c, Kind, key, 0, nil)
		if err := datastore.Get(tc, k, nil); err == nil {
			return errors.New("key found in datastore")
		} else if err == datastore.ErrNoSuchEntity {
			// Okay, good. Keep going.
		} else if err != nil {
			return err
		}

		// Put the value in the datastore.
		_, err := datastore.Put(tc, k, &e{Value: val})
		return err
	}, nil)
}
<|endoftext|>


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

package cloudinary

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
)

const (
	baseAdminUrl = "https://api.cloudinary.com/v1_1"
)

const (
	pathListAllImages = "/resources/image"
	pathListAllRaws   = "/resources/raw"
)

const (
	maxResults = 256
)

func (s *Service) dropAllResources(rtype ResourceType, w io.Writer) error {
	qs := url.Values{
		"max_results": []string{strconv.FormatInt(maxResults, 10)},
	}
	path := pathListAllImages
	if rtype == RawType {
		path = pathListAllRaws
	}
	for {
		resp, err := http.Get(fmt.Sprintf("%s%s?%s", s.adminURI, path, qs.Encode()))
		m, err := handleHttpResponse(resp)
		if err != nil {
			return err
		}
		for _, v := range m["resources"].([]interface{}) {
			publicId := v.(map[string]interface{})["public_id"].(string)
			if w != nil {
				fmt.Fprintf(w, "Deleting %s ... ", publicId)
			}
			if err := s.Delete(publicId, "", rtype); err != nil {
				// Do not return. Report the error but continue through the list.
				fmt.Fprintf(w, "Error: %s: %s\n", publicId, err.Error())
			}
		}
		if e, ok := m["next_cursor"]; ok {
			qs.Set("next_cursor", e.(string))
		} else {
			break
		}
	}

	return nil
}

// DropAllImages deletes all remote images from Cloudinary. File names are
// written to io.Writer if available.
func (s *Service) DropAllImages(w io.Writer) error {
	return s.dropAllResources(ImageType, w)
}

// DropAllRaws deletes all remote raw files from Cloudinary. File names are
// written to io.Writer if available.
func (s *Service) DropAllRaws(w io.Writer) error {
	return s.dropAllResources(RawType, w)
}

// DropAll deletes all remote resources (both images and raw files) from Cloudinary.
// File names are written to io.Writer if available.
func (s *Service) DropAll(w io.Writer) error {
	if err := s.DropAllImages(w); err != nil {
		return err
	}
	if err := s.DropAllRaws(w); err != nil {
		return err
	}
	return nil
}

func (s *Service) doGetResources(rtype ResourceType) ([]*Resource, error) {
	qs := url.Values{
		"max_results": []string{strconv.FormatInt(maxResults, 10)},
	}
	path := pathListAllImages
	if rtype == RawType {
		path = pathListAllRaws
	}
	allres := make([]*Resource, 0)
	for {
		resp, err := http.Get(fmt.Sprintf("%s%s?%s", s.adminURI, path, qs.Encode()))
		if err != nil {
			return nil, err
		}

		rs := new(resourceList)
		dec := json.NewDecoder(resp.Body)
		if err := dec.Decode(rs); err != nil {
			return nil, err
		}
		for _, res := range rs.Resources {
			allres = append(allres, res)
		}
		if rs.NextCursor > 0 {
			qs.Set("next_cursor", strconv.FormatInt(rs.NextCursor, 10))
		} else {
			break
		}
	}
	return allres, nil
}

// Resources returns a list of all uploaded resources. They can be
// images or raw files, depending on the resource type passed in rtype.
// Cloudinary can return a limited set of results. Pagination is supported,
// so the full set of results is returned.
func (s *Service) Resources(rtype ResourceType) ([]*Resource, error) {
	return s.doGetResources(rtype)
}
<commit_msg>Push maxResults to 2048 (admin search)<commit_after>// Copyright 2013 Mathias Monnerville and Anthony Baillard.
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cloudinary

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
)

const (
	baseAdminUrl = "https://api.cloudinary.com/v1_1"
)

const (
	pathListAllImages = "/resources/image"
	pathListAllRaws   = "/resources/raw"
)

const (
	maxResults = 2048
)

func (s *Service) dropAllResources(rtype ResourceType, w io.Writer) error {
	qs := url.Values{
		"max_results": []string{strconv.FormatInt(maxResults, 10)},
	}
	path := pathListAllImages
	if rtype == RawType {
		path = pathListAllRaws
	}
	for {
		resp, err := http.Get(fmt.Sprintf("%s%s?%s", s.adminURI, path, qs.Encode()))
		m, err := handleHttpResponse(resp)
		if err != nil {
			return err
		}
		for _, v := range m["resources"].([]interface{}) {
			publicId := v.(map[string]interface{})["public_id"].(string)
			if w != nil {
				fmt.Fprintf(w, "Deleting %s ... ", publicId)
			}
			if err := s.Delete(publicId, "", rtype); err != nil {
				// Do not return. Report the error but continue through the list.
				fmt.Fprintf(w, "Error: %s: %s\n", publicId, err.Error())
			}
		}
		if e, ok := m["next_cursor"]; ok {
			qs.Set("next_cursor", e.(string))
		} else {
			break
		}
	}

	return nil
}

// DropAllImages deletes all remote images from Cloudinary. File names are
// written to io.Writer if available.
func (s *Service) DropAllImages(w io.Writer) error {
	return s.dropAllResources(ImageType, w)
}

// DropAllRaws deletes all remote raw files from Cloudinary. File names are
// written to io.Writer if available.
func (s *Service) DropAllRaws(w io.Writer) error {
	return s.dropAllResources(RawType, w)
}

// DropAll deletes all remote resources (both images and raw files) from Cloudinary.
// File names are written to io.Writer if available.
func (s *Service) DropAll(w io.Writer) error {
	if err := s.DropAllImages(w); err != nil {
		return err
	}
	if err := s.DropAllRaws(w); err != nil {
		return err
	}
	return nil
}

func (s *Service) doGetResources(rtype ResourceType) ([]*Resource, error) {
	qs := url.Values{
		"max_results": []string{strconv.FormatInt(maxResults, 10)},
	}
	path := pathListAllImages
	if rtype == RawType {
		path = pathListAllRaws
	}
	allres := make([]*Resource, 0)
	for {
		resp, err := http.Get(fmt.Sprintf("%s%s?%s", s.adminURI, path, qs.Encode()))
		if err != nil {
			return nil, err
		}

		rs := new(resourceList)
		dec := json.NewDecoder(resp.Body)
		if err := dec.Decode(rs); err != nil {
			return nil, err
		}
		for _, res := range rs.Resources {
			allres = append(allres, res)
		}
		if rs.NextCursor > 0 {
			qs.Set("next_cursor", strconv.FormatInt(rs.NextCursor, 10))
		} else {
			break
		}
	}
	return allres, nil
}

// Resources returns a list of all uploaded resources. They can be
// images or raw files, depending on the resource type passed in rtype.
// Cloudinary can return a limited set of results. Pagination is supported,
// so the full set of results is returned.
func (s *Service) Resources(rtype ResourceType) ([]*Resource, error) {
	return s.doGetResources(rtype)
}
<|endoftext|>


<commit_before>package main

import (
	aguin_api "aguin/api"
	"aguin/config"
	"flag"
	"fmt"
	"github.com/go-martini/martini"
	"github.com/martini-contrib/render"
	"net/http"
	"aguin/utils"
)

func main() {
	var (
		host string
		port int
	)
	log := utils.GetLogger("system")
	flag.StringVar(&host, "h", "", "Host to listen on")
	flag.IntVar(&port, "p", 0, "Port number to listen on")

	flag.Parse()
	config.ReadConfig("./config")
	api := martini.Classic()
	api.Use(render.Renderer())
	api.Use(aguin_api.VerifyRequest())
	api.Get("/", aguin_api.IndexGet)
	api.Post("/", aguin_api.IndexPost)
	api.Get("/status", aguin_api.IndexStatus)
	api.NotFound(aguin_api.NotFound)
	serverConfig := config.ServerConf()
	if port != 0 {
		serverConfig.Port = port
	}
	if host != "" {
		serverConfig.Host = host
	}
	log.Print(fmt.Sprintf("listening to address %s:%d", serverConfig.Host, serverConfig.Port))
	http.ListenAndServe(fmt.Sprintf("%s:%d", serverConfig.Host, serverConfig.Port), api)
}
<commit_msg>Make the port larger then zero<commit_after>package main

import (
	aguin_api "aguin/api"
	"aguin/config"
	"flag"
	"fmt"
	"github.com/go-martini/martini"
	"github.com/martini-contrib/render"
	"net/http"
	"aguin/utils"
)

func main() {
	var (
		host string
		port int
	)
	log := utils.GetLogger("system")
	flag.StringVar(&host, "h", "", "Host to listen on")
	flag.IntVar(&port, "p", 0, "Port number to listen on")

	flag.Parse()
	config.ReadConfig("./config")
	api := martini.Classic()
	api.Use(render.Renderer())
	api.Use(aguin_api.VerifyRequest())
	api.Get("/", aguin_api.IndexGet)
	api.Post("/", aguin_api.IndexPost)
	api.Get("/status", aguin_api.IndexStatus)
	api.NotFound(aguin_api.NotFound)
	serverConfig := config.ServerConf()
	if port > 0 {
		serverConfig.Port = port
	}
	if host != "" {
		serverConfig.Host = host
	}
	log.Print(fmt.Sprintf("listening to address %s:%d", serverConfig.Host, serverConfig.Port))
	http.ListenAndServe(fmt.Sprintf("%s:%d", serverConfig.Host, serverConfig.Port), api)
}
<|endoftext|>


<commit_before>package align

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"strings"

	"github.com/mattn/go-runewidth"
)

// Justification is used to set the alignment of the column
// contents itself along the right, left, or center.
type Justification byte

// Left, Right or Center Justification options.
const (
	JustifyRight Justification = iota + 1
	JustifyCenter
	JustifyLeft
)

// TextQualifier is used to configure the scanner to account for a text qualifier.
type TextQualifier struct {
	On        bool
	Qualifier string
}

// PaddingOpts provides configurability for left/center/right Justification and padding length.
type PaddingOpts struct {
	Justification  Justification
	ColumnOverride map[int]Justification //override the Justification of specified columns
	Pad            int                   // padding surrounding the separator
}

// Grower grows by the given number of bytes n.
// Reset will set the Grower to 0.
type Grower interface {
	Grow(n int)
	Reset()
}

// Padder builds a string and can return its string value.
type Padder interface {
	io.Writer
	fmt.Stringer
	WriteByte(c byte) error
	WriteString(s string) (int, error)
	Bytes() []byte
}

// PadGrower makes a string with the ability to
// grow the underlying buffer.
type PadGrower interface {
	Grower
	Padder
}

// fieldPad ructs the contents of a field
// with padding.
type fieldPad struct {
	bytes.Buffer
}

// Align scans input and writes output with aligned text.
type Align struct {
	scanner      *bufio.Scanner
	writer       *bufio.Writer
	sep          string // separator string or delimiter
	sepOut       string
	columnCounts map[int]int
	txtq         TextQualifier
	padOpts      PaddingOpts
	filter       []int
	filterLen    int
	lines        []string
	padder       PadGrower
}

// NewAlign creates and initializes a ScanWriter with in and out as its initial Reader and Writer
// and sets del to the desired delimiter to be used for alignment.
// It is meant to read the contents of its io.Reader to determine the length of each field
// and output the results in an aligned format.
// Left Justification is used by default.  See UpdatePadding to set the Justification.
func NewAlign(in io.Reader, out io.Writer, sep string, qu TextQualifier) *Align {
	return &Align{
		scanner:      bufio.NewScanner(in),
		writer:       bufio.NewWriter(out),
		sep:          sep,
		sepOut:       sep,
		columnCounts: make(map[int]int),
		txtq:         qu,
		padOpts: PaddingOpts{
			//defaults
			Justification: JustifyLeft,
			Pad:           1,
		},
		padder: &fieldPad{}, // default; set with UpdatePadder()
	}
}

// OutputSep sets the output separator string with outsep if a different value from the input sep is desired.
func (a *Align) OutputSep(outsep string) {
	a.sepOut = outsep
}

// Align determines the length of each field of text around the configured delimiter and aligns all of the
// text by the delimiter.
func (a *Align) Align() {
	a.columnLength()
	a.export()
}

// columnSize looks up the Align's columnCounts key with num and returns the value
// that was set by ColumnCounts().
// If num is not a valid key in Align.columnCounts, then -1 is returned.
func (a *Align) columnSize(num int) int {
	if _, ok := a.columnCounts[num]; !ok {
		return -1
	}
	return a.columnCounts[num]
}

// UpdatePadding uses PaddingOpts p to update the Align's padding options.
func (a *Align) UpdatePadding(p PaddingOpts) {
	a.padOpts = p
}

// UpdatePadder sets the Align's padder implementation if a different
// one is desired from the default.
func (a *Align) UpdatePadder(padder PadGrower) {
	a.padder = padder
}

// fieldLen works in a similar manner to the standard lib function strings.Index().
// Instead of returning the index of the first instance of sep, it returns the length
// of s before the first index of sep.
func fieldLen(s, sep string) int {
	return genFieldLen(s, sep, "")
}

// fieldLenEscaped works in the same way as FieldLen, but a text qualifer string can
// be provided.  If qual is an empty string, then the behavior will be exactly the same
// as FieldLen.
func fieldLenEscaped(s, sep, qual string) int {
	return genFieldLen(s, sep, qual)
}

func genFieldLen(s, sep, qual string) int {
	i := 0
	if qual == "" || !strings.HasPrefix(s, qual) {
		i = strings.Index(s, sep)
	} else {
		i = strings.Index(s, qual+sep)

		if i == -1 {
			return len(s)
		}
		return len(s[:i+len(qual)])
	}

	if i == -1 {
		return len(s)
	}

	return len(s[:i])
}

// columnLength scans the input and determines the maximum length of each field based on
// the longest value for each field in all of the pertaining lines.
// All of the lines of the io.Reader are returned as a string slice.
func (a *Align) columnLength() {
	a.lines = make([]string, 0)

	for a.scanner.Scan() {
		var columnNum int
		var temp int

		line := a.scanner.Text()

		if a.txtq.On {
			for start := 0; start < len(line); {
				temp = fieldLenEscaped(line[start:], a.sep, a.txtq.Qualifier)
				start += temp + len(a.sep)
				if temp > a.columnCounts[columnNum] {
					a.columnCounts[columnNum] = temp
				}
				columnNum++
				temp = 0
			}
		} else {
			for start := 0; start < len(line); {
				temp = fieldLen(line[start:], a.sep)
				start += temp + len(a.sep)
				if temp > a.columnCounts[columnNum] {
					a.columnCounts[columnNum] = temp
				}
				columnNum++
				temp = 0
			}
		}

		a.lines = append(a.lines, line)
	}
}

const padchar byte = ' '

// export will pad each field in lines based on the Align's column counts.
func (a *Align) export() {
	if a.padOpts.Pad < 0 {
		a.padOpts.Pad = 0
	}

	surroundingPad := make([]byte, 0, a.padOpts.Pad)
	for i := 0; i < a.padOpts.Pad; i++ {
		surroundingPad = append(surroundingPad, padchar)
	}

	for _, line := range a.lines {
		words := a.splitWithQual(line, a.sep, a.txtq.Qualifier)

		var columnNum int
		var tempColumn int // used for call to pad() to incorporate column filtering
		for _, word := range words {
			if a.filterLen > 0 {
				if !contains(a.filter, columnNum+1) {
					columnNum++
					if columnNum == len(words) {
						a.writer.WriteString("\n")
					}
					continue
				}
			}

			j := a.padOpts.Justification

			// override Justification for the specified columnNum in the key for the PaddingOpts.columnOverride map
			if len(a.padOpts.ColumnOverride) > 0 {
				for k, v := range a.padOpts.ColumnOverride {
					if k == columnNum+1 {
						j = v
					}
				}
			}

			padLength := countPadding(word, a.columnCounts[columnNum])
			paddedWord := applyPadding(a.padder, word, string(surroundingPad), tempColumn, padLength, j)

			a.padder.Reset() // empty the buffer for the next iteration.

			columnNum++
			tempColumn++

			// Do not add a delimiter to the last field
			// This also properly aligns the output even if there are lines with a different number of fields
			if a.filterLen > 0 && a.filter[a.filterLen-1] == columnNum || columnNum == len(paddedWord) {
				a.writer.Write(paddedWord)
				a.writer.WriteByte('\n')
				break
			}
			a.writer.Write(paddedWord)
			a.writer.WriteString(a.sepOut)
		}
	}
	a.writer.Flush()
}

func fillWithPadding(padder Padder, length int) {
	for i := 0; i < length; i++ {
		padder.WriteByte(padchar)
	}
}

// applyPadding rebuilds word by adding padding appropriately based on the
// desired justification, the overall padding length and the supplied surrounding
// padding string.
func applyPadding(padder Padder, original, surroundingPad string, columnNum, padLength int, just Justification) []byte {
	// add surrounding pad to beginning of column (except for the 1st column)
	if len(surroundingPad) > 0 {
		if columnNum > 0 {
			padder.WriteString(surroundingPad)
		}
	}

	switch just {
	case JustifyLeft:
		padder.WriteString(original)
		fillWithPadding(padder, padLength)
	case JustifyRight:
		fillWithPadding(padder, padLength)
		padder.WriteString(original)
	case JustifyCenter:
		// not much of a point to 'center' justification with such a small padding; default it if <= 2.
		if padLength > 2 {
			fillWithPadding(padder, (padLength - (padLength / 2)))
			padder.WriteString(original)
			fillWithPadding(padder, padLength/2)
		} else {
			padder.WriteString(original)
			fillWithPadding(padder, padLength)
		}
	}

	// add surrounding pad to end of column
	if len(surroundingPad) > 0 {
		padder.WriteString(surroundingPad)
	}
	return padder.Bytes()
}

// determines the length of the padding needed.
func countPadding(s string, count int) int {
	padLength := count - len(s)
	rCount, wordLen := runewidth.StringWidth(s), len(s)
	if rCount < wordLen {
		padLength += wordLen - rCount
	}
	return padLength
}

// prepends padding.
func leadingPad(sb *strings.Builder, padLen int) {
	for i := 0; i < padLen; i++ {
		sb.WriteByte(padchar)
	}
}

// appends padding.
func trailingPad(sb *strings.Builder, padLen int) {
	for i := 0; i < padLen; i++ {
		sb.WriteByte(padchar)
	}
}

// splitWithQual basically works like the standard strings.Split() func, but will consider a text qualifier if set.
func (a *Align) splitWithQual(s, sep, qual string) []string {
	if !a.txtq.On {
		return strings.Split(s, sep) // use standard Split() method if no qualifier is considered
	}
	var words = make([]string, 0, strings.Count(s, sep))

	for start := 0; start < len(s); {
		count := genFieldLen(s[start:], sep, qual)
		words = append(words, s[start:start+count])
		start += count + len(sep)
	}

	return words
}

// FilterColumns sets which column numbers should be output.
func (a *Align) FilterColumns(c []int) {
	a.filter = c
	a.filterLen = len(c)
}

func contains(nums []int, num int) bool {
	for _, v := range nums {
		if v == num {
			return true
		}
	}
	return false
}
<commit_msg>count the right variable -_- (#70)<commit_after>package align

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"strings"

	"github.com/mattn/go-runewidth"
)

// Justification is used to set the alignment of the column
// contents itself along the right, left, or center.
type Justification byte

// Left, Right or Center Justification options.
const (
	JustifyRight Justification = iota + 1
	JustifyCenter
	JustifyLeft
)

// TextQualifier is used to configure the scanner to account for a text qualifier.
type TextQualifier struct {
	On        bool
	Qualifier string
}

// PaddingOpts provides configurability for left/center/right Justification and padding length.
type PaddingOpts struct {
	Justification  Justification
	ColumnOverride map[int]Justification //override the Justification of specified columns
	Pad            int                   // padding surrounding the separator
}

// Grower grows by the given number of bytes n.
// Reset will set the Grower to 0.
type Grower interface {
	Grow(n int)
	Reset()
}

// Padder builds a string and can return its string value.
type Padder interface {
	io.Writer
	fmt.Stringer
	WriteByte(c byte) error
	WriteString(s string) (int, error)
	Bytes() []byte
}

// PadGrower makes a string with the ability to
// grow the underlying buffer.
type PadGrower interface {
	Grower
	Padder
}

// fieldPad ructs the contents of a field
// with padding.
type fieldPad struct {
	bytes.Buffer
}

// Align scans input and writes output with aligned text.
type Align struct {
	scanner      *bufio.Scanner
	writer       *bufio.Writer
	sep          string // separator string or delimiter
	sepOut       string
	columnCounts map[int]int
	txtq         TextQualifier
	padOpts      PaddingOpts
	filter       []int
	filterLen    int
	lines        []string
	padder       PadGrower
}

// NewAlign creates and initializes a ScanWriter with in and out as its initial Reader and Writer
// and sets del to the desired delimiter to be used for alignment.
// It is meant to read the contents of its io.Reader to determine the length of each field
// and output the results in an aligned format.
// Left Justification is used by default.  See UpdatePadding to set the Justification.
func NewAlign(in io.Reader, out io.Writer, sep string, qu TextQualifier) *Align {
	return &Align{
		scanner:      bufio.NewScanner(in),
		writer:       bufio.NewWriter(out),
		sep:          sep,
		sepOut:       sep,
		columnCounts: make(map[int]int),
		txtq:         qu,
		padOpts: PaddingOpts{
			//defaults
			Justification: JustifyLeft,
			Pad:           1,
		},
		padder: &fieldPad{}, // default; set with UpdatePadder()
	}
}

// OutputSep sets the output separator string with outsep if a different value from the input sep is desired.
func (a *Align) OutputSep(outsep string) {
	a.sepOut = outsep
}

// Align determines the length of each field of text around the configured delimiter and aligns all of the
// text by the delimiter.
func (a *Align) Align() {
	a.columnLength()
	a.export()
}

// columnSize looks up the Align's columnCounts key with num and returns the value
// that was set by ColumnCounts().
// If num is not a valid key in Align.columnCounts, then -1 is returned.
func (a *Align) columnSize(num int) int {
	if _, ok := a.columnCounts[num]; !ok {
		return -1
	}
	return a.columnCounts[num]
}

// UpdatePadding uses PaddingOpts p to update the Align's padding options.
func (a *Align) UpdatePadding(p PaddingOpts) {
	a.padOpts = p
}

// UpdatePadder sets the Align's padder implementation if a different
// one is desired from the default.
func (a *Align) UpdatePadder(padder PadGrower) {
	a.padder = padder
}

// fieldLen works in a similar manner to the standard lib function strings.Index().
// Instead of returning the index of the first instance of sep, it returns the length
// of s before the first index of sep.
func fieldLen(s, sep string) int {
	return genFieldLen(s, sep, "")
}

// fieldLenEscaped works in the same way as FieldLen, but a text qualifer string can
// be provided.  If qual is an empty string, then the behavior will be exactly the same
// as FieldLen.
func fieldLenEscaped(s, sep, qual string) int {
	return genFieldLen(s, sep, qual)
}

func genFieldLen(s, sep, qual string) int {
	i := 0
	if qual == "" || !strings.HasPrefix(s, qual) {
		i = strings.Index(s, sep)
	} else {
		i = strings.Index(s, qual+sep)

		if i == -1 {
			return len(s)
		}
		return len(s[:i+len(qual)])
	}

	if i == -1 {
		return len(s)
	}

	return len(s[:i])
}

// columnLength scans the input and determines the maximum length of each field based on
// the longest value for each field in all of the pertaining lines.
// All of the lines of the io.Reader are returned as a string slice.
func (a *Align) columnLength() {
	a.lines = make([]string, 0)

	for a.scanner.Scan() {
		var columnNum int
		var temp int

		line := a.scanner.Text()

		if a.txtq.On {
			for start := 0; start < len(line); {
				temp = fieldLenEscaped(line[start:], a.sep, a.txtq.Qualifier)
				start += temp + len(a.sep)
				if temp > a.columnCounts[columnNum] {
					a.columnCounts[columnNum] = temp
				}
				columnNum++
				temp = 0
			}
		} else {
			for start := 0; start < len(line); {
				temp = fieldLen(line[start:], a.sep)
				start += temp + len(a.sep)
				if temp > a.columnCounts[columnNum] {
					a.columnCounts[columnNum] = temp
				}
				columnNum++
				temp = 0
			}
		}

		a.lines = append(a.lines, line)
	}
}

const padchar byte = ' '

// export will pad each field in lines based on the Align's column counts.
func (a *Align) export() {
	if a.padOpts.Pad < 0 {
		a.padOpts.Pad = 0
	}

	surroundingPad := make([]byte, 0, a.padOpts.Pad)
	for i := 0; i < a.padOpts.Pad; i++ {
		surroundingPad = append(surroundingPad, padchar)
	}

	for _, line := range a.lines {
		words := a.splitWithQual(line, a.sep, a.txtq.Qualifier)

		var columnNum int
		var tempColumn int // used for call to pad() to incorporate column filtering
		for _, word := range words {
			if a.filterLen > 0 {
				if !contains(a.filter, columnNum+1) {
					columnNum++
					if columnNum == len(words) {
						a.writer.WriteString("\n")
					}
					continue
				}
			}

			j := a.padOpts.Justification

			// override Justification for the specified columnNum in the key for the PaddingOpts.columnOverride map
			if len(a.padOpts.ColumnOverride) > 0 {
				for k, v := range a.padOpts.ColumnOverride {
					if k == columnNum+1 {
						j = v
					}
				}
			}

			padLength := countPadding(word, a.columnCounts[columnNum])
			paddedWord := applyPadding(a.padder, word, string(surroundingPad), tempColumn, padLength, j)

			a.padder.Reset() // empty the buffer for the next iteration.

			columnNum++
			tempColumn++

			// Do not add a delimiter to the last field
			// This also properly aligns the output even if there are lines with a different number of fields
			if a.filterLen > 0 && a.filter[a.filterLen-1] == columnNum || columnNum == len(words) {
				a.writer.Write(paddedWord)
				a.writer.WriteByte('\n')
				break
			}
			a.writer.Write(paddedWord)
			a.writer.WriteString(a.sepOut)
		}
	}
	a.writer.Flush()
}

func fillWithPadding(padder Padder, length int) {
	for i := 0; i < length; i++ {
		padder.WriteByte(padchar)
	}
}

// applyPadding rebuilds word by adding padding appropriately based on the
// desired justification, the overall padding length and the supplied surrounding
// padding string.
func applyPadding(padder Padder, original, surroundingPad string, columnNum, padLength int, just Justification) []byte {
	// add surrounding pad to beginning of column (except for the 1st column)
	if len(surroundingPad) > 0 {
		if columnNum > 0 {
			padder.WriteString(surroundingPad)
		}
	}

	switch just {
	case JustifyLeft:
		padder.WriteString(original)
		fillWithPadding(padder, padLength)
	case JustifyRight:
		fillWithPadding(padder, padLength)
		padder.WriteString(original)
	case JustifyCenter:
		// not much of a point to 'center' justification with such a small padding; default it if <= 2.
		if padLength > 2 {
			fillWithPadding(padder, (padLength - (padLength / 2)))
			padder.WriteString(original)
			fillWithPadding(padder, padLength/2)
		} else {
			padder.WriteString(original)
			fillWithPadding(padder, padLength)
		}
	}

	// add surrounding pad to end of column
	if len(surroundingPad) > 0 {
		padder.WriteString(surroundingPad)
	}
	return padder.Bytes()
}

// determines the length of the padding needed.
func countPadding(s string, count int) int {
	padLength := count - len(s)
	rCount, wordLen := runewidth.StringWidth(s), len(s)
	if rCount < wordLen {
		padLength += wordLen - rCount
	}
	return padLength
}

// prepends padding.
func leadingPad(sb *strings.Builder, padLen int) {
	for i := 0; i < padLen; i++ {
		sb.WriteByte(padchar)
	}
}

// appends padding.
func trailingPad(sb *strings.Builder, padLen int) {
	for i := 0; i < padLen; i++ {
		sb.WriteByte(padchar)
	}
}

// splitWithQual basically works like the standard strings.Split() func, but will consider a text qualifier if set.
func (a *Align) splitWithQual(s, sep, qual string) []string {
	if !a.txtq.On {
		return strings.Split(s, sep) // use standard Split() method if no qualifier is considered
	}
	var words = make([]string, 0, strings.Count(s, sep))

	for start := 0; start < len(s); {
		count := genFieldLen(s[start:], sep, qual)
		words = append(words, s[start:start+count])
		start += count + len(sep)
	}

	return words
}

// FilterColumns sets which column numbers should be output.
func (a *Align) FilterColumns(c []int) {
	a.filter = c
	a.filterLen = len(c)
}

func contains(nums []int, num int) bool {
	for _, v := range nums {
		if v == num {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package vault

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
	"github.com/hashicorp/vault/api"
)

func Provider() terraform.ResourceProvider {
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"address": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_ADDR", nil),
				Description: "URL of the root of the target Vault server.",
			},
			"token": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_TOKEN", ""),
				Description: "Token to use to authenticate to Vault.",
			},
			"ca_cert_file": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_CACERT", ""),
				Description: "Path to a CA certificate file to validate the server's certificate.",
			},
			"ca_cert_dir": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_CAPATH", ""),
				Description: "Path to directory containing CA certificate files to validate the server's certificate.",
			},
			"client_auth": &schema.Schema{
				Type:        schema.TypeList,
				Optional:    true,
				Description: "Client authentication credentials.",
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"cert_file": &schema.Schema{
							Type:        schema.TypeString,
							Required:    true,
							DefaultFunc: schema.EnvDefaultFunc("VAULT_CLIENT_CERT", ""),
							Description: "Path to a file containing the client certificate.",
						},
						"key_file": &schema.Schema{
							Type:        schema.TypeString,
							Required:    true,
							DefaultFunc: schema.EnvDefaultFunc("VAULT_CLIENT_KEY", ""),
							Description: "Path to a file containing the private key that the certificate was issued for.",
						},
					},
				},
			},
			"skip_tls_verify": &schema.Schema{
				Type:        schema.TypeBool,
				Optional:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_SKIP_VERIFY", ""),
				Description: "Set this to true only if the target Vault server is an insecure development instance.",
			},
			"max_lease_ttl_seconds": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,

				// Default is 20min, which is intended to be enough time for
				// a reasonable Terraform run can complete but not
				// significantly longer, so that any leases are revoked shortly
				// after Terraform has finished running.
				DefaultFunc: schema.EnvDefaultFunc("TERRAFORM_VAULT_MAX_TTL", 1200),

				Description: "Maximum TTL for secret leases requested by this provider",
			},
		},

		ConfigureFunc: providerConfigure,

		DataSourcesMap: map[string]*schema.Resource{
			"vault_generic_secret": genericSecretDataSource(),
		},

		ResourcesMap: map[string]*schema.Resource{
			"vault_generic_secret": genericSecretResource(),
		},
	}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
	config := &api.Config{
		Address: d.Get("address").(string),
	}

	clientAuthI := d.Get("client_auth").([]interface{})
	if len(clientAuthI) > 1 {
		return nil, fmt.Errorf("client_auth block may appear only once")
	}

	clientAuthCert := ""
	clientAuthKey := ""
	if len(clientAuthI) == 1 {
		clientAuth := clientAuthI[0].(map[string]interface{})
		clientAuthCert = clientAuth["cert_file"].(string)
		clientAuthKey = clientAuth["key_file"].(string)
	}

	config.ConfigureTLS(&api.TLSConfig{
		CACert:   d.Get("ca_cert_file").(string),
		CAPath:   d.Get("ca_cert_dir").(string),
		Insecure: d.Get("skip_tls_verify").(bool),

		ClientCert: clientAuthCert,
		ClientKey:  clientAuthKey,
	})

	client, err := api.NewClient(config)
	if err != nil {
		return nil, fmt.Errorf("failed to configure Vault API: %s", err)
	}

	token := d.Get("token").(string)
	if token == "" {
		// Use the vault CLI's token, if present.
		tokenFile := fmt.Sprintf("%s/.vault-token", os.Getenv("HOME"))
		tokenBytes, err := ioutil.ReadFile(tokenFile)
		if err != nil {
			return nil, fmt.Errorf("No vault token found: %s", err)
		}

		token = string(tokenBytes)
	}

	// In order to enforce our relatively-short lease TTL, we derive a
	// temporary child token that inherits all of the policies of the
	// token we were given but expires after max_lease_ttl_seconds.
	//
	// The intent here is that Terraform will need to re-fetch any
	// secrets on each run and so we limit the exposure risk of secrets
	// that end up stored in the Terraform state, assuming that they are
	// credentials that Vault is able to revoke.
	//
	// Caution is still required with state files since not all secrets
	// can explicitly be revoked, and this limited scope won't apply to
	// any secrets that are *written* by Terraform to Vault.

	client.SetToken(token)
	renewable := false
	childTokenLease, err := client.Auth().Token().Create(&api.TokenCreateRequest{
		DisplayName:    "terraform",
		TTL:            fmt.Sprintf("%ds", d.Get("max_lease_ttl_seconds").(int)),
		ExplicitMaxTTL: fmt.Sprintf("%ds", d.Get("max_lease_ttl_seconds").(int)),
		Renewable:      &renewable,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to create limited child token: %s", err)
	}

	childToken := childTokenLease.Auth.ClientToken
	policies := childTokenLease.Auth.Policies

	log.Printf("[INFO] Using Vault token with the following policies: %s", strings.Join(policies, ", "))

	client.SetToken(childToken)

	return client, nil
}
<commit_msg>Use go-homedir (as vault does)<commit_after>package vault

import (
	"fmt"
	"io/ioutil"
	"log"
	"strings"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
	"github.com/hashicorp/vault/api"
	"github.com/mitchellh/go-homedir"
)

func Provider() terraform.ResourceProvider {
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"address": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_ADDR", nil),
				Description: "URL of the root of the target Vault server.",
			},
			"token": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_TOKEN", ""),
				Description: "Token to use to authenticate to Vault.",
			},
			"ca_cert_file": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_CACERT", ""),
				Description: "Path to a CA certificate file to validate the server's certificate.",
			},
			"ca_cert_dir": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_CAPATH", ""),
				Description: "Path to directory containing CA certificate files to validate the server's certificate.",
			},
			"client_auth": &schema.Schema{
				Type:        schema.TypeList,
				Optional:    true,
				Description: "Client authentication credentials.",
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"cert_file": &schema.Schema{
							Type:        schema.TypeString,
							Required:    true,
							DefaultFunc: schema.EnvDefaultFunc("VAULT_CLIENT_CERT", ""),
							Description: "Path to a file containing the client certificate.",
						},
						"key_file": &schema.Schema{
							Type:        schema.TypeString,
							Required:    true,
							DefaultFunc: schema.EnvDefaultFunc("VAULT_CLIENT_KEY", ""),
							Description: "Path to a file containing the private key that the certificate was issued for.",
						},
					},
				},
			},
			"skip_tls_verify": &schema.Schema{
				Type:        schema.TypeBool,
				Optional:    true,
				DefaultFunc: schema.EnvDefaultFunc("VAULT_SKIP_VERIFY", ""),
				Description: "Set this to true only if the target Vault server is an insecure development instance.",
			},
			"max_lease_ttl_seconds": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,

				// Default is 20min, which is intended to be enough time for
				// a reasonable Terraform run can complete but not
				// significantly longer, so that any leases are revoked shortly
				// after Terraform has finished running.
				DefaultFunc: schema.EnvDefaultFunc("TERRAFORM_VAULT_MAX_TTL", 1200),

				Description: "Maximum TTL for secret leases requested by this provider",
			},
		},

		ConfigureFunc: providerConfigure,

		DataSourcesMap: map[string]*schema.Resource{
			"vault_generic_secret": genericSecretDataSource(),
		},

		ResourcesMap: map[string]*schema.Resource{
			"vault_generic_secret": genericSecretResource(),
		},
	}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
	config := &api.Config{
		Address: d.Get("address").(string),
	}

	clientAuthI := d.Get("client_auth").([]interface{})
	if len(clientAuthI) > 1 {
		return nil, fmt.Errorf("client_auth block may appear only once")
	}

	clientAuthCert := ""
	clientAuthKey := ""
	if len(clientAuthI) == 1 {
		clientAuth := clientAuthI[0].(map[string]interface{})
		clientAuthCert = clientAuth["cert_file"].(string)
		clientAuthKey = clientAuth["key_file"].(string)
	}

	config.ConfigureTLS(&api.TLSConfig{
		CACert:   d.Get("ca_cert_file").(string),
		CAPath:   d.Get("ca_cert_dir").(string),
		Insecure: d.Get("skip_tls_verify").(bool),

		ClientCert: clientAuthCert,
		ClientKey:  clientAuthKey,
	})

	client, err := api.NewClient(config)
	if err != nil {
		return nil, fmt.Errorf("failed to configure Vault API: %s", err)
	}

	token := d.Get("token").(string)
	if token == "" {
		// Use the vault CLI's token, if present.
		homePath, err := homedir.Dir()
		if err != nil {
			return nil, fmt.Errorf("No vault token found: %s", err)
		}
		tokenBytes, err := ioutil.ReadFile(homePath + "/.vault-token")
		if err != nil {
			return nil, fmt.Errorf("No vault token found: %s", err)
		}

		token = strings.TrimSpace(string(tokenBytes))
	}

	// In order to enforce our relatively-short lease TTL, we derive a
	// temporary child token that inherits all of the policies of the
	// token we were given but expires after max_lease_ttl_seconds.
	//
	// The intent here is that Terraform will need to re-fetch any
	// secrets on each run and so we limit the exposure risk of secrets
	// that end up stored in the Terraform state, assuming that they are
	// credentials that Vault is able to revoke.
	//
	// Caution is still required with state files since not all secrets
	// can explicitly be revoked, and this limited scope won't apply to
	// any secrets that are *written* by Terraform to Vault.

	client.SetToken(token)
	renewable := false
	childTokenLease, err := client.Auth().Token().Create(&api.TokenCreateRequest{
		DisplayName:    "terraform",
		TTL:            fmt.Sprintf("%ds", d.Get("max_lease_ttl_seconds").(int)),
		ExplicitMaxTTL: fmt.Sprintf("%ds", d.Get("max_lease_ttl_seconds").(int)),
		Renewable:      &renewable,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to create limited child token: %s", err)
	}

	childToken := childTokenLease.Auth.ClientToken
	policies := childTokenLease.Auth.Policies

	log.Printf("[INFO] Using Vault token with the following policies: %s", strings.Join(policies, ", "))

	client.SetToken(childToken)

	return client, nil
}
<|endoftext|>


<commit_before>package backend

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/stretchr/testify/assert"
)

type recordingHTTPTransport struct {
	req *http.Request
}

func (t *recordingHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	t.req = req
	return nil, fmt.Errorf("recording HTTP transport impl")
}

func TestAsBool(t *testing.T) {
	for s, b := range map[string]bool{
		"yes":     true,
		"on":      true,
		"1":       true,
		"boo":     true,
		"0":       false,
		"99":      true,
		"a":       true,
		"off":     false,
		"no":      false,
		"fafafaf": true,
		"":        false,
	} {
		assert.Equal(t, b, asBool(s))
	}
}
<commit_msg>test for asBool "true" => true, "false" => false<commit_after>package backend

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/stretchr/testify/assert"
)

type recordingHTTPTransport struct {
	req *http.Request
}

func (t *recordingHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	t.req = req
	return nil, fmt.Errorf("recording HTTP transport impl")
}

func TestAsBool(t *testing.T) {
	for s, b := range map[string]bool{
		"yes":     true,
		"on":      true,
		"1":       true,
		"boo":     true,
		"0":       false,
		"99":      true,
		"a":       true,
		"off":     false,
		"no":      false,
		"fafafaf": true,
		"true":    true,
		"false":   false,
		"":        false,
	} {
		assert.Equal(t, b, asBool(s))
	}
}
<|endoftext|>


<commit_before>package mantle

import (
        "github.com/garyburd/redigo/redis"
        pool "github.com/vireshas/mantle/backends/redis/pool"
        "time"
)

//redis struct
type Redis struct{
        Host string
        Port string
        Capacity int
        pool *pool.RedisPool
}

//set default values
func (r *Redis) SetDefaults(){
        if r.Host == "" { r.Host = "localHost" }
        if r.Port == "" { r.Port = "6379" }
        if r.Capacity == 0 { r.Capacity = 10 }
        r.pool = pool.NewPool( r.Host, r.Port, r.Capacity, r.Capacity, time.Minute )
}

//alias to SetDefaults
func (r *Redis) Configure(){
        r.SetDefaults()
}

//get a client from pool
func (r *Redis) GetClient() (*pool.RedisConn, error){
        return r.pool.GetConn()
}

//put a client back in pool
func (r *Redis) PutClient(c *pool.RedisConn){
        r.pool.PutConn(c)
}

//generic methods to execute any redis call
func (r *Redis) execute(cmd string, args ...interface{}) (interface{}, error){
        client, err := r.GetClient()
        if err != nil {
                return nil, err
        }
        defer r.PutClient(client)
        return client.Do(cmd, args...)
}

//wrapper around redis get
func (r *Redis) Get(key string) string{
        value, err := redis.String(r.execute("GET", key))
        if err != nil { return "Key not found!" }
        return value
}

//wrapper around redis set
func (r *Redis) Set(key string, value interface{}) bool{
        _, redis_err := r.execute("SET", key, value)
        if redis_err != nil { return false }
        return true
}

//wrapper around redis mget
func (r *Redis) MGet(keys ...interface{}) []string{
        values, err := redis.Strings(r.execute("MGET", keys...))
        if err != nil { return []string{} }
        return values
}
/*
func (r *Redis) Get(k_v_map map[interface{}]interface{}) bool{}
func (r *Redis) Expire(keys ...interface{}) bool{}
*/
<commit_msg>cleaning code<commit_after>package mantle

import (
        "github.com/garyburd/redigo/redis"
        pool "github.com/vireshas/mantle/backends/redis/pool"
        "time"
)

//redis struct
type Redis struct {
        Host string
        Port string
        Capacity int
        pool *pool.RedisPool
}

//set default values
func (r *Redis) SetDefaults() {
        if r.Host == "" { r.Host = "localHost" }
        if r.Port == "" { r.Port = "6379" }
        if r.Capacity == 0 { r.Capacity = 10 }
        r.pool = pool.NewPool( r.Host, r.Port, r.Capacity, r.Capacity, time.Minute )
}

//alias to SetDefaults
func (r *Redis) Configure() {
        r.SetDefaults()
}

//get a client from pool
func (r *Redis) GetClient() (*pool.RedisConn, error) {
        return r.pool.GetConn()
}

//put a client back in pool
func (r *Redis) PutClient(c *pool.RedisConn) {
        r.pool.PutConn(c)
}

//generic methods to execute any redis call
func (r *Redis) execute(cmd string, args ...interface{}) (interface{}, error) {
        client, err := r.GetClient()
        if err != nil {
                return nil, err
        }
        defer r.PutClient(client)
        return client.Do(cmd, args...)
}

//wrapper around redis get
func (r *Redis) Get(key string) string {
        value, err := redis.String(r.execute("GET", key))
        if err != nil { return "Key not found!" }
        return value
}

//wrapper around redis set
func (r *Redis) Set(key string, value interface{}) bool {
        _, redis_err := r.execute("SET", key, value)
        if redis_err != nil { return false }
        return true
}

//wrapper around redis mget
func (r *Redis) MGet(keys ...interface{}) []string {
        values, err := redis.Strings(r.execute("MGET", keys...))
        if err != nil { return []string{} }
        return values
}
/*
func (r *Redis) Get(k_v_map map[interface{}]interface{}) bool{}
func (r *Redis) Expire(keys ...interface{}) bool{}
*/
<|endoftext|>