<commit_before>/*
Copyright 2018 The Jetstack cert-manager contributors.

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 kube

import (
	"crypto"
	"crypto/x509"
	"fmt"

	api "k8s.io/api/core/v1"
	corelisters "k8s.io/client-go/listers/core/v1"

	"github.com/jetstack/cert-manager/pkg/util/errors"
	"github.com/jetstack/cert-manager/pkg/util/pki"
)

// SecretTLSKeyRef will decode a PKCS1/SEC1 (in effect, a RSA or ECDSA) private key stored in a
// secret with 'name' in 'namespace'. It will read the private key data from the secret
// entry with name 'keyName'.
func SecretTLSKeyRef(secretLister corelisters.SecretLister, namespace, name, keyName string) (crypto.Signer, error) {
	secret, err := secretLister.Secrets(namespace).Get(name)
	if err != nil {
		return nil, err
	}

	keyBytes, ok := secret.Data[keyName]
	if !ok {
		return nil, fmt.Errorf("no data for %q in secret '%s/%s'", keyName, namespace, name)
	}
	key, err := pki.DecodePrivateKeyBytes(keyBytes)
	if err != nil {
		return key, errors.NewInvalidData(err.Error())
	}

	return key, nil
}

// SecretTLSKey will decode a PKCS1/SEC1 (in effect, a RSA or ECDSA) private key stored in a
// secret with 'name' in 'namespace'. It will read the private key data from the secret
// entry with name 'keyName'.
func SecretTLSKey(secretLister corelisters.SecretLister, namespace, name string) (crypto.Signer, error) {
	return SecretTLSKeyRef(secretLister, namespace, name, api.TLSPrivateKeyKey)
}

func SecretTLSCert(secretLister corelisters.SecretLister, namespace, name string) (*x509.Certificate, error) {
	secret, err := secretLister.Secrets(namespace).Get(name)
	if err != nil {
		return nil, err
	}

	certBytes, ok := secret.Data[api.TLSCertKey]
	if !ok {
		return nil, fmt.Errorf("no data for %q in secret '%s/%s'", api.TLSCertKey, namespace, name)
	}
	cert, err := pki.DecodeX509CertificateBytes(certBytes)
	if err != nil {
		return cert, errors.NewInvalidData(err.Error())
	}

	return cert, nil
}

func SecretTLSKeyPair(secretLister corelisters.SecretLister, namespace, name string) (*x509.Certificate, crypto.Signer, error) {
	secret, err := secretLister.Secrets(namespace).Get(name)
	if err != nil {
		return nil, nil, err
	}

	keyBytes, ok := secret.Data[api.TLSPrivateKeyKey]
	if !ok {
		return nil, nil, fmt.Errorf("no private key data for %q in secret '%s/%s'", api.TLSCertKey, namespace, name)
	}
	key, err := pki.DecodePrivateKeyBytes(keyBytes)
	if err != nil {
		return nil, nil, errors.NewInvalidData(err.Error())
	}

	certBytes, ok := secret.Data[api.TLSCertKey]
	if !ok {
		return nil, key, fmt.Errorf("no certificate data for %q in secret '%s/%s'", api.TLSCertKey, namespace, name)
	}
	cert, err := pki.DecodeX509CertificateBytes(certBytes)
	if err != nil {
		return nil, key, errors.NewInvalidData(err.Error())
	}

	return cert, key, nil
}
<commit_msg>Wrap missing secret data errors with Invalid<commit_after>/*
Copyright 2018 The Jetstack cert-manager contributors.

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 kube

import (
	"crypto"
	"crypto/x509"
	"fmt"

	api "k8s.io/api/core/v1"
	corelisters "k8s.io/client-go/listers/core/v1"

	"github.com/jetstack/cert-manager/pkg/util/errors"
	"github.com/jetstack/cert-manager/pkg/util/pki"
)

// SecretTLSKeyRef will decode a PKCS1/SEC1 (in effect, a RSA or ECDSA) private key stored in a
// secret with 'name' in 'namespace'. It will read the private key data from the secret
// entry with name 'keyName'.
func SecretTLSKeyRef(secretLister corelisters.SecretLister, namespace, name, keyName string) (crypto.Signer, error) {
	secret, err := secretLister.Secrets(namespace).Get(name)
	if err != nil {
		return nil, err
	}

	keyBytes, ok := secret.Data[keyName]
	if !ok {
		return nil, fmt.Errorf("no data for %q in secret '%s/%s'", keyName, namespace, name)
	}
	key, err := pki.DecodePrivateKeyBytes(keyBytes)
	if err != nil {
		return key, errors.NewInvalidData(err.Error())
	}

	return key, nil
}

// SecretTLSKey will decode a PKCS1/SEC1 (in effect, a RSA or ECDSA) private key stored in a
// secret with 'name' in 'namespace'. It will read the private key data from the secret
// entry with name 'keyName'.
func SecretTLSKey(secretLister corelisters.SecretLister, namespace, name string) (crypto.Signer, error) {
	return SecretTLSKeyRef(secretLister, namespace, name, api.TLSPrivateKeyKey)
}

func SecretTLSCert(secretLister corelisters.SecretLister, namespace, name string) (*x509.Certificate, error) {
	secret, err := secretLister.Secrets(namespace).Get(name)
	if err != nil {
		return nil, err
	}

	certBytes, ok := secret.Data[api.TLSCertKey]
	if !ok {
		return nil, fmt.Errorf("no data for %q in secret '%s/%s'", api.TLSCertKey, namespace, name)
	}
	cert, err := pki.DecodeX509CertificateBytes(certBytes)
	if err != nil {
		return cert, errors.NewInvalidData(err.Error())
	}

	return cert, nil
}

func SecretTLSKeyPair(secretLister corelisters.SecretLister, namespace, name string) (*x509.Certificate, crypto.Signer, error) {
	secret, err := secretLister.Secrets(namespace).Get(name)
	if err != nil {
		return nil, nil, err
	}

	keyBytes, ok := secret.Data[api.TLSPrivateKeyKey]
	if !ok {
		return nil, nil, errors.NewInvalidData("no private key data for %q in secret '%s/%s'", api.TLSCertKey, namespace, name)
	}
	key, err := pki.DecodePrivateKeyBytes(keyBytes)
	if err != nil {
		return nil, nil, errors.NewInvalidData(err.Error())
	}

	certBytes, ok := secret.Data[api.TLSCertKey]
	if !ok {
		return nil, key, errors.NewInvalidData("no certificate data for %q in secret '%s/%s'", api.TLSCertKey, namespace, name)
	}
	cert, err := pki.DecodeX509CertificateBytes(certBytes)
	if err != nil {
		return nil, key, errors.NewInvalidData(err.Error())
	}

	return cert, key, nil
}
<|endoftext|>


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

package visitors

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"

	"github.com/linuxboot/fiano/pkg/guid"
	"github.com/linuxboot/fiano/pkg/uefi"
)

// FindPredicate is used to filter matches in the Find visitor.
type FindPredicate = func(f uefi.Firmware) bool

// Find a firmware file given its name or GUID.
type Find struct {
	// Input
	// Only when this functions returns true will the file appear in the
	// `Matches` slice.
	Predicate FindPredicate

	// Output
	Matches []uefi.Firmware

	// JSON is written to this writer.
	W io.Writer

	// Private
	currentFile *uefi.File
}

// Run wraps Visit and performs some setup and teardown tasks.
func (v *Find) Run(f uefi.Firmware) error {
	if err := f.Apply(v); err != nil {
		return err
	}
	if v.W != nil {
		b, err := json.MarshalIndent(v.Matches, "", "\t")
		if err != nil {
			log.Fatal(err)
		}
		fmt.Fprintln(v.W, string(b))
	}
	return nil
}

// Visit applies the Find visitor to any Firmware type.
func (v *Find) Visit(f uefi.Firmware) error {
	switch f := f.(type) {

	case *uefi.File:
		// Clone the visitor so the `currentFile` is passed only to descendents.
		v2 := &Find{
			Predicate:   v.Predicate,
			currentFile: f,
		}

		if v.Predicate(f) {
			v.Matches = append(v.Matches, f)
			// Don't match with direct descendents.
			v2.currentFile = nil
		}

		err := f.ApplyChildren(v2)
		v.Matches = append(v.Matches, v2.Matches...) // Merge together
		return err

	case *uefi.Section:
		if v.currentFile != nil && v.Predicate(f) {
			v.Matches = append(v.Matches, v.currentFile)
			v.currentFile = nil // Do not double-match with a sibling if there are duplicate names.
		}
		return f.ApplyChildren(v)

	case *uefi.NVar:
		// don't find NVar embedded in NVar (TODO have a parameter for that ?)
		if v.Predicate(f) {
			v.Matches = append(v.Matches, f)
		}
		return nil

	default:
		if v.Predicate(f) {
			v.Matches = append(v.Matches, f)
		}
		return f.ApplyChildren(v)
	}
}

// FindFileGUIDPredicate is a generic predicate for searching file GUIDs only.
func FindFileGUIDPredicate(r guid.GUID) FindPredicate {
	return func(f uefi.Firmware) bool {
		if f, ok := f.(*uefi.File); ok {
			return f.Header.GUID == r
		}
		return false
	}
}

// FindFileTypePredicate is a generic predicate for searching file types only.
func FindFileTypePredicate(t uefi.FVFileType) FindPredicate {
	return func(f uefi.Firmware) bool {
		if f, ok := f.(*uefi.File); ok {
			return f.Header.Type == t
		}
		return false
	}
}

// FindFilePredicate is a generic predicate for searching files and UI sections only.
func FindFilePredicate(r string) (func(f uefi.Firmware) bool, error) {
	searchRE, err := regexp.Compile("^(" + r + ")$")
	if err != nil {
		return nil, err
	}
	ciRE, err := regexp.Compile("^(?i)(" + r + ")$")
	if err != nil {
		return nil, err
	}
	return func(f uefi.Firmware) bool {
		switch f := f.(type) {
		case *uefi.File:
			return ciRE.MatchString(f.Header.GUID.String())
		case *uefi.Section:
			return searchRE.MatchString(f.Name)
		}
		return false
	}, nil
}

// FindFileFVPredicate is a generic predicate for searching FVs, files and UI sections.
func FindFileFVPredicate(r string) (func(f uefi.Firmware) bool, error) {
	searchRE, err := regexp.Compile("^" + r + "$")
	if err != nil {
		return nil, err
	}
	ciRE, err := regexp.Compile("^(?i)" + r + "$")
	if err != nil {
		return nil, err
	}
	return func(f uefi.Firmware) bool {
		switch f := f.(type) {
		case *uefi.FirmwareVolume:
			return searchRE.MatchString(f.FVName.String())
		case *uefi.File:
			return ciRE.MatchString(f.Header.GUID.String())
		case *uefi.Section:
			return searchRE.MatchString(f.Name)
		}
		return false
	}, nil
}

// FindNotPredicate is a generic predicate which takes the logical NOT of an existing predicate.
func FindNotPredicate(predicate FindPredicate) FindPredicate {
	return func(f uefi.Firmware) bool {
		return !predicate(f)
	}
}

// FindAndPredicate is a generic predicate which takes the logical OR of two existing predicates.
func FindAndPredicate(predicate1 FindPredicate, predicate2 FindPredicate) FindPredicate {
	return func(f uefi.Firmware) bool {
		return predicate1(f) && predicate2(f)
	}
}

// FindExactlyOne does a find using a supplied predicate and errors if there's more than one.
func FindExactlyOne(f uefi.Firmware, pred func(f uefi.Firmware) bool) (uefi.Firmware, error) {
	find := &Find{
		Predicate: pred,
	}
	if err := find.Run(f); err != nil {
		return nil, err
	}
	// There should only be one match, there should only be one Dxe Core.
	if mlen := len(find.Matches); mlen != 1 {
		return nil, fmt.Errorf("expected exactly one match, got %v, matches were: %v", mlen, find.Matches)
	}
	return find.Matches[0], nil
}

// FindEnclosingFV finds the FV that contains a file.
func FindEnclosingFV(f uefi.Firmware, file *uefi.File) (*uefi.FirmwareVolume, error) {
	pred := func(f uefi.Firmware) bool {
		switch f := f.(type) {
		case *uefi.FirmwareVolume:
			for _, v := range f.Files {
				if v == file {
					return true
				}
			}
		}
		return false
	}
	dxeFV, err := FindExactlyOne(f, pred)
	if err != nil {
		return nil, fmt.Errorf("unable to find DXE FV, got: %v", err)
	}
	// result must be a FV.
	fv, ok := dxeFV.(*uefi.FirmwareVolume)
	if !ok {
		return nil, fmt.Errorf("result was not a firmware volume! was type %T", dxeFV)
	}

	return fv, nil
}

// FindDXEFV is a helper function to quickly retrieve the firmware volume that contains the DxeCore.
func FindDXEFV(f uefi.Firmware) (*uefi.FirmwareVolume, error) {
	// We identify the Dxe Firmware Volume via the presence of the DxeCore
	// This will cause problems if there are multiple dxe volumes.
	pred := FindFileTypePredicate(uefi.FVFileTypeDXECore)
	dxeCore, err := FindExactlyOne(f, pred)
	if err != nil {
		return nil, fmt.Errorf("unable to find DXE Core, got: %v", err)
	}

	// result must be a File.
	file, ok := dxeCore.(*uefi.File)
	if !ok {
		return nil, fmt.Errorf("result was not a file! was type %T", file)
	}
	return FindEnclosingFV(f, file)
}

// FindNVarPredicate is a generic predicate for searching NVar only.
func FindNVarPredicate(r string) (func(f uefi.Firmware) bool, error) {
	searchRE, err := regexp.Compile("^(" + r + ")$")
	if err != nil {
		return nil, err
	}
	return func(f uefi.Firmware) bool {
		switch f := f.(type) {
		case *uefi.NVar:
			return searchRE.MatchString(f.Name)
		}
		return false
	}, nil
}

func init() {
	RegisterCLI("find", "find a file by GUID or Name", 1, func(args []string) (uefi.Visitor, error) {
		pred, err := FindFilePredicate(args[0])
		if err != nil {
			return nil, err
		}
		return &Find{
			Predicate: pred,
			W:         os.Stdout,
		}, nil
	})
	RegisterCLI("find_nvar", "find an NVAR by Name", 1, func(args []string) (uefi.Visitor, error) {
		pred, err := FindNVarPredicate(args[0])
		if err != nil {
			return nil, err
		}
		return &Find{
			Predicate: pred,
			W:         os.Stdout,
		}, nil
	})
}
<commit_msg>Firmware Volume 'Name' is a GUID so use the case insensitive match<commit_after>// Copyright 2018 the LinuxBoot Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package visitors

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"

	"github.com/linuxboot/fiano/pkg/guid"
	"github.com/linuxboot/fiano/pkg/uefi"
)

// FindPredicate is used to filter matches in the Find visitor.
type FindPredicate = func(f uefi.Firmware) bool

// Find a firmware file given its name or GUID.
type Find struct {
	// Input
	// Only when this functions returns true will the file appear in the
	// `Matches` slice.
	Predicate FindPredicate

	// Output
	Matches []uefi.Firmware

	// JSON is written to this writer.
	W io.Writer

	// Private
	currentFile *uefi.File
}

// Run wraps Visit and performs some setup and teardown tasks.
func (v *Find) Run(f uefi.Firmware) error {
	if err := f.Apply(v); err != nil {
		return err
	}
	if v.W != nil {
		b, err := json.MarshalIndent(v.Matches, "", "\t")
		if err != nil {
			log.Fatal(err)
		}
		fmt.Fprintln(v.W, string(b))
	}
	return nil
}

// Visit applies the Find visitor to any Firmware type.
func (v *Find) Visit(f uefi.Firmware) error {
	switch f := f.(type) {

	case *uefi.File:
		// Clone the visitor so the `currentFile` is passed only to descendents.
		v2 := &Find{
			Predicate:   v.Predicate,
			currentFile: f,
		}

		if v.Predicate(f) {
			v.Matches = append(v.Matches, f)
			// Don't match with direct descendents.
			v2.currentFile = nil
		}

		err := f.ApplyChildren(v2)
		v.Matches = append(v.Matches, v2.Matches...) // Merge together
		return err

	case *uefi.Section:
		if v.currentFile != nil && v.Predicate(f) {
			v.Matches = append(v.Matches, v.currentFile)
			v.currentFile = nil // Do not double-match with a sibling if there are duplicate names.
		}
		return f.ApplyChildren(v)

	case *uefi.NVar:
		// don't find NVar embedded in NVar (TODO have a parameter for that ?)
		if v.Predicate(f) {
			v.Matches = append(v.Matches, f)
		}
		return nil

	default:
		if v.Predicate(f) {
			v.Matches = append(v.Matches, f)
		}
		return f.ApplyChildren(v)
	}
}

// FindFileGUIDPredicate is a generic predicate for searching file GUIDs only.
func FindFileGUIDPredicate(r guid.GUID) FindPredicate {
	return func(f uefi.Firmware) bool {
		if f, ok := f.(*uefi.File); ok {
			return f.Header.GUID == r
		}
		return false
	}
}

// FindFileTypePredicate is a generic predicate for searching file types only.
func FindFileTypePredicate(t uefi.FVFileType) FindPredicate {
	return func(f uefi.Firmware) bool {
		if f, ok := f.(*uefi.File); ok {
			return f.Header.Type == t
		}
		return false
	}
}

// FindFilePredicate is a generic predicate for searching files and UI sections only.
func FindFilePredicate(r string) (func(f uefi.Firmware) bool, error) {
	searchRE, err := regexp.Compile("^(" + r + ")$")
	if err != nil {
		return nil, err
	}
	ciRE, err := regexp.Compile("^(?i)(" + r + ")$")
	if err != nil {
		return nil, err
	}
	return func(f uefi.Firmware) bool {
		switch f := f.(type) {
		case *uefi.File:
			return ciRE.MatchString(f.Header.GUID.String())
		case *uefi.Section:
			return searchRE.MatchString(f.Name)
		}
		return false
	}, nil
}

// FindFileFVPredicate is a generic predicate for searching FVs, files and UI sections.
func FindFileFVPredicate(r string) (func(f uefi.Firmware) bool, error) {
	searchRE, err := regexp.Compile("^" + r + "$")
	if err != nil {
		return nil, err
	}
	ciRE, err := regexp.Compile("^(?i)" + r + "$")
	if err != nil {
		return nil, err
	}
	return func(f uefi.Firmware) bool {
		switch f := f.(type) {
		case *uefi.FirmwareVolume:
			return ciRE.MatchString(f.FVName.String())
		case *uefi.File:
			return ciRE.MatchString(f.Header.GUID.String())
		case *uefi.Section:
			return searchRE.MatchString(f.Name)
		}
		return false
	}, nil
}

// FindNotPredicate is a generic predicate which takes the logical NOT of an existing predicate.
func FindNotPredicate(predicate FindPredicate) FindPredicate {
	return func(f uefi.Firmware) bool {
		return !predicate(f)
	}
}

// FindAndPredicate is a generic predicate which takes the logical OR of two existing predicates.
func FindAndPredicate(predicate1 FindPredicate, predicate2 FindPredicate) FindPredicate {
	return func(f uefi.Firmware) bool {
		return predicate1(f) && predicate2(f)
	}
}

// FindExactlyOne does a find using a supplied predicate and errors if there's more than one.
func FindExactlyOne(f uefi.Firmware, pred func(f uefi.Firmware) bool) (uefi.Firmware, error) {
	find := &Find{
		Predicate: pred,
	}
	if err := find.Run(f); err != nil {
		return nil, err
	}
	// There should only be one match, there should only be one Dxe Core.
	if mlen := len(find.Matches); mlen != 1 {
		return nil, fmt.Errorf("expected exactly one match, got %v, matches were: %v", mlen, find.Matches)
	}
	return find.Matches[0], nil
}

// FindEnclosingFV finds the FV that contains a file.
func FindEnclosingFV(f uefi.Firmware, file *uefi.File) (*uefi.FirmwareVolume, error) {
	pred := func(f uefi.Firmware) bool {
		switch f := f.(type) {
		case *uefi.FirmwareVolume:
			for _, v := range f.Files {
				if v == file {
					return true
				}
			}
		}
		return false
	}
	dxeFV, err := FindExactlyOne(f, pred)
	if err != nil {
		return nil, fmt.Errorf("unable to find DXE FV, got: %v", err)
	}
	// result must be a FV.
	fv, ok := dxeFV.(*uefi.FirmwareVolume)
	if !ok {
		return nil, fmt.Errorf("result was not a firmware volume! was type %T", dxeFV)
	}

	return fv, nil
}

// FindDXEFV is a helper function to quickly retrieve the firmware volume that contains the DxeCore.
func FindDXEFV(f uefi.Firmware) (*uefi.FirmwareVolume, error) {
	// We identify the Dxe Firmware Volume via the presence of the DxeCore
	// This will cause problems if there are multiple dxe volumes.
	pred := FindFileTypePredicate(uefi.FVFileTypeDXECore)
	dxeCore, err := FindExactlyOne(f, pred)
	if err != nil {
		return nil, fmt.Errorf("unable to find DXE Core, got: %v", err)
	}

	// result must be a File.
	file, ok := dxeCore.(*uefi.File)
	if !ok {
		return nil, fmt.Errorf("result was not a file! was type %T", file)
	}
	return FindEnclosingFV(f, file)
}

// FindNVarPredicate is a generic predicate for searching NVar only.
func FindNVarPredicate(r string) (func(f uefi.Firmware) bool, error) {
	searchRE, err := regexp.Compile("^(" + r + ")$")
	if err != nil {
		return nil, err
	}
	return func(f uefi.Firmware) bool {
		switch f := f.(type) {
		case *uefi.NVar:
			return searchRE.MatchString(f.Name)
		}
		return false
	}, nil
}

func init() {
	RegisterCLI("find", "find a file by GUID or Name", 1, func(args []string) (uefi.Visitor, error) {
		pred, err := FindFilePredicate(args[0])
		if err != nil {
			return nil, err
		}
		return &Find{
			Predicate: pred,
			W:         os.Stdout,
		}, nil
	})
	RegisterCLI("find_nvar", "find an NVAR by Name", 1, func(args []string) (uefi.Visitor, error) {
		pred, err := FindNVarPredicate(args[0])
		if err != nil {
			return nil, err
		}
		return &Find{
			Predicate: pred,
			W:         os.Stdout,
		}, nil
	})
}
<|endoftext|>


<commit_before>package gocouchbase

import "time"
import "fmt"
import "github.com/couchbase/gocouchbaseio"

type Cluster struct {
	manager *ClusterManager

	spec              connSpec
	connectionTimeout time.Duration
}

func Connect(connSpecStr string) (*Cluster, error) {
	spec := parseConnSpec(connSpecStr)
	if spec.Scheme == "" {
		spec.Scheme = "http"
	}
	if spec.Scheme != "couchbase" && spec.Scheme != "couchbases" && spec.Scheme != "http" {
		panic("Unsupported Scheme!")
	}
	cluster := &Cluster{
		spec:              spec,
		connectionTimeout: 10000 * time.Millisecond,
	}
	return cluster, nil
}

func (c *Cluster) OpenBucket(bucket, password string) (*Bucket, error) {
	var memdHosts []string
	var httpHosts []string
	isHttpHosts := c.spec.Scheme == "http"
	isSslHosts := c.spec.Scheme == "couchbases"
	for _, specHost := range c.spec.Hosts {
		if specHost.Port == 0 {
			if !isHttpHosts {
				if !isSslHosts {
					specHost.Port = 11210
				} else {
					specHost.Port = 11207
				}
			} else {
				panic("HTTP configuration not yet supported")
				//specHost.Port = 8091
			}
		}
		memdHosts = append(memdHosts, fmt.Sprintf("%s:%d", specHost.Host, specHost.Port))
	}

	authFn := func(srv gocouchbaseio.MemdAuthClient) error {
		fmt.Printf("Want to auth for %s\n", srv.Address())

		auths, err := srv.ListMechs()
		fmt.Printf("ListMechs said %v, %s\n", err, auths)

		// Build PLAIN auth data
		userBuf := []byte(bucket)
		passBuf := []byte(password)
		authData := make([]byte, 1+len(userBuf)+1+len(passBuf))
		authData[0] = 0
		copy(authData[1:], userBuf)
		authData[1+len(userBuf)] = 0
		copy(authData[1+len(userBuf)+1:], passBuf)

		// Execute PLAIN authentication
		authR, err := srv.Auth([]byte("PLAIN"), authData)
		fmt.Printf("SaslAuth said %v, %s\n", err, authR)

		return nil
	}
	cli, err := gocouchbaseio.CreateAgent(memdHosts, httpHosts, isSslHosts, authFn)
	if err != nil {
		return nil, err
	}

	return &Bucket{
		client: cli,
	}, nil
}

func (c *Cluster) Manager(username, password string) *ClusterManager {
	if c.manager == nil {
		c.manager = &ClusterManager{}
	}
	return c.manager
}
<commit_msg>SASL Authentication is ftw.<commit_after>package gocouchbase

import "time"
import "fmt"
import "github.com/couchbase/gocouchbaseio"

type Cluster struct {
	manager *ClusterManager

	spec              connSpec
	connectionTimeout time.Duration
}

func Connect(connSpecStr string) (*Cluster, error) {
	spec := parseConnSpec(connSpecStr)
	if spec.Scheme == "" {
		spec.Scheme = "http"
	}
	if spec.Scheme != "couchbase" && spec.Scheme != "couchbases" && spec.Scheme != "http" {
		panic("Unsupported Scheme!")
	}
	cluster := &Cluster{
		spec:              spec,
		connectionTimeout: 10000 * time.Millisecond,
	}
	return cluster, nil
}

func (c *Cluster) OpenBucket(bucket, password string) (*Bucket, error) {
	var memdHosts []string
	var httpHosts []string
	isHttpHosts := c.spec.Scheme == "http"
	isSslHosts := c.spec.Scheme == "couchbases"
	for _, specHost := range c.spec.Hosts {
		if specHost.Port == 0 {
			if !isHttpHosts {
				if !isSslHosts {
					specHost.Port = 11210
				} else {
					specHost.Port = 11207
				}
			} else {
				panic("HTTP configuration not yet supported")
				//specHost.Port = 8091
			}
		}
		memdHosts = append(memdHosts, fmt.Sprintf("%s:%d", specHost.Host, specHost.Port))
	}

	authFn := func(srv gocouchbaseio.MemdAuthClient) error {
		fmt.Printf("Want to auth for %s\n", srv.Address())

		// Build PLAIN auth data
		userBuf := []byte(bucket)
		passBuf := []byte(password)
		authData := make([]byte, 1+len(userBuf)+1+len(passBuf))
		authData[0] = 0
		copy(authData[1:], userBuf)
		authData[1+len(userBuf)] = 0
		copy(authData[1+len(userBuf)+1:], passBuf)

		// Execute PLAIN authentication
		authR, err := srv.SaslAuth([]byte("PLAIN"), authData)
		fmt.Printf("SaslAuth said %v, %s\n", err, authR)

		return nil
	}
	cli, err := gocouchbaseio.CreateAgent(memdHosts, httpHosts, isSslHosts, authFn)
	if err != nil {
		return nil, err
	}

	return &Bucket{
		client: cli,
	}, nil
}

func (c *Cluster) Manager(username, password string) *ClusterManager {
	if c.manager == nil {
		c.manager = &ClusterManager{}
	}
	return c.manager
}
<|endoftext|>


<commit_before>/*
	Package cmd provides a more domain-specific layer over exec.Cmd.
*/
package cmd

import (
	"io"
	"os"
	"os/exec"
	"syscall"
)

const (
	// Shell will have the command line passed to its `-c` option.
	Shell = "/bin/bash"
)

type Cmd struct {
	cmd        *exec.Cmd
	stderrPipe io.ReadCloser
	stdinPipe  io.WriteCloser
	stdoutPipe io.ReadCloser
}

// WaitResult is sent to the channel returned by WaitChan().
// It indicates the exit status, or a non-exit-status error e.g. IO error.
// In the case of a non-exit-status, Status is -1
type WaitResult struct {
	Status int
	Err    error
}

// NewCommand returns a Cmd with IO configured, but not started.
func NewCommand(shellCmd string) (cmd *Cmd, out <-chan []byte, err error) {
	cmd = &Cmd{}
	cmd.cmd = exec.Command(Shell, "-c", shellCmd)

	stdin, err := cmd.cmd.StdinPipe()
	if err == nil {
		cmd.stdinPipe = stdin
	} else {
		return
	}

	stdout, err := cmd.cmd.StdoutPipe()
	if err == nil {
		cmd.stdoutPipe = stdout
	} else {
		return
	}

	cmd.cmd.Stderr = os.Stderr
	cmd.stderrPipe = os.Stderr

	out = readerToChannel(cmd.stdoutPipe)
	return
}

// Start the process, write input to stdin, then close stdin.
func (c *Cmd) StartWithStdin(input []byte) (err error) {
	err = c.cmd.Start()
	if err != nil {
		return
	}
	_, err = c.stdinPipe.Write(input)
	if err != nil {
		return
	}
	c.stdinPipe.Close()
	return nil
}

// Terminate the process with SIGTERM.
// TODO: follow up with SIGKILL if still running.
func (c *Cmd) Terminate() (err error) {
	return c.cmd.Process.Signal(syscall.SIGTERM)
}

// Given a command, waits and sends the exit status over the returned channel.
func (cmd *Cmd) WaitChan() <-chan WaitResult {
	ch := make(chan WaitResult)
	go func() {
		err := cmd.cmd.Wait()
		if err == nil {
			ch <- WaitResult{0, nil}
		} else if e1, ok := err.(*exec.ExitError); ok {
			status := e1.Sys().(syscall.WaitStatus).ExitStatus()
			ch <- WaitResult{status, nil}
		} else {
			ch <- WaitResult{-1, err}
		}
	}()
	return ch
}

func readerToChannel(reader io.Reader) <-chan []byte {
	c := make(chan []byte)
	go func() {
		buf := make([]byte, 1024)
		for {
			n, err := reader.Read(buf)
			if n > 0 {
				res := make([]byte, n)
				copy(res, buf[:n])
				c <- res
			}
			if err != nil {
				close(c)
				break
			}
		}
	}()
	return c
}
<commit_msg>cmd.Cmd.WaitChan() doc improved.<commit_after>/*
	Package cmd provides a more domain-specific layer over exec.Cmd.
*/
package cmd

import (
	"io"
	"os"
	"os/exec"
	"syscall"
)

const (
	// Shell will have the command line passed to its `-c` option.
	Shell = "/bin/bash"
)

type Cmd struct {
	cmd        *exec.Cmd
	stderrPipe io.ReadCloser
	stdinPipe  io.WriteCloser
	stdoutPipe io.ReadCloser
}

// WaitResult is sent to the channel returned by WaitChan().
// It indicates the exit status, or a non-exit-status error e.g. IO error.
// In the case of a non-exit-status, Status is -1
type WaitResult struct {
	Status int
	Err    error
}

// NewCommand returns a Cmd with IO configured, but not started.
func NewCommand(shellCmd string) (cmd *Cmd, out <-chan []byte, err error) {
	cmd = &Cmd{}
	cmd.cmd = exec.Command(Shell, "-c", shellCmd)

	stdin, err := cmd.cmd.StdinPipe()
	if err == nil {
		cmd.stdinPipe = stdin
	} else {
		return
	}

	stdout, err := cmd.cmd.StdoutPipe()
	if err == nil {
		cmd.stdoutPipe = stdout
	} else {
		return
	}

	cmd.cmd.Stderr = os.Stderr
	cmd.stderrPipe = os.Stderr

	out = readerToChannel(cmd.stdoutPipe)
	return
}

// Start the process, write input to stdin, then close stdin.
func (c *Cmd) StartWithStdin(input []byte) (err error) {
	err = c.cmd.Start()
	if err != nil {
		return
	}
	_, err = c.stdinPipe.Write(input)
	if err != nil {
		return
	}
	c.stdinPipe.Close()
	return nil
}

// Terminate the process with SIGTERM.
// TODO: follow up with SIGKILL if still running.
func (c *Cmd) Terminate() (err error) {
	return c.cmd.Process.Signal(syscall.SIGTERM)
}

// WaitChan starts a goroutine to wait for the command to exit, and returns
// a channel over which will be sent the WaitResult, containing either the
// exit status (0 for success) or a non-exit error, e.g. IO error.
func (cmd *Cmd) WaitChan() <-chan WaitResult {
	ch := make(chan WaitResult)
	go func() {
		err := cmd.cmd.Wait()
		if err == nil {
			ch <- WaitResult{0, nil}
		} else if e1, ok := err.(*exec.ExitError); ok {
			status := e1.Sys().(syscall.WaitStatus).ExitStatus()
			ch <- WaitResult{status, nil}
		} else {
			ch <- WaitResult{-1, err}
		}
	}()
	return ch
}

func readerToChannel(reader io.Reader) <-chan []byte {
	c := make(chan []byte)
	go func() {
		buf := make([]byte, 1024)
		for {
			n, err := reader.Read(buf)
			if n > 0 {
				res := make([]byte, n)
				copy(res, buf[:n])
				c <- res
			}
			if err != nil {
				close(c)
				break
			}
		}
	}()
	return c
}
<|endoftext|>


<commit_before>package cmd

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"

	"github.com/kballard/go-shellquote"
	"github.com/robhurring/jit/utils"
)

func Copy(data string) (err error) {
	echo := New("echo").WithArgs(data)
	copy := New("pbcopy")
	_, _, err = Pipeline(echo, copy)
	return
}

func Open(location string) error {
	return New("open").WithArg(location).Run()
}

type Cmd struct {
	Name string
	Args []string
}

func (cmd Cmd) String() string {
	return fmt.Sprintf("%s %s", cmd.Name, strings.Join(cmd.Args, " "))
}

func (cmd *Cmd) WithArg(arg string) *Cmd {
	cmd.Args = append(cmd.Args, arg)

	return cmd
}

func (cmd *Cmd) WithArgs(args ...string) *Cmd {
	for _, arg := range args {
		cmd.WithArg(arg)
	}

	return cmd
}

func (cmd *Cmd) CombinedOutput() (string, error) {
	output, err := exec.Command(cmd.Name, cmd.Args...).CombinedOutput()

	return string(output), err
}

// Run runs command with `Exec` on platforms except Windows
// which only supports `Spawn`
func (cmd *Cmd) Run() error {
	if runtime.GOOS == "windows" {
		return cmd.Spawn()
	} else {
		return cmd.Exec()
	}
}

// Spawn runs command with spawn(3)
func (cmd *Cmd) Spawn() error {
	c := exec.Command(cmd.Name, cmd.Args...)
	c.Stdin = os.Stdin
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	return c.Run()
}

// Exec runs command with exec(3)
// Note that Windows doesn't support exec(3): http://golang.org/src/pkg/syscall/exec_windows.go#L339
func (cmd *Cmd) Exec() error {
	binary, err := exec.LookPath(cmd.Name)
	if err != nil {
		return fmt.Errorf("command not found: %s", cmd.Name)
	}

	args := []string{binary}
	args = append(args, cmd.Args...)

	return syscall.Exec(binary, args, os.Environ())
}

func Pipeline(list ...*Cmd) (pipeStdout, pipeStderr string, perr error) {
	// Require at least one command
	if len(list) < 1 {
		return "", "", nil
	}

	var newCmd *exec.Cmd
	cmds := make([]*exec.Cmd, 0, 4)

	// Convert into an exec.Cmd
	for _, cmd := range list {
		newCmd = exec.Command(cmd.Name, cmd.Args...)
		cmds = append(cmds, newCmd)
	}

	// Collect the output from the command(s)
	var output bytes.Buffer
	var stderr bytes.Buffer

	last := len(cmds) - 1
	for i, cmd := range cmds[:last] {
		var err error
		// Connect each command's stdin to the previous command's stdout
		if cmds[i+1].Stdin, err = cmd.StdoutPipe(); err != nil {
			return "", "", err
		}
		// Connect each command's stderr to a buffer
		cmd.Stderr = &stderr
	}

	// Connect the output and error for the last command
	cmds[last].Stdout, cmds[last].Stderr = &output, &stderr

	// Start each command
	for _, cmd := range cmds {
		if err := cmd.Start(); err != nil {
			return output.String(), stderr.String(), err
		}
	}

	// Wait for each command to complete
	for _, cmd := range cmds {
		if err := cmd.Wait(); err != nil {
			return output.String(), stderr.String(), err
		}
	}

	// Return the pipeline output and the collected standard error
	return output.String(), stderr.String(), nil
}

func New(cmd string) *Cmd {
	cmds, err := shellquote.Split(cmd)
	utils.Check(err)

	name := cmds[0]
	args := make([]string, 0)
	for _, arg := range cmds[1:] {
		args = append(args, arg)
	}
	return &Cmd{Name: name, Args: args}
}

func NewWithArray(cmd []string) *Cmd {
	return &Cmd{Name: cmd[0], Args: cmd[1:]}
}
<commit_msg>remove dep on utils<commit_after>package cmd

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"

	"github.com/kballard/go-shellquote"
)

func Copy(data string) (err error) {
	echo := New("echo").WithArgs(data)
	copy := New("pbcopy")
	_, _, err = Pipeline(echo, copy)
	return
}

func Open(location string) error {
	return New("open").WithArg(location).Run()
}

type Cmd struct {
	Name string
	Args []string
}

func (cmd Cmd) String() string {
	return fmt.Sprintf("%s %s", cmd.Name, strings.Join(cmd.Args, " "))
}

func (cmd *Cmd) WithArg(arg string) *Cmd {
	cmd.Args = append(cmd.Args, arg)

	return cmd
}

func (cmd *Cmd) WithArgs(args ...string) *Cmd {
	for _, arg := range args {
		cmd.WithArg(arg)
	}

	return cmd
}

func (cmd *Cmd) CombinedOutput() (string, error) {
	output, err := exec.Command(cmd.Name, cmd.Args...).CombinedOutput()

	return string(output), err
}

// Run runs command with `Exec` on platforms except Windows
// which only supports `Spawn`
func (cmd *Cmd) Run() error {
	if runtime.GOOS == "windows" {
		return cmd.Spawn()
	} else {
		return cmd.Exec()
	}
}

// Spawn runs command with spawn(3)
func (cmd *Cmd) Spawn() error {
	c := exec.Command(cmd.Name, cmd.Args...)
	c.Stdin = os.Stdin
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	return c.Run()
}

// Exec runs command with exec(3)
// Note that Windows doesn't support exec(3): http://golang.org/src/pkg/syscall/exec_windows.go#L339
func (cmd *Cmd) Exec() error {
	binary, err := exec.LookPath(cmd.Name)
	if err != nil {
		return fmt.Errorf("command not found: %s", cmd.Name)
	}

	args := []string{binary}
	args = append(args, cmd.Args...)

	return syscall.Exec(binary, args, os.Environ())
}

func Pipeline(list ...*Cmd) (pipeStdout, pipeStderr string, perr error) {
	// Require at least one command
	if len(list) < 1 {
		return "", "", nil
	}

	var newCmd *exec.Cmd
	cmds := make([]*exec.Cmd, 0, 4)

	// Convert into an exec.Cmd
	for _, cmd := range list {
		newCmd = exec.Command(cmd.Name, cmd.Args...)
		cmds = append(cmds, newCmd)
	}

	// Collect the output from the command(s)
	var output bytes.Buffer
	var stderr bytes.Buffer

	last := len(cmds) - 1
	for i, cmd := range cmds[:last] {
		var err error
		// Connect each command's stdin to the previous command's stdout
		if cmds[i+1].Stdin, err = cmd.StdoutPipe(); err != nil {
			return "", "", err
		}
		// Connect each command's stderr to a buffer
		cmd.Stderr = &stderr
	}

	// Connect the output and error for the last command
	cmds[last].Stdout, cmds[last].Stderr = &output, &stderr

	// Start each command
	for _, cmd := range cmds {
		if err := cmd.Start(); err != nil {
			return output.String(), stderr.String(), err
		}
	}

	// Wait for each command to complete
	for _, cmd := range cmds {
		if err := cmd.Wait(); err != nil {
			return output.String(), stderr.String(), err
		}
	}

	// Return the pipeline output and the collected standard error
	return output.String(), stderr.String(), nil
}

func New(cmd string) *Cmd {
	cmds, err := shellquote.Split(cmd)
	if err != nil {
		panic(err)
	}

	name := cmds[0]
	args := make([]string, 0)
	for _, arg := range cmds[1:] {
		args = append(args, arg)
	}
	return &Cmd{Name: name, Args: args}
}

func NewWithArray(cmd []string) *Cmd {
	return &Cmd{Name: cmd[0], Args: cmd[1:]}
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 Blacknon. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.

// This file describes the code of the built-in command used by lsftp.

package sftp

import (
	"fmt"
	"os"
	"path/filepath"
	"strconv"

	"github.com/blacknon/lssh/common"
	"github.com/urfave/cli"
)

// chmod
func (r *RunSftp) chmod(args []string) {
	// create app
	app := cli.NewApp()
	// app.UseShortOptionHandling = true

	// set help message
	app.CustomAppHelpTemplate = helptext
	app.Name = "chmod"
	app.Usage = "lsftp build-in command: chmod [remote machine chmod]"
	app.ArgsUsage = "[perm path]"
	app.HideHelp = true
	app.HideVersion = true
	app.EnableBashCompletion = true

	// action
	app.Action = func(c *cli.Context) error {
		if len(c.Args()) != 2 {
			fmt.Println("Requires two arguments")
			fmt.Println("chmod mode path")
			return nil
		}

		exit := make(chan bool)
		for s, cl := range r.Client {
			server := s
			client := cl

			mode := c.Args()[0]
			path := c.Args()[1]

			go func() {
				// get writer
				client.Output.Create(server)
				w := client.Output.NewWriter()

				// set arg path
				if !filepath.IsAbs(path) {
					path = filepath.Join(client.Pwd, path)
				}

				// get mode
				modeint, err := strconv.ParseUint(mode, 8, 32)
				if err != nil {
					fmt.Fprintf(w, "%s\n", err)
					exit <- true
					return
				}
				filemode := os.FileMode(modeint)

				// set filemode
				err = client.Connect.Chmod(path, filemode)
				if err != nil {
					fmt.Fprintf(w, "%s\n", err)
					exit <- true
					return
				}

				fmt.Fprintf(w, "chmod: set %s's permission as %o(%s)\n", path, filemode.Perm(), filemode.String())
				exit <- true
				return
			}()
		}

		for i := 0; i < len(r.Client); i++ {
			<-exit
		}

		return nil
	}

	// parse short options
	args = common.ParseArgs(app.Flags, args)
	app.Run(args)

	return
}
<commit_msg>update. lsftpのchmodで複数path+ホストの指定機能を追加<commit_after>// Copyright (c) 2021 Blacknon. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.

// This file describes the code of the built-in command used by lsftp.

package sftp

import (
	"fmt"
	"os"
	"path/filepath"
	"strconv"

	"github.com/blacknon/lssh/common"
	"github.com/urfave/cli"
)

// chmod
func (r *RunSftp) chmod(args []string) {
	// create app
	app := cli.NewApp()
	// app.UseShortOptionHandling = true

	// set help message
	app.CustomAppHelpTemplate = helptext
	app.Name = "chmod"
	app.Usage = "lsftp build-in command: chmod [remote machine chmod]"
	app.ArgsUsage = "[perm path]"
	app.HideHelp = true
	app.HideVersion = true
	app.EnableBashCompletion = true

	// action
	app.Action = func(c *cli.Context) error {
		if len(c.Args()) <= 1 {
			fmt.Println("Requires over two arguments")
			fmt.Println("chmod mode path...")
			return nil
		}

		mode := c.Args()[0]
		pathlist := c.Args()[1:]

		targetmap := map[string]*TargetConnectMap{}
		for _, p := range pathlist {
			targetmap = r.createTargetMap(targetmap, p)
		}

		exit := make(chan bool)
		for s, cl := range targetmap {
			server := s
			client := cl

			go func() {
				// get writer
				client.Output.Create(server)
				w := client.Output.NewWriter()

				// get mode
				modeint, err := strconv.ParseUint(mode, 8, 32)
				if err != nil {
					fmt.Fprintf(w, "%s\n", err)
					exit <- true
					return
				}
				filemode := os.FileMode(modeint)

				for _, path := range client.Path {

					// set arg path
					if !filepath.IsAbs(path) {
						path = filepath.Join(client.Pwd, path)
					}

					// set filemode
					err = client.Connect.Chmod(path, filemode)
					if err != nil {
						fmt.Fprintf(w, "%s\n", err)
						exit <- true
						return
					}

					fmt.Fprintf(w, "chmod: set %s's permission as %o(%s)\n", path, filemode.Perm(), filemode.String())
				}

				exit <- true
				return
			}()
		}

		for i := 0; i < len(targetmap); i++ {
			<-exit
		}

		return nil
	}

	// parse short options
	args = common.ParseArgs(app.Flags, args)
	app.Run(args)

	return
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"

	"github.com/codegangsta/cli"
)

var logger *log.Logger

func main() {
	logger = log.New(os.Stderr, "", 0)
	app := cli.NewApp()
	app.Name = "corectl"
	app.Usage = "corectl is a command line driven interface to the cluster wide CoreOS init system."
	app.Action = listUnits

	app.Commands = []cli.Command{
		{
			Name:   "list-units",
			Usage:  "List installed unit files",
			Action: listUnits,
		},
		{
			Name:   "start",
			Usage:  "Start (activate) one or more units",
			Action: startUnit,
		},
	}

	app.Run(os.Args)
}
<commit_msg>feat(cmd): add command descriptions.<commit_after>package main

import (
	"log"
	"os"

	"github.com/codegangsta/cli"
)

var logger *log.Logger

func main() {
	logger = log.New(os.Stderr, "", 0)

	app := cli.NewApp()
	app.Name = "corectl"
	app.Usage = "corectl is a command line driven interface to the cluster wide CoreOS init system."
	app.Action = listUnits

	app.Commands = []cli.Command{
		{
			Name:   "list-units",
			Usage:  "List installed unit files",
			Description: `List all of the units that are scheduled on the
cluster and their current state.`,
			Action: listUnits,
		},
		{
			Name:   "start",
			Usage:  "Start (activate) one or more units",
			Description: `Start adds one or more units to the cluster schedule.
Once scheduled the cluster will ensure that the unit is
running on one machine.`,
			Action: startUnit,
		},
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package cmd

import (
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"github.com/minamijoyo/myaws/myaws"
)

func init() {
	RootCmd.AddCommand(newEC2Cmd())
}

func newEC2Cmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "ec2",
		Short: "Manage EC2 resources",
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Help()
		},
	}

	cmd.AddCommand(
		newEC2LsCmd(),
		newEC2StartCmd(),
		newEC2StopCmd(),
		newEC2SSHCmd(),
	)

	return cmd
}

func newEC2LsCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "ls",
		Short: "List EC2 instances",
		RunE:  runEC2LsCmd,
	}

	flags := cmd.Flags()
	flags.BoolP("all", "a", false, "List all instances (by default, list running instances only)")
	flags.BoolP("quiet", "q", false, "Only display InstanceIDs")
	flags.StringP("filter-tag", "t", "Name:",
		"Filter instances by tag, such as \"Name:app-production\". The value of tag is assumed to be a partial match",
	)
	flags.StringP("fields", "F", "InstanceId InstanceType PublicIpAddress PrivateIpAddress StateName LaunchTime Tag:Name", "Output fields list separated by space")

	viper.BindPFlag("ec2.ls.all", flags.Lookup("all"))
	viper.BindPFlag("ec2.ls.quiet", flags.Lookup("quiet"))
	viper.BindPFlag("ec2.ls.filter-tag", flags.Lookup("filter-tag"))
	viper.BindPFlag("ec2.ls.fields", flags.Lookup("fields"))

	return cmd
}

func runEC2LsCmd(cmd *cobra.Command, args []string) error {
	client, err := newClient()
	if err != nil {
		return errors.Wrap(err, "newClient failed:")
	}

	options := myaws.EC2LsOptions{
		All:       viper.GetBool("ec2.ls.all"),
		Quiet:     viper.GetBool("ec2.ls.quiet"),
		FilterTag: viper.GetString("ec2.ls.filter-tag"),
		Fields:    viper.GetStringSlice("ec2.ls.fields"),
	}

	return client.EC2Ls(options)
}

func newEC2StartCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "start INSTANCE_ID [...]",
		Short: "Start EC2 instances",
		RunE:  runEC2StartCmd,
	}

	flags := cmd.Flags()
	flags.BoolP("wait", "w", false, "Wait until instance running")

	viper.BindPFlag("ec2.start.wait", flags.Lookup("wait"))

	return cmd
}

func runEC2StartCmd(cmd *cobra.Command, args []string) error {
	client, err := newClient()
	if err != nil {
		return errors.Wrap(err, "newClient failed:")
	}

	if len(args) == 0 {
		return errors.New("INSTANCE_ID is required")
	}
	instanceIds := aws.StringSlice(args)

	options := myaws.EC2StartOptions{
		InstanceIds: instanceIds,
		Wait:        viper.GetBool("ec2.start.wait"),
	}

	return client.EC2Start(options)
}

func newEC2StopCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "stop INSTANCE_ID [...]",
		Short: "Stop EC2 instances",
		RunE:  runEC2StopCmd,
	}

	flags := cmd.Flags()
	flags.BoolP("wait", "w", false, "Wait until instance stopped")

	viper.BindPFlag("ec2.stop.wait", flags.Lookup("wait"))

	return cmd
}

func runEC2StopCmd(cmd *cobra.Command, args []string) error {
	client, err := newClient()
	if err != nil {
		return errors.Wrap(err, "newClient failed:")
	}

	if len(args) == 0 {
		return errors.New("INSTANCE_ID is required")
	}
	instanceIds := aws.StringSlice(args)

	options := myaws.EC2StopOptions{
		InstanceIds: instanceIds,
		Wait:        viper.GetBool("ec2.stop.wait"),
	}

	return client.EC2Stop(options)
}

func newEC2SSHCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "ssh INSTANCE_ID",
		Short: "SSH to EC2 instance",
		RunE:  runEC2SSHCmd,
	}

	flags := cmd.Flags()
	flags.StringP("login-name", "l", "", "Login username")
	flags.StringP("identity-file", "i", "~/.ssh/id_rsa", "SSH private key file")
	flags.BoolP("private", "", false, "Use private IP to connect")

	viper.BindPFlag("ec2.ssh.login-name", flags.Lookup("login-name"))
	viper.BindPFlag("ec2.ssh.identity-file", flags.Lookup("identity-file"))
	viper.BindPFlag("ec2.ssh.private", flags.Lookup("private"))

	return cmd
}

func runEC2SSHCmd(cmd *cobra.Command, args []string) error {
	client, err := newClient()
	if err != nil {
		return errors.Wrap(err, "newClient failed:")
	}

	if len(args) == 0 {
		return errors.New("Instance name is required")
	}

	var loginName, instanceName string
	if strings.Contains(args[0], "@") {
		// parse loginName@instanceName format
		splitted := strings.SplitN(args[0], "@", 2)
		loginName, instanceName = splitted[0], splitted[1]
	} else {
		loginName = viper.GetString("ec2.ssh.login-name")
		instanceName = args[0]
	}

	filterTag := "Name:" + instanceName
	options := myaws.EC2SSHOptions{
		FilterTag:    filterTag,
		LoginName:    loginName,
		IdentityFile: viper.GetString("ec2.ssh.identity-file"),
		Private:      viper.GetBool("ec2.ssh.private"),
	}

	return client.EC2SSH(options)
}
<commit_msg>Fix ec2 ssh usage<commit_after>package cmd

import (
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"github.com/minamijoyo/myaws/myaws"
)

func init() {
	RootCmd.AddCommand(newEC2Cmd())
}

func newEC2Cmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "ec2",
		Short: "Manage EC2 resources",
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Help()
		},
	}

	cmd.AddCommand(
		newEC2LsCmd(),
		newEC2StartCmd(),
		newEC2StopCmd(),
		newEC2SSHCmd(),
	)

	return cmd
}

func newEC2LsCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "ls",
		Short: "List EC2 instances",
		RunE:  runEC2LsCmd,
	}

	flags := cmd.Flags()
	flags.BoolP("all", "a", false, "List all instances (by default, list running instances only)")
	flags.BoolP("quiet", "q", false, "Only display InstanceIDs")
	flags.StringP("filter-tag", "t", "Name:",
		"Filter instances by tag, such as \"Name:app-production\". The value of tag is assumed to be a partial match",
	)
	flags.StringP("fields", "F", "InstanceId InstanceType PublicIpAddress PrivateIpAddress StateName LaunchTime Tag:Name", "Output fields list separated by space")

	viper.BindPFlag("ec2.ls.all", flags.Lookup("all"))
	viper.BindPFlag("ec2.ls.quiet", flags.Lookup("quiet"))
	viper.BindPFlag("ec2.ls.filter-tag", flags.Lookup("filter-tag"))
	viper.BindPFlag("ec2.ls.fields", flags.Lookup("fields"))

	return cmd
}

func runEC2LsCmd(cmd *cobra.Command, args []string) error {
	client, err := newClient()
	if err != nil {
		return errors.Wrap(err, "newClient failed:")
	}

	options := myaws.EC2LsOptions{
		All:       viper.GetBool("ec2.ls.all"),
		Quiet:     viper.GetBool("ec2.ls.quiet"),
		FilterTag: viper.GetString("ec2.ls.filter-tag"),
		Fields:    viper.GetStringSlice("ec2.ls.fields"),
	}

	return client.EC2Ls(options)
}

func newEC2StartCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "start INSTANCE_ID [...]",
		Short: "Start EC2 instances",
		RunE:  runEC2StartCmd,
	}

	flags := cmd.Flags()
	flags.BoolP("wait", "w", false, "Wait until instance running")

	viper.BindPFlag("ec2.start.wait", flags.Lookup("wait"))

	return cmd
}

func runEC2StartCmd(cmd *cobra.Command, args []string) error {
	client, err := newClient()
	if err != nil {
		return errors.Wrap(err, "newClient failed:")
	}

	if len(args) == 0 {
		return errors.New("INSTANCE_ID is required")
	}
	instanceIds := aws.StringSlice(args)

	options := myaws.EC2StartOptions{
		InstanceIds: instanceIds,
		Wait:        viper.GetBool("ec2.start.wait"),
	}

	return client.EC2Start(options)
}

func newEC2StopCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "stop INSTANCE_ID [...]",
		Short: "Stop EC2 instances",
		RunE:  runEC2StopCmd,
	}

	flags := cmd.Flags()
	flags.BoolP("wait", "w", false, "Wait until instance stopped")

	viper.BindPFlag("ec2.stop.wait", flags.Lookup("wait"))

	return cmd
}

func runEC2StopCmd(cmd *cobra.Command, args []string) error {
	client, err := newClient()
	if err != nil {
		return errors.Wrap(err, "newClient failed:")
	}

	if len(args) == 0 {
		return errors.New("INSTANCE_ID is required")
	}
	instanceIds := aws.StringSlice(args)

	options := myaws.EC2StopOptions{
		InstanceIds: instanceIds,
		Wait:        viper.GetBool("ec2.stop.wait"),
	}

	return client.EC2Stop(options)
}

func newEC2SSHCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "ssh [USER]@INSTANCE_NAME",
		Short: "SSH to EC2 instance",
		RunE:  runEC2SSHCmd,
	}

	flags := cmd.Flags()
	flags.StringP("login-name", "l", "", "Login username")
	flags.StringP("identity-file", "i", "~/.ssh/id_rsa", "SSH private key file")
	flags.BoolP("private", "", false, "Use private IP to connect")

	viper.BindPFlag("ec2.ssh.login-name", flags.Lookup("login-name"))
	viper.BindPFlag("ec2.ssh.identity-file", flags.Lookup("identity-file"))
	viper.BindPFlag("ec2.ssh.private", flags.Lookup("private"))

	return cmd
}

func runEC2SSHCmd(cmd *cobra.Command, args []string) error {
	client, err := newClient()
	if err != nil {
		return errors.Wrap(err, "newClient failed:")
	}

	if len(args) == 0 {
		return errors.New("Instance name is required")
	}

	var loginName, instanceName string
	if strings.Contains(args[0], "@") {
		// parse loginName@instanceName format
		splitted := strings.SplitN(args[0], "@", 2)
		loginName, instanceName = splitted[0], splitted[1]
	} else {
		loginName = viper.GetString("ec2.ssh.login-name")
		instanceName = args[0]
	}

	filterTag := "Name:" + instanceName
	options := myaws.EC2SSHOptions{
		FilterTag:    filterTag,
		LoginName:    loginName,
		IdentityFile: viper.GetString("ec2.ssh.identity-file"),
		Private:      viper.GetBool("ec2.ssh.private"),
	}

	return client.EC2SSH(options)
}
<|endoftext|>


<commit_before>package lexer

type Lexer struct {
	input			string
	position		int		// current position in input (points to current char)
	readPosition	int		// current reading position in input (after current char)
	ch				byte	// current char being looked at
}

func New(input string) *Lexer {
	l := &Lexer{ input: input }
	return l
}<commit_msg>Add readChar helper.<commit_after>package lexer

type Lexer struct {
	input			string
	position		int		// current position in input (points to current char)
	readPosition	int		// current reading position in input (after current char)
	ch				byte	// current char being looked at
}

func New(input string) *Lexer {
	l := &Lexer{ input: input }
	return l
}

func (l *Lexer) readChar() {
	if l.readPosition >= len(l.input) {
		l.ch = 0
	} else {
		l.ch = l.input[l.readPosition]
	}
	l.position = l.readPosition
	l.readPosition += 1
}<|endoftext|>


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

package cmd

import (
	"context"
	"fmt"
	"os"
	"os/signal"

	"cloud.google.com/go/pubsub"
	ps "github.com/erikwilliamsa/gcloudps/pubsub"
	"github.com/erikwilliamsa/gcloudps/workers"
	"github.com/spf13/cobra"
)

var subName string

var deletesub = true

// subCmd represents the sub command
var subCmd = &cobra.Command{
	Use:   "sub",
	Short: "Subscribe to a given subscription/topic",
	Args: func(cmd *cobra.Command, args []string) error {
		flags := make(map[string]string)
		flags["subname"] = subName
		return CheckRequiredFlags(flags)
	},
	Long: `
	Creates a subscriber that will continue to recieve messages while running.`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Using project " + ProjectName)

		ctx, client, topic := initClient()

		fmt.Println("Creating subscription " + subName)
		subscription, err := client.CreateSubscription(ctx, subName,
			pubsub.SubscriptionConfig{Topic: topic})
		if err != nil {

			fmt.Println(subName + " already created")
		}

		cleanup(ctx, subscription)

		sc := ps.NewSubscriberClient(ctx, subscription, workers.NewCountMessageHandler())

		workers.Subscribe(ctx, sc)

	},
}

func cleanup(ctx context.Context, s *pubsub.Subscription) {
	//Want to figure out how to do this
	// in its own method to be used elsewhere
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for sig := range c {
			if sig != nil {
				fmt.Println("\nExiting")
				fmt.Println("Deleting the subscribtions")
				ctx.Done()
				err := s.Delete(ctx)
				if err != nil {
					fmt.Println("Topic was not deleted: " + err.Error())
				} else {
					fmt.Println("Topic deleted")
				}

			}

		}
	}()

}
func init() {
	RootCmd.AddCommand(subCmd)
	subCmd.Flags().StringVarP(&subName, "subname", "s", "", "Name of the subscription to use")

}
<commit_msg>Bug fix: would not exit.  Also fixed typos and fails to print<commit_after>// Copyright © 2017 NAME HERE Erik Williams erikwilliamsa@gmail.com
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"
	"strings"

	"cloud.google.com/go/pubsub"
	ps "github.com/erikwilliamsa/gcloudps/pubsub"
	"github.com/erikwilliamsa/gcloudps/workers"
	"github.com/spf13/cobra"
)

var subName string

var deletesub = true

// subCmd represents the sub command
var subCmd = &cobra.Command{
	Use:   "sub",
	Short: "Subscribe to a given subscription/topic",
	Args: func(cmd *cobra.Command, args []string) error {
		flags := make(map[string]string)
		flags["subname"] = subName
		return CheckRequiredFlags(flags)
	},
	Long: `
	Creates a subscriber that will continue to recieve messages while running.`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Using project " + ProjectName)

		ctx, client, topic := initClient()

		fmt.Println("Creating subscription " + subName)
		subscription, err := client.CreateSubscription(ctx, subName,
			pubsub.SubscriptionConfig{Topic: topic})
		if err != nil {
			if strings.Contains(err.Error(), "Resource not found") {
				log.Fatal(err.Error())
			} else {
				fmt.Println(subName + " already created" + err.Error())
			}

		}

		cleanup(ctx, subscription)

		sc := ps.NewSubscriberClient(ctx, subscription, workers.NewCountMessageHandler())
		fmt.Printf("\rConsumed:  %d", 0)
		workers.Subscribe(ctx, sc)

	},
}

func cleanup(ctx context.Context, s *pubsub.Subscription) {
	//Want to figure out how to do this
	// in its own method to be used elsewhere
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	fmt.Println("Press Ctrl+c to exit")
	go func() {
		for sig := range c {
			if sig != nil {
				fmt.Println("\nExiting")
				fmt.Println("Deleting the subscribtion")
				err := s.Delete(ctx)
				if err != nil {
					fmt.Println("Subscribtion was not deleted: " + err.Error())
				} else {
					fmt.Println("Subscribtion deleted")
				}

			}

		}
	}()

}
func init() {
	RootCmd.AddCommand(subCmd)
	subCmd.Flags().StringVarP(&subName, "subname", "s", "", "Name of the subscription to use")

}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strconv"
	"sync"
	"time"

	"github.com/montanaflynn/stats"
)

// global command line parameters
var runs *int
var cpus [2]string
var threads *string
var hermitcore *bool

func main() {
	commandFile := parseArgs()

	commands, err := readCommands(*commandFile)
	if err != nil {
		log.Fatalf("Error reading command file %v: %v", *commandFile, err)
	}
	if len(commands) < 2 {
		log.Fatal("You must provide at least 2 commands")
	}

	commandPairs := generateCommandPairs(commands)

	fmt.Println("Executing the following command pairs:")
	for _, c := range commandPairs {
		fmt.Println(c)
	}

	for i, c := range commandPairs {
		fmt.Printf("Running pair %v\n", i)
		fmt.Println(c)
		// TODO run for every combination of CAT setup
		err := runPair(c, i)
		if err != nil {
			log.Fatalf("Error while running pair %v (%v): %v", i, c, err)
		}
	}
}

func runCmdMinTimes(cmd *exec.Cmd, min int, wg *sync.WaitGroup, measurement *string, done chan int, errs chan error) {
	var runtime []float64

	defer wg.Done()

	defer func() {
		mean, _ := stats.Mean(runtime)
		stddev, _ := stats.StandardDeviation(runtime)
		vari, _ := stats.Variance(runtime)

		fmt.Printf("%v \t %9.2fs avg. runtime \t %1.6f std. dev. \t %1.6f variance \t %v runs\n", cmd.Args, mean, stddev, vari, len(runtime))
	}()

	for i := 1; ; i++ {
		// create a copy of the command
		cmd := *cmd

		start := time.Now()
		err := cmd.Run()
		elapsed := time.Since(start)

		if err != nil {
			errs <- fmt.Errorf("Error running %v: %v", cmd.Args, err)
			return
		}

		// did the other cmd result in an error?
		if len(errs) != 0 {
			return
		}

		d := <-done

		// check if the other application was running the whole time
		if d == len(cpus) {
			// no
			*measurement += "# "
		} else {
			runtime = append(runtime, elapsed.Seconds())
		}
		*measurement += strconv.FormatInt(elapsed.Nanoseconds(), 10)
		*measurement += "\n"

		// did we run min times?
		if i == min {
			d++
		}
		done <- d

		// both applications are done
		if d == len(cpus) {
			return
		}
	}
}

func runPair(cPair [2]string, id int) error {
	env := os.Environ()

	var cmds [len(cpus)]*exec.Cmd
	// setup commands
	for i, _ := range cmds {
		if *hermitcore {
			cmds[i] = exec.Command("numactl", "--physcpubind", cpus[i], "/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "HERMIT_CPUS="+*threads, "HERMIT_MEM=4G", "HERMIT_ISLE=uhyve")
		} else {
			cmds[i] = exec.Command("/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "GOMP_CPU_AFFINITY="+cpus[i], "OMP_NUM_THREADS="+*threads)
		}

		outfile, err := os.Create(fmt.Sprintf("%v-%v.log", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer outfile.Close()
		cmds[i].Stdout = outfile
	}

	var measurements [len(cmds)]string
	// used to count how many apps have reached there min limit
	done := make(chan int, 1)
	done <- 0

	// used to return an error from the go-routines
	errs := make(chan error, len(cmds))

	// used to wait for the following 2 goroutines
	var wg sync.WaitGroup
	wg.Add(len(cmds))

	for i, c := range cmds {
		go runCmdMinTimes(c, *runs, &wg, &measurements[i], done, errs)
	}

	wg.Wait()

	if len(errs) != 0 {
		return <-errs
	}

	for i, s := range measurements {
		measurementsFile, err := os.Create(fmt.Sprintf("%v-%v.time", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer measurementsFile.Close()

		_, err = measurementsFile.WriteString("# runtime in nanoseconds of \"" + cPair[i] + "\" while \"" + cPair[(i+1)%2] + "\" is running\n" + s)
		if err != nil {
			return fmt.Errorf("Error while writing measurements file: %v", err)
		}
	}

	return nil
}

func generateCommandPairs(commands []string) [][2]string {
	var pairs [][2]string
	for i, c0 := range commands {
		for j, c1 := range commands {
			if i >= j {
				continue
			}
			pairs = append(pairs, [2]string{c0, c1})
		}
	}
	return pairs
}

func readCommands(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, errors.New("Error opening file " + filename + ": " + err.Error())
	}
	defer file.Close()

	var commands []string

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		commands = append(commands, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, errors.New("Error scanning commands: " + err.Error())
	}

	return commands, nil
}

func parseArgs() *string {
	runs = flag.Int("arun", 2, "Number of times the applications are executed")
	commandFile := flag.String("cmd", "cmd.txt", "Text file containing the commands to execute")
	cpus0 := flag.String("cpus0", "0-4", "List of CPUs to be used for the 1st command")
	cpus1 := flag.String("cpus1", "5-9", "List of CPUs to be used for the 2nd command")
	threads = flag.String("threads", "5", "Number of threads to be used")
	hermitcore = flag.Bool("hermitcore", false, "Use if you are executing hermitcore binaries")
	//resctrlPath := flag.String("resctrl", "/sys/fs/resctrl/", "Root path of the resctrl file system")
	flag.Parse()

	cpus[0] = *cpus0
	cpus[1] = *cpus1

	return commandFile
}
<commit_msg>Create stats file even in case of error.<commit_after>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strconv"
	"sync"
	"time"

	"github.com/montanaflynn/stats"
)

// global command line parameters
var runs *int
var cpus [2]string
var threads *string
var hermitcore *bool

func main() {
	commandFile := parseArgs()

	commands, err := readCommands(*commandFile)
	if err != nil {
		log.Fatalf("Error reading command file %v: %v", *commandFile, err)
	}
	if len(commands) < 2 {
		log.Fatal("You must provide at least 2 commands")
	}

	commandPairs := generateCommandPairs(commands)

	fmt.Println("Executing the following command pairs:")
	for _, c := range commandPairs {
		fmt.Println(c)
	}

	for i, c := range commandPairs {
		fmt.Printf("Running pair %v\n", i)
		fmt.Println(c)
		// TODO run for every combination of CAT setup
		err := runPair(c, i)
		if err != nil {
			log.Fatalf("Error while running pair %v (%v): %v", i, c, err)
		}
	}
}

func runCmdMinTimes(cmd *exec.Cmd, min int, wg *sync.WaitGroup, measurement *string, done chan int, errs chan error) {
	var runtime []float64

	defer wg.Done()

	defer func() {
		mean, _ := stats.Mean(runtime)
		stddev, _ := stats.StandardDeviation(runtime)
		vari, _ := stats.Variance(runtime)

		fmt.Printf("%v \t %9.2fs avg. runtime \t %1.6f std. dev. \t %1.6f variance \t %v runs\n", cmd.Args, mean, stddev, vari, len(runtime))
	}()

	for i := 1; ; i++ {
		// create a copy of the command
		cmd := *cmd

		start := time.Now()
		err := cmd.Run()
		elapsed := time.Since(start)

		if err != nil {
			errs <- fmt.Errorf("Error running %v: %v", cmd.Args, err)
			return
		}

		// did the other cmd result in an error?
		if len(errs) != 0 {
			return
		}

		d := <-done

		// check if the other application was running the whole time
		if d == len(cpus) {
			// no
			*measurement += "# "
		} else {
			runtime = append(runtime, elapsed.Seconds())
		}
		*measurement += strconv.FormatInt(elapsed.Nanoseconds(), 10)
		*measurement += "\n"

		// did we run min times?
		if i == min {
			d++
		}
		done <- d

		// both applications are done
		if d == len(cpus) {
			return
		}
	}
}

func runPair(cPair [2]string, id int) error {
	env := os.Environ()

	var cmds [len(cpus)]*exec.Cmd
	// setup commands
	for i, _ := range cmds {
		if *hermitcore {
			cmds[i] = exec.Command("numactl", "--physcpubind", cpus[i], "/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "HERMIT_CPUS="+*threads, "HERMIT_MEM=4G", "HERMIT_ISLE=uhyve")
		} else {
			cmds[i] = exec.Command("/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "GOMP_CPU_AFFINITY="+cpus[i], "OMP_NUM_THREADS="+*threads)
		}

		outfile, err := os.Create(fmt.Sprintf("%v-%v.log", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer outfile.Close()
		cmds[i].Stdout = outfile
	}

	var measurements [len(cmds)]string
	// used to count how many apps have reached there min limit
	done := make(chan int, 1)
	done <- 0

	// used to return an error from the go-routines
	errs := make(chan error, len(cmds))

	// used to wait for the following 2 goroutines
	var wg sync.WaitGroup
	wg.Add(len(cmds))

	for i, c := range cmds {
		go runCmdMinTimes(c, *runs, &wg, &measurements[i], done, errs)
	}

	wg.Wait()

	for i, s := range measurements {
		measurementsFile, err := os.Create(fmt.Sprintf("%v-%v.time", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer measurementsFile.Close()

		_, err = measurementsFile.WriteString("# runtime in nanoseconds of \"" + cPair[i] + "\" while \"" + cPair[(i+1)%2] + "\" is running\n" + s)
		if err != nil {
			return fmt.Errorf("Error while writing measurements file: %v", err)
		}
	}

	if len(errs) != 0 {
		return <-errs
	}

	return nil
}

func generateCommandPairs(commands []string) [][2]string {
	var pairs [][2]string
	for i, c0 := range commands {
		for j, c1 := range commands {
			if i >= j {
				continue
			}
			pairs = append(pairs, [2]string{c0, c1})
		}
	}
	return pairs
}

func readCommands(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, errors.New("Error opening file " + filename + ": " + err.Error())
	}
	defer file.Close()

	var commands []string

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		commands = append(commands, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, errors.New("Error scanning commands: " + err.Error())
	}

	return commands, nil
}

func parseArgs() *string {
	runs = flag.Int("arun", 2, "Number of times the applications are executed")
	commandFile := flag.String("cmd", "cmd.txt", "Text file containing the commands to execute")
	cpus0 := flag.String("cpus0", "0-4", "List of CPUs to be used for the 1st command")
	cpus1 := flag.String("cpus1", "5-9", "List of CPUs to be used for the 2nd command")
	threads = flag.String("threads", "5", "Number of threads to be used")
	hermitcore = flag.Bool("hermitcore", false, "Use if you are executing hermitcore binaries")
	//resctrlPath := flag.String("resctrl", "/sys/fs/resctrl/", "Root path of the resctrl file system")
	flag.Parse()

	cpus[0] = *cpus0
	cpus[1] = *cpus1

	return commandFile
}
<|endoftext|>


<commit_before>/*
SharedBuffer reader. What to know when creating such a reader:

	1. Timeless access to all present and future buffer data
	2. Close() must be called when it's done
	3. Will return a EOF after the buffer is closed and all data has been read
*/
package sharedbuffer

import (
	"container/heap"
	"io"
)

// reader represents a consumer of a SharedBuffer
type reader struct {
	at  int
	idx int
	sb  *SharedBuffer
}

// Read some data from the buffer. Will block until data is available or an error occurs
func (r *reader) Read(p []byte) (n int, err error) {
	r.sb.lock.Lock()
	defer r.sb.lock.Unlock()
	n, err = 0, nil

	// Block until available data or error
	for !r.availableData() && !r.sb.closed {
		r.sb.lock.Unlock()
		<-r.sb.newData
		r.sb.lock.Lock()
	}
	if !r.availableData() && r.sb.closed {
		return 0, io.EOF
	}

	// Copy data and move the reader's position in the buffer
	readStart := r.at - r.sb.start
	n = copy(p, r.sb.buf[readStart:])
	r.at += n

	// Tell SharedBuffer to resort its readers
	heap.Fix(&r.sb.readers, r.idx)
	r.sb.flush()

	return
}

// Close the reader. Tells the SharedBuffer to forget about its data guarantees.
func (r *reader) Close() error {
	r.sb.lock.Lock()
	defer r.sb.lock.Unlock()

	// SharedBuffer can now forget about tracking this reader
	heap.Remove(&r.sb.readers, r.idx)

	r.at = 0
	r.idx = -1
	r.sb = nil

	return nil
}

// availableData returns true if the buffer has new data after the reader's
// current position
func (r *reader) availableData() bool {
	return r.at < r.sb.start+len(r.sb.buf)
}

/*
readers is a heap enabled collection of reader instances.

A SharedBuffer effectively stores what data its slowest reader
has yet to consume. As the slowest reader can change after any
read, it is good to have an efficient lookup for the slowest
reader.

A heap of readers reduces a naive O(n) lookup time to O(log n),
where n is the number of active readers.
*/
type readers []*reader

func (rs readers) Len() int           { return len(rs) }
func (rs readers) Less(i, j int) bool { return rs[i].at < rs[j].at }

func (rs readers) Swap(i, j int) {
	rs[i], rs[j] = rs[j], rs[i]
	rs[i].idx, rs[j].idx = rs[j].idx, rs[i].idx
}

func (rs *readers) Push(x interface{}) {
	r := x.(*reader)
	*rs = append(*rs, r)
	r.idx = len(*rs) - 1
}

func (rs *readers) Pop() interface{} {
	h := *rs
	l := len(h)
	min := h[l-1]
	*rs = h[:l-1]

	min.idx = -1
	return min
}
<commit_msg>Add "Closed Buffer" reporting for sharedbuffer<commit_after>/*
SharedBuffer reader. What to know when creating such a reader:

	1. Timeless access to all present and future buffer data
	2. Close() must be called when it's done
	3. Will return a EOF after the buffer is closed and all data has been read
*/
package sharedbuffer

import (
	"container/heap"
	"errors"
	"io"
)

// reader represents a consumer of a SharedBuffer
type reader struct {
	at  int
	idx int
	sb  *SharedBuffer
}

var ErrClosedReader = errors.New("closed reader")

// Read some data from the buffer. Will block until data is available or an error occurs
func (r *reader) Read(p []byte) (n int, err error) {
	if r.idx < 0 || r.sb == nil {
		return 0, ErrClosedReader
	}

	r.sb.lock.Lock()
	defer r.sb.lock.Unlock()
	n, err = 0, nil

	// Block until available data or error
	for !r.availableData() && !r.sb.closed {
		r.sb.lock.Unlock()
		<-r.sb.newData
		r.sb.lock.Lock()
	}
	if !r.availableData() && r.sb.closed {
		return 0, io.EOF
	}

	// Copy data and move the reader's position in the buffer
	readStart := r.at - r.sb.start
	n = copy(p, r.sb.buf[readStart:])
	r.at += n

	// Tell SharedBuffer to resort its readers
	heap.Fix(&r.sb.readers, r.idx)
	r.sb.flush()

	return
}

// Close the reader. Tells the SharedBuffer to forget about its data guarantees.
func (r *reader) Close() error {
	r.sb.lock.Lock()
	defer r.sb.lock.Unlock()

	// SharedBuffer can now forget about tracking this reader
	heap.Remove(&r.sb.readers, r.idx)

	r.at = 0
	r.idx = -1
	r.sb = nil

	return nil
}

// availableData returns true if the buffer has new data after the reader's
// current position
func (r reader) availableData() bool {
	return r.at < r.sb.start+len(r.sb.buf)
}

/*
readers is a heap enabled collection of reader instances.

A SharedBuffer effectively stores what data its slowest reader
has yet to consume. As the slowest reader can change after any
read, it is good to have an efficient lookup for the slowest
reader.

A heap of readers reduces a naive O(n) lookup time to O(log n),
where n is the number of active readers.
*/
type readers []*reader

func (rs readers) Len() int           { return len(rs) }
func (rs readers) Less(i, j int) bool { return rs[i].at < rs[j].at }

func (rs readers) Swap(i, j int) {
	rs[i], rs[j] = rs[j], rs[i]
	rs[i].idx, rs[j].idx = rs[j].idx, rs[i].idx
}

func (rs *readers) Push(x interface{}) {
	r := x.(*reader)
	*rs = append(*rs, r)
	r.idx = len(*rs) - 1
}

func (rs *readers) Pop() interface{} {
	h := *rs
	l := len(h)
	p := h[l-1]
	*rs = h[:l-1]

	p.idx = -1
	return p
}
<|endoftext|>


<commit_before>package plugins

// Important: Register this module _AFTER_ successful connection!

import (
	"log"
	"fmt"
	"ircclient"
	"http"
	"xml"
	"time"
)

type root struct {
	Events Events
}

type Events struct {
	Event []Event
}

type Event struct {
	Id         int `xml:"attr"`
	Submission *Submission
	Judging    *Judging
}

type Submission struct {
	Id       int `xml:"attr"`
	Team     string
	Problem  string
	Language string
}

type Judging struct {
	Id       int    `xml:"attr"`
	Submitid int    `xml:"attr"`
	Result   string `xml:"chardata"`
}

type HalloWeltPlugin struct {
	ic *ircclient.IRCClient
	done chan bool
}

func (q *HalloWeltPlugin) Register(cl *ircclient.IRCClient) {
	q.ic = cl
	var client http.Client
	q.done = make(chan bool)
	p, err := q.ic.GetIntOption("HalloWelt", "polling")
	polling := int64(p)
	channel := q.ic.GetStringOption("HalloWelt", "channel")
	url := q.ic.GetStringOption("HalloWelt", "url")
	if err != nil || channel == "" || url == "" {
		log.Println("WARNING: No complete HalloWelt configuration found. Setting defaults. Please edit your config and reload this plugin")
		q.ic.SetStringOption("HalloWelt", "channel", "hallowelt")
		q.ic.SetStringOption("HalloWelt", "url", "https://EDITTHIS")
		q.ic.SetIntOption("HalloWelt", "polling", 60)
		go func() {
			<-q.done
			q.done <- true
		}()
		return
	}
	go func() {
		for {
			t := time.After(polling * 1e9)
			select {
			case <- t:
			case <- q.done:
			q.done <- true
			return;
			}
			response, err := client.Get(url)
			if response.StatusCode != 200 || err != nil {
				log.Println("ERROR: (HalloWelt): Unable to get current event list from DomJudge")
				time.Sleep(120 * 1e9)
				continue
			}
			var res root
			// Parse XML
			xml.Unmarshal(response.Body, &res)
			response.Body.Close()
			last, err := q.ic.GetIntOption("HalloWelt", "last")
			q.ic.SetIntOption("HalloWelt", "last", len(res.Events.Event))
			if err != nil || last == len(res.Events.Event) {
				continue
			}
			// Report new submissions
			for i := last; i < len(res.Events.Event); i = i + 1 {
				ev := res.Events.Event[i].Judging
				if ev == nil {
					continue
				}
				if ev.Result != "correct" {
					continue
				}
				tries, team, problem := 0, "", ""
				for i := len(res.Events.Event) - 1; i >= 0; i = i - 1 {
					if res.Events.Event[i].Submission == nil {
						continue
					}
					if res.Events.Event[i].Submission.Id == ev.Submitid {
						tries = 1
						team = res.Events.Event[i].Submission.Team
						problem = res.Events.Event[i].Submission.Problem
						continue
					}
					if tries != 0 && res.Events.Event[i].Submission.Problem == problem && res.Events.Event[i].Submission.Team == team {
						tries = tries + 1
					}
				}
				if tries == 0 {
					// Ignore invalid input
					continue
				}
				q.ic.SendLine("PRIVMSG #" + channel + " :" + team + " solved " + problem + " (after " + fmt.Sprintf("%d", tries - 1) + " failed attempts)")
			}
		}
	}()
}

func (q *HalloWeltPlugin) String() string {
	return "hallowelt"
}

func (q *HalloWeltPlugin) Info() string {
	return "DomJudge live ticker"
}

func (q *HalloWeltPlugin) Usage(cmd string) string {
	return "This plugin provides no commands"
}

func (q *HalloWeltPlugin) ProcessLine(msg *ircclient.IRCMessage) {
}

func (q *HalloWeltPlugin) ProcessCommand(cmd *ircclient.IRCCommand) {
}

func (q *HalloWeltPlugin) Unregister() {
	q.done <- true
	<-q.done
}
<commit_msg>Ignore team "DOMjudge"<commit_after>package plugins

// Important: Register this module _AFTER_ successful connection!

import (
	"log"
	"fmt"
	"ircclient"
	"http"
	"xml"
	"time"
)

type root struct {
	Events Events
}

type Events struct {
	Event []Event
}

type Event struct {
	Id         int `xml:"attr"`
	Submission *Submission
	Judging    *Judging
}

type Submission struct {
	Id       int `xml:"attr"`
	Team     string
	Problem  string
	Language string
}

type Judging struct {
	Id       int    `xml:"attr"`
	Submitid int    `xml:"attr"`
	Result   string `xml:"chardata"`
}

type HalloWeltPlugin struct {
	ic *ircclient.IRCClient
	done chan bool
}

func (q *HalloWeltPlugin) Register(cl *ircclient.IRCClient) {
	q.ic = cl
	var client http.Client
	q.done = make(chan bool)
	p, err := q.ic.GetIntOption("HalloWelt", "polling")
	polling := int64(p)
	channel := q.ic.GetStringOption("HalloWelt", "channel")
	url := q.ic.GetStringOption("HalloWelt", "url")
	if err != nil || channel == "" || url == "" {
		log.Println("WARNING: No complete HalloWelt configuration found. Setting defaults. Please edit your config and reload this plugin")
		q.ic.SetStringOption("HalloWelt", "channel", "hallowelt")
		q.ic.SetStringOption("HalloWelt", "url", "https://EDITTHIS")
		q.ic.SetIntOption("HalloWelt", "polling", 60)
		go func() {
			<-q.done
			q.done <- true
		}()
		return
	}
	go func() {
		for {
			t := time.After(polling * 1e9)
			select {
			case <- t:
			case <- q.done:
			q.done <- true
			return;
			}
			response, err := client.Get(url)
			if response.StatusCode != 200 || err != nil {
				log.Println("ERROR: (HalloWelt): Unable to get current event list from DomJudge")
				time.Sleep(120 * 1e9)
				continue
			}
			var res root
			// Parse XML
			xml.Unmarshal(response.Body, &res)
			response.Body.Close()
			last, err := q.ic.GetIntOption("HalloWelt", "last")
			q.ic.SetIntOption("HalloWelt", "last", len(res.Events.Event))
			if err != nil || last == len(res.Events.Event) {
				continue
			}
			// Report new submissions
			for i := last; i < len(res.Events.Event); i = i + 1 {
				ev := res.Events.Event[i].Judging
				if ev == nil {
					continue
				}
				if ev.Result != "correct" {
					continue
				}
				tries, team, problem := 0, "", ""
				for i := len(res.Events.Event) - 1; i >= 0; i = i - 1 {
					if res.Events.Event[i].Submission == nil {
						continue
					}
					if res.Events.Event[i].Submission.Id == ev.Submitid {
						tries = 1
						team = res.Events.Event[i].Submission.Team
						problem = res.Events.Event[i].Submission.Problem
						continue
					}
					if tries != 0 && res.Events.Event[i].Submission.Problem == problem && res.Events.Event[i].Submission.Team == team {
						tries = tries + 1
					}
				}
				if tries == 0 || team == "DOMjudge" {
					// Ignore invalid input
					continue
				}
				q.ic.SendLine("PRIVMSG #" + channel + " :" + team + " solved " + problem + " (after " + fmt.Sprintf("%d", tries - 1) + " failed attempts)")
			}
		}
	}()
}

func (q *HalloWeltPlugin) String() string {
	return "hallowelt"
}

func (q *HalloWeltPlugin) Info() string {
	return "DomJudge live ticker"
}

func (q *HalloWeltPlugin) Usage(cmd string) string {
	return "This plugin provides no commands"
}

func (q *HalloWeltPlugin) ProcessLine(msg *ircclient.IRCMessage) {
}

func (q *HalloWeltPlugin) ProcessCommand(cmd *ircclient.IRCCommand) {
}

func (q *HalloWeltPlugin) Unregister() {
	q.done <- true
	<-q.done
}
<|endoftext|>


<commit_before>package logs

import (
	"fmt"

	"github.com/dokku/dokku/plugins/common"
)

// MaxSize is the default max retention size for docker logs
const MaxSize = "10m"

var (
	// DefaultProperties is a map of all valid logs properties with corresponding default property values
	DefaultProperties = map[string]string{
		"max-size":    "",
		"vector-sink": "",
	}

	// GlobalProperties is a map of all valid global logs properties
	GlobalProperties = map[string]bool{
		"max-size":    true,
		"vector-sink": true,
	}
)

// VectorImage contains the default vector image to run
const VectorImage = "timberio/vector:0.12.X-debian"

// GetFailedLogs outputs failed deploy logs for a given app
func GetFailedLogs(appName string) error {
	common.LogInfo2Quiet(fmt.Sprintf("%s failed deploy logs", appName))
	s := common.GetAppScheduler(appName)
	if err := common.PlugnTrigger("scheduler-logs-failed", s, appName); err != nil {
		return err
	}
	return nil
}
<commit_msg>feat: upgrade vector image to 0.16.x<commit_after>package logs

import (
	"fmt"

	"github.com/dokku/dokku/plugins/common"
)

// MaxSize is the default max retention size for docker logs
const MaxSize = "10m"

var (
	// DefaultProperties is a map of all valid logs properties with corresponding default property values
	DefaultProperties = map[string]string{
		"max-size":    "",
		"vector-sink": "",
	}

	// GlobalProperties is a map of all valid global logs properties
	GlobalProperties = map[string]bool{
		"max-size":    true,
		"vector-sink": true,
	}
)

// VectorImage contains the default vector image to run
const VectorImage = "timberio/vector:0.16.X-debian"

// GetFailedLogs outputs failed deploy logs for a given app
func GetFailedLogs(appName string) error {
	common.LogInfo2Quiet(fmt.Sprintf("%s failed deploy logs", appName))
	s := common.GetAppScheduler(appName)
	if err := common.PlugnTrigger("scheduler-logs-failed", s, appName); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package plugins

import (
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os/exec"
	"strings"

	"github.com/belak/irc"
	"github.com/belak/seabird/bot"
	"github.com/belak/seabird/mux"
)

type NetToolsPlugin struct {
	Key string
}

func init() {
	bot.RegisterPlugin("net_tools", NewNetToolsPlugin)
}

func NewNetToolsPlugin(b *bot.Bot, m *mux.CommandMux) error {
	p := &NetToolsPlugin{}

	b.Config("net_tools", p)

	m.Event("dig", p.Dig, &mux.HelpInfo{
		"<domain>",
		"Retrieves IP records for given domain",
	})
	m.Event("ping", p.Ping, &mux.HelpInfo{
		"<host>",
		"Pings given host once",
	})
	m.Event("traceroute", p.Traceroute, &mux.HelpInfo{
		"<host>",
		"Runs traceroute on given host and returns pastebin URL for results",
	})
	m.Event("whois", p.Whois, &mux.HelpInfo{
		"<domain>",
		"Runs whois on given domain and returns pastebin URL for results",
	})
	m.Event("dnscheck", p.DnsCheck, &mux.HelpInfo{
		"<domain>",
		"Returns DNSCheck URL for domain",
	})

	return nil
}

func (p *NetToolsPlugin) Dig(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		addrs, err := net.LookupHost(e.Trailing())
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		if len(addrs) == 0 {
			c.MentionReply(e, "No results found")
			return
		}

		c.MentionReply(e, addrs[0])

		if len(addrs) > 1 {
			for _, addr := range addrs[1:] {
				c.Writef("NOTICE %s :%s", e.Identity.Nick, addr)
			}
		}
	}()
}

func (p *NetToolsPlugin) Ping(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Host required")
			return
		}

		out, err := exec.Command("ping", "-c1", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		arr := strings.Split(string(out), "\n")
		if len(arr) < 2 {
			c.MentionReply(e, "Error retrieving ping results")
			return
		}

		c.MentionReply(e, arr[1])
	}()
}

func (p *NetToolsPlugin) Traceroute(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Host required")
			return
		}

		out, err := exec.Command("traceroute", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		resp, err := http.PostForm("http://pastebin.com/api/api_post.php", url.Values{
			"api_dev_key":    {p.Key},
			"api_option":     {"paste"},
			"api_paste_code": {string(out)},
		})
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		c.MentionReply(e, "%s", body)
	}()
}

func (p *NetToolsPlugin) Whois(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		out, err := exec.Command("whois", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		resp, err := http.PostForm("http://pastebin.com/api/api_post.php", url.Values{
			"api_dev_key":    {p.Key},
			"api_option":     {"paste"},
			"api_paste_code": {string(out)},
		})
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		c.MentionReply(e, "%s", body)
	}()
}

func (p *NetToolsPlugin) DnsCheck(c *irc.Client, e *irc.Event) {
	// Just for Kaleb
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		c.MentionReply(e, "https://www.whatsmydns.net/#A/"+e.Trailing())
	}()
}
<commit_msg>Add !rdns command. Closes #71.<commit_after>package plugins

import (
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os/exec"
	"strings"

	"github.com/belak/irc"
	"github.com/belak/seabird/bot"
	"github.com/belak/seabird/mux"
)

type NetToolsPlugin struct {
	Key string
}

func init() {
	bot.RegisterPlugin("net_tools", NewNetToolsPlugin)
}

func NewNetToolsPlugin(b *bot.Bot, m *mux.CommandMux) error {
	p := &NetToolsPlugin{}

	b.Config("net_tools", p)

	m.Event("rdns", p.RDNS, &mux.HelpInfo{
		"<ip>",
		"Does a reverse DNS lookup on the given IP",
	})
	m.Event("dig", p.Dig, &mux.HelpInfo{
		"<domain>",
		"Retrieves IP records for given domain",
	})
	m.Event("ping", p.Ping, &mux.HelpInfo{
		"<host>",
		"Pings given host once",
	})
	m.Event("traceroute", p.Traceroute, &mux.HelpInfo{
		"<host>",
		"Runs traceroute on given host and returns pastebin URL for results",
	})
	m.Event("whois", p.Whois, &mux.HelpInfo{
		"<domain>",
		"Runs whois on given domain and returns pastebin URL for results",
	})
	m.Event("dnscheck", p.DnsCheck, &mux.HelpInfo{
		"<domain>",
		"Returns DNSCheck URL for domain",
	})

	return nil
}

func (p *NetToolsPlugin) RDNS(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Argument required")
			return
		}
		names, err := net.LookupAddr(e.Trailing())
		if err != nil {
			c.MentionReply(e, err.Error())
			return
		}

		if len(names) == 0 {
			c.MentionReply(e, "No results found")
			return
		}

		c.MentionReply(e, names[0])

		if len(names) > 1 {
			for _, name := range names[1:] {
				c.Writef("NOTICE %s :%s", e.Identity.Nick, name)
			}
		}
	}()
}

func (p *NetToolsPlugin) Dig(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		addrs, err := net.LookupHost(e.Trailing())
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		if len(addrs) == 0 {
			c.MentionReply(e, "No results found")
			return
		}

		c.MentionReply(e, addrs[0])

		if len(addrs) > 1 {
			for _, addr := range addrs[1:] {
				c.Writef("NOTICE %s :%s", e.Identity.Nick, addr)
			}
		}
	}()
}

func (p *NetToolsPlugin) Ping(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Host required")
			return
		}

		out, err := exec.Command("ping", "-c1", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		arr := strings.Split(string(out), "\n")
		if len(arr) < 2 {
			c.MentionReply(e, "Error retrieving ping results")
			return
		}

		c.MentionReply(e, arr[1])
	}()
}

func (p *NetToolsPlugin) Traceroute(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Host required")
			return
		}

		out, err := exec.Command("traceroute", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		resp, err := http.PostForm("http://pastebin.com/api/api_post.php", url.Values{
			"api_dev_key":    {p.Key},
			"api_option":     {"paste"},
			"api_paste_code": {string(out)},
		})
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		c.MentionReply(e, "%s", body)
	}()
}

func (p *NetToolsPlugin) Whois(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		out, err := exec.Command("whois", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		resp, err := http.PostForm("http://pastebin.com/api/api_post.php", url.Values{
			"api_dev_key":    {p.Key},
			"api_option":     {"paste"},
			"api_paste_code": {string(out)},
		})
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		c.MentionReply(e, "%s", body)
	}()
}

func (p *NetToolsPlugin) DnsCheck(c *irc.Client, e *irc.Event) {
	// Just for Kaleb
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		c.MentionReply(e, "https://www.whatsmydns.net/#A/"+e.Trailing())
	}()
}
<|endoftext|>


<commit_before>package seen

import (
	"strings"
	"sync"
	"time"

	"github.com/peted27/gherkin/lib"
	"github.com/peted27/go-ircevent"
)

var (
	db      = Log{}
	command = "!seen"
	con     *irc.Connection
)

// Log is an accessible map of channels to nick to entries.
type Log struct {
	sync.Mutex
	M map[string]map[string]time.Time
}

func Register(c *irc.Connection) {
	con = c
	c.AddCallback("PRIVMSG",
		func(e *irc.Event) {
			if !lib.IsPublicMessage(e) && !lib.IsCommandMessage(e) {
				return
			}
			handle(e)
		})
}

func handle(e *irc.Event) {
	channel := e.Arguments[0]
	text := e.Arguments[1]
	nick := e.Nick
	target := nick

	db.Store(channel, nick, time.Now())

	if !strings.HasPrefix(e.Arguments[1], command) {
		return
	}

	if text != command {
		target = strings.TrimPrefix(text, command+" ")
		target = strings.TrimSpace(target)
	}

	if t, found := db.Search(channel, target); found == false {
		e.Connection.Action(channel, target+" has not been seen")
	} else {
		e.Connection.Action(channel, target+" last seen "+t.Format("15:04:05 (2006-01-02) MST"))
	}
}

// Store saves a line from a channel/nick into backlog.
func (l *Log) Store(channel, nick string, seen time.Time) {
	l.Lock()
	defer l.Unlock()

	if l.M == nil {
		if con.Debug {
			con.Log.Println("plugin (seen): creating channel map for " + channel)
		}
		l.M = map[string]map[string]time.Time{}
	}

	if _, p := l.M[channel]; p {
		// update time
		if con.Debug {
			con.Log.Println("plugin (seen): updating seen time for " + nick)
		}
		l.M[channel][nick] = seen
	} else {
		if con.Debug {
			con.Log.Println("plugin (seen): creating nick map for " + nick)
		}
		l.M[channel] = map[string]time.Time{nick: seen}
	}
}

// Search returns backlog lines of a channel/nick.
func (l *Log) Search(channel, nick string) (time.Time, bool) {
	var results time.Time
	l.Lock()
	defer l.Unlock()
	if _, p := l.M[channel]; p {
		if _, q := l.M[channel][nick]; q {
			results := l.M[channel][nick]
			if con.Debug {
				con.Log.Println("plugin (seen): found result")
			}
			return results, true
		}
	}
	if con.Debug {
		con.Log.Println("plugin (seen): result not found")
	}
	return results, false
}
<commit_msg>update seen plugin<commit_after>package seen

import (
	"strings"
	"sync"
	"time"

	"github.com/peted27/gherkin/lib"
	"github.com/peted27/go-ircevent"
)

var (
	db            = Log{}
	command       = "!seen"
	con           *irc.Connection
	timeConnected time.Time
)

// Log is an accessible map of channels to nick to entries.
type Log struct {
	sync.Mutex
	M map[string]map[string]time.Time
}

func Register(c *irc.Connection) {
	con = c
	timeConnected = time.Now()
	c.AddCallback("PRIVMSG",
		func(e *irc.Event) {
			if !lib.IsPublicMessage(e) && !lib.IsCommandMessage(e) {
				return
			}
			handle(e)
		})
}

func handle(e *irc.Event) {
	channel := e.Arguments[0]
	text := e.Arguments[1]
	nick := e.Nick
	target := nick

	db.Store(channel, nick, time.Now())

	if !strings.HasPrefix(e.Arguments[1], command) {
		return
	}

	if text != command {
		target = strings.TrimPrefix(text, command+" ")
		target = strings.TrimSpace(target)
	}

	if t, found := db.Search(channel, target); found == false {
		e.Connection.Action(channel, target+" has not been seen (bot online since "+timeConnected.Format("15:04:05 (2006-01-02) MST")+")")
	} else {
		e.Connection.Action(channel, target+" last seen "+t.Format("15:04:05 (2006-01-02) MST"))
	}
}

// Store saves a line from a channel/nick into backlog.
func (l *Log) Store(channel, nick string, seen time.Time) {
	l.Lock()
	defer l.Unlock()

	if l.M == nil {
		if con.Debug {
			con.Log.Println("plugin (seen): creating channel map for " + channel)
		}
		l.M = map[string]map[string]time.Time{}
	}

	if _, p := l.M[channel]; p {
		// update time
		if con.Debug {
			con.Log.Println("plugin (seen): updating seen time for " + nick)
		}
		l.M[channel][nick] = seen
	} else {
		if con.Debug {
			con.Log.Println("plugin (seen): creating nick map for " + nick)
		}
		l.M[channel] = map[string]time.Time{nick: seen}
	}
}

// Search returns backlog lines of a channel/nick.
func (l *Log) Search(channel, nick string) (time.Time, bool) {
	var results time.Time
	l.Lock()
	defer l.Unlock()
	if _, p := l.M[channel]; p {
		if _, q := l.M[channel][nick]; q {
			results := l.M[channel][nick]
			if con.Debug {
				con.Log.Println("plugin (seen): found result")
			}
			return results, true
		}
	}
	if con.Debug {
		con.Log.Println("plugin (seen): result not found")
	}
	return results, false
}
<|endoftext|>