<commit_before>package dms

import (
	"reflect"
	"sync"
	"time"
)

var (
	MaxResolveTime = time.Second * 8
)

type Mod interface {
	Load(loader Loader)
}

type Loader struct {
	reqChan chan req
	proChan chan pro
}

type Sys struct {
	loader Loader
	closed chan struct{}
}

type req struct {
	name string
	p    interface{}
	res  chan error
}

type pro struct {
	name string
	v    interface{}
	res  chan error
}

func New() *Sys {
	closed := make(chan struct{})

	// start keeper
	reqChan := make(chan req)
	proChan := make(chan pro)
	go func() {
		keep := make(map[string]reflect.Value)
		reqs := make(map[string][]req)
		for {
			select {
			case r := <-reqChan:
				if v, ok := keep[r.name]; ok {
					if target := reflect.ValueOf(r.p).Elem(); target.Type() != v.Type() {
						r.res <- ErrTypeMismatch{v.Type(), target.Type()}
					} else {
						target.Set(v)
						r.res <- nil
					}
				} else {
					reqs[r.name] = append(reqs[r.name], r)
				}
			case p := <-proChan:
				if _, ok := keep[p.name]; ok {
					p.res <- ErrDuplicatedProvision{p.name}
				} else {
					v := reflect.ValueOf(p.v)
					keep[p.name] = v
					for _, r := range reqs[p.name] {
						if target := reflect.ValueOf(r.p).Elem(); target.Type() != v.Type() {
							r.res <- ErrTypeMismatch{v.Type(), target.Type()}
						} else {
							target.Set(v)
							r.res <- nil
						}
					}
					reqs[p.name] = reqs[p.name][0:0]
					p.res <- nil
				}
			case <-closed:
				return
			}
		}
	}()

	return &Sys{
		loader: Loader{
			reqChan: reqChan,
			proChan: proChan,
		},
		closed: closed,
	}
}

func (s *Sys) Close() {
	close(s.closed)
}

func (s *Sys) Load(mod Mod) {
	mod.Load(s.loader)
}

var resChanPool = sync.Pool{
	New: func() interface{} {
		return make(chan error)
	},
}

func (l Loader) Require(name string, p interface{}) {
	res := resChanPool.Get().(chan error)
	l.reqChan <- req{
		name: name,
		p:    p,
		res:  res,
	}
	select {
	case err := <-res:
		if err != nil {
			panic(err)
		}
	case <-time.After(MaxResolveTime):
		panic(ErrNotProvided{name})
	}
	resChanPool.Put(res)
}

func (l Loader) Provide(name string, v interface{}) {
	res := resChanPool.Get().(chan error)
	l.proChan <- pro{
		name: name,
		v:    v,
		res:  res,
	}
	if err := <-res; err != nil {
		panic(err)
	}
	resChanPool.Put(res)
}

type Cast struct {
	fns  []interface{}
	what reflect.Type
}

func NewCast(castType interface{}) *Cast {
	what := reflect.TypeOf(castType).Elem()
	if _, ok := castHandlers[what]; !ok {
		panic(ErrUnknownCastType{what})
	}
	return &Cast{
		what: what,
	}
}

var castHandlers = map[reflect.Type]func(fn interface{}, args []interface{}){
	reflect.TypeOf((*func())(nil)).Elem(): func(fn interface{}, args []interface{}) {
		fn.(func())()
	},
	reflect.TypeOf((*func(int))(nil)).Elem(): func(fn interface{}, args []interface{}) {
		fn.(func(int))(args[0].(int))
	},
}

func AddCastType(p interface{}, handler func(fn interface{}, args []interface{})) {
	castHandlers[reflect.TypeOf(p).Elem()] = handler
}

func (c *Cast) Call(args ...interface{}) {
	handler := castHandlers[c.what]
	for _, fn := range c.fns {
		handler(fn, args)
	}
}

func (c *Cast) Pcall(args ...interface{}) {
	handler := castHandlers[c.what]
	wg := new(sync.WaitGroup)
	wg.Add(len(c.fns))
	for _, fn := range c.fns {
		fn := fn
		go func() {
			handler(fn, args)
			wg.Done()
		}()
	}
	wg.Wait()
}

func (c *Cast) Add(fn interface{}) {
	if reflect.TypeOf(fn) != c.what {
		panic(ErrBadCastFunc{fn})
	}
	c.fns = append(c.fns, fn)
}

type Duration struct {
	cond    *sync.Cond
	state   map[string]struct{}
	waiting int
}

func NewDuration() *Duration {
	d := &Duration{
		cond: sync.NewCond(new(sync.Mutex)),
	}
	d.Start()
	return d
}

func (d *Duration) Start() {
	d.state = make(map[string]struct{})
	d.waiting = 0
}

func (d *Duration) Wait(what string) {
	d.cond.L.Lock()
	d.waiting++
	for _, ok := d.state[what]; !ok; _, ok = d.state[what] {
		d.cond.Wait()
	}
	d.waiting--
	d.cond.L.Unlock()
}

func (d *Duration) Done(what string) {
	d.cond.L.Lock()
	d.state[what] = struct{}{}
	d.cond.Broadcast()
	d.cond.L.Unlock()
}

func (d *Duration) End() {
	d.cond.L.Lock()
	if d.waiting != 0 {
		panic(ErrStarvation{})
	}
	d.cond.L.Unlock()
}
<commit_msg>unify req and pro structs to call<commit_after>package dms

import (
	"reflect"
	"sync"
	"time"
)

var (
	MaxResolveTime = time.Second * 8
)

type Mod interface {
	Load(loader Loader)
}

type Loader struct {
	reqChan chan call
	proChan chan call
}

type Sys struct {
	loader Loader
	closed chan struct{}
}

type call struct {
	str   string
	iface interface{}
	res   chan error
}

func New() *Sys {
	closed := make(chan struct{})

	// start keeper
	reqChan := make(chan call)
	proChan := make(chan call)
	go func() {
		keep := make(map[string]reflect.Value)
		reqs := make(map[string][]call)
		for {
			select {
			case r := <-reqChan:
				if v, ok := keep[r.str]; ok {
					if target := reflect.ValueOf(r.iface).Elem(); target.Type() != v.Type() {
						r.res <- ErrTypeMismatch{v.Type(), target.Type()}
					} else {
						target.Set(v)
						r.res <- nil
					}
				} else {
					reqs[r.str] = append(reqs[r.str], r)
				}
			case p := <-proChan:
				if _, ok := keep[p.str]; ok {
					p.res <- ErrDuplicatedProvision{p.str}
				} else {
					v := reflect.ValueOf(p.iface)
					keep[p.str] = v
					for _, r := range reqs[p.str] {
						if target := reflect.ValueOf(r.iface).Elem(); target.Type() != v.Type() {
							r.res <- ErrTypeMismatch{v.Type(), target.Type()}
						} else {
							target.Set(v)
							r.res <- nil
						}
					}
					reqs[p.str] = reqs[p.str][0:0]
					p.res <- nil
				}
			case <-closed:
				return
			}
		}
	}()

	return &Sys{
		loader: Loader{
			reqChan: reqChan,
			proChan: proChan,
		},
		closed: closed,
	}
}

func (s *Sys) Close() {
	close(s.closed)
}

func (s *Sys) Load(mod Mod) {
	mod.Load(s.loader)
}

var resChanPool = sync.Pool{
	New: func() interface{} {
		return make(chan error)
	},
}

func (l Loader) Require(name string, p interface{}) {
	res := resChanPool.Get().(chan error)
	l.reqChan <- call{
		str:   name,
		iface: p,
		res:   res,
	}
	select {
	case err := <-res:
		if err != nil {
			panic(err)
		}
	case <-time.After(MaxResolveTime):
		panic(ErrNotProvided{name})
	}
	resChanPool.Put(res)
}

func (l Loader) Provide(name string, v interface{}) {
	res := resChanPool.Get().(chan error)
	l.proChan <- call{
		str:   name,
		iface: v,
		res:   res,
	}
	if err := <-res; err != nil {
		panic(err)
	}
	resChanPool.Put(res)
}

type Cast struct {
	fns  []interface{}
	what reflect.Type
}

func NewCast(castType interface{}) *Cast {
	what := reflect.TypeOf(castType).Elem()
	if _, ok := castHandlers[what]; !ok {
		panic(ErrUnknownCastType{what})
	}
	return &Cast{
		what: what,
	}
}

var castHandlers = map[reflect.Type]func(fn interface{}, args []interface{}){
	reflect.TypeOf((*func())(nil)).Elem(): func(fn interface{}, args []interface{}) {
		fn.(func())()
	},
	reflect.TypeOf((*func(int))(nil)).Elem(): func(fn interface{}, args []interface{}) {
		fn.(func(int))(args[0].(int))
	},
}

func AddCastType(p interface{}, handler func(fn interface{}, args []interface{})) {
	castHandlers[reflect.TypeOf(p).Elem()] = handler
}

func (c *Cast) Call(args ...interface{}) {
	handler := castHandlers[c.what]
	for _, fn := range c.fns {
		handler(fn, args)
	}
}

func (c *Cast) Pcall(args ...interface{}) {
	handler := castHandlers[c.what]
	wg := new(sync.WaitGroup)
	wg.Add(len(c.fns))
	for _, fn := range c.fns {
		fn := fn
		go func() {
			handler(fn, args)
			wg.Done()
		}()
	}
	wg.Wait()
}

func (c *Cast) Add(fn interface{}) {
	if reflect.TypeOf(fn) != c.what {
		panic(ErrBadCastFunc{fn})
	}
	c.fns = append(c.fns, fn)
}

type Duration struct {
	cond    *sync.Cond
	state   map[string]struct{}
	waiting int
}

func NewDuration() *Duration {
	d := &Duration{
		cond: sync.NewCond(new(sync.Mutex)),
	}
	d.Start()
	return d
}

func (d *Duration) Start() {
	d.state = make(map[string]struct{})
	d.waiting = 0
}

func (d *Duration) Wait(what string) {
	d.cond.L.Lock()
	d.waiting++
	for _, ok := d.state[what]; !ok; _, ok = d.state[what] {
		d.cond.Wait()
	}
	d.waiting--
	d.cond.L.Unlock()
}

func (d *Duration) Done(what string) {
	d.cond.L.Lock()
	d.state[what] = struct{}{}
	d.cond.Broadcast()
	d.cond.L.Unlock()
}

func (d *Duration) End() {
	d.cond.L.Lock()
	if d.waiting != 0 {
		panic(ErrStarvation{})
	}
	d.cond.L.Unlock()
}
<|endoftext|>


<commit_before>// Copyright 2012 The Gorilla 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 gorilla/reverse is a set of utilities to create request routers.

If provides interfaces to match and extract variables from an HTTP request
and build URLs for registered routes. It also has a variety of matcher
implementations for all kinds of request attributes, among other utilities.

For example, the Regexp type produces reversible regular expressions that
can be used to generate URLs for a regexp-based mux. To demonstrate, let's
compile a simple regexp:

	regexp, err := reverse.CompileRegexp(`/foo/1(\d+)3`)

Now we can call regexp.Revert() passing variables to fill the capturing groups.
Because our variable is not named, we use an empty string as key for
url.Values, like this:

	// url is "/foo/123".
	url, err := regexp.Revert(url.Values{"": {"2"}})

Non-capturing groups are ignored, but named capturing groups can be filled
normally. Just set the key in url.Values:

	regexp, err := reverse.CompileRegexp(`/foo/1(?P<two>\d+)3`)
	if err != nil {
		panic(err)
	}
	// url is "/foo/123".
	url, err := re.Revert(url.Values{"two": {"2"}})

There are a few limitations that can't be changed:

1. Nested capturing groups are ignored; only the outermost groups become
a placeholder. So in `1(\d+([a-z]+))3` there is only one placeholder
although there are two capturing groups: re.Revert(url.Values{"": {"2", "a"}})
results in "123" and not "12a3".

2. Literals inside capturing groups are ignored; the whole group becomes
a placeholder.
*/
package reverse
<commit_msg>Fix typo in doc.go<commit_after>// Copyright 2012 The Gorilla 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 gorilla/reverse is a set of utilities to create request routers.

It provides interfaces to match and extract variables from an HTTP request
and build URLs for registered routes. It also has a variety of matcher
implementations for all kinds of request attributes, among other utilities.

For example, the Regexp type produces reversible regular expressions that
can be used to generate URLs for a regexp-based mux. To demonstrate, let's
compile a simple regexp:

	regexp, err := reverse.CompileRegexp(`/foo/1(\d+)3`)

Now we can call regexp.Revert() passing variables to fill the capturing groups.
Because our variable is not named, we use an empty string as key for
url.Values, like this:

	// url is "/foo/123".
	url, err := regexp.Revert(url.Values{"": {"2"}})

Non-capturing groups are ignored, but named capturing groups can be filled
normally. Just set the key in url.Values:

	regexp, err := reverse.CompileRegexp(`/foo/1(?P<two>\d+)3`)
	if err != nil {
		panic(err)
	}
	// url is "/foo/123".
	url, err := re.Revert(url.Values{"two": {"2"}})

There are a few limitations that can't be changed:

1. Nested capturing groups are ignored; only the outermost groups become
a placeholder. So in `1(\d+([a-z]+))3` there is only one placeholder
although there are two capturing groups: re.Revert(url.Values{"": {"2", "a"}})
results in "123" and not "12a3".

2. Literals inside capturing groups are ignored; the whole group becomes
a placeholder.
*/
package reverse
<|endoftext|>


<commit_before>package m3u8

// Copyleft 2013 Alexander I.Grafov aka Axel <grafov@gmail.com>
// Library licensed under GPLv3
//
// ॐ तारे तुत्तारे तुरे स्व

/*

__This is only draft of the library. API may be changed!__

Library may be used for parsing and generation of M3U8 playlists. M3U8 format used in HTTP Live Streaming (Apple HLS) for internet video translations. Also the library may be useful for common M3U format parsing and generation.

Planned support of specific extensions such as Widevine or Verimatrix.

Library coded acordingly with http://tools.ietf.org/html/draft-pantos-http-live-streaming-11

Examples of usage may be found in *_test.go files of a package. Also see below some simple examples.

Create simple media playlist with sliding window of 3 segments and maximum of 50 segments.

	      p, e := NewMediaPlaylist(3, 50)
	      if e != nil {
		      panic(fmt.Sprintf("Create media playlist failed: %s", e))
	      }
				for i := 0; i < 5; i++ {
					e = p.Add(fmt.Sprintf("test%d.ts", i), 5.0)
					if e != nil {
						panic(fmt.Sprintf("Add segment #%d to a media playlist failed: %s", i, e))
					}
				}
				fmt.Println(p.Encode(true).String())

We add 5 testX.ts segments to playlist then encode it to M3U8 format and convert to string.

				f, err := os.Open("sample-playlists/master.m3u8")
				if err != nil {
					fmt.Println(err)
				}
				p := NewMasterPlaylist()
				err = p.Decode(bufio.NewReader(f), false)
				if err != nil {
					fmt.Println(err)
				}

			  fmt.Printf("Playlist object: %+v\n", p)

We are open playlist from the file and parse it as master playlist.

*/
<commit_msg>Fixed godoc file format.<commit_after>// Copyleft 2013 Alexander I.Grafov aka Axel <grafov@gmail.com>
// Library licensed under GPLv3
//
// ॐ तारे तुत्तारे तुरे स्व

/*

__This is only draft of the library. API may be changed!__

Library may be used for parsing and generation of M3U8 playlists. M3U8 format used in HTTP Live Streaming (Apple HLS) for internet video translations. Also the library may be useful for common M3U format parsing and generation.

Planned support of specific extensions such as Widevine or Verimatrix.

Library coded acordingly with http://tools.ietf.org/html/draft-pantos-http-live-streaming-11

Examples of usage may be found in *_test.go files of a package. Also see below some simple examples.

Create simple media playlist with sliding window of 3 segments and maximum of 50 segments.

	      p, e := NewMediaPlaylist(3, 50)
	      if e != nil {
		      panic(fmt.Sprintf("Create media playlist failed: %s", e))
	      }
				for i := 0; i < 5; i++ {
					e = p.Add(fmt.Sprintf("test%d.ts", i), 5.0)
					if e != nil {
						panic(fmt.Sprintf("Add segment #%d to a media playlist failed: %s", i, e))
					}
				}
				fmt.Println(p.Encode(true).String())

We add 5 testX.ts segments to playlist then encode it to M3U8 format and convert to string.

				f, err := os.Open("sample-playlists/master.m3u8")
				if err != nil {
					fmt.Println(err)
				}
				p := NewMasterPlaylist()
				err = p.Decode(bufio.NewReader(f), false)
				if err != nil {
					fmt.Println(err)
				}

			  fmt.Printf("Playlist object: %+v\n", p)

We are open playlist from the file and parse it as master playlist.

*/
package m3u8
<|endoftext|>


<commit_before>/*
Gonew generates new Go project directories. Its produced project
directories contain stub files and initialized repositories (only
git/github supported now). It can be used to create new packages and
commands.

The gonew configuration file is stored at ~/.gonewrc. It is generated the
first time you run gonew. Command line options can be used to override
some details of the configuration file.

Usage:

    gonew [options] cmd NAME
    gonew [options] pkg NAME
    gonew [options] lib NAME PKG

Arguments:

    NAME
            The name of the new project/repo.

    PKG
            The package a library (.go file) belongs to.

Options:

    -host=""
            Repository host if any (currently, "github" is the only
            supported host).

    -user=""
            Username for the repo host (necessary for "github").

    -repo="git"
            Repository type (currently, "git" is the only supported
            repository type).

    -target=""
            Makefile target. The executable name in case the argument
            TYPE is "cmd", package name in case of "pkg". The default
            value based on the argument NAME.

    -help
            Print a usage message

Configuration:

The configuration for gonew is simple. The configuration can provide
default hosts, usernames, and repositories. However, it also contains the
setting of the {{name}} and {{email}} template variables.

The configuration file for gonew (~/.gonewrc) is generated on the spot if
one does not exist. So you do not need to worry about editing it for the
most part.

If you wish to write/edit the configuration file. An example configuration
file can be found at the path

    $GOROOT/src/pkg/github.com/bmatsuo/gonew/gonewrc.example
*/
package documentation
<commit_msg>doc.go: Update option documentation and add example gonew calls.<commit_after>/*
Gonew generates new Go project directories. Its produced project
directories contain stub files and initialized repositories (only
git/github supported now). It can be used to create new packages and
commands.

The gonew configuration file is stored at ~/.gonewrc. It is generated the
first time you run gonew. Command line options can be used to override
some details of the configuration file.

Usage:

    gonew [options] cmd NAME
    gonew [options] pkg NAME
    gonew [options] lib NAME PKG

Arguments:

    NAME
            The name of the new project/repo.

    PKG
            The package a library (.go file) belongs to.

Options:

    -target=""
            Makefile target. The executable name in case the argument
            TYPE is "cmd", package name in case of "pkg". The default
            value based on the argument NAME.

    -repo="git"
            Repository type (currently, "git" is the only supported
            repository type).

    -remote=""
            When passed a url to a remote repository, attempt to
            initialize the remote repository to the new project's
            repository. The url passed in must agree with the host
            specified in the config file (or by -host).

    -host=""
            Repository host if any (currently, "github" is the only
            supported host). The value supplied must agree with the
            value of -repo.

    -user=""
            Username for the repo host (necessary for "github").

    -v
            Print verbose output to the stdout (this intersects with
            some -debug output).

    -debug=-1
            When set to a non-negative value, debugging output will be
            printed.

    -help
            Print a usage message

Configuration:

The configuration for gonew is simple. The configuration can provide
default hosts, usernames, and repositories. However, it also contains the
setting of the {{name}} and {{email}} template variables.

The configuration file for gonew (~/.gonewrc) is generated on the spot if
one does not exist. So you do not need to worry about editing it for the
most part.

If you wish to write/edit the configuration file. An example configuration
file can be found at the path

    $GOROOT/src/pkg/github.com/bmatsuo/gonew/gonewrc.example

Examples:

    gonew -target=mp3lib pkg go-mp3lib
    gonew lib decode mp3lib
    gonew -remote=git@github.com:bmatsuo/goplay.git cmd goplay

*/
package documentation
<|endoftext|>


<commit_before>// The go-rpcgen project is an attempt to create an easy-to-use, open source
// protobuf service binding for the standard Go RPC package.  It provides a
// protoc-gen-go (based on the standard "main" from goprotobuf and leveraging
// its libraries) which has a plugin added to also output RPC stub code.
//
// Prerequisites
//
// You will need the protobuf compiler for your operating system of choice.
// You can retrieve this from http://code.google.com/p/protobuf/downloads/list
// if you do not have it already.  As this package builds a plugin for the
// protoc from that package, you will need to have your $GOPATH/bin in your
// path when you run protoc.
//
// Installation
//
// To install, run the following command:
//   go get -v -u github.com/kylelemons/go-rpcgen/protoc-gen-go
//
// Usage
//
// Usage of the package is pretty straightforward.  Once you have installed the
// protoc-gen-go plugin, you can compile protobufs with the following command
// (where file.proto is the protocol buffer file(s) in question):
//   protoc --go_out=. file.proto
//
// This will generate a file named like file.pb.go which contains, in addition
// to the usual Go bindings for the messages, an interface for each service
// containing the methods for that service and functions for creating and using
// them with the RPC package and a webrpc package.
//
// Configuration
//
// By default, protoc-gen-go will generate both RPC and web-based stubs,
// but this can be configured by setting the GO_STUBS environment variable.
// This variable is a comma-separated list of the stubs to generate.  The known
// stubs are:
//
//   rpc // Generate stubs for net/rpc
//   web // Generate stubs for direct HTTP access, e.g. via AppEngine
//
// Generated Code for RPC
//
// Given the following basic .proto definition:
//
//   package echoservice;
//   message payload {
//       required string message = 1;
//   }
//   service echo_service {
//       rpc echo (payload) returns (payload);
//   }
//
// The protoc-gen-go plugin will generate a service definition similar to below:
//
//   // EchoService is an interface satisfied by the generated client and
//   // which must be implemented by the object wrapped by the server.
//   type EchoService interface {
//       Echo(in *Payload, out *Payload) error
//   }
//
//   // DialEchoService returns a EchoService for calling the EchoService servince.
//   func DialEchoService(addr string) (EchoService, error) {
//
//   // NewEchoServiceClient returns an *rpc.Client wrapper for calling the methods
//   // of EchoService remotely.
//   func NewEchoServiceClient(conn net.Conn) EchoService
//
//   // ListenAndServeEchoService serves the given EchoService backend implementation
//   // on all connections accepted as a result of listening on addr (TCP).
//   func ListenAndServeEchoService(addr string, backend EchoService) error
//
//   // ServeEchoService serves the given EchoService backend implementation on conn.
//   func ServeEchoService(conn net.Conn, backend EchoService) error
//
// Any type which implements EchoService can thus be registered via ServeEchoService
// or ListenAndServeEchoService to be called remotely via NewEchoServiceClient or
// DialEchoService.
//
// Generated Code for WebRPC
//
// In addition to the above, the following are also generated to facilitate
// serving RPCs over the web (e.g. AppEngine; see example_ae/):
//
//   // EchoServiceWeb is the web-based RPC version of the interface which
//   // must be implemented by the object wrapped by the webrpc server.
//   type EchoServiceWeb interface {
//     Echo(r *http.Request, in *Payload, out *Payload) error
//   }
//
//   // NewEchoServiceWebClient returns a webrpc wrapper for calling EchoService
//   // remotely via the web.  The remote URL is the base URL of the webrpc server.
//   func NewEchoServiceWebClient(remote *url.URL, pro webrpc.Protocol) EchoService
//
//   // Register a EchoServiceWeb implementation with the given webrpc ServeMux.
//   // If mux is nil, the default webrpc.ServeMux is used.
//   func RegisterEchoServiceWeb(this EchoServiceWeb, mux webrpc.ServeMux) error
//
// Any type which implements EchoServiceWeb (notice that the handlers also
// receive the *http.Request) can be registered.  The RegisterEchoServiceWeb
// function registers the given backend implementation to be called from the
// web via the webrpc package.
//
// Examples
//
// See the examples/ subdirectory for some complete examples demonstrating
// basic usage.  See the example_ae/ subdirectory for an appengine example and
// for directions about how to deploy go-rpcgen on appengine.
package documentation
<commit_msg>Add acknowledgements<commit_after>// The go-rpcgen project is an attempt to create an easy-to-use, open source
// protobuf service binding for the standard Go RPC package.  It provides a
// protoc-gen-go (based on the standard "main" from goprotobuf and leveraging
// its libraries) which has a plugin added to also output RPC stub code.
//
// Prerequisites
//
// You will need the protobuf compiler for your operating system of choice.
// You can retrieve this from http://code.google.com/p/protobuf/downloads/list
// if you do not have it already.  As this package builds a plugin for the
// protoc from that package, you will need to have your $GOPATH/bin in your
// path when you run protoc.
//
// Installation
//
// To install, run the following command:
//   go get -v -u github.com/kylelemons/go-rpcgen/protoc-gen-go
//
// Usage
//
// Usage of the package is pretty straightforward.  Once you have installed the
// protoc-gen-go plugin, you can compile protobufs with the following command
// (where file.proto is the protocol buffer file(s) in question):
//   protoc --go_out=. file.proto
//
// This will generate a file named like file.pb.go which contains, in addition
// to the usual Go bindings for the messages, an interface for each service
// containing the methods for that service and functions for creating and using
// them with the RPC package and a webrpc package.
//
// Configuration
//
// By default, protoc-gen-go will generate both RPC and web-based stubs,
// but this can be configured by setting the GO_STUBS environment variable.
// This variable is a comma-separated list of the stubs to generate.  The known
// stubs are:
//
//   rpc // Generate stubs for net/rpc
//   web // Generate stubs for direct HTTP access, e.g. via AppEngine
//
// Generated Code for RPC
//
// Given the following basic .proto definition:
//
//   package echoservice;
//   message payload {
//       required string message = 1;
//   }
//   service echo_service {
//       rpc echo (payload) returns (payload);
//   }
//
// The protoc-gen-go plugin will generate a service definition similar to below:
//
//   // EchoService is an interface satisfied by the generated client and
//   // which must be implemented by the object wrapped by the server.
//   type EchoService interface {
//       Echo(in *Payload, out *Payload) error
//   }
//
//   // DialEchoService returns a EchoService for calling the EchoService servince.
//   func DialEchoService(addr string) (EchoService, error) {
//
//   // NewEchoServiceClient returns an *rpc.Client wrapper for calling the methods
//   // of EchoService remotely.
//   func NewEchoServiceClient(conn net.Conn) EchoService
//
//   // ListenAndServeEchoService serves the given EchoService backend implementation
//   // on all connections accepted as a result of listening on addr (TCP).
//   func ListenAndServeEchoService(addr string, backend EchoService) error
//
//   // ServeEchoService serves the given EchoService backend implementation on conn.
//   func ServeEchoService(conn net.Conn, backend EchoService) error
//
// Any type which implements EchoService can thus be registered via ServeEchoService
// or ListenAndServeEchoService to be called remotely via NewEchoServiceClient or
// DialEchoService.
//
// Generated Code for WebRPC
//
// In addition to the above, the following are also generated to facilitate
// serving RPCs over the web (e.g. AppEngine; see example_ae/):
//
//   // EchoServiceWeb is the web-based RPC version of the interface which
//   // must be implemented by the object wrapped by the webrpc server.
//   type EchoServiceWeb interface {
//     Echo(r *http.Request, in *Payload, out *Payload) error
//   }
//
//   // NewEchoServiceWebClient returns a webrpc wrapper for calling EchoService
//   // remotely via the web.  The remote URL is the base URL of the webrpc server.
//   func NewEchoServiceWebClient(remote *url.URL, pro webrpc.Protocol) EchoService
//
//   // Register a EchoServiceWeb implementation with the given webrpc ServeMux.
//   // If mux is nil, the default webrpc.ServeMux is used.
//   func RegisterEchoServiceWeb(this EchoServiceWeb, mux webrpc.ServeMux) error
//
// Any type which implements EchoServiceWeb (notice that the handlers also
// receive the *http.Request) can be registered.  The RegisterEchoServiceWeb
// function registers the given backend implementation to be called from the
// web via the webrpc package.
//
// Examples
//
// See the examples/ subdirectory for some complete examples demonstrating
// basic usage.  See the example_ae/ subdirectory for an appengine example and
// for directions about how to deploy go-rpcgen on appengine.
//
// Acknowledgements
//
// Thanks to the following people:
//   Bill Broadely <bill@broadley.org> - for beta testing and examples
package documentation
<|endoftext|>


<commit_before>/*
Package goa provides the runtime support for goa web services. See also http://goa.design.

package design: https://godoc.org/github.com/goadesign/goa/design

package dsl: https://godoc.org/github.com/goadesign/goa/design/dsl

Code Generation

goa service development begins with writing the *design* of a service. The design is described using
the goa language implemented by the github.com/goadesign/goa/design/dsl package. The goagen tool
consumes the metadata produced from executing the design language to generate service specific code
that glues the underlying HTTP server with action specific code and data structures.

The goa package contains supporting functionality for the generated code including basic request
and response state management through the Context data structure, error handling via the
service and controller ErrorHandler field, middleware support via the Middleware data structure as
well as input (and output) format validation algorithms.

Request Context

The Context data structure provides access to both the request and response state. It implements
the golang.org/x/net/Context interface so that deadlines and cancelation signals may also be
implemented with it.

The request state is accessible through the Get, GetMany and Payload methods which return the values
of the request parameters, query strings and request body. Action specific contexts wrap Context and
expose properly typed fields corresponding to the request parameters and body data structure
descriptions appearing in the design.

The response state can be accessed through the ResponseStatus, ResponseLength and Header methods.
The Context type implements the http.ResponseWriter interface and thus action contexts can be used
in places http.ResponseWriter can. Action contexts provide action specific helper methods that write
the responses as described in the design optionally taking an instance of the media type for
responses that contain a body.

Here is an example showing an "update" action corresponding to following design (extract):

	Resource("bottle", func() {
		DefaultMedia(Bottle)
		Action("update", func() {
			Params(func() {
				Param("bottleID", Integer)
			})
			Payload(UpdateBottlePayload)
			Response(OK)
			Response(NotFound)
		})
	})

The action signature generated by goagen is:

	type BottleController interface {
		goa.Controller
		Update(*UpdateBottleContext) error
	}

where UpdateBottleContext is:

	type UpdateBottleContext struct {
        	*goa.Context
        	BottleID  int
        	Payload   *UpdateBottlePayload
	}

and implements:

	func (ctx *UpdateBottleContext) OK(resp *Bottle) error
	func (ctx *UpdateBottleContext) NotFound() error

The definitions of the Bottle and UpdateBottlePayload data structures are ommitted for brievity.

Controllers

There is one controller interface generated per resource defined via the design language. The
interface exposes the controller actions as well as methods to set controller specific middleware
and error handlers (see below). User code must provide data structures that implement these
interfaces when mounting a controller onto a service. The controller data structure should include
an anonymous field of type *goa.ApplicationController which takes care of implementing the
middleware and error handler handling.

Error Handling

The controller action methods generated by goagen such as the Update method of the BottleController
interface shown above all return an error value. The controller or service-wide error handler (if no
controller specific error handler) function is invoked whenever the value returned by a controller
action is not nil. The handler gets both the request context and the error as argument.

The default handler implementation returns a response with status code 500 containing the error
message in the body. A different error handler can be specificied using the SetErrorHandler
function on either a controller or service wide. goa comes with an alternative error handler - the
TerseErrorHandler - which also returns a response with status 500 but does not write the error
message to the body of the response.

Middleware

A goa middleware is a function that takes and returns a Handler. A Handler is a the low level
function which handles incoming HTTP requests. goagen generates the handlers code so each handler
creates the action specific context and calls the controller action with it.

Middleware can be added to a goa service or a specific controller using the Service type Use method.
goa comes with a few stock middleware that handle common needs such as logging, panic recovery or
using the RequestID header to trace requests across multiple services.

Validation

The goa design language documented in the dsl package makes it possible to attach validations to
data structure definitions. One specific type of validation consists of defining the format that a
data structure string field must follow. Example of formats include email, data time, hostnames etc.
The ValidateFormat function provides the implementation for the format validation invoked from the
code generated by goagen.
*/
package goa
<commit_msg>Update docs<commit_after>/*
Package goa provides the runtime support for goa web services.

Code Generation

goa service development begins with writing the *design* of a service. The design is described using
the goa language implemented by the github.com/goadesign/goa/design/apidsl package. The goagen tool
consumes the metadata produced from executing the design language to generate service specific code
that glues the underlying HTTP server with action specific code and data structures.

The goa package contains supporting functionality for the generated code including basic request
and response state management through the Context data structure, error handling via the
service and controller ErrorHandler field, middleware support via the Middleware data structure as
well as input (and output) format validation algorithms.

Request Context

The Context data structure provides access to both the request and response state. It implements
the golang.org/x/net/Context interface so that deadlines and cancelation signals may also be
implemented with it.

The request state is accessible through the Get, GetMany and Payload methods which return the values
of the request parameters, query strings and request body. Action specific contexts wrap Context and
expose properly typed fields corresponding to the request parameters and body data structure
descriptions appearing in the design.

The response state can be accessed through the ResponseStatus, ResponseLength and Header methods.
The Context type implements the http.ResponseWriter interface and thus action contexts can be used
in places http.ResponseWriter can. Action contexts provide action specific helper methods that write
the responses as described in the design optionally taking an instance of the media type for
responses that contain a body.

Here is an example showing an "update" action corresponding to following design (extract):

	Resource("bottle", func() {
		DefaultMedia(Bottle)
		Action("update", func() {
			Params(func() {
				Param("bottleID", Integer)
			})
			Payload(UpdateBottlePayload)
			Response(OK)
			Response(NotFound)
		})
	})

The action signature generated by goagen is:

	type BottleController interface {
		goa.Controller
		Update(*UpdateBottleContext) error
	}

where UpdateBottleContext is:

	type UpdateBottleContext struct {
        	*goa.Context
        	BottleID  int
        	Payload   *UpdateBottlePayload
	}

and implements:

	func (ctx *UpdateBottleContext) OK(resp *Bottle) error
	func (ctx *UpdateBottleContext) NotFound() error

The definitions of the Bottle and UpdateBottlePayload data structures are ommitted for brievity.

Controllers

There is one controller interface generated per resource defined via the design language. The
interface exposes the controller actions as well as methods to set controller specific middleware
and error handlers (see below). User code must provide data structures that implement these
interfaces when mounting a controller onto a service. The controller data structure should include
an anonymous field of type *goa.ApplicationController which takes care of implementing the
middleware and error handler handling.

Error Handling

The controller action methods generated by goagen such as the Update method of the BottleController
interface shown above all return an error value. The controller or service-wide error handler (if no
controller specific error handler) function is invoked whenever the value returned by a controller
action is not nil. The handler gets both the request context and the error as argument.

The default handler implementation returns a response with status code 500 containing the error
message in the body. A different error handler can be specificied using the SetErrorHandler
function on either a controller or service wide. goa comes with an alternative error handler - the
TerseErrorHandler - which also returns a response with status 500 but does not write the error
message to the body of the response.

Middleware

A goa middleware is a function that takes and returns a Handler. A Handler is a the low level
function which handles incoming HTTP requests. goagen generates the handlers code so each handler
creates the action specific context and calls the controller action with it.

Middleware can be added to a goa service or a specific controller using the Service type Use method.
goa comes with a few stock middleware that handle common needs such as logging, panic recovery or
using the RequestID header to trace requests across multiple services.

Validation

The goa design language documented in the dsl package makes it possible to attach validations to
data structure definitions. One specific type of validation consists of defining the format that a
data structure string field must follow. Example of formats include email, data time, hostnames etc.
The ValidateFormat function provides the implementation for the format validation invoked from the
code generated by goagen.

Encoding

The goa design language makes it possible to specify the encodings supported by the API both as
input (Consumes) and output (Produces). goagen uses that information to registed the corresponding
packages with the service encoders and decoders via the SetEncoder and SetDecoder methods. The
service exposes the Decode, DecodeRequest, Encode and EncodeResponse that implement a simple content
type negotiation algorithm for picking the right encoder for the "Accept" request header.
*/
package goa
<|endoftext|>


<commit_before>/*
Package hitbot allows for easy bot creation for Hitbox.tv streaming platform.

Setup:

To create bot instance use:
    bot := hitbox.NewBot("name")

Then you need to get server list:
    bot.GetServers()

After that you need to get connection id for one of the servers:
    bot.GetID()

Before you can connect, you have to login to Hitbox.tv for access token. Following command does it for you:
    bot.Auth("pass")

At any point you can register commands by using provided BasicCmd handler factory, or create your own. To create basic cmd response:
    bot.BasicCmd("response")

For custom handlers use:
    bot.RegisterHandler("cmdname", handler)
Where `handler` is:
    func handler(params map[string]interface{}) (string, string){
        //returns channel and response text
    }

If you don't want your bot's name to be white, you can set color with:
    bot.NameColor("hex value without `#`")

Then you can finally connect, and start MessageHandler:
    bot.Connect("channel")
    bot.MessageHandler()

Channels specified in Connect method will be joined as soon as MessageHandler recieves confirmation for connection, you can still join channels manually, just make sure it happens after confirmation.
Keep in mind, you can run MessageHandler as goroutine, so you can perform actions within your program.
*/
package hitbot
<commit_msg>Another doc fix :8ball:<commit_after>/*
Package hitbot allows for easy bot creation for Hitbox.tv streaming platform.

Setup:

To create bot instance use:
    bot := hitbox.NewBot("name")

Then you need to get server list:
    bot.GetServers()

After that you need to get connection id for one of the servers:
    bot.GetID()

Before you can connect, you have to login to Hitbox.tv for access token. Following command does it for you:
    bot.Auth("pass")

At any point you can register commands by using provided BasicCmd handler factory, or create your own. To create basic cmd response:
    bot.BasicCmd("cmdname","response")

For custom handlers use:
    bot.RegisterHandler("cmdname", handler)
Where `handler` is:
    func handler(params map[string]interface{}) (string, string){
        //returns channel and response text
    }

If you don't want your bot's name to be white, you can set color with:
    bot.NameColor("hex value without `#`")

Then you can finally connect, and start MessageHandler:
    bot.Connect("channel")
    bot.MessageHandler()

Channels specified in Connect method will be joined as soon as MessageHandler recieves confirmation for connection, you can still join channels manually, just make sure it happens after confirmation.
Keep in mind, you can run MessageHandler as goroutine, so you can perform actions within your program.
*/
package hitbot
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"code.google.com/p/gopass"
	"codebook/cblib"
	"flag"
	"fmt"
	"os"
)

const (
	VERSION = "0.3"
)

func printUsage() {
	help := "\nUsage: codebook [--version] [--help] <command> [<args>]\n" +
		"\nPassword Management Tools Simplified.\n\nCommands:\n"

	for _, command := range [][]string{
		{"new <website>", "Generate A New Random Password for <website>"},
		{"set <website> <password>", "Set <password> for <website>"},
		{"get <website>", "Get the password for <website>"},
		{"get all", "Get the password for all stored websites"},
	} {
		help += fmt.Sprintf("    %-30.300s%s\n", command[0], command[1])
	}
	fmt.Fprintf(os.Stdout, "%s\n", help)
}

func parseFlags() bool {
	// flag parsing
	var help = flag.Bool("help", false, "Codebook is the tool to manage your passcode for all websites.")
	var version = flag.Bool("version", false, "")

	flag.Parse()

	if *help {
		printUsage()
		return true
	} else if *version {
		fmt.Println(VERSION)
		return true
	}
	return false
}

func main() {
	if len(os.Args) < 2 {
		printUsage()
		return
	}

	if parseFlags() {
		return
	}

	master_key, err := gopass.GetPass(
		"Enter master key (recommended shorter than 16 bytes): ")
	if err != nil {
		panic(err)
	}

	c := cblib.Init(master_key)
	command := os.Args[1]
	website := []byte(os.Args[2])

	switch command {
	case "get":
		if bytes.Equal(website, []byte("all")) {
			c.PrintPlain()
			return
		}
		if pwd, err := c.Get(website); err == nil {
			fmt.Println(string(pwd))
			cblib.CopyToClipBoard(string(pwd))
		} else {
			panic(err)
		}
	case "new":
		var y_or_n string
		if pwd, err := c.Get(website); err == nil {
			fmt.Println(pwd)
			fmt.Println("Password already exists for", string(website))
		} else {
			new_code := cblib.NewPasscodeHard(15)
			fmt.Println(
				"The password for", string(website),
				"is", string(new_code),
				"\nAccept? (y/N):")
			_, _ = fmt.Scanf("%s", &y_or_n)
			if y_or_n != "N" || y_or_n != "n" {
				// when we add, it's encrypted
				c.Add(website, new_code)
				c.Save()
				cblib.CopyToClipBoard(string(new_code))
			}
		}
	}
}
<commit_msg>minor output fix<commit_after>package main

import (
	"bytes"
	"code.google.com/p/gopass"
	"codebook/cblib"
	"flag"
	"fmt"
	"os"
)

const (
	VERSION = "0.3"
)

func printUsage() {
	help := "Usage: codebook [--version] [--help] <command> [<args>]\n" +
		"\nPassword Management Tools Simplified.\n\nCommands:\n"

	for _, command := range [][]string{
		{"new <website>", "Generate a new random password for <website>"},
		{"get <website>", "Get the password for <website>"},
		{"get all", "Get the password for all stored websites"},
	} {
		help += fmt.Sprintf("    %-30.300s%s\n", command[0], command[1])
	}
	fmt.Fprintf(os.Stdout, "%s\n", help)
}

func parseFlags() bool {
	// flag parsing
	var help = flag.Bool("help", false, "Codebook is the tool to manage your passcode for all websites.")
	var version = flag.Bool("version", false, "")

	flag.Parse()

	if *help {
		printUsage()
		return true
	} else if *version {
		fmt.Println(VERSION)
		return true
	}
	return false
}

func main() {
	if len(os.Args) < 2 {
		printUsage()
		return
	}

	if parseFlags() {
		return
	}

	master_key, err := gopass.GetPass(
		"Enter master key (recommended shorter than 16 bytes): ")
	if err != nil {
		panic(err)
	}

	c := cblib.Init(master_key)
	command := os.Args[1]
	website := []byte(os.Args[2])

	switch command {
	case "get":
		if bytes.Equal(website, []byte("all")) {
			c.PrintPlain()
			return
		}
		if pwd, err := c.Get(website); err == nil {
			fmt.Println(string(pwd))
			cblib.CopyToClipBoard(string(pwd))
		} else {
			panic(err)
		}
	case "new":
		var y_or_n string
		if pwd, err := c.Get(website); err == nil {
			fmt.Println(pwd)
			fmt.Println("Password already exists for", string(website))
		} else {
			new_code := cblib.NewPasscodeHard(15)
			fmt.Println(
				"The password for", string(website),
				"is", string(new_code),
				"\nAccept? (y/N):")
			_, _ = fmt.Scanf("%s", &y_or_n)
			if y_or_n != "N" || y_or_n != "n" {
				// when we add, it's encrypted
				c.Add(website, new_code)
				c.Save()
				cblib.CopyToClipBoard(string(new_code))
			}
		}
	}
}
<|endoftext|>


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

package shlib_test

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"

	"github.com/zombiezen/mcm/catalog"
	"github.com/zombiezen/mcm/internal/catpogs"
	"github.com/zombiezen/mcm/shellify/shlib"
)

func TestIntegration(t *testing.T) {
	bashPath, err := exec.LookPath("bash")
	if err != nil {
		t.Skipf("Can't find bash: %v", err)
	}
	t.Logf("using %s for bash", bashPath)
	t.Run("file", func(t *testing.T) { fileIntegrationTest(t, bashPath) })
}

func fileIntegrationTest(t *testing.T, bashPath string) {
	root, deleteTempDir, err := makeTempDir(t)
	if err != nil {
		t.Fatalf("temp directory: %v", err)
	}
	defer deleteTempDir()
	fpath := filepath.Join(root, "foo.txt")
	const fileContent = "Hello!\n"
	c, err := (&catpogs.Catalog{
		Resources: []*catpogs.Resource{
			{
				ID:      42,
				Comment: "file",
				Which:   catalog.Resource_Which_file,
				File:    catpogs.PlainFile(fpath, []byte(fileContent)),
			},
		},
	}).ToCapnp()
	if err != nil {
		t.Fatalf("build catalog: %v", err)
	}
	_, err = runCatalog(bashPath, t, c)
	if err != nil {
		t.Errorf("run catalog: %v", err)
	}
	gotContent, err := ioutil.ReadFile(fpath)
	if err != nil {
		t.Errorf("read %s: %v", fpath, err)
	}
	if !bytes.Equal(gotContent, []byte(fileContent)) {
		t.Errorf("content of %s = %q; want %q", fpath, gotContent, fileContent)
	}
}

const tmpDirEnv = "TEST_TMPDIR"

func runCatalog(bashPath string, log logger, c catalog.Catalog, args ...string) ([]byte, error) {
	sc, err := ioutil.TempFile(os.Getenv(tmpDirEnv), "shlib_testscript")
	if err != nil {
		return nil, err
	}
	scriptPath := sc.Name()
	defer func() {
		if err := os.Remove(scriptPath); err != nil {
			log.Logf("removing temporary script file: %v", err)
		}
	}()
	err = shlib.WriteScript(sc, c)
	cerr := sc.Close()
	if err != nil {
		return nil, err
	}
	if cerr != nil {
		return nil, cerr
	}
	log.Logf("%s -- %s %s", bashPath, scriptPath, strings.Join(args, " "))
	cmd := exec.Command(bashPath, append([]string{"--", scriptPath}, args...)...)
	stdout := new(bytes.Buffer)
	cmd.Stdout = stdout
	stderr := new(bytes.Buffer)
	cmd.Stderr = stderr
	if err := cmd.Run(); err != nil {
		return stdout.Bytes(), fmt.Errorf("bash failed: %v; stderr:\n%s", err, stderr.Bytes())
	}
	return stdout.Bytes(), nil
}

func makeTempDir(log logger) (path string, done func(), err error) {
	path, err = ioutil.TempDir(os.Getenv(tmpDirEnv), "shlib_testdir")
	if err != nil {
		return "", nil, err
	}
	return path, func() {
		if err := os.RemoveAll(path); err != nil {
			log.Logf("removing temporary directory: %v", err)
		}
	}, nil
}

type logger interface {
	Logf(string, ...interface{})
}
<commit_msg>shellify: add link tests<commit_after>// Copyright 2016 The Minimal Configuration Manager Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package shlib_test

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"

	"github.com/zombiezen/mcm/catalog"
	"github.com/zombiezen/mcm/internal/catpogs"
	"github.com/zombiezen/mcm/shellify/shlib"
)

func TestIntegration(t *testing.T) {
	bashPath, err := exec.LookPath("bash")
	if err != nil {
		t.Skipf("Can't find bash: %v", err)
	}
	t.Logf("using %s for bash", bashPath)
	t.Run("Empty", func(t *testing.T) { emptyTest(t, bashPath) })
	t.Run("File", func(t *testing.T) { fileTest(t, bashPath) })
	t.Run("Link", func(t *testing.T) { linkTest(t, bashPath) })
	t.Run("Relink", func(t *testing.T) { relinkTest(t, bashPath) })
}

func emptyTest(t *testing.T, bashPath string) {
	c, err := new(catpogs.Catalog).ToCapnp()
	if err != nil {
		t.Fatalf("build empty catalog: %v", err)
	}
	_, err = runCatalog(bashPath, t, c)
	if err != nil {
		t.Errorf("run catalog: %v", err)
	}
}

func fileTest(t *testing.T, bashPath string) {
	root, deleteTempDir, err := makeTempDir(t)
	if err != nil {
		t.Fatalf("temp directory: %v", err)
	}
	defer deleteTempDir()
	fpath := filepath.Join(root, "foo.txt")
	const fileContent = "Hello!\n"
	c, err := (&catpogs.Catalog{
		Resources: []*catpogs.Resource{
			{
				ID:      42,
				Comment: "file",
				Which:   catalog.Resource_Which_file,
				File:    catpogs.PlainFile(fpath, []byte(fileContent)),
			},
		},
	}).ToCapnp()
	if err != nil {
		t.Fatalf("build catalog: %v", err)
	}
	_, err = runCatalog(bashPath, t, c)
	if err != nil {
		t.Errorf("run catalog: %v", err)
	}
	gotContent, err := ioutil.ReadFile(fpath)
	if err != nil {
		t.Errorf("read %s: %v", fpath, err)
	}
	if !bytes.Equal(gotContent, []byte(fileContent)) {
		t.Errorf("content of %s = %q; want %q", fpath, gotContent, fileContent)
	}
}

func linkTest(t *testing.T, bashPath string) {
	t.Skip("TODO(now): links not implemented")

	root, deleteTempDir, err := makeTempDir(t)
	if err != nil {
		t.Fatalf("temp directory: %v", err)
	}
	defer deleteTempDir()
	fpath := filepath.Join(root, "foo")
	lpath := filepath.Join(root, "link")
	c, err := (&catpogs.Catalog{
		Resources: []*catpogs.Resource{
			{
				ID:      42,
				Comment: "file",
				Which:   catalog.Resource_Which_file,
				File:    catpogs.PlainFile(fpath, []byte("Hello")),
			},
			{
				ID:      100,
				Deps:    []uint64{42},
				Comment: "link",
				Which:   catalog.Resource_Which_file,
				File:    catpogs.SymlinkFile(fpath, lpath),
			},
		},
	}).ToCapnp()
	if err != nil {
		t.Fatalf("build catalog: %v", err)
	}
	_, err = runCatalog(bashPath, t, c)
	if err != nil {
		t.Errorf("run catalog: %v", err)
	}

	if info, err := os.Lstat(lpath); err == nil {
		if info.Mode()&os.ModeType != os.ModeSymlink {
			t.Errorf("os.Lstat(%q).Mode() = %v; want symlink", lpath, info.Mode())
		}
	} else {
		t.Errorf("os.Lstat(%q): %v", lpath, err)
	}
	if target, err := os.Readlink(lpath); err == nil {
		if target != fpath {
			t.Errorf("os.Readlink(%q) = %q; want %q", lpath, target, fpath)
		}
	} else {
		t.Errorf("os.Readlink(%q): %v", lpath, err)
	}
}

func relinkTest(t *testing.T, bashPath string) {
	t.Skip("TODO(now): links not implemented")

	root, deleteTempDir, err := makeTempDir(t)
	if err != nil {
		t.Fatalf("temp directory: %v", err)
	}
	defer deleteTempDir()
	f1path := filepath.Join(root, "foo")
	f2path := filepath.Join(root, "bar")
	lpath := filepath.Join(root, "link")
	c, err := (&catpogs.Catalog{
		Resources: []*catpogs.Resource{
			{
				ID:      42,
				Comment: "link",
				Which:   catalog.Resource_Which_file,
				File:    catpogs.SymlinkFile(f2path, lpath),
			},
		},
	}).ToCapnp()
	if err != nil {
		t.Fatalf("build catalog: %v", err)
	}
	if err := ioutil.WriteFile(f1path, []byte("File 1"), 0666); err != nil {
		t.Fatal("WriteFile 1:", err)
	}
	if err := ioutil.WriteFile(f2path, []byte("File 2"), 0666); err != nil {
		t.Fatal("WriteFile 2:", err)
	}
	if err := os.Symlink(f1path, lpath); err != nil {
		t.Fatalf("os.Symlink %s -> %s: %v", lpath, f1path, err)
	}
	_, err = runCatalog(bashPath, t, c)
	if err != nil {
		t.Errorf("run catalog: %v", err)
	}

	if info, err := os.Lstat(lpath); err == nil {
		if info.Mode()&os.ModeType != os.ModeSymlink {
			t.Errorf("os.Lstat(%q).Mode() = %v; want symlink", lpath, info.Mode())
		}
	} else {
		t.Errorf("os.Lstat(%q): %v", lpath, err)
	}
	if target, err := os.Readlink(lpath); err == nil {
		if target != f2path {
			t.Errorf("os.Readlink(%q) = %q; want %q", lpath, target, f2path)
		}
	} else {
		t.Errorf("os.Readlink(%q): %v", lpath, err)
	}
}

const tmpDirEnv = "TEST_TMPDIR"

func runCatalog(bashPath string, log logger, c catalog.Catalog, args ...string) ([]byte, error) {
	sc, err := ioutil.TempFile(os.Getenv(tmpDirEnv), "shlib_testscript")
	if err != nil {
		return nil, err
	}
	scriptPath := sc.Name()
	defer func() {
		if err := os.Remove(scriptPath); err != nil {
			log.Logf("removing temporary script file: %v", err)
		}
	}()
	err = shlib.WriteScript(sc, c)
	cerr := sc.Close()
	if err != nil {
		return nil, err
	}
	if cerr != nil {
		return nil, cerr
	}
	log.Logf("%s -- %s %s", bashPath, scriptPath, strings.Join(args, " "))
	cmd := exec.Command(bashPath, append([]string{"--", scriptPath}, args...)...)
	stdout := new(bytes.Buffer)
	cmd.Stdout = stdout
	stderr := new(bytes.Buffer)
	cmd.Stderr = stderr
	if err := cmd.Run(); err != nil {
		return stdout.Bytes(), fmt.Errorf("bash failed: %v; stderr:\n%s", err, stderr.Bytes())
	}
	return stdout.Bytes(), nil
}

func makeTempDir(log logger) (path string, done func(), err error) {
	path, err = ioutil.TempDir(os.Getenv(tmpDirEnv), "shlib_testdir")
	if err != nil {
		return "", nil, err
	}
	return path, func() {
		if err := os.RemoveAll(path); err != nil {
			log.Logf("removing temporary directory: %v", err)
		}
	}, nil
}

type logger interface {
	Logf(string, ...interface{})
}
<|endoftext|>


<commit_before>// Package globus implements MG-RAST OAuth authentication
package mgrast

import (
	"encoding/json"
	"errors"
	"fmt"
	client "github.com/MG-RAST/Shock/shock-client/lib/httpclient"
	"github.com/MG-RAST/Shock/shock-server/conf"
	"github.com/MG-RAST/Shock/shock-server/user"
	"io/ioutil"
	"strconv"
	"strings"
)

type resErr struct {
	error string `json:"error"`
}

type credentials struct {
	Uname  string   `json:"user"`
	Fname  string   `json:"firstname"`
	Lname  string   `json:"lastname"`
	Email  string   `json:"email"`
	Groups []string `json:"groups"`
}

func authHeaderType(header string) string {
	tmp := strings.Split(header, " ")
	if len(tmp) > 1 {
		return strings.ToLower(tmp[0])
	}
	return ""
}

// Auth takes the request authorization header and returns
// user
func Auth(header string) (*user.User, error) {
	switch authHeaderType(header) {
	case "mgrast", "oauth":
		return authToken(strings.Split(header, " ")[1])
	case "basic":
		return nil, errors.New("This authentication method does not support username/password authentication. Please use MG-RAST your token.")
	default:
		return nil, errors.New("Invalid authentication header.")
	}
}

// authToken validiates token by fetching user information.
func authToken(t string) (*user.User, error) {
	url := conf.Conf["mgrast_oauth_url"]
	if url == "" {
		return nil, errors.New("mgrast_oauth_url not set in configuration")
	}

	form := client.NewForm()
	form.AddParam("token", t)
	form.AddParam("action", "credentials")
	form.AddParam("groups", "true")
	err := form.Create()
	if err != nil {
		return nil, err
	}

	headers := client.Header{
		"Content-Type":   form.ContentType,
		"Content-Length": strconv.FormatInt(form.Length, 10),
	}

	if res, err := client.Do("POST", url, headers, form.Reader); err == nil {
		if res.StatusCode == 200 {
			r := credentials{}
			body, _ := ioutil.ReadAll(res.Body)
			if err = json.Unmarshal(body, &r); err != nil {
				return nil, err
			}
			return &user.User{Username: r.Uname, Fullname: r.Fname + " " + r.Lname, Email: r.Email, CustomFields: map[string][]string{"groups": r.Groups}}, nil
		} else {
			r := resErr{}
			body, _ := ioutil.ReadAll(res.Body)
			fmt.Printf("%s\n", body)
			if err = json.Unmarshal(body, &r); err == nil {
				return nil, errors.New("request error: " + res.Status)
			} else {
				return nil, errors.New(res.Status + ": " + r.error)
			}
		}
	}
	return nil, nil
}
<commit_msg>Refactored mgrast auth plug-in to work with current setup.<commit_after>// Package globus implements MG-RAST OAuth authentication
package mgrast

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"github.com/MG-RAST/Shock/shock-server/conf"
	e "github.com/MG-RAST/Shock/shock-server/errors"
	"github.com/MG-RAST/Shock/shock-server/logger"
	"github.com/MG-RAST/Shock/shock-server/user"
	"io/ioutil"
	"net/http"
	"strings"
)

type resErr struct {
	error string `json:"error"`
}

type credentials struct {
	Uname string `json:"login"`
	Fname string `json:"firstname"`
	Lname string `json:"lastname"`
	Email string `json:"email"`
}

func authHeaderType(header string) string {
	tmp := strings.Split(header, " ")
	if len(tmp) > 1 {
		return strings.ToLower(tmp[0])
	}
	return ""
}

// Auth takes the request authorization header and returns
// user
func Auth(header string) (*user.User, error) {
	switch authHeaderType(header) {
	case "mgrast", "oauth":
		return authToken(strings.Split(header, " ")[1])
	case "basic":
		return nil, errors.New("This authentication method does not support username/password authentication. Please use MG-RAST your token.")
	default:
		return nil, errors.New("Invalid authentication header.")
	}
}

// authToken validiates token by fetching user information.
func authToken(t string) (u *user.User, err error) {
	client := &http.Client{
		Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
	}
	req, err := http.NewRequest("GET", conf.Conf["mgrast_oauth_url"], nil)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Auth", t)
	if resp, err := client.Do(req); err == nil {
		defer resp.Body.Close()
		if resp.StatusCode == http.StatusOK {
			if body, err := ioutil.ReadAll(resp.Body); err == nil {
				u = &user.User{}
				c := &credentials{}
				if err = json.Unmarshal(body, &c); err != nil {
					return nil, err
				} else {
					if c.Uname == "" {
						return nil, errors.New(e.InvalidAuth)
					}
					u.Username = c.Uname
					u.Fullname = c.Fname + " " + c.Lname
					u.Email = c.Email
					if err = u.SetMongoInfo(); err != nil {
						return nil, err
					}
				}
			}
		} else if resp.StatusCode == http.StatusForbidden {
			return nil, errors.New(e.InvalidAuth)
		} else {
			err_str := "Authentication failed: Unexpected response status: " + resp.Status
			logger.Error(err_str)
			return nil, errors.New(err_str)
		}
	} else {
		return nil, err
	}
	return
}
<|endoftext|>


<commit_before>// Package env provides convenience wrapper around getting environment variables.
package env

import (
	"errors"
	"fmt"
	"os"
	"strconv"
)

// String gets string variable from the environment and
// returns it if it exists, otherwise it returns the default.
func String(key string, def string) string {
	val := os.Getenv(key)
	if val == "" {
		return def
	}
	return val
}

// MustString panics if an environment variable is not present.
func MustString(key string) string {
	val := os.Getenv(key)
	if val == "" {
		panic(errors.New(fmt.Sprintf("%s must be provided.", key)))
	}
	return val
}

// Int gets int variable from the environment and
// returns it if it exists, otherwise it returns the default.
func Int(key string, def int) int {
	val := os.Getenv(key)
	if val == "" {
		return def
	}

	i, err := strconv.Atoi(val)
	if err != nil {
		return def
	}
	return i
}

// Bool gets boolean variable from the environment and
// returns it if it exists, otherwise it returns the default.
func Bool(key string, def bool) bool {
	val := os.Getenv(key)
	if val == "" {
		return def
	}

	b, err := strconv.ParseBool(val)
	if err != nil {
		return def
	}
	return b
}

// Float gets float variable with a provided bit type from the environment and
// returns it if it exists, otherwise it returns the default.
func Float(key string, def float64, bit int) float64 {
	val := os.Getenv(key)
	if val == "" {
		return def
	}

	f, err := strconv.ParseFloat(val, bit)
	if err != nil {
		return def
	}
	return f
}
<commit_msg>Change MustString behavior from panic to just an os exit.<commit_after>// Package env provides convenience wrapper around getting environment variables.
package env

import (
	"fmt"
	"os"
	"strconv"
)

// String gets string variable from the environment and
// returns it if it exists, otherwise it returns the default.
func String(key string, def string) string {
	val := os.Getenv(key)
	if val == "" {
		return def
	}
	return val
}

// MustString exits if an environment variable is not present.
func MustString(key string) string {
	val := os.Getenv(key)
	if val == "" {
		fmt.Printf("%s must be provided.", key)
		os.Exit(1)
	}
	return val
}

// Int gets int variable from the environment and
// returns it if it exists, otherwise it returns the default.
func Int(key string, def int) int {
	val := os.Getenv(key)
	if val == "" {
		return def
	}

	i, err := strconv.Atoi(val)
	if err != nil {
		return def
	}
	return i
}

// Bool gets boolean variable from the environment and
// returns it if it exists, otherwise it returns the default.
func Bool(key string, def bool) bool {
	val := os.Getenv(key)
	if val == "" {
		return def
	}

	b, err := strconv.ParseBool(val)
	if err != nil {
		return def
	}
	return b
}

// Float gets float variable with a provided bit type from the environment and
// returns it if it exists, otherwise it returns the default.
func Float(key string, def float64, bit int) float64 {
	val := os.Getenv(key)
	if val == "" {
		return def
	}

	f, err := strconv.ParseFloat(val, bit)
	if err != nil {
		return def
	}
	return f
}
<|endoftext|>


<commit_before>package ddb

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

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/urfave/cli"
)

func ScanTable(ctx *cli.Context) error {
	tableName := ctx.String("table")
	printAsJson := ctx.Bool("json-output")

	if tableName == "" {
		cli.ShowSubcommandHelp(ctx)
		return nil
	}

	c := client()
	out, err := c.Scan(&dynamodb.ScanInput{
		TableName: aws.String(tableName),
	})
	if err != nil {
		log.Fatalln("ERROR", err)
	}

	kd := describeTableKey(tableName, c)

	limit := ctx.Int("row-limit")
	for i, item := range out.Items {
		if i >= limit {
			break
		}
		if printAsJson {
			printItemAsJson(item)
		} else {
			printItem(item, kd)
			fmt.Println()
		}
	}

	return nil
}

func printItemAsJson(item map[string]*dynamodb.AttributeValue) {
	values := map[string]interface{}{}

	for k, v := range item {
		val := v.S
		if val == nil {
			val = v.N
		}
		values[k] = *val
	}

	err := json.NewEncoder(os.Stdout).Encode(values)
	if err != nil {
		log.Fatalln("ERROR", err)
	}
}
<commit_msg>Print JSON numbers as numbers<commit_after>package ddb

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strconv"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/urfave/cli"
)

func ScanTable(ctx *cli.Context) error {
	tableName := ctx.String("table")
	printAsJson := ctx.Bool("json-output")

	if tableName == "" {
		cli.ShowSubcommandHelp(ctx)
		return nil
	}

	c := client()
	out, err := c.Scan(&dynamodb.ScanInput{
		TableName: aws.String(tableName),
	})
	if err != nil {
		log.Fatalln("ERROR", err)
	}

	kd := describeTableKey(tableName, c)

	limit := ctx.Int("row-limit")
	for i, item := range out.Items {
		if i >= limit {
			break
		}
		if printAsJson {
			printItemAsJson(item)
		} else {
			printItem(item, kd)
			fmt.Println()
		}
	}

	return nil
}

func printItemAsJson(item map[string]*dynamodb.AttributeValue) {
	values := map[string]interface{}{}

	for k, v := range item {
		if v.S != nil {
			values[k] = *v.S
		} else if v.N != nil {
			c, err := strconv.Atoi(*v.N)
			if err != nil {
				log.Fatalln("ERROR", err)
			}

			values[k] = c
		}
	}

	err := json.NewEncoder(os.Stdout).Encode(values)
	if err != nil {
		log.Fatalln("ERROR", err)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Huawei Technologies Co., Ltd. All Rights Reserved.
//
// 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.

/*
This module implements a entry into the OpenSDS service.

*/

package cli

import (
	"encoding/json"
	"os"

	"github.com/opensds/opensds/pkg/model"
	"github.com/spf13/cobra"
)

var volumeAttachmentCommand = &cobra.Command{
	Use:   "attachment",
	Short: "manage volume attachments in the cluster",
	Run:   volumeAttachmentAction,
}

var volumeAttachmentCreateCommand = &cobra.Command{
	Use:   "create <attachment info>",
	Short: "create an attachment of specified volume in the cluster",
	Run:   volumeAttachmentCreateAction,
}

var volumeAttachmentShowCommand = &cobra.Command{
	Use:   "show <attachment id>",
	Short: "show a volume attachment in the cluster",
	Run:   volumeAttachmentShowAction,
}

var volumeAttachmentListCommand = &cobra.Command{
	Use:   "list",
	Short: "list all volume attachments in the cluster",
	Run:   volumeAttachmentListAction,
}

var volumeAttachmentDeleteCommand = &cobra.Command{
	Use:   "delete <attachment id>",
	Short: "delete a volume attachment of specified volume in the cluster",
	Run:   volumeAttachmentDeleteAction,
}

var volumeAttachmentUpdateCommand = &cobra.Command{
	Use:   "update <attachment id> <attachment info>",
	Short: "update a volume attachment in the cluster",
	Run:   volumeAttachmentUpdateAction,
}

var (
	volAtmLimit      string
	volAtmOffset     string
	volAtmSortDir    string
	volAtmSortKey    string
	volAtmId         string
	volAtmUserId     string
	volAtmVolumeId   string
	volAtmMountpoint string
	volAtmStatus     string
)

func init() {
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmLimit, "limit", "", "50", "the number of ertries displayed per page")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmOffset, "offset", "", "0", "all requested data offsets")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmSortDir, "sortDir", "", "desc", "the sort direction of all requested data. supports asc or desc(default)")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmSortKey, "sortKey", "", "id",
		"the sort key of all requested data. supports id(default), volumeid, status, userid, tenantid")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmId, "id", "", "", "list volume attachment by id")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmUserId, "userId", "", "", "list volume attachment by storage userId")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmVolumeId, "volumeId", "", "", "list volume attachment by volumeId")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmStatus, "status", "", "", "list volume attachment by status")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmMountpoint, "mountpoint", "", "", "list volume attachment by mountpoint")

	volumeAttachmentCommand.AddCommand(volumeAttachmentCreateCommand)
	volumeAttachmentCommand.AddCommand(volumeAttachmentShowCommand)
	volumeAttachmentCommand.AddCommand(volumeAttachmentListCommand)
	volumeAttachmentCommand.AddCommand(volumeAttachmentDeleteCommand)
	volumeAttachmentCommand.AddCommand(volumeAttachmentUpdateCommand)
}

func volumeAttachmentAction(cmd *cobra.Command, args []string) {
	cmd.Usage()
	os.Exit(1)
}

var attachmentFormatters = FormatterList{"HostInfo": JsonFormatter, "ConnectionInfo": JsonFormatter}

func volumeAttachmentCreateAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 1)
	attachment := &model.VolumeAttachmentSpec{}
	if err := json.Unmarshal([]byte(args[0]), attachment); err != nil {
		Errorln(err)
		cmd.Usage()
		os.Exit(1)
	}
	resp, err := client.CreateVolumeAttachment(attachment)
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
	keys := KeyList{"Id", "CreatedAt", "UpdatedAt", "TenantId", "UserId", "HostInfo", "ConnectionInfo",
		"Mountpoint", "Status", "VolumeId"}
	PrintDict(resp, keys, attachmentFormatters)
}

func volumeAttachmentShowAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 1)
	resp, err := client.GetVolumeAttachment(args[0])
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
	keys := KeyList{"Id", "CreatedAt", "UpdatedAt", "TenantId", "UserId", "HostInfo", "ConnectionInfo",
		"Mountpoint", "Status", "VolumeId", "AccessProtocol"}
	PrintDict(resp, keys, attachmentFormatters)
}

func volumeAttachmentListAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 0)

	var opts = map[string]string{"limit": volAtmLimit, "offset": volAtmOffset,
		"sortDir": volAtmSortDir, "sortKey": volAtmSortKey, "Id": volAtmId,
		"UserId": volAtmUserId, "VolumeId": volAtmVolumeId,
		"Status": volAtmStatus, "Mountpoint": volAtmMountpoint}

	resp, err := client.ListVolumeAttachments(opts)
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
	keys := KeyList{"Id", "TenantId", "UserId", "Mountpoint", "Status", "VolumeId", "AccessProtocol"}
	PrintList(resp, keys, attachmentFormatters)
}

func volumeAttachmentDeleteAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 1)
	attachment := &model.VolumeAttachmentSpec{}
	err := client.DeleteVolumeAttachment(args[0], attachment)
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
}

func volumeAttachmentUpdateAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 2)
	attachment := &model.VolumeAttachmentSpec{}
	if err := json.Unmarshal([]byte(args[1]), attachment); err != nil {
		Errorln(err)
		cmd.Usage()
		os.Exit(1)
	}

	resp, err := client.UpdateVolumeAttachment(args[0], attachment)
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
	keys := KeyList{"Id", "CreatedAt", "UpdatedAt", "TenantId", "UserId", "HostInfo", "ConnectionInfo",
		"Mountpoint", "Status", "VolumeId"}
	PrintDict(resp, keys, attachmentFormatters)
}
<commit_msg>fix bugs<commit_after>// Copyright (c) 2017 Huawei Technologies Co., Ltd. All Rights Reserved.
//
// 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.

/*
This module implements a entry into the OpenSDS service.

*/

package cli

import (
	"encoding/json"
	"os"

	"github.com/opensds/opensds/pkg/model"
	"github.com/spf13/cobra"
)

var volumeAttachmentCommand = &cobra.Command{
	Use:   "attachment",
	Short: "manage volume attachments in the cluster",
	Run:   volumeAttachmentAction,
}

var volumeAttachmentCreateCommand = &cobra.Command{
	Use:   "create <attachment info>",
	Short: "create an attachment of specified volume in the cluster",
	Run:   volumeAttachmentCreateAction,
}

var volumeAttachmentShowCommand = &cobra.Command{
	Use:   "show <attachment id>",
	Short: "show a volume attachment in the cluster",
	Run:   volumeAttachmentShowAction,
}

var volumeAttachmentListCommand = &cobra.Command{
	Use:   "list",
	Short: "list all volume attachments in the cluster",
	Run:   volumeAttachmentListAction,
}

var volumeAttachmentDeleteCommand = &cobra.Command{
	Use:   "delete <attachment id>",
	Short: "delete a volume attachment of specified volume in the cluster",
	Run:   volumeAttachmentDeleteAction,
}

var volumeAttachmentUpdateCommand = &cobra.Command{
	Use:   "update <attachment id> <attachment info>",
	Short: "update a volume attachment in the cluster",
	Run:   volumeAttachmentUpdateAction,
}

var (
	volAtmLimit      string
	volAtmOffset     string
	volAtmSortDir    string
	volAtmSortKey    string
	volAtmId         string
	volAtmUserId     string
	volAtmVolumeId   string
	volAtmMountpoint string
	volAtmStatus     string
)

func init() {
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmLimit, "limit", "", "50", "the number of ertries displayed per page")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmOffset, "offset", "", "0", "all requested data offsets")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmSortDir, "sortDir", "", "desc", "the sort direction of all requested data. supports asc or desc(default)")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmSortKey, "sortKey", "", "id",
		"the sort key of all requested data. supports id(default), volumeid, status, userid, tenantid")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmId, "id", "", "", "list volume attachment by id")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmUserId, "userId", "", "", "list volume attachment by storage userId")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmVolumeId, "volumeId", "", "", "list volume attachment by volumeId")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmStatus, "status", "", "", "list volume attachment by status")
	volumeAttachmentListCommand.Flags().StringVarP(&volAtmMountpoint, "mountpoint", "", "", "list volume attachment by mountpoint")

	volumeAttachmentCommand.AddCommand(volumeAttachmentCreateCommand)
	volumeAttachmentCommand.AddCommand(volumeAttachmentShowCommand)
	volumeAttachmentCommand.AddCommand(volumeAttachmentListCommand)
	volumeAttachmentCommand.AddCommand(volumeAttachmentDeleteCommand)
	volumeAttachmentCommand.AddCommand(volumeAttachmentUpdateCommand)
}

func volumeAttachmentAction(cmd *cobra.Command, args []string) {
	cmd.Usage()
	os.Exit(1)
}

var attachmentFormatters = FormatterList{"HostInfo": JsonFormatter, "ConnectionInfo": JsonFormatter}

func volumeAttachmentCreateAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 1)
	attachment := &model.VolumeAttachmentSpec{}
	if err := json.Unmarshal([]byte(args[0]), attachment); err != nil {
		Errorln(err)
		cmd.Usage()
		os.Exit(1)
	}
	resp, err := client.CreateVolumeAttachment(attachment)
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
	keys := KeyList{"Id", "CreatedAt", "UpdatedAt", "TenantId", "UserId", "HostInfo", "ConnectionInfo",
		"Mountpoint", "Status", "VolumeId", "AttachMode"}
	PrintDict(resp, keys, attachmentFormatters)
}

func volumeAttachmentShowAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 1)
	resp, err := client.GetVolumeAttachment(args[0])
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
	keys := KeyList{"Id", "CreatedAt", "UpdatedAt", "TenantId", "UserId", "HostInfo", "ConnectionInfo",
		"Mountpoint", "Status", "VolumeId", "AccessProtocol", "AttachMode"}
	PrintDict(resp, keys, attachmentFormatters)
}

func volumeAttachmentListAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 0)

	var opts = map[string]string{"limit": volAtmLimit, "offset": volAtmOffset,
		"sortDir": volAtmSortDir, "sortKey": volAtmSortKey, "Id": volAtmId,
		"UserId": volAtmUserId, "VolumeId": volAtmVolumeId,
		"Status": volAtmStatus, "Mountpoint": volAtmMountpoint}

	resp, err := client.ListVolumeAttachments(opts)
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
	keys := KeyList{"Id", "TenantId", "UserId", "Mountpoint", "Status", "VolumeId", "AccessProtocol", "AttachMode"}
	PrintList(resp, keys, attachmentFormatters)
}

func volumeAttachmentDeleteAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 1)
	attachment := &model.VolumeAttachmentSpec{}
	err := client.DeleteVolumeAttachment(args[0], attachment)
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
}

func volumeAttachmentUpdateAction(cmd *cobra.Command, args []string) {
	ArgsNumCheck(cmd, args, 2)
	attachment := &model.VolumeAttachmentSpec{}
	if err := json.Unmarshal([]byte(args[1]), attachment); err != nil {
		Errorln(err)
		cmd.Usage()
		os.Exit(1)
	}

	resp, err := client.UpdateVolumeAttachment(args[0], attachment)
	if err != nil {
		Fatalln(HttpErrStrip(err))
	}
	keys := KeyList{"Id", "CreatedAt", "UpdatedAt", "TenantId", "UserId", "HostInfo", "ConnectionInfo",
		"Mountpoint", "Status", "VolumeId", "AttachMode"}
	PrintDict(resp, keys, attachmentFormatters)
}
<|endoftext|>


<commit_before>// 23 june 2014
package main

import (
	"fmt"
	"os"
	"bytes"
)

func generate(ns Namespace) {
	b := new(bytes.Buffer)

	fmt.Fprintf(b, "package %s\n\nimport \"unsafe\"\nimport \"errors\"\nimport \"math\"\n\n// ADD IMPORTS AND CGO DIRECTIVES HERE\n// BE SURE TO INCLUDE stdio.h\n\n", nsGoName(ns.Name))

	// enumerations
	// to avoid unnecessary typing, let's collect all value names
	// if, for any enum, at least one name is ambiguous, we require the first word of the enum name as a prefix
	namecount := map[string]int{}
	for _, n := range ns.TopLevelEnums {
		e := ns.Enums[n]
		if e.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		for _, i := range e.Values {
			v := ns.Values[i]
			namecount[ns.GoName(v)]++
		}
	}
	for _, n := range ns.TopLevelEnums {
		e := ns.Enums[n]
		if e.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		goName := ns.GoName(e)
		fmt.Fprintf(b, "type %s %s\n", goName, e.StorageType.BasicString())
		fmt.Fprintf(b, "const (\n")
		fgw := ""
		for _, i := range e.Values {
			v := ns.Values[i]
			if namecount[ns.GoName(v)] > 1 {
				fgw = firstGoWord(goName)
				break
			}
		}
		for _, i := range e.Values {
			v := ns.Values[i]
			fmt.Fprintf(b, "\t%s%s %s = C.%s\n",
				fgw, ns.GoName(v), goName, ns.CName(v))
		}
		fmt.Fprintf(b, ")\n")
		fmt.Fprintf(b, "\n")
	}

	// interfaces
	// we don't need to worry about implementations of methods for each object until we get to the objects themselves
	// we also don't need to worry about signals
	// we DO need to worry about prerequisite types, putting an I before object prerequisites
	for _, n := range ns.TopLevelInterfaces {
		ii := ns.Interfaces[n]
		if ii.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		goName := ns.GoName(ii)
		fmt.Fprintf(b, "type %s interface {\n", goName)
		for _, p := range ii.Prerequisites {
			fmt.Fprintf(b, "\t%s\n", ns.GoIName(p))
		}
		for _, m := range ii.VFuncs {
			v := ns.VFuncs[m]
			fmt.Fprintf(b, "\tfunc %s\n", ns.GoFuncSig(v.CallableInfo))
		}
		fmt.Fprintf(b, "}\n")
		// TODO constants
		fmt.Fprintf(b, "\n")
	}

	// objects
	// all objects are either derived (embed the base class) or not (have a native member)
	// each object also gets the methods of the interfaces it implements
	// each object ALSO gets its own interface, to play into the whole polymorphism thing
	for _, n := range ns.TopLevelObjects {
		o := ns.Objects[n]
		if o.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		goName := ns.GoName(o)
		goIName := ns.GoIName(o)
		fmt.Fprintf(b, "type %s struct {\n", goName)
		if o.Parent == -1 {		// base
			fmt.Fprintf(b, "\tnative unsafe.Pointer\n")
			fmt.Fprintf(b, "}\n")
			fmt.Fprintf(b, "func (c *%s) Native() uintptr {\n", goName)
			fmt.Fprintf(b, "\treturn uintptr(c.native)\n");
		} else {
			oo := ns.Objects[o.Parent]
			fmt.Fprintf(b, "\t%s\n", ns.GoName(oo))
		}
		fmt.Fprintf(b, "}\n")
		for _, m := range o.Methods {
			mm := ns.Functions[m]
			fmt.Fprintf(b, "%s\n", ns.wrap(mm, o, false, InterfaceInfo{}))
		}
		for _, ii := range o.Interfaces {
			iii := ns.Interfaces[ii]
			for _, m := range iii.Methods {
				mm := ns.Functions[m]
				fmt.Fprintf(b, "%s\n", ns.wrap(mm, o, true, iii))
			}
		}
		// TODO other methods
		fmt.Fprintf(b, "type %s interface {\n", goIName)
		if o.Parent != -1 {
			oo := ns.Objects[o.Parent]
			fmt.Fprintf(b, "\t%s\n", ns.GoIName(oo))
		}
		for _, ii := range o.Interfaces {
			iii := ns.Interfaces[ii]
			fmt.Fprintf(b, "\t%s\n", ns.GoName(iii))
		}
		for _, m := range o.Methods {
			f := ns.Functions[m]
			if f.IsMethod {			// only actual methods
				fmt.Fprintf(b, "\tfunc %s\n", ns.GoFuncSig(f.CallableInfo))
			}
		}
		fmt.Fprintf(b, "}\n")
		// TODO constants
		fmt.Fprintf(b, "\n")
	}

	// structures
	for _, n := range ns.TopLevelStructs {
		s := ns.Structs[n]
		if s.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		if s.IsClassStruct {				// skip GObject boilerplate
			continue
		}
		if s.Foreign {		// TODO debugging
			fmt.Fprintf(b, "// foreign\n")
		}
		goName := ns.GoName(s)
		if len(s.Fields) == 0 && bytes.HasSuffix([]byte(goName), []byte("Private")) {
			// skip opaque private structures (implementation details that are slowly being eliminated)
			// this should be safe; very few nonempty privates are left that it doesn't matter (and let's bind glib.Private anyway, just to be safe)
			continue
		}
		fmt.Fprintf(b, "type %s struct {\n", goName)
		for _, m := range s.Fields {
			f := ns.Fields[m]
			// TODO substitute TypeToGo()
			fmt.Fprintf(b, "\t%s %s\n", ns.GoName(f), ns.TypeToGo(f.Type))
		}
		fmt.Fprintf(b, "}\n")
		// TODO conversion functions
//		for _, m := range s.Methods {
//			mm := ns.Functions[m]
//			fmt.Fprintf(b, "%s\n", ns.wrap(mm, s, false, InterfaceInfo{}))
//		}
//		fmt.Fprintf(b, "\n")
	}

	os.Stdout.Write(b.Bytes())
}

func (ns Namespace) wrap(method FunctionInfo, to ObjectInfo, isInterface bool, iface InterfaceInfo) string {
	namespace = ns.Name
	s := "func "
	prefix := ""
	suffix := ""
	arglist := ""
	// method receivers aren't listed in the arguments; we have to fake it
	if method.IsMethod {
		receiver := receiverArg(to.BaseInfo, isInterface, iface.BaseInfo)
		s += "("
		prefix += receiver.Prefix()
		suffix = receiver.Suffix() + suffix
		arglist += receiver.GoArg() + ", "
		s += receiver.GoDecl()
		s += ") "
	}
	// disambiguate between constructors
	// a more Go-like way would be to insert the type name after the New but before anything else :/ conformal/gotk3 does it this way so meh
	if (method.Flags & FunctionIsConstructor) != 0 {
		s += ns.GoName(to)
	}
	s += ns.GoName(method) + "("
	for i := 0; i < len(method.Args); i++ {
		arg := argumentArg(ns.Args[method.Args[i]], ns)
		prefix += arg.Prefix()
		suffix = arg.Suffix() + suffix
		arglist += arg.GoArg() + ", "
		s += arg.GoDecl()
		s += ", "
	}
	s += ") "
	retarg := returnArg(ns.Types[method.ReturnType], ns)
	prefix += retarg.Prefix()
	suffix = retarg.Suffix() + suffix
	s += retarg.GoDecl()
	if len(retarg.GoDecl()) != 0 {
		s += " "
	}
	s += "{\n"
	s += prefix
	s += "\t" + retarg.GoCall("C." + ns.CName(method) + "(" + arglist + ")") + "\n"
	s += suffix
	s += retarg.GoRet()
	s += "}"
	return s
}
<commit_msg>Added structure methods.<commit_after>// 23 june 2014
package main

import (
	"fmt"
	"os"
	"bytes"
)

func generate(ns Namespace) {
	b := new(bytes.Buffer)

	fmt.Fprintf(b, "package %s\n\nimport \"unsafe\"\nimport \"errors\"\nimport \"math\"\n\n// ADD IMPORTS AND CGO DIRECTIVES HERE\n// BE SURE TO INCLUDE stdio.h\n\n", nsGoName(ns.Name))

	// enumerations
	// to avoid unnecessary typing, let's collect all value names
	// if, for any enum, at least one name is ambiguous, we require the first word of the enum name as a prefix
	namecount := map[string]int{}
	for _, n := range ns.TopLevelEnums {
		e := ns.Enums[n]
		if e.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		for _, i := range e.Values {
			v := ns.Values[i]
			namecount[ns.GoName(v)]++
		}
	}
	for _, n := range ns.TopLevelEnums {
		e := ns.Enums[n]
		if e.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		goName := ns.GoName(e)
		fmt.Fprintf(b, "type %s %s\n", goName, e.StorageType.BasicString())
		fmt.Fprintf(b, "const (\n")
		fgw := ""
		for _, i := range e.Values {
			v := ns.Values[i]
			if namecount[ns.GoName(v)] > 1 {
				fgw = firstGoWord(goName)
				break
			}
		}
		for _, i := range e.Values {
			v := ns.Values[i]
			fmt.Fprintf(b, "\t%s%s %s = C.%s\n",
				fgw, ns.GoName(v), goName, ns.CName(v))
		}
		fmt.Fprintf(b, ")\n")
		fmt.Fprintf(b, "\n")
	}

	// interfaces
	// we don't need to worry about implementations of methods for each object until we get to the objects themselves
	// we also don't need to worry about signals
	// we DO need to worry about prerequisite types, putting an I before object prerequisites
	for _, n := range ns.TopLevelInterfaces {
		ii := ns.Interfaces[n]
		if ii.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		goName := ns.GoName(ii)
		fmt.Fprintf(b, "type %s interface {\n", goName)
		for _, p := range ii.Prerequisites {
			fmt.Fprintf(b, "\t%s\n", ns.GoIName(p))
		}
		for _, m := range ii.VFuncs {
			v := ns.VFuncs[m]
			fmt.Fprintf(b, "\tfunc %s\n", ns.GoFuncSig(v.CallableInfo))
		}
		fmt.Fprintf(b, "}\n")
		// TODO constants
		fmt.Fprintf(b, "\n")
	}

	// objects
	// all objects are either derived (embed the base class) or not (have a native member)
	// each object also gets the methods of the interfaces it implements
	// each object ALSO gets its own interface, to play into the whole polymorphism thing
	for _, n := range ns.TopLevelObjects {
		o := ns.Objects[n]
		if o.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		goName := ns.GoName(o)
		goIName := ns.GoIName(o)
		fmt.Fprintf(b, "type %s struct {\n", goName)
		if o.Parent == -1 {		// base
			fmt.Fprintf(b, "\tnative unsafe.Pointer\n")
			fmt.Fprintf(b, "}\n")
			fmt.Fprintf(b, "func (c *%s) Native() uintptr {\n", goName)
			fmt.Fprintf(b, "\treturn uintptr(c.native)\n");
		} else {
			oo := ns.Objects[o.Parent]
			fmt.Fprintf(b, "\t%s\n", ns.GoName(oo))
		}
		fmt.Fprintf(b, "}\n")
		for _, m := range o.Methods {
			mm := ns.Functions[m]
			fmt.Fprintf(b, "%s\n", ns.wrap(mm, o.BaseInfo, false, InterfaceInfo{}))
		}
		for _, ii := range o.Interfaces {
			iii := ns.Interfaces[ii]
			for _, m := range iii.Methods {
				mm := ns.Functions[m]
				fmt.Fprintf(b, "%s\n", ns.wrap(mm, o.BaseInfo, true, iii))
			}
		}
		// TODO other methods
		fmt.Fprintf(b, "type %s interface {\n", goIName)
		if o.Parent != -1 {
			oo := ns.Objects[o.Parent]
			fmt.Fprintf(b, "\t%s\n", ns.GoIName(oo))
		}
		for _, ii := range o.Interfaces {
			iii := ns.Interfaces[ii]
			fmt.Fprintf(b, "\t%s\n", ns.GoName(iii))
		}
		for _, m := range o.Methods {
			f := ns.Functions[m]
			if f.IsMethod {			// only actual methods
				fmt.Fprintf(b, "\tfunc %s\n", ns.GoFuncSig(f.CallableInfo))
			}
		}
		fmt.Fprintf(b, "}\n")
		// TODO constants
		fmt.Fprintf(b, "\n")
	}

	// structures
	for _, n := range ns.TopLevelStructs {
		s := ns.Structs[n]
		if s.Namespace != ns.Name {		// skip foreign imports
			continue
		}
		if s.IsClassStruct {				// skip GObject boilerplate
			continue
		}
		if s.Foreign {		// TODO debugging
			fmt.Fprintf(b, "// foreign\n")
		}
		goName := ns.GoName(s)
		if len(s.Fields) == 0 && bytes.HasSuffix([]byte(goName), []byte("Private")) {
			// skip opaque private structures (implementation details that are slowly being eliminated)
			// this should be safe; very few nonempty privates are left that it doesn't matter (and let's bind glib.Private anyway, just to be safe)
			continue
		}
		fmt.Fprintf(b, "type %s struct {\n", goName)
		for _, m := range s.Fields {
			f := ns.Fields[m]
			// TODO substitute TypeToGo()
			fmt.Fprintf(b, "\t%s %s\n", ns.GoName(f), ns.TypeToGo(f.Type))
		}
		fmt.Fprintf(b, "}\n")
		// TODO conversion functions
		for _, m := range s.Methods {
			mm := ns.Functions[m]
			fmt.Fprintf(b, "%s\n", ns.wrap(mm, s.BaseInfo, false, InterfaceInfo{}))
		}
		fmt.Fprintf(b, "\n")
	}

	os.Stdout.Write(b.Bytes())
}

func (ns Namespace) wrap(method FunctionInfo, to BaseInfo, isInterface bool, iface InterfaceInfo) string {
	namespace = ns.Name
	s := "func "
	prefix := ""
	suffix := ""
	arglist := ""
	// method receivers aren't listed in the arguments; we have to fake it
	if method.IsMethod {
		receiver := receiverArg(to, isInterface, iface.BaseInfo)
		s += "("
		prefix += receiver.Prefix()
		suffix = receiver.Suffix() + suffix
		arglist += receiver.GoArg() + ", "
		s += receiver.GoDecl()
		s += ") "
	}
	// disambiguate between constructors
	// a more Go-like way would be to insert the type name after the New but before anything else :/ conformal/gotk3 does it this way so meh
	if (method.Flags & FunctionIsConstructor) != 0 {
		s += ns.GoName(to)
	}
	s += ns.GoName(method) + "("
	for i := 0; i < len(method.Args); i++ {
		arg := argumentArg(ns.Args[method.Args[i]], ns)
		prefix += arg.Prefix()
		suffix = arg.Suffix() + suffix
		arglist += arg.GoArg() + ", "
		s += arg.GoDecl()
		s += ", "
	}
	s += ") "
	retarg := returnArg(ns.Types[method.ReturnType], ns)
	prefix += retarg.Prefix()
	suffix = retarg.Suffix() + suffix
	s += retarg.GoDecl()
	if len(retarg.GoDecl()) != 0 {
		s += " "
	}
	s += "{\n"
	s += prefix
	s += "\t" + retarg.GoCall("C." + ns.CName(method) + "(" + arglist + ")") + "\n"
	s += suffix
	s += retarg.GoRet()
	s += "}"
	return s
}
<|endoftext|>