<commit_before>package k8s

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"fmt"
	"github.com/containous/traefik/log"
	"github.com/parnurzeal/gorequest"
	"net/http"
	"net/url"
	"strings"
)

const (
	// APIEndpoint defines the base path for kubernetes API resources.
	APIEndpoint        = "/api/v1"
	extentionsEndpoint = "/apis/extensions/v1beta1"
	defaultIngress     = "/ingresses"
	namespaces         = "/namespaces/"
)

// Client is a client for the Kubernetes master.
type Client interface {
	GetIngresses(labelSelector string, predicate func(Ingress) bool) ([]Ingress, error)
	GetService(name, namespace string) (Service, error)
	GetEndpoints(name, namespace string) (Endpoints, error)
	WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error)
}

type clientImpl struct {
	endpointURL string
	tls         *tls.Config
	token       string
	caCert      []byte
}

// NewClient returns a new Kubernetes client.
// The provided host is an url (scheme://hostname[:port]) of a
// Kubernetes master without any path.
// The provided client is an authorized http.Client used to perform requests to the Kubernetes API master.
func NewClient(baseURL string, caCert []byte, token string) (Client, error) {
	validURL, err := url.Parse(baseURL)
	if err != nil {
		return nil, fmt.Errorf("failed to parse URL %q: %v", baseURL, err)
	}
	return &clientImpl{
		endpointURL: strings.TrimSuffix(validURL.String(), "/"),
		token:       token,
		caCert:      caCert,
	}, nil
}

func makeQueryString(baseParams map[string]string, labelSelector string) (string, error) {
	if labelSelector != "" {
		baseParams["labelSelector"] = labelSelector
	}
	queryData, err := json.Marshal(baseParams)
	if err != nil {
		return "", err
	}
	return string(queryData), nil
}

// GetIngresses returns all ingresses in the cluster
func (c *clientImpl) GetIngresses(labelSelector string, predicate func(Ingress) bool) ([]Ingress, error) {
	getURL := c.endpointURL + extentionsEndpoint + defaultIngress
	queryParams := map[string]string{}
	queryData, err := makeQueryString(queryParams, labelSelector)
	if err != nil {
		return nil, fmt.Errorf("Had problems constructing query string %s : %v", queryParams, err)
	}
	body, err := c.do(c.request(getURL, queryData))
	if err != nil {
		return nil, fmt.Errorf("failed to create ingresses request: GET %q : %v", getURL, err)
	}

	var ingressList IngressList
	if err := json.Unmarshal(body, &ingressList); err != nil {
		return nil, fmt.Errorf("failed to decode list of ingress resources: %v", err)
	}
	ingresses := ingressList.Items[:0]
	for _, ingress := range ingressList.Items {
		if predicate(ingress) {
			ingresses = append(ingresses, ingress)
		}
	}
	return ingresses, nil
}

// WatchIngresses returns all ingresses in the cluster
func (c *clientImpl) WatchIngresses(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
	getURL := c.endpointURL + extentionsEndpoint + defaultIngress
	return c.watch(getURL, labelSelector, stopCh)
}

// GetService returns the named service from the named namespace
func (c *clientImpl) GetService(name, namespace string) (Service, error) {
	getURL := c.endpointURL + APIEndpoint + namespaces + namespace + "/services/" + name

	body, err := c.do(c.request(getURL, ""))
	if err != nil {
		return Service{}, fmt.Errorf("failed to create services request: GET %q : %v", getURL, err)
	}

	var service Service
	if err := json.Unmarshal(body, &service); err != nil {
		return Service{}, fmt.Errorf("failed to decode service resource: %v", err)
	}
	return service, nil
}

// WatchServices returns all services in the cluster
func (c *clientImpl) WatchServices(stopCh <-chan bool) (chan interface{}, chan error, error) {
	getURL := c.endpointURL + APIEndpoint + "/services"
	return c.watch(getURL, "", stopCh)
}

// GetEndpoints returns the named Endpoints
// Endpoints have the same name as the coresponding service
func (c *clientImpl) GetEndpoints(name, namespace string) (Endpoints, error) {
	getURL := c.endpointURL + APIEndpoint + namespaces + namespace + "/endpoints/" + name

	body, err := c.do(c.request(getURL, ""))
	if err != nil {
		return Endpoints{}, fmt.Errorf("failed to create endpoints request: GET %q : %v", getURL, err)
	}

	var endpoints Endpoints
	if err := json.Unmarshal(body, &endpoints); err != nil {
		return Endpoints{}, fmt.Errorf("failed to decode endpoints resources: %v", err)
	}
	return endpoints, nil
}

// WatchEndpoints returns endpoints in the cluster
func (c *clientImpl) WatchEndpoints(stopCh <-chan bool) (chan interface{}, chan error, error) {
	getURL := c.endpointURL + APIEndpoint + "/endpoints"
	return c.watch(getURL, "", stopCh)
}

// WatchAll returns events in the cluster
func (c *clientImpl) WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
	watchCh := make(chan interface{}, 100)
	errCh := make(chan error, 100)

	stopIngresses := make(chan bool, 10)
	chanIngresses, chanIngressesErr, err := c.WatchIngresses(labelSelector, stopIngresses)
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
	}
	stopServices := make(chan bool, 10)
	chanServices, chanServicesErr, err := c.WatchServices(stopServices)
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
	}
	stopEndpoints := make(chan bool, 10)
	chanEndpoints, chanEndpointsErr, err := c.WatchEndpoints(stopEndpoints)
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
	}
	go func() {
		defer close(watchCh)
		defer close(errCh)
		defer close(stopIngresses)
		defer close(stopServices)
		defer close(stopEndpoints)

		for {
			select {
			case <-stopCh:
				stopIngresses <- true
				stopServices <- true
				stopEndpoints <- true
				return
			case err := <-chanIngressesErr:
				errCh <- err
			case err := <-chanServicesErr:
				errCh <- err
			case err := <-chanEndpointsErr:
				errCh <- err
			case event := <-chanIngresses:
				watchCh <- event
			case event := <-chanServices:
				watchCh <- event
			case event := <-chanEndpoints:
				watchCh <- event
			}
		}
	}()

	return watchCh, errCh, nil
}

func (c *clientImpl) do(request *gorequest.SuperAgent) ([]byte, error) {
	res, body, errs := request.EndBytes()
	if errs != nil {
		return nil, fmt.Errorf("failed to create request: GET %q : %v", request.Url, errs)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("http error %d GET %q: %q", res.StatusCode, request.Url, string(body))
	}
	return body, nil
}

func (c *clientImpl) request(reqURL string, queryContent interface{}) *gorequest.SuperAgent {
	// Make request to Kubernetes API
	parsedURL, parseErr := url.Parse(reqURL)
	if parseErr != nil {
		log.Errorf("Had issues parsing url %s. Trying anyway.", reqURL)
	}
	request := gorequest.New().Get(reqURL)
	request.Transport.DisableKeepAlives = true

	if parsedURL.Scheme == "https" {
		pool := x509.NewCertPool()
		pool.AppendCertsFromPEM(c.caCert)
		c.tls = &tls.Config{RootCAs: pool}
		request.TLSClientConfig(c.tls)
	}
	if len(c.token) > 0 {
		request.Header["Authorization"] = "Bearer " + c.token
	}
	request.Query(queryContent)
	return request
}

// GenericObject generic object
type GenericObject struct {
	TypeMeta `json:",inline"`
	ListMeta `json:"metadata,omitempty"`
}

func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
	watchCh := make(chan interface{}, 10)
	errCh := make(chan error, 10)

	// get version
	body, err := c.do(c.request(url, ""))
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to do version request: GET %q : %v", url, err)
	}

	var generic GenericObject
	if err := json.Unmarshal(body, &generic); err != nil {
		return watchCh, errCh, fmt.Errorf("failed to decode version %v", err)
	}
	resourceVersion := generic.ResourceVersion
	queryParams := map[string]string{"watch": "", "resourceVersion": resourceVersion}
	queryData, err := makeQueryString(queryParams, labelSelector)
	if err != nil {
		return watchCh, errCh, fmt.Errorf("Unable to construct query args")
	}
	request := c.request(url, queryData)
	req, err := request.MakeRequest()
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to make watch request: GET %q : %v", url, err)
	}
	ctx, cancel := context.WithCancel(context.Background())
	req = req.WithContext(ctx)
	request.Client.Transport = request.Transport

	res, err := request.Client.Do(req)
	if err != nil {
		cancel()
		return watchCh, errCh, fmt.Errorf("failed to do watch request: GET %q: %v", url, err)
	}

	go func() {
		defer close(watchCh)
		defer close(errCh)
		go func() {
			defer res.Body.Close()
			for {
				var eventList interface{}
				if err := json.NewDecoder(res.Body).Decode(&eventList); err != nil {
					if !strings.Contains(err.Error(), "net/http: request canceled") {
						errCh <- fmt.Errorf("failed to decode watch event: GET %q : %v", url, err)
					}
					return
				}
				watchCh <- eventList
			}
		}()
		<-stopCh
		go func() {
			cancel() // cancel watch request
		}()
	}()
	return watchCh, errCh, nil
}
<commit_msg>Fix missing value for k8s watch request parameter (#874)<commit_after>package k8s

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"fmt"
	"github.com/containous/traefik/log"
	"github.com/parnurzeal/gorequest"
	"net/http"
	"net/url"
	"strings"
)

const (
	// APIEndpoint defines the base path for kubernetes API resources.
	APIEndpoint        = "/api/v1"
	extentionsEndpoint = "/apis/extensions/v1beta1"
	defaultIngress     = "/ingresses"
	namespaces         = "/namespaces/"
)

// Client is a client for the Kubernetes master.
type Client interface {
	GetIngresses(labelSelector string, predicate func(Ingress) bool) ([]Ingress, error)
	GetService(name, namespace string) (Service, error)
	GetEndpoints(name, namespace string) (Endpoints, error)
	WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error)
}

type clientImpl struct {
	endpointURL string
	tls         *tls.Config
	token       string
	caCert      []byte
}

// NewClient returns a new Kubernetes client.
// The provided host is an url (scheme://hostname[:port]) of a
// Kubernetes master without any path.
// The provided client is an authorized http.Client used to perform requests to the Kubernetes API master.
func NewClient(baseURL string, caCert []byte, token string) (Client, error) {
	validURL, err := url.Parse(baseURL)
	if err != nil {
		return nil, fmt.Errorf("failed to parse URL %q: %v", baseURL, err)
	}
	return &clientImpl{
		endpointURL: strings.TrimSuffix(validURL.String(), "/"),
		token:       token,
		caCert:      caCert,
	}, nil
}

func makeQueryString(baseParams map[string]string, labelSelector string) (string, error) {
	if labelSelector != "" {
		baseParams["labelSelector"] = labelSelector
	}
	queryData, err := json.Marshal(baseParams)
	if err != nil {
		return "", err
	}
	return string(queryData), nil
}

// GetIngresses returns all ingresses in the cluster
func (c *clientImpl) GetIngresses(labelSelector string, predicate func(Ingress) bool) ([]Ingress, error) {
	getURL := c.endpointURL + extentionsEndpoint + defaultIngress
	queryParams := map[string]string{}
	queryData, err := makeQueryString(queryParams, labelSelector)
	if err != nil {
		return nil, fmt.Errorf("Had problems constructing query string %s : %v", queryParams, err)
	}
	body, err := c.do(c.request(getURL, queryData))
	if err != nil {
		return nil, fmt.Errorf("failed to create ingresses request: GET %q : %v", getURL, err)
	}

	var ingressList IngressList
	if err := json.Unmarshal(body, &ingressList); err != nil {
		return nil, fmt.Errorf("failed to decode list of ingress resources: %v", err)
	}
	ingresses := ingressList.Items[:0]
	for _, ingress := range ingressList.Items {
		if predicate(ingress) {
			ingresses = append(ingresses, ingress)
		}
	}
	return ingresses, nil
}

// WatchIngresses returns all ingresses in the cluster
func (c *clientImpl) WatchIngresses(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
	getURL := c.endpointURL + extentionsEndpoint + defaultIngress
	return c.watch(getURL, labelSelector, stopCh)
}

// GetService returns the named service from the named namespace
func (c *clientImpl) GetService(name, namespace string) (Service, error) {
	getURL := c.endpointURL + APIEndpoint + namespaces + namespace + "/services/" + name

	body, err := c.do(c.request(getURL, ""))
	if err != nil {
		return Service{}, fmt.Errorf("failed to create services request: GET %q : %v", getURL, err)
	}

	var service Service
	if err := json.Unmarshal(body, &service); err != nil {
		return Service{}, fmt.Errorf("failed to decode service resource: %v", err)
	}
	return service, nil
}

// WatchServices returns all services in the cluster
func (c *clientImpl) WatchServices(stopCh <-chan bool) (chan interface{}, chan error, error) {
	getURL := c.endpointURL + APIEndpoint + "/services"
	return c.watch(getURL, "", stopCh)
}

// GetEndpoints returns the named Endpoints
// Endpoints have the same name as the coresponding service
func (c *clientImpl) GetEndpoints(name, namespace string) (Endpoints, error) {
	getURL := c.endpointURL + APIEndpoint + namespaces + namespace + "/endpoints/" + name

	body, err := c.do(c.request(getURL, ""))
	if err != nil {
		return Endpoints{}, fmt.Errorf("failed to create endpoints request: GET %q : %v", getURL, err)
	}

	var endpoints Endpoints
	if err := json.Unmarshal(body, &endpoints); err != nil {
		return Endpoints{}, fmt.Errorf("failed to decode endpoints resources: %v", err)
	}
	return endpoints, nil
}

// WatchEndpoints returns endpoints in the cluster
func (c *clientImpl) WatchEndpoints(stopCh <-chan bool) (chan interface{}, chan error, error) {
	getURL := c.endpointURL + APIEndpoint + "/endpoints"
	return c.watch(getURL, "", stopCh)
}

// WatchAll returns events in the cluster
func (c *clientImpl) WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
	watchCh := make(chan interface{}, 100)
	errCh := make(chan error, 100)

	stopIngresses := make(chan bool, 10)
	chanIngresses, chanIngressesErr, err := c.WatchIngresses(labelSelector, stopIngresses)
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
	}
	stopServices := make(chan bool, 10)
	chanServices, chanServicesErr, err := c.WatchServices(stopServices)
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
	}
	stopEndpoints := make(chan bool, 10)
	chanEndpoints, chanEndpointsErr, err := c.WatchEndpoints(stopEndpoints)
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
	}
	go func() {
		defer close(watchCh)
		defer close(errCh)
		defer close(stopIngresses)
		defer close(stopServices)
		defer close(stopEndpoints)

		for {
			select {
			case <-stopCh:
				stopIngresses <- true
				stopServices <- true
				stopEndpoints <- true
				return
			case err := <-chanIngressesErr:
				errCh <- err
			case err := <-chanServicesErr:
				errCh <- err
			case err := <-chanEndpointsErr:
				errCh <- err
			case event := <-chanIngresses:
				watchCh <- event
			case event := <-chanServices:
				watchCh <- event
			case event := <-chanEndpoints:
				watchCh <- event
			}
		}
	}()

	return watchCh, errCh, nil
}

func (c *clientImpl) do(request *gorequest.SuperAgent) ([]byte, error) {
	res, body, errs := request.EndBytes()
	if errs != nil {
		return nil, fmt.Errorf("failed to create request: GET %q : %v", request.Url, errs)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("http error %d GET %q: %q", res.StatusCode, request.Url, string(body))
	}
	return body, nil
}

func (c *clientImpl) request(reqURL string, queryContent interface{}) *gorequest.SuperAgent {
	// Make request to Kubernetes API
	parsedURL, parseErr := url.Parse(reqURL)
	if parseErr != nil {
		log.Errorf("Had issues parsing url %s. Trying anyway.", reqURL)
	}
	request := gorequest.New().Get(reqURL)
	request.Transport.DisableKeepAlives = true

	if parsedURL.Scheme == "https" {
		pool := x509.NewCertPool()
		pool.AppendCertsFromPEM(c.caCert)
		c.tls = &tls.Config{RootCAs: pool}
		request.TLSClientConfig(c.tls)
	}
	if len(c.token) > 0 {
		request.Header["Authorization"] = "Bearer " + c.token
	}
	request.Query(queryContent)
	return request
}

// GenericObject generic object
type GenericObject struct {
	TypeMeta `json:",inline"`
	ListMeta `json:"metadata,omitempty"`
}

func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
	watchCh := make(chan interface{}, 10)
	errCh := make(chan error, 10)

	// get version
	body, err := c.do(c.request(url, ""))
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to do version request: GET %q : %v", url, err)
	}

	var generic GenericObject
	if err := json.Unmarshal(body, &generic); err != nil {
		return watchCh, errCh, fmt.Errorf("failed to decode version %v", err)
	}
	resourceVersion := generic.ResourceVersion
	queryParams := map[string]string{"watch": "true", "resourceVersion": resourceVersion}
	queryData, err := makeQueryString(queryParams, labelSelector)
	if err != nil {
		return watchCh, errCh, fmt.Errorf("Unable to construct query args")
	}
	request := c.request(url, queryData)
	req, err := request.MakeRequest()
	if err != nil {
		return watchCh, errCh, fmt.Errorf("failed to make watch request: GET %q : %v", url, err)
	}
	ctx, cancel := context.WithCancel(context.Background())
	req = req.WithContext(ctx)
	request.Client.Transport = request.Transport

	res, err := request.Client.Do(req)
	if err != nil {
		cancel()
		return watchCh, errCh, fmt.Errorf("failed to do watch request: GET %q: %v", url, err)
	}

	go func() {
		defer close(watchCh)
		defer close(errCh)
		go func() {
			defer res.Body.Close()
			for {
				var eventList interface{}
				if err := json.NewDecoder(res.Body).Decode(&eventList); err != nil {
					if !strings.Contains(err.Error(), "net/http: request canceled") {
						errCh <- fmt.Errorf("failed to decode watch event: GET %q : %v", url, err)
					}
					return
				}
				watchCh <- eventList
			}
		}()
		<-stopCh
		go func() {
			cancel() // cancel watch request
		}()
	}()
	return watchCh, errCh, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strconv"

	"github.com/arbrown/pao/game"
)

func main() {
	fmt.Printf("Hello, Pao\n")
	removeGameChan := make(chan *game.Game)
	games := make(map[string]*game.Game)
	httpMux, wsMux := http.NewServeMux(), http.NewServeMux()
	httpMux.Handle("/listGames", listGamesHandler{games: games})
	httpMux.Handle("/", http.FileServer(http.Dir("./client/")))
	httpMux.Handle("/game", gameHandler{games: games, removeGameChan: removeGameChan})

	go func() {
		for {
			select {
			case g := <-removeGameChan:
				fmt.Printf("Removing game: %v\n", g.ID)
				delete(games, g.ID)
				break
			}
		}
	}()

	host, port := os.Getenv("HOST"), os.Getenv("PORT")
	if port == "" {
		port = "2015"
	}

	err := http.ListenAndServe(bind, httpMux)
	if err != nil {
		panic("ListenAndServe:" + err.Error())
	}
}

type gameHandler struct {
	games          map[string]*game.Game
	removeGameChan chan *game.Game
}

type listGamesHandler struct {
	games map[string]*game.Game
}

type gameResponse struct {
	ID      string
	Players []string
}

func (lgh listGamesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var resp []gameResponse
	for id, game := range lgh.games {
		var players []string
		if game.CurrentPlayer != nil {
			players = append(players, game.CurrentPlayer.Name)
		}
		if game.NextPlayer != nil {
			players = append(players, game.NextPlayer.Name)
		}
		resp = append(resp, gameResponse{ID: id, Players: players})
	}
	js, err := json.Marshal(resp)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(js)
}

func (gh gameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	id := r.FormValue("id")
	name := r.FormValue("name")
	fmt.Println(id)
	if name == "" {
		name = "Anonymous Coward"
	}
	if id != "" {
		// Does the game exist?
		fmt.Printf("All Games: %v\n", gh.games)
		if existingGame, ok := gh.games[id]; ok {
			fmt.Println("Trying to join existing game")
			existingGame.Join(w, r, name)
		} else {
			// make the id requested
			g := game.NewGame(id, gh.removeGameChan)
			fmt.Printf("Made new game %s\n", id)
			gh.games[g.ID] = g
			g.Join(w, r, name)
		}
	} else {
		// no id specified, make the game
		newID := 0
		for _, exists := gh.games[strconv.Itoa(newID)]; exists; _, exists = gh.games[strconv.Itoa(newID)] {
			newID++
		}
		g := game.NewGame(strconv.Itoa(newID), gh.removeGameChan)
		fmt.Printf("Made new game %d\n", newID)
		gh.games[g.ID] = g
		g.Join(w, r, name)
	}
}
<commit_msg>removing wsMux code<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strconv"

	"github.com/arbrown/pao/game"
)

func main() {
	fmt.Printf("Hello, Pao\n")
	removeGameChan := make(chan *game.Game)
	games := make(map[string]*game.Game)
	httpMux := http.NewServeMux()
	httpMux.Handle("/listGames", listGamesHandler{games: games})
	httpMux.Handle("/", http.FileServer(http.Dir("./client/")))
	httpMux.Handle("/game", gameHandler{games: games, removeGameChan: removeGameChan})

	go func() {
		for {
			select {
			case g := <-removeGameChan:
				fmt.Printf("Removing game: %v\n", g.ID)
				delete(games, g.ID)
				break
			}
		}
	}()

	host, port := os.Getenv("HOST"), os.Getenv("PORT")
	if port == "" {
		port = "2015"
	}

	bind := fmt.Sprintf("%s:%s", host, port)

	err := http.ListenAndServe(bind, httpMux)
	if err != nil {
		panic("ListenAndServe:" + err.Error())
	}
}

type gameHandler struct {
	games          map[string]*game.Game
	removeGameChan chan *game.Game
}

type listGamesHandler struct {
	games map[string]*game.Game
}

type gameResponse struct {
	ID      string
	Players []string
}

func (lgh listGamesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var resp []gameResponse
	for id, game := range lgh.games {
		var players []string
		if game.CurrentPlayer != nil {
			players = append(players, game.CurrentPlayer.Name)
		}
		if game.NextPlayer != nil {
			players = append(players, game.NextPlayer.Name)
		}
		resp = append(resp, gameResponse{ID: id, Players: players})
	}
	js, err := json.Marshal(resp)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(js)
}

func (gh gameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	id := r.FormValue("id")
	name := r.FormValue("name")
	fmt.Println(id)
	if name == "" {
		name = "Anonymous Coward"
	}
	if id != "" {
		// Does the game exist?
		fmt.Printf("All Games: %v\n", gh.games)
		if existingGame, ok := gh.games[id]; ok {
			fmt.Println("Trying to join existing game")
			existingGame.Join(w, r, name)
		} else {
			// make the id requested
			g := game.NewGame(id, gh.removeGameChan)
			fmt.Printf("Made new game %s\n", id)
			gh.games[g.ID] = g
			g.Join(w, r, name)
		}
	} else {
		// no id specified, make the game
		newID := 0
		for _, exists := gh.games[strconv.Itoa(newID)]; exists; _, exists = gh.games[strconv.Itoa(newID)] {
			newID++
		}
		g := game.NewGame(strconv.Itoa(newID), gh.removeGameChan)
		fmt.Printf("Made new game %d\n", newID)
		gh.games[g.ID] = g
		g.Join(w, r, name)
	}
}
<|endoftext|>


<commit_before>package proxy

import (
	"bytes"
	"crypto/tls"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strconv"
	"strings"
)

// NewReverseProxy returns new reverse proxy handler that replaces text in response
func NewReverseProxy(host, search, replace string) (http.Handler, error) {
	if !strings.Contains(host, "https") {
		host = "https://" + host
	}

	hostUrl, err := url.Parse(host)
	if err != nil {
		return nil, err
	}

	reverseProxy := httputil.NewSingleHostReverseProxy(hostUrl)
	reverseProxy.Transport = &http.Transport{DialTLS: dialTLS}

	director := reverseProxy.Director
	reverseProxy.Director = func(req *http.Request) {
		director(req)
		req.Host = req.URL.Host
	}

	reverseProxy.ModifyResponse = func(resp *http.Response) (err error) {
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return
		}

		err = resp.Body.Close()
		if err != nil {
			return
		}

		b = bytes.Replace(b, []byte(search), []byte(replace), -1)
		body := ioutil.NopCloser(bytes.NewReader(b))

		resp.Body = body
		resp.ContentLength = int64(len(b))
		resp.Header.Set("Content-Length", strconv.Itoa(len(b)))

		return
	}

	return reverseProxy, nil
}

// dialTLS is custom TLS dialer to verify host
func dialTLS(network, addr string) (net.Conn, error) {
	conn, err := net.Dial(network, addr)
	if err != nil {
		return nil, err
	}

	host, _, err := net.SplitHostPort(addr)
	if err != nil {
		return nil, err
	}
	cfg := &tls.Config{ServerName: host}

	tlsConn := tls.Client(conn, cfg)
	if err := tlsConn.Handshake(); err != nil {
		conn.Close()
		return nil, err
	}

	cs := tlsConn.ConnectionState()
	cert := cs.PeerCertificates[0]

	cert.VerifyHostname(host)

	return tlsConn, nil
}
<commit_msg>- HTTP works. Problems with HTTPS traffic<commit_after>package proxy

import (
	"bytes"
	"crypto/tls"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strconv"
	"strings"
)

// NewReverseProxy returns new reverse proxy handler that replaces text in response
func NewReverseProxy(host, search, replace string) (http.Handler, error) {
	if !strings.Contains(host, "http") {
		host = "http://" + host
	}

	hostUrl, err := url.Parse(host)
	if err != nil {
		return nil, err
	}

	reverseProxy := httputil.NewSingleHostReverseProxy(hostUrl)
	// TODO Uncomment when HTTPS will be fixed
	//reverseProxy.Transport = &http.Transport{DialTLS: dialTLS}

	director := reverseProxy.Director
	reverseProxy.Director = func(req *http.Request) {
		director(req)
		req.Host = req.URL.Host
	}

	reverseProxy.ModifyResponse = func(resp *http.Response) (err error) {
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return
		}

		err = resp.Body.Close()
		if err != nil {
			return
		}

		b = bytes.Replace(b, []byte(search), []byte(replace), -1)
		body := ioutil.NopCloser(bytes.NewReader(b))

		resp.Body = body
		resp.ContentLength = int64(len(b))
		resp.Header.Set("Content-Length", strconv.Itoa(len(b)))

		return
	}

	return reverseProxy, nil
}

// dialTLS is custom TLS dialer to verify host
func dialTLS(network, addr string) (net.Conn, error) {
	conn, err := net.Dial(network, addr)
	if err != nil {
		return nil, err
	}

	host, _, err := net.SplitHostPort(addr)
	if err != nil {
		return nil, err
	}
	cfg := &tls.Config{ServerName: host}

	tlsConn := tls.Client(conn, cfg)
	if err := tlsConn.Handshake(); err != nil {
		conn.Close()
		return nil, err
	}

	cs := tlsConn.ConnectionState()
	cert := cs.PeerCertificates[0]

	cert.VerifyHostname(host)

	return tlsConn, nil
}
<|endoftext|>


<commit_before>package vmess

import (
	"crypto/md5"
	"io"
	"net"
	"sync"

	"github.com/v2ray/v2ray-core"
	"github.com/v2ray/v2ray-core/common/alloc"
	v2io "github.com/v2ray/v2ray-core/common/io"
	"github.com/v2ray/v2ray-core/common/log"
	v2net "github.com/v2ray/v2ray-core/common/net"
	"github.com/v2ray/v2ray-core/proxy/vmess/protocol"
	"github.com/v2ray/v2ray-core/proxy/vmess/protocol/user"
)

type VMessInboundHandler struct {
	vPoint     *core.Point
	clients    user.UserSet
	accepting  bool
	udpEnabled bool
}

func NewVMessInboundHandler(vp *core.Point, clients user.UserSet, udpEnabled bool) *VMessInboundHandler {
	return &VMessInboundHandler{
		vPoint:     vp,
		clients:    clients,
		udpEnabled: udpEnabled,
	}
}

func (handler *VMessInboundHandler) Listen(port uint16) error {
	listener, err := net.ListenTCP("tcp", &net.TCPAddr{
		IP:   []byte{0, 0, 0, 0},
		Port: int(port),
		Zone: "",
	})
	if err != nil {
		return log.Error("Unable to listen tcp:%d", port)
	}
	handler.accepting = true
	go handler.AcceptConnections(listener)

	if handler.udpEnabled {
		handler.ListenUDP(port)
	}

	return nil
}

func (handler *VMessInboundHandler) AcceptConnections(listener *net.TCPListener) error {
	for handler.accepting {
		connection, err := listener.AcceptTCP()
		if err != nil {
			return log.Error("Failed to accpet connection: %s", err.Error())
		}
		go handler.HandleConnection(connection)
	}
	return nil
}

func (handler *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error {
	defer connection.Close()

	connReader := v2net.NewTimeOutReader(120, connection)
	requestReader := protocol.NewVMessRequestReader(handler.clients)

	request, err := requestReader.Read(connReader)
	if err != nil {
		log.Access(connection.RemoteAddr().String(), "", log.AccessRejected, "Invalid Auth")
		log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err)
		return err
	}
	log.Access(connection.RemoteAddr().String(), request.Address.String(), log.AccessAccepted, "")
	log.Debug("VMessIn: Received request for %s", request.Address.String())

	ray := handler.vPoint.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true))
	input := ray.InboundInput()
	output := ray.InboundOutput()
	var readFinish, writeFinish sync.Mutex
	readFinish.Lock()
	writeFinish.Lock()

	go handleInput(request, connReader, input, &readFinish)

	responseKey := md5.Sum(request.RequestKey)
	responseIV := md5.Sum(request.RequestIV)

	responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
	if err != nil {
		return log.Error("VMessIn: Failed to create encrypt writer: %v", err)
	}

	// Optimize for small response packet
	buffer := alloc.NewLargeBuffer()
	buffer.Clear()
	buffer.Append(request.ResponseHeader)

	if data, open := <-output; open {
		buffer.Append(data.Value)
		data.Release()
		responseWriter.Write(buffer.Value)
		buffer.Release()
		go handleOutput(request, responseWriter, output, &writeFinish)
		writeFinish.Lock()
	}

	connection.CloseWrite()
	readFinish.Lock()

	return nil
}

func handleInput(request *protocol.VMessRequest, reader io.Reader, input chan<- *alloc.Buffer, finish *sync.Mutex) {
	defer close(input)
	defer finish.Unlock()

	requestReader, err := v2io.NewAesDecryptReader(request.RequestKey, request.RequestIV, reader)
	if err != nil {
		log.Error("VMessIn: Failed to create decrypt reader: %v", err)
		return
	}

	v2net.ReaderToChan(input, requestReader)
}

func handleOutput(request *protocol.VMessRequest, writer io.Writer, output <-chan *alloc.Buffer, finish *sync.Mutex) {
	v2net.ChanToWriter(writer, output)
	finish.Unlock()
}

type VMessInboundHandlerFactory struct {
}

func (factory *VMessInboundHandlerFactory) Create(vp *core.Point, rawConfig interface{}) (core.InboundConnectionHandler, error) {
	config := rawConfig.(*VMessInboundConfig)

	allowedClients := user.NewTimedUserSet()
	for _, client := range config.AllowedClients {
		user, err := client.ToUser()
		if err != nil {
			panic(log.Error("VMessIn: Failed to parse user id %s: %v", client.Id, err))
		}
		allowedClients.AddUser(user)
	}

	return NewVMessInboundHandler(vp, allowedClients, config.UDPEnabled), nil
}

func init() {
	core.RegisterInboundConnectionHandlerFactory("vmess", &VMessInboundHandlerFactory{})
}
<commit_msg>Update access log in vmess in<commit_after>package vmess

import (
	"crypto/md5"
	"io"
	"net"
	"sync"

	"github.com/v2ray/v2ray-core"
	"github.com/v2ray/v2ray-core/common/alloc"
	v2io "github.com/v2ray/v2ray-core/common/io"
	"github.com/v2ray/v2ray-core/common/log"
	v2net "github.com/v2ray/v2ray-core/common/net"
	"github.com/v2ray/v2ray-core/proxy/vmess/protocol"
	"github.com/v2ray/v2ray-core/proxy/vmess/protocol/user"
)

type VMessInboundHandler struct {
	vPoint     *core.Point
	clients    user.UserSet
	accepting  bool
	udpEnabled bool
}

func NewVMessInboundHandler(vp *core.Point, clients user.UserSet, udpEnabled bool) *VMessInboundHandler {
	return &VMessInboundHandler{
		vPoint:     vp,
		clients:    clients,
		udpEnabled: udpEnabled,
	}
}

func (handler *VMessInboundHandler) Listen(port uint16) error {
	listener, err := net.ListenTCP("tcp", &net.TCPAddr{
		IP:   []byte{0, 0, 0, 0},
		Port: int(port),
		Zone: "",
	})
	if err != nil {
		return log.Error("Unable to listen tcp:%d", port)
	}
	handler.accepting = true
	go handler.AcceptConnections(listener)

	if handler.udpEnabled {
		handler.ListenUDP(port)
	}

	return nil
}

func (handler *VMessInboundHandler) AcceptConnections(listener *net.TCPListener) error {
	for handler.accepting {
		connection, err := listener.AcceptTCP()
		if err != nil {
			return log.Error("Failed to accpet connection: %s", err.Error())
		}
		go handler.HandleConnection(connection)
	}
	return nil
}

func (handler *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error {
	defer connection.Close()

	connReader := v2net.NewTimeOutReader(120, connection)
	requestReader := protocol.NewVMessRequestReader(handler.clients)

	request, err := requestReader.Read(connReader)
	if err != nil {
		log.Access(connection.RemoteAddr().String(), "", log.AccessRejected, err.Error())
		log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err)
		return err
	}
	log.Access(connection.RemoteAddr().String(), request.Address.String(), log.AccessAccepted, "")
	log.Debug("VMessIn: Received request for %s", request.Address.String())

	ray := handler.vPoint.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true))
	input := ray.InboundInput()
	output := ray.InboundOutput()
	var readFinish, writeFinish sync.Mutex
	readFinish.Lock()
	writeFinish.Lock()

	go handleInput(request, connReader, input, &readFinish)

	responseKey := md5.Sum(request.RequestKey)
	responseIV := md5.Sum(request.RequestIV)

	responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
	if err != nil {
		return log.Error("VMessIn: Failed to create encrypt writer: %v", err)
	}

	// Optimize for small response packet
	buffer := alloc.NewLargeBuffer()
	buffer.Clear()
	buffer.Append(request.ResponseHeader)

	if data, open := <-output; open {
		buffer.Append(data.Value)
		data.Release()
		responseWriter.Write(buffer.Value)
		buffer.Release()
		go handleOutput(request, responseWriter, output, &writeFinish)
		writeFinish.Lock()
	}

	connection.CloseWrite()
	readFinish.Lock()

	return nil
}

func handleInput(request *protocol.VMessRequest, reader io.Reader, input chan<- *alloc.Buffer, finish *sync.Mutex) {
	defer close(input)
	defer finish.Unlock()

	requestReader, err := v2io.NewAesDecryptReader(request.RequestKey, request.RequestIV, reader)
	if err != nil {
		log.Error("VMessIn: Failed to create decrypt reader: %v", err)
		return
	}

	v2net.ReaderToChan(input, requestReader)
}

func handleOutput(request *protocol.VMessRequest, writer io.Writer, output <-chan *alloc.Buffer, finish *sync.Mutex) {
	v2net.ChanToWriter(writer, output)
	finish.Unlock()
}

type VMessInboundHandlerFactory struct {
}

func (factory *VMessInboundHandlerFactory) Create(vp *core.Point, rawConfig interface{}) (core.InboundConnectionHandler, error) {
	config := rawConfig.(*VMessInboundConfig)

	allowedClients := user.NewTimedUserSet()
	for _, client := range config.AllowedClients {
		user, err := client.ToUser()
		if err != nil {
			panic(log.Error("VMessIn: Failed to parse user id %s: %v", client.Id, err))
		}
		allowedClients.AddUser(user)
	}

	return NewVMessInboundHandler(vp, allowedClients, config.UDPEnabled), nil
}

func init() {
	core.RegisterInboundConnectionHandlerFactory("vmess", &VMessInboundHandlerFactory{})
}
<|endoftext|>


<commit_before>package cmd

import (
	"errors"

	"github.com/zenoss/serviced/serviced/api"
)

var DefaultSnapshotAPITest = SnapshotAPITest{snapshots: DefaultTestSnapshots}

var DefaultTestSnapshots = []string{
	"test-service-1-snapshot-1",
	"test-service-1-snapshot-2",
	"test-service-2-snapshot-1",
}

var (
	ErrNoServiceFound  = errors.New("no service found")
	ErrNoSnapshotFound = errors.New("no snapshot found")
)

type SnapshotAPITest struct {
	api.API
	snapshots []string
}

func InitSnapshotAPITest(args ...string) {
	New(DefaultSnapshotAPITest).Run(args)
}

func (t SnapshotAPITest) GetSnapshots() ([]string, error) {
	return nil, nil
}

func (t SnapshotAPITest) GetSnapshotsByServiceID(serviceID string) ([]string, error) {
	return nil, nil
}

func (t SnapshotAPITest) AddSnapshot(serviceID string) (string, error) {
	return "", nil
}

func (t SnapshotAPITest) RemoveSnapshot(id string) error {
	return nil
}

func (t SnapshotAPITest) Commit(dockerID string) (string, error) {
	return "", nil
}

func (t SnapshotAPITest) Rollback(id string) error {
	return nil
}

func ExampleServicedCli_cmdSnapshotList() {
	InitSnapshotAPITest("serviced", "snapshot", "list")
}

func ExampleServicedCli_cmdSnapshotAdd() {
	InitSnapshotAPITest("serviced", "snapshot", "add")
}

func ExampleServicedCli_cmdSnapshotRemove() {
	InitSnapshotAPITest("serviced", "snapshot", "remove")
	InitSnapshotAPITest("serviced", "snapshot", "rm")
}

func ExampleServicedCli_cmdSnapshotCommit() {
	InitSnapshotAPITest("serviced", "snapshot", "commit")
}

func ExampleServicedCli_cmdSnapshotRollback() {
	InitSnapshotAPITest("serviced", "snapshot", "rollback")
}
<commit_msg>Added snapshot tests<commit_after>package cmd

import (
	"errors"
	"fmt"
	"strings"

	"github.com/zenoss/serviced/serviced/api"
)

var DefaultSnapshotAPITest = SnapshotAPITest{snapshots: DefaultTestSnapshots}

var DefaultTestSnapshots = []string{
	"test-service-1-snapshot-1",
	"test-service-1-snapshot-2",
	"test-service-2-snapshot-1",
}

var (
	ErrNoServiceFound  = errors.New("no service found")
	ErrNoSnapshotFound = errors.New("no snapshot found")
)

type SnapshotAPITest struct {
	api.API
	snapshots []string
}

func InitSnapshotAPITest(args ...string) {
	New(DefaultSnapshotAPITest).Run(args)
}

func (t SnapshotAPITest) GetSnapshots() ([]string, error) {
	return t.snapshots, nil
}

func (t SnapshotAPITest) GetSnapshotsByServiceID(serviceID string) ([]string, error) {
	var snapshots []string
	for _, s := range t.snapshots {
		if strings.HasPrefix(s, serviceID) {
			snapshots = append(snapshots, s)
		}
	}

	return snapshots, nil
}

func (t SnapshotAPITest) AddSnapshot(serviceID string) (string, error) {
	return fmt.Sprintf("%s-snapshot", serviceID), nil
}

func (t SnapshotAPITest) RemoveSnapshot(id string) error {
	for _, s := range t.snapshots {
		if s == id {
			return nil
		}
	}

	return ErrNoSnapshotFound
}

func (t SnapshotAPITest) Commit(dockerID string) (string, error) {
	return fmt.Sprintf("%s-snapshot", dockerID), nil
}

func (t SnapshotAPITest) Rollback(id string) error {
	for _, s := range t.snapshots {
		if s == id {
			return nil
		}
	}

	return ErrNoSnapshotFound
}

func ExampleServicedCli_cmdSnapshotList() {
	InitSnapshotAPITest("serviced", "snapshot", "list")

	// Output:
	// test-service-1-snapshot-1
	// test-service-1-snapshot-2
	// test-service-2-snapshot-1
}

func ExampleServicedCli_cmdSnapshotList_ByServiced() {
	InitSnapshotAPITest("serviced", "snapshot", "list", "test-service-1")

	// Output
	// test-service-1-snapshot-1
	// test-service-1-snapshot-2
}

func ExampleServicedCli_cmdSnapshotAdd() {
	InitSnapshotAPITest("serviced", "snapshot", "add", "test-service-99")

	// Output:
	// test-service-99-snapshot
}

func ExampleServicedCli_cmdSnapshotRemove() {
	InitSnapshotAPITest("serviced", "snapshot", "remove", "test-service-2-snapshot-1", "test-service-0-snapshot-4")

	// Output:
	// test-service-2-snapshot-1
}

func ExampleServicedCli_cmdSnapshotCommit() {
	InitSnapshotAPITest("serviced", "snapshot", "commit", "ABC123")

	// Output:
	// ABC123-snapshot
}

func ExampleServicedCli_cmdSnapshotRollback() {
	InitSnapshotAPITest("serviced", "snapshot", "rollback", "test-service-1-snapshot-1")

	// Output:
	// test-service-1-snapshot-1
}
<|endoftext|>


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

// +build linux freebsd netbsd solaris darwin

package saslauthd

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"io"
	"net"
	"os"
)

func readString(r io.Reader) ([]byte, error) {
	var size uint16
	err := binary.Read(r, binary.BigEndian, &size)
	if err != nil {
		return nil, err
	}
	b := make([]byte, int(size))
	_, err = io.ReadFull(r, b)
	if err != nil {
		return nil, err
	}
	return b, nil
}

func writeString(w io.Writer, s string) error {
	b := make([]byte, 2+len(s))
	binary.BigEndian.PutUint16(b, uint16(len(s)))
	copy(b[2:], s)
	_, err := w.Write(b)
	return err
}

func writeReq(w io.Writer, user, pwd, service, realm string) error {
	blen := 2*4 + len(user) + len(pwd) + len(service) + len(realm)
	buf := bytes.NewBuffer(make([]byte, blen)[:0])
	writeString(buf, user)
	writeString(buf, pwd)
	writeString(buf, service)
	writeString(buf, realm)
	if len(buf.Bytes()) != blen {
		panic("BUG")
	}
	_, err := w.Write(buf.Bytes())
	return err
}

var sockPath = initSockpath()

func initSockpath() string {
	s := os.Getenv("CBAUTH_SOCKPATH")
	if s == "" {
		s = "/var/run/saslauthd/mux"
	}
	return s
}

type ConnectFn func() (io.ReadWriteCloser, error)

func connect() (io.ReadWriteCloser, error) {
	return net.Dial("unix", sockPath)
}

func AuthWithConnect(user, pwd, service, real string, connect ConnectFn) (ok bool, err error) {
	conn, err := connect()
	if err != nil {
		return
	}
	defer conn.Close()
	err = writeReq(conn, user, pwd, service, real)
	if err != nil {
		return
	}
	resp, err := readString(bufio.NewReader(conn))
	ok = (len(resp) >= 2 && string(resp[:2]) == "OK")
	return
}

func Auth(user, pwd, service, real string) (ok bool, err error) {
	return AuthWithConnect(user, pwd, service, real, connect)
}

func Supported() bool {
	return true
}

func Available() bool {
	c, _ := connect()
	if c != nil {
		c.Close()
	}
	return c != nil
}
<commit_msg>added godoc to saslauthd package<commit_after>// @author Couchbase <info@couchbase.com>
// @copyright 2014 Couchbase, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build linux freebsd netbsd solaris darwin

package saslauthd

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"io"
	"net"
	"os"
)

func readString(r io.Reader) ([]byte, error) {
	var size uint16
	err := binary.Read(r, binary.BigEndian, &size)
	if err != nil {
		return nil, err
	}
	b := make([]byte, int(size))
	_, err = io.ReadFull(r, b)
	if err != nil {
		return nil, err
	}
	return b, nil
}

func writeString(w io.Writer, s string) error {
	b := make([]byte, 2+len(s))
	binary.BigEndian.PutUint16(b, uint16(len(s)))
	copy(b[2:], s)
	_, err := w.Write(b)
	return err
}

func writeReq(w io.Writer, user, pwd, service, realm string) error {
	blen := 2*4 + len(user) + len(pwd) + len(service) + len(realm)
	buf := bytes.NewBuffer(make([]byte, blen)[:0])
	writeString(buf, user)
	writeString(buf, pwd)
	writeString(buf, service)
	writeString(buf, realm)
	if len(buf.Bytes()) != blen {
		panic("BUG")
	}
	_, err := w.Write(buf.Bytes())
	return err
}

var sockPath = initSockpath()

func initSockpath() string {
	s := os.Getenv("CBAUTH_SOCKPATH")
	if s == "" {
		s = "/var/run/saslauthd/mux"
	}
	return s
}

// ConnectFn is function used to establish connection to saslauthd.
type ConnectFn func() (io.ReadWriteCloser, error)

func connect() (io.ReadWriteCloser, error) {
	return net.Dial("unix", sockPath)
}

// AuthWithConnect verifies given creds in saslauthd using given
// connect function to reach it.
func AuthWithConnect(user, pwd, service, real string, connect ConnectFn) (ok bool, err error) {
	conn, err := connect()
	if err != nil {
		return
	}
	defer conn.Close()
	err = writeReq(conn, user, pwd, service, real)
	if err != nil {
		return
	}
	resp, err := readString(bufio.NewReader(conn))
	ok = (len(resp) >= 2 && string(resp[:2]) == "OK")
	return
}

// Auth verifies given creds in saslauthd.
func Auth(user, pwd, service, real string) (ok bool, err error) {
	return AuthWithConnect(user, pwd, service, real, connect)
}

// Supported returns true on all platforms where saslauthd code is
// supported (which is essentially all but windows).
func Supported() bool {
	return true
}

// Available returns true iff saslauthd socket is reachable.
func Available() bool {
	c, _ := connect()
	if c != nil {
		c.Close()
	}
	return c != nil
}
<|endoftext|>


<commit_before>package ddns

import (
	"log"
	"net"
	"github.com/mediocregopher/radix.v2/pool"
)

func (s *Server) logq2b(name string, addr net.Addr, pool *pool.Pool) error {
	conn, err := pool.Get()
	if err != nil {
		log.Printf("q2b: %s", err)
		return err
	}
	defer pool.Put(conn)

	err = conn.Cmd("SETEX", name, 120, addr).Err
	if err != nil {
		log.Printf("q2b: %s", err)
	}
	return err
}
<commit_msg>remove last '.' and client port when send to redis backend<commit_after>package ddns

import (
	"log"
	"net"
	"strings"
	"github.com/mediocregopher/radix.v2/pool"
)

func (s *Server) logq2b(name string, addr net.Addr, pool *pool.Pool) error {
	conn, err := pool.Get()
	if err != nil {
		log.Printf("q2b: %s", err)
		return err
	}
	defer pool.Put(conn)

	name = strings.TrimSuffix(name, ".")
	clientip, _, err := net.SplitHostPort(addr.String())
	if err != nil {
		return err
	}
	err = conn.Cmd("SETEX", name, 120, clientip).Err
	if err != nil {
		log.Printf("q2b: %s", err)
	}
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"strings"

	"github.com/garyburd/redigo/redis"
	"github.com/gorilla/mux"
)

type Similar interface {
	Similar(v []float32) float32
}

type Request struct {
	Urls []string `json:"urls"`
}

type Response struct {
	Recommendation map[string]float32 `json:"recommendation"`
	Err            string             `json:"error"`

	conn redis.Conn
}

func stringToFloat32(vString string) (v float32, err error) {
	v64, err := strconv.ParseFloat(vString, 32)
	if err != nil {
		return
	}
	v = float32(v64)
	return
}

func newFloat32Matrix(height, width int) [][]float32 {
	var mx [][]float32 = make([][]float32, height)
	for i := 0; i < width; i++ {
		mx[i] = make([]float32, width)
	}
	return mx
}

func matrixPosition(width, i, j int) int {
	return i*width + j
}

func weightKey(url, profile string) string {
	return strings.Join([]string{url, profile}, "|")
}

func weightKeys(urls, profiles []string) []interface{} {
	var keys = make([]interface{}, 0, len(urls)*len(profiles))
	for _, url := range urls {
		for _, profile := range profiles {
			key := weightKey(url, profile)
			keys = append(keys, key)
		}
	}
	return keys
}

func getWeight(conn redis.Conn, url, profile string) (w float32, err error) {
	key := weightKey(url, profile)

	weight, err := redis.String(conn.Do("GET", key))
	if err == redis.ErrNil {
		weight = "0"
	} else if err != nil {
		return
	}

	return stringToFloat32(weight)
}

func getWeights(conn redis.Conn, urls, profiles []string) ([][]float32, error) {
	keys := weightKeys(urls, profiles)

	// TODO: how to pass []string?
	weightsString, err := redis.Strings(conn.Do("MGET", keys...))
	if err != nil {
		return nil, err
	}

	urlProfile := newFloat32Matrix(len(urls), len(profiles))

	for i := range urls {
		for j := range profiles {
			pos := matrixPosition(len(profiles), i, j)

			wString := weightsString[pos]
			if wString == "" {
				continue
			}

			w, err := stringToFloat32(wString)
			if err != nil {
				return nil, err
			}

			urlProfile[i][j] = w
		}
	}

	return urlProfile, nil
}

func setWeight(conn redis.Conn, url, profile string) {
}

func (self *Response) countRecommendation(session []string) (recommendation map[string]float32, err error) {
	urls, err := redis.Strings(self.conn.Do("SMEMBERS", "urls"))
	if err != nil {
		return
	}

	profiles, err := redis.Strings(self.conn.Do("SMEMBERS", "profiles"))
	if err != nil {
		return
	}

	weights, err := getWeights(self.conn, urls, profiles)
	if err != nil {
		return
	}

	// Мамдани епта
	for i, url := range urls {
		for j, profile := range profiles {
			log.Println(url, profile, weights[i][j])
			//min(similarity, freq)
		}
		//max
	}

	return
}

func (self *Response) SetRecommendation(session []string) (err error) {
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		return
	}
	defer conn.Close()
	self.conn = conn

	self.Recommendation, err = self.countRecommendation(session)
	return
}

func recommendHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	decoder := json.NewDecoder(r.Body)
	encoder := json.NewEncoder(w)

	req := new(Request)
	resp := &Response{}

	var err error

	defer func() {
		if err != nil {
			log.Println(err)
			resp.Err = err.Error()
		}

		err := encoder.Encode(resp)
		if err != nil {
			log.Println(err)
		}
	}()

	err = decoder.Decode(req)
	if err != nil {
		return
	}

	err = resp.SetRecommendation(req.Urls)
}

func startRecommendationServer() {
	r := mux.NewRouter()
	r.HandleFunc("/recommend", recommendHandler).Methods("POST")
	http.Handle("/", r)

	log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil))
}

func main() {
	startRecommendationServer()
}

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}
<commit_msg>added TODOs<commit_after>package main

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"strings"

	"github.com/garyburd/redigo/redis"
	"github.com/gorilla/mux"
)

type Similar interface {
	Similar(v []float32) float32
}

type Request struct {
	Urls []string `json:"urls"`
}

type Response struct {
	Recommendation map[string]float32 `json:"recommendation"`
	Err            string             `json:"error"`

	conn redis.Conn
}

func stringToFloat32(vString string) (v float32, err error) {
	v64, err := strconv.ParseFloat(vString, 32)
	if err != nil {
		return
	}
	v = float32(v64)
	return
}

func newFloat32Matrix(height, width int) [][]float32 {
	var mx [][]float32 = make([][]float32, height)
	for i := 0; i < width; i++ {
		mx[i] = make([]float32, width)
	}
	return mx
}

func matrixPosition(width, i, j int) int {
	return i*width + j
}

func weightKey(url, profile string) string {
	return strings.Join([]string{url, profile}, "|")
}

func weightKeys(urls, profiles []string) []interface{} {
	var keys = make([]interface{}, 0, len(urls)*len(profiles))
	for _, url := range urls {
		for _, profile := range profiles {
			key := weightKey(url, profile)
			keys = append(keys, key)
		}
	}
	return keys
}

func getWeight(conn redis.Conn, url, profile string) (w float32, err error) {
	key := weightKey(url, profile)

	weight, err := redis.String(conn.Do("GET", key))
	if err == redis.ErrNil {
		weight = "0"
	} else if err != nil {
		return
	}

	return stringToFloat32(weight)
}

func getWeights(conn redis.Conn, urls, profiles []string) ([][]float32, error) {
	keys := weightKeys(urls, profiles)

	// TODO: how to pass []string?
	weightsString, err := redis.Strings(conn.Do("MGET", keys...))
	if err != nil {
		return nil, err
	}

	urlProfile := newFloat32Matrix(len(urls), len(profiles))

	for i := range urls {
		for j := range profiles {
			pos := matrixPosition(len(profiles), i, j)

			wString := weightsString[pos]
			if wString == "" {
				continue
			}

			w, err := stringToFloat32(wString)
			if err != nil {
				return nil, err
			}

			urlProfile[i][j] = w
		}
	}

	return urlProfile, nil
}

func setWeight(conn redis.Conn, url, profile string) {
}

// TODO: 3 requests to redis is too much
// TODO: add timeouts
func (self *Response) countRecommendation(session []string) (recommendation map[string]float32, err error) {
	urls, err := redis.Strings(self.conn.Do("SMEMBERS", "urls"))
	if err != nil {
		return
	}

	profiles, err := redis.Strings(self.conn.Do("SMEMBERS", "profiles"))
	if err != nil {
		return
	}

	weights, err := getWeights(self.conn, urls, profiles)
	if err != nil {
		return
	}

	// Мамдани епта
	for i, url := range urls {
		for j, profile := range profiles {
			log.Println(url, profile, weights[i][j])
			//min(similarity, freq)
		}
		//max
	}

	return
}

func (self *Response) SetRecommendation(session []string) (err error) {
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		return
	}
	defer conn.Close()
	self.conn = conn

	self.Recommendation, err = self.countRecommendation(session)
	return
}

func recommendHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	decoder := json.NewDecoder(r.Body)
	encoder := json.NewEncoder(w)

	req := new(Request)
	resp := &Response{}

	var err error

	defer func() {
		if err != nil {
			log.Println(err)
			resp.Err = err.Error()
		}

		err := encoder.Encode(resp)
		if err != nil {
			log.Println(err)
		}
	}()

	err = decoder.Decode(req)
	if err != nil {
		return
	}

	err = resp.SetRecommendation(req.Urls)
}

func startRecommendationServer() {
	r := mux.NewRouter()
	r.HandleFunc("/recommend", recommendHandler).Methods("POST")
	http.Handle("/", r)

	log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil))
}

func main() {
	startRecommendationServer()
}

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}
<|endoftext|>


<commit_before>package scontext

import (
	"context"
	"github.com/shawnfeng/sutil/slog"
)

// 由于请求的上下文信息的 thrift 定义在 util 项目中，本模块主要为了避免循环依赖
const (
	ContextKeyTraceID = "traceID"
	ContextKeyControl = "Control"

	ContextKeyHead        = "Head"
	ContextKeyHeadUid     = "uid"
	ContextKeyHeadSource  = "source"
	ContextKeyHeadIp      = "ip"
	ContextKeyHeadRegion  = "region"
	ContextKeyHeadDt      = "dt"
	ContextKeyHeadUnionId = "unionid"
)

type ContextHeader interface {
	ToKV() map[string]interface{}
}

type ContextController interface {
	GetGroup() string
}

func GetGroup(ctx context.Context) string {
	fun := "GetGroup -->"
	value := ctx.Value(ContextKeyControl)
	if value == nil {
		slog.Infof("%s value is nil", fun)
		return ""
	}

	control, ok := value.(ContextController)
	if ok == false {
		slog.Infof("%s value.(ContextController) is false", fun)
		return ""
	}

	group := control.GetGroup()
	slog.Infof("%s group: %s", fun, group)

	return group
}
<commit_msg>MOD:del log<commit_after>package scontext

import (
	"context"
)

// 由于请求的上下文信息的 thrift 定义在 util 项目中，本模块主要为了避免循环依赖
const (
	ContextKeyTraceID = "traceID"
	ContextKeyControl = "Control"

	ContextKeyHead        = "Head"
	ContextKeyHeadUid     = "uid"
	ContextKeyHeadSource  = "source"
	ContextKeyHeadIp      = "ip"
	ContextKeyHeadRegion  = "region"
	ContextKeyHeadDt      = "dt"
	ContextKeyHeadUnionId = "unionid"
)

type ContextHeader interface {
	ToKV() map[string]interface{}
}

type ContextController interface {
	GetGroup() string
}

func GetGroup(ctx context.Context) string {
	value := ctx.Value(ContextKeyControl)
	if value == nil {
		return ""
	}

	control, ok := value.(ContextController)
	if ok == false {
		return ""
	}

	return control.GetGroup()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"go/format"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
	"text/template"

	"github.com/golang/protobuf/protoc-gen-go/descriptor"
	"github.com/serenize/snaker"
	"github.com/xtgo/set"

	"github.com/fatih/color"
	"github.com/golang/glog"
	"github.com/golang/protobuf/proto"
	plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
)

var (
	templatePath = os.Getenv("GOPATH") + "/src/github.com/lileio/lile/protoc-gen-lile-server/templates"

	input  io.Reader
	output io.Writer
)

type grpcMethod struct {
	ServiceName     string
	ImportName      string
	Name            string
	InType          string
	OutType         string
	ClientStreaming bool
	ServerStreaming bool

	GoPackage    string
	InputImport  string
	OutputImport string
}

// Used to import other packages correctly, for example..
// Package: "google.protobuf"
// GoPackage: "github.com/golang/protobuf/ptypes/empty"
// we replace all occurences of Package with the end of GoPackage and import it
type goimport struct {
	Package   string
	GoPackage string
	GoType    string
}

func main() {
	gen(os.Stdin, os.Stdout)
}

func gen(i io.Reader, o io.Writer) {
	input = i
	output = o

	// Force color output
	if runtime.GOOS != "windows" {
		color.NoColor = false
	}

	// Parse the incoming protobuf request
	req, err := parseReq(input)
	if err != nil {
		emitError(err)
		log.Fatal(err)
	}

	path := "./server"
	if req.Parameter != nil {
		path = *req.Parameter
	}

	files := []*plugin.CodeGeneratorResponse_File{}
	imports := []goimport{}

	for _, file := range req.ProtoFile {
		pkgParts := strings.Split(file.GetOptions().GetGoPackage(), "/")
		imports = append(imports, goimport{
			Package:   file.GetPackage(),
			GoPackage: file.GetOptions().GetGoPackage(),
			GoType:    pkgParts[len(pkgParts)-1],
		})

		// Only generate methods for this file/project
		if *file.Name != req.FileToGenerate[0] {
			if file.Options == nil || file.Options.GoPackage == nil {
				log.Fatalf("No go_package option defined for import %s", *file.Name)
			}

			continue
		}

		if file.Options == nil || file.Options.GoPackage == nil {
			log.Fatalf("No go_package option defined in %s", *file.Name)
		}

		pkgSplit := strings.Split(file.Options.GetGoPackage(), "/")

		for _, service := range file.Service {
			for _, method := range service.Method {
				gm := grpcMethod{
					ServiceName:     service.GetName(),
					GoPackage:       file.Options.GetGoPackage(),
					ImportName:      pkgSplit[len(pkgSplit)-1],
					Name:            method.GetName(),
					InType:          toGoType(imports, method.GetInputType()),
					OutType:         toGoType(imports, method.GetOutputType()),
					ClientStreaming: method.GetClientStreaming(),
					ServerStreaming: method.GetServerStreaming(),

					InputImport:  inputImport(imports, method),
					OutputImport: outputImport(imports, method),
				}

				f, err := generateMethod(path, gm)
				if err != nil {
					emitError(err)
					log.Fatal(err)
				}

				if len(f) > 0 {
					for _, v := range f {
						files = append(files, v)
					}
				}
			}
		}
	}

	emitFiles(files)
}

func DedupImports(imports ...string) string {
	data := sort.StringSlice(imports)
	sort.Sort(data)
	n := set.Uniq(data)
	imports = data[:n]

	return fmt.Sprintf("\t\"%s\"", strings.Join(imports, "\"\n\t\""))
}

func toGoType(imports []goimport, t string) string {
	t = strings.Trim(t, ".")
	for _, i := range imports {
		if strings.Contains(t, i.Package) {
			return strings.Replace(t, i.Package, i.GoType, 1)
		}
	}

	return t
}

func inputImport(imports []goimport, method *descriptor.MethodDescriptorProto) string {
	for _, i := range imports {
		if strings.Contains(method.GetInputType(), i.Package) {
			return i.GoPackage
		}
	}

	return ""
}

func outputImport(imports []goimport, method *descriptor.MethodDescriptorProto) string {
	for _, i := range imports {
		if strings.Contains(method.GetOutputType(), i.Package) {
			return i.GoPackage
		}
	}

	return ""
}

func generateMethod(basePath string, m grpcMethod) ([]*plugin.CodeGeneratorResponse_File, error) {
	path := filepath.Join(basePath, snaker.CamelToSnake(m.Name)+".go")
	test_path := filepath.Join(basePath, snaker.CamelToSnake(m.Name)+"_test.go")

	template := fmt.Sprintf("%s_%s",
		streamFromBool(m.ClientStreaming),
		streamFromBool(m.ServerStreaming),
	)

	// If the file exists then just skip the creation
	_, err := os.Stat(path)
	if err == nil {
		log.Printf("%s %s", color.YellowString("[Skipping]"), path)
		return nil, nil
	}

	files := []*plugin.CodeGeneratorResponse_File{}

	log.Printf("%s %s", color.GreenString("[Creating]"), path)
	f, err := render(path, template+".tmpl", m)
	if err != nil {
		return nil, err
	}

	files = append(files, f)

	log.Printf("%s %s", color.CyanString("[Creating test]"), test_path)
	f, err = render(test_path, template+"_test.tmpl", m)

	files = append(files, f)
	return files, err
}

func streamFromBool(streaming bool) string {
	if streaming {
		return "stream"
	}

	return "unary"
}

func render(path, tmpl string, m grpcMethod) (*plugin.CodeGeneratorResponse_File, error) {
	t := template.New(tmpl)

	funcMap := template.FuncMap{
		"dedupImports": DedupImports,
	}

	t = t.Funcs(funcMap)
	t, err := t.ParseFiles(filepath.Join(templatePath, tmpl))
	if err != nil {
		return nil, err
	}

	var out bytes.Buffer
	err = t.Execute(&out, m)
	if err != nil {
		return nil, err
	}

	b, err := format.Source(out.Bytes())
	if err != nil {
		return nil, err
	}

	str := string(b)

	return &plugin.CodeGeneratorResponse_File{
		Name:    &path,
		Content: &str,
	}, nil
}

func parseReq(r io.Reader) (*plugin.CodeGeneratorRequest, error) {
	input, err := ioutil.ReadAll(r)
	if err != nil {
		log.Fatalf("Failed to read code generator request: %v", err)
		return nil, err
	}

	req := new(plugin.CodeGeneratorRequest)
	if err = proto.Unmarshal(input, req); err != nil {
		log.Fatalf("Failed to unmarshal code generator request: %v", err)
		return nil, err
	}

	return req, nil
}

func emitFiles(files []*plugin.CodeGeneratorResponse_File) {
	emitResp(&plugin.CodeGeneratorResponse{File: files})
}

func emitError(err error) {
	emitResp(&plugin.CodeGeneratorResponse{Error: proto.String(err.Error())})
}

func emitResp(resp *plugin.CodeGeneratorResponse) {
	buf, err := proto.Marshal(resp)
	if err != nil {
		glog.Fatal(err)
	}
	if _, err := output.Write(buf); err != nil {
		glog.Fatal(err)
	}
}
<commit_msg>get GOPATH from "go env GOPATH" if not set<commit_after>package main

import (
	"bytes"
	"fmt"
	"go/format"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
	"text/template"

	"github.com/golang/protobuf/protoc-gen-go/descriptor"
	"github.com/serenize/snaker"
	"github.com/xtgo/set"

	"github.com/fatih/color"
	"github.com/golang/glog"
	"github.com/golang/protobuf/proto"
	plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
)

var (
	gopath       string
	templatePath string

	input  io.Reader
	output io.Writer
)

type grpcMethod struct {
	ServiceName     string
	ImportName      string
	Name            string
	InType          string
	OutType         string
	ClientStreaming bool
	ServerStreaming bool

	GoPackage    string
	InputImport  string
	OutputImport string
}

// Used to import other packages correctly, for example..
// Package: "google.protobuf"
// GoPackage: "github.com/golang/protobuf/ptypes/empty"
// we replace all occurences of Package with the end of GoPackage and import it
type goimport struct {
	Package   string
	GoPackage string
	GoType    string
}

func init() {
	gopath = os.Getenv("GOPATH")
	if gopath == "" {
		b, err := exec.Command("go", "env", "GOPATH").CombinedOutput()
		if err != nil {
			panic(string(b))
		}
		gopath = strings.TrimSpace(string(b))
	}
	if paths := filepath.SplitList(gopath); len(paths) > 0 {
		gopath = paths[0]
	}
	templatePath = filepath.Clean(filepath.Join(gopath, "/src/github.com/lileio/lile/protoc-gen-lile-server/templates"))
}

func main() {
	gen(os.Stdin, os.Stdout)
}

func gen(i io.Reader, o io.Writer) {
	input = i
	output = o

	// Force color output
	if runtime.GOOS != "windows" {
		color.NoColor = false
	}

	// Parse the incoming protobuf request
	req, err := parseReq(input)
	if err != nil {
		emitError(err)
		log.Fatal(err)
	}

	path := "./server"
	if req.Parameter != nil {
		path = *req.Parameter
	}

	files := []*plugin.CodeGeneratorResponse_File{}
	imports := []goimport{}

	for _, file := range req.ProtoFile {
		pkgParts := strings.Split(file.GetOptions().GetGoPackage(), "/")
		imports = append(imports, goimport{
			Package:   file.GetPackage(),
			GoPackage: file.GetOptions().GetGoPackage(),
			GoType:    pkgParts[len(pkgParts)-1],
		})

		// Only generate methods for this file/project
		if *file.Name != req.FileToGenerate[0] {
			if file.Options == nil || file.Options.GoPackage == nil {
				log.Fatalf("No go_package option defined for import %s", *file.Name)
			}

			continue
		}

		if file.Options == nil || file.Options.GoPackage == nil {
			log.Fatalf("No go_package option defined in %s", *file.Name)
		}

		pkgSplit := strings.Split(file.Options.GetGoPackage(), "/")

		for _, service := range file.Service {
			for _, method := range service.Method {
				gm := grpcMethod{
					ServiceName:     service.GetName(),
					GoPackage:       file.Options.GetGoPackage(),
					ImportName:      pkgSplit[len(pkgSplit)-1],
					Name:            method.GetName(),
					InType:          toGoType(imports, method.GetInputType()),
					OutType:         toGoType(imports, method.GetOutputType()),
					ClientStreaming: method.GetClientStreaming(),
					ServerStreaming: method.GetServerStreaming(),

					InputImport:  inputImport(imports, method),
					OutputImport: outputImport(imports, method),
				}

				f, err := generateMethod(path, gm)
				if err != nil {
					emitError(err)
					log.Fatal(err)
				}

				if len(f) > 0 {
					for _, v := range f {
						files = append(files, v)
					}
				}
			}
		}
	}

	emitFiles(files)
}

func DedupImports(imports ...string) string {
	data := sort.StringSlice(imports)
	sort.Sort(data)
	n := set.Uniq(data)
	imports = data[:n]

	return fmt.Sprintf("\t\"%s\"", strings.Join(imports, "\"\n\t\""))
}

func toGoType(imports []goimport, t string) string {
	t = strings.Trim(t, ".")
	for _, i := range imports {
		if strings.Contains(t, i.Package) {
			return strings.Replace(t, i.Package, i.GoType, 1)
		}
	}

	return t
}

func inputImport(imports []goimport, method *descriptor.MethodDescriptorProto) string {
	for _, i := range imports {
		if strings.Contains(method.GetInputType(), i.Package) {
			return i.GoPackage
		}
	}

	return ""
}

func outputImport(imports []goimport, method *descriptor.MethodDescriptorProto) string {
	for _, i := range imports {
		if strings.Contains(method.GetOutputType(), i.Package) {
			return i.GoPackage
		}
	}

	return ""
}

func generateMethod(basePath string, m grpcMethod) ([]*plugin.CodeGeneratorResponse_File, error) {
	path := filepath.Join(basePath, snaker.CamelToSnake(m.Name)+".go")
	test_path := filepath.Join(basePath, snaker.CamelToSnake(m.Name)+"_test.go")

	template := fmt.Sprintf("%s_%s",
		streamFromBool(m.ClientStreaming),
		streamFromBool(m.ServerStreaming),
	)

	// If the file exists then just skip the creation
	_, err := os.Stat(path)
	if err == nil {
		log.Printf("%s %s", color.YellowString("[Skipping]"), path)
		return nil, nil
	}

	files := []*plugin.CodeGeneratorResponse_File{}

	log.Printf("%s %s", color.GreenString("[Creating]"), path)
	f, err := render(path, template+".tmpl", m)
	if err != nil {
		return nil, err
	}

	files = append(files, f)

	log.Printf("%s %s", color.CyanString("[Creating test]"), test_path)
	f, err = render(test_path, template+"_test.tmpl", m)

	files = append(files, f)
	return files, err
}

func streamFromBool(streaming bool) string {
	if streaming {
		return "stream"
	}

	return "unary"
}

func render(path, tmpl string, m grpcMethod) (*plugin.CodeGeneratorResponse_File, error) {
	t := template.New(tmpl)

	funcMap := template.FuncMap{
		"dedupImports": DedupImports,
	}

	t = t.Funcs(funcMap)
	t, err := t.ParseFiles(filepath.Join(templatePath, tmpl))
	if err != nil {
		return nil, err
	}

	var out bytes.Buffer
	err = t.Execute(&out, m)
	if err != nil {
		return nil, err
	}

	b, err := format.Source(out.Bytes())
	if err != nil {
		return nil, err
	}

	str := string(b)

	return &plugin.CodeGeneratorResponse_File{
		Name:    &path,
		Content: &str,
	}, nil
}

func parseReq(r io.Reader) (*plugin.CodeGeneratorRequest, error) {
	input, err := ioutil.ReadAll(r)
	if err != nil {
		log.Fatalf("Failed to read code generator request: %v", err)
		return nil, err
	}

	req := new(plugin.CodeGeneratorRequest)
	if err = proto.Unmarshal(input, req); err != nil {
		log.Fatalf("Failed to unmarshal code generator request: %v", err)
		return nil, err
	}

	return req, nil
}

func emitFiles(files []*plugin.CodeGeneratorResponse_File) {
	emitResp(&plugin.CodeGeneratorResponse{File: files})
}

func emitError(err error) {
	emitResp(&plugin.CodeGeneratorResponse{Error: proto.String(err.Error())})
}

func emitResp(resp *plugin.CodeGeneratorResponse) {
	buf, err := proto.Marshal(resp)
	if err != nil {
		glog.Fatal(err)
	}
	if _, err := output.Write(buf); err != nil {
		glog.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package dnsimple

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/dnsimple/dnsimple-go/dnsimple"
	"github.com/juju/ratelimit"
	"github.com/rancher/external-dns/providers"
	"github.com/rancher/external-dns/utils"
	api "github.com/weppos/go-dnsimple/dnsimple"
)

type DNSimpleProvider struct {
	client    *api.Client
	client2   *dnsimple.Client
	accountID string
	root      string
	limiter   *ratelimit.Bucket
}

func init() {
	providers.RegisterProvider("dnsimple", &DNSimpleProvider{})
}

func (d *DNSimpleProvider) Init(rootDomainName string) error {
	var email, apiToken, oauthToken string

	if email = os.Getenv("DNSIMPLE_EMAIL"); len(email) == 0 {
		return fmt.Errorf("DNSIMPLE_EMAIL is not set")
	}

	if apiToken = os.Getenv("DNSIMPLE_TOKEN"); len(apiToken) == 0 {
		return fmt.Errorf("DNSIMPLE_TOKEN is not set")
	}

	if oauthToken = os.Getenv("DNSIMPLE_TOKEN"); len(oauthToken) == 0 {
		return fmt.Errorf("DNSIMPLE_TOKEN is not set")
	}

	d.root = utils.UnFqdn(rootDomainName)
	d.client = api.NewClient(apiToken, email)
	d.client2 = dnsimple.NewClient(dnsimple.NewOauthTokenCredentials(oauthToken))
	d.limiter = ratelimit.NewBucketWithRate(1.5, 5)

	whoamiResponse, err := d.client2.Identity.Whoami()
	if err != nil {
		return fmt.Errorf("DNSimple Authentication failed: %v", err)
	}
	if whoamiResponse.Data.Account == nil {
		return fmt.Errorf("DNSimple User tokens are not supported, use an Account token")
	}
	d.accountID = strconv.Itoa(whoamiResponse.Data.Account.ID)

	_, err = d.client2.Zones.GetZone(d.accountID, d.root)
	if err != nil {
		return fmt.Errorf("Failed to get zone for '%s': %v", d.root)
	}

	logrus.Infof("Configured %s with zone '%s'", d.GetName(), d.root)
	return nil
}

func (*DNSimpleProvider) GetName() string {
	return "DNSimple"
}

func (d *DNSimpleProvider) HealthCheck() error {
	d.limiter.Wait(1)
	_, err := d.client2.Identity.Whoami()
	return err
}

func (d *DNSimpleProvider) parseName(record utils.DnsRecord) string {
	name := strings.TrimSuffix(record.Fqdn, fmt.Sprintf(".%s.", d.root))
	return name
}

func (d *DNSimpleProvider) AddRecord(record utils.DnsRecord) error {
	name := d.parseName(record)
	for _, rec := range record.Records {
		recordInput := dnsimple.ZoneRecord{
			Name:    name,
			TTL:     record.TTL,
			Type:    record.Type,
			Content: rec,
		}
		d.limiter.Wait(1)
		_, err := d.client2.Zones.CreateRecord(d.accountID, d.root, recordInput)
		if err != nil {
			return fmt.Errorf("DNSimple API call has failed: %v", err)
		}
	}

	return nil
}

func (d *DNSimpleProvider) findRecords(record utils.DnsRecord) ([]api.Record, error) {
	var records []api.Record

	d.limiter.Wait(1)
	resp, _, err := d.client.Domains.ListRecords(d.root, "", "")
	if err != nil {
		return records, fmt.Errorf("DNSimple API call has failed: %v", err)
	}

	name := d.parseName(record)
	for _, rec := range resp {
		if rec.Name == name && rec.Type == record.Type {
			records = append(records, rec)
		}
	}

	return records, nil
}

func (d *DNSimpleProvider) UpdateRecord(record utils.DnsRecord) error {
	err := d.RemoveRecord(record)
	if err != nil {
		return err
	}

	return d.AddRecord(record)
}

func (d *DNSimpleProvider) RemoveRecord(record utils.DnsRecord) error {
	records, err := d.findRecords(record)
	if err != nil {
		return err
	}

	for _, rec := range records {
		d.limiter.Wait(1)
		_, err := d.client.Domains.DeleteRecord(d.root, rec.Id)
		if err != nil {
			return fmt.Errorf("DNSimple API call has failed: %v", err)
		}
	}

	return nil
}

func (d *DNSimpleProvider) GetRecords() ([]utils.DnsRecord, error) {
	var records []utils.DnsRecord

	d.limiter.Wait(1)
	recordResp, _, err := d.client.Domains.ListRecords(d.root, "", "")
	if err != nil {
		return records, fmt.Errorf("DNSimple API call has failed: %v", err)
	}

	recordMap := map[string]map[string][]string{}
	recordTTLs := map[string]map[string]int{}

	for _, rec := range recordResp {
		var fqdn string
		if rec.Name == "" {
			fqdn = d.root + "."
		} else {
			fqdn = fmt.Sprintf("%s.%s.", rec.Name, d.root)
		}

		recordTTLs[fqdn] = map[string]int{}
		recordTTLs[fqdn][rec.Type] = rec.TTL
		recordSet, exists := recordMap[fqdn]
		if exists {
			recordSlice, sliceExists := recordSet[rec.Type]
			if sliceExists {
				recordSlice = append(recordSlice, rec.Content)
				recordSet[rec.Type] = recordSlice
			} else {
				recordSet[rec.Type] = []string{rec.Content}
			}
		} else {
			recordMap[fqdn] = map[string][]string{}
			recordMap[fqdn][rec.Type] = []string{rec.Content}
		}
	}

	for fqdn, recordSet := range recordMap {
		for recordType, recordSlice := range recordSet {
			ttl := recordTTLs[fqdn][recordType]
			record := utils.DnsRecord{Fqdn: fqdn, Records: recordSlice, Type: recordType, TTL: ttl}
			records = append(records, record)
		}
	}
	return records, nil
}
<commit_msg>Update RemoveRecord() to use API v2<commit_after>package dnsimple

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/dnsimple/dnsimple-go/dnsimple"
	"github.com/juju/ratelimit"
	"github.com/rancher/external-dns/providers"
	"github.com/rancher/external-dns/utils"
	api "github.com/weppos/go-dnsimple/dnsimple"
)

type DNSimpleProvider struct {
	client    *api.Client
	client2   *dnsimple.Client
	accountID string
	root      string
	limiter   *ratelimit.Bucket
}

func init() {
	providers.RegisterProvider("dnsimple", &DNSimpleProvider{})
}

func (d *DNSimpleProvider) Init(rootDomainName string) error {
	var email, apiToken, oauthToken string

	if email = os.Getenv("DNSIMPLE_EMAIL"); len(email) == 0 {
		return fmt.Errorf("DNSIMPLE_EMAIL is not set")
	}

	if apiToken = os.Getenv("DNSIMPLE_TOKEN"); len(apiToken) == 0 {
		return fmt.Errorf("DNSIMPLE_TOKEN is not set")
	}

	if oauthToken = os.Getenv("DNSIMPLE_TOKEN"); len(oauthToken) == 0 {
		return fmt.Errorf("DNSIMPLE_TOKEN is not set")
	}

	d.root = utils.UnFqdn(rootDomainName)
	d.client = api.NewClient(apiToken, email)
	d.client2 = dnsimple.NewClient(dnsimple.NewOauthTokenCredentials(oauthToken))
	d.limiter = ratelimit.NewBucketWithRate(1.5, 5)

	whoamiResponse, err := d.client2.Identity.Whoami()
	if err != nil {
		return fmt.Errorf("DNSimple Authentication failed: %v", err)
	}
	if whoamiResponse.Data.Account == nil {
		return fmt.Errorf("DNSimple User tokens are not supported, use an Account token")
	}
	d.accountID = strconv.Itoa(whoamiResponse.Data.Account.ID)

	_, err = d.client2.Zones.GetZone(d.accountID, d.root)
	if err != nil {
		return fmt.Errorf("Failed to get zone for '%s': %v", d.root)
	}

	logrus.Infof("Configured %s with zone '%s'", d.GetName(), d.root)
	return nil
}

func (*DNSimpleProvider) GetName() string {
	return "DNSimple"
}

func (d *DNSimpleProvider) HealthCheck() error {
	d.limiter.Wait(1)
	_, err := d.client2.Identity.Whoami()
	return err
}

func (d *DNSimpleProvider) parseName(record utils.DnsRecord) string {
	name := strings.TrimSuffix(record.Fqdn, fmt.Sprintf(".%s.", d.root))
	return name
}

func (d *DNSimpleProvider) AddRecord(record utils.DnsRecord) error {
	name := d.parseName(record)
	for _, rec := range record.Records {
		recordInput := dnsimple.ZoneRecord{
			Name:    name,
			TTL:     record.TTL,
			Type:    record.Type,
			Content: rec,
		}
		d.limiter.Wait(1)
		_, err := d.client2.Zones.CreateRecord(d.accountID, d.root, recordInput)
		if err != nil {
			return fmt.Errorf("DNSimple API call has failed: %v", err)
		}
	}

	return nil
}

func (d *DNSimpleProvider) findRecords(record utils.DnsRecord) ([]api.Record, error) {
	var records []api.Record

	d.limiter.Wait(1)
	resp, _, err := d.client.Domains.ListRecords(d.root, "", "")
	if err != nil {
		return records, fmt.Errorf("DNSimple API call has failed: %v", err)
	}

	name := d.parseName(record)
	for _, rec := range resp {
		if rec.Name == name && rec.Type == record.Type {
			records = append(records, rec)
		}
	}

	return records, nil
}

func (d *DNSimpleProvider) UpdateRecord(record utils.DnsRecord) error {
	err := d.RemoveRecord(record)
	if err != nil {
		return err
	}

	return d.AddRecord(record)
}

func (d *DNSimpleProvider) RemoveRecord(record utils.DnsRecord) error {
	records, err := d.findRecords(record)
	if err != nil {
		return err
	}

	for _, rec := range records {
		d.limiter.Wait(1)
		_, err := d.client2.Zones.DeleteRecord(d.accountID, d.root, rec.Id)
		if err != nil {
			return fmt.Errorf("DNSimple API call has failed: %v", err)
		}
	}

	return nil
}

func (d *DNSimpleProvider) GetRecords() ([]utils.DnsRecord, error) {
	var records []utils.DnsRecord

	d.limiter.Wait(1)
	recordResp, _, err := d.client.Domains.ListRecords(d.root, "", "")
	if err != nil {
		return records, fmt.Errorf("DNSimple API call has failed: %v", err)
	}

	recordMap := map[string]map[string][]string{}
	recordTTLs := map[string]map[string]int{}

	for _, rec := range recordResp {
		var fqdn string
		if rec.Name == "" {
			fqdn = d.root + "."
		} else {
			fqdn = fmt.Sprintf("%s.%s.", rec.Name, d.root)
		}

		recordTTLs[fqdn] = map[string]int{}
		recordTTLs[fqdn][rec.Type] = rec.TTL
		recordSet, exists := recordMap[fqdn]
		if exists {
			recordSlice, sliceExists := recordSet[rec.Type]
			if sliceExists {
				recordSlice = append(recordSlice, rec.Content)
				recordSet[rec.Type] = recordSlice
			} else {
				recordSet[rec.Type] = []string{rec.Content}
			}
		} else {
			recordMap[fqdn] = map[string][]string{}
			recordMap[fqdn][rec.Type] = []string{rec.Content}
		}
	}

	for fqdn, recordSet := range recordMap {
		for recordType, recordSlice := range recordSet {
			ttl := recordTTLs[fqdn][recordType]
			record := utils.DnsRecord{Fqdn: fqdn, Records: recordSlice, Type: recordType, TTL: ttl}
			records = append(records, record)
		}
	}
	return records, nil
}
<|endoftext|>


<commit_before>// +build unit

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

package events

import (
	"fmt"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestToStatsdLabel(t *testing.T) {
	Convey("When converting a StatsEvent to a StatsD label", t, func() {

		// Spot check a few event types
		Convey("Known events should produce valid labels", func() {
			So(toStatsdLabel(
				StatsEvent{evttype: 2}), // 2 => TCPResolveFailed
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "tcp_input.tcp_resolve_failures"))
			So(toStatsdLabel(
				StatsEvent{evttype: 13}), // 13 => KafkaLookupFailed
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "kafka_output.framework_lookup_failures"))
			So(toStatsdLabel(
				StatsEvent{evttype: 19}), // 19 => AgentIPLookup
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "agent_poll.ip_lookups"))
			So(toStatsdLabel(
				StatsEvent{evttype: 27}), // 27 => RecordNoAgentStateAvailable
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "topic_sorter.no_agent_state_available"))
		})

		Convey("Unknown events should produce UNKNOWN label", func() {
			So(toStatsdLabel(StatsEvent{evttype: 9000}),
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "UNKNOWN"))
		})

		Convey("Events with a suffix should contain the suffix", func() {
			So(toStatsdLabel(StatsEvent{evttype: 9000, suffix: "bar"}),
				ShouldEqual, fmt.Sprintf("%s.%s.%s", statsdPrefix, "UNKNOWN", "bar"))
		})

		Convey("Events without a suffix should output the bare key", func() {
			So(toStatsdLabel(StatsEvent{evttype: 9000}),
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "UNKNOWN"))
		})
	})
}
<commit_msg>(fixup) use labels instead of integers<commit_after>// +build unit

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

package events

import (
	"fmt"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestToStatsdLabel(t *testing.T) {
	Convey("When converting a StatsEvent to a StatsD label", t, func() {

		// Spot check a few event types
		Convey("Known events should produce valid labels", func() {
			So(toStatsdLabel(
				StatsEvent{evttype: TCPResolveFailed}),
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "tcp_input.tcp_resolve_failures"))
			So(toStatsdLabel(
				StatsEvent{evttype: KafkaLookupFailed}),
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "kafka_output.framework_lookup_failures"))
			So(toStatsdLabel(
				StatsEvent{evttype: AgentIPLookup}),
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "agent_poll.ip_lookups"))
			So(toStatsdLabel(
				StatsEvent{evttype: RecordNoAgentStateAvailable}),
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "topic_sorter.no_agent_state_available"))
		})

		Convey("Unknown events should produce UNKNOWN label", func() {
			So(toStatsdLabel(StatsEvent{evttype: 9000}),
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "UNKNOWN"))
		})

		Convey("Events with a suffix should contain the suffix", func() {
			So(toStatsdLabel(StatsEvent{evttype: 9000, suffix: "bar"}),
				ShouldEqual, fmt.Sprintf("%s.%s.%s", statsdPrefix, "UNKNOWN", "bar"))
		})

		Convey("Events without a suffix should output the bare key", func() {
			So(toStatsdLabel(StatsEvent{evttype: 9000}),
				ShouldEqual, fmt.Sprintf("%s.%s", statsdPrefix, "UNKNOWN"))
		})
	})
}
<|endoftext|>