<commit_before>package acl

import (
	"errors"
	"strings"
)

// These error constants define the standard ACL error types. The values
// must not be changed since the error values are sent via RPC calls
// from older clients and may not have the correct type.
const (
	errNotFound         = "ACL not found"
	errRootDenied       = "Cannot resolve root ACL"
	errDisabled         = "ACL support disabled"
	errPermissionDenied = "Permission denied"
	errInvalidParent    = "Invalid Parent"
)

var (
	// ErrNotFound indicates there is no matching ACL.
	ErrNotFound = errors.New(errNotFound)

	// ErrRootDenied is returned when attempting to resolve a root ACL.
	ErrRootDenied = errors.New(errRootDenied)

	// ErrDisabled is returned when ACL changes are not permitted since
	// they are disabled.
	ErrDisabled = errors.New(errDisabled)

	// ErrPermissionDenied is returned when an ACL based rejection
	// happens.
	ErrPermissionDenied = PermissionDeniedError{}

	// ErrInvalidParent is returned when a remotely resolve ACL
	// token claims to have a non-root parent
	ErrInvalidParent = errors.New(errInvalidParent)
)

// IsErrNotFound checks if the given error message is comparable to
// ErrNotFound.
func IsErrNotFound(err error) bool {
	return err != nil && strings.Contains(err.Error(), errNotFound)
}

// IsErrRootDenied checks if the given error message is comparable to
// ErrRootDenied.
func IsErrRootDenied(err error) bool {
	return err != nil && strings.Contains(err.Error(), errRootDenied)
}

// IsErrDisabled checks if the given error message is comparable to
// ErrDisabled.
func IsErrDisabled(err error) bool {
	return err != nil && strings.Contains(err.Error(), errDisabled)
}

// IsErrPermissionDenied checks if the given error message is comparable
// to ErrPermissionDenied.
func IsErrPermissionDenied(err error) bool {
	return err != nil && strings.Contains(err.Error(), errPermissionDenied)
}

type PermissionDeniedError struct {
	Cause string
}

func (e PermissionDeniedError) Error() string {
	if e.Cause != "" {
		return errPermissionDenied + ": " + e.Cause
	}
	return errPermissionDenied
}
<commit_msg>Add helper for generating better permission denied errors<commit_after>package acl

import (
	"errors"
	"fmt"
	"strings"
)

// These error constants define the standard ACL error types. The values
// must not be changed since the error values are sent via RPC calls
// from older clients and may not have the correct type.
const (
	errNotFound         = "ACL not found"
	errRootDenied       = "Cannot resolve root ACL"
	errDisabled         = "ACL support disabled"
	errPermissionDenied = "Permission denied"
	errInvalidParent    = "Invalid Parent"
)

var (
	// ErrNotFound indicates there is no matching ACL.
	ErrNotFound = errors.New(errNotFound)

	// ErrRootDenied is returned when attempting to resolve a root ACL.
	ErrRootDenied = errors.New(errRootDenied)

	// ErrDisabled is returned when ACL changes are not permitted since
	// they are disabled.
	ErrDisabled = errors.New(errDisabled)

	// ErrPermissionDenied is returned when an ACL based rejection
	// happens.
	ErrPermissionDenied = PermissionDeniedError{}

	// ErrInvalidParent is returned when a remotely resolve ACL
	// token claims to have a non-root parent
	ErrInvalidParent = errors.New(errInvalidParent)
)

// IsErrNotFound checks if the given error message is comparable to
// ErrNotFound.
func IsErrNotFound(err error) bool {
	return err != nil && strings.Contains(err.Error(), errNotFound)
}

// IsErrRootDenied checks if the given error message is comparable to
// ErrRootDenied.
func IsErrRootDenied(err error) bool {
	return err != nil && strings.Contains(err.Error(), errRootDenied)
}

// IsErrDisabled checks if the given error message is comparable to
// ErrDisabled.
func IsErrDisabled(err error) bool {
	return err != nil && strings.Contains(err.Error(), errDisabled)
}

// IsErrPermissionDenied checks if the given error message is comparable
// to ErrPermissionDenied.
func IsErrPermissionDenied(err error) bool {
	return err != nil && strings.Contains(err.Error(), errPermissionDenied)
}

type PermissionDeniedError struct {
	Cause string
}

func (e PermissionDeniedError) Error() string {
	if e.Cause != "" {
		return errPermissionDenied + ": " + e.Cause
	}
	return errPermissionDenied
}

func PermissionDenied(msg string, args ...interface{}) PermissionDeniedError {
	cause := fmt.Sprintf(msg, args...)
	return PermissionDeniedError{Cause: cause}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package adb

import (
	"bufio"
	"fmt"
	"io"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

type Device struct {
	ID       string
	Usb      string
	Product  string
	Model    string
	Device   string
	ABIs     []string
	APILevel int
}

var deviceRegex = regexp.MustCompile(`^([^\s]+)\s+device(.*)$`)

func Devices() ([]*Device, error) {
	cmd := exec.Command("adb", "devices", "-l")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	var devices []*Device
	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		line := scanner.Text()
		m := deviceRegex.FindStringSubmatch(line)
		if m == nil {
			continue
		}
		device := &Device{
			ID: m[1],
		}
		for _, extra := range strings.Split(m[2], " ") {
			sp := strings.SplitN(extra, ":", 2)
			if len(sp) < 2 {
				continue
			}
			switch sp[0] {
			case "usb":
				device.Usb = sp[1]
			case "product":
				device.Product = sp[1]
			case "model":
				device.Model = sp[1]
			case "device":
				device.Device = sp[1]
			}
		}

		props, err := device.AdbProps()
		if err != nil {
			return nil, err
		}
		device.ABIs = getAbis(props)
		if len(device.ABIs) == 0 {
			return nil, fmt.Errorf("failed to get device ABIs")
		}
		device.APILevel, err = strconv.Atoi(props["ro.build.version.sdk"])
		if device.APILevel == 0 {
			return nil, fmt.Errorf("failed to get device API level")
		}

		devices = append(devices, device)
	}
	return devices, nil
}

func (d *Device) AdbCmd(args ...string) *exec.Cmd {
	cmdArgs := append([]string{"-s", d.ID}, args...)
	return exec.Command("adb", cmdArgs...)
}

func (d *Device) AdbShell(args ...string) *exec.Cmd {
	shellArgs := append([]string{"shell"}, args...)
	return d.AdbCmd(shellArgs...)
}

var propLineRegex = regexp.MustCompile(`^\[(.*)\]: \[(.*)\]$`)

func (d *Device) AdbProps() (map[string]string, error) {
	cmd := d.AdbShell("getprop")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	props := make(map[string]string)
	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		m := propLineRegex.FindStringSubmatch(scanner.Text())
		if m == nil {
			continue
		}
		key, val := m[1], m[2]
		props[key] = val
	}
	return props, nil
}

func getFailureCode(r *regexp.Regexp, line string) string {
	return r.FindStringSubmatch(line)[1]
}

func getAbis(props map[string]string) []string {
	// Android 5.0 and later specify a list of ABIs
	if abilist, e := props["ro.product.cpu.abilist"]; e {
		return strings.Split(abilist, ",")
	}
	// Older Android versions specify one primary ABI and optionally
	// one secondary ABI
	abi, e := props["ro.product.cpu.abi"]
	if !e {
		return nil
	}
	if abi2, e := props["ro.product.cpu.abi2"]; e {
		return []string{abi, abi2}
	}
	return []string{abi}
}

var installFailureRegex = regexp.MustCompile(`^Failure \[INSTALL_(.+)\]$`)

func withOpts(cmd string, opts []string, args ...string) []string {
	v := append([]string{"install"}, opts...)
	return append(v, args...)
}

func (d *Device) install(opts []string, path string) error {
	cmd := d.AdbCmd(withOpts("install", opts, path)...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	if err := cmd.Start(); err != nil {
		return err
	}
	line := getResultLine(stdout)
	if line == "Success" {
		return nil
	}
	return parseError(getFailureCode(installFailureRegex, line))
}

func (d *Device) Install(path string) error {
	return d.install(nil, path)
}

func (d *Device) Upgrade(path string) error {
	return d.install([]string{"-r"}, path)
}

func getResultLine(out io.Reader) string {
	scanner := bufio.NewScanner(out)
	for scanner.Scan() {
		l := scanner.Text()
		if strings.HasPrefix(l, "Failure") || strings.HasPrefix(l, "Success") {
			return l
		}
	}
	return ""
}

var deleteFailureRegex = regexp.MustCompile(`^Failure \[DELETE_(.+)\]$`)

func (d *Device) Uninstall(pkg string) error {
	cmd := d.AdbCmd("uninstall", pkg)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	if err := cmd.Start(); err != nil {
		return err
	}
	line := getResultLine(stdout)
	if line == "Success" {
		return nil
	}
	return parseError(getFailureCode(deleteFailureRegex, line))
}

type Package struct {
	ID    string
	VCode int
	VName string
}

var (
	packageRegex = regexp.MustCompile(`^  Package \[([^\s]+)\]`)
	verCodeRegex = regexp.MustCompile(`^    versionCode=([0-9]+)`)
	verNameRegex = regexp.MustCompile(`^    versionName=(.+)`)
)

func (d *Device) Installed() (map[string]Package, error) {
	cmd := d.AdbShell("dumpsys", "package", "packages")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	packages := make(map[string]Package)
	scanner := bufio.NewScanner(stdout)
	var cur Package
	first := true
	for scanner.Scan() {
		l := scanner.Text()
		if m := packageRegex.FindStringSubmatch(l); m != nil {
			if first {
				first = false
			} else {
				packages[cur.ID] = cur
				cur = Package{}
			}
			cur.ID = m[1]
		} else if m := verCodeRegex.FindStringSubmatch(l); m != nil {
			n, err := strconv.Atoi(m[1])
			if err != nil {
				panic(err)
			}
			cur.VCode = n
		} else if m := verNameRegex.FindStringSubmatch(l); m != nil {
			cur.VName = m[1]
		}
	}
	if !first {
		packages[cur.ID] = cur
	}
	return packages, nil
}
<commit_msg>adb: make ineffassign happy<commit_after>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package adb

import (
	"bufio"
	"fmt"
	"io"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

type Device struct {
	ID       string
	Usb      string
	Product  string
	Model    string
	Device   string
	ABIs     []string
	APILevel int
}

var deviceRegex = regexp.MustCompile(`^([^\s]+)\s+device(.*)$`)

func Devices() ([]*Device, error) {
	cmd := exec.Command("adb", "devices", "-l")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	var devices []*Device
	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		m := deviceRegex.FindStringSubmatch(scanner.Text())
		if m == nil {
			continue
		}
		device := &Device{
			ID: m[1],
		}
		for _, extra := range strings.Split(m[2], " ") {
			sp := strings.SplitN(extra, ":", 2)
			if len(sp) < 2 {
				continue
			}
			switch sp[0] {
			case "usb":
				device.Usb = sp[1]
			case "product":
				device.Product = sp[1]
			case "model":
				device.Model = sp[1]
			case "device":
				device.Device = sp[1]
			}
		}

		props, err := device.AdbProps()
		if err != nil {
			return nil, err
		}
		device.ABIs = getAbis(props)
		if len(device.ABIs) == 0 {
			return nil, fmt.Errorf("failed to get device ABIs")
		}
		device.APILevel, _ = strconv.Atoi(props["ro.build.version.sdk"])
		if device.APILevel == 0 {
			return nil, fmt.Errorf("failed to get device API level")
		}

		devices = append(devices, device)
	}
	return devices, nil
}

func (d *Device) AdbCmd(args ...string) *exec.Cmd {
	cmdArgs := append([]string{"-s", d.ID}, args...)
	return exec.Command("adb", cmdArgs...)
}

func (d *Device) AdbShell(args ...string) *exec.Cmd {
	shellArgs := append([]string{"shell"}, args...)
	return d.AdbCmd(shellArgs...)
}

var propLineRegex = regexp.MustCompile(`^\[(.*)\]: \[(.*)\]$`)

func (d *Device) AdbProps() (map[string]string, error) {
	cmd := d.AdbShell("getprop")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	props := make(map[string]string)
	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		m := propLineRegex.FindStringSubmatch(scanner.Text())
		if m == nil {
			continue
		}
		key, val := m[1], m[2]
		props[key] = val
	}
	return props, nil
}

func getFailureCode(r *regexp.Regexp, line string) string {
	return r.FindStringSubmatch(line)[1]
}

func getAbis(props map[string]string) []string {
	// Android 5.0 and later specify a list of ABIs
	if abilist, e := props["ro.product.cpu.abilist"]; e {
		return strings.Split(abilist, ",")
	}
	// Older Android versions specify one primary ABI and optionally
	// one secondary ABI
	abi, e := props["ro.product.cpu.abi"]
	if !e {
		return nil
	}
	if abi2, e := props["ro.product.cpu.abi2"]; e {
		return []string{abi, abi2}
	}
	return []string{abi}
}

var installFailureRegex = regexp.MustCompile(`^Failure \[INSTALL_(.+)\]$`)

func withOpts(cmd string, opts []string, args ...string) []string {
	v := append([]string{"install"}, opts...)
	return append(v, args...)
}

func (d *Device) install(opts []string, path string) error {
	cmd := d.AdbCmd(withOpts("install", opts, path)...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	if err := cmd.Start(); err != nil {
		return err
	}
	line := getResultLine(stdout)
	if line == "Success" {
		return nil
	}
	return parseError(getFailureCode(installFailureRegex, line))
}

func (d *Device) Install(path string) error {
	return d.install(nil, path)
}

func (d *Device) Upgrade(path string) error {
	return d.install([]string{"-r"}, path)
}

func getResultLine(out io.Reader) string {
	scanner := bufio.NewScanner(out)
	for scanner.Scan() {
		l := scanner.Text()
		if strings.HasPrefix(l, "Failure") || strings.HasPrefix(l, "Success") {
			return l
		}
	}
	return ""
}

var deleteFailureRegex = regexp.MustCompile(`^Failure \[DELETE_(.+)\]$`)

func (d *Device) Uninstall(pkg string) error {
	cmd := d.AdbCmd("uninstall", pkg)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	if err := cmd.Start(); err != nil {
		return err
	}
	line := getResultLine(stdout)
	if line == "Success" {
		return nil
	}
	return parseError(getFailureCode(deleteFailureRegex, line))
}

type Package struct {
	ID    string
	VCode int
	VName string
}

var (
	packageRegex = regexp.MustCompile(`^  Package \[([^\s]+)\]`)
	verCodeRegex = regexp.MustCompile(`^    versionCode=([0-9]+)`)
	verNameRegex = regexp.MustCompile(`^    versionName=(.+)`)
)

func (d *Device) Installed() (map[string]Package, error) {
	cmd := d.AdbShell("dumpsys", "package", "packages")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	packages := make(map[string]Package)
	scanner := bufio.NewScanner(stdout)
	var cur Package
	first := true
	for scanner.Scan() {
		l := scanner.Text()
		if m := packageRegex.FindStringSubmatch(l); m != nil {
			if first {
				first = false
			} else {
				packages[cur.ID] = cur
				cur = Package{}
			}
			cur.ID = m[1]
		} else if m := verCodeRegex.FindStringSubmatch(l); m != nil {
			n, err := strconv.Atoi(m[1])
			if err != nil {
				panic(err)
			}
			cur.VCode = n
		} else if m := verNameRegex.FindStringSubmatch(l); m != nil {
			cur.VName = m[1]
		}
	}
	if !first {
		packages[cur.ID] = cur
	}
	return packages, nil
}
<|endoftext|>


<commit_before>package creds

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"sort"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/sts"
)

// Creds defines a set of AWS credentials
type Creds struct {
	AccessKey, SecretKey, SessionToken, Region string
}

// New initializes credentials from a map
func New(argCreds map[string]string) (Creds, error) {
	required := []string{"AccessKey", "SecretKey", "SessionToken"}
	for _, key := range required {
		elem, ok := argCreds[key]
		if !ok || elem == "" {
			return Creds{}, fmt.Errorf("missing required key for Creds: %s", key)
		}
	}
	c := Creds{
		AccessKey:    argCreds["AccessKey"],
		SecretKey:    argCreds["SecretKey"],
		SessionToken: argCreds["SessionToken"],
		Region:       argCreds["Region"],
	}
	return c, nil
}

// NewFromStsSdk initializes a credential object from an AWS SDK Credentials object
func NewFromStsSdk(stsCreds *sts.Credentials) (Creds, error) {
	return New(map[string]string{
		"AccessKey":    *stsCreds.AccessKeyId,
		"SecretKey":    *stsCreds.SecretAccessKey,
		"SessionToken": *stsCreds.SessionToken,
	})
}

// NewFromEnv initializes credentials from the environment variables
func NewFromEnv() (Creds, error) {
	envCreds := make(map[string]string)
	for k, v := range Translations["envvar"] {
		if envCreds[v] == "" {
			envCreds[v] = os.Getenv(k)
		}
	}
	return New(envCreds)
}

// Translations defines common mappings for credential variables
var Translations = map[string]map[string]string{
	"envvar": {
		"AWS_ACCESS_KEY_ID":     "AccessKey",
		"AWS_SECRET_ACCESS_KEY": "SecretKey",
		"AWS_SESSION_TOKEN":     "SessionToken",
		"AWS_SECURITY_TOKEN":    "SessionToken",
		"AWS_DEFAULT_REGION":    "Region",
	},
	"console": {
		"sessionId":    "AccessKey",
		"sessionKey":   "SecretKey",
		"sessionToken": "SessionToken",
	},
}

func (c Creds) toMap() map[string]string {
	return map[string]string{
		"AccessKey":    c.AccessKey,
		"SecretKey":    c.SecretKey,
		"SessionToken": c.SessionToken,
		"Region":       c.Region,
	}
}

// Translate converts credentials based on a map of field names
func (c Creds) Translate(dictionary map[string]string) map[string]string {
	old := c.toMap()
	new := make(map[string]string)
	for k, v := range dictionary {
		new[k] = old[v]
	}
	return new
}

// ToSdk returns an AWS SDK Credentials object
func (c *Creds) ToSdk() *credentials.Credentials {
	return credentials.NewStaticCredentials(c.AccessKey, c.SecretKey, c.SessionToken)
}

// ToEnvVars returns environment variables suitable for eval-ing into the shell
func (c Creds) ToEnvVars() []string {
	envCreds := c.Translate(Translations["envvar"])
	var res []string
	for k, v := range envCreds {
		if v != "" {
			res = append(res, fmt.Sprintf("export %s=%s", k, v))
		}
	}
	sort.Strings(res)
	return res
}

var consoleTokenURL = "https://signin.%s.com" // #nosec

type consoleTokenResponse struct {
	SigninToken string
}

func (c Creds) toConsoleToken() (string, error) {
	args := []string{"?Action=getSigninToken"}

	consoleCreds := c.Translate(Translations["console"])
	jsonCreds, err := json.Marshal(consoleCreds)
	if err != nil {
		return "", err
	}
	urlCreds := url.QueryEscape(string(jsonCreds))
	paramCreds := fmt.Sprintf("Session=%s", urlCreds)
	args = append(args, paramCreds)

	argString := strings.Join(args, "&")
	namespace, err := c.namespace()
	if err != nil {
		return "", err
	}
	baseURL := fmt.Sprintf(consoleTokenURL, namespace)
	url := strings.Join([]string{baseURL, "/federation", argString}, "")

	resp, err := http.Get(url)

	if err != nil {
		return "", err
	}
	defer func() {
		if err := resp.Body.Close(); err != nil {
			panic(err)
		}
	}()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	tokenObj := consoleTokenResponse{}
	if err := json.Unmarshal(body, &tokenObj); err != nil {
		return "", err
	}

	return tokenObj.SigninToken, nil
}

// ToConsoleURL returns a console URL for the role
func (c Creds) ToConsoleURL() (string, error) {
	consoleToken, err := c.toConsoleToken()
	if err != nil {
		return "", err
	}
	namespace, err := c.namespace()
	if err != nil {
		return "", err
	}
	baseURL := fmt.Sprintf(consoleTokenURL, namespace)
	var targetURL string
	if c.Region != "" {
		targetURL = fmt.Sprintf("https://%s.console.%s.com/", c.Region, namespace)
	} else {
		targetURL = fmt.Sprintf("https://console.%s.com/", namespace)
	}
	urlParts := []string{
		baseURL,
		"/federation",
		"?Action=login",
		"&Issuer=",
		"&Destination=",
		url.QueryEscape(targetURL),
		"&SigninToken=",
		consoleToken,
	}
	urlString := strings.Join(urlParts, "")
	return urlString, nil
}

// ToSignoutURL returns a signout URL for the console
func (c Creds) ToSignoutURL() (string, error) {
	namespace, err := c.namespace()
	if err != nil {
		return "", err
	}
	baseURL := fmt.Sprintf(consoleTokenURL, namespace)
	url := strings.Join([]string{baseURL, "/oauth?Action=logout"}, "")
	return url, nil
}

// Client returns an AWS STS client for these creds
func (c Creds) Client() *sts.STS {
	config := aws.NewConfig().WithCredentialsChainVerboseErrors(true)
	if c.AccessKey != "" {
		config.WithCredentials(c.ToSdk())
	}
	sess := session.Must(session.NewSessionWithOptions(session.Options{
		Config:            *config,
		SharedConfigState: session.SharedConfigEnable,
	}))
	return sts.New(sess)
}

func (c Creds) identity() (*sts.GetCallerIdentityOutput, error) {
	params := &sts.GetCallerIdentityInput{}
	client := c.Client()
	return client.GetCallerIdentity(params)
}

func (c Creds) partition() (string, error) {
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	pieces := strings.Split(*identity.Arn, ":")
	return pieces[1], nil
}

func (c Creds) namespace() (string, error) {
	partition, err := c.partition()
	if err != nil {
		return "", err
	}
	result, ok := namespaces[partition]
	if ok {
		return result, nil
	}
	return "", fmt.Errorf("unknown partition: %s", partition)
}

var namespaces = map[string]string{
	"aws":        "aws.amazon",
	"aws-us-gov": "amazonaws-us-gov",
}

// AccountID returns the user's account ID
func (c Creds) AccountID() (string, error) {
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	return *identity.Account, nil
}

// MfaArn returns the user's virtual MFA token ARN
func (c Creds) MfaArn() (string, error) {
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	if !strings.Contains(*identity.Arn, ":user/") {
		return "", fmt.Errorf("failed to parse MFA ARN for non-user: %s", *identity.Arn)
	}
	mfaArn := strings.Replace(*identity.Arn, ":user/", ":mfa/", 1)
	return mfaArn, nil
}

// SessionName returns the default session name
func (c Creds) SessionName() (string, error) {
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	arnChunks := strings.Split(*identity.Arn, "/")
	oldName := arnChunks[len(arnChunks)-1]
	return oldName, nil
}

// NextRoleArn returns the new role's ARN
func (c Creds) NextRoleArn(role, inputAccountID string) (string, error) {
	if role == "" {
		return "", fmt.Errorf("role name cannot be empty")
	}
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	partition, err := c.partition()
	if err != nil {
		return "", err
	}
	accountID := inputAccountID
	if accountID == "" {
		accountID = *identity.Account
	}
	arn := fmt.Sprintf("arn:%s:iam::%s:role/%s", partition, accountID, role)
	return arn, nil
}
<commit_msg>support custom console url<commit_after>package creds

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"sort"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/sts"
)

// Creds defines a set of AWS credentials
type Creds struct {
	AccessKey, SecretKey, SessionToken, Region string
}

// New initializes credentials from a map
func New(argCreds map[string]string) (Creds, error) {
	required := []string{"AccessKey", "SecretKey", "SessionToken"}
	for _, key := range required {
		elem, ok := argCreds[key]
		if !ok || elem == "" {
			return Creds{}, fmt.Errorf("missing required key for Creds: %s", key)
		}
	}
	c := Creds{
		AccessKey:    argCreds["AccessKey"],
		SecretKey:    argCreds["SecretKey"],
		SessionToken: argCreds["SessionToken"],
		Region:       argCreds["Region"],
	}
	return c, nil
}

// NewFromStsSdk initializes a credential object from an AWS SDK Credentials object
func NewFromStsSdk(stsCreds *sts.Credentials) (Creds, error) {
	return New(map[string]string{
		"AccessKey":    *stsCreds.AccessKeyId,
		"SecretKey":    *stsCreds.SecretAccessKey,
		"SessionToken": *stsCreds.SessionToken,
	})
}

// NewFromEnv initializes credentials from the environment variables
func NewFromEnv() (Creds, error) {
	envCreds := make(map[string]string)
	for k, v := range Translations["envvar"] {
		if envCreds[v] == "" {
			envCreds[v] = os.Getenv(k)
		}
	}
	return New(envCreds)
}

// Translations defines common mappings for credential variables
var Translations = map[string]map[string]string{
	"envvar": {
		"AWS_ACCESS_KEY_ID":     "AccessKey",
		"AWS_SECRET_ACCESS_KEY": "SecretKey",
		"AWS_SESSION_TOKEN":     "SessionToken",
		"AWS_SECURITY_TOKEN":    "SessionToken",
		"AWS_DEFAULT_REGION":    "Region",
	},
	"console": {
		"sessionId":    "AccessKey",
		"sessionKey":   "SecretKey",
		"sessionToken": "SessionToken",
	},
}

func (c Creds) toMap() map[string]string {
	return map[string]string{
		"AccessKey":    c.AccessKey,
		"SecretKey":    c.SecretKey,
		"SessionToken": c.SessionToken,
		"Region":       c.Region,
	}
}

// Translate converts credentials based on a map of field names
func (c Creds) Translate(dictionary map[string]string) map[string]string {
	old := c.toMap()
	new := make(map[string]string)
	for k, v := range dictionary {
		new[k] = old[v]
	}
	return new
}

// ToSdk returns an AWS SDK Credentials object
func (c *Creds) ToSdk() *credentials.Credentials {
	return credentials.NewStaticCredentials(c.AccessKey, c.SecretKey, c.SessionToken)
}

// ToEnvVars returns environment variables suitable for eval-ing into the shell
func (c Creds) ToEnvVars() []string {
	envCreds := c.Translate(Translations["envvar"])
	var res []string
	for k, v := range envCreds {
		if v != "" {
			res = append(res, fmt.Sprintf("export %s=%s", k, v))
		}
	}
	sort.Strings(res)
	return res
}

var consoleTokenURL = "https://signin.%s.com" // #nosec

type consoleTokenResponse struct {
	SigninToken string
}

func (c Creds) toConsoleToken() (string, error) {
	args := []string{"?Action=getSigninToken"}

	consoleCreds := c.Translate(Translations["console"])
	jsonCreds, err := json.Marshal(consoleCreds)
	if err != nil {
		return "", err
	}
	urlCreds := url.QueryEscape(string(jsonCreds))
	paramCreds := fmt.Sprintf("Session=%s", urlCreds)
	args = append(args, paramCreds)

	argString := strings.Join(args, "&")
	namespace, err := c.namespace()
	if err != nil {
		return "", err
	}
	baseURL := fmt.Sprintf(consoleTokenURL, namespace)
	url := strings.Join([]string{baseURL, "/federation", argString}, "")

	resp, err := http.Get(url)

	if err != nil {
		return "", err
	}
	defer func() {
		if err := resp.Body.Close(); err != nil {
			panic(err)
		}
	}()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	tokenObj := consoleTokenResponse{}
	if err := json.Unmarshal(body, &tokenObj); err != nil {
		return "", err
	}

	return tokenObj.SigninToken, nil
}

// ToConsoleURL returns a console URL for the role
func (c Creds) ToConsoleURL() (string, error) {
	return c.ToCustomConsoleURL("")
}

// ToCustomConsoleURL returns a console URL with a custom path
func (c Creds) ToCustomConsoleURL(dest string) (string, error) {
	consoleToken, err := c.toConsoleToken()
	if err != nil {
		return "", err
	}
	namespace, err := c.namespace()
	if err != nil {
		return "", err
	}
	baseURL := fmt.Sprintf(consoleTokenURL, namespace)
	var targetURL string
	if c.Region != "" {
		targetURL = fmt.Sprintf("https://%s.console.%s.com/%s", c.Region, namespace, dest)
	} else {
		targetURL = fmt.Sprintf("https://console.%s.com/%s", namespace, dest)
	}
	urlParts := []string{
		baseURL,
		"/federation",
		"?Action=login",
		"&Issuer=",
		"&Destination=",
		url.QueryEscape(targetURL),
		"&SigninToken=",
		consoleToken,
	}
	urlString := strings.Join(urlParts, "")
	return urlString, nil
}

// ToSignoutURL returns a signout URL for the console
func (c Creds) ToSignoutURL() (string, error) {
	namespace, err := c.namespace()
	if err != nil {
		return "", err
	}
	baseURL := fmt.Sprintf(consoleTokenURL, namespace)
	url := strings.Join([]string{baseURL, "/oauth?Action=logout"}, "")
	return url, nil
}

// Client returns an AWS STS client for these creds
func (c Creds) Client() *sts.STS {
	config := aws.NewConfig().WithCredentialsChainVerboseErrors(true)
	if c.AccessKey != "" {
		config.WithCredentials(c.ToSdk())
	}
	sess := session.Must(session.NewSessionWithOptions(session.Options{
		Config:            *config,
		SharedConfigState: session.SharedConfigEnable,
	}))
	return sts.New(sess)
}

func (c Creds) identity() (*sts.GetCallerIdentityOutput, error) {
	params := &sts.GetCallerIdentityInput{}
	client := c.Client()
	return client.GetCallerIdentity(params)
}

func (c Creds) partition() (string, error) {
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	pieces := strings.Split(*identity.Arn, ":")
	return pieces[1], nil
}

func (c Creds) namespace() (string, error) {
	partition, err := c.partition()
	if err != nil {
		return "", err
	}
	result, ok := namespaces[partition]
	if ok {
		return result, nil
	}
	return "", fmt.Errorf("unknown partition: %s", partition)
}

var namespaces = map[string]string{
	"aws":        "aws.amazon",
	"aws-us-gov": "amazonaws-us-gov",
}

// AccountID returns the user's account ID
func (c Creds) AccountID() (string, error) {
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	return *identity.Account, nil
}

// MfaArn returns the user's virtual MFA token ARN
func (c Creds) MfaArn() (string, error) {
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	if !strings.Contains(*identity.Arn, ":user/") {
		return "", fmt.Errorf("failed to parse MFA ARN for non-user: %s", *identity.Arn)
	}
	mfaArn := strings.Replace(*identity.Arn, ":user/", ":mfa/", 1)
	return mfaArn, nil
}

// SessionName returns the default session name
func (c Creds) SessionName() (string, error) {
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	arnChunks := strings.Split(*identity.Arn, "/")
	oldName := arnChunks[len(arnChunks)-1]
	return oldName, nil
}

// NextRoleArn returns the new role's ARN
func (c Creds) NextRoleArn(role, inputAccountID string) (string, error) {
	if role == "" {
		return "", fmt.Errorf("role name cannot be empty")
	}
	identity, err := c.identity()
	if err != nil {
		return "", err
	}
	partition, err := c.partition()
	if err != nil {
		return "", err
	}
	accountID := inputAccountID
	if accountID == "" {
		accountID = *identity.Account
	}
	arn := fmt.Sprintf("arn:%s:iam::%s:role/%s", partition, accountID, role)
	return arn, nil
}
<|endoftext|>


<commit_before>// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package crypto

import (
	"bytes"
	"crypto/ecdsa"
	"encoding/hex"
	"encoding/json"
	"io"
	"strings"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto/secp256k1"
	"github.com/pborman/uuid"
)

const (
	version = 3
)

type Key struct {
	Id uuid.UUID // Version 4 "random" for unique id not derived from key data
	// to simplify lookups we also store the address
	Address common.Address
	// we only store privkey as pubkey/address can be derived from it
	// privkey in this struct is always in plaintext
	PrivateKey *ecdsa.PrivateKey
}

type plainKeyJSON struct {
	Address    string `json:"address"`
	PrivateKey string `json:"privatekey"`
	Id         string `json:"id"`
	Version    int    `json:"version"`
}

type encryptedKeyJSONV3 struct {
	Address string `json:"address"`
	Crypto  cryptoJSON
	Id      string `json:"id"`
	Version int    `json:"version"`
}

type encryptedKeyJSONV1 struct {
	Address string `json:"address"`
	Crypto  cryptoJSON
	Id      string `json:"id"`
	Version string `json:"version"`
}

type cryptoJSON struct {
	Cipher       string                 `json:"cipher"`
	CipherText   string                 `json:"ciphertext"`
	CipherParams cipherparamsJSON       `json:"cipherparams"`
	KDF          string                 `json:"kdf"`
	KDFParams    map[string]interface{} `json:"kdfparams"`
	MAC          string                 `json:"mac"`
}

type cipherparamsJSON struct {
	IV string `json:"iv"`
}

type scryptParamsJSON struct {
	N     int    `json:"n"`
	R     int    `json:"r"`
	P     int    `json:"p"`
	DkLen int    `json:"dklen"`
	Salt  string `json:"salt"`
}

func (k *Key) MarshalJSON() (j []byte, err error) {
	jStruct := plainKeyJSON{
		hex.EncodeToString(k.Address[:]),
		hex.EncodeToString(FromECDSA(k.PrivateKey)),
		k.Id.String(),
		version,
	}
	j, err = json.Marshal(jStruct)
	return j, err
}

func (k *Key) UnmarshalJSON(j []byte) (err error) {
	keyJSON := new(plainKeyJSON)
	err = json.Unmarshal(j, &keyJSON)
	if err != nil {
		return err
	}

	u := new(uuid.UUID)
	*u = uuid.Parse(keyJSON.Id)
	k.Id = *u
	addr, err := hex.DecodeString(keyJSON.Address)
	if err != nil {
		return err
	}

	privkey, err := hex.DecodeString(keyJSON.PrivateKey)
	if err != nil {
		return err
	}

	k.Address = common.BytesToAddress(addr)
	k.PrivateKey = ToECDSA(privkey)

	return nil
}

func NewKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key {
	id := uuid.NewRandom()
	key := &Key{
		Id:         id,
		Address:    PubkeyToAddress(privateKeyECDSA.PublicKey),
		PrivateKey: privateKeyECDSA,
	}
	return key
}

func NewKey(rand io.Reader) *Key {
	randBytes := make([]byte, 64)
	_, err := rand.Read(randBytes)
	if err != nil {
		panic("key generation: could not read from random source: " + err.Error())
	}
	reader := bytes.NewReader(randBytes)
	privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), reader)
	if err != nil {
		panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
	}

	return NewKeyFromECDSA(privateKeyECDSA)
}

// generate key whose address fits into < 155 bits so it can fit into
// the Direct ICAP spec. for simplicity and easier compatibility with
// other libs, we retry until the first byte is 0.
func NewKeyForDirectICAP(rand io.Reader) *Key {
	randBytes := make([]byte, 64)
	_, err := rand.Read(randBytes)
	if err != nil {
		panic("key generation: could not read from random source: " + err.Error())
	}
	reader := bytes.NewReader(randBytes)
	privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), reader)
	if err != nil {
		panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
	}
	key := NewKeyFromECDSA(privateKeyECDSA)
	if !strings.HasPrefix(key.Address.Hex(), "0x00") {
		return NewKeyForDirectICAP(rand)
	}
	return key
}
<commit_msg>crypto: "Crypto" -> "crypto" in web3 key format<commit_after>// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package crypto

import (
	"bytes"
	"crypto/ecdsa"
	"encoding/hex"
	"encoding/json"
	"io"
	"strings"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto/secp256k1"
	"github.com/pborman/uuid"
)

const (
	version = 3
)

type Key struct {
	Id uuid.UUID // Version 4 "random" for unique id not derived from key data
	// to simplify lookups we also store the address
	Address common.Address
	// we only store privkey as pubkey/address can be derived from it
	// privkey in this struct is always in plaintext
	PrivateKey *ecdsa.PrivateKey
}

type plainKeyJSON struct {
	Address    string `json:"address"`
	PrivateKey string `json:"privatekey"`
	Id         string `json:"id"`
	Version    int    `json:"version"`
}

type encryptedKeyJSONV3 struct {
	Address string     `json:"address"`
	Crypto  cryptoJSON `json:"crypto"`
	Id      string     `json:"id"`
	Version int        `json:"version"`
}

type encryptedKeyJSONV1 struct {
	Address string     `json:"address"`
	Crypto  cryptoJSON `json:"crypto"`
	Id      string     `json:"id"`
	Version string     `json:"version"`
}

type cryptoJSON struct {
	Cipher       string                 `json:"cipher"`
	CipherText   string                 `json:"ciphertext"`
	CipherParams cipherparamsJSON       `json:"cipherparams"`
	KDF          string                 `json:"kdf"`
	KDFParams    map[string]interface{} `json:"kdfparams"`
	MAC          string                 `json:"mac"`
}

type cipherparamsJSON struct {
	IV string `json:"iv"`
}

type scryptParamsJSON struct {
	N     int    `json:"n"`
	R     int    `json:"r"`
	P     int    `json:"p"`
	DkLen int    `json:"dklen"`
	Salt  string `json:"salt"`
}

func (k *Key) MarshalJSON() (j []byte, err error) {
	jStruct := plainKeyJSON{
		hex.EncodeToString(k.Address[:]),
		hex.EncodeToString(FromECDSA(k.PrivateKey)),
		k.Id.String(),
		version,
	}
	j, err = json.Marshal(jStruct)
	return j, err
}

func (k *Key) UnmarshalJSON(j []byte) (err error) {
	keyJSON := new(plainKeyJSON)
	err = json.Unmarshal(j, &keyJSON)
	if err != nil {
		return err
	}

	u := new(uuid.UUID)
	*u = uuid.Parse(keyJSON.Id)
	k.Id = *u
	addr, err := hex.DecodeString(keyJSON.Address)
	if err != nil {
		return err
	}

	privkey, err := hex.DecodeString(keyJSON.PrivateKey)
	if err != nil {
		return err
	}

	k.Address = common.BytesToAddress(addr)
	k.PrivateKey = ToECDSA(privkey)

	return nil
}

func NewKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key {
	id := uuid.NewRandom()
	key := &Key{
		Id:         id,
		Address:    PubkeyToAddress(privateKeyECDSA.PublicKey),
		PrivateKey: privateKeyECDSA,
	}
	return key
}

func NewKey(rand io.Reader) *Key {
	randBytes := make([]byte, 64)
	_, err := rand.Read(randBytes)
	if err != nil {
		panic("key generation: could not read from random source: " + err.Error())
	}
	reader := bytes.NewReader(randBytes)
	privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), reader)
	if err != nil {
		panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
	}

	return NewKeyFromECDSA(privateKeyECDSA)
}

// generate key whose address fits into < 155 bits so it can fit into
// the Direct ICAP spec. for simplicity and easier compatibility with
// other libs, we retry until the first byte is 0.
func NewKeyForDirectICAP(rand io.Reader) *Key {
	randBytes := make([]byte, 64)
	_, err := rand.Read(randBytes)
	if err != nil {
		panic("key generation: could not read from random source: " + err.Error())
	}
	reader := bytes.NewReader(randBytes)
	privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), reader)
	if err != nil {
		panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
	}
	key := NewKeyFromECDSA(privateKeyECDSA)
	if !strings.HasPrefix(key.Address.Hex(), "0x00") {
		return NewKeyForDirectICAP(rand)
	}
	return key
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"

	"github.com/vbauerster/mpb/v4"
	"github.com/vbauerster/mpb/v4/decor"
)

const (
	totalBars = 32
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func main() {
	var wg sync.WaitGroup
	p := mpb.New(
		mpb.WithWaitGroup(&wg),
		mpb.WithRefreshRate(50*time.Millisecond),
	)
	wg.Add(totalBars)

	for i := 0; i < totalBars; i++ {
		name := fmt.Sprintf("Bar#%02d: ", i)
		total := rand.Intn(320) + 10
		bar := p.AddBar(int64(total),
			mpb.PrependDecorators(
				decor.Name(name),
				decor.EwmaETA(decor.ET_STYLE_GO, 60, decor.WCSyncSpace),
			),
			mpb.AppendDecorators(
				decor.Percentage(decor.WC{W: 5}),
			),
		)

		go func() {
			defer wg.Done()
			max := 100 * time.Millisecond
			for !bar.Completed() {
				start := time.Now()
				time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10)
				// ewma based decorators require work duration measurement
				bar.IncrBy(1, time.Since(start))
			}
		}()
	}

	p.Wait()
}
<commit_msg>OnComplete<commit_after>package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"

	"github.com/vbauerster/mpb/v4"
	"github.com/vbauerster/mpb/v4/decor"
)

const (
	totalBars = 32
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func main() {
	var wg sync.WaitGroup
	p := mpb.New(
		mpb.WithWaitGroup(&wg),
		mpb.WithRefreshRate(50*time.Millisecond),
	)
	wg.Add(totalBars)

	for i := 0; i < totalBars; i++ {
		name := fmt.Sprintf("Bar#%02d: ", i)
		total := rand.Intn(320) + 10
		bar := p.AddBar(int64(total),
			mpb.PrependDecorators(
				decor.Name(name),
				decor.EwmaETA(decor.ET_STYLE_GO, 60, decor.WCSyncSpace),
			),
			mpb.AppendDecorators(
				decor.OnComplete(
					decor.Percentage(decor.WC{W: 5}), "done",
				),
			),
		)

		go func() {
			defer wg.Done()
			max := 100 * time.Millisecond
			for !bar.Completed() {
				start := time.Now()
				time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10)
				// ewma based decorators require work duration measurement
				bar.IncrBy(1, time.Since(start))
			}
		}()
	}

	p.Wait()
}
<|endoftext|>


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

// Code forked from Docker project
package daemon

import (
	"net"
	"os"
)

// SdNotify sends a message to the init daemon. It is common to ignore the error.
// If `unsetEnvironment` is true, the environment variable `NOTIFY_SOCKET`
// will be unconditionally unset.
//
// It returns one of the following:
// (false, nil) - notification not supported (i.e. NOTIFY_SOCKET is unset)
// (false, err) - notification supported, but failure happened (e.g. error connecting to NOTIFY_SOCKET or while sending data)
// (true, nil) - notification supported, data has been sent
func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
	socketAddr := &net.UnixAddr{
		Name: os.Getenv("NOTIFY_SOCKET"),
		Net:  "unixgram",
	}

	// NOTIFY_SOCKET not set
	if socketAddr.Name == "" {
		return false, nil
	}

	if unsetEnvironment {
		err = os.Unsetenv("NOTIFY_SOCKET")
	}
	if err != nil {
		return false, err
	}

	conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr)
	// Error connecting to NOTIFY_SOCKET
	if err != nil {
		return false, err
	}
	defer conn.Close()

	_, err = conn.Write([]byte(state))
	// Error sending the message
	if err != nil {
		return false, err
	}
	return true, nil
}
<commit_msg>daemon: Clean up copyright headers and documentation<commit_after>// Copyright 2014 Docker, Inc.
// Copyright 2015-2018 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

// Package daemon provides a Go implementation of the sd_notify protocol.
// It can be used to inform systemd of service start-up completion, watchdog
// events, and other status changes.
//
// https://www.freedesktop.org/software/systemd/man/sd_notify.html#Description
package daemon

import (
	"net"
	"os"
)

// SdNotify sends a message to the init daemon. It is common to ignore the error.
// If `unsetEnvironment` is true, the environment variable `NOTIFY_SOCKET`
// will be unconditionally unset.
//
// It returns one of the following:
// (false, nil) - notification not supported (i.e. NOTIFY_SOCKET is unset)
// (false, err) - notification supported, but failure happened (e.g. error connecting to NOTIFY_SOCKET or while sending data)
// (true, nil) - notification supported, data has been sent
func SdNotify(unsetEnvironment bool, state string) (bool, error) {
	socketAddr := &net.UnixAddr{
		Name: os.Getenv("NOTIFY_SOCKET"),
		Net:  "unixgram",
	}

	// NOTIFY_SOCKET not set
	if socketAddr.Name == "" {
		return false, nil
	}

	if unsetEnvironment {
		if err := os.Unsetenv("NOTIFY_SOCKET"); err != nil {
			return false, err
		}
	}

	conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr)
	// Error connecting to NOTIFY_SOCKET
	if err != nil {
		return false, err
	}
	defer conn.Close()

	if _, err = conn.Write([]byte(state)); err != nil {
		return false, err
	}
	return true, nil
}
<|endoftext|>


<commit_before>package rpc

import (
	"context"
	"fmt"
	"net"
	"strings"
	"sync"

	"github.com/appleboy/gorush/config"
	"github.com/appleboy/gorush/core"
	"github.com/appleboy/gorush/logx"
	"github.com/appleboy/gorush/notify"
	"github.com/appleboy/gorush/rpc/proto"

	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/reflection"
	"google.golang.org/grpc/status"
)

// Server is used to implement gorush grpc server.
type Server struct {
	cfg *config.ConfYaml
	mu  sync.Mutex
	// statusMap stores the serving status of the services this Server monitors.
	statusMap map[string]proto.HealthCheckResponse_ServingStatus
}

// NewServer returns a new Server.
func NewServer(cfg *config.ConfYaml) *Server {
	return &Server{
		cfg:       cfg,
		statusMap: make(map[string]proto.HealthCheckResponse_ServingStatus),
	}
}

// Check implements `service Health`.
func (s *Server) Check(ctx context.Context, in *proto.HealthCheckRequest) (*proto.HealthCheckResponse, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if in.Service == "" {
		// check the server overall health status.
		return &proto.HealthCheckResponse{
			Status: proto.HealthCheckResponse_SERVING,
		}, nil
	}
	if status, ok := s.statusMap[in.Service]; ok {
		return &proto.HealthCheckResponse{
			Status: status,
		}, nil
	}
	return nil, status.Error(codes.NotFound, "unknown service")
}

// Send implements helloworld.GreeterServer
func (s *Server) Send(ctx context.Context, in *proto.NotificationRequest) (*proto.NotificationReply, error) {
	badge := int(in.Badge)
	notification := notify.PushNotification{
		ID:               in.ID,
		Platform:         int(in.Platform),
		Tokens:           in.Tokens,
		Message:          in.Message,
		Title:            in.Title,
		Topic:            in.Topic,
		APIKey:           in.Key,
		Category:         in.Category,
		Sound:            in.Sound,
		ContentAvailable: in.ContentAvailable,
		ThreadID:         in.ThreadID,
		MutableContent:   in.MutableContent,
		Image:            in.Image,
		Priority:         strings.ToLower(in.GetPriority().String()),
	}

	if badge > 0 {
		notification.Badge = &badge
	}

	if in.Topic != "" && in.Platform == core.PlatFormAndroid {
		notification.To = in.Topic
	}

	if in.Alert != nil {
		notification.Alert = notify.Alert{
			Title:        in.Alert.Title,
			Body:         in.Alert.Body,
			Subtitle:     in.Alert.Subtitle,
			Action:       in.Alert.Action,
			ActionLocKey: in.Alert.Action,
			LaunchImage:  in.Alert.LaunchImage,
			LocArgs:      in.Alert.LocArgs,
			LocKey:       in.Alert.LocKey,
			TitleLocArgs: in.Alert.TitleLocArgs,
			TitleLocKey:  in.Alert.TitleLocKey,
		}
	}

	if in.Data != nil {
		notification.Data = map[string]interface{}{}
		for k, v := range in.Data.AsMap() {
			notification.Data[k] = fmt.Sprintf("%v", v)
		}
	}

	go func() {
		_, err := notify.SendNotification(&notification, s.cfg)
		if err != nil {
			logx.LogError.Error(err)
		}
	}()

	return &proto.NotificationReply{
		Success: true,
		Counts:  int32(len(notification.Tokens)),
	}, nil
}

// RunGRPCServer run gorush grpc server
func RunGRPCServer(ctx context.Context, cfg *config.ConfYaml) error {
	if !cfg.GRPC.Enabled {
		logx.LogAccess.Info("gRPC server is disabled.")
		return nil
	}

	s := grpc.NewServer()
	rpcSrv := NewServer(cfg)
	proto.RegisterGorushServer(s, rpcSrv)
	proto.RegisterHealthServer(s, rpcSrv)

	// Register reflection service on gRPC server.
	reflection.Register(s)

	lis, err := net.Listen("tcp", ":"+cfg.GRPC.Port)
	if err != nil {
		logx.LogError.Fatalln(err)
		return err
	}
	logx.LogAccess.Info("gRPC server is running on " + cfg.GRPC.Port + " port.")
	go func() {
		<-ctx.Done()
		s.GracefulStop() // graceful shutdown
		logx.LogAccess.Info("shutdown the gRPC server")
	}()
	if err = s.Serve(lis); err != nil {
		logx.LogError.Fatalln(err)
	}
	return err
}
<commit_msg>fix: Serialise nested protobuf structs correctly (#674)<commit_after>package rpc

import (
	"context"
	"net"
	"strings"
	"sync"

	"github.com/appleboy/gorush/config"
	"github.com/appleboy/gorush/core"
	"github.com/appleboy/gorush/logx"
	"github.com/appleboy/gorush/notify"
	"github.com/appleboy/gorush/rpc/proto"

	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/reflection"
	"google.golang.org/grpc/status"
)

// Server is used to implement gorush grpc server.
type Server struct {
	cfg *config.ConfYaml
	mu  sync.Mutex
	// statusMap stores the serving status of the services this Server monitors.
	statusMap map[string]proto.HealthCheckResponse_ServingStatus
}

// NewServer returns a new Server.
func NewServer(cfg *config.ConfYaml) *Server {
	return &Server{
		cfg:       cfg,
		statusMap: make(map[string]proto.HealthCheckResponse_ServingStatus),
	}
}

// Check implements `service Health`.
func (s *Server) Check(ctx context.Context, in *proto.HealthCheckRequest) (*proto.HealthCheckResponse, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if in.Service == "" {
		// check the server overall health status.
		return &proto.HealthCheckResponse{
			Status: proto.HealthCheckResponse_SERVING,
		}, nil
	}
	if status, ok := s.statusMap[in.Service]; ok {
		return &proto.HealthCheckResponse{
			Status: status,
		}, nil
	}
	return nil, status.Error(codes.NotFound, "unknown service")
}

// Send implements helloworld.GreeterServer
func (s *Server) Send(ctx context.Context, in *proto.NotificationRequest) (*proto.NotificationReply, error) {
	badge := int(in.Badge)
	notification := notify.PushNotification{
		ID:               in.ID,
		Platform:         int(in.Platform),
		Tokens:           in.Tokens,
		Message:          in.Message,
		Title:            in.Title,
		Topic:            in.Topic,
		APIKey:           in.Key,
		Category:         in.Category,
		Sound:            in.Sound,
		ContentAvailable: in.ContentAvailable,
		ThreadID:         in.ThreadID,
		MutableContent:   in.MutableContent,
		Image:            in.Image,
		Priority:         strings.ToLower(in.GetPriority().String()),
	}

	if badge > 0 {
		notification.Badge = &badge
	}

	if in.Topic != "" && in.Platform == core.PlatFormAndroid {
		notification.To = in.Topic
	}

	if in.Alert != nil {
		notification.Alert = notify.Alert{
			Title:        in.Alert.Title,
			Body:         in.Alert.Body,
			Subtitle:     in.Alert.Subtitle,
			Action:       in.Alert.Action,
			ActionLocKey: in.Alert.Action,
			LaunchImage:  in.Alert.LaunchImage,
			LocArgs:      in.Alert.LocArgs,
			LocKey:       in.Alert.LocKey,
			TitleLocArgs: in.Alert.TitleLocArgs,
			TitleLocKey:  in.Alert.TitleLocKey,
		}
	}

	if in.Data != nil {
		notification.Data = in.Data.AsMap()
	}

	go func() {
		_, err := notify.SendNotification(&notification, s.cfg)
		if err != nil {
			logx.LogError.Error(err)
		}
	}()

	return &proto.NotificationReply{
		Success: true,
		Counts:  int32(len(notification.Tokens)),
	}, nil
}

// RunGRPCServer run gorush grpc server
func RunGRPCServer(ctx context.Context, cfg *config.ConfYaml) error {
	if !cfg.GRPC.Enabled {
		logx.LogAccess.Info("gRPC server is disabled.")
		return nil
	}

	s := grpc.NewServer()
	rpcSrv := NewServer(cfg)
	proto.RegisterGorushServer(s, rpcSrv)
	proto.RegisterHealthServer(s, rpcSrv)

	// Register reflection service on gRPC server.
	reflection.Register(s)

	lis, err := net.Listen("tcp", ":"+cfg.GRPC.Port)
	if err != nil {
		logx.LogError.Fatalln(err)
		return err
	}
	logx.LogAccess.Info("gRPC server is running on " + cfg.GRPC.Port + " port.")
	go func() {
		<-ctx.Done()
		s.GracefulStop() // graceful shutdown
		logx.LogAccess.Info("shutdown the gRPC server")
	}()
	if err = s.Serve(lis); err != nil {
		logx.LogError.Fatalln(err)
	}
	return err
}
<|endoftext|>


<commit_before>package data_test

import (
	"encoding/base64"
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	data "github.com/tendermint/go-wire/data"
)

func TestEncoders(t *testing.T) {
	assert := assert.New(t)

	hex := data.HexEncoder
	b64 := data.B64Encoder
	rb64 := data.RawB64Encoder
	cases := []struct {
		encoder         data.ByteEncoder
		input, expected []byte
	}{
		// hexidecimal
		{hex, []byte(`"1A2B3C4D"`), []byte{0x1a, 0x2b, 0x3c, 0x4d}},
		{hex, []byte(`"DE14"`), []byte{0xde, 0x14}},
		// these are errors
		{hex, []byte(`0123`), nil},     // not in quotes
		{hex, []byte(`"dewq12"`), nil}, // invalid chars
		{hex, []byte(`"abc"`), nil},    // uneven length

		// base64
		{b64, []byte(`"Zm9v"`), []byte("foo")},
		{b64, []byte(`"RCEuM3M="`), []byte("D!.3s")},
		// make sure url encoding!
		{b64, []byte(`"D4_a--w="`), []byte{0x0f, 0x8f, 0xda, 0xfb, 0xec}},
		// these are errors
		{b64, []byte(`"D4/a++1="`), nil}, // non-url encoding
		{b64, []byte(`0123`), nil},       // not in quotes
		{b64, []byte(`"hey!"`), nil},     // invalid chars
		{b64, []byte(`"abc"`), nil},      // length%4 != 0

		// raw base64
		{rb64, []byte(`"Zm9v"`), []byte("foo")},
		{rb64, []byte(`"RCEuM3M"`), []byte("D!.3s")},
		// make sure url encoding!
		{rb64, []byte(`"D4_a--w"`), []byte{0x0f, 0x8f, 0xda, 0xfb, 0xec}},
		// these are errors
		{rb64, []byte(`"D4/a++1"`), nil}, // non-url encoding
		{rb64, []byte(`0123`), nil},      // not in quotes
		{rb64, []byte(`"hey!"`), nil},    // invalid chars
		{rb64, []byte(`"abc="`), nil},    // with padding

	}

	for _, tc := range cases {
		var output []byte
		err := tc.encoder.Unmarshal(&output, tc.input)
		if tc.expected == nil {
			assert.NotNil(err, tc.input)
		} else if assert.Nil(err, "%s: %+v", tc.input, err) {
			assert.Equal(tc.expected, output, tc.input)
			rev, err := tc.encoder.Marshal(tc.expected)
			if assert.Nil(err, tc.input) {
				assert.Equal(tc.input, rev)
			}
		}
	}
}

func TestString(t *testing.T) {
	assert := assert.New(t)

	hex := data.HexEncoder
	b64 := data.B64Encoder
	rb64 := data.RawB64Encoder
	cases := []struct {
		encoder  data.ByteEncoder
		expected string
		input    []byte
	}{
		// hexidecimal
		{hex, "1A2B3C4D", []byte{0x1a, 0x2b, 0x3c, 0x4d}},
		{hex, "DE14", []byte{0xde, 0x14}},
		{b64, "RCEuM3M=", []byte("D!.3s")},
		{rb64, "D4_a--w", []byte{0x0f, 0x8f, 0xda, 0xfb, 0xec}},
	}
	for _, tc := range cases {
		data.Encoder = tc.encoder
		b := data.Bytes(tc.input)
		assert.Equal(tc.expected, b.String())
	}
}

// BData can be encoded/decoded
type BData struct {
	Count int
	Data  data.Bytes
}

// BView is to unmarshall and check the encoding
type BView struct {
	Count int
	Data  string
}

func TestBytes(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	cases := []struct {
		encoder  data.ByteEncoder
		data     data.Bytes
		expected string
	}{
		{data.HexEncoder, []byte{0x1a, 0x2b, 0x3c, 0x4d}, "1A2B3C4D"},
		{data.B64Encoder, []byte("D!.3s"), "RCEuM3M="},
		{data.RawB64Encoder, []byte("D!.3s"), "RCEuM3M"},
	}

	for i, tc := range cases {
		data.Encoder = tc.encoder
		// encode the data
		in := BData{Count: 15, Data: tc.data}
		d, err := json.Marshal(in)
		require.Nil(err, "%d: %+v", i, err)
		// recover the data
		out := BData{}
		err = json.Unmarshal(d, &out)
		require.Nil(err, "%d: %+v", i, err)
		assert.Equal(in.Count, out.Count, "%d", i)
		assert.Equal(in.Data, out.Data, "%d", i)
		// check the encoding
		view := BView{}
		err = json.Unmarshal(d, &view)
		require.Nil(err, "%d: %+v", i, err)
		assert.Equal(tc.expected, view.Data)
	}
}

/*** this is example code for the byte array ***/

type Dings [5]byte

func (d Dings) MarshalJSON() ([]byte, error) {
	return data.Encoder.Marshal(d[:])
}

func (d *Dings) UnmarshalJSON(enc []byte) error {
	var ref []byte
	err := data.Encoder.Unmarshal(&ref, enc)
	copy(d[:], ref)
	return err
}

func TestByteArray(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	d := Dings{}
	copy(d[:], []byte("D!.3s"))

	cases := []struct {
		encoder  data.ByteEncoder
		data     Dings
		expected string
	}{
		{data.HexEncoder, Dings{0x1a, 0x2b, 0x3c, 0x4d, 0x5e}, "1A2B3C4D5E"},
		{data.B64Encoder, d, "RCEuM3M="},
		{data.RawB64Encoder, d, "RCEuM3M"},
	}

	for i, tc := range cases {
		data.Encoder = tc.encoder
		// encode the data
		d, err := json.Marshal(tc.data)
		require.Nil(err, "%d: %+v", i, err)
		// recover the data
		out := Dings{}
		err = json.Unmarshal(d, &out)
		require.Nil(err, "%d: %+v", i, err)
		assert.Equal(tc.data, out, "%d", i)
		// check the encoding
		view := ""
		err = json.Unmarshal(d, &view)
		require.Nil(err, "%d: %+v", i, err)
		assert.Equal(tc.expected, view)
	}

	// Test invalid data
	invalid := []byte(`"food"`)
	data.Encoder = data.HexEncoder
	ding := Dings{1, 2, 3, 4, 5}
	parsed := ding
	require.Equal(ding, parsed)
	// on a failed parsing, we don't overwrite any data
	err := json.Unmarshal(invalid, &parsed)
	require.NotNil(err)
	assert.Equal(ding, parsed)
}

func TestWTF(t *testing.T) {
	assert := assert.New(t)
	enc := base64.URLEncoding

	cases := []string{
		// normal...
		"ABCD",
		"RCEuM3M=",
		"RCE_M3M=",
		"RCE_M30=",
		"D4_a--1B",
		// these fail...
		// "D4_a--1=",
		// "D4_a0-1=",
		// "D4_a__1=",
		// "D4_a0-9=",
		// "Finey-1=",
		// "Finey41=",
		// "Fineyo1=",
		// these work
		"D4_a0-A=",
		"D4_a0BA=",
		// more random ending in [1-9]=
		// "aa4=",
		// "deadbe7=",
		// wait, 0 is safe...
		"deadbe0=",
	}

	for _, tc := range cases {
		b, err := enc.DecodeString(tc)
		if assert.Nil(err, tc) {
			s := enc.EncodeToString(b)
			assert.Equal(tc, s)
		}
	}
}
<commit_msg>Comment out crazy base64 tests<commit_after>package data_test

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	data "github.com/tendermint/go-wire/data"
)

func TestEncoders(t *testing.T) {
	assert := assert.New(t)

	hex := data.HexEncoder
	b64 := data.B64Encoder
	rb64 := data.RawB64Encoder
	cases := []struct {
		encoder         data.ByteEncoder
		input, expected []byte
	}{
		// hexidecimal
		{hex, []byte(`"1A2B3C4D"`), []byte{0x1a, 0x2b, 0x3c, 0x4d}},
		{hex, []byte(`"DE14"`), []byte{0xde, 0x14}},
		// these are errors
		{hex, []byte(`0123`), nil},     // not in quotes
		{hex, []byte(`"dewq12"`), nil}, // invalid chars
		{hex, []byte(`"abc"`), nil},    // uneven length

		// base64
		{b64, []byte(`"Zm9v"`), []byte("foo")},
		{b64, []byte(`"RCEuM3M="`), []byte("D!.3s")},
		// make sure url encoding!
		{b64, []byte(`"D4_a--w="`), []byte{0x0f, 0x8f, 0xda, 0xfb, 0xec}},
		// these are errors
		{b64, []byte(`"D4/a++1="`), nil}, // non-url encoding
		{b64, []byte(`0123`), nil},       // not in quotes
		{b64, []byte(`"hey!"`), nil},     // invalid chars
		{b64, []byte(`"abc"`), nil},      // length%4 != 0

		// raw base64
		{rb64, []byte(`"Zm9v"`), []byte("foo")},
		{rb64, []byte(`"RCEuM3M"`), []byte("D!.3s")},
		// make sure url encoding!
		{rb64, []byte(`"D4_a--w"`), []byte{0x0f, 0x8f, 0xda, 0xfb, 0xec}},
		// these are errors
		{rb64, []byte(`"D4/a++1"`), nil}, // non-url encoding
		{rb64, []byte(`0123`), nil},      // not in quotes
		{rb64, []byte(`"hey!"`), nil},    // invalid chars
		{rb64, []byte(`"abc="`), nil},    // with padding

	}

	for _, tc := range cases {
		var output []byte
		err := tc.encoder.Unmarshal(&output, tc.input)
		if tc.expected == nil {
			assert.NotNil(err, tc.input)
		} else if assert.Nil(err, "%s: %+v", tc.input, err) {
			assert.Equal(tc.expected, output, tc.input)
			rev, err := tc.encoder.Marshal(tc.expected)
			if assert.Nil(err, tc.input) {
				assert.Equal(tc.input, rev)
			}
		}
	}
}

func TestString(t *testing.T) {
	assert := assert.New(t)

	hex := data.HexEncoder
	b64 := data.B64Encoder
	rb64 := data.RawB64Encoder
	cases := []struct {
		encoder  data.ByteEncoder
		expected string
		input    []byte
	}{
		// hexidecimal
		{hex, "1A2B3C4D", []byte{0x1a, 0x2b, 0x3c, 0x4d}},
		{hex, "DE14", []byte{0xde, 0x14}},
		{b64, "RCEuM3M=", []byte("D!.3s")},
		{rb64, "D4_a--w", []byte{0x0f, 0x8f, 0xda, 0xfb, 0xec}},
	}
	for _, tc := range cases {
		data.Encoder = tc.encoder
		b := data.Bytes(tc.input)
		assert.Equal(tc.expected, b.String())
	}
}

// BData can be encoded/decoded
type BData struct {
	Count int
	Data  data.Bytes
}

// BView is to unmarshall and check the encoding
type BView struct {
	Count int
	Data  string
}

func TestBytes(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	cases := []struct {
		encoder  data.ByteEncoder
		data     data.Bytes
		expected string
	}{
		{data.HexEncoder, []byte{0x1a, 0x2b, 0x3c, 0x4d}, "1A2B3C4D"},
		{data.B64Encoder, []byte("D!.3s"), "RCEuM3M="},
		{data.RawB64Encoder, []byte("D!.3s"), "RCEuM3M"},
	}

	for i, tc := range cases {
		data.Encoder = tc.encoder
		// encode the data
		in := BData{Count: 15, Data: tc.data}
		d, err := json.Marshal(in)
		require.Nil(err, "%d: %+v", i, err)
		// recover the data
		out := BData{}
		err = json.Unmarshal(d, &out)
		require.Nil(err, "%d: %+v", i, err)
		assert.Equal(in.Count, out.Count, "%d", i)
		assert.Equal(in.Data, out.Data, "%d", i)
		// check the encoding
		view := BView{}
		err = json.Unmarshal(d, &view)
		require.Nil(err, "%d: %+v", i, err)
		assert.Equal(tc.expected, view.Data)
	}
}

/*** this is example code for the byte array ***/

type Dings [5]byte

func (d Dings) MarshalJSON() ([]byte, error) {
	return data.Encoder.Marshal(d[:])
}

func (d *Dings) UnmarshalJSON(enc []byte) error {
	var ref []byte
	err := data.Encoder.Unmarshal(&ref, enc)
	copy(d[:], ref)
	return err
}

func TestByteArray(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	d := Dings{}
	copy(d[:], []byte("D!.3s"))

	cases := []struct {
		encoder  data.ByteEncoder
		data     Dings
		expected string
	}{
		{data.HexEncoder, Dings{0x1a, 0x2b, 0x3c, 0x4d, 0x5e}, "1A2B3C4D5E"},
		{data.B64Encoder, d, "RCEuM3M="},
		{data.RawB64Encoder, d, "RCEuM3M"},
	}

	for i, tc := range cases {
		data.Encoder = tc.encoder
		// encode the data
		d, err := json.Marshal(tc.data)
		require.Nil(err, "%d: %+v", i, err)
		// recover the data
		out := Dings{}
		err = json.Unmarshal(d, &out)
		require.Nil(err, "%d: %+v", i, err)
		assert.Equal(tc.data, out, "%d", i)
		// check the encoding
		view := ""
		err = json.Unmarshal(d, &view)
		require.Nil(err, "%d: %+v", i, err)
		assert.Equal(tc.expected, view)
	}

	// Test invalid data
	invalid := []byte(`"food"`)
	data.Encoder = data.HexEncoder
	ding := Dings{1, 2, 3, 4, 5}
	parsed := ding
	require.Equal(ding, parsed)
	// on a failed parsing, we don't overwrite any data
	err := json.Unmarshal(invalid, &parsed)
	require.NotNil(err)
	assert.Equal(ding, parsed)
}

// I guess this is "proper"?  Seems funny though...
// echo -n "deadbQ==" | base64 -D | od -H
// echo -n "deadb9==" | base64 -D | od -H
// both ---> 6f9de675
// func TestWTF(t *testing.T) {
// 	assert := assert.New(t)
// 	url := base64.URLEncoding
// 	std := base64.StdEncoding

// 	cases := []struct {
// 		s string
// 		e *base64.Encoding
// 	}{
// 		// these fail...
// 		{"D4_a--1=", url},
// 		{"D4_a0-1=", url},
// 		{"D4_a__1=", url},
// 		{"D4/a++1=", std},
// 		{"D4_a0-9=", url},
// 		{"Finey-1=", url},
// 		{"Finey41=", url},
// 		{"Finey+1=", std},
// 		{"Finey+1+", std},
// 		{"Fineyo1=", url},
// 		// these work
// 		{"D4_a0-A=", url},
// 		{"D4_a0BA=", url},
// 		// more random ending in [1-9]=
// 		{"deadbe7=", url},
// 		{"deadb7==", url},
// 		{"deadbe==", url},
// 		// wait, 0= is safe...
// 		{"deadbe0=", url},
// 		{"deadAA2=", std},
// 		{"deadAA9=", std},
// 		{"deadaa9=", url},
// 	}

// 	for _, tc := range cases {
// 		b, err := tc.e.DecodeString(tc.s)
// 		if assert.Nil(err, "%#v", err) {
// 			s := tc.e.EncodeToString(b)
// 			assert.Equal(tc.s, s)
// 		}
// 	}
// }
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"compress/gzip"
	"crypto/sha512"
	"encoding/base64"
	"flag"
	"fmt"
	"io"
	"os"
	"path"
	"path/filepath"
)

type creationContext struct {
	rootArchivePath string
	archive *tar.Writer
	mapping map[string]bool
}

func (ctx* creationContext) addDir(dirPath string, archivePath string, dir *os.File, isRoot bool) error {
	entries, err := dir.Readdir(0)
	if err != nil {
		return err
	}

	for _, fi := range entries {
		if isRoot && fi.Name() == ".backing_store" {
			continue
		}

		err = ctx.addEntry(filepath.Join(dirPath, fi.Name()), path.Join(archivePath, fi.Name()), fi)
		if err != nil {
			return err
		}
	}

	return nil
}

func (ctx* creationContext) addEntry(entryPath string, archivePath string, fi os.FileInfo) error {
	f, err := os.OpenFile(entryPath, os.O_RDONLY, 0)
	if err != nil {
		return err
	}

	if fi.Mode() & (os.ModeDir | os.ModeSymlink) == os.ModeDir {
		// Entry is a directory.
		return ctx.addDir(entryPath, archivePath, f, false)
	}

	// Entry is a file. Hash its contents and add a map entry.
	hash := sha512.New()
	_, err = io.Copy(hash, f)
	if err != nil {
		return err
	}

	hashKey := base64.URLEncoding.EncodeToString(hash.Sum(nil))
	backingFileArchivePath := path.Join(ctx.rootArchivePath, ".backing_store", hashKey)

	if _, ok := ctx.mapping[hashKey]; !ok {
		// The hash was not present in the map. Add a new entry to the archive for the backing file.
		_, err = f.Seek(0, os.SEEK_SET)
		if err != nil {
			return err
		}

		header, err := tar.FileInfoHeader(fi, "")
		if err != nil {
			return err
		}

		header.Name = backingFileArchivePath

		err = ctx.archive.WriteHeader(header)
		if err != nil {
			return err
		}

		_, err = io.Copy(ctx.archive, f)
		if err != nil {
			return err
		}

		ctx.mapping[hashKey] = true
	}

	// Add a hard link entry to the archive from the backing file to the archive path.
	header, err := tar.FileInfoHeader(fi, "")
	if err != nil {
		return err
	}

	header.Name = archivePath
	header.Typeflag = tar.TypeLink
	header.Linkname = backingFileArchivePath
	header.Size = 0

	return ctx.archive.WriteHeader(header)
}

func main() {
	flag.Usage = func() {
		_, program := filepath.Split(os.Args[0])
		fmt.Fprintf(os.Stderr, "usage: %s [OPTIONS] [FILE]\n", program)
		flag.PrintDefaults()
	}

	shouldCompress := flag.Bool("compress", false, "compress output using gzip")

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}

	root, err := filepath.Abs(flag.Arg(0))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}

	f, err := os.OpenFile(root, os.O_RDONLY, os.ModeDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}

	output := io.WriteCloser(os.Stdout)
	if *shouldCompress {
		output = gzip.NewWriter(output)
	}

	_, rootArchivePath := filepath.Split(root)
	ctx := &creationContext{rootArchivePath, tar.NewWriter(output), make(map[string]bool)}

	err = ctx.addDir(root, rootArchivePath, f, true)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}

	err = ctx.archive.Close()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}

	err = output.Close()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}
}
<commit_msg>Run the source through gofmt.<commit_after>package main

import (
	"archive/tar"
	"compress/gzip"
	"crypto/sha512"
	"encoding/base64"
	"flag"
	"fmt"
	"io"
	"os"
	"path"
	"path/filepath"
)

type creationContext struct {
	rootArchivePath string
	archive         *tar.Writer
	mapping         map[string]bool
}

func (ctx *creationContext) addDir(dirPath string, archivePath string, dir *os.File, isRoot bool) error {
	entries, err := dir.Readdir(0)
	if err != nil {
		return err
	}

	for _, fi := range entries {
		if isRoot && fi.Name() == ".backing_store" {
			continue
		}

		err = ctx.addEntry(filepath.Join(dirPath, fi.Name()), path.Join(archivePath, fi.Name()), fi)
		if err != nil {
			return err
		}
	}

	return nil
}

func (ctx *creationContext) addEntry(entryPath string, archivePath string, fi os.FileInfo) error {
	f, err := os.OpenFile(entryPath, os.O_RDONLY, 0)
	if err != nil {
		return err
	}

	if fi.Mode()&(os.ModeDir|os.ModeSymlink) == os.ModeDir {
		// Entry is a directory.
		return ctx.addDir(entryPath, archivePath, f, false)
	}

	// Entry is a file. Hash its contents and add a map entry.
	hash := sha512.New()
	_, err = io.Copy(hash, f)
	if err != nil {
		return err
	}

	hashKey := base64.URLEncoding.EncodeToString(hash.Sum(nil))
	backingFileArchivePath := path.Join(ctx.rootArchivePath, ".backing_store", hashKey)

	if _, ok := ctx.mapping[hashKey]; !ok {
		// The hash was not present in the map. Add a new entry to the archive for the backing file.
		_, err = f.Seek(0, os.SEEK_SET)
		if err != nil {
			return err
		}

		header, err := tar.FileInfoHeader(fi, "")
		if err != nil {
			return err
		}

		header.Name = backingFileArchivePath

		err = ctx.archive.WriteHeader(header)
		if err != nil {
			return err
		}

		_, err = io.Copy(ctx.archive, f)
		if err != nil {
			return err
		}

		ctx.mapping[hashKey] = true
	}

	// Add a hard link entry to the archive from the backing file to the archive path.
	header, err := tar.FileInfoHeader(fi, "")
	if err != nil {
		return err
	}

	header.Name = archivePath
	header.Typeflag = tar.TypeLink
	header.Linkname = backingFileArchivePath
	header.Size = 0

	return ctx.archive.WriteHeader(header)
}

func main() {
	flag.Usage = func() {
		_, program := filepath.Split(os.Args[0])
		fmt.Fprintf(os.Stderr, "usage: %s [OPTIONS] [FILE]\n", program)
		flag.PrintDefaults()
	}

	shouldCompress := flag.Bool("compress", false, "compress output using gzip")

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}

	root, err := filepath.Abs(flag.Arg(0))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}

	f, err := os.OpenFile(root, os.O_RDONLY, os.ModeDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}

	output := io.WriteCloser(os.Stdout)
	if *shouldCompress {
		output = gzip.NewWriter(output)
	}

	_, rootArchivePath := filepath.Split(root)
	ctx := &creationContext{rootArchivePath, tar.NewWriter(output), make(map[string]bool)}

	err = ctx.addDir(root, rootArchivePath, f, true)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}

	err = ctx.archive.Close()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}

	err = output.Close()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(-1)
	}
}
<|endoftext|>


<commit_before>package tarpan

import (
	"log"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/soniah/gosnmp"
)

// Tarpan constants
const (
	ConcurrentProcesses = 5
)

// Exit code
const (
	ExitCodeOK = iota
	ExitCodeConfError
	ExitCodeParseFlagError
)

// SNMP constants
const (
	community = "public"
	port      = 161
	timeout   = 2
	retry     = 3
	//MaximumPDUBytes = 512
)

// JSON structure definition
type DataSet struct {
	Default Defaults `json:"defaults"`
	Targets []Target `json:"targets"`
}

type Defaults struct {
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
}

type Target struct {
	Name      string `json:"name"`
	Address   string `json:"address"`
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
	OIDs      []OID  `json:"oids"`
}

type OID struct {
	OID         string `json:"oid"`
	Description string `json:"description"`
}

// Tarpan result structures
type TarpanResult struct {
	Name      string    `json:"name"`
	Address   string    `json:"address"`
	Port      uint16    `json:"port"`
	Version   string    `json:"version"`
	Community string    `json:"community"`
	VarBinds  []VarBind `json:"varbinds"`
}

type VarBind struct {
	Description string         `json:"description"`
	OID         string         `json:"oid"`
	Type        gosnmp.Asn1BER `json:"type"`
	Value       interface{}    `json:"value"`
	Time        int64          `json:"time"`
}

type Tarpan interface {
	makeRequestBody()
	SetManager()
	SetParams()
	Get(params map[string]string, oids []string) []gosnmp.SnmpPDU
	Run()
}

type TarpanManager struct {
	snmp *gosnmp.GoSNMP
}

type SnmpResult struct {
	target  Target
	results []gosnmp.SnmpPDU
	time    int64
}

type Channels struct {
	semaphoe chan int
	results  chan SnmpResult
}

func (t *TarpanManager) Get(params map[string]string,
	oids []string) []gosnmp.SnmpPDU {
	t.SetParams(params)
	connection_err := t.snmp.Connect()
	if connection_err != nil {
		log.Fatalf("Connection error: %")
	}
	result, request_err := t.snmp.Get(oids)
	if request_err != nil {
		log.Println("Get() error: %v", request_err)
	}
	t.snmp.Conn.Close()

	return result.Variables
}

func (t *TarpanManager) SetManager(manager *gosnmp.GoSNMP) {
	t.snmp = manager
	return
}

func (t *TarpanManager) SetParams(p map[string]string) {
	if value, ok := p["target"]; ok {
		t.snmp.Target = value
	}
	if value, ok := p["port"]; ok {
		port, _ := strconv.ParseUint(value, 10, 16)
		t.snmp.Port = uint16(port)
	} else {
		t.snmp.Port = uint16(port)
	}
	if value, ok := p["community"]; ok {
		t.snmp.Community = value
	}
	if value, ok := p["version"]; ok {
		if value == "2c" {
			t.snmp.Version = gosnmp.Version2c
		}
	}
	if value, ok := p["timeout"]; ok {
		sec, _ := strconv.Atoi(value)
		t.snmp.Timeout = time.Duration(sec) * time.Second
	} else {
		t.snmp.Timeout = time.Duration(timeout) * time.Second
	}
	if value, ok := p["retries"]; ok {
		retries, _ := strconv.Atoi(value)
		t.snmp.Retries = retries
	} else {
		t.snmp.Retries = retry

	}

	return
}

func makeRequestBody(ds *DataSet, idx int) (map[string]string, error) {
	address := ""
	err := validateIP(ds.Targets[idx].Address)
	if err == nil {
		address = ds.Targets[idx].Address
	} else {
		return map[string]string{}, err
	}
	community := ds.Targets[idx].Community
	if community == "" {
		community = ds.Default.Community
	}
	version := ds.Targets[idx].Version
	if version == "" {
		version = ds.Default.Version
	}
	request_body := map[string]string{
		"target":    address,
		"community": community,
		"version":   version,
	}

	return request_body, err
}

func makeChannel(result_buffer_length int) *Channels {
	channel := &Channels{
		semaphoe: make(chan int, ConcurrentProcesses),
		results:  make(chan SnmpResult, result_buffer_length),
	}

	return channel
}

func makeTarpanResult(c *Channels) []*TarpanResult {
	var tarpanResults []*TarpanResult
	var varbinds []VarBind
	var result SnmpResult
	length := len(c.results)
	for i := 0; i < length; i++ {
		varbinds = []VarBind{}
		result = <-c.results
		for _, val := range result.results {
			for _, o := range result.target.OIDs {
				n := strings.TrimLeft(val.Name, ".")
				if o.OID == n {
					v := VarBind{
						Description: o.Description,
						OID:         val.Name,
						Type:        val.Type,
						Value:       val.Value,
						Time:        result.time,
					}
					varbinds = append(varbinds, v)
					break
				}
			}
		}
		tr := &TarpanResult{
			Name:      result.target.Name,
			Address:   result.target.Address,
			Port:      result.target.Port,
			Version:   result.target.Version,
			Community: result.target.Community,
			VarBinds:  varbinds,
		}
		tarpanResults = append(tarpanResults, tr)
	}

	return tarpanResults
}

func Collect(dataset *DataSet) []*TarpanResult {
	var waitGroup sync.WaitGroup
	var tm TarpanManager
	var channels *Channels
	var oids []string

	channels = makeChannel(len(dataset.Targets))
	for index := range dataset.Targets {
		tm = TarpanManager{}
		tm.SetManager(new(gosnmp.GoSNMP))

		// TODO: split oid slice according to PDU size
		oids = []string{}
		for oid_idx := range dataset.Targets[index].OIDs {
			oids = append(oids, dataset.Targets[index].OIDs[oid_idx].OID)
		}

		waitGroup.Add(1)
		go func(ds *DataSet, idx int, o []string, c *Channels) {
			c.semaphoe <- 0
			req_body, req_body_err := makeRequestBody(ds, idx)
			if req_body_err != nil {
				log.Print(req_body_err)
				<-c.semaphoe
				return
			}
			t := time.Now()
			results := tm.Get(req_body, o)
			ret := SnmpResult{
				target:  ds.Targets[idx],
				results: results,
				time:    t.Unix(),
			}
			c.results <- ret
			<-c.semaphoe
			waitGroup.Done()
		}(dataset, index, oids, channels)
	}
	waitGroup.Wait()
	tr := makeTarpanResult(channels)

	return tr
}

func Run(target string) (int, error) {
	var err error

	// Load targets
	dataset, loadErr := loadConfig(target)
	if loadErr != nil {
		return ExitCodeConfError, loadErr
	}

	// collect data
	tr := Collect(dataset)

	// output
	Write("aa", tr)

	return ExitCodeOK, err
}
<commit_msg>manager list<commit_after>package tarpan

import (
	"log"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/soniah/gosnmp"
)

// Tarpan constants
const (
	ConcurrentProcesses = 5
)

// Exit code
const (
	ExitCodeOK = iota
	ExitCodeConfError
	ExitCodeParseFlagError
)

// SNMP constants
const (
	community = "public"
	port      = 161
	timeout   = 2
	retry     = 3
	//MaximumPDUBytes = 512
)

// JSON structure definition
type DataSet struct {
	Default Defaults `json:"defaults"`
	Targets []Target `json:"targets"`
}

type Defaults struct {
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
}

type Target struct {
	Name      string `json:"name"`
	Address   string `json:"address"`
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
	OIDs      []OID  `json:"oids"`
}

type OID struct {
	OID         string `json:"oid"`
	Description string `json:"description"`
}

// Tarpan result structures
type TarpanResult struct {
	Name      string    `json:"name"`
	Address   string    `json:"address"`
	Port      uint16    `json:"port"`
	Version   string    `json:"version"`
	Community string    `json:"community"`
	VarBinds  []VarBind `json:"varbinds"`
}

type VarBind struct {
	Description string         `json:"description"`
	OID         string         `json:"oid"`
	Type        gosnmp.Asn1BER `json:"type"`
	Value       interface{}    `json:"value"`
	Time        int64          `json:"time"`
}

type Tarpan interface {
	makeRequestBody()
	SetManager()
	SetParams()
	Get(params map[string]string, oids []string) []gosnmp.SnmpPDU
	Run()
}

type TarpanManager struct {
	snmp *gosnmp.GoSNMP
}

type SnmpResult struct {
	target  Target
	results []gosnmp.SnmpPDU
	time    int64
}

type Channels struct {
	semaphoe chan int
	results  chan SnmpResult
}

func (t *TarpanManager) Get(params map[string]string,
	oids []string) []gosnmp.SnmpPDU {
	t.SetParams(params)
	connection_err := t.snmp.Connect()
	if connection_err != nil {
		log.Fatalf("Connection error: %")
	}
	result, request_err := t.snmp.Get(oids)
	if request_err != nil {
		log.Println("Get() error: %v", request_err)
	}
	t.snmp.Conn.Close()

	return result.Variables
}

func (t *TarpanManager) SetManager(manager *gosnmp.GoSNMP) {
	t.snmp = manager
	return
}

func (t *TarpanManager) SetParams(p map[string]string) {
	if value, ok := p["target"]; ok {
		t.snmp.Target = value
	}
	if value, ok := p["port"]; ok {
		port, _ := strconv.ParseUint(value, 10, 16)
		t.snmp.Port = uint16(port)
	} else {
		t.snmp.Port = uint16(port)
	}
	if value, ok := p["community"]; ok {
		t.snmp.Community = value
	}
	if value, ok := p["version"]; ok {
		if value == "2c" {
			t.snmp.Version = gosnmp.Version2c
		}
	}
	if value, ok := p["timeout"]; ok {
		sec, _ := strconv.Atoi(value)
		t.snmp.Timeout = time.Duration(sec) * time.Second
	} else {
		t.snmp.Timeout = time.Duration(timeout) * time.Second
	}
	if value, ok := p["retries"]; ok {
		retries, _ := strconv.Atoi(value)
		t.snmp.Retries = retries
	} else {
		t.snmp.Retries = retry

	}

	return
}

func makeRequestBody(ds *DataSet, idx int) (map[string]string, error) {
	address := ""
	err := validateIP(ds.Targets[idx].Address)
	if err == nil {
		address = ds.Targets[idx].Address
	} else {
		return map[string]string{}, err
	}
	community := ds.Targets[idx].Community
	if community == "" {
		community = ds.Default.Community
	}
	version := ds.Targets[idx].Version
	if version == "" {
		version = ds.Default.Version
	}
	request_body := map[string]string{
		"target":    address,
		"community": community,
		"version":   version,
	}

	return request_body, err
}

func makeChannel(result_buffer_length int) *Channels {
	channel := &Channels{
		semaphoe: make(chan int, ConcurrentProcesses),
		results:  make(chan SnmpResult, result_buffer_length),
	}

	return channel
}

func makeTarpanResult(c *Channels) []*TarpanResult {
	var tarpanResults []*TarpanResult
	var varbinds []VarBind
	var result SnmpResult
	length := len(c.results)
	for i := 0; i < length; i++ {
		varbinds = []VarBind{}
		result = <-c.results
		for _, val := range result.results {
			for _, o := range result.target.OIDs {
				n := strings.TrimLeft(val.Name, ".")
				if o.OID == n {
					v := VarBind{
						Description: o.Description,
						OID:         val.Name,
						Type:        val.Type,
						Value:       val.Value,
						Time:        result.time,
					}
					varbinds = append(varbinds, v)
					break
				}
			}
		}
		tr := &TarpanResult{
			Name:      result.target.Name,
			Address:   result.target.Address,
			Port:      result.target.Port,
			Version:   result.target.Version,
			Community: result.target.Community,
			VarBinds:  varbinds,
		}
		tarpanResults = append(tarpanResults, tr)
	}

	return tarpanResults
}

func Collect(dataset *DataSet) []*TarpanResult {
	var waitGroup sync.WaitGroup
	var managers []TarpanManager
	var tm TarpanManager
	var channels *Channels
	var oids []string

	channels = makeChannel(len(dataset.Targets))
	for index := range dataset.Targets {
		tm = TarpanManager{}
		tm.SetManager(new(gosnmp.GoSNMP))
		managers = append(managers, tm)

		// TODO: split oid slice according to PDU size
		oids = []string{}
		for oid_idx := range dataset.Targets[index].OIDs {
			oids = append(oids, dataset.Targets[index].OIDs[oid_idx].OID)
		}

		waitGroup.Add(1)
		go func(ds *DataSet, idx int, o []string, c *Channels) {
			c.semaphoe <- 0
			req_body, req_body_err := makeRequestBody(ds, idx)
			if req_body_err != nil {
				log.Print(req_body_err)
				<-c.semaphoe
				return
			}
			t := time.Now()
			//results := tm.Get(req_body, o)
			results := managers[index].Get(req_body, o)
			ret := SnmpResult{
				target:  ds.Targets[idx],
				results: results,
				time:    t.Unix(),
			}
			c.results <- ret
			<-c.semaphoe
			waitGroup.Done()
		}(dataset, index, oids, channels)
	}
	waitGroup.Wait()
	tr := makeTarpanResult(channels)

	return tr
}

func Run(target string) (int, error) {
	var err error

	// Load targets
	dataset, loadErr := loadConfig(target)
	if loadErr != nil {
		return ExitCodeConfError, loadErr
	}

	// collect data
	tr := Collect(dataset)

	// output
	Write("aa", tr)

	return ExitCodeOK, err
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/hawx/alexandria/data"
	"github.com/hawx/alexandria/web/assets"
	"github.com/hawx/alexandria/web/events"
	"github.com/hawx/alexandria/web/filters"
	"github.com/hawx/alexandria/web/handlers"
	"github.com/hawx/alexandria/web/persona"

	"github.com/BurntSushi/toml"
	"github.com/gorilla/context"
	"github.com/gorilla/mux"

	"flag"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
)

var (
	settingsPath = flag.String("settings", "./settings.toml", "")
	port         = flag.String("port", "8080", "")
	socket       = flag.String("socket", "", "")
)

func main() {
	flag.Parse()

	var conf struct {
		Users     []string
		Secret    string
		Audience  string
		DbPath    string `toml:"database"`
		BooksPath string `toml:"library"`
	}
	if _, err := toml.DecodeFile(*settingsPath, &conf); err != nil {
		log.Fatal("toml:", err)
	}

	store := persona.NewStore(conf.Secret)
	persona := persona.New(store, conf.Audience, conf.Users)

	db := data.Open(conf.DbPath)
	defer db.Close()

	es := events.New()
	defer es.Close()

	r := mux.NewRouter()

	r.Path("/").Methods("GET").Handler(persona.Switch(handlers.List(true), handlers.List(false)))

	booksHandler := handlers.Books(db, es)
	r.Path("/books").Methods("GET").Handler(persona.Protect(booksHandler.GetAll))
	r.Path("/books/{id}").Methods("GET").Handler(persona.Protect(booksHandler.Get))
	r.Path("/books/{id}").Methods("PATCH").Handler(persona.Protect(booksHandler.Update))
	r.Path("/books/{id}").Methods("DELETE").Handler(persona.Protect(booksHandler.Delete))

	editionsHandler := handlers.Editions(db)
	r.Path("/editions/{id}").Methods("GET").Handler(persona.Protect(editionsHandler.Get))

	uploadHandler := handlers.Upload(db, es, conf.BooksPath)
	r.Path("/upload").Methods("POST").Handler(persona.Protect(uploadHandler.Upload))

	r.Path("/sign-in").Methods("POST").Handler(persona.SignIn)
	r.Path("/sign-out").Methods("GET").Handler(persona.SignOut)

	http.Handle("/", r)
	http.Handle("/events", es)
	http.Handle("/assets/", http.StripPrefix("/assets/", assets.Server(map[string]string{
		"main.js":        assets.MainJs,
		"mustache.js":    assets.MustacheJs,
		"tablesorter.js": assets.TablesorterJs,
		"tablefilter.js": assets.TablefilterJs,
		"styles.css":     assets.StylesCss,
	})))

	mux := context.ClearHandler(filters.Log(http.DefaultServeMux))
	if *socket == "" {
		go func() {
			log.Print("listening on :" + *port)
			log.Fatal(http.ListenAndServe(":"+*port, mux))
		}()

	} else {
		l, err := net.Listen("unix", *socket)
		if err != nil {
			log.Fatal(err)
		}

		defer l.Close()

		go func() {
			log.Println("listening on", *socket)
			log.Fatal(http.Serve(l, mux))
		}()
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	s := <-c
	log.Printf("caught %s: shutting down", s)
}
<commit_msg>Use new hawx/serve and hawx/persona packages<commit_after>package main

import (
	"github.com/hawx/alexandria/data"
	"github.com/hawx/alexandria/web/assets"
	"github.com/hawx/alexandria/web/events"
	"github.com/hawx/alexandria/web/filters"
	"github.com/hawx/alexandria/web/handlers"

	"github.com/BurntSushi/toml"
	"github.com/gorilla/context"
	"github.com/gorilla/mux"
	"github.com/hawx/persona"
	"github.com/hawx/serve"

	"flag"
	"log"
	"net/http"
)

var (
	settingsPath = flag.String("settings", "./settings.toml", "")
	port         = flag.String("port", "8080", "")
	socket       = flag.String("socket", "", "")
)

func main() {
	flag.Parse()

	var conf struct {
		Users     []string
		Secret    string
		Audience  string
		DbPath    string `toml:"database"`
		BooksPath string `toml:"library"`
	}
	if _, err := toml.DecodeFile(*settingsPath, &conf); err != nil {
		log.Fatal("toml:", err)
	}

	store := persona.NewStore(conf.Secret)
	persona := persona.New(store, conf.Audience, conf.Users)

	db := data.Open(conf.DbPath)
	defer db.Close()

	es := events.New()
	defer es.Close()

	r := mux.NewRouter()

	r.Path("/").Methods("GET").Handler(persona.Switch(handlers.List(true), handlers.List(false)))

	booksHandler := handlers.Books(db, es)
	r.Path("/books").Methods("GET").Handler(persona.Protect(booksHandler.GetAll))
	r.Path("/books/{id}").Methods("GET").Handler(persona.Protect(booksHandler.Get))
	r.Path("/books/{id}").Methods("PATCH").Handler(persona.Protect(booksHandler.Update))
	r.Path("/books/{id}").Methods("DELETE").Handler(persona.Protect(booksHandler.Delete))

	editionsHandler := handlers.Editions(db)
	r.Path("/editions/{id}").Methods("GET").Handler(persona.Protect(editionsHandler.Get))

	uploadHandler := handlers.Upload(db, es, conf.BooksPath)
	r.Path("/upload").Methods("POST").Handler(persona.Protect(uploadHandler.Upload))

	r.Path("/sign-in").Methods("POST").Handler(persona.SignIn)
	r.Path("/sign-out").Methods("GET").Handler(persona.SignOut)

	http.Handle("/", r)
	http.Handle("/events", es)
	http.Handle("/assets/", http.StripPrefix("/assets/", assets.Server(map[string]string{
		"main.js":        assets.MainJs,
		"mustache.js":    assets.MustacheJs,
		"tablesorter.js": assets.TablesorterJs,
		"tablefilter.js": assets.TablefilterJs,
		"styles.css":     assets.StylesCss,
	})))

	serve.Serve(*port, *socket, context.ClearHandler(filters.Log(http.DefaultServeMux)))
}
<|endoftext|>


<commit_before>package metrics

import (
	"fmt"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/rcrowley/go-metrics"
	"strings"
	"time"
)

// PrometheusConfig provides a container with config parameters for the
// Prometheus Exporter

type PrometheusConfig struct {
	namespace     string
	Registry      metrics.Registry // Registry to be exported
	subsystem     string
	promRegistry  prometheus.Registerer //Prometheus registry
	FlushInterval time.Duration         //interval to update prom metrics
	gauges        map[string]prometheus.Gauge
}

// NewPrometheusProvider returns a Provider that produces Prometheus metrics.
// Namespace and subsystem are applied to all produced metrics.
func NewPrometheusProvider(r metrics.Registry, namespace string, subsystem string, promRegistry prometheus.Registerer, FlushInterval time.Duration) *PrometheusConfig {
	return &PrometheusConfig{
		namespace:     namespace,
		subsystem:     subsystem,
		Registry:      r,
		promRegistry:  promRegistry,
		FlushInterval: FlushInterval,
		gauges:        make(map[string]prometheus.Gauge),
	}
}

func (c *PrometheusConfig) flattenKey(key string) string {
	key = strings.Replace(key, " ", "_", -1)
	key = strings.Replace(key, ".", "_", -1)
	key = strings.Replace(key, "-", "_", -1)
	key = strings.Replace(key, "=", "_", -1)
	return key
}

func (c *PrometheusConfig) gaugeFromNameAndValue(name string, val float64) {
	key := fmt.Sprintf("%s_%s_%s", c.namespace, c.subsystem, name)
	g, ok := c.gauges[key]
	if !ok {
		g = prometheus.NewGauge(prometheus.GaugeOpts{
			Namespace: c.flattenKey(c.namespace),
			Subsystem: c.flattenKey(c.subsystem),
			Name:      c.flattenKey(name),
			Help:      name,
		})
		c.promRegistry.MustRegister(g)
		c.gauges[key] = g
	}
	g.Set(val)
}
func (c *PrometheusConfig) UpdatePrometheusMetrics() {
	for _ = range time.Tick(c.FlushInterval) {
		c.UpdatePrometheusMetricsOnce()
	}
}

func (c *PrometheusConfig) UpdatePrometheusMetricsOnce() error {
	c.Registry.Each(func(name string, i interface{}) {
		switch metric := i.(type) {
		case metrics.Counter:
			c.gaugeFromNameAndValue(name, float64(metric.Count()))
		case metrics.Gauge:
		case metrics.GaugeFloat64:
			c.gaugeFromNameAndValue(name, float64(metric.Value()))
		case metrics.Histogram:
			samples := metric.Snapshot().Sample().Values()
			lastSample := samples[len(samples)-1]
			c.gaugeFromNameAndValue(name, float64(lastSample))
		case metrics.Meter:
		case metrics.Timer:
			lastSample := metric.Snapshot().Rate1()
			c.gaugeFromNameAndValue(name, float64(lastSample))
		}
	})
	return nil
}
<commit_msg>Change package name<commit_after>package prometheusmetrics

import (
	"fmt"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/rcrowley/go-metrics"
	"strings"
	"time"
)

// PrometheusConfig provides a container with config parameters for the
// Prometheus Exporter

type PrometheusConfig struct {
	namespace     string
	Registry      metrics.Registry // Registry to be exported
	subsystem     string
	promRegistry  prometheus.Registerer //Prometheus registry
	FlushInterval time.Duration         //interval to update prom metrics
	gauges        map[string]prometheus.Gauge
}

// NewPrometheusProvider returns a Provider that produces Prometheus metrics.
// Namespace and subsystem are applied to all produced metrics.
func NewPrometheusProvider(r metrics.Registry, namespace string, subsystem string, promRegistry prometheus.Registerer, FlushInterval time.Duration) *PrometheusConfig {
	return &PrometheusConfig{
		namespace:     namespace,
		subsystem:     subsystem,
		Registry:      r,
		promRegistry:  promRegistry,
		FlushInterval: FlushInterval,
		gauges:        make(map[string]prometheus.Gauge),
	}
}

func (c *PrometheusConfig) flattenKey(key string) string {
	key = strings.Replace(key, " ", "_", -1)
	key = strings.Replace(key, ".", "_", -1)
	key = strings.Replace(key, "-", "_", -1)
	key = strings.Replace(key, "=", "_", -1)
	return key
}

func (c *PrometheusConfig) gaugeFromNameAndValue(name string, val float64) {
	key := fmt.Sprintf("%s_%s_%s", c.namespace, c.subsystem, name)
	g, ok := c.gauges[key]
	if !ok {
		g = prometheus.NewGauge(prometheus.GaugeOpts{
			Namespace: c.flattenKey(c.namespace),
			Subsystem: c.flattenKey(c.subsystem),
			Name:      c.flattenKey(name),
			Help:      name,
		})
		c.promRegistry.MustRegister(g)
		c.gauges[key] = g
	}
	g.Set(val)
}
func (c *PrometheusConfig) UpdatePrometheusMetrics() {
	for _ = range time.Tick(c.FlushInterval) {
		c.UpdatePrometheusMetricsOnce()
	}
}

func (c *PrometheusConfig) UpdatePrometheusMetricsOnce() error {
	c.Registry.Each(func(name string, i interface{}) {
		switch metric := i.(type) {
		case metrics.Counter:
			c.gaugeFromNameAndValue(name, float64(metric.Count()))
		case metrics.Gauge:
		case metrics.GaugeFloat64:
			c.gaugeFromNameAndValue(name, float64(metric.Value()))
		case metrics.Histogram:
			samples := metric.Snapshot().Sample().Values()
			lastSample := samples[len(samples)-1]
			c.gaugeFromNameAndValue(name, float64(lastSample))
		case metrics.Meter:
		case metrics.Timer:
			lastSample := metric.Snapshot().Rate1()
			c.gaugeFromNameAndValue(name, float64(lastSample))
		}
	})
	return nil
}
<|endoftext|>