<commit_before>// Copyright (c) 2016 Intel Corporation
//
// 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 client

import (
	"encoding/json"
	"errors"
	"fmt"
	"net"

	"github.com/clearcontainers/proxy/api"
)

// The Client struct can be used to issue proxy API calls with a convenient
// high level API.
type Client struct {
	conn *net.UnixConn
}

// NewClient creates a new client object to communicate with the proxy using
// the connection conn. The user should call Close() once finished with the
// client object to close conn.
func NewClient(conn *net.UnixConn) *Client {
	return &Client{
		conn: conn,
	}
}

// Close a client, closing the underlying AF_UNIX socket.
func (client *Client) Close() {
	client.conn.Close()
}

func (client *Client) sendCommandFull(cmd api.Command, payload interface{},
	waitForResponse bool) (*api.Frame, error) {
	var data []byte
	var frame *api.Frame
	var err error

	if payload != nil {
		if data, err = json.Marshal(payload); err != nil {
			return nil, err
		}
	}

	if err := api.WriteCommand(client.conn, cmd, data); err != nil {
		return nil, err
	}

	if !waitForResponse {
		return nil, nil
	}

	if frame, err = api.ReadFrame(client.conn); err != nil {
		return nil, err
	}

	if frame.Header.Type != api.TypeResponse {
		return nil, fmt.Errorf("unexepected frame type %v", frame.Header.Type)
	}

	if frame.Header.Opcode != int(cmd) {
		return nil, fmt.Errorf("unexepected opcode %v", frame.Header.Opcode)
	}

	return frame, nil
}

func (client *Client) sendCommand(cmd api.Command, payload interface{}) (*api.Frame, error) {
	return client.sendCommandFull(cmd, payload, true)
}

func (client *Client) sendCommandNoResponse(cmd api.Command, payload interface{}) error {
	_, err := client.sendCommandFull(cmd, payload, false)
	return err
}

func errorFromResponse(resp *api.Frame) error {
	// We should always have an error with the response, but better safe
	// than sorry.
	if !resp.Header.InError {
		return nil
	}

	decoded := api.ErrorResponse{}
	if err := json.Unmarshal(resp.Payload, &decoded); err != nil {
		return err
	}

	if decoded.Message == "" {
		return errors.New("unknown error")
	}

	return errors.New(decoded.Message)
}

func unmarshalResponse(resp *api.Frame, decoded interface{}) error {
	if len(resp.Payload) == 0 {
		return nil
	}

	if err := json.Unmarshal(resp.Payload, decoded); err != nil {
		return err
	}

	return nil
}

// RegisterVMOptions holds extra arguments one can pass to the RegisterVM
// function.
//
// See the api.RegisterVM payload for more details.
type RegisterVMOptions struct {
	Console      string
	NumIOStreams int
}

// RegisterVMReturn contains the return values from RegisterVM.
//
// See the api.RegisterVM and api.RegisterVMResponse payloads.
type RegisterVMReturn api.RegisterVMResponse

// RegisterVM wraps the api.RegisterVM payload.
//
// See payload description for more details.
func (client *Client) RegisterVM(containerID, ctlSerial, ioSerial string,
	options *RegisterVMOptions) (*RegisterVMReturn, error) {
	payload := api.RegisterVM{
		ContainerID: containerID,
		CtlSerial:   ctlSerial,
		IoSerial:    ioSerial,
	}

	if options != nil {
		payload.Console = options.Console
		payload.NumIOStreams = options.NumIOStreams
	}

	resp, err := client.sendCommand(api.CmdRegisterVM, &payload)
	if err != nil {
		return nil, err
	}

	if err := errorFromResponse(resp); err != nil {
		return nil, err
	}

	decoded := RegisterVMReturn{}
	err = unmarshalResponse(resp, &decoded)
	return &decoded, err
}

// AttachVMOptions holds extra arguments one can pass to the AttachVM function.
//
// See the api.AttachVM payload for more details.
type AttachVMOptions struct {
	NumIOStreams int
}

// AttachVMReturn contains the return values from AttachVM.
//
// See the api.AttachVM and api.AttachVMResponse payloads.
type AttachVMReturn api.AttachVMResponse

// AttachVM wraps the api.AttachVM payload.
//
// See the api.AttachVM payload description for more details.
func (client *Client) AttachVM(containerID string, options *AttachVMOptions) (*AttachVMReturn, error) {
	payload := api.AttachVM{
		ContainerID: containerID,
	}

	if options != nil {
		payload.NumIOStreams = options.NumIOStreams
	}

	resp, err := client.sendCommand(api.CmdAttachVM, &payload)
	if err != nil {
		return nil, err
	}

	if err := errorFromResponse(resp); err != nil {
		return nil, err
	}

	decoded := AttachVMReturn{}
	err = unmarshalResponse(resp, &decoded)
	return &decoded, err
}

// Hyper wraps the Hyper payload (see payload description for more details)
func (client *Client) Hyper(hyperName string, hyperMessage interface{}) error {
	return client.HyperWithTokens(hyperName, nil, hyperMessage)
}

// HyperWithTokens is a Hyper variant where the users can specify a list of I/O tokens.
//
// See the api.Hyper payload description for more details.
func (client *Client) HyperWithTokens(hyperName string, tokens []string, hyperMessage interface{}) error {
	var data []byte

	if hyperMessage != nil {
		var err error

		data, err = json.Marshal(hyperMessage)
		if err != nil {
			return err
		}
	}

	hyper := api.Hyper{
		HyperName: hyperName,
		Data:      data,
	}

	if tokens != nil {
		hyper.Tokens = tokens
	}

	resp, err := client.sendCommand(api.CmdHyper, &hyper)
	if err != nil {
		return err
	}

	return errorFromResponse(resp)
}

// UnregisterVM wraps the api.UnregisterVM payload.
//
// See the api.UnregisterVM payload description for more details.
func (client *Client) UnregisterVM(containerID string) error {
	payload := api.UnregisterVM{
		ContainerID: containerID,
	}

	resp, err := client.sendCommand(api.CmdUnregisterVM, &payload)
	if err != nil {
		return err
	}

	return errorFromResponse(resp)
}

// ConnectShim wraps the api.CmdConnectShim command and associated
// api.ConnectShim payload.
func (client *Client) ConnectShim(token string) error {
	payload := api.ConnectShim{
		Token: token,
	}

	resp, err := client.sendCommand(api.CmdConnectShim, &payload)
	if err != nil {
		return err
	}

	return errorFromResponse(resp)
}

// DisconnectShim wraps the api.CmdDisconnectShim command and associated
// api.DisconnectShim payload.
func (client *Client) DisconnectShim() error {
	return client.sendCommandNoResponse(api.CmdDisconnectShim, nil)
}
<commit_msg>client: Add API wrappers around the Signal command<commit_after>// Copyright (c) 2016 Intel Corporation
//
// 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 client

import (
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"syscall"

	"github.com/clearcontainers/proxy/api"
)

// The Client struct can be used to issue proxy API calls with a convenient
// high level API.
type Client struct {
	conn *net.UnixConn
}

// NewClient creates a new client object to communicate with the proxy using
// the connection conn. The user should call Close() once finished with the
// client object to close conn.
func NewClient(conn *net.UnixConn) *Client {
	return &Client{
		conn: conn,
	}
}

// Close a client, closing the underlying AF_UNIX socket.
func (client *Client) Close() {
	client.conn.Close()
}

func (client *Client) sendCommandFull(cmd api.Command, payload interface{},
	waitForResponse bool) (*api.Frame, error) {
	var data []byte
	var frame *api.Frame
	var err error

	if payload != nil {
		if data, err = json.Marshal(payload); err != nil {
			return nil, err
		}
	}

	if err := api.WriteCommand(client.conn, cmd, data); err != nil {
		return nil, err
	}

	if !waitForResponse {
		return nil, nil
	}

	if frame, err = api.ReadFrame(client.conn); err != nil {
		return nil, err
	}

	if frame.Header.Type != api.TypeResponse {
		return nil, fmt.Errorf("unexepected frame type %v", frame.Header.Type)
	}

	if frame.Header.Opcode != int(cmd) {
		return nil, fmt.Errorf("unexepected opcode %v", frame.Header.Opcode)
	}

	return frame, nil
}

func (client *Client) sendCommand(cmd api.Command, payload interface{}) (*api.Frame, error) {
	return client.sendCommandFull(cmd, payload, true)
}

func (client *Client) sendCommandNoResponse(cmd api.Command, payload interface{}) error {
	_, err := client.sendCommandFull(cmd, payload, false)
	return err
}

func errorFromResponse(resp *api.Frame) error {
	// We should always have an error with the response, but better safe
	// than sorry.
	if !resp.Header.InError {
		return nil
	}

	decoded := api.ErrorResponse{}
	if err := json.Unmarshal(resp.Payload, &decoded); err != nil {
		return err
	}

	if decoded.Message == "" {
		return errors.New("unknown error")
	}

	return errors.New(decoded.Message)
}

func unmarshalResponse(resp *api.Frame, decoded interface{}) error {
	if len(resp.Payload) == 0 {
		return nil
	}

	if err := json.Unmarshal(resp.Payload, decoded); err != nil {
		return err
	}

	return nil
}

// RegisterVMOptions holds extra arguments one can pass to the RegisterVM
// function.
//
// See the api.RegisterVM payload for more details.
type RegisterVMOptions struct {
	Console      string
	NumIOStreams int
}

// RegisterVMReturn contains the return values from RegisterVM.
//
// See the api.RegisterVM and api.RegisterVMResponse payloads.
type RegisterVMReturn api.RegisterVMResponse

// RegisterVM wraps the api.RegisterVM payload.
//
// See payload description for more details.
func (client *Client) RegisterVM(containerID, ctlSerial, ioSerial string,
	options *RegisterVMOptions) (*RegisterVMReturn, error) {
	payload := api.RegisterVM{
		ContainerID: containerID,
		CtlSerial:   ctlSerial,
		IoSerial:    ioSerial,
	}

	if options != nil {
		payload.Console = options.Console
		payload.NumIOStreams = options.NumIOStreams
	}

	resp, err := client.sendCommand(api.CmdRegisterVM, &payload)
	if err != nil {
		return nil, err
	}

	if err := errorFromResponse(resp); err != nil {
		return nil, err
	}

	decoded := RegisterVMReturn{}
	err = unmarshalResponse(resp, &decoded)
	return &decoded, err
}

// AttachVMOptions holds extra arguments one can pass to the AttachVM function.
//
// See the api.AttachVM payload for more details.
type AttachVMOptions struct {
	NumIOStreams int
}

// AttachVMReturn contains the return values from AttachVM.
//
// See the api.AttachVM and api.AttachVMResponse payloads.
type AttachVMReturn api.AttachVMResponse

// AttachVM wraps the api.AttachVM payload.
//
// See the api.AttachVM payload description for more details.
func (client *Client) AttachVM(containerID string, options *AttachVMOptions) (*AttachVMReturn, error) {
	payload := api.AttachVM{
		ContainerID: containerID,
	}

	if options != nil {
		payload.NumIOStreams = options.NumIOStreams
	}

	resp, err := client.sendCommand(api.CmdAttachVM, &payload)
	if err != nil {
		return nil, err
	}

	if err := errorFromResponse(resp); err != nil {
		return nil, err
	}

	decoded := AttachVMReturn{}
	err = unmarshalResponse(resp, &decoded)
	return &decoded, err
}

// Hyper wraps the Hyper payload (see payload description for more details)
func (client *Client) Hyper(hyperName string, hyperMessage interface{}) error {
	return client.HyperWithTokens(hyperName, nil, hyperMessage)
}

// HyperWithTokens is a Hyper variant where the users can specify a list of I/O tokens.
//
// See the api.Hyper payload description for more details.
func (client *Client) HyperWithTokens(hyperName string, tokens []string, hyperMessage interface{}) error {
	var data []byte

	if hyperMessage != nil {
		var err error

		data, err = json.Marshal(hyperMessage)
		if err != nil {
			return err
		}
	}

	hyper := api.Hyper{
		HyperName: hyperName,
		Data:      data,
	}

	if tokens != nil {
		hyper.Tokens = tokens
	}

	resp, err := client.sendCommand(api.CmdHyper, &hyper)
	if err != nil {
		return err
	}

	return errorFromResponse(resp)
}

// UnregisterVM wraps the api.UnregisterVM payload.
//
// See the api.UnregisterVM payload description for more details.
func (client *Client) UnregisterVM(containerID string) error {
	payload := api.UnregisterVM{
		ContainerID: containerID,
	}

	resp, err := client.sendCommand(api.CmdUnregisterVM, &payload)
	if err != nil {
		return err
	}

	return errorFromResponse(resp)
}

// ConnectShim wraps the api.CmdConnectShim command and associated
// api.ConnectShim payload.
func (client *Client) ConnectShim(token string) error {
	payload := api.ConnectShim{
		Token: token,
	}

	resp, err := client.sendCommand(api.CmdConnectShim, &payload)
	if err != nil {
		return err
	}

	return errorFromResponse(resp)
}

// DisconnectShim wraps the api.CmdDisconnectShim command and associated
// api.DisconnectShim payload.
func (client *Client) DisconnectShim() error {
	return client.sendCommandNoResponse(api.CmdDisconnectShim, nil)
}

func (client *Client) signal(signal syscall.Signal, columns, rows int) error {
	payload := api.Signal{
		SignalNumber: int(signal),
		Columns:      columns,
		Rows:         rows,
	}

	resp, err := client.sendCommand(api.CmdSignal, &payload)
	if err != nil {
		return err
	}

	return errorFromResponse(resp)
}

// Kill wraps the api.CmdSignal command and can be used by a shim to send a
// signal to the associated process.
func (client *Client) Kill(signal syscall.Signal) error {
	return client.signal(signal, 0, 0)
}

// SendTerminalSize wraps the api.CmdSignal command and can be used by a shim
// to send a new signal to the associated process.
func (client *Client) SendTerminalSize(columns, rows int) error {
	return client.signal(syscall.SIGWINCH, columns, rows)
}
<|endoftext|>


<commit_before>package gitmediaclient

import (
	".."
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/cheggaaa/pb"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

const (
	gitMediaType      = "application/vnd.git-media"
	gitMediaMetaType  = gitMediaType + "+json; charset=utf-8"
	gitMediaHeader    = "--git-media."
	gitBoundaryLength = 61
)

func Options(filehash string) error {
	oid := filepath.Base(filehash)
	_, err := os.Stat(filehash)
	if err != nil {
		return err
	}

	req, creds, err := clientRequest("OPTIONS", oid)
	if err != nil {
		return err
	}

	_, err = doRequest(req, creds)
	if err != nil {
		return err
	}

	return nil
}

func Put(filehash, filename string) error {
	if filename == "" {
		filename = filehash
	}

	oid := filepath.Base(filehash)
	stat, err := os.Stat(filehash)
	if err != nil {
		return err
	}

	file, err := os.Open(filehash)
	if err != nil {
		return err
	}

	req, creds, err := clientRequest("PUT", oid)
	if err != nil {
		return err
	}

	bar := pb.StartNew(int(stat.Size()))
	bar.SetUnits(pb.U_BYTES)
	bar.Start()

	req.Header.Set("Content-Type", gitMediaType)
	req.Header.Set("Accept", gitMediaMetaType)
	req.Body = ioutil.NopCloser(bar.NewProxyReader(file))
	req.ContentLength = stat.Size()

	fmt.Printf("Sending %s\n", filename)

	_, err = doRequest(req, creds)
	if err != nil {
		return err
	}

	return nil
}

func Get(filename string) (io.ReadCloser, error) {
	oid := filepath.Base(filename)
	if stat, err := os.Stat(filename); err != nil || stat == nil {
		req, creds, err := clientRequest("GET", oid)
		if err != nil {
			return nil, err
		}

		req.Header.Set("Accept", gitMediaType)
		res, err := doRequest(req, creds)

		if err != nil {
			return nil, err
		}

		header := make([]byte, len(gitMediaHeader)+gitBoundaryLength)
		_, err = io.ReadAtLeast(res.Body, header, len(gitMediaHeader)+gitBoundaryLength)
		if err != nil {
			return nil, err
		}

		if !strings.HasPrefix(string(header), gitMediaHeader) {
			return nil, errors.New("Invalid header")
		}

		return res.Body, nil
	}

	return os.Open(filename)
}

func doRequest(req *http.Request, creds Creds) (*http.Response, error) {
	res, err := http.DefaultClient.Do(req)

	if err == nil {
		if res.StatusCode > 299 {
			execCreds(creds, "reject")

			apierr := &Error{}
			dec := json.NewDecoder(res.Body)
			if err := dec.Decode(apierr); err != nil {
				return res, err
			}

			return res, apierr
		}
	} else {
		execCreds(creds, "approve")
	}

	return res, err
}

func clientRequest(method, oid string) (*http.Request, Creds, error) {
	u := ObjectUrl(oid)
	req, err := http.NewRequest(method, u.String(), nil)
	if err == nil {
		creds, err := credentials(u)
		if err != nil {
			return req, nil, err
		}

		token := fmt.Sprintf("%s:%s", creds["username"], creds["password"])
		auth := "Basic " + base64.URLEncoding.EncodeToString([]byte(token))
		req.Header.Set("Authorization", auth)
		return req, creds, nil
	}

	return req, nil, err
}

func ObjectUrl(oid string) *url.URL {
	c := gitmedia.Config
	u, _ := url.Parse(c.Endpoint())
	u.Path = filepath.Join(u.Path, "/objects/"+oid)
	return u
}

type Error struct {
	Message   string `json:"message"`
	RequestId string `json:"request_id,omitempty"`
}

func (e *Error) Error() string {
	return e.Message
}
<commit_msg>more strict parsing of media header<commit_after>package gitmediaclient

import (
	".."
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/cheggaaa/pb"
	"io"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
)

const (
	gitMediaType      = "application/vnd.git-media"
	gitMediaMetaType  = gitMediaType + "+json; charset=utf-8"
	gitMediaHeader    = "--git-media."
	gitBoundaryLength = 61
)

func Options(filehash string) error {
	oid := filepath.Base(filehash)
	_, err := os.Stat(filehash)
	if err != nil {
		return err
	}

	req, creds, err := clientRequest("OPTIONS", oid)
	if err != nil {
		return err
	}

	_, err = doRequest(req, creds)
	if err != nil {
		return err
	}

	return nil
}

func Put(filehash, filename string) error {
	if filename == "" {
		filename = filehash
	}

	oid := filepath.Base(filehash)
	stat, err := os.Stat(filehash)
	if err != nil {
		return err
	}

	file, err := os.Open(filehash)
	if err != nil {
		return err
	}

	req, creds, err := clientRequest("PUT", oid)
	if err != nil {
		return err
	}

	bar := pb.StartNew(int(stat.Size()))
	bar.SetUnits(pb.U_BYTES)
	bar.Start()

	req.Header.Set("Content-Type", gitMediaType)
	req.Header.Set("Accept", gitMediaMetaType)
	req.Body = ioutil.NopCloser(bar.NewProxyReader(file))
	req.ContentLength = stat.Size()

	fmt.Printf("Sending %s\n", filename)

	_, err = doRequest(req, creds)
	if err != nil {
		return err
	}

	return nil
}

func Get(filename string) (io.ReadCloser, error) {
	oid := filepath.Base(filename)
	if stat, err := os.Stat(filename); err != nil || stat == nil {
		req, creds, err := clientRequest("GET", oid)
		if err != nil {
			return nil, err
		}

		req.Header.Set("Accept", gitMediaType)
		res, err := doRequest(req, creds)

		if err != nil {
			return nil, err
		}

		contentType := res.Header.Get("Content-Type")
		if contentType == "" {
			return nil, errors.New("Invalid Content-Type")
		}

		mediaType, params, err := mime.ParseMediaType(contentType)
		if err != nil {
			return nil, errors.New("Invalid Media Type")
		}

		if mediaType != gitMediaType {
			return nil, errors.New("Invalid Media Type")
		}

		givenHeader, ok := params["header"]
		if !ok {
			return nil, errors.New("Invalid header")
		}

		header := make([]byte, len(gitMediaHeader)+gitBoundaryLength)
		_, err = io.ReadAtLeast(res.Body, header, len(gitMediaHeader)+gitBoundaryLength)
		if err != nil {
			return nil, err
		}

		if string(header) != givenHeader {
			return nil, errors.New("Invalid header")
		}

		return res.Body, nil
	}

	return os.Open(filename)
}

func doRequest(req *http.Request, creds Creds) (*http.Response, error) {
	res, err := http.DefaultClient.Do(req)

	if err == nil {
		if res.StatusCode > 299 {
			execCreds(creds, "reject")

			apierr := &Error{}
			dec := json.NewDecoder(res.Body)
			if err := dec.Decode(apierr); err != nil {
				return res, err
			}

			return res, apierr
		}
	} else {
		execCreds(creds, "approve")
	}

	return res, err
}

func clientRequest(method, oid string) (*http.Request, Creds, error) {
	u := ObjectUrl(oid)
	req, err := http.NewRequest(method, u.String(), nil)
	if err == nil {
		creds, err := credentials(u)
		if err != nil {
			return req, nil, err
		}

		token := fmt.Sprintf("%s:%s", creds["username"], creds["password"])
		auth := "Basic " + base64.URLEncoding.EncodeToString([]byte(token))
		req.Header.Set("Authorization", auth)
		return req, creds, nil
	}

	return req, nil, err
}

func ObjectUrl(oid string) *url.URL {
	c := gitmedia.Config
	u, _ := url.Parse(c.Endpoint())
	u.Path = filepath.Join(u.Path, "/objects/"+oid)
	return u
}

type Error struct {
	Message   string `json:"message"`
	RequestId string `json:"request_id,omitempty"`
}

func (e *Error) Error() string {
	return e.Message
}
<|endoftext|>


<commit_before>package client

import (
	"fmt"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/docker/engine-api/client/transport"
	"github.com/docker/go-connections/tlsconfig"
)

// DefaultVersion is the version of the current stable API
const DefaultVersion string = "1.23"

// Client is the API client that performs all operations
// against a docker server.
type Client struct {
	// proto holds the client protocol i.e. unix.
	proto string
	// addr holds the client address.
	addr string
	// basePath holds the path to prepend to the requests.
	basePath string
	// transport is the interface to send request with, it implements transport.Client.
	transport transport.Client
	// version of the server to talk to.
	version string
	// custom http headers configured by users.
	customHTTPHeaders map[string]string
}

// NewEnvClient initializes a new API client based on environment variables.
// Use DOCKER_HOST to set the url to the docker server.
// Use DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
// Use DOCKER_CERT_PATH to load the tls certificates from.
// Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
func NewEnvClient() (*Client, error) {
	var client *http.Client
	if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
		options := tlsconfig.Options{
			CAFile:             filepath.Join(dockerCertPath, "ca.pem"),
			CertFile:           filepath.Join(dockerCertPath, "cert.pem"),
			KeyFile:            filepath.Join(dockerCertPath, "key.pem"),
			InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
		}
		tlsc, err := tlsconfig.Client(options)
		if err != nil {
			return nil, err
		}

		client = &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: tlsc,
			},
		}
	}

	host := os.Getenv("DOCKER_HOST")
	if host == "" {
		host = DefaultDockerHost
	}

	version := os.Getenv("DOCKER_API_VERSION")
	if version == "" {
		version = DefaultVersion
	}

	return NewClient(host, version, client, nil)
}

// NewClient initializes a new API client for the given host and API version.
// It won't send any version information if the version number is empty.
// It uses the given http client as transport.
// It also initializes the custom http headers to add to each request.
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
	proto, addr, basePath, err := ParseHost(host)
	if err != nil {
		return nil, err
	}

	transport, err := transport.NewTransportWithHTTP(proto, addr, client)
	if err != nil {
		return nil, err
	}

	return &Client{
		proto:             proto,
		addr:              addr,
		basePath:          basePath,
		transport:         transport,
		version:           version,
		customHTTPHeaders: httpHeaders,
	}, nil
}

// getAPIPath returns the versioned request path to call the api.
// It appends the query parameters to the path if they are not empty.
func (cli *Client) getAPIPath(p string, query url.Values) string {
	var apiPath string
	if cli.version != "" {
		v := strings.TrimPrefix(cli.version, "v")
		apiPath = fmt.Sprintf("%s/v%s%s", cli.basePath, v, p)
	} else {
		apiPath = fmt.Sprintf("%s%s", cli.basePath, p)
	}

	u := &url.URL{
		Path: apiPath,
	}
	if len(query) > 0 {
		u.RawQuery = query.Encode()
	}
	return u.String()
}

// ClientVersion returns the version string associated with this
// instance of the Client. Note that this value can be changed
// via the DOCKER_API_VERSION env var.
func (cli *Client) ClientVersion() string {
	return cli.version
}

// UpdateClientVersion updates the version string associated with this
// instance of the Client.
func (cli *Client) UpdateClientVersion(v string) {
	cli.version = v
}

// ParseHost verifies that the given host strings is valid.
func ParseHost(host string) (string, string, string, error) {
	protoAddrParts := strings.SplitN(host, "://", 2)
	if len(protoAddrParts) == 1 {
		return "", "", "", fmt.Errorf("unable to parse docker host `%s`", host)
	}

	var basePath string
	proto, addr := protoAddrParts[0], protoAddrParts[1]
	if proto == "tcp" {
		parsed, err := url.Parse("tcp://" + addr)
		if err != nil {
			return "", "", "", err
		}
		addr = parsed.Host
		basePath = parsed.Path
	}
	return proto, addr, basePath, nil
}
<commit_msg>Add warning about setting version in NewClient<commit_after>package client

import (
	"fmt"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/docker/engine-api/client/transport"
	"github.com/docker/go-connections/tlsconfig"
)

// DefaultVersion is the version of the current stable API
const DefaultVersion string = "1.23"

// Client is the API client that performs all operations
// against a docker server.
type Client struct {
	// proto holds the client protocol i.e. unix.
	proto string
	// addr holds the client address.
	addr string
	// basePath holds the path to prepend to the requests.
	basePath string
	// transport is the interface to send request with, it implements transport.Client.
	transport transport.Client
	// version of the server to talk to.
	version string
	// custom http headers configured by users.
	customHTTPHeaders map[string]string
}

// NewEnvClient initializes a new API client based on environment variables.
// Use DOCKER_HOST to set the url to the docker server.
// Use DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
// Use DOCKER_CERT_PATH to load the tls certificates from.
// Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
func NewEnvClient() (*Client, error) {
	var client *http.Client
	if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
		options := tlsconfig.Options{
			CAFile:             filepath.Join(dockerCertPath, "ca.pem"),
			CertFile:           filepath.Join(dockerCertPath, "cert.pem"),
			KeyFile:            filepath.Join(dockerCertPath, "key.pem"),
			InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
		}
		tlsc, err := tlsconfig.Client(options)
		if err != nil {
			return nil, err
		}

		client = &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: tlsc,
			},
		}
	}

	host := os.Getenv("DOCKER_HOST")
	if host == "" {
		host = DefaultDockerHost
	}

	version := os.Getenv("DOCKER_API_VERSION")
	if version == "" {
		version = DefaultVersion
	}

	return NewClient(host, version, client, nil)
}

// NewClient initializes a new API client for the given host and API version.
// It uses the given http client as transport.
// It also initializes the custom http headers to add to each request.
//
// It won't send any version information if the version number is empty. It is
// highly recommended that you set a version or your client may break if the
// server is upgraded.
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
	proto, addr, basePath, err := ParseHost(host)
	if err != nil {
		return nil, err
	}

	transport, err := transport.NewTransportWithHTTP(proto, addr, client)
	if err != nil {
		return nil, err
	}

	return &Client{
		proto:             proto,
		addr:              addr,
		basePath:          basePath,
		transport:         transport,
		version:           version,
		customHTTPHeaders: httpHeaders,
	}, nil
}

// getAPIPath returns the versioned request path to call the api.
// It appends the query parameters to the path if they are not empty.
func (cli *Client) getAPIPath(p string, query url.Values) string {
	var apiPath string
	if cli.version != "" {
		v := strings.TrimPrefix(cli.version, "v")
		apiPath = fmt.Sprintf("%s/v%s%s", cli.basePath, v, p)
	} else {
		apiPath = fmt.Sprintf("%s%s", cli.basePath, p)
	}

	u := &url.URL{
		Path: apiPath,
	}
	if len(query) > 0 {
		u.RawQuery = query.Encode()
	}
	return u.String()
}

// ClientVersion returns the version string associated with this
// instance of the Client. Note that this value can be changed
// via the DOCKER_API_VERSION env var.
func (cli *Client) ClientVersion() string {
	return cli.version
}

// UpdateClientVersion updates the version string associated with this
// instance of the Client.
func (cli *Client) UpdateClientVersion(v string) {
	cli.version = v
}

// ParseHost verifies that the given host strings is valid.
func ParseHost(host string) (string, string, string, error) {
	protoAddrParts := strings.SplitN(host, "://", 2)
	if len(protoAddrParts) == 1 {
		return "", "", "", fmt.Errorf("unable to parse docker host `%s`", host)
	}

	var basePath string
	proto, addr := protoAddrParts[0], protoAddrParts[1]
	if proto == "tcp" {
		parsed, err := url.Parse("tcp://" + addr)
		if err != nil {
			return "", "", "", err
		}
		addr = parsed.Host
		basePath = parsed.Path
	}
	return proto, addr, basePath, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Tony Bai.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package cmppclient

import (
	"encoding/binary"
	"errors"
	"io"
	"net"

	"github.com/bigwhite/gocmpp/packet"
)

var ErrNotCompleted = errors.New("data not being handled completed")
var ErrRespNotMatch = errors.New("the response is not matched with the request")

// Client stands for one client-side instance, just like a session.
// It may connect to the server, send & recv cmpp packets and terminate the connection.
type Client struct {
	t         uint8 // packet response timeout, default: 60s
	keepAlive bool  // indicates whether current session is a keepalive one, default: true
	conn      net.Conn
	typ       cmpppacket.Type
	seqId     <-chan uint32
	done      chan<- struct{}
}

// New establishes a new cmpp client.
func New(typ cmpppacket.Type) *Client {
	seqId, done := newSeqIdGenerator()
	return &Client{
		t:         60,
		keepAlive: true,
		typ:       typ,
		seqId:     seqId,
		done:      done,
	}
}

func newSeqIdGenerator() (<-chan uint32, chan<- struct{}) {
	out := make(chan uint32)
	done := make(chan struct{})

	go func() {
		var i uint32
		for {
			select {
			case out <- i:
				i++
			case <-done:
				close(out)
				return
			}
		}
	}()
	return out, done
}

func (cli *Client) Free() {
	if cli != nil {
		if cli.conn != nil {
			cli.conn.Close()
		}
		close(cli.done)
		cli = nil
	}
}

// SetT sets the heartbeat response timeout for the client.
// You should call this method before session established.
func (cli *Client) SetT(t uint8) {
	cli.t = t
}

// SetKeepAlive sets the connection attribute for the client.
// You should call this method before session established.
func (cli *Client) SetKeepAlive(keepAlive bool) {
	cli.keepAlive = keepAlive
}

// Connect connect to the cmpp server in block mode.
// It sends login packet, receive and parse connect response packet.
func (cli *Client) Connect(servAddr, user, password string) error {
	var err error
	cli.conn, err = net.Dial("tcp", servAddr)
	if err != nil {
		return err
	}

	// Login to the server.
	req := &cmpppacket.CmppConnReqPkt{
		SrcAddr: user,
		Secret:  password,
		Version: cli.typ,
	}

	err = cli.SendPacket(req)
	if err != nil {
		return err
	}

	p, err := cli.RecvAndUnpackPkt()
	if err != nil {
		return err
	}

	var ok bool
	var status uint8
	if cli.typ == cmpppacket.V20 || cli.typ == cmpppacket.V21 {
		var rsp *cmpppacket.Cmpp2ConnRspPkt
		rsp, ok = p.(*cmpppacket.Cmpp2ConnRspPkt)
		status = rsp.Status
	} else {
		var rsp *cmpppacket.Cmpp3ConnRspPkt
		rsp, ok = p.(*cmpppacket.Cmpp3ConnRspPkt)
		status = uint8(rsp.Status)
	}

	if ok {
		return ErrRespNotMatch
	}

	if status != 0 {
		return cmpppacket.ConnRspStatusErrMap[status]
	}

	return nil
}

// SendPacket pack the cmpp packet structure and send it to the other peer.
func (cli *Client) SendPacket(packet cmpppacket.Packer) error {
	data, err := packet.Pack(<-cli.seqId)
	if err != nil {
		return err
	}

	n, err := cli.conn.Write(data)
	if err != nil {
		return nil
	}

	if n != len(data) {
		return ErrNotCompleted
	}
	return nil
}

// RecvAndUnpackPkt receives cmpp byte stream, and unpack it to some cmpp packet structure.
func (cli *Client) RecvAndUnpackPkt() (interface{}, error) {
	// Total_Length in packet
	var totalLen uint32
	err := binary.Read(cli.conn, binary.BigEndian, &totalLen)
	if err != nil {
		return nil, err
	}

	if cli.typ == cmpppacket.V30 {
		if totalLen < cmpppacket.CMPP3_PACKET_MIN || totalLen > cmpppacket.CMPP3_PACKET_MAX {
			return nil, cmpppacket.ErrTotalLengthInvalid
		}
	}

	if cli.typ == cmpppacket.V21 || cli.typ == cmpppacket.V20 {
		if totalLen < cmpppacket.CMPP2_PACKET_MIN || totalLen > cmpppacket.CMPP2_PACKET_MAX {
			return nil, cmpppacket.ErrTotalLengthInvalid
		}
	}

	// Command_Id
	var commandId cmpppacket.CommandId
	err = binary.Read(cli.conn, binary.BigEndian, &commandId)
	if err != nil {
		return nil, err
	}

	if !((commandId > cmpppacket.CMPP_REQUEST_MIN && commandId < cmpppacket.CMPP_REQUEST_MAX) ||
		(commandId > cmpppacket.CMPP_RESPONSE_MIN && commandId < cmpppacket.CMPP_RESPONSE_MAX)) {
		return nil, cmpppacket.ErrCommandIdInvalid
	}

	// The left packet data (start from seqId in header).
	// todo: may use cli.conn.SetReadDeadline to avoid longtime block
	var leftData = make([]byte, totalLen-8)
	_, err = io.ReadFull(cli.conn, leftData)
	if err != nil {
		return nil, err
	}

	var p cmpppacket.Packer
	switch commandId {
	case cmpppacket.CMPP_CONNECT:
		p = &cmpppacket.CmppConnReqPkt{}
	case cmpppacket.CMPP_CONNECT_RESP:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3ConnRspPkt{}
		} else {
			p = &cmpppacket.Cmpp2ConnRspPkt{}
		}
	case cmpppacket.CMPP_SUBMIT:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3SubmitReqPkt{}
		} else {
			p = &cmpppacket.Cmpp2SubmitReqPkt{}
		}
	case cmpppacket.CMPP_SUBMIT_RESP:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3SubmitRspPkt{}
		} else {
			p = &cmpppacket.Cmpp2SubmitRspPkt{}
		}
	case cmpppacket.CMPP_FWD:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3FwdReqPkt{}
		} else {
			p = &cmpppacket.Cmpp2FwdReqPkt{}
		}
	case cmpppacket.CMPP_FWD_RESP:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3FwdRspPkt{}
		} else {
			p = &cmpppacket.Cmpp2FwdRspPkt{}
		}
	default:
		p = nil
		return nil, cmpppacket.ErrCommandIdNotSupported
	}

	err = p.Unpack(leftData)
	if err != nil {
		return nil, err
	}
	return p, nil
}
<commit_msg>fix logic check issue<commit_after>// Copyright 2015 Tony Bai.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package cmppclient

import (
	"encoding/binary"
	"errors"
	"io"
	"net"

	"github.com/bigwhite/gocmpp/packet"
)

var ErrNotCompleted = errors.New("data not being handled completed")
var ErrRespNotMatch = errors.New("the response is not matched with the request")

// Client stands for one client-side instance, just like a session.
// It may connect to the server, send & recv cmpp packets and terminate the connection.
type Client struct {
	t         uint8 // packet response timeout, default: 60s
	keepAlive bool  // indicates whether current session is a keepalive one, default: true
	conn      net.Conn
	typ       cmpppacket.Type
	seqId     <-chan uint32
	done      chan<- struct{}
}

// New establishes a new cmpp client.
func New(typ cmpppacket.Type) *Client {
	seqId, done := newSeqIdGenerator()
	return &Client{
		t:         60,
		keepAlive: true,
		typ:       typ,
		seqId:     seqId,
		done:      done,
	}
}

func newSeqIdGenerator() (<-chan uint32, chan<- struct{}) {
	out := make(chan uint32)
	done := make(chan struct{})

	go func() {
		var i uint32
		for {
			select {
			case out <- i:
				i++
			case <-done:
				close(out)
				return
			}
		}
	}()
	return out, done
}

func (cli *Client) Free() {
	if cli != nil {
		if cli.conn != nil {
			cli.conn.Close()
		}
		close(cli.done)
		cli = nil
	}
}

// SetT sets the heartbeat response timeout for the client.
// You should call this method before session established.
func (cli *Client) SetT(t uint8) {
	cli.t = t
}

// SetKeepAlive sets the connection attribute for the client.
// You should call this method before session established.
func (cli *Client) SetKeepAlive(keepAlive bool) {
	cli.keepAlive = keepAlive
}

// Connect connect to the cmpp server in block mode.
// It sends login packet, receive and parse connect response packet.
func (cli *Client) Connect(servAddr, user, password string) error {
	var err error
	cli.conn, err = net.Dial("tcp", servAddr)
	if err != nil {
		return err
	}

	// Login to the server.
	req := &cmpppacket.CmppConnReqPkt{
		SrcAddr: user,
		Secret:  password,
		Version: cli.typ,
	}

	err = cli.SendPacket(req)
	if err != nil {
		return err
	}

	p, err := cli.RecvAndUnpackPkt()
	if err != nil {
		return err
	}

	var ok bool
	var status uint8
	if cli.typ == cmpppacket.V20 || cli.typ == cmpppacket.V21 {
		var rsp *cmpppacket.Cmpp2ConnRspPkt
		rsp, ok = p.(*cmpppacket.Cmpp2ConnRspPkt)
		status = rsp.Status
	} else {
		var rsp *cmpppacket.Cmpp3ConnRspPkt
		rsp, ok = p.(*cmpppacket.Cmpp3ConnRspPkt)
		status = uint8(rsp.Status)
	}

	if !ok {
		return ErrRespNotMatch
	}

	if status != 0 {
		return cmpppacket.ConnRspStatusErrMap[status]
	}

	return nil
}

// SendPacket pack the cmpp packet structure and send it to the other peer.
func (cli *Client) SendPacket(packet cmpppacket.Packer) error {
	data, err := packet.Pack(<-cli.seqId)
	if err != nil {
		return err
	}

	n, err := cli.conn.Write(data)
	if err != nil {
		return nil
	}

	if n != len(data) {
		return ErrNotCompleted
	}
	return nil
}

// RecvAndUnpackPkt receives cmpp byte stream, and unpack it to some cmpp packet structure.
func (cli *Client) RecvAndUnpackPkt() (interface{}, error) {
	// Total_Length in packet
	var totalLen uint32
	err := binary.Read(cli.conn, binary.BigEndian, &totalLen)
	if err != nil {
		return nil, err
	}

	if cli.typ == cmpppacket.V30 {
		if totalLen < cmpppacket.CMPP3_PACKET_MIN || totalLen > cmpppacket.CMPP3_PACKET_MAX {
			return nil, cmpppacket.ErrTotalLengthInvalid
		}
	}

	if cli.typ == cmpppacket.V21 || cli.typ == cmpppacket.V20 {
		if totalLen < cmpppacket.CMPP2_PACKET_MIN || totalLen > cmpppacket.CMPP2_PACKET_MAX {
			return nil, cmpppacket.ErrTotalLengthInvalid
		}
	}

	// Command_Id
	var commandId cmpppacket.CommandId
	err = binary.Read(cli.conn, binary.BigEndian, &commandId)
	if err != nil {
		return nil, err
	}

	if !((commandId > cmpppacket.CMPP_REQUEST_MIN && commandId < cmpppacket.CMPP_REQUEST_MAX) ||
		(commandId > cmpppacket.CMPP_RESPONSE_MIN && commandId < cmpppacket.CMPP_RESPONSE_MAX)) {
		return nil, cmpppacket.ErrCommandIdInvalid
	}

	// The left packet data (start from seqId in header).
	// todo: may use cli.conn.SetReadDeadline to avoid longtime block
	var leftData = make([]byte, totalLen-8)
	_, err = io.ReadFull(cli.conn, leftData)
	if err != nil {
		return nil, err
	}

	var p cmpppacket.Packer
	switch commandId {
	case cmpppacket.CMPP_CONNECT:
		p = &cmpppacket.CmppConnReqPkt{}
	case cmpppacket.CMPP_CONNECT_RESP:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3ConnRspPkt{}
		} else {
			p = &cmpppacket.Cmpp2ConnRspPkt{}
		}
	case cmpppacket.CMPP_SUBMIT:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3SubmitReqPkt{}
		} else {
			p = &cmpppacket.Cmpp2SubmitReqPkt{}
		}
	case cmpppacket.CMPP_SUBMIT_RESP:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3SubmitRspPkt{}
		} else {
			p = &cmpppacket.Cmpp2SubmitRspPkt{}
		}
	case cmpppacket.CMPP_FWD:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3FwdReqPkt{}
		} else {
			p = &cmpppacket.Cmpp2FwdReqPkt{}
		}
	case cmpppacket.CMPP_FWD_RESP:
		if cli.typ == cmpppacket.V30 {
			p = &cmpppacket.Cmpp3FwdRspPkt{}
		} else {
			p = &cmpppacket.Cmpp2FwdRspPkt{}
		}
	default:
		p = nil
		return nil, cmpppacket.ErrCommandIdNotSupported
	}

	err = p.Unpack(leftData)
	if err != nil {
		return nil, err
	}
	return p, nil
}
<|endoftext|>


<commit_before>package client

import (
	"errors"
	"io"
	"sync"

	"github.com/joushou/qp"
)

var (
	// ErrWeirdResponse indicates that a response type was unexpected. That is,
	// not the response fitting the request or ErrorResponse.
	ErrWeirdResponse = errors.New("weird response")

	// ErrNoFidsAvailable indicate that the pool of fids have been depleted,
	// due to 0xFFFE files being open.
	ErrNoFidsAvailable = errors.New("no available fids")

	// ErrNoSuchFid indicates that the fid does not exist.
	ErrNoSuchFid = errors.New("no such fid")
)

func toError(m qp.Message) error {
	if eresp, ok := m.(*qp.ErrorResponse); ok {
		return errors.New(eresp.Error)
	}
	return nil
}

// DirectClient allows for wrapped access to the low-level 9P primitives, but
// without having to deal with concerns about actual serialization.
type DirectClient struct {
	fids    map[qp.Fid]*Fid
	fidLock sync.Mutex
	client  *Client
	nextFid qp.Fid
}

// NewDirectClient returns an initialized DirectClient.
func NewDirectClient() *DirectClient {
	return &DirectClient{
		fids: make(map[qp.Fid]*Fid),
	}
}

// getFid allocates and returns a new Fid.
func (dc *DirectClient) getFid() (*Fid, error) {
	dc.fidLock.Lock()
	defer dc.fidLock.Unlock()
	for i := qp.Fid(0); i < qp.NOFID; i++ {
		taken := false
		for key := range dc.fids {
			if key == i {
				taken = true
				break
			}
		}
		if !taken {
			f := &Fid{
				fid:    i,
				parent: dc,
			}
			dc.fids[i] = f
			return f, nil
		}
	}
	return nil, ErrNoFidsAvailable
}

// rmFid removes a Fid from the usage pool.
func (dc *DirectClient) rmFid(f *Fid) error {
	dc.fidLock.Lock()
	defer dc.fidLock.Unlock()
	_, ok := dc.fids[f.fid]
	if ok {
		delete(dc.fids, f.fid)
	}
	return ErrNoSuchFid
}

// Connect starts a DirectClient on the provided io.ReadWriter.
func (dc *DirectClient) Connect(rw io.ReadWriter) {
	dc.client = New(rw)
	go dc.client.Start()
}

// Stop clunks all fids and terminates the client.
func (dc *DirectClient) Stop() {
	for _, fid := range dc.fids {
		fid.Clunk()
	}
	dc.fids = nil
	dc.client.Stop()
}

// FlushAll flushes all current requests.
func (dc *DirectClient) FlushAll() {
	tags := dc.client.PendingTags()
	for _, t := range tags {
		dc.Flush(t)
		dc.client.Ditch(t)
	}
}

func (dc *DirectClient) Flush(oldtag qp.Tag) error {
	t, err := dc.client.Tag()
	if err != nil {
		return err
	}
	_, err = dc.client.Send(&qp.FlushRequest{
		Tag:    t,
		OldTag: oldtag,
	})

	return err
}

func (dc *DirectClient) Version(maxsize uint32, version string) (uint32, string, error) {
	resp, err := dc.client.Send(&qp.VersionRequest{
		Tag:     qp.NOTAG,
		MaxSize: maxsize,
		Version: qp.Version,
	})

	if err != nil {
		return 0, "", err
	}
	if err = toError(resp); err != nil {
		return 0, "", err
	}

	vresp, ok := resp.(*qp.VersionResponse)
	if !ok {
		return 0, "", ErrWeirdResponse
	}

	return vresp.MaxSize, vresp.Version, nil
}

func (dc *DirectClient) Auth(user, service string) (*Fid, qp.Qid, error) {
	t, err := dc.client.Tag()
	if err != nil {
		return nil, qp.Qid{}, err
	}

	nfid, err := dc.getFid()
	if err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}

	resp, err := dc.client.Send(&qp.AuthRequest{
		Tag:      t,
		AuthFid:  nfid.fid,
		Username: user,
		Service:  service,
	})
	if err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}
	if err = toError(resp); err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}

	aresp, ok := resp.(*qp.AuthResponse)
	if !ok {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, ErrWeirdResponse
	}

	return nfid, aresp.AuthQid, nil
}

func (dc *DirectClient) Attach(authfid *Fid, user, service string) (*Fid, qp.Qid, error) {
	t, err := dc.client.Tag()
	if err != nil {
		return nil, qp.Qid{}, err
	}

	nfid, err := dc.getFid()
	if err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}

	afid := qp.NOFID
	if authfid != nil {
		afid = authfid.fid
	}

	resp, err := dc.client.Send(&qp.AttachRequest{
		Tag:      t,
		Fid:      nfid.fid,
		AuthFid:  afid,
		Username: user,
		Service:  service,
	})
	if err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}
	if err = toError(resp); err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}

	aresp, ok := resp.(*qp.AttachResponse)
	if !ok {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, ErrWeirdResponse
	}
	return nfid, aresp.Qid, nil
}

type Fid struct {
	fid    qp.Fid
	parent *DirectClient
}

func (f *Fid) Walk(names []string) (*Fid, []qp.Qid, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return nil, nil, err
	}

	nfid, err := f.parent.getFid()
	if err != nil {
		f.parent.rmFid(nfid)
		return nil, nil, err
	}

	resp, err := f.parent.client.Send(&qp.WalkRequest{
		Tag:    t,
		Fid:    f.fid,
		NewFid: nfid.fid,
		Names:  names,
	})

	if err != nil {
		return nil, nil, err
	}
	if err = toError(resp); err != nil {
		f.parent.rmFid(nfid)
		return nil, nil, err
	}

	wresp, ok := resp.(*qp.WalkResponse)
	if !ok {
		f.parent.rmFid(nfid)
		return nil, nil, ErrWeirdResponse
	}

	if len(wresp.Qids) != len(names) {
		f.parent.rmFid(nfid)
		nfid = nil
	}
	return nfid, wresp.Qids, nil
}

func (f *Fid) Clunk() error {
	t, err := f.parent.client.Tag()
	if err != nil {
		return err
	}

	resp, err := f.parent.client.Send(&qp.ClunkRequest{
		Tag: t,
		Fid: f.fid,
	})
	if err != nil {
		return err
	}
	if err = toError(resp); err != nil {
		return err
	}
	_, ok := resp.(*qp.ClunkResponse)
	if !ok {
		return ErrWeirdResponse
	}
	f.parent.rmFid(f)
	return nil
}

func (f *Fid) Remove() error {
	t, err := f.parent.client.Tag()
	if err != nil {
		return err
	}

	resp, err := f.parent.client.Send(&qp.RemoveRequest{
		Tag: t,
		Fid: f.fid,
	})
	if err != nil {
		return err
	}
	if err = toError(resp); err != nil {
		return err
	}
	_, ok := resp.(*qp.RemoveResponse)
	if !ok {
		return ErrWeirdResponse
	}
	f.parent.rmFid(f)
	return nil
}

func (f *Fid) Open(mode qp.OpenMode) (qp.Qid, uint32, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return qp.Qid{}, 0, err
	}

	resp, err := f.parent.client.Send(&qp.OpenRequest{
		Tag:  t,
		Fid:  f.fid,
		Mode: mode,
	})

	if err != nil {
		return qp.Qid{}, 0, err
	}
	if err = toError(resp); err != nil {
		return qp.Qid{}, 0, err
	}

	oresp, ok := resp.(*qp.OpenResponse)
	if !ok {
		return qp.Qid{}, 0, ErrWeirdResponse
	}

	return oresp.Qid, oresp.IOUnit, nil
}

func (f *Fid) Create(name string, perm qp.FileMode, mode qp.OpenMode) (qp.Qid, uint32, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return qp.Qid{}, 0, err
	}

	resp, err := f.parent.client.Send(&qp.CreateRequest{
		Tag:         t,
		Fid:         f.fid,
		Name:        name,
		Permissions: perm,
		Mode:        mode,
	})

	if err != nil {
		return qp.Qid{}, 0, err
	}
	if err = toError(resp); err != nil {
		return qp.Qid{}, 0, err
	}

	oresp, ok := resp.(*qp.CreateResponse)
	if !ok {
		return qp.Qid{}, 0, ErrWeirdResponse
	}

	return oresp.Qid, oresp.IOUnit, nil
}

func (f *Fid) Read(offset uint64, count uint32) ([]byte, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return nil, err
	}

	resp, err := f.parent.client.Send(&qp.ReadRequest{
		Tag:    t,
		Fid:    f.fid,
		Offset: offset,
		Count:  count,
	})

	if err != nil {
		return nil, err
	}
	if err = toError(resp); err != nil {
		return nil, err
	}
	rresp, ok := resp.(*qp.ReadResponse)
	if !ok {
		return nil, ErrWeirdResponse
	}
	return rresp.Data, nil
}

func (f *Fid) Write(offset uint64, data []byte) (uint32, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return 0, err
	}

	resp, err := f.parent.client.Send(&qp.WriteRequest{
		Tag:    t,
		Fid:    f.fid,
		Offset: offset,
		Data:   data,
	})
	if err != nil {
		return 0, err
	}
	if err = toError(resp); err != nil {
		return 0, err
	}

	wresp, ok := resp.(*qp.WriteResponse)
	if !ok {
		return 0, ErrWeirdResponse
	}

	return wresp.Count, nil
}

func (f *Fid) Stat() (qp.Stat, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return qp.Stat{}, err
	}

	resp, err := f.parent.client.Send(&qp.StatRequest{
		Tag: t,
		Fid: f.fid,
	})

	if err != nil {
		return qp.Stat{}, err
	}
	if err = toError(resp); err != nil {
		return qp.Stat{}, err
	}

	sresp, ok := resp.(*qp.StatResponse)
	if !ok {
		return qp.Stat{}, ErrWeirdResponse
	}

	return sresp.Stat, nil
}

func (f *Fid) WriteStat(stat qp.Stat) error {
	t, err := f.parent.client.Tag()
	if err != nil {
		return err
	}

	resp, err := f.parent.client.Send(&qp.WriteStatRequest{
		Tag:  t,
		Fid:  f.fid,
		Stat: stat,
	})

	if err != nil {
		return err
	}
	if err = toError(resp); err != nil {
		return err
	}

	_, ok := resp.(*qp.WriteStatResponse)
	if !ok {
		return ErrWeirdResponse
	}

	return nil
}
<commit_msg>Even more linter massage<commit_after>package client

import (
	"errors"
	"io"
	"sync"

	"github.com/joushou/qp"
)

var (
	// ErrWeirdResponse indicates that a response type was unexpected. That is,
	// not the response fitting the request or ErrorResponse.
	ErrWeirdResponse = errors.New("weird response")

	// ErrNoFidsAvailable indicate that the pool of fids have been depleted,
	// due to 0xFFFE files being open.
	ErrNoFidsAvailable = errors.New("no available fids")

	// ErrNoSuchFid indicates that the fid does not exist.
	ErrNoSuchFid = errors.New("no such fid")
)

func toError(m qp.Message) error {
	if eresp, ok := m.(*qp.ErrorResponse); ok {
		return errors.New(eresp.Error)
	}
	return nil
}

// DirectClient allows for wrapped access to the low-level 9P primitives, but
// without having to deal with concerns about actual serialization.
type DirectClient struct {
	fids    map[qp.Fid]*Fid
	fidLock sync.Mutex
	client  *Client
	nextFid qp.Fid
}

// NewDirectClient returns an initialized DirectClient.
func NewDirectClient() *DirectClient {
	return &DirectClient{
		fids: make(map[qp.Fid]*Fid),
	}
}

// getFid allocates and returns a new Fid.
func (dc *DirectClient) getFid() (*Fid, error) {
	dc.fidLock.Lock()
	defer dc.fidLock.Unlock()
	for i := qp.Fid(0); i < qp.NOFID; i++ {
		taken := false
		for key := range dc.fids {
			if key == i {
				taken = true
				break
			}
		}
		if !taken {
			f := &Fid{
				fid:    i,
				parent: dc,
			}
			dc.fids[i] = f
			return f, nil
		}
	}
	return nil, ErrNoFidsAvailable
}

// rmFid removes a Fid from the usage pool.
func (dc *DirectClient) rmFid(f *Fid) error {
	dc.fidLock.Lock()
	defer dc.fidLock.Unlock()
	_, ok := dc.fids[f.fid]
	if ok {
		delete(dc.fids, f.fid)
	}
	return ErrNoSuchFid
}

// Connect starts a DirectClient on the provided io.ReadWriter.
func (dc *DirectClient) Connect(rw io.ReadWriter) {
	dc.client = New(rw)
	go dc.client.Start()
}

// Stop clunks all fids and terminates the client.
func (dc *DirectClient) Stop() {
	for _, fid := range dc.fids {
		fid.Clunk()
	}
	dc.fids = nil
	dc.client.Stop()
}

// FlushAll flushes all current requests.
func (dc *DirectClient) FlushAll() {
	tags := dc.client.PendingTags()
	for _, t := range tags {
		dc.Flush(t)
		dc.client.Ditch(t)
	}
}

// Flush sends Tflush.
func (dc *DirectClient) Flush(oldtag qp.Tag) error {
	t, err := dc.client.Tag()
	if err != nil {
		return err
	}
	_, err = dc.client.Send(&qp.FlushRequest{
		Tag:    t,
		OldTag: oldtag,
	})

	return err
}

// Version sends Tversion.
func (dc *DirectClient) Version(maxsize uint32, version string) (uint32, string, error) {
	resp, err := dc.client.Send(&qp.VersionRequest{
		Tag:     qp.NOTAG,
		MaxSize: maxsize,
		Version: qp.Version,
	})

	if err != nil {
		return 0, "", err
	}
	if err = toError(resp); err != nil {
		return 0, "", err
	}

	vresp, ok := resp.(*qp.VersionResponse)
	if !ok {
		return 0, "", ErrWeirdResponse
	}

	return vresp.MaxSize, vresp.Version, nil
}

// Auth sends Tauth.
func (dc *DirectClient) Auth(user, service string) (*Fid, qp.Qid, error) {
	t, err := dc.client.Tag()
	if err != nil {
		return nil, qp.Qid{}, err
	}

	nfid, err := dc.getFid()
	if err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}

	resp, err := dc.client.Send(&qp.AuthRequest{
		Tag:      t,
		AuthFid:  nfid.fid,
		Username: user,
		Service:  service,
	})
	if err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}
	if err = toError(resp); err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}

	aresp, ok := resp.(*qp.AuthResponse)
	if !ok {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, ErrWeirdResponse
	}

	return nfid, aresp.AuthQid, nil
}

// Attach sends Tattch.
func (dc *DirectClient) Attach(authfid *Fid, user, service string) (*Fid, qp.Qid, error) {
	t, err := dc.client.Tag()
	if err != nil {
		return nil, qp.Qid{}, err
	}

	nfid, err := dc.getFid()
	if err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}

	afid := qp.NOFID
	if authfid != nil {
		afid = authfid.fid
	}

	resp, err := dc.client.Send(&qp.AttachRequest{
		Tag:      t,
		Fid:      nfid.fid,
		AuthFid:  afid,
		Username: user,
		Service:  service,
	})
	if err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}
	if err = toError(resp); err != nil {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, err
	}

	aresp, ok := resp.(*qp.AttachResponse)
	if !ok {
		dc.rmFid(nfid)
		return nil, qp.Qid{}, ErrWeirdResponse
	}
	return nfid, aresp.Qid, nil
}

// Fid represents a fid, implementing all 9P features that operate on a fid.
type Fid struct {
	fid    qp.Fid
	parent *DirectClient
}

// Walk sends Twalk.
func (f *Fid) Walk(names []string) (*Fid, []qp.Qid, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return nil, nil, err
	}

	nfid, err := f.parent.getFid()
	if err != nil {
		f.parent.rmFid(nfid)
		return nil, nil, err
	}

	resp, err := f.parent.client.Send(&qp.WalkRequest{
		Tag:    t,
		Fid:    f.fid,
		NewFid: nfid.fid,
		Names:  names,
	})

	if err != nil {
		return nil, nil, err
	}
	if err = toError(resp); err != nil {
		f.parent.rmFid(nfid)
		return nil, nil, err
	}

	wresp, ok := resp.(*qp.WalkResponse)
	if !ok {
		f.parent.rmFid(nfid)
		return nil, nil, ErrWeirdResponse
	}

	if len(wresp.Qids) != len(names) {
		f.parent.rmFid(nfid)
		nfid = nil
	}
	return nfid, wresp.Qids, nil
}

// Clunk sends Tclunk.
func (f *Fid) Clunk() error {
	t, err := f.parent.client.Tag()
	if err != nil {
		return err
	}

	resp, err := f.parent.client.Send(&qp.ClunkRequest{
		Tag: t,
		Fid: f.fid,
	})
	if err != nil {
		return err
	}
	if err = toError(resp); err != nil {
		return err
	}
	_, ok := resp.(*qp.ClunkResponse)
	if !ok {
		return ErrWeirdResponse
	}
	f.parent.rmFid(f)
	return nil
}

// Remove sends Tremove.
func (f *Fid) Remove() error {
	t, err := f.parent.client.Tag()
	if err != nil {
		return err
	}

	resp, err := f.parent.client.Send(&qp.RemoveRequest{
		Tag: t,
		Fid: f.fid,
	})
	if err != nil {
		return err
	}
	if err = toError(resp); err != nil {
		return err
	}
	_, ok := resp.(*qp.RemoveResponse)
	if !ok {
		return ErrWeirdResponse
	}
	f.parent.rmFid(f)
	return nil
}

// Open sends Topen.
func (f *Fid) Open(mode qp.OpenMode) (qp.Qid, uint32, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return qp.Qid{}, 0, err
	}

	resp, err := f.parent.client.Send(&qp.OpenRequest{
		Tag:  t,
		Fid:  f.fid,
		Mode: mode,
	})

	if err != nil {
		return qp.Qid{}, 0, err
	}
	if err = toError(resp); err != nil {
		return qp.Qid{}, 0, err
	}

	oresp, ok := resp.(*qp.OpenResponse)
	if !ok {
		return qp.Qid{}, 0, ErrWeirdResponse
	}

	return oresp.Qid, oresp.IOUnit, nil
}

// Create sends Tcreate.
func (f *Fid) Create(name string, perm qp.FileMode, mode qp.OpenMode) (qp.Qid, uint32, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return qp.Qid{}, 0, err
	}

	resp, err := f.parent.client.Send(&qp.CreateRequest{
		Tag:         t,
		Fid:         f.fid,
		Name:        name,
		Permissions: perm,
		Mode:        mode,
	})

	if err != nil {
		return qp.Qid{}, 0, err
	}
	if err = toError(resp); err != nil {
		return qp.Qid{}, 0, err
	}

	oresp, ok := resp.(*qp.CreateResponse)
	if !ok {
		return qp.Qid{}, 0, ErrWeirdResponse
	}

	return oresp.Qid, oresp.IOUnit, nil
}

// Read sends Tread.
func (f *Fid) Read(offset uint64, count uint32) ([]byte, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return nil, err
	}

	resp, err := f.parent.client.Send(&qp.ReadRequest{
		Tag:    t,
		Fid:    f.fid,
		Offset: offset,
		Count:  count,
	})

	if err != nil {
		return nil, err
	}
	if err = toError(resp); err != nil {
		return nil, err
	}
	rresp, ok := resp.(*qp.ReadResponse)
	if !ok {
		return nil, ErrWeirdResponse
	}
	return rresp.Data, nil
}

// Write sends Twrite.
func (f *Fid) Write(offset uint64, data []byte) (uint32, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return 0, err
	}

	resp, err := f.parent.client.Send(&qp.WriteRequest{
		Tag:    t,
		Fid:    f.fid,
		Offset: offset,
		Data:   data,
	})
	if err != nil {
		return 0, err
	}
	if err = toError(resp); err != nil {
		return 0, err
	}

	wresp, ok := resp.(*qp.WriteResponse)
	if !ok {
		return 0, ErrWeirdResponse
	}

	return wresp.Count, nil
}

// Stat sends Tstat.
func (f *Fid) Stat() (qp.Stat, error) {
	t, err := f.parent.client.Tag()
	if err != nil {
		return qp.Stat{}, err
	}

	resp, err := f.parent.client.Send(&qp.StatRequest{
		Tag: t,
		Fid: f.fid,
	})

	if err != nil {
		return qp.Stat{}, err
	}
	if err = toError(resp); err != nil {
		return qp.Stat{}, err
	}

	sresp, ok := resp.(*qp.StatResponse)
	if !ok {
		return qp.Stat{}, ErrWeirdResponse
	}

	return sresp.Stat, nil
}

// WriteStat sends Twstat.
func (f *Fid) WriteStat(stat qp.Stat) error {
	t, err := f.parent.client.Tag()
	if err != nil {
		return err
	}

	resp, err := f.parent.client.Send(&qp.WriteStatRequest{
		Tag:  t,
		Fid:  f.fid,
		Stat: stat,
	})

	if err != nil {
		return err
	}
	if err = toError(resp); err != nil {
		return err
	}

	_, ok := resp.(*qp.WriteStatResponse)
	if !ok {
		return ErrWeirdResponse
	}

	return nil
}
<|endoftext|>


<commit_before>package nc

const documentation = []struct {
	Endpoint    string
	Request     string
	Response    string
	Description string
}{
	{"ari:applications:all", "ignored", "[]string", "Get all applications"},
	{"ari:applications:data:>", "ignored", "ari.ApplicationData", "Get the data for the given applications"},
	{"ari:applications:subscribe:>", "string", "ignored", "Subscribe the app to the event source"},
	{"ari:applications:unsubscribe:>", "string", "ignored", "Unsubscribe the app from the event source"},
}
<commit_msg>v3 - nats client - fix compile error in documentation<commit_after>package nc

// Documentation is the list of nats endpoints, their request and response types, and their descriptions.
var Documentation = []struct {
	Endpoint    string
	Request     string
	Response    string
	Description string
}{
	{"ari:applications:all", "ignored", "[]string", "Get all applications"},
	{"ari:applications:data:>", "ignored", "ari.ApplicationData", "Get the data for the given applications"},
	{"ari:applications:subscribe:>", "string", "ignored", "Subscribe the app to the event source"},
	{"ari:applications:unsubscribe:>", "string", "ignored", "Unsubscribe the app from the event source"},
}
<|endoftext|>


<commit_before>// Copyright 2013 docker-cluster 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 cluster

import (
	"github.com/fsouza/go-dockerclient"
	"io"
)

// RemoveImage removes an image from all nodes in the cluster, returning an
// error in case of failure.
func (c *Cluster) RemoveImage(name string) error {
	_, err := c.runOnNodes(func(n node) (interface{}, error) {
		return nil, n.RemoveImage(name)
	}, docker.ErrNoSuchImage, false)
	return err
}

// PullImage pulls an image from a remote registry server, returning an error
// in case of failure.
func (c *Cluster) PullImage(opts docker.PullImageOptions, w io.Writer) error {
	_, err := c.runOnNodes(func(n node) (interface{}, error) {
		return nil, n.PullImage(opts, w)
	}, docker.ErrNoSuchImage, true)
	return err
}

// PushImage pushes an image to a remote registry server, returning an error in
// case of failure.
func (c *Cluster) PushImage(opts docker.PushImageOptions, auth docker.AuthConfiguration, w io.Writer) error {
	if node, err := c.getNodeForImage(opts.Name); err == nil {
		return node.PushImage(opts, auth, w)
	} else if err != errStorageDisabled {
		return err
	}
	_, err := c.runOnNodes(func(n node) (interface{}, error) {
		return nil, n.PushImage(opts, auth, w)
	}, docker.ErrNoSuchImage, false)
	return err
}

func (c *Cluster) getNodeForImage(image string) (node, error) {
	return c.getNode(func(s Storage) (string, error) {
		return s.RetrieveImage(image)
	})
}

// ImportImage imports an image from a url or stdin
func (c *Cluster) ImportImage(opts docker.ImportImageOptions, w io.Writer) error {
	_, err := c.runOnNodes(func(n node) (interface{}, error) {
		return nil, n.ImportImage(opts, w)
	}, docker.ErrNoSuchImage)
	return err
}
<commit_msg>cluster/image: passing wait parameter to runOnNodes<commit_after>// Copyright 2013 docker-cluster 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 cluster

import (
	"github.com/fsouza/go-dockerclient"
	"io"
)

// RemoveImage removes an image from all nodes in the cluster, returning an
// error in case of failure.
func (c *Cluster) RemoveImage(name string) error {
	_, err := c.runOnNodes(func(n node) (interface{}, error) {
		return nil, n.RemoveImage(name)
	}, docker.ErrNoSuchImage, false)
	return err
}

// PullImage pulls an image from a remote registry server, returning an error
// in case of failure.
func (c *Cluster) PullImage(opts docker.PullImageOptions, w io.Writer) error {
	_, err := c.runOnNodes(func(n node) (interface{}, error) {
		return nil, n.PullImage(opts, w)
	}, docker.ErrNoSuchImage, true)
	return err
}

// PushImage pushes an image to a remote registry server, returning an error in
// case of failure.
func (c *Cluster) PushImage(opts docker.PushImageOptions, auth docker.AuthConfiguration, w io.Writer) error {
	if node, err := c.getNodeForImage(opts.Name); err == nil {
		return node.PushImage(opts, auth, w)
	} else if err != errStorageDisabled {
		return err
	}
	_, err := c.runOnNodes(func(n node) (interface{}, error) {
		return nil, n.PushImage(opts, auth, w)
	}, docker.ErrNoSuchImage, false)
	return err
}

func (c *Cluster) getNodeForImage(image string) (node, error) {
	return c.getNode(func(s Storage) (string, error) {
		return s.RetrieveImage(image)
	})
}

// ImportImage imports an image from a url or stdin
func (c *Cluster) ImportImage(opts docker.ImportImageOptions, w io.Writer) error {
	_, err := c.runOnNodes(func(n node) (interface{}, error) {
		return nil, n.ImportImage(opts, w)
	}, docker.ErrNoSuchImage, false)
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"net"
	"time"

	"github.com/caarlos0/env"
	"github.com/vardius/go-api-boilerplate/pkg/auth/infrastructure/proto"
	server "github.com/vardius/go-api-boilerplate/pkg/auth/interfaces/grpc"
	"github.com/vardius/go-api-boilerplate/pkg/common/application/jwt"
	"github.com/vardius/go-api-boilerplate/pkg/common/application/log"
	"github.com/vardius/go-api-boilerplate/pkg/common/application/os/shutdown"
	"google.golang.org/grpc"
)

type config struct {
	Env    string `env:"ENV"    envDefault:"development"`
	Host   string `env:"HOST"   envDefault:"0.0.0.0"`
	Port   int    `env:"PORT"   envDefault:"3001"`
	Secret string `env:"SECRET" envDefault:"secret"`
}

func main() {
	ctx := context.Background()

	cfg := config{}
	env.Parse(&cfg)

	logger := log.New(cfg.Env)
	jwtService := jwt.New([]byte(cfg.Secret), time.Hour*24)

	grpcServer := grpc.NewServer()
	authServer := server.New(jwtService)

	proto.RegisterAuthenticationServer(grpcServer, authServer)

	lis, err := net.Listen("tcp", fmt.Sprintf("%s:%d", cfg.Host, cfg.Port))
	if err != nil {
		logger.Critical(ctx, "[auth] failed to listen %s:%d\n%v\n", cfg.Host, cfg.Port, err)
	} else {
		logger.Info(ctx, "[auth] running at %s:%d\n", cfg.Host, cfg.Port)
	}

	go func() {
		logger.Critical(ctx, "[auth] failed to serve: %v\n", grpcServer.Serve(lis))
	}()

	shutdown.GracefulStop(func() {
		logger.Info(ctx, "[auth] shutting down...\n")

		grpcServer.GracefulStop()

		logger.Info(ctx, "[auth] gracefully stopped\n")
	})
}
<commit_msg>Handle panic on grpc server<commit_after>package main

import (
	"context"
	"fmt"
	"net"
	"time"

	"github.com/caarlos0/env"
	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
	grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
	"github.com/vardius/go-api-boilerplate/pkg/auth/infrastructure/proto"
	server "github.com/vardius/go-api-boilerplate/pkg/auth/interfaces/grpc"
	"github.com/vardius/go-api-boilerplate/pkg/common/application/jwt"
	"github.com/vardius/go-api-boilerplate/pkg/common/application/log"
	"github.com/vardius/go-api-boilerplate/pkg/common/application/os/shutdown"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

type config struct {
	Env    string `env:"ENV"    envDefault:"development"`
	Host   string `env:"HOST"   envDefault:"0.0.0.0"`
	Port   int    `env:"PORT"   envDefault:"3001"`
	Secret string `env:"SECRET" envDefault:"secret"`
}

func main() {
	ctx := context.Background()

	cfg := config{}
	env.Parse(&cfg)

	logger := log.New(cfg.Env)
	jwtService := jwt.New([]byte(cfg.Secret), time.Hour*24)

	opts := []grpc_recovery.Option{
		grpc_recovery.WithRecoveryHandlerContext(func(ctx context.Context, rec interface{}) (err error) {
			logger.Critical(ctx, "Recovered in f %v", rec)

			return grpc.Errorf(codes.Internal, "%s", rec)
		}),
	}

	grpcServer := grpc.NewServer(
		grpc_middleware.WithUnaryServerChain(
			grpc_recovery.UnaryServerInterceptor(opts...),
		),
		grpc_middleware.WithStreamServerChain(
			grpc_recovery.StreamServerInterceptor(opts...),
		),
	)
	authServer := server.New(jwtService)

	proto.RegisterAuthenticationServer(grpcServer, authServer)

	lis, err := net.Listen("tcp", fmt.Sprintf("%s:%d", cfg.Host, cfg.Port))
	if err != nil {
		logger.Critical(ctx, "[auth] failed to listen %s:%d\n%v\n", cfg.Host, cfg.Port, err)
	} else {
		logger.Info(ctx, "[auth] running at %s:%d\n", cfg.Host, cfg.Port)
	}

	go func() {
		logger.Critical(ctx, "[auth] failed to serve: %v\n", grpcServer.Serve(lis))
	}()

	shutdown.GracefulStop(func() {
		logger.Info(ctx, "[auth] shutting down...\n")

		grpcServer.GracefulStop()

		logger.Info(ctx, "[auth] gracefully stopped\n")
	})
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"os"

	"github.com/kubernetes/helm/pkg/client"
	"github.com/spf13/cobra"
)

const initDesc = `
This command installs Tiller (the helm server side component) onto your
Kubernetes Cluster and sets up local configuration in $HELM_HOME (default: ~/.helm/)
`

var (
	tillerImg  string
	clientOnly bool
)

func init() {
	initCmd.Flags().StringVarP(&tillerImg, "tiller-image", "i", "", "override tiller image")
	initCmd.Flags().BoolVarP(&clientOnly, "client-only", "c", false, "If set does not install tiller")
	RootCommand.AddCommand(initCmd)
}

var initCmd = &cobra.Command{
	Use:   "init",
	Short: "Initialize Helm on both client and server.",
	Long:  installDesc,
	RunE:  runInit,
}

// runInit initializes local config and installs tiller to Kubernetes Cluster
func runInit(cmd *cobra.Command, args []string) error {
	if len(args) != 0 {
		return errors.New("This command does not accept arguments. \n")
	}

	if err := ensureHome(); err != nil {
		return err
	}

	if !clientOnly {
		if err := installTiller(); err != nil {
			return err
		}
	} else {
		fmt.Println("Not installing tiller due to 'client-only' flag having been set")
	}

	fmt.Println("Happy Helming!")
	return nil
}

func installTiller() error {
	i := client.NewInstaller()
	i.Tiller["Image"] = tillerImg
	err := i.Install()

	if err != nil {
		return fmt.Errorf("error installing: %s", err)
	}
	fmt.Println("\nTiller (the helm server side component) has been installed into your Kubernetes Cluster.")

	return nil
}

// ensureHome checks to see if $HELM_HOME exists
//
// If $HELM_HOME does not exist, this function will create it.
func ensureHome() error {
	configDirectories := []string{homePath(), cacheDirectory(), localRepoDirectory()}

	for _, p := range configDirectories {
		if fi, err := os.Stat(p); err != nil {
			fmt.Printf("Creating %s \n", p)
			if err := os.MkdirAll(p, 0755); err != nil {
				return fmt.Errorf("Could not create %s: %s", p, err)
			}
		} else if !fi.IsDir() {
			return fmt.Errorf("%s must be a directory", p)
		}
	}

	repoFile := repositoriesFile()
	if fi, err := os.Stat(repoFile); err != nil {
		fmt.Printf("Creating %s \n", repoFile)
		if _, err := os.Create(repoFile); err != nil {
			return err
		}
		if err := insertRepoLine("local", "http://localhost:8879/charts"); err != nil {
			return err
		}
	} else if fi.IsDir() {
		return fmt.Errorf("%s must be a file, not a directory", repoFile)
	}

	localRepoCacheFile := localRepoDirectory(localRepoCacheFilePath)
	if fi, err := os.Stat(localRepoCacheFile); err != nil {
		fmt.Printf("Creating %s \n", localRepoCacheFile)
		_, err := os.Create(localRepoCacheFile)
		if err != nil {
			return err
		}

		//TODO: take this out and replace with helm update functionality
		os.Symlink(localRepoCacheFile, cacheDirectory("local-cache.yaml"))
	} else if fi.IsDir() {
		return fmt.Errorf("%s must be a file, not a directory", localRepoCacheFile)
	}

	fmt.Printf("$HELM_HOME has been configured at %s.", helmHome)
	return nil
}
<commit_msg>Add missing newline to HELM_HOME info output string<commit_after>package main

import (
	"errors"
	"fmt"
	"os"

	"github.com/kubernetes/helm/pkg/client"
	"github.com/spf13/cobra"
)

const initDesc = `
This command installs Tiller (the helm server side component) onto your
Kubernetes Cluster and sets up local configuration in $HELM_HOME (default: ~/.helm/)
`

var (
	tillerImg  string
	clientOnly bool
)

func init() {
	initCmd.Flags().StringVarP(&tillerImg, "tiller-image", "i", "", "override tiller image")
	initCmd.Flags().BoolVarP(&clientOnly, "client-only", "c", false, "If set does not install tiller")
	RootCommand.AddCommand(initCmd)
}

var initCmd = &cobra.Command{
	Use:   "init",
	Short: "Initialize Helm on both client and server.",
	Long:  installDesc,
	RunE:  runInit,
}

// runInit initializes local config and installs tiller to Kubernetes Cluster
func runInit(cmd *cobra.Command, args []string) error {
	if len(args) != 0 {
		return errors.New("This command does not accept arguments. \n")
	}

	if err := ensureHome(); err != nil {
		return err
	}

	if !clientOnly {
		if err := installTiller(); err != nil {
			return err
		}
	} else {
		fmt.Println("Not installing tiller due to 'client-only' flag having been set")
	}

	fmt.Println("Happy Helming!")
	return nil
}

func installTiller() error {
	i := client.NewInstaller()
	i.Tiller["Image"] = tillerImg
	err := i.Install()

	if err != nil {
		return fmt.Errorf("error installing: %s", err)
	}
	fmt.Println("\nTiller (the helm server side component) has been installed into your Kubernetes Cluster.")

	return nil
}

// ensureHome checks to see if $HELM_HOME exists
//
// If $HELM_HOME does not exist, this function will create it.
func ensureHome() error {
	configDirectories := []string{homePath(), cacheDirectory(), localRepoDirectory()}

	for _, p := range configDirectories {
		if fi, err := os.Stat(p); err != nil {
			fmt.Printf("Creating %s \n", p)
			if err := os.MkdirAll(p, 0755); err != nil {
				return fmt.Errorf("Could not create %s: %s", p, err)
			}
		} else if !fi.IsDir() {
			return fmt.Errorf("%s must be a directory", p)
		}
	}

	repoFile := repositoriesFile()
	if fi, err := os.Stat(repoFile); err != nil {
		fmt.Printf("Creating %s \n", repoFile)
		if _, err := os.Create(repoFile); err != nil {
			return err
		}
		if err := insertRepoLine("local", "http://localhost:8879/charts"); err != nil {
			return err
		}
	} else if fi.IsDir() {
		return fmt.Errorf("%s must be a file, not a directory", repoFile)
	}

	localRepoCacheFile := localRepoDirectory(localRepoCacheFilePath)
	if fi, err := os.Stat(localRepoCacheFile); err != nil {
		fmt.Printf("Creating %s \n", localRepoCacheFile)
		_, err := os.Create(localRepoCacheFile)
		if err != nil {
			return err
		}

		//TODO: take this out and replace with helm update functionality
		os.Symlink(localRepoCacheFile, cacheDirectory("local-cache.yaml"))
	} else if fi.IsDir() {
		return fmt.Errorf("%s must be a file, not a directory", localRepoCacheFile)
	}

	fmt.Printf("$HELM_HOME has been configured at %s.\n", helmHome)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"path/filepath"

	"github.com/mattn/go-gtk/gdk"
	"github.com/mattn/go-gtk/gtk"
)

const (
	cellSize  = 100
	lineWidth = 4
	largeFont = "DejaVu Sans 28"
	smallFont = "DejaVu Sans 12"
)

var (
	table     *gtk.Table
	cellLabel [][]*gtk.Label
	noteLabel [][]*gtk.Label

	white = gdk.NewColor("white")
)

func initUI() {
	gtk.Init(nil)
	size := puzzle.Size()
	table = gtk.NewTable(uint(size), uint(size), true)
	cellLabel = make([][]*gtk.Label, size)
	noteLabel = make([][]*gtk.Label, size)
	window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
	window.SetTitle(fmt.Sprintf("KenKen %s", filepath.Base(path)))
	window.Connect("destroy", gtk.MainQuit)
	window.SetResizable(false)
	for y := 0; y < size; y++ {
		cellLabel[y] = make([]*gtk.Label, size)
		noteLabel[y] = make([]*gtk.Label, size)
		for x := 0; x < size; x++ {
			attachCell(x, y)
		}
	}
	window.Add(table)
	window.Connect("configure-event", drawCages)
	window.Connect("expose-event", drawCages)
	window.ShowAll()
}

func runUI() {
	gtk.Main()
}

func attachCell(x, y int) {
	vbox := gtk.NewVBox(false, 0)
	vbox.SetSizeRequest(cellSize, cellSize)

	// Clue, if any
	label := gtk.NewLabel(clueString(x, y))
	label.ModifyFontEasy(smallFont)
	align := gtk.NewAlignment(0, 0, 0, 0)
	align.Add(label)
	vbox.PackStart(align, false, false, 0)

	// Cell contents
	str := ""
	if isConstant(x, y) {
		str = fmt.Sprintf("%d", puzzle.Answer[y][x])
	}
	label = gtk.NewLabel(str)
	cellLabel[y][x] = label
	label.ModifyFontEasy(largeFont)
	label.ModifyFG(gtk.STATE_INSENSITIVE, white)
	vbox.Add(label)

	// Notes
	label = gtk.NewLabel("")
	noteLabel[y][x] = label
	label.ModifyFontEasy(smallFont)
	align = gtk.NewAlignment(1, 0, 0, 0)
	align.Add(label)
	vbox.PackEnd(align, false, false, 0)

	button := gtk.NewButton()
	button.SetRelief(gtk.RELIEF_NONE)
	if isConstant(x, y) {
		button.SetSensitive(false)
	}
	button.Add(vbox)
	button.Connect("enter-notify-event", func() { button.GrabFocus() })
	button.Connect("expose-event", drawCages)
	button.Connect("key-press-event", keypress(x, y))
	button.Connect("button-press-event", buttonpress(x, y))

	table.AttachDefaults(button, uint(x), uint(x+1), uint(y), uint(y+1))
}

func setCellLabel(x, y, n int) {
	cellLabel[y][x].SetText(fmt.Sprintf("%d", n))
}

func clearCellLabel(x, y int) {
	cellLabel[y][x].SetText("")
}

func setNoteLabel(x, y int, digits string) {
	noteLabel[y][x].SetText(digits)
}

func drawCages() {
	a := table.GetAllocation()
	size := puzzle.Size()
	w := a.Width / size
	h := a.Height / size
	d := table.GetWindow().GetDrawable()
	gc := gdk.NewGC(d)
	gc.SetRgbFgColor(white)

	t := lineWidth

	d.DrawRectangle(gc, true, 0, 0, t, a.Height)
	d.DrawRectangle(gc, true, 0, 0, a.Width, t)
	d.DrawRectangle(gc, true, 0, a.Height-t, a.Width, t)
	d.DrawRectangle(gc, true, a.Width-t, 0, t, a.Height)

	for j := 0; j < size; j++ {
		y := j*h - t/2
		for i := 0; i < size; i++ {
			x := i*w - t/2
			if i > 0 && puzzle.Vertical[j][i-1] {
				d.DrawRectangle(gc, true, x, y, t, h+t/2)
			}
			if j > 0 && puzzle.Horizontal[i][j-1] {
				d.DrawRectangle(gc, true, x, y, w+t/2, t)
			}
		}
	}
}

var winning = false

func winnerWinner() {
	if winning {
		return
	}
	winning = true
	dialog := gtk.NewMessageDialogWithMarkup(
		table.GetTopLevelAsWindow(), gtk.DIALOG_MODAL,
		gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Correct!",
	)
	dialog.Response(gtk.MainQuit)
	dialog.Run()
}

var losing = false

func tryAgain() {
	if losing {
		return
	}
	losing = true
	dialog := gtk.NewMessageDialogWithMarkup(
		table.GetTopLevelAsWindow(), gtk.DIALOG_MODAL,
		gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, "Try again?",
	)
	if dialog.Run() == gtk.RESPONSE_YES {
		restartGame()
	}
	dialog.Destroy()
	losing = false
}
<commit_msg>Create window at the center of the screen<commit_after>package main

import (
	"fmt"
	"path/filepath"

	"github.com/mattn/go-gtk/gdk"
	"github.com/mattn/go-gtk/gtk"
)

const (
	cellSize  = 100
	lineWidth = 4
	largeFont = "DejaVu Sans 28"
	smallFont = "DejaVu Sans 12"
)

var (
	table     *gtk.Table
	cellLabel [][]*gtk.Label
	noteLabel [][]*gtk.Label

	white = gdk.NewColor("white")
)

func initUI() {
	gtk.Init(nil)
	size := puzzle.Size()
	table = gtk.NewTable(uint(size), uint(size), true)
	cellLabel = make([][]*gtk.Label, size)
	noteLabel = make([][]*gtk.Label, size)
	window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
	window.SetTitle(fmt.Sprintf("KenKen %s", filepath.Base(path)))
	window.SetPosition(gtk.WIN_POS_CENTER_ALWAYS)
	window.SetResizable(false)
	window.Connect("destroy", gtk.MainQuit)
	for y := 0; y < size; y++ {
		cellLabel[y] = make([]*gtk.Label, size)
		noteLabel[y] = make([]*gtk.Label, size)
		for x := 0; x < size; x++ {
			attachCell(x, y)
		}
	}
	window.Add(table)
	window.Connect("configure-event", drawCages)
	window.Connect("expose-event", drawCages)
	window.ShowAll()
}

func runUI() {
	gtk.Main()
}

func attachCell(x, y int) {
	vbox := gtk.NewVBox(false, 0)
	vbox.SetSizeRequest(cellSize, cellSize)

	// Clue, if any
	label := gtk.NewLabel(clueString(x, y))
	label.ModifyFontEasy(smallFont)
	align := gtk.NewAlignment(0, 0, 0, 0)
	align.Add(label)
	vbox.PackStart(align, false, false, 0)

	// Cell contents
	str := ""
	if isConstant(x, y) {
		str = fmt.Sprintf("%d", puzzle.Answer[y][x])
	}
	label = gtk.NewLabel(str)
	cellLabel[y][x] = label
	label.ModifyFontEasy(largeFont)
	label.ModifyFG(gtk.STATE_INSENSITIVE, white)
	vbox.Add(label)

	// Notes
	label = gtk.NewLabel("")
	noteLabel[y][x] = label
	label.ModifyFontEasy(smallFont)
	align = gtk.NewAlignment(1, 0, 0, 0)
	align.Add(label)
	vbox.PackEnd(align, false, false, 0)

	button := gtk.NewButton()
	button.SetRelief(gtk.RELIEF_NONE)
	if isConstant(x, y) {
		button.SetSensitive(false)
	}
	button.Add(vbox)
	button.Connect("enter-notify-event", button.GrabFocus)
	button.Connect("expose-event", drawCages)
	button.Connect("key-press-event", keypress(x, y))
	button.Connect("button-press-event", buttonpress(x, y))

	table.AttachDefaults(button, uint(x), uint(x+1), uint(y), uint(y+1))
}

func setCellLabel(x, y, n int) {
	cellLabel[y][x].SetText(fmt.Sprintf("%d", n))
}

func clearCellLabel(x, y int) {
	cellLabel[y][x].SetText("")
}

func setNoteLabel(x, y int, digits string) {
	noteLabel[y][x].SetText(digits)
}

func drawCages() {
	a := table.GetAllocation()
	size := puzzle.Size()
	w := a.Width / size
	h := a.Height / size
	d := table.GetWindow().GetDrawable()
	gc := gdk.NewGC(d)
	gc.SetRgbFgColor(white)

	t := lineWidth

	d.DrawRectangle(gc, true, 0, 0, t, a.Height)
	d.DrawRectangle(gc, true, 0, 0, a.Width, t)
	d.DrawRectangle(gc, true, 0, a.Height-t, a.Width, t)
	d.DrawRectangle(gc, true, a.Width-t, 0, t, a.Height)

	for j := 0; j < size; j++ {
		y := j*h - t/2
		for i := 0; i < size; i++ {
			x := i*w - t/2
			if i > 0 && puzzle.Vertical[j][i-1] {
				d.DrawRectangle(gc, true, x, y, t, h+t/2)
			}
			if j > 0 && puzzle.Horizontal[i][j-1] {
				d.DrawRectangle(gc, true, x, y, w+t/2, t)
			}
		}
	}
}

var winning = false

func winnerWinner() {
	if winning {
		return
	}
	winning = true
	dialog := gtk.NewMessageDialogWithMarkup(
		table.GetTopLevelAsWindow(), gtk.DIALOG_MODAL,
		gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Correct!",
	)
	dialog.Response(gtk.MainQuit)
	dialog.Run()
}

var losing = false

func tryAgain() {
	if losing {
		return
	}
	losing = true
	dialog := gtk.NewMessageDialogWithMarkup(
		table.GetTopLevelAsWindow(), gtk.DIALOG_MODAL,
		gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, "Try again?",
	)
	if dialog.Run() == gtk.RESPONSE_YES {
		restartGame()
	}
	dialog.Destroy()
	losing = false
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/hoffie/larasync/api"
	"github.com/hoffie/larasync/repository"
)

// pushAction implements "lara push"
func (d *Dispatcher) pushAction() int {
	if len(d.flags.Args()) != 0 {
		fmt.Fprint(d.stderr, "Error: this command takes no arguments\n")
		return 1
	}
	root, err := d.getRootFromWd()
	if err != nil {
		return 1
	}
	r := repository.New(root)

	client, err := clientFor(r)
	if err != nil {
		fmt.Fprintf(d.stderr, "Error: %s\n",
			err)
	}

	//FIXME:
	nibs, err := r.GetAllNibs()
	if err != nil {
		fmt.Fprintf(d.stderr, "Error: unable to get NIB list (%s)\n", err)
		return 1
	}
	for nib := range nibs {
		objectIDs := nib.AllObjectIDs()
		for _, objectID := range objectIDs {
			object, err := r.GetObjectData(objectID)
			if err != nil {
				fmt.Fprintf(d.stderr, "Error: unable to load object %s (%s)\n",
					objectID, err)
				return 1
			}
			defer object.Close()
			//FIXME We currently upload all objects, even multiple times
			// in some cases and even although they may already exist on
			// the server. This is not as well performing as it might be.
			err = client.PutObject(objectID, object)
			if err != nil {
				fmt.Fprintf(d.stderr, "Error: uploading object %s failed (%s)\n",
					objectID, err)
				return 1
			}
		}
		nibReader, err := r.GetNIBReader(nib.ID)
		if err != nil {
			fmt.Fprintf(d.stderr, "Error: unable to load nib %s (%s)\n",
				nib.ID, err)
			return 1
		}
		//FIXME We currently assume that the server will prevent us
		// from overwriting data we are not supposed to be overwriting.
		// This will be implemented as part of #105
		err = client.PutNIB(nib.ID, nibReader)
		if err != nil {
			fmt.Fprintf(d.stderr, "Error: uploading nib %s failed (%s)\n",
				nib.ID, err)
			return 1
		}
	}
	return 0
}
<commit_msg>cmd: removed /api import in the push.go file.<commit_after>package main

import (
	"fmt"

	"github.com/hoffie/larasync/repository"
)

// pushAction implements "lara push"
func (d *Dispatcher) pushAction() int {
	if len(d.flags.Args()) != 0 {
		fmt.Fprint(d.stderr, "Error: this command takes no arguments\n")
		return 1
	}
	root, err := d.getRootFromWd()
	if err != nil {
		return 1
	}
	r := repository.New(root)

	client, err := clientFor(r)
	if err != nil {
		fmt.Fprintf(d.stderr, "Error: %s\n",
			err)
	}

	//FIXME:
	nibs, err := r.GetAllNibs()
	if err != nil {
		fmt.Fprintf(d.stderr, "Error: unable to get NIB list (%s)\n", err)
		return 1
	}
	for nib := range nibs {
		objectIDs := nib.AllObjectIDs()
		for _, objectID := range objectIDs {
			object, err := r.GetObjectData(objectID)
			if err != nil {
				fmt.Fprintf(d.stderr, "Error: unable to load object %s (%s)\n",
					objectID, err)
				return 1
			}
			defer object.Close()
			//FIXME We currently upload all objects, even multiple times
			// in some cases and even although they may already exist on
			// the server. This is not as well performing as it might be.
			err = client.PutObject(objectID, object)
			if err != nil {
				fmt.Fprintf(d.stderr, "Error: uploading object %s failed (%s)\n",
					objectID, err)
				return 1
			}
		}
		nibReader, err := r.GetNIBReader(nib.ID)
		if err != nil {
			fmt.Fprintf(d.stderr, "Error: unable to load nib %s (%s)\n",
				nib.ID, err)
			return 1
		}
		//FIXME We currently assume that the server will prevent us
		// from overwriting data we are not supposed to be overwriting.
		// This will be implemented as part of #105
		err = client.PutNIB(nib.ID, nibReader)
		if err != nil {
			fmt.Fprintf(d.stderr, "Error: uploading nib %s failed (%s)\n",
				nib.ID, err)
			return 1
		}
	}
	return 0
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"testing"

	"github.com/bouk/monkey"
	"github.com/evandroflores/claimr/model"
	"github.com/shomali11/slacker"
)

func TestTryToListDirect(t *testing.T) {
	mockResponse, patchReply := createMockReply(t, "this look like a direct message. Containers are related to a channels")
	patchGetEvent := createMockEvent(t, "team", "DIRECT", "user")

	list(new(slacker.Request), mockResponse)

	patchReply.Unpatch()
	patchGetEvent.Unpatch()
}

func TestListError(t *testing.T) {

	guard := monkey.Patch(model.GetContainers,
		func(Team string, Channel string) ([]model.Container, error) {
			return []model.Container{}, fmt.Errorf("simulated error")
		})

	teamName := "TestTeamList"
	channelName := "TestChannel"
	userName := "user"

	mockResponse, patchReply := createMockReply(t, "Fail to list containers.")
	patchGetEvent := createMockEvent(t, teamName, channelName, userName)
	mockRequest, patchParam := createMockRequest(t, nil)

	list(mockRequest, mockResponse)

	patchReply.Unpatch()
	patchGetEvent.Unpatch()
	patchParam.Unpatch()
	guard.Unpatch()
}

func TestListNoContainers(t *testing.T) {

	teamName := "TestTeamList"
	channelName := "TestChannel"
	userName := "user"

	mockResponse, patchReply := createMockReply(t, "No containers to list.")
	patchGetEvent := createMockEvent(t, teamName, channelName, userName)
	mockRequest, patchParam := createMockRequest(t, nil)

	list(mockRequest, mockResponse)

	patchReply.Unpatch()
	patchGetEvent.Unpatch()
	patchParam.Unpatch()
}
<commit_msg>TestListAvailableContainers<commit_after>package cmd

import (
	"fmt"
	"strings"
	"testing"

	"github.com/bouk/monkey"
	"github.com/evandroflores/claimr/model"
	"github.com/shomali11/slacker"
	"github.com/stretchr/testify/assert"
)

func TestTryToListDirect(t *testing.T) {
	mockResponse, patchReply := createMockReply(t, "this look like a direct message. Containers are related to a channels")
	patchGetEvent := createMockEvent(t, "team", "DIRECT", "user")

	list(new(slacker.Request), mockResponse)

	patchReply.Unpatch()
	patchGetEvent.Unpatch()
}

func TestListError(t *testing.T) {

	guard := monkey.Patch(model.GetContainers,
		func(Team string, Channel string) ([]model.Container, error) {
			return []model.Container{}, fmt.Errorf("simulated error")
		})

	teamName := "TestTeamList"
	channelName := "TestChannel"
	userName := "user"

	mockResponse, patchReply := createMockReply(t, "Fail to list containers.")
	patchGetEvent := createMockEvent(t, teamName, channelName, userName)
	mockRequest, patchParam := createMockRequest(t, nil)

	list(mockRequest, mockResponse)

	patchReply.Unpatch()
	patchGetEvent.Unpatch()
	patchParam.Unpatch()
	guard.Unpatch()
}

func TestListAvailableContainers(t *testing.T) {
	teamName := "TestTeamList"
	channelName := "TestChannel"
	userName := "user"

	expected := []string{"Here is a list of containers for this channel:"}

	for i := 0; i < 5; i++ {
		containerName := fmt.Sprintf("container_%d", i)
		container := model.Container{TeamID: teamName, ChannelID: channelName, Name: containerName}
		err := container.Add()
		defer container.Delete()
		assert.NoError(t, err)

		line := fmt.Sprintf("`%s`\t%s %s", container.Name, "_available_", "")
		expected = append(expected, line)
	}

	mockResponse, patchReply := createMockReply(t, strings.Join(expected, "\n"))
	patchGetEvent := createMockEvent(t, teamName, channelName, userName)
	mockRequest, patchParam := createMockRequest(t, nil)

	list(mockRequest, mockResponse)

	patchReply.Unpatch()
	patchGetEvent.Unpatch()
	patchParam.Unpatch()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"os/exec"
	"strings"
)

// Maze drawing sequences.
var (
	SpaceRune  = " "
	WallRune   = "*"
	StartRune  = "S"
	FinishRune = "F"
	StepRune   = "·"
	PathRune   = "•"

	StepColor = Tput("setaf", 61)  // Cursor color StaleBlue3
	PathColor = Tput("setaf", 128) // Cursor color DarkViolet
	Reset     = Tput("sgr0")       // Cursor highlight reset
)

// Maze as printed to the terminal or file.
var TerminalTmpl = `
{{define "Terminal"}}
 {{.Title}}

{{range .Maze}}  {{range .}}{{colorize .}}{{end}}{{println}}{{end}}
 {{colorize "* - wall  S - start  ··· - explored  ••• - shortest path"}}
 Run with “-help” for available options.
{{end}}

{{define "File"}}{{.Title}}

{{range .Maze}}{{range .}}{{print .}}{{end}}{{println}}{{end}}
{{print "* - wall  S - start  ··· - explored  ••• - shortest path"}}
{{end}}`

var (
	helpers = map[string]interface{}{
		"colorize": func(in string) (out string) {
			for _, s := range strings.Split(in, "") {
				switch s {
				case StartRune, FinishRune, PathRune:
					out += PathColor + s + Reset
				case StepRune:
					out += StepColor + s + Reset
				default:
					out += s
				}
			}
			return out
		},
	}

	estimateFunc = genEuclidEstimate(*estimFlag)
)

// genManhattanEstimate generates a Manhattan distance Estimate() function
// with custom multiplier.
func genManhattanEstimate(multiplier float64) func(interface{}, interface{}) float64 {
	return func(finish, neighbor interface{}) float64 {
		var (
			aI = float64(neighbor.(Location).i)
			bI = float64(finish.(Location).i)
			aJ = float64(neighbor.(Location).j)
			bJ = float64(finish.(Location).j)
		)
		return math.Abs(aI-bI) + math.Abs(aJ-bJ)*multiplier
	}
}

// genEuclidEstimate generates a Euclidean distance Estimate() function with
// custom multiplier.
func genEuclidEstimate(multiplier float64) func(interface{}, interface{}) float64 {
	return func(finish, neighbor interface{}) float64 {
		var (
			aI = float64(neighbor.(Location).i)
			bI = float64(finish.(Location).i)
			aJ = float64(neighbor.(Location).j)
			bJ = float64(finish.(Location).j)
		)
		return math.Sqrt(math.Pow(aI-bI, 2) + math.Pow(aJ-bJ, 2)*multiplier)
	}
}

type Location struct {
	i, j int
}

type Maze struct {
	maze                [][]string
	start, finish, curr Location
}

func (m Maze) Start() interface{}                { return m.start }
func (m Maze) Finish() bool                      { return m.curr == m.finish }
func (m *Maze) Move(t interface{})               { m.curr = t.(Location) }
func (m Maze) Cost(neighbor interface{}) float64 { return *costFlag }

func (m Maze) Estimate(neighbor interface{}) float64 {
	return estimateFunc(m.finish, neighbor)
}

func (m Maze) Successors() []interface{} {
	successors := []interface{}{}

	checkLocation := func(i, j int) {
		switch m.maze[i][j] {
		case SpaceRune, FinishRune:
			successors = append(successors, Location{i, j})
		}
	}

	i, j := m.curr.i, m.curr.j

	if i > 0 {
		checkLocation(i-1, j)
	}

	if i < len(m.maze)-1 {
		checkLocation(i+1, j)
	}

	if j > 0 {
		checkLocation(i, j-1)
	}

	if j < len(m.maze[i])-1 {
		checkLocation(i, j+1)
	}

	return successors
}

// Tput controls the terminal using tput(1). Command is a capability name and
// params are either strings or integers. Does nothing if a capability
// or tput(1) is not available. See terminfo(5) and infocmp(1) for a list of
// capability names.
func Tput(command string, params ...interface{}) string {
	args := []string{command}

	for _, param := range params {
		switch param.(type) {
		case string:
			args = append(args, param.(string))
		case int:
			args = append(args, fmt.Sprintf("%d", param))
		}
	}

	out, err := exec.Command("tput", args...).Output()
	if err != nil {
		return ""
	}
	return string(out)
}

// New initialize a maze with given slice of strings.
func New(m []string) *Maze {
	maze := make([][]string, len(m))

	var start, finish Location

	for i, line := range m {
		maze[i] = []string{}

		for j, rune := range strings.Split(line, "") {
			maze[i] = append(maze[i], rune)
			switch rune {
			case StartRune:
				start = Location{i, j}
			case FinishRune:
				finish = Location{i, j}
			}
		}
	}

	return &Maze{
		maze:   maze,
		start:  start,
		finish: finish,
		curr:   start,
	}
}

// DrawMaze applies path and explored state lists to a maze
// and returns it as a matrix of strings.
func (m *Maze) DrawMaze(path, steps []interface{}) [][]string {
	states := map[Location]string{}

	for _, state := range steps {
		states[state.(Location)] = StepRune
	}

	for _, state := range path {
		states[state.(Location)] = PathRune
	}

	maze := make([][]string, len(m.maze))
	for i := 0; i < len(m.maze); i++ {
		maze[i] = make([]string, len(m.maze[i]))
		for j := 0; j < len(maze[i]); j++ {
			if state, ok := states[Location{i, j}]; ok && m.maze[i][j] == SpaceRune {
				maze[i][j] = fmt.Sprint(state)
			} else {
				maze[i][j] = m.maze[i][j]
			}
		}
	}

	return maze
}
<commit_msg>Less checks checkLocation<commit_after>package main

import (
	"fmt"
	"math"
	"os/exec"
	"strings"
)

// Maze drawing sequences.
var (
	SpaceRune  = " "
	WallRune   = "*"
	StartRune  = "S"
	FinishRune = "F"
	StepRune   = "·"
	PathRune   = "•"

	StepColor = Tput("setaf", 61)  // Cursor color StaleBlue3
	PathColor = Tput("setaf", 128) // Cursor color DarkViolet
	Reset     = Tput("sgr0")       // Cursor highlight reset
)

// Maze as printed to the terminal or file.
var TerminalTmpl = `
{{define "Terminal"}}
 {{.Title}}

{{range .Maze}}  {{range .}}{{colorize .}}{{end}}{{println}}{{end}}
 {{colorize "* - wall  S - start  ··· - explored  ••• - shortest path"}}
 Run with “-help” for available options.
{{end}}

{{define "File"}}{{.Title}}

{{range .Maze}}{{range .}}{{print .}}{{end}}{{println}}{{end}}
{{print "* - wall  S - start  ··· - explored  ••• - shortest path"}}
{{end}}`

var (
	helpers = map[string]interface{}{
		"colorize": func(in string) (out string) {
			for _, s := range strings.Split(in, "") {
				switch s {
				case StartRune, FinishRune, PathRune:
					out += PathColor + s + Reset
				case StepRune:
					out += StepColor + s + Reset
				default:
					out += s
				}
			}
			return out
		},
	}

	estimateFunc = genEuclidEstimate(*estimFlag)
)

// genManhattanEstimate generates a Manhattan distance Estimate() function
// with custom multiplier.
func genManhattanEstimate(multiplier float64) func(interface{}, interface{}) float64 {
	return func(finish, neighbor interface{}) float64 {
		var (
			aI = float64(neighbor.(Location).i)
			bI = float64(finish.(Location).i)
			aJ = float64(neighbor.(Location).j)
			bJ = float64(finish.(Location).j)
		)
		return math.Abs(aI-bI) + math.Abs(aJ-bJ)*multiplier
	}
}

// genEuclidEstimate generates a Euclidean distance Estimate() function with
// custom multiplier.
func genEuclidEstimate(multiplier float64) func(interface{}, interface{}) float64 {
	return func(finish, neighbor interface{}) float64 {
		var (
			aI = float64(neighbor.(Location).i)
			bI = float64(finish.(Location).i)
			aJ = float64(neighbor.(Location).j)
			bJ = float64(finish.(Location).j)
		)
		return math.Sqrt(math.Pow(aI-bI, 2) + math.Pow(aJ-bJ, 2)*multiplier)
	}
}

type Location struct {
	i, j int
}

type Maze struct {
	maze                [][]string
	start, finish, curr Location
}

func (m Maze) Start() interface{}                { return m.start }
func (m Maze) Finish() bool                      { return m.curr == m.finish }
func (m *Maze) Move(t interface{})               { m.curr = t.(Location) }
func (m Maze) Cost(neighbor interface{}) float64 { return *costFlag }

func (m Maze) Estimate(neighbor interface{}) float64 {
	return estimateFunc(m.finish, neighbor)
}

func (m Maze) Successors() []interface{} {
	successors := []interface{}{}

	checkLocation := func(i, j int) {
		// The matrix is not necessarily rectangular.
		if i >= len(m.maze) || j >= len(m.maze[i]) {
			return
		}

		switch m.maze[i][j] {
		case SpaceRune, FinishRune:
			successors = append(successors, Location{i, j})
		}
	}

	i, j := m.curr.i, m.curr.j

	// North.
	checkLocation(i-1, j)
	// South.
	checkLocation(i+1, j)
	// West.
	checkLocation(i, j-1)
	// East.
	checkLocation(i, j+1)

	return successors
}

// Tput controls the terminal using tput(1). Command is a capability name and
// params are either strings or integers. Does nothing if a capability
// or tput(1) is not available. See terminfo(5) and infocmp(1) for a list of
// capability names.
func Tput(command string, params ...interface{}) string {
	args := []string{command}

	for _, param := range params {
		switch param.(type) {
		case string:
			args = append(args, param.(string))
		case int:
			args = append(args, fmt.Sprintf("%d", param))
		}
	}

	out, err := exec.Command("tput", args...).Output()
	if err != nil {
		return ""
	}
	return string(out)
}

// New initialize a maze with given slice of strings.
func New(m []string) *Maze {
	maze := make([][]string, len(m))

	var start, finish Location

	for i, line := range m {
		maze[i] = []string{}

		for j, rune := range strings.Split(line, "") {
			maze[i] = append(maze[i], rune)
			switch rune {
			case StartRune:
				start = Location{i, j}
			case FinishRune:
				finish = Location{i, j}
			}
		}
	}

	return &Maze{
		maze:   maze,
		start:  start,
		finish: finish,
		curr:   start,
	}
}

// DrawMaze applies path and explored state lists to a maze
// and returns it as a matrix of strings.
func (m *Maze) DrawMaze(path, steps []interface{}) [][]string {
	states := map[Location]string{}

	for _, state := range steps {
		states[state.(Location)] = StepRune
	}

	for _, state := range path {
		states[state.(Location)] = PathRune
	}

	maze := make([][]string, len(m.maze))
	for i := 0; i < len(m.maze); i++ {
		maze[i] = make([]string, len(m.maze[i]))
		for j := 0; j < len(maze[i]); j++ {
			if state, ok := states[Location{i, j}]; ok && m.maze[i][j] == SpaceRune {
				maze[i][j] = fmt.Sprint(state)
			} else {
				maze[i][j] = m.maze[i][j]
			}
		}
	}

	return maze
}
<|endoftext|>