<commit_before>package config

import (
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"runtime"
	"strings"

	"github.com/juju/persistent-cookiejar"
	schemaform "gopkg.in/juju/environschema.v1/form"
	"gopkg.in/macaroon-bakery.v2/httpbakery"
	"gopkg.in/macaroon-bakery.v2/httpbakery/form"

	"github.com/lxc/lxd/client"
	"github.com/lxc/lxd/shared"
)

// Remote holds details for communication with a remote daemon.
type Remote struct {
	Addr     string `yaml:"addr"`
	AuthType string `yaml:"auth_type,omitempty"`
	Domain   string `yaml:"domain,omitempty"`
	Project  string `yaml:"project,omitempty"`
	Protocol string `yaml:"protocol,omitempty"`
	Public   bool   `yaml:"public"`
	Global   bool   `yaml:"-"`
	Static   bool   `yaml:"-"`
}

// ParseRemote splits remote and object.
func (c *Config) ParseRemote(raw string) (string, string, error) {
	result := strings.SplitN(raw, ":", 2)
	if len(result) == 1 {
		return c.DefaultRemote, raw, nil
	}

	_, ok := c.Remotes[result[0]]
	if !ok {
		// Attempt to play nice with snapshots containing ":"
		if shared.IsSnapshot(raw) && shared.IsSnapshot(result[0]) {
			return c.DefaultRemote, raw, nil
		}

		return "", "", fmt.Errorf("The remote \"%s\" doesn't exist", result[0])
	}

	return result[0], result[1], nil
}

// GetInstanceServer returns a InstanceServer struct for the remote.
func (c *Config) GetInstanceServer(name string) (lxd.InstanceServer, error) {
	// Handle "local" on non-Linux
	if name == "local" && runtime.GOOS != "linux" {
		return nil, ErrNotLinux
	}

	// Get the remote
	remote, ok := c.Remotes[name]
	if !ok {
		return nil, fmt.Errorf("The remote \"%s\" doesn't exist", name)
	}

	// Quick checks.
	if remote.Public || remote.Protocol == "simplestreams" {
		return nil, fmt.Errorf("The remote isn't a private LXD server")
	}

	// Get connection arguments
	args, err := c.getConnectionArgs(name)
	if err != nil {
		return nil, err
	}

	// Unix socket
	if strings.HasPrefix(remote.Addr, "unix:") {
		d, err := lxd.ConnectLXDUnix(strings.TrimPrefix(strings.TrimPrefix(remote.Addr, "unix:"), "//"), args)
		if err != nil {
			return nil, err
		}

		if remote.Project != "" && remote.Project != "default" {
			d = d.UseProject(remote.Project)
		}

		if c.ProjectOverride != "" {
			d = d.UseProject(c.ProjectOverride)
		}

		return d, nil
	}

	// HTTPs
	if remote.AuthType != "candid" && (args.TLSClientCert == "" || args.TLSClientKey == "") {
		return nil, fmt.Errorf("Missing TLS client certificate and key")
	}

	d, err := lxd.ConnectLXD(remote.Addr, args)
	if err != nil {
		return nil, err
	}

	if remote.Project != "" && remote.Project != "default" {
		d = d.UseProject(remote.Project)
	}

	if c.ProjectOverride != "" {
		d = d.UseProject(c.ProjectOverride)
	}

	return d, nil
}

// GetImageServer returns a ImageServer struct for the remote.
func (c *Config) GetImageServer(name string) (lxd.ImageServer, error) {
	// Handle "local" on non-Linux
	if name == "local" && runtime.GOOS != "linux" {
		return nil, ErrNotLinux
	}

	// Get the remote
	remote, ok := c.Remotes[name]
	if !ok {
		return nil, fmt.Errorf("The remote \"%s\" doesn't exist", name)
	}

	// Get connection arguments
	args, err := c.getConnectionArgs(name)
	if err != nil {
		return nil, err
	}

	// Unix socket
	if strings.HasPrefix(remote.Addr, "unix:") {
		d, err := lxd.ConnectLXDUnix(strings.TrimPrefix(strings.TrimPrefix(remote.Addr, "unix:"), "//"), args)
		if err != nil {
			return nil, err
		}

		if remote.Project != "" && remote.Project != "default" {
			d = d.UseProject(remote.Project)
		}

		if c.ProjectOverride != "" {
			d = d.UseProject(c.ProjectOverride)
		}

		return d, nil
	}

	// HTTPs (simplestreams)
	if remote.Protocol == "simplestreams" {
		d, err := lxd.ConnectSimpleStreams(remote.Addr, args)
		if err != nil {
			return nil, err
		}

		return d, nil
	}

	// HTTPs (public LXD)
	if remote.Public {
		d, err := lxd.ConnectPublicLXD(remote.Addr, args)
		if err != nil {
			return nil, err
		}

		return d, nil
	}

	// HTTPs (private LXD)
	d, err := lxd.ConnectLXD(remote.Addr, args)
	if err != nil {
		return nil, err
	}

	if remote.Project != "" && remote.Project != "default" {
		d = d.UseProject(remote.Project)
	}

	if c.ProjectOverride != "" {
		d = d.UseProject(c.ProjectOverride)
	}

	return d, nil
}

func (c *Config) getConnectionArgs(name string) (*lxd.ConnectionArgs, error) {
	remote := c.Remotes[name]
	args := lxd.ConnectionArgs{
		UserAgent: c.UserAgent,
		AuthType:  remote.AuthType,
	}

	if args.AuthType == "candid" {
		args.AuthInteractor = []httpbakery.Interactor{
			form.Interactor{Filler: schemaform.IOFiller{}},
			httpbakery.WebBrowserInteractor{
				OpenWebBrowser: func(uri *url.URL) error {
					if remote.Domain != "" {
						query := uri.Query()
						query.Set("domain", remote.Domain)
						uri.RawQuery = query.Encode()
					}

					return httpbakery.OpenWebBrowser(uri)
				},
			},
		}

		if c.cookieJars == nil || c.cookieJars[name] == nil {
			if !shared.PathExists(c.ConfigPath("jars")) {
				err := os.MkdirAll(c.ConfigPath("jars"), 0700)
				if err != nil {
					return nil, err
				}
			}

			if !shared.PathExists(c.CookiesPath(name)) {
				if shared.PathExists(c.ConfigPath("cookies")) {
					err := shared.FileCopy(c.ConfigPath("cookies"), c.CookiesPath(name))
					if err != nil {
						return nil, err
					}
				}
			}

			jar, err := cookiejar.New(
				&cookiejar.Options{
					Filename: c.CookiesPath(name),
				})
			if err != nil {
				return nil, err
			}

			if c.cookieJars == nil {
				c.cookieJars = map[string]*cookiejar.Jar{}
			}

			c.cookieJars[name] = jar
		}

		args.CookieJar = c.cookieJars[name]
	}

	// Stop here if no TLS involved
	if strings.HasPrefix(remote.Addr, "unix:") {
		return &args, nil
	}

	// Server certificate
	if shared.PathExists(c.ServerCertPath(name)) {
		content, err := ioutil.ReadFile(c.ServerCertPath(name))
		if err != nil {
			return nil, err
		}

		args.TLSServerCert = string(content)
	}

	// Stop here if no client certificate involved
	if remote.Protocol == "simplestreams" || remote.AuthType == "candid" {
		return &args, nil
	}

	// Client certificate
	if shared.PathExists(c.ConfigPath("client.crt")) {
		content, err := ioutil.ReadFile(c.ConfigPath("client.crt"))
		if err != nil {
			return nil, err
		}

		args.TLSClientCert = string(content)
	}

	// Client CA
	if shared.PathExists(c.ConfigPath("client.ca")) {
		content, err := ioutil.ReadFile(c.ConfigPath("client.ca"))
		if err != nil {
			return nil, err
		}

		args.TLSCA = string(content)
	}

	// Client key
	if shared.PathExists(c.ConfigPath("client.key")) {
		content, err := ioutil.ReadFile(c.ConfigPath("client.key"))
		if err != nil {
			return nil, err
		}

		pemKey, _ := pem.Decode(content)
		// Golang has deprecated all methods relating to PEM encryption due to a vulnerability.
		// However, the weakness does not make PEM unsafe for our purposes as it pertains to password protection on the
		// key file (client.key is only readable to the user in any case), so we'll ignore deprecation.
		if x509.IsEncryptedPEMBlock(pemKey) { //nolint:staticcheck
			if c.PromptPassword == nil {
				return nil, fmt.Errorf("Private key is password protected and no helper was configured")
			}

			password, err := c.PromptPassword("client.crt")
			if err != nil {
				return nil, err
			}

			derKey, err := x509.DecryptPEMBlock(pemKey, []byte(password)) //nolint:staticcheck
			if err != nil {
				return nil, err
			}

			content = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: derKey})
		}

		args.TLSClientKey = string(content)
	}

	return &args, nil
}
<commit_msg>lxc: Move to bakery.v3<commit_after>package config

import (
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"runtime"
	"strings"

	"github.com/juju/persistent-cookiejar"
	schemaform "gopkg.in/juju/environschema.v1/form"
	"gopkg.in/macaroon-bakery.v3/httpbakery"
	"gopkg.in/macaroon-bakery.v3/httpbakery/form"

	"github.com/lxc/lxd/client"
	"github.com/lxc/lxd/shared"
)

// Remote holds details for communication with a remote daemon.
type Remote struct {
	Addr     string `yaml:"addr"`
	AuthType string `yaml:"auth_type,omitempty"`
	Domain   string `yaml:"domain,omitempty"`
	Project  string `yaml:"project,omitempty"`
	Protocol string `yaml:"protocol,omitempty"`
	Public   bool   `yaml:"public"`
	Global   bool   `yaml:"-"`
	Static   bool   `yaml:"-"`
}

// ParseRemote splits remote and object.
func (c *Config) ParseRemote(raw string) (string, string, error) {
	result := strings.SplitN(raw, ":", 2)
	if len(result) == 1 {
		return c.DefaultRemote, raw, nil
	}

	_, ok := c.Remotes[result[0]]
	if !ok {
		// Attempt to play nice with snapshots containing ":"
		if shared.IsSnapshot(raw) && shared.IsSnapshot(result[0]) {
			return c.DefaultRemote, raw, nil
		}

		return "", "", fmt.Errorf("The remote \"%s\" doesn't exist", result[0])
	}

	return result[0], result[1], nil
}

// GetInstanceServer returns a InstanceServer struct for the remote.
func (c *Config) GetInstanceServer(name string) (lxd.InstanceServer, error) {
	// Handle "local" on non-Linux
	if name == "local" && runtime.GOOS != "linux" {
		return nil, ErrNotLinux
	}

	// Get the remote
	remote, ok := c.Remotes[name]
	if !ok {
		return nil, fmt.Errorf("The remote \"%s\" doesn't exist", name)
	}

	// Quick checks.
	if remote.Public || remote.Protocol == "simplestreams" {
		return nil, fmt.Errorf("The remote isn't a private LXD server")
	}

	// Get connection arguments
	args, err := c.getConnectionArgs(name)
	if err != nil {
		return nil, err
	}

	// Unix socket
	if strings.HasPrefix(remote.Addr, "unix:") {
		d, err := lxd.ConnectLXDUnix(strings.TrimPrefix(strings.TrimPrefix(remote.Addr, "unix:"), "//"), args)
		if err != nil {
			return nil, err
		}

		if remote.Project != "" && remote.Project != "default" {
			d = d.UseProject(remote.Project)
		}

		if c.ProjectOverride != "" {
			d = d.UseProject(c.ProjectOverride)
		}

		return d, nil
	}

	// HTTPs
	if remote.AuthType != "candid" && (args.TLSClientCert == "" || args.TLSClientKey == "") {
		return nil, fmt.Errorf("Missing TLS client certificate and key")
	}

	d, err := lxd.ConnectLXD(remote.Addr, args)
	if err != nil {
		return nil, err
	}

	if remote.Project != "" && remote.Project != "default" {
		d = d.UseProject(remote.Project)
	}

	if c.ProjectOverride != "" {
		d = d.UseProject(c.ProjectOverride)
	}

	return d, nil
}

// GetImageServer returns a ImageServer struct for the remote.
func (c *Config) GetImageServer(name string) (lxd.ImageServer, error) {
	// Handle "local" on non-Linux
	if name == "local" && runtime.GOOS != "linux" {
		return nil, ErrNotLinux
	}

	// Get the remote
	remote, ok := c.Remotes[name]
	if !ok {
		return nil, fmt.Errorf("The remote \"%s\" doesn't exist", name)
	}

	// Get connection arguments
	args, err := c.getConnectionArgs(name)
	if err != nil {
		return nil, err
	}

	// Unix socket
	if strings.HasPrefix(remote.Addr, "unix:") {
		d, err := lxd.ConnectLXDUnix(strings.TrimPrefix(strings.TrimPrefix(remote.Addr, "unix:"), "//"), args)
		if err != nil {
			return nil, err
		}

		if remote.Project != "" && remote.Project != "default" {
			d = d.UseProject(remote.Project)
		}

		if c.ProjectOverride != "" {
			d = d.UseProject(c.ProjectOverride)
		}

		return d, nil
	}

	// HTTPs (simplestreams)
	if remote.Protocol == "simplestreams" {
		d, err := lxd.ConnectSimpleStreams(remote.Addr, args)
		if err != nil {
			return nil, err
		}

		return d, nil
	}

	// HTTPs (public LXD)
	if remote.Public {
		d, err := lxd.ConnectPublicLXD(remote.Addr, args)
		if err != nil {
			return nil, err
		}

		return d, nil
	}

	// HTTPs (private LXD)
	d, err := lxd.ConnectLXD(remote.Addr, args)
	if err != nil {
		return nil, err
	}

	if remote.Project != "" && remote.Project != "default" {
		d = d.UseProject(remote.Project)
	}

	if c.ProjectOverride != "" {
		d = d.UseProject(c.ProjectOverride)
	}

	return d, nil
}

func (c *Config) getConnectionArgs(name string) (*lxd.ConnectionArgs, error) {
	remote := c.Remotes[name]
	args := lxd.ConnectionArgs{
		UserAgent: c.UserAgent,
		AuthType:  remote.AuthType,
	}

	if args.AuthType == "candid" {
		args.AuthInteractor = []httpbakery.Interactor{
			form.Interactor{Filler: schemaform.IOFiller{}},
			httpbakery.WebBrowserInteractor{
				OpenWebBrowser: func(uri *url.URL) error {
					if remote.Domain != "" {
						query := uri.Query()
						query.Set("domain", remote.Domain)
						uri.RawQuery = query.Encode()
					}

					return httpbakery.OpenWebBrowser(uri)
				},
			},
		}

		if c.cookieJars == nil || c.cookieJars[name] == nil {
			if !shared.PathExists(c.ConfigPath("jars")) {
				err := os.MkdirAll(c.ConfigPath("jars"), 0700)
				if err != nil {
					return nil, err
				}
			}

			if !shared.PathExists(c.CookiesPath(name)) {
				if shared.PathExists(c.ConfigPath("cookies")) {
					err := shared.FileCopy(c.ConfigPath("cookies"), c.CookiesPath(name))
					if err != nil {
						return nil, err
					}
				}
			}

			jar, err := cookiejar.New(
				&cookiejar.Options{
					Filename: c.CookiesPath(name),
				})
			if err != nil {
				return nil, err
			}

			if c.cookieJars == nil {
				c.cookieJars = map[string]*cookiejar.Jar{}
			}

			c.cookieJars[name] = jar
		}

		args.CookieJar = c.cookieJars[name]
	}

	// Stop here if no TLS involved
	if strings.HasPrefix(remote.Addr, "unix:") {
		return &args, nil
	}

	// Server certificate
	if shared.PathExists(c.ServerCertPath(name)) {
		content, err := ioutil.ReadFile(c.ServerCertPath(name))
		if err != nil {
			return nil, err
		}

		args.TLSServerCert = string(content)
	}

	// Stop here if no client certificate involved
	if remote.Protocol == "simplestreams" || remote.AuthType == "candid" {
		return &args, nil
	}

	// Client certificate
	if shared.PathExists(c.ConfigPath("client.crt")) {
		content, err := ioutil.ReadFile(c.ConfigPath("client.crt"))
		if err != nil {
			return nil, err
		}

		args.TLSClientCert = string(content)
	}

	// Client CA
	if shared.PathExists(c.ConfigPath("client.ca")) {
		content, err := ioutil.ReadFile(c.ConfigPath("client.ca"))
		if err != nil {
			return nil, err
		}

		args.TLSCA = string(content)
	}

	// Client key
	if shared.PathExists(c.ConfigPath("client.key")) {
		content, err := ioutil.ReadFile(c.ConfigPath("client.key"))
		if err != nil {
			return nil, err
		}

		pemKey, _ := pem.Decode(content)
		// Golang has deprecated all methods relating to PEM encryption due to a vulnerability.
		// However, the weakness does not make PEM unsafe for our purposes as it pertains to password protection on the
		// key file (client.key is only readable to the user in any case), so we'll ignore deprecation.
		if x509.IsEncryptedPEMBlock(pemKey) { //nolint:staticcheck
			if c.PromptPassword == nil {
				return nil, fmt.Errorf("Private key is password protected and no helper was configured")
			}

			password, err := c.PromptPassword("client.crt")
			if err != nil {
				return nil, err
			}

			derKey, err := x509.DecryptPEMBlock(pemKey, []byte(password)) //nolint:staticcheck
			if err != nil {
				return nil, err
			}

			content = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: derKey})
		}

		args.TLSClientKey = string(content)
	}

	return &args, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"sync"

	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/instance/instancetype"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/response"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
)

func coalesceErrors(errors map[string]error) error {
	if len(errors) == 0 {
		return nil
	}

	errorMsg := "The following instances failed to update state:\n"
	for instName, err := range errors {
		errorMsg += fmt.Sprintf(" - Instance: %s: %v\n", instName, err)
	}

	return fmt.Errorf("%s", errorMsg)
}

// Update all instance states
func instancesPut(d *Daemon, r *http.Request) response.Response {
	project := projectParam(r)

	c, err := instance.LoadNodeAll(d.State(), instancetype.Any)
	if err != nil {
		return response.BadRequest(err)
	}

	req := api.InstancesPut{}
	req.State = &api.InstanceStatePut{}
	req.State.Timeout = -1
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return response.BadRequest(err)
	}

	action := shared.InstanceAction(req.State.Action)

	var names []string
	var instances []instance.Instance
	for _, inst := range c {
		if inst.Project() != project {
			continue
		}

		switch action {
		case shared.Freeze:
			if !inst.IsRunning() {
				continue
			}
		case shared.Restart:
			if !inst.IsRunning() {
				continue
			}
		case shared.Start:
			if inst.IsRunning() {
				continue
			}
		case shared.Stop:
			if !inst.IsRunning() {
				continue
			}
		case shared.Unfreeze:
			if inst.IsRunning() {
				continue
			}
		}

		instances = append(instances, inst)
		names = append(names, inst.Name())
	}

	// Don't mess with containers while in setup mode
	<-d.readyChan

	// Determine operation type.
	opType, err := instanceActionToOptype(req.State.Action)
	if err != nil {
		return response.BadRequest(err)
	}

	// Batch the changes.
	do := func(op *operations.Operation) error {
		failures := map[string]error{}
		failuresLock := sync.Mutex{}
		wgAction := sync.WaitGroup{}

		for _, inst := range instances {
			wgAction.Add(1)
			go func(inst instance.Instance) {
				defer wgAction.Done()

				err := doInstanceStatePut(inst, *req.State)
				if err != nil {
					failuresLock.Lock()
					failures[inst.Name()] = err
					failuresLock.Unlock()
				}
			}(inst)
		}

		wgAction.Wait()
		return coalesceErrors(failures)
	}

	resources := map[string][]string{}
	resources["instances"] = names
	op, err := operations.OperationCreate(d.State(), project, operations.OperationClassTask, opType, resources, nil, do, nil, nil)
	if err != nil {
		return response.InternalError(err)
	}

	return operations.OperationResponse(op)
}
<commit_msg>lxd/instances_put: Properly handle clusters<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"sync"

	"github.com/lxc/lxd/lxd/cluster"
	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/instance/instancetype"
	"github.com/lxc/lxd/lxd/node"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/response"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
)

func coalesceErrors(local bool, errors map[string]error) error {
	if len(errors) == 0 {
		return nil
	}

	var errorMsg string
	if local {
		errorMsg += "The following instances failed to update state:\n"
	}

	for instName, err := range errors {
		if local {
			errorMsg += fmt.Sprintf(" - Instance: %s: %v\n", instName, err)
		} else {
			errorMsg += strings.TrimSpace(fmt.Sprintf("%v\n", err))
		}
	}

	return fmt.Errorf("%s", errorMsg)
}

// Update all instance states
func instancesPut(d *Daemon, r *http.Request) response.Response {
	project := projectParam(r)

	// Don't mess with containers while in setup mode
	<-d.readyChan

	c, err := instance.LoadNodeAll(d.State(), instancetype.Any)
	if err != nil {
		return response.BadRequest(err)
	}

	req := api.InstancesPut{}
	req.State = &api.InstanceStatePut{}
	req.State.Timeout = -1
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return response.BadRequest(err)
	}

	action := shared.InstanceAction(req.State.Action)

	var names []string
	var instances []instance.Instance
	for _, inst := range c {
		if inst.Project() != project {
			continue
		}

		switch action {
		case shared.Freeze:
			if !inst.IsRunning() {
				continue
			}
		case shared.Restart:
			if !inst.IsRunning() {
				continue
			}
		case shared.Start:
			if inst.IsRunning() {
				continue
			}
		case shared.Stop:
			if !inst.IsRunning() {
				continue
			}
		case shared.Unfreeze:
			if inst.IsRunning() {
				continue
			}
		}

		instances = append(instances, inst)
		names = append(names, inst.Name())
	}

	// Determine operation type.
	opType, err := instanceActionToOptype(req.State.Action)
	if err != nil {
		return response.BadRequest(err)
	}

	// Batch the changes.
	do := func(op *operations.Operation) error {
		localAction := func(local bool) error {
			failures := map[string]error{}
			failuresLock := sync.Mutex{}
			wgAction := sync.WaitGroup{}

			for _, inst := range instances {
				wgAction.Add(1)
				go func(inst instance.Instance) {
					defer wgAction.Done()

					err := doInstanceStatePut(inst, *req.State)
					if err != nil {
						failuresLock.Lock()
						failures[inst.Name()] = err
						failuresLock.Unlock()
					}
				}(inst)
			}

			wgAction.Wait()
			return coalesceErrors(local, failures)
		}

		// Only return the local data if asked by cluster member.
		if isClusterNotification(r) {
			return localAction(false)
		}

		// Check if clustered.
		clustered, err := cluster.Enabled(d.db)
		if err != nil {
			return err
		}

		// If not clustered, return the local data.
		if !clustered {
			return localAction(true)
		}

		// Get all online nodes.
		var nodes []db.NodeInfo
		err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
			var err error

			nodes, err = tx.GetNodes()
			if err != nil {
				return err
			}

			return nil
		})
		if err != nil {
			return err
		}

		// Get local address.
		localAddress, err := node.HTTPSAddress(d.db)
		if err != nil {
			return err
		}

		// Record the results.
		failures := map[string]error{}
		failuresLock := sync.Mutex{}
		wgAction := sync.WaitGroup{}

		cert := d.endpoints.NetworkCert()
		for _, node := range nodes {
			wgAction.Add(1)
			go func(node db.NodeInfo) {
				defer wgAction.Done()

				// Special handling for the local node.
				if node.Address == localAddress {
					err := localAction(false)
					if err != nil {
						failuresLock.Lock()
						failures[node.Name] = err
						failuresLock.Unlock()
					}
					return
				}

				// Connect to the remote server.
				client, err := cluster.Connect(node.Address, cert, true)
				if err != nil {
					failuresLock.Lock()
					failures[node.Name] = err
					failuresLock.Unlock()
					return
				}
				client = client.UseProject(project)

				// Perform the action.
				op, err := client.UpdateInstances(req, "")
				if err != nil {
					failuresLock.Lock()
					failures[node.Name] = err
					failuresLock.Unlock()
					return
				}

				err = op.Wait()
				if err != nil {
					failuresLock.Lock()
					failures[node.Name] = err
					failuresLock.Unlock()
					return
				}
			}(node)
		}

		wgAction.Wait()
		return coalesceErrors(true, failures)
	}

	resources := map[string][]string{}
	resources["instances"] = names
	op, err := operations.OperationCreate(d.State(), project, operations.OperationClassTask, opType, resources, nil, do, nil, nil)
	if err != nil {
		return response.InternalError(err)
	}

	return operations.OperationResponse(op)
}
<|endoftext|>


<commit_before>package controllerlib

import (
	"fmt"
)

type UpdateRequest struct {
	MyName 	string
	Type	string
	XPos	int
	YPos	int
}

var XSize = 25
var YSize = 25

func GetGridCode(r UpdateRequest) string {
	switch r.Type {
		case "Empty":
			return " "
		case "Robber":
			return "R"
		case "Cop":
			return "C"
		default:
			return "?"
	}
}

func WhereAmI(GameState [][]UpdateRequest, me UpdateRequest) (int, int) {
	fmt.Println("In controllerlib.WhereAmI")
        for i := range GameState {
                for j := range GameState[i] {
			fmt.Println("Comparing: ", me.MyName, GameState[i][jj].MyName)
			if me.MyName == GameState[i][j].MyName {
				return GameState[i][j].XPos, GameState[i][j].YPos
			}
                }
        }
	return -1, -1
}
<commit_msg>syntax<commit_after>package controllerlib

import (
	"fmt"
)

type UpdateRequest struct {
	MyName 	string
	Type	string
	XPos	int
	YPos	int
}

var XSize = 25
var YSize = 25

func GetGridCode(r UpdateRequest) string {
	switch r.Type {
		case "Empty":
			return " "
		case "Robber":
			return "R"
		case "Cop":
			return "C"
		default:
			return "?"
	}
}

func WhereAmI(GameState [][]UpdateRequest, me UpdateRequest) (int, int) {
	fmt.Println("In controllerlib.WhereAmI")
        for i := range GameState {
                for j := range GameState[i] {
			fmt.Println("Comparing: ", me.MyName, GameState[i][j].MyName)
			if me.MyName == GameState[i][j].MyName {
				return GameState[i][j].XPos, GameState[i][j].YPos
			}
                }
        }
	return -1, -1
}
<|endoftext|>


<commit_before>package markdown

import (
	"fmt"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/brandur/sorg"
	"github.com/russross/blackfriday"
)

var renderFuncs = []func(string, *RenderOptions) string{
	// pre-transformations
	transformFigures,
	transformHeaders,

	// main Markdown rendering
	renderMarkdown,

	// post-transformations
	transformCodeWithLanguagePrefix,
	transformSections,
	transformFootnotes,
	transformImagesToAbsoluteURLs,
	transformImagesToRetina,
}

// RenderOptions describes a rendering operation to be customized.
type RenderOptions struct {
	// AbsoluteURLs replaces the sources of any images that pointed to relative
	// URLs with absolute URLs.
	AbsoluteURLs bool

	// NoHeaderLinks disables automatic permalinks on headers.
	NoHeaderLinks bool

	// NoRetina disables the Retina.JS rendering attributes.
	NoRetina bool
}

// Render a Markdown string to HTML while applying all custom project-specific
// filters including footnotes and stable header links.
func Render(source string, options *RenderOptions) string {
	for _, f := range renderFuncs {
		source = f(source, options)
	}
	return source
}

// Look for any whitespace between HTML tags.
var whitespaceRE = regexp.MustCompile(`>\s+<`)

// Simply collapses certain HTML snippets by removing newlines and whitespace
// between tags. This is mainline used to make HTML snippets readable as
// constants, but then to make them fit a little more nicely into the rendered
// markup.
func collapseHTML(html string) string {
	html = strings.Replace(html, "\n", "", -1)
	html = whitespaceRE.ReplaceAllString(html, "><")
	return html
}

func renderMarkdown(source string, options *RenderOptions) string {
	htmlFlags := 0
	htmlFlags |= blackfriday.HTML_SMARTYPANTS_DASHES
	htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
	htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
	htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
	htmlFlags |= blackfriday.HTML_USE_XHTML

	extensions := 0
	extensions |= blackfriday.EXTENSION_AUTO_HEADER_IDS
	extensions |= blackfriday.EXTENSION_AUTOLINK
	extensions |= blackfriday.EXTENSION_FENCED_CODE
	extensions |= blackfriday.EXTENSION_HEADER_IDS
	extensions |= blackfriday.EXTENSION_LAX_HTML_BLOCKS
	extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
	extensions |= blackfriday.EXTENSION_TABLES
	extensions |= blackfriday.EXTENSION_SPACE_HEADERS
	extensions |= blackfriday.EXTENSION_STRIKETHROUGH

	renderer := blackfriday.HtmlRenderer(htmlFlags, "", "")
	return string(blackfriday.Markdown([]byte(source), renderer, extensions))
}

var codeRE = regexp.MustCompile(`<code class="(\w+)">`)

func transformCodeWithLanguagePrefix(source string, options *RenderOptions) string {
	return codeRE.ReplaceAllString(source, `<code class="language-$1">`)
}

const openSectionHTML = `<section class="%s">`
const closeSectionHTML = `</section>`

var openSectionRE = regexp.MustCompile(`(<p>)?!section class=("|“)(.*)("|”)(</p>)?`)
var closeSectionRE = regexp.MustCompile(`(<p>)?!/section(</p>)?`)

func transformSections(source string, options *RenderOptions) string {
	out := source

	out = openSectionRE.ReplaceAllStringFunc(out, func(div string) string {
		matches := openSectionRE.FindStringSubmatch(div)
		class := matches[3]
		return fmt.Sprintf(openSectionHTML, class)
	})
	out = closeSectionRE.ReplaceAllString(out, closeSectionHTML)

	return out
}

const figureHTML = `

%s

`

var figureRE = regexp.MustCompile(`!fig src="(.*)" caption="(.*)"`)

func transformFigures(source string, options *RenderOptions) string {
	return figureRE.ReplaceAllStringFunc(source, func(figure string) string {
		matches := figureRE.FindStringSubmatch(figure)
		src := matches[1]

		link := src
		extension := filepath.Ext(link)
		if extension != "" && extension != ".svg" {
			link = link[0:len(src)-len(extension)] + "@2x" + extension
		}

		// This is a really ugly hack in that it relies on the regex above
		// being greedy about quotes, but meh, I'll make it better when there's
		// a good reason to.
		caption := strings.Replace(matches[2], `\"`, `"`, -1)

		return fmt.Sprintf(figureHTML, link, src, caption)
	})
}

// A layer that we wrap the entire footer section in for styling purposes.
const footerWrapper = `

  %s

`

// HTML for a footnote within the document.
const footnoteAnchorHTML = `

  %s

`

// HTML for a reference to a footnote within the document.
const footnoteReferenceHTML = `

  %s

`

// Look for the section the section at the bottom of the page that looks like
//
[1] (the paragraph tag is there because Markdown will have already
// wrapped it by this point).
var footerRE = regexp.MustCompile(`(?ms:^<p>\[\d+\].*)`)

// Look for a single footnote within the footer.
var footnoteRE = regexp.MustCompile(`\[(\d+)\](\s+.*)`)

// Note that this must be a post-transform filter. If it wasn't, our Markdown
// renderer would not render the Markdown inside the footnotes layer because it
// would already be wrapped in HTML.
func transformFootnotes(source string, options *RenderOptions) string {
	footer := footerRE.FindString(source)

	if footer != "" {
		// remove the footer for now
		source = strings.Replace(source, footer, "", 1)

		footer = footnoteRE.ReplaceAllStringFunc(footer, func(footnote string) string {
			// first create a footnote with an anchor that links can target
			matches := footnoteRE.FindStringSubmatch(footnote)
			number := matches[1]
			anchor := fmt.Sprintf(footnoteAnchorHTML, number, number, number) + matches[2]

			// then replace all references in the body to this footnote
			referenceRE := regexp.MustCompile(fmt.Sprintf(`\[%s\]`, number))
			reference := fmt.Sprintf(footnoteReferenceHTML, number, number, number)
			source = referenceRE.ReplaceAllString(source, collapseHTML(reference))

			return collapseHTML(anchor)
		})

		// and wrap the whole footer section in a layer for styling
		footer = fmt.Sprintf(footerWrapper, footer)
		source = source + footer
	}

	return source
}

const headerHTML = `
<h%v id="%s">
  %s
</h%v>
`

const headerHTMLNoLink = `
<h%v>%s</h%v>
`

// Matches one of the following:
//
//   # header
//   # header (#header-id)
//
// For now, only match ## or more so as to remove code comments from
// matches. We need a better way of doing that though.
var headerRE = regexp.MustCompile(`(?m:^(#{2,})\s+(.*?)(\s+\(#(.*)\))?$)`)

func transformHeaders(source string, options *RenderOptions) string {
	headerNum := 0

	// Tracks previously assigned headers so that we can detect duplicates.
	headers := make(map[string]int)

	source = headerRE.ReplaceAllStringFunc(source, func(header string) string {
		matches := headerRE.FindStringSubmatch(header)

		level := len(matches[1])
		title := matches[2]
		id := matches[4]

		var newID string

		if id == "" {
			// Header with no name, assign a prefixed number.
			newID = fmt.Sprintf("section-%v", headerNum)

		} else {
			occurrence, ok := headers[id]

			if ok {
				// Give duplicate IDs a suffix.
				newID = fmt.Sprintf("%s-%d", id, occurrence)
				headers[id]++

			} else {
				// Otherwise this is the first such ID we've seen.
				newID = id
				headers[id] = 1
			}
		}

		headerNum++

		// Replace the Markdown header with HTML equivalent.
		if options != nil && options.NoHeaderLinks {
			return collapseHTML(fmt.Sprintf(headerHTMLNoLink, level, title, level))
		}

		return collapseHTML(fmt.Sprintf(headerHTML, level, newID, newID, title, level))

	})

	return source
}

var imageRE = regexp.MustCompile(`<img src="(.+)"`)

func transformImagesToRetina(source string, options *RenderOptions) string {
	if options != nil && options.NoRetina {
		return source
	}

	// The basic idea here is that we give every image a `retina-rjs` tag so
	// that Retina.JS will replace it with a retina version *except* if the
	// image is an SVG. These are resolution agnostic and don't need replacing.
	return imageRE.ReplaceAllStringFunc(source, func(img string) string {
		matches := imageRE.FindStringSubmatch(img)
		if filepath.Ext(matches[1]) == ".svg" {
			return fmt.Sprintf(`<img src="%s"`, matches[1])
		}
		return fmt.Sprintf(`<img data-rjs="2" src="%s"`, matches[1])
	})
}

var relativeImageRE = regexp.MustCompile(`<img src="/`)

func transformImagesToAbsoluteURLs(source string, options *RenderOptions) string {
	if options == nil || !options.AbsoluteURLs {
		return source
	}

	return relativeImageRE.ReplaceAllStringFunc(source, func(img string) string {
		return `<img src="` + sorg.AbsoluteURL + `/`
	})
}
<commit_msg>Don't need regex to search for footnote references<commit_after>package markdown

import (
	"fmt"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/brandur/sorg"
	"github.com/russross/blackfriday"
)

var renderFuncs = []func(string, *RenderOptions) string{
	// pre-transformations
	transformFigures,
	transformHeaders,

	// main Markdown rendering
	renderMarkdown,

	// post-transformations
	transformCodeWithLanguagePrefix,
	transformSections,
	transformFootnotes,
	transformImagesToAbsoluteURLs,
	transformImagesToRetina,
}

// RenderOptions describes a rendering operation to be customized.
type RenderOptions struct {
	// AbsoluteURLs replaces the sources of any images that pointed to relative
	// URLs with absolute URLs.
	AbsoluteURLs bool

	// NoHeaderLinks disables automatic permalinks on headers.
	NoHeaderLinks bool

	// NoRetina disables the Retina.JS rendering attributes.
	NoRetina bool
}

// Render a Markdown string to HTML while applying all custom project-specific
// filters including footnotes and stable header links.
func Render(source string, options *RenderOptions) string {
	for _, f := range renderFuncs {
		source = f(source, options)
	}
	return source
}

// Look for any whitespace between HTML tags.
var whitespaceRE = regexp.MustCompile(`>\s+<`)

// Simply collapses certain HTML snippets by removing newlines and whitespace
// between tags. This is mainline used to make HTML snippets readable as
// constants, but then to make them fit a little more nicely into the rendered
// markup.
func collapseHTML(html string) string {
	html = strings.Replace(html, "\n", "", -1)
	html = whitespaceRE.ReplaceAllString(html, "><")
	return html
}

func renderMarkdown(source string, options *RenderOptions) string {
	htmlFlags := 0
	htmlFlags |= blackfriday.HTML_SMARTYPANTS_DASHES
	htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
	htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
	htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
	htmlFlags |= blackfriday.HTML_USE_XHTML

	extensions := 0
	extensions |= blackfriday.EXTENSION_AUTO_HEADER_IDS
	extensions |= blackfriday.EXTENSION_AUTOLINK
	extensions |= blackfriday.EXTENSION_FENCED_CODE
	extensions |= blackfriday.EXTENSION_HEADER_IDS
	extensions |= blackfriday.EXTENSION_LAX_HTML_BLOCKS
	extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
	extensions |= blackfriday.EXTENSION_TABLES
	extensions |= blackfriday.EXTENSION_SPACE_HEADERS
	extensions |= blackfriday.EXTENSION_STRIKETHROUGH

	renderer := blackfriday.HtmlRenderer(htmlFlags, "", "")
	return string(blackfriday.Markdown([]byte(source), renderer, extensions))
}

var codeRE = regexp.MustCompile(`<code class="(\w+)">`)

func transformCodeWithLanguagePrefix(source string, options *RenderOptions) string {
	return codeRE.ReplaceAllString(source, `<code class="language-$1">`)
}

const openSectionHTML = `<section class="%s">`
const closeSectionHTML = `</section>`

var openSectionRE = regexp.MustCompile(`(<p>)?!section class=("|“)(.*)("|”)(</p>)?`)
var closeSectionRE = regexp.MustCompile(`(<p>)?!/section(</p>)?`)

func transformSections(source string, options *RenderOptions) string {
	out := source

	out = openSectionRE.ReplaceAllStringFunc(out, func(div string) string {
		matches := openSectionRE.FindStringSubmatch(div)
		class := matches[3]
		return fmt.Sprintf(openSectionHTML, class)
	})
	out = closeSectionRE.ReplaceAllString(out, closeSectionHTML)

	return out
}

const figureHTML = `

%s

`

var figureRE = regexp.MustCompile(`!fig src="(.*)" caption="(.*)"`)

func transformFigures(source string, options *RenderOptions) string {
	return figureRE.ReplaceAllStringFunc(source, func(figure string) string {
		matches := figureRE.FindStringSubmatch(figure)
		src := matches[1]

		link := src
		extension := filepath.Ext(link)
		if extension != "" && extension != ".svg" {
			link = link[0:len(src)-len(extension)] + "@2x" + extension
		}

		// This is a really ugly hack in that it relies on the regex above
		// being greedy about quotes, but meh, I'll make it better when there's
		// a good reason to.
		caption := strings.Replace(matches[2], `\"`, `"`, -1)

		return fmt.Sprintf(figureHTML, link, src, caption)
	})
}

// A layer that we wrap the entire footer section in for styling purposes.
const footerWrapper = `

  %s

`

// HTML for a footnote within the document.
const footnoteAnchorHTML = `

  %s

`

// HTML for a reference to a footnote within the document.
const footnoteReferenceHTML = `

  %s

`

// Look for the section the section at the bottom of the page that looks like
//
[1] (the paragraph tag is there because Markdown will have already
// wrapped it by this point).
var footerRE = regexp.MustCompile(`(?ms:^<p>\[\d+\].*)`)

// Look for a single footnote within the footer.
var footnoteRE = regexp.MustCompile(`\[(\d+)\](\s+.*)`)

// Note that this must be a post-transform filter. If it wasn't, our Markdown
// renderer would not render the Markdown inside the footnotes layer because it
// would already be wrapped in HTML.
func transformFootnotes(source string, options *RenderOptions) string {
	footer := footerRE.FindString(source)

	if footer != "" {
		// remove the footer for now
		source = strings.Replace(source, footer, "", 1)

		footer = footnoteRE.ReplaceAllStringFunc(footer, func(footnote string) string {
			// first create a footnote with an anchor that links can target
			matches := footnoteRE.FindStringSubmatch(footnote)
			number := matches[1]
			anchor := fmt.Sprintf(footnoteAnchorHTML, number, number, number) + matches[2]

			// then replace all references in the body to this footnote
			reference := fmt.Sprintf(footnoteReferenceHTML, number, number, number)
			source = strings.Replace(source,
				fmt.Sprintf(`[%s]`, number),
				collapseHTML(reference), -1)

			return collapseHTML(anchor)
		})

		// and wrap the whole footer section in a layer for styling
		footer = fmt.Sprintf(footerWrapper, footer)
		source = source + footer
	}

	return source
}

const headerHTML = `
<h%v id="%s">
  %s
</h%v>
`

const headerHTMLNoLink = `
<h%v>%s</h%v>
`

// Matches one of the following:
//
//   # header
//   # header (#header-id)
//
// For now, only match ## or more so as to remove code comments from
// matches. We need a better way of doing that though.
var headerRE = regexp.MustCompile(`(?m:^(#{2,})\s+(.*?)(\s+\(#(.*)\))?$)`)

func transformHeaders(source string, options *RenderOptions) string {
	headerNum := 0

	// Tracks previously assigned headers so that we can detect duplicates.
	headers := make(map[string]int)

	source = headerRE.ReplaceAllStringFunc(source, func(header string) string {
		matches := headerRE.FindStringSubmatch(header)

		level := len(matches[1])
		title := matches[2]
		id := matches[4]

		var newID string

		if id == "" {
			// Header with no name, assign a prefixed number.
			newID = fmt.Sprintf("section-%v", headerNum)

		} else {
			occurrence, ok := headers[id]

			if ok {
				// Give duplicate IDs a suffix.
				newID = fmt.Sprintf("%s-%d", id, occurrence)
				headers[id]++

			} else {
				// Otherwise this is the first such ID we've seen.
				newID = id
				headers[id] = 1
			}
		}

		headerNum++

		// Replace the Markdown header with HTML equivalent.
		if options != nil && options.NoHeaderLinks {
			return collapseHTML(fmt.Sprintf(headerHTMLNoLink, level, title, level))
		}

		return collapseHTML(fmt.Sprintf(headerHTML, level, newID, newID, title, level))

	})

	return source
}

var imageRE = regexp.MustCompile(`<img src="(.+)"`)

func transformImagesToRetina(source string, options *RenderOptions) string {
	if options != nil && options.NoRetina {
		return source
	}

	// The basic idea here is that we give every image a `retina-rjs` tag so
	// that Retina.JS will replace it with a retina version *except* if the
	// image is an SVG. These are resolution agnostic and don't need replacing.
	return imageRE.ReplaceAllStringFunc(source, func(img string) string {
		matches := imageRE.FindStringSubmatch(img)
		if filepath.Ext(matches[1]) == ".svg" {
			return fmt.Sprintf(`<img src="%s"`, matches[1])
		}
		return fmt.Sprintf(`<img data-rjs="2" src="%s"`, matches[1])
	})
}

var relativeImageRE = regexp.MustCompile(`<img src="/`)

func transformImagesToAbsoluteURLs(source string, options *RenderOptions) string {
	if options == nil || !options.AbsoluteURLs {
		return source
	}

	return relativeImageRE.ReplaceAllStringFunc(source, func(img string) string {
		return `<img src="` + sorg.AbsoluteURL + `/`
	})
}
<|endoftext|>


<commit_before>package fabric

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

// RouterMiddleware is the selector middleware
type RouterMiddleware struct {
	Handlers map[string]Handler
}

// Name of the middleware
func (m *RouterMiddleware) Name() string {
	return "router"
}

// Handle is the middleware handler for the server
func (m *RouterMiddleware) Handle(ctx context.Context, c Conn) (context.Context, Conn, error) {
	// we need to negotiate what they need from us
	// read the next token, which is the request for the next middleware
	pr, err := ReadToken(c)
	if err != nil {
		return nil, nil, err
	}

	addr := c.GetAddress()

	fmt.Println("Router.Handle: pr=", string(pr))
	fmt.Println("Router.Handle: stack=", addr.stack)

	// TODO not sure about append, might wanna cut the stack up to our index
	// and the append the new stack
	addr.stack = append(addr.stack, strings.Split(string(pr), "/")[1:]...)
	fmt.Println("Router.Handle: stack=", addr.stack)

	if err := WriteToken(c, pr); err != nil {
		return nil, nil, err
	}

	return ctx, c, nil
}

// Negotiate handles the client's side of the nimona middleware
func (m *RouterMiddleware) Negotiate(ctx context.Context, c Conn) (context.Context, Conn, error) {
	pr := c.GetAddress().RemainingString()
	fmt.Println("Router.Negotiate: pr=", pr)

	if err := WriteToken(c, []byte(pr)); err != nil {
		return ctx, nil, err
	}

	if err := m.verifyResponse(c, pr); err != nil {
		return ctx, nil, err
	}

	return ctx, c, nil
}

func (m *RouterMiddleware) verifyResponse(c Conn, pr string) error {
	resp, err := ReadToken(c)
	if err != nil {
		return err
	}

	if string(resp) != pr {
		return errors.New("Invalid selector response")
	}

	return nil
}
<commit_msg>Add SEL and ACK to router<commit_after>package fabric

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

// RouterMiddleware is the selector middleware
type RouterMiddleware struct {
	Handlers map[string]Handler
}

// Name of the middleware
func (m *RouterMiddleware) Name() string {
	return "router"
}

// Handle is the middleware handler for the server
func (m *RouterMiddleware) Handle(ctx context.Context, c Conn) (context.Context, Conn, error) {
	// we need to negotiate what they need from us
	// read the next token, which is the request for the next middleware
	pr, err := ReadToken(c)
	if err != nil {
		return nil, nil, err
	}

	pf := strings.Split(string(pr), " ")
	if len(pf) != 2 {
		return nil, nil, errors.New("invalid router command format")
	}

	cm := pf[0]
	pm := pf[1]

	switch cm {
	case "SEL":
		return m.handleGet(ctx, c, pm)
	default:
		c.Close()
		return nil, nil, errors.New("invalid router command")
	}

}

func (m *RouterMiddleware) handleGet(ctx context.Context, c Conn, pm string) (context.Context, Conn, error) {
	addr := c.GetAddress()

	fmt.Println("Router.Handle: pm=", pm)
	fmt.Println("Router.Handle: stack=", addr.stack)

	// TODO not sure about append, might wanna cut the stack up to our index
	// and the append the new stack
	addr.stack = append(addr.stack, strings.Split(pm, "/")[1:]...)
	fmt.Println("Router.Handle: stack=", addr.stack)

	if err := WriteToken(c, []byte("ACK "+pm)); err != nil {
		return nil, nil, err
	}

	return ctx, c, nil
}

// Negotiate handles the client's side of the nimona middleware
func (m *RouterMiddleware) Negotiate(ctx context.Context, c Conn) (context.Context, Conn, error) {
	pr := c.GetAddress().RemainingString()
	fmt.Println("Router.Negotiate: pr=", pr)

	if err := WriteToken(c, []byte("SEL "+pr)); err != nil {
		return ctx, nil, err
	}

	if err := m.verifyResponse(c, "ACK "+pr); err != nil {
		return ctx, nil, err
	}

	return ctx, c, nil
}

func (m *RouterMiddleware) verifyResponse(c Conn, pr string) error {
	resp, err := ReadToken(c)
	if err != nil {
		return err
	}

	if string(resp) != pr {
		return errors.New("Invalid selector response")
	}

	return nil
}
<|endoftext|>


<commit_before>package models

import (
	"testing"
	"time"

	"bitbucket.org/mundipagg/boletoapi/test"
)

func TestShouldReturnValidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.Type.IsCpf() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CNPJ"}
	if document.Type.IsCpf() {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CnpJ"}
	if document.Type.IsCnpj() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.Type.IsCnpj() {
		t.Fail()
	}
}

func TestShouldReturnValidCpfOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.Number.IsCpf() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCpfOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901asd", Type: "CPF"}
	if document.Number.IsCpf() {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564", Type: "CNPJ"}
	if document.Number.IsCnpj() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564asdf", Type: "CNPJ"}
	if document.Number.IsCnpj() {
		t.Fail()
	}
}

func TestShouldReturnNewTitle(t *testing.T) {
	expDate := time.Now().AddDate(0, 0, 6).Format("2006-01-02")
	_, err := NewTitle(expDate, 100, 231654)
	if err != nil {
		t.Fail()
	}
}

func TestShouldCreateNewTitleWithEqualExpireDateAndCreateDate(t *testing.T) {
	expDate := time.Now().Format("2006-01-02")
	_, err := NewTitle(expDate, 100, 231654)
	if err != nil {
		t.Fail()
	}
}

func TestShouldFailWithCreateDateBiggerThanExpireDate(t *testing.T) {
	expDate := time.Now().AddDate(0, 0, -6).Format("2006-01-02")
	_, err := NewTitle(expDate, 100, 231654)
	if err == nil {
		t.Fail()
	}
}

func TestShouldFailWithAmountInCentsMinorThanOne(t *testing.T) {
	expDate := time.Now().AddDate(0, 0, 6).Format("2006-01-02")
	_, err := NewTitle(expDate, 0, 231654)
	if err == nil {
		t.Fail()
	}
}

func TestShouldReturnBankNumberIsValid(t *testing.T) {
	var b BankNumber = 237

	if b.IsBankNumberValid() == false {
		t.Fail()
	}
}

func TestShouldAppendCollectionOfErrrors(t *testing.T) {
	e := NewErrorCollection(ErrorResponse{Code: 200, Message: "Hue2"})
	e.Append(ErrorResponse{Code: 100, Message: "Hue"})
	test.ExpectTrue(len(e) == 2, t)
}
<commit_msg>:white_check_mark: Arruma o teste que tava quebrando e adiciona teste de criação de erro<commit_after>package models

import (
	"testing"
	"time"

	"bitbucket.org/mundipagg/boletoapi/test"
)

func TestShouldReturnValidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.Type.IsCpf() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CNPJ"}
	if document.Type.IsCpf() {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CnpJ"}
	if document.Type.IsCnpj() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.Type.IsCnpj() {
		t.Fail()
	}
}

func TestShouldReturnValidCpfOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.Number.IsCpf() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCpfOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901asd", Type: "CPF"}
	if document.Number.IsCpf() {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564", Type: "CNPJ"}
	if document.Number.IsCnpj() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564asdf", Type: "CNPJ"}
	if document.Number.IsCnpj() {
		t.Fail()
	}
}

func TestShouldReturnNewTitle(t *testing.T) {
	expDate := time.Now().AddDate(0, 0, 6).Format("2006-01-02")
	_, err := NewTitle(expDate, 100, 231654)
	if err != nil {
		t.Fail()
	}
}

func TestShouldCreateNewTitleWithEqualExpireDateAndCreateDate(t *testing.T) {
	expDate := time.Now().Format("2006-01-02")
	_, err := NewTitle(expDate, 100, 231654)
	if err != nil {
		t.Fail()
	}
}

func TestShouldFailWithCreateDateBiggerThanExpireDate(t *testing.T) {
	expDate := time.Now().AddDate(0, 0, -6).Format("2006-01-02")
	_, err := NewTitle(expDate, 100, 231654)
	if err == nil {
		t.Fail()
	}
}

func TestShouldFailWithAmountInCentsMinorThanOne(t *testing.T) {
	expDate := time.Now().AddDate(0, 0, 6).Format("2006-01-02")
	_, err := NewTitle(expDate, 0, 231654)
	if err == nil {
		t.Fail()
	}
}

func TestShouldReturnBankNumberIsValid(t *testing.T) {
	var b BankNumber = 237

	if b.IsBankNumberValid() == false {
		t.Fail()
	}
}

func TestShouldAppendCollectionOfErrrors(t *testing.T) {
	e := NewErrorCollection(ErrorResponse{Code: "200", Message: "Hue2"})
	e.Append(ErrorResponse{Code: "100", Message: "Hue"})
	test.ExpectTrue(len(e) == 2, t)
}

func TestShouldCreateNewSingleErrorCollection(t *testing.T) {
	e := NewSingleErrorCollection("200", "Hue2")
	test.ExpectTrue(len(e) == 1, t)
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package mongo

import "gopkg.in/mgo.v2"

// CollectionFromName returns a named collection on the specified database,
// initialised with a new session. Also returned is a close function which
// must be called when the collection is no longer required.
func CollectionFromName(db *mgo.Database, coll string) (Collection, func()) {
	session := db.Session.Copy()
	newColl := db.C(coll).With(session)
	return WrapCollection(newColl), session.Close
}

// Collection allows us to construct wrappers for *mgo.Collection objects.
// It's not generally useful for mocking, because (1) you need a real mongo
// in the background to implement Find[Id], not to mention Underlying; and
// (2) if you're working at the level where you're directly concerned with
// collections, it's important to write tests that verify their practical
// behaviour.
type Collection interface {

	// Name returns the name of the collection.
	Name() string

	// Underlying returns the underlying *mgo.Collection. If you're using
	// the collection with mgo/txn, you should be very wary of this method:
	// careless use will disrupt the operation of mgo/txn and cause arbitrary
	// badness.
	Underlying() *mgo.Collection

	// All other methods act as documented for *mgo.Collection.
	Count() (int, error)
	Find(query interface{}) *mgo.Query
	FindId(id interface{}) *mgo.Query
}

// WrapCollection returns a Collection that wraps the supplied *mgo.Collection.
func WrapCollection(coll *mgo.Collection) Collection {
	return collectionWrapper{coll}
}

// collectionWrapper wraps a *mgo.Collection and implements Collection.
type collectionWrapper struct {
	*mgo.Collection
}

// Name is part of the Collection interface.
func (cw collectionWrapper) Name() string {
	return cw.Collection.Name
}

// Underlying is part of the Collection interface.
func (cw collectionWrapper) Underlying() *mgo.Collection {
	return cw.Collection
}
<commit_msg>just removed dangerous Collection methods<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package mongo

import "gopkg.in/mgo.v2"

// CollectionFromName returns a named collection on the specified database,
// initialised with a new session. Also returned is a close function which
// must be called when the collection is no longer required.
func CollectionFromName(db *mgo.Database, coll string) (Collection, func()) {
	session := db.Session.Copy()
	newColl := db.C(coll).With(session)
	return WrapCollection(newColl), session.Close
}

// ReadCollection imperfectly insulates clients from the capacity to write to
// MongoDB. Query results can still be used to write; and the WriteCollection
// allows access to the underlying *mgo.Collection when absolutely required.
type ReadCollection interface {

	// Name returns the name of the collection.
	Name() string

	// Count, Find, and FindId methods act as documented for *mgo.Collection.
	Count() (int, error)
	Find(query interface{}) *mgo.Query
	FindId(id interface{}) *mgo.Query

	// WriteCollection gives access to methods that enable direct DB access.
	// It should be used with judicious care, and for only the best of reasons.
	WriteCollection() WriteCollection
}

// WriteCollection allows read/write access to a MongoDB collection.
type WriteCollection interface {
	ReadCollection

	// Underlying returns the underlying *mgo.Collection.
	Underlying() *mgo.Collection

	// All other methods act as documented for *mgo.Collection.
	Insert(docs ...interface{}) error
	Update(selector interface{}, update interface{}) error
	UpdateId(id interface{}, update interface{}) error
	Remove(sel interface{}) error
	RemoveId(id interface{}) error
	RemoveAll(sel interface{}) (*mgo.ChangeInfo, error)
}

// WrapCollection returns a Collection that wraps the supplied *mgo.Collection.
func WrapCollection(coll *mgo.Collection) ReadCollection {
	return collectionWrapper{coll}
}

// collectionWrapper wraps a *mgo.Collection and implements ReadCollection and
// WriteCollection.
type collectionWrapper struct {
	*mgo.Collection
}

// Name is part of the ReadCollection interface.
func (cw collectionWrapper) Name() string {
	return cw.Collection.Name
}

// WriteCollection is part of the ReadCollection interface.
func (cw collectionWrapper) WriteCollection() WriteCollection {
	return cw
}

// Underlying is part of the WriteCollection interface.
func (cw collectionWrapper) Underlying() *mgo.Collection {
	return cw.Collection
}
<|endoftext|>


<commit_before>//go:generate nanoinstall -M result -v v1.3.0
//go:generate nanotemplate -T string --input=_result.tt.go
package main

import (
	"flag"
	"fmt"
	"github.com/nanoservice/monad.go/nanotemplate/result_string"
	"io/ioutil"
	"os"
	"path"
	"strings"
)

const (
	dirPermission  = 0775
	filePermission = 0664
)

var (
	typeName          = flag.String("T", "", "TYPE to substitute in the template")
	lowercaseTypeName = flag.String("t", "", "LOWERCASETYPE to substitute in package name")
	inputFilename     = flag.String("input", "", "INPUT template filename")
	importName        = flag.String("I", "", "IMPORT string for importing a type")
)

func main() {
	flag.Parse()

	if *typeName == "" {
		reportIsNotProvided("TYPE")
	}

	if *inputFilename == "" {
		reportIsNotProvided("INPUT")
	}

	if *importName != "" {
		*importName = "\"" + *importName + "\""
	}

	if *lowercaseTypeName == "" {
		*lowercaseTypeName = strings.ToLower(*typeName)
	}

	packageName := "result_" + *lowercaseTypeName
	packageFile := packageName + ".t.go"
	outputFile := path.Join(packageName, packageFile)

	os.Mkdir(packageName, dirPermission)

	readTemplate().Chain(
		replace("{{I}}", *importName),
		replace("{{T}}", *typeName),
		replace("{{t}}", *lowercaseTypeName),
		saveTo(outputFile),
	).OnErrorFn(reportGenerationError)
}

func reportIsNotProvided(what string) {
	fmt.Printf("%s is not provided\n", what)
	flag.Usage()
	os.Exit(1)
}

func reportGenerationError(err error) {
	fmt.Printf("Unable to generate from template: %v\n", err)
	os.Exit(1)
}

func readTemplate() result_string.Result {
	return result_string.Success("").Bind(_readTemplate)
}

func _readTemplate(_ string) result_string.Result {
	rawTemplate, err := ioutil.ReadFile(*inputFilename)
	return result_string.NewResult(string(rawTemplate), err)
}

func replace(target, value string) func(string) result_string.Result {
	return func(body string) result_string.Result {
		return result_string.Success(
			strings.Replace(body, target, value, -1),
		)
	}
}

func saveTo(outputFile string) func(string) result_string.Result {
	return func(content string) result_string.Result {
		err := ioutil.WriteFile(outputFile, []byte(content), filePermission)
		return result_string.NewResult("", err)
	}
}
<commit_msg>[nanotemplate] make it usable not only for result_ monads<commit_after>//go:generate nanoinstall -M result -v v1.3.0
//go:generate nanotemplate -T string --input=_result.tt.go
package main

import (
	"flag"
	"fmt"
	"github.com/nanoservice/monad.go/nanotemplate/result_string"
	"io/ioutil"
	"os"
	"path"
	"strings"
)

const (
	dirPermission  = 0775
	filePermission = 0664
)

var (
	typeName          = flag.String("T", "", "TYPE to substitute in the template")
	lowercaseTypeName = flag.String("t", "", "LOWERCASETYPE to substitute in package name")
	inputFilename     = flag.String("input", "", "INPUT template filename")
	importName        = flag.String("I", "", "IMPORT string for importing a type")
)

func main() {
	flag.Parse()

	if *typeName == "" {
		reportIsNotProvided("TYPE")
	}

	if *inputFilename == "" {
		reportIsNotProvided("INPUT")
	}

	if *importName != "" {
		*importName = "\"" + *importName + "\""
	}

	if *lowercaseTypeName == "" {
		*lowercaseTypeName = strings.ToLower(*typeName)
	}

	packageName := packagePrefix() + "_" + *lowercaseTypeName
	packageFile := packageName + ".t.go"
	outputFile := path.Join(packageName, packageFile)

	os.Mkdir(packageName, dirPermission)

	readTemplate().Chain(
		replace("{{I}}", *importName),
		replace("{{T}}", *typeName),
		replace("{{t}}", *lowercaseTypeName),
		saveTo(outputFile),
	).OnErrorFn(reportGenerationError)
}

// assumes _package_prefix_here.tt.go
func packagePrefix() string {
	return (*inputFilename)[1 : len(*inputFilename)-6]
}

func reportIsNotProvided(what string) {
	fmt.Printf("%s is not provided\n", what)
	flag.Usage()
	os.Exit(1)
}

func reportGenerationError(err error) {
	fmt.Printf("Unable to generate from template: %v\n", err)
	os.Exit(1)
}

func readTemplate() result_string.Result {
	return result_string.Success("").Bind(_readTemplate)
}

func _readTemplate(_ string) result_string.Result {
	rawTemplate, err := ioutil.ReadFile(*inputFilename)
	return result_string.NewResult(string(rawTemplate), err)
}

func replace(target, value string) func(string) result_string.Result {
	return func(body string) result_string.Result {
		return result_string.Success(
			strings.Replace(body, target, value, -1),
		)
	}
}

func saveTo(outputFile string) func(string) result_string.Result {
	return func(content string) result_string.Result {
		err := ioutil.WriteFile(outputFile, []byte(content), filePermission)
		return result_string.NewResult("", err)
	}
}
<|endoftext|>


<commit_before>package neoutils

import (
	log "github.com/sirupsen/logrus"
	"github.com/jmcvetta/neoism"
)

// StringerDb wraps neoism Database to provide a String function, which outputs the database URL
type StringerDb struct{ *neoism.Database }

func (sdb StringerDb) String() string {
	return sdb.Url
}

// Check will use the supplied CypherRunner to check connectivity to Neo4j
func Check(cr CypherRunner) error {
	results := []struct {
		node interface{}
	}{}

	query := &neoism.CypherQuery{
		Statement: `MATCH (n) RETURN id(n) LIMIT 1`,
		Result:    &results,
	}

	err := cr.CypherBatch([]*neoism.CypherQuery{query})

	if err != nil {
		return err
	}
	return nil
}

// EnsureIndexes will, for a map of labels and properties, check whether an index exists for a given property on a given label, and if missing will create one
func EnsureIndexes(im IndexManager, indexes map[string]string) error {
	for label, propertyName := range indexes {
		err := ensureIndex(im, label, propertyName)
		if err != nil { // stop as soon as something goes wrong
			return err
		}
	}
	return nil
}

// EnsureConstraints will, for a map of labels and properties, check whether a constraint exists for a given property on a given label, and
// if missing will create one. Creating the unique constraint ensures an index automatically.
func EnsureConstraints(im IndexManager, indexes map[string]string) error {
	for label, propertyName := range indexes {
		err := ensureConstraint(im, label, propertyName)
		if err != nil { // stop as soon as something goes wrong
			return err
		}
	}
	return nil
}

func ensureIndex(im IndexManager, label string, propertyName string) error {

	indexes, err := im.Indexes(label)

	var indexFound bool

	if err != nil && err != neoism.NotFound {
		return err
	}

	for _, index := range indexes {
		if len(index.PropertyKeys) == 1 && index.PropertyKeys[0] == propertyName {
			indexFound = true
			break
		}
	}

	if !indexFound {
		log.Infof("Creating index for type %s on property %s\n", label, propertyName)
		_, err := im.CreateIndex(label, propertyName)
		if err != nil {
			return err
		}
	}
	return nil

}

func ensureConstraint(im IndexManager, label string, propertyName string) error {
	_, err := im.UniqueConstraints(label, propertyName)

	if err != nil {
		if err == neoism.NotFound {
			log.Infof("Creating unique constraint for type %s on property %s\n", label, propertyName)
			_, err = im.CreateUniqueConstraint(label, propertyName)
			if err != nil {
				log.Errorf("Cannot create constraint for type %s on property %s\n", label, propertyName)
				return err
			}
		}
		return err
	}
	return nil

}

func getIndex(im IndexManager, label string, propertyName string) (*neoism.Index, error) {
	indexes, err := im.Indexes(label)

	if err != nil {
		return nil, err
	}

	for _, index := range indexes {
		if len(index.PropertyKeys) == 1 && index.PropertyKeys[0] == propertyName {
			return index, nil
		}
	}
	return nil, nil
}

// IndexManager manages the maintenance of indexes and unique constraints
type IndexManager interface {
	CreateIndex(label string, propertyName string) (*neoism.Index, error)
	Indexes(label string) ([]*neoism.Index, error)
	CreateUniqueConstraint(label string, propertyName string) (*neoism.UniqueConstraint, error)
	UniqueConstraints(label string, propertyName string) ([]*neoism.UniqueConstraint, error)
}
<commit_msg>Writable check addition.<commit_after>package neoutils

import (
	"errors"
	"github.com/jmcvetta/neoism"
	log "github.com/sirupsen/logrus"
)

// StringerDb wraps neoism Database to provide a String function, which outputs the database URL
type StringerDb struct{ *neoism.Database }

func (sdb StringerDb) String() string {
	return sdb.Url
}

// Check will use the supplied CypherRunner to check connectivity to Neo4j
func Check(cr CypherRunner) error {
	var results []struct {
		node interface{}
	}

	query := &neoism.CypherQuery{
		Statement: `MATCH (n) RETURN id(n) LIMIT 1`,
		Result:    &results,
	}

	err := cr.CypherBatch([]*neoism.CypherQuery{query})

	if err != nil {
		return err
	}
	return nil
}

// CheckWritable calls the dbms.cluster.role() procedure and verifies the role if it's LEADER or not.
func CheckWritable(cr CypherRunner) error {

	var res []struct {
		Role string `json:"role"`
	}

	query := &neoism.CypherQuery{
		Statement: `CALL dbms.cluster.role()`,
		Result:    &res,
	}

	err := cr.CypherBatch([]*neoism.CypherQuery{query})

	if err != nil {
		return err
	}

	if len(res) == 0 || res[0].Role == "" {
		return errors.New("got empty response from dbms.cluster.role()")
	}

	role := res[0].Role

	if role != "LEADER" {
		return errors.New("role has to be LEADER for writing but it's " + role)
	}

	return nil
}

// EnsureIndexes will, for a map of labels and properties, check whether an index exists for a given property on a given label, and if missing will create one
func EnsureIndexes(im IndexManager, indexes map[string]string) error {
	for label, propertyName := range indexes {
		err := ensureIndex(im, label, propertyName)
		if err != nil { // stop as soon as something goes wrong
			return err
		}
	}
	return nil
}

// EnsureConstraints will, for a map of labels and properties, check whether a constraint exists for a given property on a given label, and
// if missing will create one. Creating the unique constraint ensures an index automatically.
func EnsureConstraints(im IndexManager, indexes map[string]string) error {
	for label, propertyName := range indexes {
		err := ensureConstraint(im, label, propertyName)
		if err != nil { // stop as soon as something goes wrong
			return err
		}
	}
	return nil
}

func ensureIndex(im IndexManager, label string, propertyName string) error {

	indexes, err := im.Indexes(label)

	var indexFound bool

	if err != nil && err != neoism.NotFound {
		return err
	}

	for _, index := range indexes {
		if len(index.PropertyKeys) == 1 && index.PropertyKeys[0] == propertyName {
			indexFound = true
			break
		}
	}

	if !indexFound {
		log.Infof("Creating index for type %s on property %s\n", label, propertyName)
		_, err := im.CreateIndex(label, propertyName)
		if err != nil {
			return err
		}
	}
	return nil

}

func ensureConstraint(im IndexManager, label string, propertyName string) error {
	_, err := im.UniqueConstraints(label, propertyName)

	if err != nil {
		if err == neoism.NotFound {
			log.Infof("Creating unique constraint for type %s on property %s\n", label, propertyName)
			_, err = im.CreateUniqueConstraint(label, propertyName)
			if err != nil {
				log.Errorf("Cannot create constraint for type %s on property %s\n", label, propertyName)
				return err
			}
		}
		return err
	}
	return nil

}

func getIndex(im IndexManager, label string, propertyName string) (*neoism.Index, error) {
	indexes, err := im.Indexes(label)

	if err != nil {
		return nil, err
	}

	for _, index := range indexes {
		if len(index.PropertyKeys) == 1 && index.PropertyKeys[0] == propertyName {
			return index, nil
		}
	}
	return nil, nil
}

// IndexManager manages the maintenance of indexes and unique constraints
type IndexManager interface {
	CreateIndex(label string, propertyName string) (*neoism.Index, error)
	Indexes(label string) ([]*neoism.Index, error)
	CreateUniqueConstraint(label string, propertyName string) (*neoism.UniqueConstraint, error)
	UniqueConstraints(label string, propertyName string) ([]*neoism.UniqueConstraint, error)
}
<|endoftext|>


<commit_before>package weed_server

// https://yusufs.medium.com/creating-distributed-kv-database-by-implementing-raft-consensus-using-golang-d0884eef2e28
// https://github.com/Jille/raft-grpc-example/blob/cd5bcab0218f008e044fbeee4facdd01b06018ad/application.go#L18

import (
	"fmt"
	transport "github.com/Jille/raft-grpc-transport"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/hashicorp/raft"
	boltdb "github.com/hashicorp/raft-boltdb"
	"google.golang.org/grpc"
	"math/rand"
	"os"
	"path/filepath"
	"time"
)

func (s *RaftServer) AddPeersConfiguration() (cfg raft.Configuration) {
	for _, peer := range s.peers {
		cfg.Servers = append(cfg.Servers, raft.Server{
			Suffrage: raft.Voter,
			ID:       raft.ServerID(peer.String()),
			Address:  raft.ServerAddress(peer.ToGrpcAddress()),
		})
	}
	return cfg
}

func (s *RaftServer) UpdatePeers() {
	for {
		select {
		case isLeader := <-s.RaftHashicorp.LeaderCh():
			if isLeader {
				peerLeader := s.serverAddr.String()
				existsPeerName := make(map[string]bool)
				for _, server := range s.RaftHashicorp.GetConfiguration().Configuration().Servers {
					if string(server.ID) == peerLeader {
						continue
					}
					existsPeerName[string(server.ID)] = true
				}
				for _, peer := range s.peers {
					if peer.String() == peerLeader || existsPeerName[peer.String()] {
						continue
					}
					glog.V(0).Infof("adding new peer: %s", peer.String())
					s.RaftHashicorp.AddVoter(
						raft.ServerID(peer.String()), raft.ServerAddress(peer.ToGrpcAddress()), 0, 0)
				}
				for peer, _ := range existsPeerName {
					if _, found := s.peers[peer]; !found {
						glog.V(0).Infof("removing old peer: %s", peer)
						s.RaftHashicorp.RemoveServer(raft.ServerID(peer), 0, 0)
					}
				}
				if _, found := s.peers[peerLeader]; !found {
					glog.V(0).Infof("removing old leader peer: %s", peerLeader)
					s.RaftHashicorp.RemoveServer(raft.ServerID(peerLeader), 0, 0)
				}
			}
			break
		}
	}
}

func NewHashicorpRaftServer(option *RaftServerOption) (*RaftServer, error) {
	s := &RaftServer{
		peers:      option.Peers,
		serverAddr: option.ServerAddr,
		dataDir:    option.DataDir,
		topo:       option.Topo,
	}

	c := raft.DefaultConfig()
	c.LocalID = raft.ServerID(s.serverAddr.String()) // TODO maybee the IP:port address will change
	c.NoSnapshotRestoreOnStart = option.RaftResumeState
	c.HeartbeatTimeout = time.Duration(float64(option.HeartbeatInterval) * (rand.Float64()*0.25 + 1))
	c.ElectionTimeout = option.ElectionTimeout
	if c.LeaderLeaseTimeout > c.HeartbeatTimeout {
		c.LeaderLeaseTimeout = c.HeartbeatTimeout
	}
	if glog.V(4) {
		c.LogLevel = "Debug"
	} else if glog.V(2) {
		c.LogLevel = "Info"
	} else if glog.V(1) {
		c.LogLevel = "Warn"
	} else if glog.V(0) {
		c.LogLevel = "Error"
	}

	baseDir := s.dataDir

	ldb, err := boltdb.NewBoltStore(filepath.Join(baseDir, "logs.dat"))
	if err != nil {
		return nil, fmt.Errorf(`boltdb.NewBoltStore(%q): %v`, filepath.Join(baseDir, "logs.dat"), err)
	}

	sdb, err := boltdb.NewBoltStore(filepath.Join(baseDir, "stable.dat"))
	if err != nil {
		return nil, fmt.Errorf(`boltdb.NewBoltStore(%q): %v`, filepath.Join(baseDir, "stable.dat"), err)
	}

	fss, err := raft.NewFileSnapshotStore(baseDir, 3, os.Stderr)
	if err != nil {
		return nil, fmt.Errorf(`raft.NewFileSnapshotStore(%q, ...): %v`, baseDir, err)
	}

	s.TransportManager = transport.New(raft.ServerAddress(s.serverAddr), []grpc.DialOption{option.GrpcDialOption})

	stateMachine := StateMachine{topo: option.Topo}
	s.RaftHashicorp, err = raft.NewRaft(c, &stateMachine, ldb, sdb, fss, s.TransportManager.Transport())
	if err != nil {
		return nil, fmt.Errorf("raft.NewRaft: %v", err)
	}
	if option.RaftBootstrap || len(s.RaftHashicorp.GetConfiguration().Configuration().Servers) == 0 {
		cfg := s.AddPeersConfiguration()
		glog.V(0).Infof("Bootstrapping new cluster %+v", cfg)
		f := s.RaftHashicorp.BootstrapCluster(cfg)
		if err := f.Error(); err != nil {
			return nil, fmt.Errorf("raft.Raft.BootstrapCluster: %v", err)
		}
	} else {
		go s.UpdatePeers()
	}

	ticker := time.NewTicker(c.HeartbeatTimeout * 10)
	if glog.V(4) {
		go func() {
			for {
				select {
				case <-ticker.C:
					cfuture := s.RaftHashicorp.GetConfiguration()
					if err = cfuture.Error(); err != nil {
						glog.Fatalf("error getting config: %s", err)
					}
					configuration := cfuture.Configuration()
					glog.V(4).Infof("Showing peers known by %s:\n%+v", s.RaftHashicorp.String(), configuration.Servers)
				}
			}
		}()
	}

	return s, nil
}
<commit_msg>LocalID from raw string<commit_after>package weed_server

// https://yusufs.medium.com/creating-distributed-kv-database-by-implementing-raft-consensus-using-golang-d0884eef2e28
// https://github.com/Jille/raft-grpc-example/blob/cd5bcab0218f008e044fbeee4facdd01b06018ad/application.go#L18

import (
	"fmt"
	transport "github.com/Jille/raft-grpc-transport"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/hashicorp/raft"
	boltdb "github.com/hashicorp/raft-boltdb"
	"google.golang.org/grpc"
	"math/rand"
	"os"
	"path/filepath"
	"time"
)

func (s *RaftServer) AddPeersConfiguration() (cfg raft.Configuration) {
	for _, peer := range s.peers {
		cfg.Servers = append(cfg.Servers, raft.Server{
			Suffrage: raft.Voter,
			ID:       raft.ServerID(peer.String()),
			Address:  raft.ServerAddress(peer.ToGrpcAddress()),
		})
	}
	return cfg
}

func (s *RaftServer) UpdatePeers() {
	for {
		select {
		case isLeader := <-s.RaftHashicorp.LeaderCh():
			if isLeader {
				peerLeader := s.serverAddr.String()
				existsPeerName := make(map[string]bool)
				for _, server := range s.RaftHashicorp.GetConfiguration().Configuration().Servers {
					if string(server.ID) == peerLeader {
						continue
					}
					existsPeerName[string(server.ID)] = true
				}
				for _, peer := range s.peers {
					if peer.String() == peerLeader || existsPeerName[peer.String()] {
						continue
					}
					glog.V(0).Infof("adding new peer: %s", peer.String())
					s.RaftHashicorp.AddVoter(
						raft.ServerID(peer.String()), raft.ServerAddress(peer.ToGrpcAddress()), 0, 0)
				}
				for peer, _ := range existsPeerName {
					if _, found := s.peers[peer]; !found {
						glog.V(0).Infof("removing old peer: %s", peer)
						s.RaftHashicorp.RemoveServer(raft.ServerID(peer), 0, 0)
					}
				}
				if _, found := s.peers[peerLeader]; !found {
					glog.V(0).Infof("removing old leader peer: %s", peerLeader)
					s.RaftHashicorp.RemoveServer(raft.ServerID(peerLeader), 0, 0)
				}
			}
			break
		}
	}
}

func NewHashicorpRaftServer(option *RaftServerOption) (*RaftServer, error) {
	s := &RaftServer{
		peers:      option.Peers,
		serverAddr: option.ServerAddr,
		dataDir:    option.DataDir,
		topo:       option.Topo,
	}

	c := raft.DefaultConfig()
	c.LocalID = raft.ServerID(s.serverAddr) // TODO maybee the IP:port address will change
	c.NoSnapshotRestoreOnStart = option.RaftResumeState
	c.HeartbeatTimeout = time.Duration(float64(option.HeartbeatInterval) * (rand.Float64()*0.25 + 1))
	c.ElectionTimeout = option.ElectionTimeout
	if c.LeaderLeaseTimeout > c.HeartbeatTimeout {
		c.LeaderLeaseTimeout = c.HeartbeatTimeout
	}
	if glog.V(4) {
		c.LogLevel = "Debug"
	} else if glog.V(2) {
		c.LogLevel = "Info"
	} else if glog.V(1) {
		c.LogLevel = "Warn"
	} else if glog.V(0) {
		c.LogLevel = "Error"
	}

	baseDir := s.dataDir

	ldb, err := boltdb.NewBoltStore(filepath.Join(baseDir, "logs.dat"))
	if err != nil {
		return nil, fmt.Errorf(`boltdb.NewBoltStore(%q): %v`, filepath.Join(baseDir, "logs.dat"), err)
	}

	sdb, err := boltdb.NewBoltStore(filepath.Join(baseDir, "stable.dat"))
	if err != nil {
		return nil, fmt.Errorf(`boltdb.NewBoltStore(%q): %v`, filepath.Join(baseDir, "stable.dat"), err)
	}

	fss, err := raft.NewFileSnapshotStore(baseDir, 3, os.Stderr)
	if err != nil {
		return nil, fmt.Errorf(`raft.NewFileSnapshotStore(%q, ...): %v`, baseDir, err)
	}

	s.TransportManager = transport.New(raft.ServerAddress(s.serverAddr), []grpc.DialOption{option.GrpcDialOption})

	stateMachine := StateMachine{topo: option.Topo}
	s.RaftHashicorp, err = raft.NewRaft(c, &stateMachine, ldb, sdb, fss, s.TransportManager.Transport())
	if err != nil {
		return nil, fmt.Errorf("raft.NewRaft: %v", err)
	}
	if option.RaftBootstrap || len(s.RaftHashicorp.GetConfiguration().Configuration().Servers) == 0 {
		cfg := s.AddPeersConfiguration()
		glog.V(0).Infof("Bootstrapping new cluster %+v", cfg)
		f := s.RaftHashicorp.BootstrapCluster(cfg)
		if err := f.Error(); err != nil {
			return nil, fmt.Errorf("raft.Raft.BootstrapCluster: %v", err)
		}
	} else {
		go s.UpdatePeers()
	}

	ticker := time.NewTicker(c.HeartbeatTimeout * 10)
	if glog.V(4) {
		go func() {
			for {
				select {
				case <-ticker.C:
					cfuture := s.RaftHashicorp.GetConfiguration()
					if err = cfuture.Error(); err != nil {
						glog.Fatalf("error getting config: %s", err)
					}
					configuration := cfuture.Configuration()
					glog.V(4).Infof("Showing peers known by %s:\n%+v", s.RaftHashicorp.String(), configuration.Servers)
				}
			}
		}()
	}

	return s, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	rct "github.com/kevinburke/rct-rides"
)

func main() {
	f, err := os.Open(os.Getenv("HOME") + "/code/OpenRCT2/openrct2.exe")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	var WIDTH = 0x12
	b := make([]byte, 100*WIDTH)
	addr := 0x0057E3B6
	f.ReadAt(b, int64(addr))

	for i := 0; i < len(rct.RIDENAMES); i++ {
		fmt.Printf("\t%d,\t", b[i*WIDTH])
		fmt.Printf("// %02x ", i)
		fmt.Printf("%s\n", rct.RIDENAMES[i])
	}
}
<commit_msg>update the byte address for reading data<commit_after>package main

import (
	"fmt"
	"os"

	rct "github.com/kevinburke/rct-rides"
)

func main() {
	f, err := os.Open(os.Getenv("HOME") + "/code/OpenRCT2/openrct2.exe")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	var WIDTH = 0x12
	b := make([]byte, 100*WIDTH)
	addr := 0x0057E3B8
	f.ReadAt(b, int64(addr))

	for i := 0; i < len(rct.RIDENAMES); i++ {
		fmt.Printf("\t%d,\t", b[i*WIDTH])
		fmt.Printf("// %02x ", i)
		fmt.Printf("%s\n", rct.RIDENAMES[i])
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 The Gosl 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 num

import (
	"math"
	"testing"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/io"
)

func f1(x float64) float64    { return math.Exp(x) }
func df1dx(x float64) float64 { return math.Exp(x) }
func f2(x float64) float64 {
	if x >= 0.0 {
		return x * math.Sqrt(x)
	}
	return 0.0
}
func df2dx(x float64) float64 {
	if x >= 0.0 {
		return 1.5 * math.Sqrt(x)
	}
	return 0.0
}
func f3(x float64) float64 {
	if x != 0.0 {
		return math.Sin(1 / x)
	}
	return 0.0
}
func df3dx(x float64) float64 {
	if x != 0.0 {
		return -math.Cos(1/x) / (x * x)
	}
	return 0.0
}
func f4(x float64) float64    { return math.Exp(-x * x) }
func df4dx(x float64) float64 { return -2.0 * x * math.Exp(-x*x) }
func f5(x float64) float64    { return x * x }
func df5dx(x float64) float64 { return 2.0 * x }
func f6(x float64) float64    { return 1.0 / x }
func df6dx(x float64) float64 { return -1.0 / (x * x) }

type NumDerivFunc func(f Cb_fx, x float64, h float64) (result, abserr float64)

func check(tst *testing.T, deriv NumDerivFunc, f Cb_fx, dfdx Cb_fx, x float64, desc string) {
	var tol float64 = 1.0e-6
	expected := dfdx(x)
	result, abserr := deriv(f, x, tol)
	if TestAbs(result, expected, MinComp(tol, expected), desc) != Equal {
		tst.Errorf("TestDeriv01 failed with abserr = %g", abserr)
	}
}

func Test_deriv01(tst *testing.T) {

	//verbose()
	chk.PrintTitle("deriv01")

	check(tst, DerivCen5, f1, df1dx, 1.0, "exp(x), x=1, central deriv")
	check(tst, DerivFwd4, f1, df1dx, 1.0, "exp(x), x=1, forward deriv")
	check(tst, DerivBackward, f1, df1dx, 1.0, "exp(x), x=1, backward deriv")

	check(tst, DerivCen5, f2, df2dx, 0.1, "x^(3/2), x=0.1, central deriv")
	check(tst, DerivFwd4, f2, df2dx, 0.1, "x^(3/2), x=0.1, forward deriv")
	check(tst, DerivBackward, f2, df2dx, 0.1, "x^(3/2), x=0.1, backward deriv")

	check(tst, DerivCen5, f3, df3dx, 0.45, "sin(1/x), x=0.45, central deriv")
	check(tst, DerivFwd4, f3, df3dx, 0.45, "sin(1/x), x=0.45, forward deriv")
	check(tst, DerivBackward, f3, df3dx, 0.45, "sin(1/x), x=0.45, backward deriv")

	check(tst, DerivCen5, f4, df4dx, 0.5, "exp(-x^2), x=0.5, central deriv")
	check(tst, DerivFwd4, f4, df4dx, 0.5, "exp(-x^2), x=0.5, forward deriv")
	check(tst, DerivBackward, f4, df4dx, 0.5, "exp(-x^2), x=0.5, backward deriv")

	check(tst, DerivCen5, f5, df5dx, 0.0, "x^2, x=0, central deriv")
	check(tst, DerivFwd4, f5, df5dx, 0.0, "x^2, x=0, forward deriv")
	check(tst, DerivBackward, f5, df5dx, 0.0, "x^2, x=0, backward deriv")

	check(tst, DerivCen5, f6, df6dx, 10.0, "1/x, x=10, central deriv")
	check(tst, DerivFwd4, f6, df6dx, 10.0, "1/x, x=10, forward deriv")
	check(tst, DerivBackward, f6, df6dx, 10.0, "1/x, x=10, backward deriv")
}

func Test_deriv02(tst *testing.T) {

	//verbose()
	chk.PrintTitle("deriv02")

	// scalar field
	fcn := func(x, y float64) float64 {
		return -math.Pow(math.Pow(math.Cos(x), 2.0)+math.Pow(math.Cos(y), 2.0), 2.0)
	}

	// gradient. u=dfdx, v=dfdy
	grad := func(x, y float64) (u, v float64) {
		m := math.Pow(math.Cos(x), 2.0) + math.Pow(math.Cos(y), 2.0)
		u = 4.0 * math.Cos(x) * math.Sin(x) * m
		v = 4.0 * math.Cos(y) * math.Sin(y) * m
		return
	}

	// grid size
	xmin, xmax, N := -math.Pi/2.0, math.Pi/2.0, 7
	dx := (xmax - xmin) / float64(N-1)

	// step size for numerical differentiation
	h := 0.01

	// tolerance
	tol := 1e-9

	// loop over grid points
	for i := 0; i < N; i++ {
		x := xmin + float64(i)*dx
		for j := 0; j < N; j++ {
			y := xmin + float64(i)*dx

			// scalar and vector field
			f := fcn(x, y)
			u, v := grad(x, y)

			// numerical dfdx @ (x,y)
			unum, _ := DerivCen5(func(xvar float64) float64 {
				return fcn(xvar, y)
			}, x, h)

			// numerical dfdy @ (x,y)
			vnum, _ := DerivCen5(func(yvar float64) float64 {
				return fcn(x, yvar)
			}, y, h)

			// output
			if chk.Verbose {
				io.Pforan("x=%+.3f y=%+.3f f=%+.3f u=%+.3f v=%+.3f unum=%+.3f vnum=%+.3f\n", x, y, f, u, v, unum, vnum)
			}

			// check
			if math.Abs(unum-u) > tol {
				tst.Errorf("x=%v y=%v f=%v u=%v v=%v unum=%v vnum=%v error=%v\n", x, y, f, u, v, unum, vnum, math.Abs(unum-u))
				return
			}
			if math.Abs(vnum-v) > tol {
				tst.Errorf("x=%v y=%v f=%v u=%v v=%v unum=%v vnum=%v error=%v\n", x, y, f, u, v, unum, vnum, math.Abs(vnum-v))
				return
			}
		}
	}
}
<commit_msg>Fix test<commit_after>// Copyright 2016 The Gosl 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 num

import (
	"math"
	"testing"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/io"
)

func f1(x float64) float64    { return math.Exp(x) }
func df1dx(x float64) float64 { return math.Exp(x) }
func f2(x float64) float64 {
	if x >= 0.0 {
		return x * math.Sqrt(x)
	}
	return 0.0
}
func df2dx(x float64) float64 {
	if x >= 0.0 {
		return 1.5 * math.Sqrt(x)
	}
	return 0.0
}
func f3(x float64) float64 {
	if x != 0.0 {
		return math.Sin(1 / x)
	}
	return 0.0
}
func df3dx(x float64) float64 {
	if x != 0.0 {
		return -math.Cos(1/x) / (x * x)
	}
	return 0.0
}
func f4(x float64) float64    { return math.Exp(-x * x) }
func df4dx(x float64) float64 { return -2.0 * x * math.Exp(-x*x) }
func f5(x float64) float64    { return x * x }
func df5dx(x float64) float64 { return 2.0 * x }
func f6(x float64) float64    { return 1.0 / x }
func df6dx(x float64) float64 { return -1.0 / (x * x) }

type NumDerivFunc func(f Cb_fx, x float64, h float64) (result, abserr float64)

func check(tst *testing.T, deriv NumDerivFunc, f Cb_fx, dfdx Cb_fx, x float64, desc string) {
	var tol float64 = 1.0e-6
	expected := dfdx(x)
	result, abserr := deriv(f, x, tol)
	if TestAbs(result, expected, MinComp(tol, expected), desc) != Equal {
		tst.Errorf("TestDeriv01 failed with abserr = %g", abserr)
	}
}

func Test_deriv01(tst *testing.T) {

	//verbose()
	chk.PrintTitle("deriv01")

	check(tst, DerivCen5, f1, df1dx, 1.0, "exp(x), x=1, central deriv")
	check(tst, DerivFwd4, f1, df1dx, 1.0, "exp(x), x=1, forward deriv")
	check(tst, DerivBwd4, f1, df1dx, 1.0, "exp(x), x=1, backward deriv")

	check(tst, DerivCen5, f2, df2dx, 0.1, "x^(3/2), x=0.1, central deriv")
	check(tst, DerivFwd4, f2, df2dx, 0.1, "x^(3/2), x=0.1, forward deriv")
	check(tst, DerivBwd4, f2, df2dx, 0.1, "x^(3/2), x=0.1, backward deriv")

	check(tst, DerivCen5, f3, df3dx, 0.45, "sin(1/x), x=0.45, central deriv")
	check(tst, DerivFwd4, f3, df3dx, 0.45, "sin(1/x), x=0.45, forward deriv")
	check(tst, DerivBwd4, f3, df3dx, 0.45, "sin(1/x), x=0.45, backward deriv")

	check(tst, DerivCen5, f4, df4dx, 0.5, "exp(-x^2), x=0.5, central deriv")
	check(tst, DerivFwd4, f4, df4dx, 0.5, "exp(-x^2), x=0.5, forward deriv")
	check(tst, DerivBwd4, f4, df4dx, 0.5, "exp(-x^2), x=0.5, backward deriv")

	check(tst, DerivCen5, f5, df5dx, 0.0, "x^2, x=0, central deriv")
	check(tst, DerivFwd4, f5, df5dx, 0.0, "x^2, x=0, forward deriv")
	check(tst, DerivBwd4, f5, df5dx, 0.0, "x^2, x=0, backward deriv")

	check(tst, DerivCen5, f6, df6dx, 10.0, "1/x, x=10, central deriv")
	check(tst, DerivFwd4, f6, df6dx, 10.0, "1/x, x=10, forward deriv")
	check(tst, DerivBwd4, f6, df6dx, 10.0, "1/x, x=10, backward deriv")
}

func Test_deriv02(tst *testing.T) {

	//verbose()
	chk.PrintTitle("deriv02")

	// scalar field
	fcn := func(x, y float64) float64 {
		return -math.Pow(math.Pow(math.Cos(x), 2.0)+math.Pow(math.Cos(y), 2.0), 2.0)
	}

	// gradient. u=dfdx, v=dfdy
	grad := func(x, y float64) (u, v float64) {
		m := math.Pow(math.Cos(x), 2.0) + math.Pow(math.Cos(y), 2.0)
		u = 4.0 * math.Cos(x) * math.Sin(x) * m
		v = 4.0 * math.Cos(y) * math.Sin(y) * m
		return
	}

	// grid size
	xmin, xmax, N := -math.Pi/2.0, math.Pi/2.0, 7
	dx := (xmax - xmin) / float64(N-1)

	// step size for numerical differentiation
	h := 0.01

	// tolerance
	tol := 1e-9

	// loop over grid points
	for i := 0; i < N; i++ {
		x := xmin + float64(i)*dx
		for j := 0; j < N; j++ {
			y := xmin + float64(i)*dx

			// scalar and vector field
			f := fcn(x, y)
			u, v := grad(x, y)

			// numerical dfdx @ (x,y)
			unum, _ := DerivCen5(func(xvar float64) float64 {
				return fcn(xvar, y)
			}, x, h)

			// numerical dfdy @ (x,y)
			vnum, _ := DerivCen5(func(yvar float64) float64 {
				return fcn(x, yvar)
			}, y, h)

			// output
			if chk.Verbose {
				io.Pforan("x=%+.3f y=%+.3f f=%+.3f u=%+.3f v=%+.3f unum=%+.3f vnum=%+.3f\n", x, y, f, u, v, unum, vnum)
			}

			// check
			if math.Abs(unum-u) > tol {
				tst.Errorf("x=%v y=%v f=%v u=%v v=%v unum=%v vnum=%v error=%v\n", x, y, f, u, v, unum, vnum, math.Abs(unum-u))
				return
			}
			if math.Abs(vnum-v) > tol {
				tst.Errorf("x=%v y=%v f=%v u=%v v=%v unum=%v vnum=%v error=%v\n", x, y, f, u, v, unum, vnum, math.Abs(vnum-v))
				return
			}
		}
	}
}
<|endoftext|>


<commit_before>package testbin

import (
	"fmt"
	"os"
	"os/exec"
	"path"
	"reflect"
	"time"
)

type t struct{}

var (
	built     = false
	buildPath = ""
)

const behaviorKey = "ALTERNATE_TESTBIN_BEHAVIOR"

func GetBehavior() string {
	return os.Getenv(behaviorKey)
}
func SetBehavior(exitAfterStartDelay, exitAfterSigintDelay time.Duration, label string) string {
	s := fmt.Sprintf("%v %v %s", exitAfterStartDelay, exitAfterSigintDelay, label)
	os.Setenv(behaviorKey, s)
	return s
}

func Build() string {
	if built {
		return buildPath
	}

	if buildPath == "" {
		dir := os.TempDir()
		p := path.Join(dir, "testbin")
		build(p)
		buildPath = p
	} else {
		build(buildPath)
	}

	built = true
	return buildPath
}

func Clean() {
	if !built {
		return
	}
	if err := os.Remove(buildPath); err == nil {
		built = false
	}
}

func binPkgPath() string {
	return reflect.TypeOf(t{}).PkgPath() + "/bin"
}

func build(p string) {
	c := exec.Command("go", "build", "-o", p, binPkgPath())
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	fmt.Printf("Building testbin: %v\n", c.Args)

	if err := c.Run(); err != nil {
		panic(err)
	}
}
<commit_msg>Avoid testbin path conflicts<commit_after>package testbin

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"reflect"
	"time"
)

type t struct{}

var (
	built     = false
	buildPath = ""
)

const behaviorKey = "ALTERNATE_TESTBIN_BEHAVIOR"

func GetBehavior() string {
	return os.Getenv(behaviorKey)
}
func SetBehavior(exitAfterStartDelay, exitAfterSigintDelay time.Duration, label string) string {
	s := fmt.Sprintf("%v %v %s", exitAfterStartDelay, exitAfterSigintDelay, label)
	os.Setenv(behaviorKey, s)
	return s
}

func Build() string {
	if built {
		return buildPath
	}

	if buildPath == "" {
		dir, err := ioutil.TempDir("", "testbin_")
		if err != nil {
			panic(err)
		}
		p := path.Join(dir, "testbin")
		build(p)
		buildPath = p
	} else {
		build(buildPath)
	}

	built = true
	return buildPath
}

func Clean() {
	if !built {
		return
	}
	if err := os.Remove(buildPath); err == nil {
		built = false
	}
}

func binPkgPath() string {
	return reflect.TypeOf(t{}).PkgPath() + "/bin"
}

func build(p string) {
	c := exec.Command("go", "build", "-o", p, binPkgPath())
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	fmt.Printf("Building testbin: %v\n", c.Args)

	if err := c.Run(); err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package testflight_test

import (
	"fmt"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
	"io/ioutil"
	"os"
	"path/filepath"
)

var _ = Describe("set-pipeline Step", func() {
	const (
		pipelineName       = "first-sp"
		secondPipelineName = "second-sp"
	)

	const pipelineContent = `---
resources:
- name: some-resource
  type: mock
  source:
    create_files:
      pipeline.yml: |
        ---
        jobs:
        - name: normal-job
          public: true
          plan:
          - task: a-task
            config:
              platform: linux
              image_resource:
                type: mock
                source: {mirror_self: true}
              run:
                path: echo
                args: ["hello world"]
      name.yml: |
        ---
        name: somebody

jobs:
- name: sp
  public: true
  plan:
    - get: some-resource
    - set_pipeline: %s
      file: some-resource/pipeline.yml
      var_files:
      - some-resource/name.yml
      vars:
        greetings: hello
`

	const pipelineContentWithTeam = pipelineContent + `
      team: ` + teamName

	var (
		fixture                string
		currentPipelineContent string
		currentFlyTarget       string
	)

	BeforeEach(func() {
		fixture = filepath.Join(tmp, "fixture")

		err := os.MkdirAll(fixture, 0755)
		Expect(err).NotTo(HaveOccurred())
	})

	JustBeforeEach(func() {
		err := ioutil.WriteFile(
			filepath.Join(fixture, pipelineName+".yml"),
			[]byte(fmt.Sprintf(currentPipelineContent, secondPipelineName)),
			0755,
		)
		Expect(err).NotTo(HaveOccurred())

		withFlyTarget(currentFlyTarget, func() {
			fly("set-pipeline", "-n", "-p", pipelineName, "-c", fixture+"/"+pipelineName+".yml")
			fly("unpause-pipeline", "-p", pipelineName)
		})
	})

	AfterEach(func() {
		withFlyTarget(currentFlyTarget, func() {
			fly("destroy-pipeline", "-n", "-p", pipelineName)
		})
	})

	Context("when setting the current team's pipeline", func() {
		BeforeEach(func() {
			currentPipelineContent = pipelineContent
			currentFlyTarget = testflightFlyTarget
		})

		AfterEach(func() {
			fly("destroy-pipeline", "-n", "-p", secondPipelineName)
		})

		It("sets the other pipeline", func() {
			By("second pipeline should initially not exist")
			execS := spawnFly("get-pipeline", "-p", secondPipelineName)
			<-execS.Exited
			Expect(execS).To(gexec.Exit(1))
			Expect(execS.Err).To(gbytes.Say("pipeline not found"))

			By("set-pipeline step should succeed")
			execS = fly("trigger-job", "-w", "-j", pipelineName+"/sp")
			Expect(execS.Out).To(gbytes.Say("setting pipeline: second-sp"))
			Expect(execS.Out).To(gbytes.Say("done"))

			By("should trigger the second pipeline job successfully")
			execS = fly("trigger-job", "-w", "-j", secondPipelineName+"/normal-job")
			Expect(execS.Out).To(gbytes.Say("hello world"))
		})
	})

	Context("when setting another team's pipeline from the main team", func() {
		BeforeEach(func() {
			currentPipelineContent = pipelineContentWithTeam
			currentFlyTarget = adminFlyTarget
		})

		It("sets the other pipeline", func() {
			By("second pipeline should initially not exist")
			withFlyTarget(testflightFlyTarget, func() {
				execS := spawnFly("get-pipeline", "-p", secondPipelineName)
				<-execS.Exited
				Expect(execS).To(gexec.Exit(1))
				Expect(execS.Err).To(gbytes.Say("pipeline not found"))
			})

			By("set-pipeline step should succeed")
			withFlyTarget(adminFlyTarget, func() {
				execS := fly("trigger-job", "-w", "-j", pipelineName+"/sp")
				Expect(execS.Out).To(gbytes.Say("setting pipeline: second-sp"))
				Expect(execS.Out).To(gbytes.Say("done"))
			})

			By("should trigger the second pipeline job successfully")
			withFlyTarget(testflightFlyTarget, func() {
				execS := fly("trigger-job", "-w", "-j", secondPipelineName+"/normal-job")
				Expect(execS.Out).To(gbytes.Say("hello world"))
			})
		})

		AfterEach(func() {
			withFlyTarget(testflightFlyTarget, func() {
				fly("destroy-pipeline", "-n", "-p", secondPipelineName)
			})
		})
	})
})
<commit_msg>testflight: add set-pipeline test with other team<commit_after>package testflight_test

import (
	"fmt"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
	"io/ioutil"
	"os"
	"path/filepath"
)

var _ = Describe("set-pipeline Step", func() {
	const (
		pipelineName       = "first-sp"
		secondPipelineName = "second-sp"
	)

	const pipelineContent = `---
resources:
- name: some-resource
  type: mock
  source:
    create_files:
      pipeline.yml: |
        ---
        jobs:
        - name: normal-job
          public: true
          plan:
          - task: a-task
            config:
              platform: linux
              image_resource:
                type: mock
                source: {mirror_self: true}
              run:
                path: echo
                args: ["hello world"]
      name.yml: |
        ---
        name: somebody

jobs:
- name: sp
  public: true
  plan:
    - get: some-resource
    - set_pipeline: %s
      file: some-resource/pipeline.yml
      var_files:
      - some-resource/name.yml
      vars:
        greetings: hello
`

	const pipelineContentWithTeam = pipelineContent + `
      team: ` + teamName

	const pipelineContentWithMainTeam = pipelineContent + `
      team: main`

	var (
		fixture                string
		currentPipelineContent string
		currentFlyTarget       string
	)

	BeforeEach(func() {
		fixture = filepath.Join(tmp, "fixture")

		err := os.MkdirAll(fixture, 0755)
		Expect(err).NotTo(HaveOccurred())
	})

	JustBeforeEach(func() {
		err := ioutil.WriteFile(
			filepath.Join(fixture, pipelineName+".yml"),
			[]byte(fmt.Sprintf(currentPipelineContent, secondPipelineName)),
			0755,
		)
		Expect(err).NotTo(HaveOccurred())

		withFlyTarget(currentFlyTarget, func() {
			fly("set-pipeline", "-n", "-p", pipelineName, "-c", fixture+"/"+pipelineName+".yml")
			fly("unpause-pipeline", "-p", pipelineName)
		})
	})

	AfterEach(func() {
		withFlyTarget(currentFlyTarget, func() {
			fly("destroy-pipeline", "-n", "-p", pipelineName)
		})
	})

	Context("when setting the current team's pipeline", func() {
		BeforeEach(func() {
			currentPipelineContent = pipelineContent
			currentFlyTarget = testflightFlyTarget
		})

		AfterEach(func() {
			fly("destroy-pipeline", "-n", "-p", secondPipelineName)
		})

		It("sets the other pipeline", func() {
			By("second pipeline should initially not exist")
			execS := spawnFly("get-pipeline", "-p", secondPipelineName)
			<-execS.Exited
			Expect(execS).To(gexec.Exit(1))
			Expect(execS.Err).To(gbytes.Say("pipeline not found"))

			By("set-pipeline step should succeed")
			execS = fly("trigger-job", "-w", "-j", pipelineName+"/sp")
			Expect(execS.Out).To(gbytes.Say("setting pipeline: second-sp"))
			Expect(execS.Out).To(gbytes.Say("done"))

			By("should trigger the second pipeline job successfully")
			execS = fly("trigger-job", "-w", "-j", secondPipelineName+"/normal-job")
			Expect(execS.Out).To(gbytes.Say("hello world"))
		})
	})

	Context("when setting another team's pipeline from the main team", func() {
		BeforeEach(func() {
			currentPipelineContent = pipelineContentWithTeam
			currentFlyTarget = adminFlyTarget
		})

		It("sets the other pipeline", func() {
			By("second pipeline should initially not exist")
			withFlyTarget(testflightFlyTarget, func() {
				execS := spawnFly("get-pipeline", "-p", secondPipelineName)
				<-execS.Exited
				Expect(execS).To(gexec.Exit(1))
				Expect(execS.Err).To(gbytes.Say("pipeline not found"))
			})

			By("set-pipeline step should succeed")
			withFlyTarget(adminFlyTarget, func() {
				execS := fly("trigger-job", "-w", "-j", pipelineName+"/sp")
				Expect(execS.Out).To(gbytes.Say("setting pipeline: second-sp"))
				Expect(execS.Out).To(gbytes.Say("done"))
			})

			By("should trigger the second pipeline job successfully")
			withFlyTarget(testflightFlyTarget, func() {
				execS := fly("trigger-job", "-w", "-j", secondPipelineName+"/normal-job")
				Expect(execS.Out).To(gbytes.Say("hello world"))
			})
		})

		AfterEach(func() {
			withFlyTarget(testflightFlyTarget, func() {
				fly("destroy-pipeline", "-n", "-p", secondPipelineName)
			})
		})
	})

	Context("when setting the main team's pipeline from a normal team", func() {
		BeforeEach(func() {
			currentPipelineContent = pipelineContentWithMainTeam
			currentFlyTarget = testflightFlyTarget
		})

		It("fails to set the other pipeline", func() {
			By("second pipeline should initially not exist")
			withFlyTarget(adminFlyTarget, func() {
				execS := spawnFly("get-pipeline", "-p", secondPipelineName)
				<-execS.Exited
				Expect(execS).To(gexec.Exit(1))
				Expect(execS.Err).To(gbytes.Say("pipeline not found"))
			})

			By("set-pipeline step should fail")
			withFlyTarget(testflightFlyTarget, func() {
				execS := spawnFly("trigger-job", "-w", "-j", pipelineName+"/sp")
				<-execS.Exited
				Expect(execS).To(gexec.Exit(2))
				Expect(execS.Out).To(gbytes.Say("only main team can set another team's pipeline"))
				Expect(execS.Out).To(gbytes.Say("errored"))
			})

			By("second pipeline should still not exist")
			withFlyTarget(adminFlyTarget, func() {
				execS := spawnFly("get-pipeline", "-p", secondPipelineName)
				<-execS.Exited
				Expect(execS).To(gexec.Exit(1))
				Expect(execS.Err).To(gbytes.Say("pipeline not found"))
			})
		})
	})
})
<|endoftext|>