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

package cmd

import (
	"fmt"
	"os"
	"sort"
	"text/tabwriter"

	"github.com/cilium/cilium/api/v1/models"
	"github.com/cilium/cilium/pkg/endpoint"

	"github.com/go-openapi/swag"
	"github.com/spf13/cobra"
)

// PolicyEnabled and PolicyDisabled represent the endpoint policy status
const (
	PolicyEnabled  = "Enabled"
	PolicyDisabled = "Disabled"
)

var noHeaders bool

// endpointListCmd represents the endpoint_list command
var endpointListCmd = &cobra.Command{
	Use:   "list",
	Short: "List all endpoints",
	Run: func(cmd *cobra.Command, args []string) {
		listEndpoints()
	},
}

func init() {
	endpointCmd.AddCommand(endpointListCmd)
	endpointListCmd.Flags().BoolVar(&noHeaders, "no-headers", false, "Do not print headers")
	AddMultipleOutput(endpointListCmd)
}

func listEndpoint(w *tabwriter.Writer, ep *models.Endpoint, id string, label string) {
	var isIngressPolicyEnabled string
	var isEgressPolicyEnabled string
	switch swag.StringValue(ep.PolicyEnabled) {
	case models.EndpointPolicyEnabledNone:
		isIngressPolicyEnabled = PolicyDisabled
		isEgressPolicyEnabled = PolicyDisabled
	case models.EndpointPolicyEnabledBoth:
		isIngressPolicyEnabled = PolicyEnabled
		isEgressPolicyEnabled = PolicyEnabled
	case models.EndpointPolicyEnabledIngress:
		isIngressPolicyEnabled = PolicyEnabled
		isEgressPolicyEnabled = PolicyDisabled
	case models.EndpointPolicyEnabledEgress:
		isIngressPolicyEnabled = PolicyDisabled
		isEgressPolicyEnabled = PolicyEnabled
	}
	fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
		ep.ID, isIngressPolicyEnabled, isEgressPolicyEnabled, id, label, ep.Addressing.IPV6, ep.Addressing.IPV4, ep.State)
}

func listEndpoints() {
	eps, err := client.EndpointList()
	if err != nil {
		Fatalf("cannot get endpoint list: %s\n", err)
	}
	w := tabwriter.NewWriter(os.Stdout, 5, 0, 3, ' ', 0)
	printEndpointList(w, eps)
}

func printEndpointList(w *tabwriter.Writer, eps []*models.Endpoint) {
	endpoint.OrderEndpointAsc(eps)

	const (
		labelsIDTitle      = "IDENTITY"
		labelsDesTitle     = "LABELS (source:key[=value])"
		ipv6Title          = "IPv6"
		ipv4Title          = "IPv4"
		endpointTitle      = "ENDPOINT"
		statusTitle        = "STATUS"
		policyIngressTitle = "POLICY (ingress)"
		policyEgressTitle  = "POLICY (egress)"
		enforcementTitle   = "ENFORCEMENT"
	)

	if !noHeaders {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
			endpointTitle, policyIngressTitle, policyEgressTitle, labelsIDTitle, labelsDesTitle, ipv6Title, ipv4Title, statusTitle)
		fmt.Fprintf(w, "\t%s\t%s\t\t\t\t\t\n", enforcementTitle, enforcementTitle)
	}

	if len(dumpOutput) > 0 {
		if err := OutputPrinter(eps); err != nil {
			os.Exit(1)
		}
		return
	}

	for _, ep := range eps {
		id := "<no label id>"
		if ep.Identity != nil {
			id = fmt.Sprintf("%d", ep.Identity.ID)
		}

		if len(ep.Labels.OrchestrationIdentity) == 0 {
			listEndpoint(w, ep, id, "no labels")
		} else {

			first := true
			lbls := ep.Labels.OrchestrationIdentity
			sort.Strings(lbls)
			for _, lbl := range lbls {
				if first {
					listEndpoint(w, ep, id, lbl)
					first = false
				} else {
					fmt.Fprintf(w, "\t\t\t%s\t\t\t\t\n", lbl)
				}
			}
		}

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

package cmd

import (
	"fmt"
	"os"
	"sort"
	"text/tabwriter"

	"github.com/cilium/cilium/api/v1/models"
	"github.com/cilium/cilium/pkg/endpoint"

	"github.com/go-openapi/swag"
	"github.com/spf13/cobra"
)

// PolicyEnabled and PolicyDisabled represent the endpoint policy status
const (
	PolicyEnabled  = "Enabled"
	PolicyDisabled = "Disabled"
)

var noHeaders bool

// endpointListCmd represents the endpoint_list command
var endpointListCmd = &cobra.Command{
	Use:   "list",
	Short: "List all endpoints",
	Run: func(cmd *cobra.Command, args []string) {
		listEndpoints()
	},
}

func init() {
	endpointCmd.AddCommand(endpointListCmd)
	endpointListCmd.Flags().BoolVar(&noHeaders, "no-headers", false, "Do not print headers")
	AddMultipleOutput(endpointListCmd)
}

func listEndpoint(w *tabwriter.Writer, ep *models.Endpoint, id string, label string) {
	var isIngressPolicyEnabled string
	var isEgressPolicyEnabled string
	switch swag.StringValue(ep.PolicyEnabled) {
	case models.EndpointPolicyEnabledNone:
		isIngressPolicyEnabled = PolicyDisabled
		isEgressPolicyEnabled = PolicyDisabled
	case models.EndpointPolicyEnabledBoth:
		isIngressPolicyEnabled = PolicyEnabled
		isEgressPolicyEnabled = PolicyEnabled
	case models.EndpointPolicyEnabledIngress:
		isIngressPolicyEnabled = PolicyEnabled
		isEgressPolicyEnabled = PolicyDisabled
	case models.EndpointPolicyEnabledEgress:
		isIngressPolicyEnabled = PolicyDisabled
		isEgressPolicyEnabled = PolicyEnabled
	}
	fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
		ep.ID, isIngressPolicyEnabled, isEgressPolicyEnabled, id, label, ep.Addressing.IPV6, ep.Addressing.IPV4, ep.State)
}

func listEndpoints() {
	eps, err := client.EndpointList()
	if err != nil {
		Fatalf("cannot get endpoint list: %s\n", err)
	}
	w := tabwriter.NewWriter(os.Stdout, 5, 0, 3, ' ', 0)
	printEndpointList(w, eps)
}

func printEndpointList(w *tabwriter.Writer, eps []*models.Endpoint) {
	endpoint.OrderEndpointAsc(eps)

	const (
		labelsIDTitle      = "IDENTITY"
		labelsDesTitle     = "LABELS (source:key[=value])"
		ipv6Title          = "IPv6"
		ipv4Title          = "IPv4"
		endpointTitle      = "ENDPOINT"
		statusTitle        = "STATUS"
		policyIngressTitle = "POLICY (ingress)"
		policyEgressTitle  = "POLICY (egress)"
		enforcementTitle   = "ENFORCEMENT"
	)

	if !noHeaders {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
			endpointTitle, policyIngressTitle, policyEgressTitle, labelsIDTitle, labelsDesTitle, ipv6Title, ipv4Title, statusTitle)
		fmt.Fprintf(w, "\t%s\t%s\t\t\t\t\t\n", enforcementTitle, enforcementTitle)
	}

	if len(dumpOutput) > 0 {
		if err := OutputPrinter(eps); err != nil {
			os.Exit(1)
		}
		return
	}

	for _, ep := range eps {
		id := "<no label id>"
		if ep.Identity != nil {
			id = fmt.Sprintf("%d", ep.Identity.ID)
		}

		if len(ep.Labels.OrchestrationIdentity) == 0 {
			listEndpoint(w, ep, id, "no labels")
		} else {

			first := true
			lbls := ep.Labels.OrchestrationIdentity
			sort.Strings(lbls)
			for _, lbl := range lbls {
				if first {
					listEndpoint(w, ep, id, lbl)
					first = false
				} else {
					fmt.Fprintf(w, "\t\t\t\t%s\t\t\t\t\n", lbl)
				}
			}
		}

	}
	w.Flush()
}
<|endoftext|>


<commit_before>package stack

import (
	"fmt"
	"io/ioutil"
	"os"
	"time"

	"github.com/spf13/cobra"
	"golang.org/x/net/context"

	"github.com/aanand/compose-file/loader"
	composetypes "github.com/aanand/compose-file/types"
	"github.com/docker/docker/api/types"
	networktypes "github.com/docker/docker/api/types/network"
	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	servicecmd "github.com/docker/docker/cli/command/service"
	"github.com/docker/go-connections/nat"
)

const (
	defaultNetworkDriver = "overlay"
)

type deployOptions struct {
	composefile      string
	namespace        string
	sendRegistryAuth bool
}

func newDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
	var opts deployOptions

	cmd := &cobra.Command{
		Use:     "deploy [OPTIONS] STACK",
		Aliases: []string{"up"},
		Short:   "Deploy a new stack or update an existing stack",
		Args:    cli.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			opts.namespace = args[0]
			return runDeploy(dockerCli, opts)
		},
		Tags: map[string]string{"experimental": "", "version": "1.25"},
	}

	flags := cmd.Flags()
	addComposefileFlag(&opts.composefile, flags)
	addRegistryAuthFlag(&opts.sendRegistryAuth, flags)
	return cmd
}

func runDeploy(dockerCli *command.DockerCli, opts deployOptions) error {
	configDetails, err := getConfigDetails(opts)
	if err != nil {
		return err
	}

	config, err := loader.Load(configDetails)
	if err != nil {
		return err
	}

	ctx := context.Background()
	if err := createNetworks(ctx, dockerCli, config.Networks, opts.namespace); err != nil {
		return err
	}
	return deployServices(ctx, dockerCli, config, opts.namespace, opts.sendRegistryAuth)
}

func getConfigDetails(opts deployOptions) (composetypes.ConfigDetails, error) {
	var details composetypes.ConfigDetails
	var err error

	details.WorkingDir, err = os.Getwd()
	if err != nil {
		return details, err
	}

	configFile, err := getConfigFile(opts.composefile)
	if err != nil {
		return details, err
	}
	// TODO: support multiple files
	details.ConfigFiles = []composetypes.ConfigFile{*configFile}
	return details, nil
}

func getConfigFile(filename string) (*composetypes.ConfigFile, error) {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return loader.ParseYAML(bytes, filename)
}

func createNetworks(
	ctx context.Context,
	dockerCli *command.DockerCli,
	networks map[string]composetypes.NetworkConfig,
	namespace string,
) error {
	client := dockerCli.Client()

	existingNetworks, err := getNetworks(ctx, client, namespace)
	if err != nil {
		return err
	}

	existingNetworkMap := make(map[string]types.NetworkResource)
	for _, network := range existingNetworks {
		existingNetworkMap[network.Name] = network
	}

	for internalName, network := range networks {
		if network.ExternalName != "" {
			continue
		}

		name := fmt.Sprintf("%s_%s", namespace, internalName)
		if _, exists := existingNetworkMap[name]; exists {
			continue
		}

		createOpts := types.NetworkCreate{
			// TODO: support network labels from compose file
			Labels:  getStackLabels(namespace, nil),
			Driver:  network.Driver,
			Options: network.DriverOpts,
		}

		if network.Ipam.Driver != "" {
			createOpts.IPAM = &networktypes.IPAM{
				Driver: network.Ipam.Driver,
			}
		}
		// TODO: IPAMConfig.Config

		if createOpts.Driver == "" {
			createOpts.Driver = defaultNetworkDriver
		}

		fmt.Fprintf(dockerCli.Out(), "Creating network %s\n", name)
		if _, err := client.NetworkCreate(ctx, name, createOpts); err != nil {
			return err
		}
	}
	return nil
}

func convertNetworks(
	networks map[string]*composetypes.ServiceNetworkConfig,
	namespace string,
	name string,
) []swarm.NetworkAttachmentConfig {
	nets := []swarm.NetworkAttachmentConfig{}
	for networkName, network := range networks {
		nets = append(nets, swarm.NetworkAttachmentConfig{
			// TODO: only do this name mangling in one function
			Target:  namespace + "_" + networkName,
			Aliases: append(network.Aliases, name),
		})
	}
	return nets
}

func deployServices(
	ctx context.Context,
	dockerCli *command.DockerCli,
	config *composetypes.Config,
	namespace string,
	sendAuth bool,
) error {
	apiClient := dockerCli.Client()
	out := dockerCli.Out()
	services := config.Services
	volumes := config.Volumes

	existingServices, err := getServices(ctx, apiClient, namespace)
	if err != nil {
		return err
	}

	existingServiceMap := make(map[string]swarm.Service)
	for _, service := range existingServices {
		existingServiceMap[service.Spec.Name] = service
	}

	for _, service := range services {
		name := fmt.Sprintf("%s_%s", namespace, service.Name)

		serviceSpec, err := convertService(namespace, service, volumes)
		if err != nil {
			return err
		}

		encodedAuth := ""
		if sendAuth {
			// Retrieve encoded auth token from the image reference
			image := serviceSpec.TaskTemplate.ContainerSpec.Image
			encodedAuth, err = command.RetrieveAuthTokenFromImage(ctx, dockerCli, image)
			if err != nil {
				return err
			}
		}

		if service, exists := existingServiceMap[name]; exists {
			fmt.Fprintf(out, "Updating service %s (id: %s)\n", name, service.ID)

			updateOpts := types.ServiceUpdateOptions{}
			if sendAuth {
				updateOpts.EncodedRegistryAuth = encodedAuth
			}
			if err := apiClient.ServiceUpdate(
				ctx,
				service.ID,
				service.Version,
				serviceSpec,
				updateOpts,
			); err != nil {
				return err
			}
		} else {
			fmt.Fprintf(out, "Creating service %s\n", name)

			createOpts := types.ServiceCreateOptions{}
			if sendAuth {
				createOpts.EncodedRegistryAuth = encodedAuth
			}
			if _, err := apiClient.ServiceCreate(ctx, serviceSpec, createOpts); err != nil {
				return err
			}
		}
	}

	return nil
}

func convertService(
	namespace string,
	service composetypes.ServiceConfig,
	volumes map[string]composetypes.VolumeConfig,
) (swarm.ServiceSpec, error) {
	// TODO: remove this duplication
	name := fmt.Sprintf("%s_%s", namespace, service.Name)

	endpoint, err := convertEndpointSpec(service.Ports)
	if err != nil {
		return swarm.ServiceSpec{}, err
	}

	mode, err := convertDeployMode(service.Deploy.Mode, service.Deploy.Replicas)
	if err != nil {
		return swarm.ServiceSpec{}, err
	}

	serviceSpec := swarm.ServiceSpec{
		Annotations: swarm.Annotations{
			Name:   name,
			Labels: getStackLabels(namespace, service.Labels),
		},
		TaskTemplate: swarm.TaskSpec{
			ContainerSpec: swarm.ContainerSpec{
				Image:   service.Image,
				Command: service.Entrypoint,
				Args:    service.Command,
				Env:     convertEnvironment(service.Environment),
				Labels:  getStackLabels(namespace, service.Deploy.Labels),
				Dir:     service.WorkingDir,
				User:    service.User,
			},
			Placement: &swarm.Placement{
				Constraints: service.Deploy.Placement.Constraints,
			},
		},
		EndpointSpec: endpoint,
		Mode:         mode,
		Networks:     convertNetworks(service.Networks, namespace, service.Name),
	}

	if service.StopGracePeriod != nil {
		stopGrace, err := time.ParseDuration(*service.StopGracePeriod)
		if err != nil {
			return swarm.ServiceSpec{}, err
		}
		serviceSpec.TaskTemplate.ContainerSpec.StopGracePeriod = &stopGrace
	}

	// TODO: convert mounts
	return serviceSpec, nil
}

func convertEndpointSpec(source []string) (*swarm.EndpointSpec, error) {
	portConfigs := []swarm.PortConfig{}
	ports, portBindings, err := nat.ParsePortSpecs(source)
	if err != nil {
		return nil, err
	}

	for port := range ports {
		portConfigs = append(
			portConfigs,
			servicecmd.ConvertPortToPortConfig(port, portBindings)...)
	}

	return &swarm.EndpointSpec{Ports: portConfigs}, nil
}

func convertEnvironment(source map[string]string) []string {
	var output []string

	for name, value := range source {
		output = append(output, fmt.Sprintf("%s=%s", name, value))
	}

	return output
}

func convertDeployMode(mode string, replicas uint64) (swarm.ServiceMode, error) {
	serviceMode := swarm.ServiceMode{}

	switch mode {
	case "global":
		if replicas != 0 {
			return serviceMode, fmt.Errorf("replicas can only be used with replicated mode")
		}
		serviceMode.Global = &swarm.GlobalService{}
	case "replicated":
		serviceMode.Replicated = &swarm.ReplicatedService{Replicas: &replicas}
	default:
		return serviceMode, fmt.Errorf("Unknown mode: %s", mode)
	}
	return serviceMode, nil
}
<commit_msg>Add support for service-level 'volumes' key<commit_after>package stack

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"time"

	"github.com/spf13/cobra"
	"golang.org/x/net/context"

	"github.com/aanand/compose-file/loader"
	composetypes "github.com/aanand/compose-file/types"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/mount"
	networktypes "github.com/docker/docker/api/types/network"
	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	servicecmd "github.com/docker/docker/cli/command/service"
	"github.com/docker/go-connections/nat"
)

const (
	defaultNetworkDriver = "overlay"
)

type deployOptions struct {
	composefile      string
	namespace        string
	sendRegistryAuth bool
}

func newDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
	var opts deployOptions

	cmd := &cobra.Command{
		Use:     "deploy [OPTIONS] STACK",
		Aliases: []string{"up"},
		Short:   "Deploy a new stack or update an existing stack",
		Args:    cli.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			opts.namespace = args[0]
			return runDeploy(dockerCli, opts)
		},
		Tags: map[string]string{"experimental": "", "version": "1.25"},
	}

	flags := cmd.Flags()
	addComposefileFlag(&opts.composefile, flags)
	addRegistryAuthFlag(&opts.sendRegistryAuth, flags)
	return cmd
}

func runDeploy(dockerCli *command.DockerCli, opts deployOptions) error {
	configDetails, err := getConfigDetails(opts)
	if err != nil {
		return err
	}

	config, err := loader.Load(configDetails)
	if err != nil {
		return err
	}

	ctx := context.Background()
	if err := createNetworks(ctx, dockerCli, config.Networks, opts.namespace); err != nil {
		return err
	}
	return deployServices(ctx, dockerCli, config, opts.namespace, opts.sendRegistryAuth)
}

func getConfigDetails(opts deployOptions) (composetypes.ConfigDetails, error) {
	var details composetypes.ConfigDetails
	var err error

	details.WorkingDir, err = os.Getwd()
	if err != nil {
		return details, err
	}

	configFile, err := getConfigFile(opts.composefile)
	if err != nil {
		return details, err
	}
	// TODO: support multiple files
	details.ConfigFiles = []composetypes.ConfigFile{*configFile}
	return details, nil
}

func getConfigFile(filename string) (*composetypes.ConfigFile, error) {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	config, err := loader.ParseYAML(bytes)
	if err != nil {
		return nil, err
	}
	return &composetypes.ConfigFile{
		Filename: filename,
		Config:   config,
	}, nil
}

func createNetworks(
	ctx context.Context,
	dockerCli *command.DockerCli,
	networks map[string]composetypes.NetworkConfig,
	namespace string,
) error {
	client := dockerCli.Client()

	existingNetworks, err := getNetworks(ctx, client, namespace)
	if err != nil {
		return err
	}

	existingNetworkMap := make(map[string]types.NetworkResource)
	for _, network := range existingNetworks {
		existingNetworkMap[network.Name] = network
	}

	for internalName, network := range networks {
		if network.External.Name != "" {
			continue
		}

		name := fmt.Sprintf("%s_%s", namespace, internalName)
		if _, exists := existingNetworkMap[name]; exists {
			continue
		}

		createOpts := types.NetworkCreate{
			// TODO: support network labels from compose file
			Labels:  getStackLabels(namespace, nil),
			Driver:  network.Driver,
			Options: network.DriverOpts,
		}

		if network.Ipam.Driver != "" {
			createOpts.IPAM = &networktypes.IPAM{
				Driver: network.Ipam.Driver,
			}
		}
		// TODO: IPAMConfig.Config

		if createOpts.Driver == "" {
			createOpts.Driver = defaultNetworkDriver
		}

		fmt.Fprintf(dockerCli.Out(), "Creating network %s\n", name)
		if _, err := client.NetworkCreate(ctx, name, createOpts); err != nil {
			return err
		}
	}
	return nil
}

func convertNetworks(
	networks map[string]*composetypes.ServiceNetworkConfig,
	namespace string,
	name string,
) []swarm.NetworkAttachmentConfig {
	nets := []swarm.NetworkAttachmentConfig{}
	for networkName, network := range networks {
		nets = append(nets, swarm.NetworkAttachmentConfig{
			// TODO: only do this name mangling in one function
			Target:  namespace + "_" + networkName,
			Aliases: append(network.Aliases, name),
		})
	}
	return nets
}

func convertVolumes(
	serviceVolumes []string,
	stackVolumes map[string]composetypes.VolumeConfig,
	namespace string,
) ([]mount.Mount, error) {
	var mounts []mount.Mount

	for _, volumeString := range serviceVolumes {
		var (
			source, target string
			mountType      mount.Type
			readOnly       bool
			volumeOptions  *mount.VolumeOptions
		)

		// TODO: split Windows path mappings properly
		parts := strings.SplitN(volumeString, ":", 3)

		if len(parts) == 3 {
			source = parts[0]
			target = parts[1]
			if parts[2] == "ro" {
				readOnly = true
			}
		} else if len(parts) == 2 {
			source = parts[0]
			target = parts[1]
		} else if len(parts) == 1 {
			target = parts[0]
		}

		// TODO: catch Windows paths here
		if strings.HasPrefix(source, "/") {
			mountType = mount.TypeBind
		} else {
			mountType = mount.TypeVolume

			stackVolume, exists := stackVolumes[source]
			if !exists {
				// TODO: better error message (include service name)
				return nil, fmt.Errorf("Undefined volume: %s", source)
			}

			if stackVolume.External.Name != "" {
				source = stackVolume.External.Name
			} else {
				volumeOptions = &mount.VolumeOptions{
					Labels: stackVolume.Labels,
				}

				if stackVolume.Driver != "" {
					volumeOptions.DriverConfig = &mount.Driver{
						Name:    stackVolume.Driver,
						Options: stackVolume.DriverOpts,
					}
				}

				// TODO: remove this duplication
				source = fmt.Sprintf("%s_%s", namespace, source)
			}
		}

		mounts = append(mounts, mount.Mount{
			Type:          mountType,
			Source:        source,
			Target:        target,
			ReadOnly:      readOnly,
			VolumeOptions: volumeOptions,
		})
	}

	return mounts, nil
}

func deployServices(
	ctx context.Context,
	dockerCli *command.DockerCli,
	config *composetypes.Config,
	namespace string,
	sendAuth bool,
) error {
	apiClient := dockerCli.Client()
	out := dockerCli.Out()
	services := config.Services
	volumes := config.Volumes

	existingServices, err := getServices(ctx, apiClient, namespace)
	if err != nil {
		return err
	}

	existingServiceMap := make(map[string]swarm.Service)
	for _, service := range existingServices {
		existingServiceMap[service.Spec.Name] = service
	}

	for _, service := range services {
		name := fmt.Sprintf("%s_%s", namespace, service.Name)

		serviceSpec, err := convertService(namespace, service, volumes)
		if err != nil {
			return err
		}

		encodedAuth := ""
		if sendAuth {
			// Retrieve encoded auth token from the image reference
			image := serviceSpec.TaskTemplate.ContainerSpec.Image
			encodedAuth, err = command.RetrieveAuthTokenFromImage(ctx, dockerCli, image)
			if err != nil {
				return err
			}
		}

		if service, exists := existingServiceMap[name]; exists {
			fmt.Fprintf(out, "Updating service %s (id: %s)\n", name, service.ID)

			updateOpts := types.ServiceUpdateOptions{}
			if sendAuth {
				updateOpts.EncodedRegistryAuth = encodedAuth
			}
			if err := apiClient.ServiceUpdate(
				ctx,
				service.ID,
				service.Version,
				serviceSpec,
				updateOpts,
			); err != nil {
				return err
			}
		} else {
			fmt.Fprintf(out, "Creating service %s\n", name)

			createOpts := types.ServiceCreateOptions{}
			if sendAuth {
				createOpts.EncodedRegistryAuth = encodedAuth
			}
			if _, err := apiClient.ServiceCreate(ctx, serviceSpec, createOpts); err != nil {
				return err
			}
		}
	}

	return nil
}

func convertService(
	namespace string,
	service composetypes.ServiceConfig,
	volumes map[string]composetypes.VolumeConfig,
) (swarm.ServiceSpec, error) {
	// TODO: remove this duplication
	name := fmt.Sprintf("%s_%s", namespace, service.Name)

	endpoint, err := convertEndpointSpec(service.Ports)
	if err != nil {
		return swarm.ServiceSpec{}, err
	}

	mode, err := convertDeployMode(service.Deploy.Mode, service.Deploy.Replicas)
	if err != nil {
		return swarm.ServiceSpec{}, err
	}

	mounts, err := convertVolumes(service.Volumes, volumes, namespace)
	if err != nil {
		return swarm.ServiceSpec{}, err
	}

	serviceSpec := swarm.ServiceSpec{
		Annotations: swarm.Annotations{
			Name:   name,
			Labels: getStackLabels(namespace, service.Labels),
		},
		TaskTemplate: swarm.TaskSpec{
			ContainerSpec: swarm.ContainerSpec{
				Image:    service.Image,
				Command:  service.Entrypoint,
				Args:     service.Command,
				Hostname: service.Hostname,
				Env:      convertEnvironment(service.Environment),
				Labels:   getStackLabels(namespace, service.Deploy.Labels),
				Dir:      service.WorkingDir,
				User:     service.User,
				Mounts:   mounts,
			},
			Placement: &swarm.Placement{
				Constraints: service.Deploy.Placement.Constraints,
			},
		},
		EndpointSpec: endpoint,
		Mode:         mode,
		Networks:     convertNetworks(service.Networks, namespace, service.Name),
	}

	if service.StopGracePeriod != nil {
		stopGrace, err := time.ParseDuration(*service.StopGracePeriod)
		if err != nil {
			return swarm.ServiceSpec{}, err
		}
		serviceSpec.TaskTemplate.ContainerSpec.StopGracePeriod = &stopGrace
	}

	// TODO: convert mounts
	return serviceSpec, nil
}

func convertEndpointSpec(source []string) (*swarm.EndpointSpec, error) {
	portConfigs := []swarm.PortConfig{}
	ports, portBindings, err := nat.ParsePortSpecs(source)
	if err != nil {
		return nil, err
	}

	for port := range ports {
		portConfigs = append(
			portConfigs,
			servicecmd.ConvertPortToPortConfig(port, portBindings)...)
	}

	return &swarm.EndpointSpec{Ports: portConfigs}, nil
}

func convertEnvironment(source map[string]string) []string {
	var output []string

	for name, value := range source {
		output = append(output, fmt.Sprintf("%s=%s", name, value))
	}

	return output
}

func convertDeployMode(mode string, replicas uint64) (swarm.ServiceMode, error) {
	serviceMode := swarm.ServiceMode{}

	switch mode {
	case "global":
		if replicas != 0 {
			return serviceMode, fmt.Errorf("replicas can only be used with replicated mode")
		}
		serviceMode.Global = &swarm.GlobalService{}
	case "replicated":
		serviceMode.Replicated = &swarm.ReplicatedService{Replicas: &replicas}
	default:
		return serviceMode, fmt.Errorf("Unknown mode: %s", mode)
	}
	return serviceMode, nil
}
<|endoftext|>


<commit_before>package client

type Request interface {
	// ContentType of the payload
	ContentType() string
	// Service to be delivered to
	Service() string
	// Endpoint to be delivered to at the service
	Endpoint() string
	// Payload stores our raw payload to send
	Payload() []byte
}

type request struct {
	// contentType of the payload
	contentType string
	// service to be delivered to
	service string
	// endpoint to be delivered to at the service
	endpoint string
	// payload stores our raw payload to send
	payload []byte
}

// ContentType of the request
func (r *request) ContentType() string {
	return r.contentType
}

// Service to be delivered to
func (r *request) Service() string {
	return r.service
}

// Endpoint to be delivered to at the service
func (r *request) Endpoint() string {
	return r.endpoint
}

// Payload of the request
func (r *request) Payload() []byte {
	return r.payload
}

// NewProtoRequest creates a new request with protobuf encoding
func NewProtoRequest(service, endpoint string, payload []byte) Request {
	return &request{
		contentType: "application/x-protobuf",
		service:     service,
		endpoint:    endpoint,
		payload:     payload,
	}
}

// NewJsonRequest creates a new request with json encoding
func NewJsonRequest(service, endpoint string, payload []byte) Request {
	return &request{
		contentType: "application/json",
		service:     service,
		endpoint:    endpoint,
		payload:     payload,
	}
}
<commit_msg>Generate a unique request id when creating a request<commit_after>package client

import (
	log "github.com/cihub/seelog"
	"github.com/nu7hatch/gouuid"

	"github.com/b2aio/typhon/errors"
)

type Request interface {
	// Id of this request
	Id() string
	// ContentType of the payload
	ContentType() string
	// Service to be delivered to
	Service() string
	// Endpoint to be delivered to at the service
	Endpoint() string
	// Payload stores our raw payload to send
	Payload() []byte
}

type request struct {
	// id of this request
	id string
	// contentType of the payload
	contentType string
	// service to be delivered to
	service string
	// endpoint to be delivered to at the service
	endpoint string
	// payload stores our raw payload to send
	payload []byte
}

// Id of the request
func (r *request) Id() string {
	return r.id
}

// ContentType of the request
func (r *request) ContentType() string {
	return r.contentType
}

// Service to be delivered to
func (r *request) Service() string {
	return r.service
}

// Endpoint to be delivered to at the service
func (r *request) Endpoint() string {
	return r.endpoint
}

// Payload of the request
func (r *request) Payload() []byte {
	return r.payload
}

// NewProtoRequest creates a new request with protobuf encoding
func NewProtoRequest(service, endpoint string, payload []byte) (Request, error) {
	requestId, err := uuid.NewV4()
	if err != nil {
		log.Errorf("[Client] Failed to create unique request id: %v", err)
		return nil, errors.Wrap(err) // @todo custom error code
	}

	return &request{
		id:          requestId.String(),
		contentType: "application/x-protobuf",
		service:     service,
		endpoint:    endpoint,
		payload:     payload,
	}, nil
}

// NewJsonRequest creates a new request with json encoding
func NewJsonRequest(service, endpoint string, payload []byte) (Request, error) {
	requestId, err := uuid.NewV4()
	if err != nil {
		log.Errorf("[Client] Failed to create unique request id: %v", err)
		return nil, errors.Wrap(err) // @todo custom error code
	}

	return &request{
		id:          requestId.String(),
		contentType: "application/json",
		service:     service,
		endpoint:    endpoint,
		payload:     payload,
	}, nil
}
<|endoftext|>


<commit_before>package client // import "github.com/docker/docker/client"

import (
	"bytes"
	"context"
	"encoding/json"
	"io/ioutil"
	"net/url"

	"github.com/docker/docker/api/types"
)

// ContainerInspect returns the container information.
func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) {
	if containerID == "" {
		return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID}
	}
	serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
	if err != nil {
		return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID)
	}

	var response types.ContainerJSON
	err = json.NewDecoder(serverResp.body).Decode(&response)
	ensureReaderClosed(serverResp)
	return response, err
}

// ContainerInspectWithRaw returns the container information and its raw representation.
func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) {
	if containerID == "" {
		return types.ContainerJSON{}, nil, objectNotFoundError{object: "container", id: containerID}
	}
	query := url.Values{}
	if getSize {
		query.Set("size", "1")
	}
	serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
	if err != nil {
		return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
	}
	defer ensureReaderClosed(serverResp)

	body, err := ioutil.ReadAll(serverResp.body)
	if err != nil {
		return types.ContainerJSON{}, nil, err
	}

	var response types.ContainerJSON
	rdr := bytes.NewReader(body)
	err = json.NewDecoder(rdr).Decode(&response)
	return response, body, err
}
<commit_msg>Unify the defer syntax<commit_after>package client // import "github.com/docker/docker/client"

import (
	"bytes"
	"context"
	"encoding/json"
	"io/ioutil"
	"net/url"

	"github.com/docker/docker/api/types"
)

// ContainerInspect returns the container information.
func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) {
	if containerID == "" {
		return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID}
	}
	serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
	if err != nil {
		return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID)
	}
	defer ensureReaderClosed(serverResp)

	var response types.ContainerJSON
	err = json.NewDecoder(serverResp.body).Decode(&response)
	return response, err
}

// ContainerInspectWithRaw returns the container information and its raw representation.
func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) {
	if containerID == "" {
		return types.ContainerJSON{}, nil, objectNotFoundError{object: "container", id: containerID}
	}
	query := url.Values{}
	if getSize {
		query.Set("size", "1")
	}
	serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
	if err != nil {
		return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
	}
	defer ensureReaderClosed(serverResp)

	body, err := ioutil.ReadAll(serverResp.body)
	if err != nil {
		return types.ContainerJSON{}, nil, err
	}

	var response types.ContainerJSON
	rdr := bytes.NewReader(body)
	err = json.NewDecoder(rdr).Decode(&response)
	return response, body, err
}
<|endoftext|>


<commit_before>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package rtr_brk_http

import (
	"encoding/json"
	"fmt"
	"github.com/thethingsnetwork/core"
	"github.com/thethingsnetwork/core/lorawan/semtech"
	"github.com/thethingsnetwork/core/testing/mock_components"
	"github.com/thethingsnetwork/core/utils/log"
	"github.com/thethingsnetwork/core/utils/pointer"
	. "github.com/thethingsnetwork/core/utils/testing"
	"io"
	"net/http"
	"reflect"
	"testing"
	"time"
)

// ----- The adapter can be created and listen straigthforwardly
func TestListenOptionsTest(t *testing.T) {
	adapter, router := generateAdapterAndRouter(t)

	Desc(t, "Listen to adapter")
	if err := adapter.Listen(router, nil); err != nil {
		Ko(t, "No error was expected but got: %+v", err)
		return
	}
	Ok(t)
}

// ----- The adapter should forward a payload to a set of brokers
func TestForwardPayload(t *testing.T) {
	tests := []forwardPayloadTest{
		{generateValidPayload(), generateBrokers([]int{200, 200}), nil},
		{generateInvalidPayload(), generateBrokers([]int{200}), core.ErrInvalidPayload},
	}

	for _, test := range tests {
		test.run(t)
	}
}

type forwardPayloadTest struct {
	payload semtech.Payload
	brokers map[string]int
	want    error
}

func (test forwardPayloadTest) run(t *testing.T) {
	Desc(t, "Forward %v to %v", test.payload, test.brokers)
	adapter, router := generateAdapterAndRouter(t)
	cmsg := listenHTTP(t, test.brokers)
	<-time.After(time.Millisecond * 250)
	got := adapter.Forward(router, test.payload, toBrokerAddrs(test.brokers)...)
	test.check(t, cmsg, got)
}

func (test forwardPayloadTest) check(t *testing.T, cmsg chan semtech.Payload, got error) {
	<-time.After(time.Millisecond * 500)

	// Check for the error
	if test.want != nil {
		if test.want != got {
			Ko(t, "Expected error %v but got %v", test.want, got)
			return
		}
		Ok(t)
		return
	}

	// Check if payload should have been sent
	if len(test.brokers) == 0 {
		Ok(t)
		return
	}

	// Gather payloads and check one of them
	var payloads []semtech.Payload
	select {
	case payload := <-cmsg:
		payloads = append(payloads, payload)
		if len(payloads) == len(test.brokers) {
			break
		}
	case <-time.After(time.Millisecond * 500):
		Ko(t, "%d payload(s) send to server(s) whereas %d was/were expected", len(payloads), len(test.brokers))
		return
	}

	if !reflect.DeepEqual(test.payload, payloads[0]) {
		Ko(t, "Expected %+v to be sent but server received: %+v", test.payload, payloads[0])
		return
	}

	Ok(t)
}

// ----- Build Utilities

// Create an instance of an Adapter with a predefined logger + a mock router
func generateAdapterAndRouter(t *testing.T) (Adapter, core.Router) {
	return Adapter{
		Logger: log.TestLogger{
			Tag: "Adapter",
			T:   t,
		},
	}, mock_components.NewRouter()
}

// Generate a very basic payload holding an RXPK packet
func generateValidPayload() semtech.Payload {
	return semtech.Payload{
		RXPK: []semtech.RXPK{{
			Data: pointer.String("-DS4CGaDCdG+48eJNM3Vai-zDpsR71Pn9CPA9uCON84"),
			Freq: pointer.Float64(866.349812),
			Rssi: pointer.Int(-35),
		},
		},
	}
}

// Generate a payload with no RXPK nor STAT packet
func generateInvalidPayload() semtech.Payload {
	return semtech.Payload{}
}

// Keep track of open TCP ports
var port int = 3000

// Generate a list of brokers given a list of http response status in the form address -> status
func generateBrokers(status []int) map[string]int {
	brokers := make(map[string]int)
	for _, s := range status {
		brokers[fmt.Sprintf("0.0.0.0:%d", port)] = s
		port += 1
	}
	return brokers
}

// Transform the broker map address -> status to a list a BrokerAddress
func toBrokerAddrs(addrs map[string]int) []core.BrokerAddress {
	brokers := make([]core.BrokerAddress, 0)
	for addr := range addrs {
		brokers = append(brokers, core.BrokerAddress(addr))
	}
	return brokers
}

// Create an http handler that will listen to json request on "/" and forward payload into a
// dedicated channel. A custom response status can be given in param.
func createServeMux(t *testing.T, status int, cmsg chan semtech.Payload) *http.ServeMux {
	serveMux := http.NewServeMux()
	serveMux.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
		defer req.Body.Close()
		res.Header().Set("Content-Type", "application/json")

		// Check the header type
		if req.Header.Get("Content-Type") != "application/json" {
			t.Log("Unexpected content-type ignore")
			res.WriteHeader(http.StatusBadRequest)
			res.Write(nil)
			return
		}

		// Check the body as well
		var payload semtech.Payload
		raw := make([]byte, 512)
		n, err := req.Body.Read(raw)
		if err != nil && err != io.EOF {
			t.Logf("Error reading request body: %v", err)
			res.WriteHeader(http.StatusBadRequest)
			res.Write(nil)
			return
		}

		if err := json.Unmarshal(raw[:n], &payload); err != nil {
			t.Logf("Error while unmarshaling: %v", err)
			res.WriteHeader(http.StatusBadRequest)
			res.Write(nil)
			return
		}

		// Send a fake response
		res.WriteHeader(status)
		res.Write(nil)
		cmsg <- payload
	})
	return serveMux
}

// ----- Operate Utilities

// Start one http server per address which will forward request to the returned channel of payloads.
func listenHTTP(t *testing.T, addrs map[string]int) chan semtech.Payload {
	cmsg := make(chan semtech.Payload)

	for addr, status := range addrs {
		go func(addr string, status int) {
			s := &http.Server{Addr: addr, Handler: createServeMux(t, status, cmsg)}
			if err := s.ListenAndServe(); err != nil {
				panic(err)
			}
		}(addr, status)
	}

	return cmsg
}
<commit_msg>[router] Rewrite adapter tests. Split check functions + write Broadcast tests<commit_after>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package rtr_brk_http

import (
	"encoding/json"
	"fmt"
	"github.com/thethingsnetwork/core"
	"github.com/thethingsnetwork/core/lorawan/semtech"
	"github.com/thethingsnetwork/core/testing/mock_components"
	"github.com/thethingsnetwork/core/utils/log"
	"github.com/thethingsnetwork/core/utils/pointer"
	. "github.com/thethingsnetwork/core/utils/testing"
	"io"
	"net/http"
	"reflect"
	"testing"
	"time"
)

// ----- The adapter can be created and listen straigthforwardly
func TestListenOptionsTest(t *testing.T) {
	adapter, router := genAdapterAndRouter(t)

	Desc(t, "Listen to adapter")
	if err := adapter.Listen(router, nil); err != nil {
		Ko(t, "No error was expected but got: %+v", err)
		return
	}
	Ok(t)
}

// ----- The adapter should forward a payload to a set of brokers
func TestForwardPayload(t *testing.T) {
	tests := []forwardPayloadTest{
		{genValidPayload(), genBrokers([]int{200}), nil},
		{genValidPayload(), genBrokers([]int{200, 200}), nil},
		{genInvalidPayload(), nil, core.ErrInvalidPayload},
	}

	for _, test := range tests {
		test.run(t)
	}
}

type forwardPayloadTest struct {
	payload semtech.Payload
	brokers map[string]int
	want    error
}

func (test forwardPayloadTest) run(t *testing.T) {
	//Describe
	Desc(t, "Forward %v to %v", test.payload, test.brokers)

	// Build
	adapter, router := genAdapterAndRouter(t)
	adapter.Listen(router, toBrokerAddrs(test.brokers))
	cmsg := listenHTTP(t, test.brokers)

	// Operate
	<-time.After(time.Millisecond * 250)
	got := adapter.Forward(router, test.payload, toBrokerAddrs(test.brokers)...)

	// Check
	<-time.After(time.Millisecond * 250)
	checkErrors(t, test.want, got)
	checkReception(t, len(test.brokers), test.payload, cmsg)
}

// ----- The adapter should broadcast a payload to a set of broker
func TestBroadcastPayload(t *testing.T) {
	tests := []broadcastPayloadTest{
		{genValidPayload(), genBrokers([]int{200, 200}), nil},
		{genValidPayload(), genBrokers([]int{200, 404}), nil},
		{genValidPayloadInvalidDevAddr(), nil, core.ErrInvalidPayload},
		{genInvalidPayload(), nil, core.ErrInvalidPayload},
	}

	for _, test := range tests {
		test.run(t)
	}
}

type broadcastPayloadTest struct {
	payload semtech.Payload
	brokers map[string]int
	want    error
}

func (test broadcastPayloadTest) run(t *testing.T) {
	// Describe
	Desc(t, "Forward %v to %v", test.payload, test.brokers)

	// Build
	adapter, router := genAdapterAndRouter(t)
	adapter.Listen(router, toBrokerAddrs(test.brokers))
	cmsg := listenHTTP(t, test.brokers)

	// Operate
	<-time.After(time.Millisecond * 250)
	got := adapter.Broadcast(router, test.payload)

	// Check
	<-time.After(time.Millisecond * 250)
	checkErrors(t, test.want, got)
	checkReception(t, len(test.brokers), test.payload, cmsg)
	checkRegistration(t, router, test.payload, test.brokers)
}

// ----- Build Utilities

// Create an instance of an Adapter with a predefined logger + a mock router
func genAdapterAndRouter(t *testing.T) (Adapter, core.Router) {
	return Adapter{
		Logger: log.TestLogger{
			Tag: "Adapter",
			T:   t,
		},
	}, mock_components.NewRouter()
}

// gen a very basic payload holding an RXPK packet and identifying a valid device address
func genValidPayload() semtech.Payload {
	return semtech.Payload{
		RXPK: []semtech.RXPK{{
			Data: pointer.String(""),
			Freq: pointer.Float64(866.349812),
			Rssi: pointer.Int(-35),
		},
		},
	}
}

// gen a very basic payload holding an RXPK packet but with scrap data
func genValidPayloadInvalidDevAddr() semtech.Payload {
	return semtech.Payload{
		RXPK: []semtech.RXPK{{
			Data: pointer.String("-DS4CGaDCdG+48eJNM3Vai-zDpsR71Pn9CPA9uCON84"),
			Freq: pointer.Float64(866.349812),
			Rssi: pointer.Int(-35),
		},
		},
	}
}

// gen a payload with no RXPK nor STAT packet
func genInvalidPayload() semtech.Payload {
	return semtech.Payload{}
}

// Keep track of open TCP ports
var port int = 3000

// gen a list of brokers given a list of http response status in the form address -> status
func genBrokers(status []int) map[string]int {
	brokers := make(map[string]int)
	for _, s := range status {
		brokers[fmt.Sprintf("0.0.0.0:%d", port)] = s
		port += 1
	}
	return brokers
}

// Transform the broker map address -> status to a list a BrokerAddress
func toBrokerAddrs(addrs map[string]int) []core.BrokerAddress {
	brokers := make([]core.BrokerAddress, 0)
	for addr := range addrs {
		brokers = append(brokers, core.BrokerAddress(addr))
	}
	return brokers
}

// Create an http handler that will listen to json request on "/" and forward payload into a
// dedicated channel. A custom response status can be given in param.
func createServeMux(t *testing.T, status int, cmsg chan semtech.Payload) *http.ServeMux {
	serveMux := http.NewServeMux()
	serveMux.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
		defer req.Body.Close()
		res.Header().Set("Content-Type", "application/json")

		// Check the header type
		if req.Header.Get("Content-Type") != "application/json" {
			t.Log("Unexpected content-type ignore")
			res.WriteHeader(http.StatusBadRequest)
			res.Write(nil)
			return
		}

		// Check the body as well
		var payload semtech.Payload
		raw := make([]byte, 512)
		n, err := req.Body.Read(raw)
		if err != nil && err != io.EOF {
			t.Logf("Error reading request body: %v", err)
			res.WriteHeader(http.StatusBadRequest)
			res.Write(nil)
			return
		}

		if err := json.Unmarshal(raw[:n], &payload); err != nil {
			t.Logf("Error while unmarshaling: %v", err)
			res.WriteHeader(http.StatusBadRequest)
			res.Write(nil)
			return
		}

		// Send a fake response
		res.WriteHeader(status)
		res.Write(nil)
		cmsg <- payload
	})
	return serveMux
}

// ----- Operate Utilities

// Start one http server per address which will forward request to the returned channel of payloads.
func listenHTTP(t *testing.T, addrs map[string]int) chan semtech.Payload {
	cmsg := make(chan semtech.Payload)

	for addr, status := range addrs {
		go func(addr string, status int) {
			s := &http.Server{Addr: addr, Handler: createServeMux(t, status, cmsg)}
			if err := s.ListenAndServe(); err != nil {
				panic(err)
			}
		}(addr, status)
	}

	return cmsg
}

// ----- Check Utilities
func checkErrors(t *testing.T, want error, got error) bool {
	// Check for the error
	if want != nil {
		if want != got {
			Ko(t, "Expected error %v but got %v", want, got)
			return false
		}
		Ok(t)
		return true
	}
	return true
}

func checkReception(t *testing.T, nbExpected int, want semtech.Payload, cmsg chan semtech.Payload) bool {
	// Check if payload should have been sent
	if nbExpected <= 0 {
		Ok(t)
		return true
	}

	// Gather payloads and check one of them
	var payloads []semtech.Payload
	select {
	case payload := <-cmsg:
		payloads = append(payloads, payload)
		if len(payloads) == nbExpected {
			break
		}
	case <-time.After(time.Millisecond * 500):
		Ko(t, "%d payload(s) send to server(s) whereas %d was/were expected", len(payloads), nbExpected)
		return false
	}

	if !reflect.DeepEqual(want, payloads[0]) {
		Ko(t, "Expected %+v to be sent but server received: %+v", want, payloads[0])
		return false
	}

	Ok(t)
	return true
}

func checkRegistration(t *testing.T, router core.Router, payload semtech.Payload, brokers map[string]int) bool {
	if len(brokers) == 0 {
		Ok(t)
		return true
	}

	devAddr, err := payload.UniformDevAddr()
	if err != nil {
		panic(err)
	}

	mockRouter := router.(*mock_components.Router) // Need to access to registered devices of mock router

outer:
	for addr, status := range brokers {
		if status != 200 { // Not a HTTP 200 OK, broker probably does not handle that device
			continue
		}

		addrs, ok := mockRouter.Devices[*devAddr] // Get all registered brokers for that device
		if !ok {
			Ko(t, "Broker %s wasn't registered for payload %v", addr, payload)
			return false
		}

		for _, broker := range addrs {
			if string(broker) == addr {
				continue outer // We are registered, everything's fine for that broker
			}
		}

		Ko(t, "Broker %s wasn't registered for payload %v", addr, payload)
		return false
	}

	Ok(t)
	return true
}
<|endoftext|>


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

// +build linux

package terminal

import "syscall"

const ioctlReadTermios = syscall.TCGETS
const ioctlWriteTermios = syscall.TCSETS
<commit_msg>go.crypt/ssh/terminal: declare TCGETS, TCSETS constants locally.<commit_after>// Copyright 2013 The Go 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 terminal

// These constants are declared here, rather than importing
// them from the syscall package as some syscall packages, even
// on linux, for example gccgo, do not declare them.
const ioctlReadTermios = 0x5401  // syscall.TCGETS
const ioctlWriteTermios = 0x5402 // syscall.TCSETS
<|endoftext|>


<commit_before>package grpc_prometheus

import (
	"io"

	prom "github.com/prometheus/client_golang/prometheus"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

// ClientMetrics represents a collection of metrics to be registered on a
// Prometheus metrics registry for a gRPC client.
type ClientMetrics struct {
	clientStartedCounter             *prom.CounterVec
	clientHandledCounter             *prom.CounterVec
	clientStreamMsgReceived          *prom.CounterVec
	clientStreamMsgSent              *prom.CounterVec
	clientHandledHistogramEnabled    bool
	clientHandledHistogramOpts       prom.HistogramOpts
	clientHandledHistogram           *prom.HistogramVec
	clientStreamRecvHistogramEnabled bool
	clientStreamRecvHistogramOpts    prom.HistogramOpts
	clientStreamRecvHistogram        *prom.HistogramVec
	clientStreamSendHistogramEnabled bool
	clientStreamSendHistogramOpts    prom.HistogramOpts
	clientStreamSendHistogram        *prom.HistogramVec
}

// NewClientMetrics returns a ClientMetrics object. Use a new instance of
// ClientMetrics when not using the default Prometheus metrics registry, for
// example when wanting to control which metrics are added to a registry as
// opposed to automatically adding metrics via init functions.
func NewClientMetrics(counterOpts ...CounterOption) *ClientMetrics {
	opts := counterOptions(counterOpts)
	return &ClientMetrics{
		clientStartedCounter: prom.NewCounterVec(
			opts.apply(prom.CounterOpts{
				Name: "grpc_client_started_total",
				Help: "Total number of RPCs started on the client.",
			}), []string{"grpc_type", "grpc_service", "grpc_method"}),

		clientHandledCounter: prom.NewCounterVec(
			opts.apply(prom.CounterOpts{
				Name: "grpc_client_handled_total",
				Help: "Total number of RPCs completed by the client, regardless of success or failure.",
			}), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}),

		clientStreamMsgReceived: prom.NewCounterVec(
			opts.apply(prom.CounterOpts{
				Name: "grpc_client_msg_received_total",
				Help: "Total number of RPC stream messages received by the client.",
			}), []string{"grpc_type", "grpc_service", "grpc_method"}),

		clientStreamMsgSent: prom.NewCounterVec(
			opts.apply(prom.CounterOpts{
				Name: "grpc_client_msg_sent_total",
				Help: "Total number of gRPC stream messages sent by the client.",
			}), []string{"grpc_type", "grpc_service", "grpc_method"}),

		clientHandledHistogramEnabled: false,
		clientHandledHistogramOpts: prom.HistogramOpts{
			Name:    "grpc_client_handling_seconds",
			Help:    "Histogram of response latency (seconds) of the gRPC until it is finished by the application.",
			Buckets: prom.DefBuckets,
		},
		clientHandledHistogram:           nil,
		clientStreamRecvHistogramEnabled: false,
		clientStreamRecvHistogramOpts: prom.HistogramOpts{
			Name:    "grpc_client_msg_recv_handling_seconds",
			Help:    "Histogram of response latency (seconds) of the gRPC single message receive.",
			Buckets: prom.DefBuckets,
		},
		clientStreamRecvHistogram:        nil,
		clientStreamSendHistogramEnabled: false,
		clientStreamSendHistogramOpts: prom.HistogramOpts{
			Name:    "grpc_client_msg_send_handling_seconds",
			Help:    "Histogram of response latency (seconds) of the gRPC single message send.",
			Buckets: prom.DefBuckets,
		},
		clientStreamSendHistogram: nil,
	}
}

// Describe sends the super-set of all possible descriptors of metrics
// collected by this Collector to the provided channel and returns once
// the last descriptor has been sent.
func (m *ClientMetrics) Describe(ch chan<- *prom.Desc) {
	m.clientStartedCounter.Describe(ch)
	m.clientHandledCounter.Describe(ch)
	m.clientStreamMsgReceived.Describe(ch)
	m.clientStreamMsgSent.Describe(ch)
	if m.clientHandledHistogramEnabled {
		m.clientHandledHistogram.Describe(ch)
	}
	if m.clientStreamRecvHistogramEnabled {
		m.clientStreamRecvHistogram.Describe(ch)
	}
	if m.clientStreamSendHistogramEnabled {
		m.clientStreamSendHistogram.Describe(ch)
	}
}

// Collect is called by the Prometheus registry when collecting
// metrics. The implementation sends each collected metric via the
// provided channel and returns once the last metric has been sent.
func (m *ClientMetrics) Collect(ch chan<- prom.Metric) {
	m.clientStartedCounter.Collect(ch)
	m.clientHandledCounter.Collect(ch)
	m.clientStreamMsgReceived.Collect(ch)
	m.clientStreamMsgSent.Collect(ch)
	if m.clientHandledHistogramEnabled {
		m.clientHandledHistogram.Collect(ch)
	}
	if m.clientStreamRecvHistogramEnabled {
		m.clientStreamRecvHistogram.Collect(ch)
	}
	if m.clientStreamSendHistogramEnabled {
		m.clientStreamSendHistogram.Collect(ch)
	}
}

// EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs.
// Histogram metrics can be very expensive for Prometheus to retain and query.
func (m *ClientMetrics) EnableClientHandlingTimeHistogram(opts ...HistogramOption) {
	for _, o := range opts {
		o(&m.clientHandledHistogramOpts)
	}
	if !m.clientHandledHistogramEnabled {
		m.clientHandledHistogram = prom.NewHistogramVec(
			m.clientHandledHistogramOpts,
			[]string{"grpc_type", "grpc_service", "grpc_method"},
		)
	}
	m.clientHandledHistogramEnabled = true
}

// EnableClientStreamReceiveTimeHistogram turns on recording of single message receive time of streaming RPCs.
// Histogram metrics can be very expensive for Prometheus to retain and query.
func (m *ClientMetrics) EnableClientStreamReceiveTimeHistogram(opts ...HistogramOption) {
	for _, o := range opts {
		o(&m.clientHandledHistogramOpts)
	}

	if !m.clientStreamRecvHistogramEnabled {
		m.clientStreamRecvHistogram = prom.NewHistogramVec(
			m.clientStreamRecvHistogramOpts,
			[]string{"grpc_type", "grpc_service", "grpc_method"},
		)
	}

	m.clientStreamRecvHistogramEnabled = true
}

// EnableClientStreamSendTimeHistogram turns on recording of single message send time of streaming RPCs.
// Histogram metrics can be very expensive for Prometheus to retain and query.
func (m *ClientMetrics) EnableClientStreamSendTimeHistogram(opts ...HistogramOption) {
	for _, o := range opts {
		o(&m.clientHandledHistogramOpts)
	}

	if !m.clientStreamSendHistogramEnabled {
		m.clientStreamSendHistogram = prom.NewHistogramVec(
			m.clientStreamSendHistogramOpts,
			[]string{"grpc_type", "grpc_service", "grpc_method"},
		)
	}

	m.clientStreamSendHistogramEnabled = true
}

// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs.
func (m *ClientMetrics) UnaryClientInterceptor() func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
	return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
		monitor := newClientReporter(m, Unary, method)
		monitor.SentMessage()
		err := invoker(ctx, method, req, reply, cc, opts...)
		if err != nil {
			monitor.ReceivedMessage()
		}
		st, _ := status.FromError(err)
		monitor.Handled(st.Code())
		return err
	}
}

// StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs.
func (m *ClientMetrics) StreamClientInterceptor() func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
	return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
		monitor := newClientReporter(m, clientStreamType(desc), method)
		clientStream, err := streamer(ctx, desc, cc, method, opts...)
		if err != nil {
			st, _ := status.FromError(err)
			monitor.Handled(st.Code())
			return nil, err
		}
		return &monitoredClientStream{clientStream, monitor}, nil
	}
}

func clientStreamType(desc *grpc.StreamDesc) grpcType {
	if desc.ClientStreams && !desc.ServerStreams {
		return ClientStream
	} else if !desc.ClientStreams && desc.ServerStreams {
		return ServerStream
	}
	return BidiStream
}

// monitoredClientStream wraps grpc.ClientStream allowing each Sent/Recv of message to increment counters.
type monitoredClientStream struct {
	grpc.ClientStream
	monitor *clientReporter
}

func (s *monitoredClientStream) SendMsg(m interface{}) error {
	timer := s.monitor.SendMessageTimer()
	err := s.ClientStream.SendMsg(m)
	timer.ObserveDuration()
	if err == nil {
		s.monitor.SentMessage()
	}
	return err
}

func (s *monitoredClientStream) RecvMsg(m interface{}) error {
	timer := s.monitor.ReceiveMessageTimer()
	err := s.ClientStream.RecvMsg(m)
	timer.ObserveDuration()

	if err == nil {
		s.monitor.ReceivedMessage()
	} else if err == io.EOF {
		s.monitor.Handled(codes.OK)
	} else {
		st, _ := status.FromError(err)
		s.monitor.Handled(st.Code())
	}
	return err
}
<commit_msg>Apply suggestions from code review<commit_after>package grpc_prometheus

import (
	"io"

	prom "github.com/prometheus/client_golang/prometheus"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

// ClientMetrics represents a collection of metrics to be registered on a
// Prometheus metrics registry for a gRPC client.
type ClientMetrics struct {
	clientStartedCounter             *prom.CounterVec
	clientHandledCounter             *prom.CounterVec
	clientStreamMsgReceived          *prom.CounterVec
	clientStreamMsgSent              *prom.CounterVec
	clientHandledHistogramEnabled    bool
	clientHandledHistogramOpts       prom.HistogramOpts
	clientHandledHistogram           *prom.HistogramVec
	clientStreamRecvHistogramEnabled bool
	clientStreamRecvHistogramOpts    prom.HistogramOpts
	clientStreamRecvHistogram        *prom.HistogramVec
	clientStreamSendHistogramEnabled bool
	clientStreamSendHistogramOpts    prom.HistogramOpts
	clientStreamSendHistogram        *prom.HistogramVec
}

// NewClientMetrics returns a ClientMetrics object. Use a new instance of
// ClientMetrics when not using the default Prometheus metrics registry, for
// example when wanting to control which metrics are added to a registry as
// opposed to automatically adding metrics via init functions.
func NewClientMetrics(counterOpts ...CounterOption) *ClientMetrics {
	opts := counterOptions(counterOpts)
	return &ClientMetrics{
		clientStartedCounter: prom.NewCounterVec(
			opts.apply(prom.CounterOpts{
				Name: "grpc_client_started_total",
				Help: "Total number of RPCs started on the client.",
			}), []string{"grpc_type", "grpc_service", "grpc_method"}),

		clientHandledCounter: prom.NewCounterVec(
			opts.apply(prom.CounterOpts{
				Name: "grpc_client_handled_total",
				Help: "Total number of RPCs completed by the client, regardless of success or failure.",
			}), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}),

		clientStreamMsgReceived: prom.NewCounterVec(
			opts.apply(prom.CounterOpts{
				Name: "grpc_client_msg_received_total",
				Help: "Total number of RPC stream messages received by the client.",
			}), []string{"grpc_type", "grpc_service", "grpc_method"}),

		clientStreamMsgSent: prom.NewCounterVec(
			opts.apply(prom.CounterOpts{
				Name: "grpc_client_msg_sent_total",
				Help: "Total number of gRPC stream messages sent by the client.",
			}), []string{"grpc_type", "grpc_service", "grpc_method"}),

		clientHandledHistogramEnabled: false,
		clientHandledHistogramOpts: prom.HistogramOpts{
			Name:    "grpc_client_handling_seconds",
			Help:    "Histogram of response latency (seconds) of the gRPC until it is finished by the application.",
			Buckets: prom.DefBuckets,
		},
		clientHandledHistogram:           nil,
		clientStreamRecvHistogramEnabled: false,
		clientStreamRecvHistogramOpts: prom.HistogramOpts{
			Name:    "grpc_client_msg_recv_handling_seconds",
			Help:    "Histogram of response latency (seconds) of the gRPC single message receive.",
			Buckets: prom.DefBuckets,
		},
		clientStreamRecvHistogram:        nil,
		clientStreamSendHistogramEnabled: false,
		clientStreamSendHistogramOpts: prom.HistogramOpts{
			Name:    "grpc_client_msg_send_handling_seconds",
			Help:    "Histogram of response latency (seconds) of the gRPC single message send.",
			Buckets: prom.DefBuckets,
		},
		clientStreamSendHistogram: nil,
	}
}

// Describe sends the super-set of all possible descriptors of metrics
// collected by this Collector to the provided channel and returns once
// the last descriptor has been sent.
func (m *ClientMetrics) Describe(ch chan<- *prom.Desc) {
	m.clientStartedCounter.Describe(ch)
	m.clientHandledCounter.Describe(ch)
	m.clientStreamMsgReceived.Describe(ch)
	m.clientStreamMsgSent.Describe(ch)
	if m.clientHandledHistogramEnabled {
		m.clientHandledHistogram.Describe(ch)
	}
	if m.clientStreamRecvHistogramEnabled {
		m.clientStreamRecvHistogram.Describe(ch)
	}
	if m.clientStreamSendHistogramEnabled {
		m.clientStreamSendHistogram.Describe(ch)
	}
}

// Collect is called by the Prometheus registry when collecting
// metrics. The implementation sends each collected metric via the
// provided channel and returns once the last metric has been sent.
func (m *ClientMetrics) Collect(ch chan<- prom.Metric) {
	m.clientStartedCounter.Collect(ch)
	m.clientHandledCounter.Collect(ch)
	m.clientStreamMsgReceived.Collect(ch)
	m.clientStreamMsgSent.Collect(ch)
	if m.clientHandledHistogramEnabled {
		m.clientHandledHistogram.Collect(ch)
	}
	if m.clientStreamRecvHistogramEnabled {
		m.clientStreamRecvHistogram.Collect(ch)
	}
	if m.clientStreamSendHistogramEnabled {
		m.clientStreamSendHistogram.Collect(ch)
	}
}

// EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs.
// Histogram metrics can be very expensive for Prometheus to retain and query.
func (m *ClientMetrics) EnableClientHandlingTimeHistogram(opts ...HistogramOption) {
	for _, o := range opts {
		o(&m.clientHandledHistogramOpts)
	}
	if !m.clientHandledHistogramEnabled {
		m.clientHandledHistogram = prom.NewHistogramVec(
			m.clientHandledHistogramOpts,
			[]string{"grpc_type", "grpc_service", "grpc_method"},
		)
	}
	m.clientHandledHistogramEnabled = true
}

// EnableClientStreamReceiveTimeHistogram turns on recording of single message receive time of streaming RPCs.
// Histogram metrics can be very expensive for Prometheus to retain and query.
func (m *ClientMetrics) EnableClientStreamReceiveTimeHistogram(opts ...HistogramOption) {
	for _, o := range opts {
		o(&m.clientStreamRecvHistogramOpts)
	}

	if !m.clientStreamRecvHistogramEnabled {
		m.clientStreamRecvHistogram = prom.NewHistogramVec(
			m.clientStreamRecvHistogramOpts,
			[]string{"grpc_type", "grpc_service", "grpc_method"},
		)
	}

	m.clientStreamRecvHistogramEnabled = true
}

// EnableClientStreamSendTimeHistogram turns on recording of single message send time of streaming RPCs.
// Histogram metrics can be very expensive for Prometheus to retain and query.
func (m *ClientMetrics) EnableClientStreamSendTimeHistogram(opts ...HistogramOption) {
	for _, o := range opts {
		o(&m.clientStreamSendHistogramOpts)
	}

	if !m.clientStreamSendHistogramEnabled {
		m.clientStreamSendHistogram = prom.NewHistogramVec(
			m.clientStreamSendHistogramOpts,
			[]string{"grpc_type", "grpc_service", "grpc_method"},
		)
	}

	m.clientStreamSendHistogramEnabled = true
}

// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs.
func (m *ClientMetrics) UnaryClientInterceptor() func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
	return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
		monitor := newClientReporter(m, Unary, method)
		monitor.SentMessage()
		err := invoker(ctx, method, req, reply, cc, opts...)
		if err != nil {
			monitor.ReceivedMessage()
		}
		st, _ := status.FromError(err)
		monitor.Handled(st.Code())
		return err
	}
}

// StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs.
func (m *ClientMetrics) StreamClientInterceptor() func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
	return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
		monitor := newClientReporter(m, clientStreamType(desc), method)
		clientStream, err := streamer(ctx, desc, cc, method, opts...)
		if err != nil {
			st, _ := status.FromError(err)
			monitor.Handled(st.Code())
			return nil, err
		}
		return &monitoredClientStream{clientStream, monitor}, nil
	}
}

func clientStreamType(desc *grpc.StreamDesc) grpcType {
	if desc.ClientStreams && !desc.ServerStreams {
		return ClientStream
	} else if !desc.ClientStreams && desc.ServerStreams {
		return ServerStream
	}
	return BidiStream
}

// monitoredClientStream wraps grpc.ClientStream allowing each Sent/Recv of message to increment counters.
type monitoredClientStream struct {
	grpc.ClientStream
	monitor *clientReporter
}

func (s *monitoredClientStream) SendMsg(m interface{}) error {
	timer := s.monitor.SendMessageTimer()
	err := s.ClientStream.SendMsg(m)
	timer.ObserveDuration()
	if err == nil {
		s.monitor.SentMessage()
	}
	return err
}

func (s *monitoredClientStream) RecvMsg(m interface{}) error {
	timer := s.monitor.ReceiveMessageTimer()
	err := s.ClientStream.RecvMsg(m)
	timer.ObserveDuration()

	if err == nil {
		s.monitor.ReceivedMessage()
	} else if err == io.EOF {
		s.monitor.Handled(codes.OK)
	} else {
		st, _ := status.FromError(err)
		s.monitor.Handled(st.Code())
	}
	return err
}
<|endoftext|>


<commit_before>package consumers

import (
	"time"

	"github.com/mc0/okq/db"
	"github.com/mc0/okq/log"
	"github.com/mediocregopher/pubsubch"
)

// This piece runs separately from the main consumer thread. Its job is to
// subscribe to the notify redis channel and deal out the publishes it sees, as
// well as manage the subscription to list to make sure it's always subscribed
// to the correct channels

// Only need a buffer of size one. If two things are writing to the buffer, they
// both want subbed queues updated
var updateNotifyCh = make(chan struct{}, 1)

// This routine makes a connection to redis, and spawns of a subManager routine.
// That routine's job is to manage what channels this one's sub connection is
// actually subscribed to, while this one reads off the publish channel and
// passes those messages along
func subSpin() {
	for {
		addr := db.Inst.GetAddr()
		subConn, err := pubsubch.DialTimeout(addr, 2500*time.Millisecond)
		if err != nil {
			log.L.Printf("notifyConsumers error connecting: %v", err)
			time.Sleep(1 * time.Second)
			continue
		}

		// When this is written to it will cause the subManager routine to
		// subscribe to new queue channels and unsubscribe from old ones as
		// necessary. We proxy all messages from updateNotifyCh to this one, so
		// we can close this one when we want to close the subManager
		triggerUpdateCh := make(chan struct{}, 1)
		go subManager(subConn, triggerUpdateCh)

	selectLoop:
		for {
			select {
			// pass the notification on to the subManager for processing
			case s := <-updateNotifyCh:
				select {
				case triggerUpdateCh <- s:
				default:
				}
			// listen for any publishes and fan them out to each client
			case pub, ok := <-subConn.PublishCh:
				if !ok {
					break selectLoop
				}
				queueName, err := db.GetQueueNameFromKey(pub.Channel)
				if err != nil {
					log.L.Printf("notifyConsumer got unknown channel %v: %v", pub.Channel, err)
					continue
				}
				clients := queueClients(queueName)
				for _, client := range clients {
					client.Notify(queueName)
				}
			}
		}

		close(triggerUpdateCh)
		subConn.Close()
	}
}

// subManager is responsible for adding/removing channel subscriptions in redis.
// We do all this craziness instead of just doing a simple psubscribe so that if
// we have a bunch of okq instances, this one will only handle the publishes for
// the channels that the consumers connected to it actually care about. So we
// could partition consumer group A too hit one okq instance and group B hit
// another, and those two instances won't be stuck processing publishes that
// they don't care about
func subManager(subConn *pubsubch.PubSubCh, updateCh chan struct{}) {
	lastSubscribedQueues := []string{}
	// ensure we run immediately by filling the channel
	select {
	case updateCh <- struct{}{}:
	default:
	}

	for {
		if _, ok := <-updateCh; !ok {
			break
		}

		queueNames := registeredQueues()
		queuesAdded := stringSliceSub(queueNames, lastSubscribedQueues)
		queuesRemoved := stringSliceSub(lastSubscribedQueues, queueNames)

		lastSubscribedQueues = queueNames

		if len(queuesRemoved) != 0 {
			var redisChannels []string
			for i := range queuesRemoved {
				channelName := db.QueueChannelNameKey(queuesRemoved[i])
				redisChannels = append(redisChannels, channelName)
			}

			log.L.Debugf("unsubscribing from %v", redisChannels)
			if _, err := subConn.Unsubscribe(redisChannels...); err != nil {
				log.L.Printf("notifyConsumers error unsubscribing: %v", err)
				break
			}
		}

		if len(queuesAdded) != 0 {
			var redisChannels []string
			for i := range queuesAdded {
				channelName := db.QueueChannelNameKey(queuesAdded[i])
				redisChannels = append(redisChannels, channelName)
			}

			log.L.Debugf("subscribing to %v", redisChannels)
			if _, err := subConn.Subscribe(redisChannels...); err != nil {
				log.L.Printf("notifyConsumers error subscribing: %v", err)
				break
			}
		}
	}

	subConn.Close()
}
<commit_msg>periodically ping on the notify pubsub redis connection<commit_after>package consumers

import (
	"time"

	"github.com/mc0/okq/db"
	"github.com/mc0/okq/log"
	"github.com/mediocregopher/pubsubch"
)

// This piece runs separately from the main consumer thread. Its job is to
// subscribe to the notify redis channel and deal out the publishes it sees, as
// well as manage the subscription to list to make sure it's always subscribed
// to the correct channels

// Only need a buffer of size one. If two things are writing to the buffer, they
// both want subbed queues updated
var updateNotifyCh = make(chan struct{}, 1)

// This routine makes a connection to redis, and spawns of a subManager routine.
// That routine's job is to manage what channels this one's sub connection is
// actually subscribed to, while this one reads off the publish channel and
// passes those messages along
func subSpin() {
	for {
		addr := db.Inst.GetAddr()
		subConn, err := pubsubch.DialTimeout(addr, 2500*time.Millisecond)
		if err != nil {
			log.L.Printf("notifyConsumers error connecting: %v", err)
			time.Sleep(1 * time.Second)
			continue
		}

		// When this is written to it will cause the subManager routine to
		// subscribe to new queue channels and unsubscribe from old ones as
		// necessary. We proxy all messages from updateNotifyCh to this one, so
		// we can close this one when we want to close the subManager
		triggerUpdateCh := make(chan struct{}, 1)
		go subManager(subConn, triggerUpdateCh)

	selectLoop:
		for {
			select {
			// pass the notification on to the subManager for processing
			case s := <-updateNotifyCh:
				select {
				case triggerUpdateCh <- s:
				default:
				}
			// listen for any publishes and fan them out to each client
			case pub, ok := <-subConn.PublishCh:
				if !ok {
					break selectLoop
				}
				queueName, err := db.GetQueueNameFromKey(pub.Channel)
				if err != nil {
					log.L.Printf("notifyConsumer got unknown channel %v: %v", pub.Channel, err)
					continue
				}
				clients := queueClients(queueName)
				for _, client := range clients {
					client.Notify(queueName)
				}
			}
		}

		close(triggerUpdateCh)
		subConn.Close()
	}
}

// subManager is responsible for adding/removing channel subscriptions in redis.
// We do all this craziness instead of just doing a simple psubscribe so that if
// we have a bunch of okq instances, this one will only handle the publishes for
// the channels that the consumers connected to it actually care about. So we
// could partition consumer group A too hit one okq instance and group B hit
// another, and those two instances won't be stuck processing publishes that
// they don't care about
func subManager(subConn *pubsubch.PubSubCh, updateCh chan struct{}) {
	lastSubscribedQueues := []string{}
	tick := time.Tick(30 * time.Second)
	// ensure we run immediately by filling the channel
	select {
	case updateCh <- struct{}{}:
	default:
	}

outer:
	for {
		select {
		case <-tick:
			if err := subConn.Ping(); err != nil {
				log.L.Printf("notifyConsumers error pinging: %v", err)
				break outer
			}
		case _, ok := <-updateCh:
			if !ok {
				break outer
			}

			queueNames := registeredQueues()
			queuesAdded := stringSliceSub(queueNames, lastSubscribedQueues)
			queuesRemoved := stringSliceSub(lastSubscribedQueues, queueNames)

			lastSubscribedQueues = queueNames

			if len(queuesRemoved) != 0 {
				var redisChannels []string
				for i := range queuesRemoved {
					channelName := db.QueueChannelNameKey(queuesRemoved[i])
					redisChannels = append(redisChannels, channelName)
				}

				log.L.Debugf("unsubscribing from %v", redisChannels)
				if _, err := subConn.Unsubscribe(redisChannels...); err != nil {
					log.L.Printf("notifyConsumers error unsubscribing: %v", err)
					break outer
				}
			}

			if len(queuesAdded) != 0 {
				var redisChannels []string
				for i := range queuesAdded {
					channelName := db.QueueChannelNameKey(queuesAdded[i])
					redisChannels = append(redisChannels, channelName)
				}

				log.L.Debugf("subscribing to %v", redisChannels)
				if _, err := subConn.Subscribe(redisChannels...); err != nil {
					log.L.Printf("notifyConsumers error subscribing: %v", err)
					break outer
				}
			}
		}
	}

	subConn.Close()
}
<|endoftext|>


<commit_before>package sparta

import (
	"bytes"
	"fmt"
	"strings"
	"text/template"

	gocf "github.com/mweagle/go-cloudformation"
	"github.com/rs/zerolog"
)

// Utility function to marshal an interface
func marshalInterface(item interface{}) interface{} {
	if item != nil {
		return item
	}
	return nil
}

// Utility function to marshal an int
func marshalInt(intVal int64) *gocf.IntegerExpr {
	if intVal != 0 {
		return gocf.Integer(intVal)
	}
	return nil
}

// Utility function to marshal a string
func marshalString(stringVal string) *gocf.StringExpr {
	if stringVal != "" {
		return gocf.String(stringVal)
	}
	return nil
}

func marshalStringExpr(stringExpr gocf.Stringable) *gocf.StringExpr {
	if stringExpr != nil {
		return stringExpr.String()
	}
	return nil
}

// Utility function to marshal a string lsit
func marshalStringList(stringVals []string) *gocf.StringListExpr {
	if len(stringVals) != 0 {
		stringableList := make([]gocf.Stringable, len(stringVals))
		for eachIndex, eachStringVal := range stringVals {
			stringableList[eachIndex] = gocf.String(eachStringVal)
		}
		return gocf.StringList(stringableList...)
	}
	return nil
}

// Utility function to marshal a boolean
func marshalBool(boolValue bool) *gocf.BoolExpr {
	if !boolValue {
		return gocf.Bool(boolValue)
	}
	return nil
}

// resourceOutputs is responsible for returning the conditional
// set of CloudFormation outputs for a given resource type.
func resourceOutputs(resourceName string,
	resource gocf.ResourceProperties,
	logger *zerolog.Logger) ([]string, error) {

	outputProps := []string{}
	switch typedResource := resource.(type) {
	case gocf.IAMRole:
		// NOP
	case *gocf.DynamoDBTable:
		if typedResource.StreamSpecification != nil {
			outputProps = append(outputProps, "StreamArn")
		}
	case gocf.DynamoDBTable:
		if typedResource.StreamSpecification != nil {
			outputProps = append(outputProps, "StreamArn")
		}
	case gocf.KinesisStream,
		*gocf.KinesisStream:
		outputProps = append(outputProps, "Arn")
	case gocf.Route53RecordSet,
		*gocf.Route53RecordSet:
		// NOP
	case gocf.S3Bucket,
		*gocf.S3Bucket:
		outputProps = append(outputProps, "DomainName", "WebsiteURL")
	case gocf.SNSTopic,
		*gocf.SNSTopic:
		outputProps = append(outputProps, "TopicName")
	case gocf.SQSQueue,
		*gocf.SQSQueue:
		outputProps = append(outputProps, "Arn", "QueueName")
	default:
		logger.Warn().
			Str("ResourceType", fmt.Sprintf("%T", typedResource)).
			Msg("Discovery information for dependency not yet implemented")
	}
	return outputProps, nil
}

func newCloudFormationResource(resourceType string, logger *zerolog.Logger) (gocf.ResourceProperties, error) {
	resProps := gocf.NewResourceByType(resourceType)
	if nil == resProps {

		logger.Fatal().
			Str("Type", resourceType).
			Msg("Failed to create CloudFormation CustomResource!")

		return nil, fmt.Errorf("unsupported CustomResourceType: %s", resourceType)
	}
	return resProps, nil
}

type discoveryDataTemplate struct {
	ResourceID         string
	ResourceType       string
	ResourceProperties string
}

var discoveryDataForResourceDependency = `
	{
		"ResourceID" : "<< .ResourceID >>",
		"ResourceRef" : "{"Ref":"<< .ResourceID >>"}",
		"ResourceType" : "<< .ResourceType >>",
		"Properties" : {
			<< .ResourceProperties >>
		}
	}
`

func discoveryResourceInfoForDependency(cfTemplate *gocf.Template,
	logicalResourceName string,
	logger *zerolog.Logger) ([]byte, error) {

	item, ok := cfTemplate.Resources[logicalResourceName]
	if !ok {
		return nil, nil
	}
	resourceOutputs, resourceOutputsErr := resourceOutputs(logicalResourceName,
		item.Properties,
		logger)
	if resourceOutputsErr != nil {
		return nil, resourceOutputsErr
	}
	// Template data
	templateData := &discoveryDataTemplate{
		ResourceID:   logicalResourceName,
		ResourceType: item.Properties.CfnResourceType(),
	}
	quotedAttrs := make([]string, len(resourceOutputs))
	for eachIndex, eachOutput := range resourceOutputs {
		quotedAttrs[eachIndex] = fmt.Sprintf(`"%s" :"{ "Fn::GetAtt" : [ "%s", "%s" ] }"`,
			eachOutput,
			logicalResourceName,
			eachOutput)
	}
	templateData.ResourceProperties = strings.Join(quotedAttrs, ",")

	// Create the data that can be stuffed into Environment
	discoveryTemplate, discoveryTemplateErr := template.New("discoveryResourceData").
		Delims("<<", ">>").
		Parse(discoveryDataForResourceDependency)
	if nil != discoveryTemplateErr {
		return nil, discoveryTemplateErr
	}

	var templateResults bytes.Buffer
	evalResultErr := discoveryTemplate.Execute(&templateResults, templateData)
	return templateResults.Bytes(), evalResultErr
}
func safeAppendDependency(resource *gocf.Resource, dependencyName string) {
	if nil == resource.DependsOn {
		resource.DependsOn = []string{}
	}
	resource.DependsOn = append(resource.DependsOn, dependencyName)
}
func safeMetadataInsert(resource *gocf.Resource, key string, value interface{}) {
	if nil == resource.Metadata {
		resource.Metadata = make(map[string]interface{})
	}
	resource.Metadata[key] = value
}
<commit_msg>Add additional marshal type<commit_after>package sparta

import (
	"bytes"
	"fmt"
	"strings"
	"text/template"

	gocf "github.com/mweagle/go-cloudformation"
	"github.com/rs/zerolog"
)

// Utility function to marshal an interface
func marshalInterface(item interface{}) interface{} {
	if item != nil {
		return item
	}
	return nil
}

// Utility function to marshal array of strings
func marshalStringArray(vals []string) *gocf.StringListExpr {
	if len(vals) <= 0 {
		return nil
	}
	arrValues := []gocf.Stringable{}
	for i := 0; i != len(vals); i++ {
		arrValues = append(arrValues, gocf.String(vals[i]))
	}
	return gocf.StringList(arrValues...)
}

// Utility function to marshal an int
func marshalInt(intVal int64) *gocf.IntegerExpr {
	if intVal != 0 {
		return gocf.Integer(intVal)
	}
	return nil
}

// Utility function to marshal a string
func marshalString(stringVal string) *gocf.StringExpr {
	if stringVal != "" {
		return gocf.String(stringVal)
	}
	return nil
}

func marshalStringExpr(stringExpr gocf.Stringable) *gocf.StringExpr {
	if stringExpr != nil {
		return stringExpr.String()
	}
	return nil
}

// Utility function to marshal a string lsit
func marshalStringList(stringVals []string) *gocf.StringListExpr {
	if len(stringVals) != 0 {
		stringableList := make([]gocf.Stringable, len(stringVals))
		for eachIndex, eachStringVal := range stringVals {
			stringableList[eachIndex] = gocf.String(eachStringVal)
		}
		return gocf.StringList(stringableList...)
	}
	return nil
}

// Utility function to marshal a boolean
func marshalBool(boolValue bool) *gocf.BoolExpr {
	if !boolValue {
		return gocf.Bool(boolValue)
	}
	return nil
}

// resourceOutputs is responsible for returning the conditional
// set of CloudFormation outputs for a given resource type.
func resourceOutputs(resourceName string,
	resource gocf.ResourceProperties,
	logger *zerolog.Logger) ([]string, error) {

	outputProps := []string{}
	switch typedResource := resource.(type) {
	case gocf.IAMRole:
		// NOP
	case *gocf.DynamoDBTable:
		if typedResource.StreamSpecification != nil {
			outputProps = append(outputProps, "StreamArn")
		}
	case gocf.DynamoDBTable:
		if typedResource.StreamSpecification != nil {
			outputProps = append(outputProps, "StreamArn")
		}
	case gocf.KinesisStream,
		*gocf.KinesisStream:
		outputProps = append(outputProps, "Arn")
	case gocf.Route53RecordSet,
		*gocf.Route53RecordSet:
		// NOP
	case gocf.S3Bucket,
		*gocf.S3Bucket:
		outputProps = append(outputProps, "DomainName", "WebsiteURL")
	case gocf.SNSTopic,
		*gocf.SNSTopic:
		outputProps = append(outputProps, "TopicName")
	case gocf.SQSQueue,
		*gocf.SQSQueue:
		outputProps = append(outputProps, "Arn", "QueueName")
	default:
		logger.Warn().
			Str("ResourceType", fmt.Sprintf("%T", typedResource)).
			Msg("Discovery information for dependency not yet implemented")
	}
	return outputProps, nil
}

func newCloudFormationResource(resourceType string, logger *zerolog.Logger) (gocf.ResourceProperties, error) {
	resProps := gocf.NewResourceByType(resourceType)
	if nil == resProps {

		logger.Fatal().
			Str("Type", resourceType).
			Msg("Failed to create CloudFormation CustomResource!")

		return nil, fmt.Errorf("unsupported CustomResourceType: %s", resourceType)
	}
	return resProps, nil
}

type discoveryDataTemplate struct {
	ResourceID         string
	ResourceType       string
	ResourceProperties string
}

var discoveryDataForResourceDependency = `
	{
		"ResourceID" : "<< .ResourceID >>",
		"ResourceRef" : "{"Ref":"<< .ResourceID >>"}",
		"ResourceType" : "<< .ResourceType >>",
		"Properties" : {
			<< .ResourceProperties >>
		}
	}
`

func discoveryResourceInfoForDependency(cfTemplate *gocf.Template,
	logicalResourceName string,
	logger *zerolog.Logger) ([]byte, error) {

	item, ok := cfTemplate.Resources[logicalResourceName]
	if !ok {
		return nil, nil
	}
	resourceOutputs, resourceOutputsErr := resourceOutputs(logicalResourceName,
		item.Properties,
		logger)
	if resourceOutputsErr != nil {
		return nil, resourceOutputsErr
	}
	// Template data
	templateData := &discoveryDataTemplate{
		ResourceID:   logicalResourceName,
		ResourceType: item.Properties.CfnResourceType(),
	}
	quotedAttrs := make([]string, len(resourceOutputs))
	for eachIndex, eachOutput := range resourceOutputs {
		quotedAttrs[eachIndex] = fmt.Sprintf(`"%s" :"{ "Fn::GetAtt" : [ "%s", "%s" ] }"`,
			eachOutput,
			logicalResourceName,
			eachOutput)
	}
	templateData.ResourceProperties = strings.Join(quotedAttrs, ",")

	// Create the data that can be stuffed into Environment
	discoveryTemplate, discoveryTemplateErr := template.New("discoveryResourceData").
		Delims("<<", ">>").
		Parse(discoveryDataForResourceDependency)
	if nil != discoveryTemplateErr {
		return nil, discoveryTemplateErr
	}

	var templateResults bytes.Buffer
	evalResultErr := discoveryTemplate.Execute(&templateResults, templateData)
	return templateResults.Bytes(), evalResultErr
}
func safeAppendDependency(resource *gocf.Resource, dependencyName string) {
	if nil == resource.DependsOn {
		resource.DependsOn = []string{}
	}
	resource.DependsOn = append(resource.DependsOn, dependencyName)
}
func safeMetadataInsert(resource *gocf.Resource, key string, value interface{}) {
	if nil == resource.Metadata {
		resource.Metadata = make(map[string]interface{})
	}
	resource.Metadata[key] = value
}
<|endoftext|>


<commit_before>package builds

import (
	"log"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		// allow all connections
		return true
	},
}

func (handler *Handler) LogInput(w http.ResponseWriter, r *http.Request) {
	guid := mux.Vars(r)["guid"]

	handler.buildsMutex.RLock()
	build, found := handler.builds[guid]
	handler.buildsMutex.RUnlock()

	if !found {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}

	for {
		_, msg, err := conn.ReadMessage()
		if err != nil {
			break
		}

		build.logBuffer.Write(msg)
	}
}

func (handler *Handler) LogOutput(w http.ResponseWriter, r *http.Request) {
	guid := mux.Vars(r)["guid"]

	handler.buildsMutex.RLock()
	build, found := handler.builds[guid]
	handler.buildsMutex.RUnlock()

	if !found {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}

	build.logBuffer.Attach(conn)
}
<commit_msg>add log entry for failure to read websocket msg<commit_after>package builds

import (
	"log"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		// allow all connections
		return true
	},
}

func (handler *Handler) LogInput(w http.ResponseWriter, r *http.Request) {
	guid := mux.Vars(r)["guid"]

	handler.buildsMutex.RLock()
	build, found := handler.builds[guid]
	handler.buildsMutex.RUnlock()

	if !found {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}

	for {
		_, msg, err := conn.ReadMessage()
		if err != nil {
			log.Println("error reading message:", err)
			break
		}

		build.logBuffer.Write(msg)
	}
}

func (handler *Handler) LogOutput(w http.ResponseWriter, r *http.Request) {
	guid := mux.Vars(r)["guid"]

	handler.buildsMutex.RLock()
	build, found := handler.builds[guid]
	handler.buildsMutex.RUnlock()

	if !found {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}

	build.logBuffer.Attach(conn)
}
<|endoftext|>


<commit_before>package api

import (
	"testing"
)

// TestApiClient tests that the API client connects to the server tester and
// can call and decode routes correctly.
func TestApiClient(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	st, err := createServerTester("TestApiClient")
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.Close()

	c := NewClient(st.server.listener.Addr().String(), "")
	var gatewayInfo GatewayGET
	err = c.Get("/gateway", &gatewayInfo)
	if err != nil {
		t.Fatal(err)
	}
}

// TestAuthenticatedApiClient tests that the API client connects to an
// authenticated server tester and can call and decode routes correctly, using
// the correct password.
func TestAuthenticatedApiClient(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	testpass := "testPassword"
	st, err := createAuthenticatedServerTester("TestAuthenticatedApiClient", testpass)
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.Close()

	c := NewClient(st.server.listener.Addr().String(), "")
	var walletAddress WalletAddressGET
	err = c.Get("/wallet/address", &walletAddress)
	if err == nil {
		t.Fatal("api.Client did not return an error when requesting an authenticated resource without a password")
	}
	c = NewClient(st.server.listener.Addr().String(), testpass)
	err = c.Get("/wallet/address", &walletAddress)
	if err != nil {
		t.Fatal(err)
	}
}
<commit_msg>use TestIntegration prefix<commit_after>package api

import (
	"testing"
)

// TestApiClient tests that the API client connects to the server tester and
// can call and decode routes correctly.
func TestIntegrationApiClient(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	st, err := createServerTester("TestApiClient")
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.Close()

	c := NewClient(st.server.listener.Addr().String(), "")
	var gatewayInfo GatewayGET
	err = c.Get("/gateway", &gatewayInfo)
	if err != nil {
		t.Fatal(err)
	}
}

// TestAuthenticatedApiClient tests that the API client connects to an
// authenticated server tester and can call and decode routes correctly, using
// the correct password.
func TestIntegrationAuthenticatedApiClient(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	testpass := "testPassword"
	st, err := createAuthenticatedServerTester("TestAuthenticatedApiClient", testpass)
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.Close()

	c := NewClient(st.server.listener.Addr().String(), "")
	var walletAddress WalletAddressGET
	err = c.Get("/wallet/address", &walletAddress)
	if err == nil {
		t.Fatal("api.Client did not return an error when requesting an authenticated resource without a password")
	}
	c = NewClient(st.server.listener.Addr().String(), testpass)
	err = c.Get("/wallet/address", &walletAddress)
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import "github.com/urfave/cli"

// init injects our "traceroute" related commands/options.
func init() {
	// Fill-in the various commands
	cliCommands = append(cliCommands, cli.Command{
		Name:        "traceroute",
		Aliases:     []string{"trace"},
		Usage:       "traceroute to given host/IP",
		Description: "Send Traceroute queries to an host/IP",
		Flags: []cli.Flag{
			cli.BoolFlag{
				Name:        "6, ipv6",
				Usage:       "displays only IPv6",
				Destination: &fWant6,
			},
			cli.BoolFlag{
				Name:        "4, ipv4",
				Usage:       "displays only IPv4",
				Destination: &fWant4,
			},
		},
		Action: cmdTraceroute,
	})
}

func cmdTraceroute(c *cli.Context) error {
	return nil
}

<commit_msg>Implement Traceroute() with some options.<commit_after>package main

import (
	"fmt"
	"github.com/keltia/ripe-atlas"
	"github.com/urfave/cli"
	"log"
	"os"
)

// init injects our "traceroute" related commands/options.
func init() {
	// Fill-in the various commands
	cliCommands = append(cliCommands, cli.Command{
		Name:        "traceroute",
		Aliases:     []string{"trace"},
		Usage:       "traceroute to given host/IP",
		Description: "Send Traceroute queries to an host/IP",
		Flags: []cli.Flag{
			cli.IntFlag{
				Name:        "max_hops, m",
				Usage:       "Specify a maximum number of hops",
				Destination: &fMaxHops,
			},
			cli.IntFlag{
				Name:        "packet_size, s",
				Usage:       "Sends packets this size",
				Destination: &fPacketSize,
			},
			cli.BoolFlag{
				Name:        "6, ipv6",
				Usage:       "displays only IPv6",
				Destination: &fWant6,
			},
			cli.BoolFlag{
				Name:        "4, ipv4",
				Usage:       "displays only IPv4",
				Destination: &fWant4,
			},
		},
		Action: cmdTraceroute,
	})
}

func cmdTraceroute(c *cli.Context) error {
	// By default do both
	if !fWant4 && !fWant6 {
		fWant6, fWant4 = true, true
	}

	args := c.Args()
	if len(args) == 0 {
		log.Fatal("Error: you must specify a hostname/site!")
	}

	target := args[0]
	var defs []atlas.Definition

	if fWant4 {
		def := atlas.Definition{
			AF:          4,
			Description: fmt.Sprintf("Traceroute - %s", target),
			Type:        "traceroute",
			Target:      target,
		}
		if fPacketSize != 0 {
			def.Size = fPacketSize
		}
		if fMaxHops != 0 {
			def.MaxHops = fMaxHops
		}
		defs = append(defs, def)
	}

	if fWant6 {
		def := atlas.Definition{
			AF:          6,
			Description: fmt.Sprintf("Traceroute6 - %s", target),
			Type:        "traceroute",
			Target:      target,
		}
		if fPacketSize != 0 {
			def.Size = fPacketSize
		}
		if fMaxHops != 0 {
			def.MaxHops = fMaxHops
		}
		defs = append(defs, def)
	}

	req := atlas.MeasurementRequest{
		Definitions: defs,
		IsOneoff:    true,
	}

	// Default set of probes
	probes := atlas.ProbeSet{
		{
			Requested: mycnf.PoolSize,
			Type:      "area",
			Value:     "WW",
			Tags:      nil,
		},
	}

	req.Probes = probes
	log.Printf("req=%#v", req)
	//str := res.Result.Display()

	trc, err := atlas.Traceroute(req)
	if err != nil {
		fmt.Printf("err: %v", err)
		os.Exit(1)
	}
	fmt.Printf("NTP: %#v", trc)

	return nil
}
<|endoftext|>


<commit_before>package bbr_test

import (
	bratsutils "github.com/cloudfoundry/bosh-release-acceptance-tests/brats-utils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"fmt"
	"testing"

	"github.com/onsi/gomega/gexec"
)

const BLOBSTORE_ACCESS_LOG = "/var/vcap/sys/log/blobstore/blobstore_access.log"

func TestBBR(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "BBR Suite")
}

var (
	candidateWardenLinuxStemcellPath,
	bbrBinaryPath string
	bbrReleasePath string
)

var _ = SynchronizedBeforeSuite(func() []byte {
	bratsutils.Bootstrap()
	bratsutils.CreateAndUploadBOSHRelease()
	bratsutils.StartInnerBosh(
		fmt.Sprintf("-o %s", bratsutils.BoshDeploymentAssetPath("bbr.yml")),
		fmt.Sprintf("-o %s", bratsutils.AssetPath("latest-bbr-release.yml")),
		fmt.Sprintf("-v bbr_release_path=%s", bbrReleasePath),
	)

	return nil
}, func(data []byte) {
	bratsutils.Bootstrap()
	bbrBinaryPath = bratsutils.AssertEnvExists("BBR_BINARY_PATH")
	candidateWardenLinuxStemcellPath = bratsutils.AssertEnvExists("CANDIDATE_STEMCELL_TARBALL_PATH")
	bbrReleasePath = bratsutils.AssertEnvExists("BBR_RELEASE_PATH")
})

func bbr(args ...string) *gexec.Session {
	return bratsutils.ExecCommand(bbrBinaryPath, args...)
}
<commit_msg>Fix bbr suite to pull release from env variable before deploy<commit_after>package bbr_test

import (
	bratsutils "github.com/cloudfoundry/bosh-release-acceptance-tests/brats-utils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"fmt"
	"testing"

	"github.com/onsi/gomega/gexec"
)

const BLOBSTORE_ACCESS_LOG = "/var/vcap/sys/log/blobstore/blobstore_access.log"

func TestBBR(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "BBR Suite")
}

var (
	candidateWardenLinuxStemcellPath,
	bbrBinaryPath string
)

var _ = SynchronizedBeforeSuite(func() []byte {
	bbrReleasePath := bratsutils.AssertEnvExists("BBR_RELEASE_PATH")

	bratsutils.Bootstrap()
	bratsutils.CreateAndUploadBOSHRelease()
	bratsutils.StartInnerBosh(
		fmt.Sprintf("-o %s", bratsutils.BoshDeploymentAssetPath("bbr.yml")),
		fmt.Sprintf("-o %s", bratsutils.AssetPath("latest-bbr-release.yml")),
		fmt.Sprintf("-v bbr_release_path=%s", bbrReleasePath),
	)

	return nil
}, func(data []byte) {
	bratsutils.Bootstrap()
	bbrBinaryPath = bratsutils.AssertEnvExists("BBR_BINARY_PATH")
	candidateWardenLinuxStemcellPath = bratsutils.AssertEnvExists("CANDIDATE_STEMCELL_TARBALL_PATH")
})

func bbr(args ...string) *gexec.Session {
	return bratsutils.ExecCommand(bbrBinaryPath, args...)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func Logout(c *gin.Context) {
	removedCookie := http.Cookie{
		Name:  "session",
		MaxAge:   -1,
	}
	http.SetCookie(c.Writer, &removedCookie)
	c.Redirect(http.StatusFound, "/home/")
}<commit_msg>[logout] fix<commit_after>package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"github.com/gin-gonic/contrib/sessions"
)

func Logout(c *gin.Context) {
	session := sessions.Default(c)
	session.Delete("public")
	session.Save()
	c.Redirect(http.StatusFound, "/")
}
<|endoftext|>