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

package cmd

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

	"github.com/ghodss/yaml"
	"github.com/spf13/cobra"
	"go.uber.org/multierr"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"

	meshconfig "istio.io/api/mesh/v1alpha1"
	"istio.io/istio/pilot/cmd"
	"istio.io/istio/pilot/pkg/kube/inject"
	"istio.io/istio/pilot/pkg/model"
	"istio.io/istio/pkg/kube"
	"istio.io/pkg/log"
	"istio.io/pkg/version"
)

const (
	configMapKey       = "mesh"
	injectConfigMapKey = "config"
	valuesConfigMapKey = "values"
)

func createInterface(kubeconfig string) (kubernetes.Interface, error) {
	restConfig, err := kube.BuildClientConfig(kubeconfig, configContext)

	if err != nil {
		return nil, err
	}
	return kubernetes.NewForConfig(restConfig)
}

func getMeshConfigFromConfigMap(kubeconfig string) (*meshconfig.MeshConfig, error) {
	client, err := createInterface(kubeconfig)
	if err != nil {
		return nil, err
	}

	config, err := client.CoreV1().ConfigMaps(istioNamespace).Get(meshConfigMapName, metav1.GetOptions{})
	if err != nil {
		return nil, fmt.Errorf("could not read valid configmap %q from namespace  %q: %v - "+
			"Use --meshConfigFile or re-run kube-inject with `-i <istioSystemNamespace> and ensure valid MeshConfig exists",
			meshConfigMapName, istioNamespace, err)
	}
	// values in the data are strings, while proto might use a
	// different data type.  therefore, we have to get a value by a
	// key
	configYaml, exists := config.Data[configMapKey]
	if !exists {
		return nil, fmt.Errorf("missing configuration map key %q", configMapKey)
	}
	cfg, err := model.ApplyMeshConfigDefaults(configYaml)
	if err != nil {
		err = multierr.Append(fmt.Errorf("istioctl version %s cannot parse mesh config.  Install istioctl from the latest Istio release",
			version.Info.Version), err)
	}
	return cfg, err
}

// grabs the raw values from the ConfigMap. These are encoded as JSON.
func getValuesFromConfigMap(kubeconfig string) (string, error) {
	client, err := createInterface(kubeconfig)
	if err != nil {
		return "", err
	}

	config, err := client.CoreV1().ConfigMaps(istioNamespace).Get(injectConfigMapName, metav1.GetOptions{})
	if err != nil {
		return "", fmt.Errorf("could not find valid configmap %q from namespace  %q: %v - "+
			"Use --injectConfigFile or re-run kube-inject with `-i <istioSystemNamespace> and ensure istio-inject configmap exists",
			injectConfigMapName, istioNamespace, err)
	}

	valuesData, exists := config.Data[valuesConfigMapKey]
	if !exists {
		return "", fmt.Errorf("missing configuration map key %q in %q",
			valuesConfigMapKey, injectConfigMapName)
	}

	return valuesData, nil
}

func getInjectConfigFromConfigMap(kubeconfig string) (string, error) {
	client, err := createInterface(kubeconfig)
	if err != nil {
		return "", err
	}

	config, err := client.CoreV1().ConfigMaps(istioNamespace).Get(injectConfigMapName, metav1.GetOptions{})
	if err != nil {
		return "", fmt.Errorf("could not find valid configmap %q from namespace  %q: %v - "+
			"Use --injectConfigFile or re-run kube-inject with `-i <istioSystemNamespace> and ensure istio-inject configmap exists",
			injectConfigMapName, istioNamespace, err)
	}
	// values in the data are strings, while proto might use a
	// different data type.  therefore, we have to get a value by a
	// key
	injectData, exists := config.Data[injectConfigMapKey]
	if !exists {
		return "", fmt.Errorf("missing configuration map key %q in %q",
			injectConfigMapKey, injectConfigMapName)
	}
	var injectConfig inject.Config
	if err := yaml.Unmarshal([]byte(injectData), &injectConfig); err != nil {
		return "", fmt.Errorf("unable to convert data from configmap %q: %v",
			injectConfigMapName, err)
	}
	log.Debugf("using inject template from configmap %q", injectConfigMapName)
	return injectConfig.Template, nil
}

func validateFlags() error {
	var err error
	if inFilename != "" && emitTemplate {
		err = multierr.Append(err, errors.New("--filename and --emitTemplate are mutually exclusive"))
	}
	if inFilename == "" && !emitTemplate {
		err = multierr.Append(err, errors.New("filename not specified (see --filename or -f)"))
	}
	if meshConfigFile == "" && meshConfigMapName == "" {
		err = multierr.Append(err, errors.New("--meshConfigFile or --meshConfigMapName must be set"))
	}
	return err
}

var (
	emitTemplate bool

	inFilename          string
	outFilename         string
	meshConfigFile      string
	meshConfigMapName   string
	valuesFile          string
	injectConfigFile    string
	injectConfigMapName string
)

const (
	defaultMeshConfigMapName   = "istio"
	defaultInjectConfigMapName = "istio-sidecar-injector"
)

func injectCommand() *cobra.Command {
	injectCmd := &cobra.Command{
		Use:   "kube-inject",
		Short: "Inject Envoy sidecar into Kubernetes pod resources",
		Long: `

kube-inject manually injects the Envoy sidecar into Kubernetes
workloads. Unsupported resources are left unmodified so it is safe to
run kube-inject over a single file that contains multiple Service,
ConfigMap, Deployment, etc. definitions for a complex application. Its
best to do this when the resource is initially created.

k8s.io/docs/concepts/workloads/pods/pod-overview/#pod-templates is
updated for Job, DaemonSet, ReplicaSet, Pod and Deployment YAML resource
documents. Support for additional pod-based resource types can be
added as necessary.

The Istio project is continually evolving so the Istio sidecar
configuration may change unannounced. When in doubt re-run istioctl
kube-inject on deployments to get the most up-to-date changes.

To override the sidecar injection template from kubernetes configmap
'istio-inject', the parameters --injectConfigFile or --injectConfigMapName
can be used. Either of options would typically be used with the
file/configmap created with a new Istio release.
`,
		Example: `
# Update resources on the fly before applying.
kubectl apply -f <(istioctl kube-inject -f <resource.yaml>)

# Create a persistent version of the deployment with Envoy sidecar
# injected.
istioctl kube-inject -f deployment.yaml -o deployment-injected.yaml

# Update an existing deployment.
kubectl get deployment -o yaml | istioctl kube-inject -f - | kubectl apply -f -

# Create a persistent version of the deployment with Envoy sidecar
# injected configuration from Kubernetes configmap 'istio-inject'
istioctl kube-inject -f deployment.yaml -o deployment-injected.yaml --injectConfigMapName istio-inject
`,
		RunE: func(c *cobra.Command, _ []string) (err error) {
			if err = validateFlags(); err != nil {
				return err
			}

			var reader io.Reader
			if !emitTemplate {
				if inFilename == "-" {
					reader = os.Stdin
				} else {
					var in *os.File
					if in, err = os.Open(inFilename); err != nil {
						return err
					}
					reader = in
					defer func() {
						if errClose := in.Close(); errClose != nil {
							log.Errorf("Error: close file from %s, %s", inFilename, errClose)

							// don't overwrite the previous error
							if err == nil {
								err = errClose
							}
						}
					}()
				}
			}

			var writer io.Writer
			if outFilename == "" {
				writer = c.OutOrStdout()
			} else {
				var out *os.File
				if out, err = os.Create(outFilename); err != nil {
					return err
				}
				writer = out
				defer func() {
					if errClose := out.Close(); errClose != nil {
						log.Errorf("Error: close file from %s, %s", outFilename, errClose)

						// don't overwrite the previous error
						if err == nil {
							err = errClose
						}
					}
				}()
			}

			var meshConfig *meshconfig.MeshConfig
			if meshConfigFile != "" {
				if meshConfig, err = cmd.ReadMeshConfig(meshConfigFile); err != nil {
					return err
				}
			} else {
				if meshConfig, err = getMeshConfigFromConfigMap(kubeconfig); err != nil {
					return err
				}
			}

			var sidecarTemplate string
			if injectConfigFile != "" {
				injectionConfig, err := ioutil.ReadFile(injectConfigFile) // nolint: vetshadow
				if err != nil {
					return err
				}
				var config inject.Config
				if err := yaml.Unmarshal(injectionConfig, &config); err != nil {
					return err
				}
				sidecarTemplate = config.Template
			} else if sidecarTemplate, err = getInjectConfigFromConfigMap(kubeconfig); err != nil {
				return err
			}

			var valuesConfig string
			if valuesFile != "" {
				valuesConfigBytes, err := ioutil.ReadFile(valuesFile) // nolint: vetshadow
				if err != nil {
					return err
				}
				valuesConfig = string(valuesConfigBytes)
			} else if valuesConfig, err = getValuesFromConfigMap(kubeconfig); err != nil {
				return err
			}

			if emitTemplate {
				config := inject.Config{
					Policy:   inject.InjectionPolicyEnabled,
					Template: sidecarTemplate,
				}
				out, err := yaml.Marshal(&config)
				if err != nil {
					return err
				}
				fmt.Println(string(out))
				return nil
			}

			return inject.IntoResourceFile(sidecarTemplate, valuesConfig, meshConfig, reader, writer)
		},
		PersistentPreRunE: func(c *cobra.Command, args []string) error {
			// istioctl kube-inject is typically redirected to a .yaml file;
			// the default for log messages should be stderr, not stdout
			_ = c.Root().PersistentFlags().Set("log_target", "stderr")

			return c.Parent().PersistentPreRunE(c, args)
		},
	}

	injectCmd.PersistentFlags().StringVar(&meshConfigFile, "meshConfigFile", "",
		"mesh configuration filename. Takes precedence over --meshConfigMapName if set")
	injectCmd.PersistentFlags().StringVar(&injectConfigFile, "injectConfigFile", "",
		"injection configuration filename. Cannot be used with --injectConfigMapName")
	injectCmd.PersistentFlags().StringVar(&valuesFile, "valuesFile", "",
		"injection values configuration filename.")

	injectCmd.PersistentFlags().BoolVar(&emitTemplate, "emitTemplate", false,
		"Emit sidecar template based on parameterized flags")
	_ = injectCmd.PersistentFlags().MarkHidden("emitTemplate")

	injectCmd.PersistentFlags().StringVarP(&inFilename, "filename", "f",
		"", "Input Kubernetes resource filename")
	injectCmd.PersistentFlags().StringVarP(&outFilename, "output", "o",
		"", "Modified output Kubernetes resource filename")

	injectCmd.PersistentFlags().StringVar(&meshConfigMapName, "meshConfigMapName", defaultMeshConfigMapName,
		fmt.Sprintf("ConfigMap name for Istio mesh configuration, key should be %q", configMapKey))
	injectCmd.PersistentFlags().StringVar(&injectConfigMapName, "injectConfigMapName", defaultInjectConfigMapName,
		fmt.Sprintf("ConfigMap name for Istio sidecar injection, key should be %q.", injectConfigMapKey))

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

package cmd

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

	"github.com/ghodss/yaml"
	"github.com/spf13/cobra"
	"go.uber.org/multierr"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"

	meshconfig "istio.io/api/mesh/v1alpha1"
	"istio.io/istio/pilot/cmd"
	"istio.io/istio/pilot/pkg/kube/inject"
	"istio.io/istio/pilot/pkg/model"
	"istio.io/istio/pkg/kube"
	"istio.io/pkg/log"
	"istio.io/pkg/version"
)

const (
	configMapKey       = "mesh"
	injectConfigMapKey = "config"
	valuesConfigMapKey = "values"
)

func createInterface(kubeconfig string) (kubernetes.Interface, error) {
	restConfig, err := kube.BuildClientConfig(kubeconfig, configContext)

	if err != nil {
		return nil, err
	}
	return kubernetes.NewForConfig(restConfig)
}

func getMeshConfigFromConfigMap(kubeconfig string) (*meshconfig.MeshConfig, error) {
	client, err := createInterface(kubeconfig)
	if err != nil {
		return nil, err
	}

	config, err := client.CoreV1().ConfigMaps(istioNamespace).Get(meshConfigMapName, metav1.GetOptions{})
	if err != nil {
		return nil, fmt.Errorf("could not read valid configmap %q from namespace  %q: %v - "+
			"Use --meshConfigFile or re-run kube-inject with `-i <istioSystemNamespace> and ensure valid MeshConfig exists",
			meshConfigMapName, istioNamespace, err)
	}
	// values in the data are strings, while proto might use a
	// different data type.  therefore, we have to get a value by a
	// key
	configYaml, exists := config.Data[configMapKey]
	if !exists {
		return nil, fmt.Errorf("missing configuration map key %q", configMapKey)
	}
	cfg, err := model.ApplyMeshConfigDefaults(configYaml)
	if err != nil {
		err = multierr.Append(fmt.Errorf("istioctl version %s cannot parse mesh config.  Install istioctl from the latest Istio release",
			version.Info.Version), err)
	}
	return cfg, err
}

// grabs the raw values from the ConfigMap. These are encoded as JSON.
func getValuesFromConfigMap(kubeconfig string) (string, error) {
	client, err := createInterface(kubeconfig)
	if err != nil {
		return "", err
	}

	config, err := client.CoreV1().ConfigMaps(istioNamespace).Get(injectConfigMapName, metav1.GetOptions{})
	if err != nil {
		return "", fmt.Errorf("could not find valid configmap %q from namespace  %q: %v - "+
			"Use --injectConfigFile or re-run kube-inject with `-i <istioSystemNamespace> and ensure istio-inject configmap exists",
			injectConfigMapName, istioNamespace, err)
	}

	valuesData, exists := config.Data[valuesConfigMapKey]
	if !exists {
		return "", fmt.Errorf("missing configuration map key %q in %q",
			valuesConfigMapKey, injectConfigMapName)
	}

	return valuesData, nil
}

func getInjectConfigFromConfigMap(kubeconfig string) (string, error) {
	client, err := createInterface(kubeconfig)
	if err != nil {
		return "", err
	}

	config, err := client.CoreV1().ConfigMaps(istioNamespace).Get(injectConfigMapName, metav1.GetOptions{})
	if err != nil {
		return "", fmt.Errorf("could not find valid configmap %q from namespace  %q: %v - "+
			"Use --injectConfigFile or re-run kube-inject with `-i <istioSystemNamespace> and ensure istio-inject configmap exists",
			injectConfigMapName, istioNamespace, err)
	}
	// values in the data are strings, while proto might use a
	// different data type.  therefore, we have to get a value by a
	// key
	injectData, exists := config.Data[injectConfigMapKey]
	if !exists {
		return "", fmt.Errorf("missing configuration map key %q in %q",
			injectConfigMapKey, injectConfigMapName)
	}
	var injectConfig inject.Config
	if err := yaml.Unmarshal([]byte(injectData), &injectConfig); err != nil {
		return "", fmt.Errorf("unable to convert data from configmap %q: %v",
			injectConfigMapName, err)
	}
	log.Debugf("using inject template from configmap %q", injectConfigMapName)
	return injectConfig.Template, nil
}

func validateFlags() error {
	var err error
	if inFilename != "" && emitTemplate {
		err = multierr.Append(err, errors.New("--filename and --emitTemplate are mutually exclusive"))
	}
	if inFilename == "" && !emitTemplate {
		err = multierr.Append(err, errors.New("filename not specified (see --filename or -f)"))
	}
	if meshConfigFile == "" && meshConfigMapName == "" {
		err = multierr.Append(err, errors.New("--meshConfigFile or --meshConfigMapName must be set"))
	}
	return err
}

var (
	emitTemplate bool

	inFilename          string
	outFilename         string
	meshConfigFile      string
	meshConfigMapName   string
	valuesFile          string
	injectConfigFile    string
	injectConfigMapName string
)

const (
	defaultMeshConfigMapName   = "istio"
	defaultInjectConfigMapName = "istio-sidecar-injector"
)

func injectCommand() *cobra.Command {
	injectCmd := &cobra.Command{
		Use:   "kube-inject",
		Short: "Inject Envoy sidecar into Kubernetes pod resources",
		Long: `

kube-inject manually injects the Envoy sidecar into Kubernetes
workloads. Unsupported resources are left unmodified so it is safe to
run kube-inject over a single file that contains multiple Service,
ConfigMap, Deployment, etc. definitions for a complex application. It's
best to do this when the resource is initially created.

k8s.io/docs/concepts/workloads/pods/pod-overview/#pod-templates is
updated for Job, DaemonSet, ReplicaSet, Pod and Deployment YAML resource
documents. Support for additional pod-based resource types can be
added as necessary.

The Istio project is continually evolving so the Istio sidecar
configuration may change unannounced. When in doubt re-run istioctl
kube-inject on deployments to get the most up-to-date changes.
`,
		Example: `
# Update resources on the fly before applying.
kubectl apply -f <(istioctl kube-inject -f <resource.yaml>)

# Create a persistent version of the deployment with Envoy sidecar
# injected.
istioctl kube-inject -f deployment.yaml -o deployment-injected.yaml

# Update an existing deployment.
kubectl get deployment -o yaml | istioctl kube-inject -f - | kubectl apply -f -

# Capture cluster configuration for later use with kube-inject
kubectl -n istio-system get cm istio-sidecar-injector  -o jsonpath="{.data.config}" > /tmp/inj-template.tmpl
kubectl -n istio-system get cm istio -o jsonpath="{.data.mesh}" > /tmp/mesh.yaml
kubectl -n istio-system get cm istio-sidecar-injector -o jsonpath="{.data.values}" > /tmp/values.json
# Use kube-inject based on captured configuration
istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml \
	--injectConfigFile /tmp/inj-template.tmpl \
	--meshConfigFile /tmp/mesh.yaml \
	--valuesFile /tmp/values.json
`,
		RunE: func(c *cobra.Command, _ []string) (err error) {
			if err = validateFlags(); err != nil {
				return err
			}

			var reader io.Reader
			if !emitTemplate {
				if inFilename == "-" {
					reader = os.Stdin
				} else {
					var in *os.File
					if in, err = os.Open(inFilename); err != nil {
						return err
					}
					reader = in
					defer func() {
						if errClose := in.Close(); errClose != nil {
							log.Errorf("Error: close file from %s, %s", inFilename, errClose)

							// don't overwrite the previous error
							if err == nil {
								err = errClose
							}
						}
					}()
				}
			}

			var writer io.Writer
			if outFilename == "" {
				writer = c.OutOrStdout()
			} else {
				var out *os.File
				if out, err = os.Create(outFilename); err != nil {
					return err
				}
				writer = out
				defer func() {
					if errClose := out.Close(); errClose != nil {
						log.Errorf("Error: close file from %s, %s", outFilename, errClose)

						// don't overwrite the previous error
						if err == nil {
							err = errClose
						}
					}
				}()
			}

			var meshConfig *meshconfig.MeshConfig
			if meshConfigFile != "" {
				if meshConfig, err = cmd.ReadMeshConfig(meshConfigFile); err != nil {
					return err
				}
			} else {
				if meshConfig, err = getMeshConfigFromConfigMap(kubeconfig); err != nil {
					return err
				}
			}

			var sidecarTemplate string
			if injectConfigFile != "" {
				injectionConfig, err := ioutil.ReadFile(injectConfigFile) // nolint: vetshadow
				if err != nil {
					return err
				}
				var config inject.Config
				if err := yaml.Unmarshal(injectionConfig, &config); err != nil {
					return err
				}
				sidecarTemplate = config.Template
			} else if sidecarTemplate, err = getInjectConfigFromConfigMap(kubeconfig); err != nil {
				return err
			}

			var valuesConfig string
			if valuesFile != "" {
				valuesConfigBytes, err := ioutil.ReadFile(valuesFile) // nolint: vetshadow
				if err != nil {
					return err
				}
				valuesConfig = string(valuesConfigBytes)
			} else if valuesConfig, err = getValuesFromConfigMap(kubeconfig); err != nil {
				return err
			}

			if emitTemplate {
				config := inject.Config{
					Policy:   inject.InjectionPolicyEnabled,
					Template: sidecarTemplate,
				}
				out, err := yaml.Marshal(&config)
				if err != nil {
					return err
				}
				fmt.Println(string(out))
				return nil
			}

			return inject.IntoResourceFile(sidecarTemplate, valuesConfig, meshConfig, reader, writer)
		},
		PersistentPreRunE: func(c *cobra.Command, args []string) error {
			// istioctl kube-inject is typically redirected to a .yaml file;
			// the default for log messages should be stderr, not stdout
			_ = c.Root().PersistentFlags().Set("log_target", "stderr")

			return c.Parent().PersistentPreRunE(c, args)
		},
	}

	injectCmd.PersistentFlags().StringVar(&meshConfigFile, "meshConfigFile", "",
		"mesh configuration filename. Takes precedence over --meshConfigMapName if set")
	injectCmd.PersistentFlags().StringVar(&injectConfigFile, "injectConfigFile", "",
		"injection configuration filename. Cannot be used with --injectConfigMapName")
	injectCmd.PersistentFlags().StringVar(&valuesFile, "valuesFile", "",
		"injection values configuration filename.")

	injectCmd.PersistentFlags().BoolVar(&emitTemplate, "emitTemplate", false,
		"Emit sidecar template based on parameterized flags")
	_ = injectCmd.PersistentFlags().MarkHidden("emitTemplate")

	injectCmd.PersistentFlags().StringVarP(&inFilename, "filename", "f",
		"", "Input Kubernetes resource filename")
	injectCmd.PersistentFlags().StringVarP(&outFilename, "output", "o",
		"", "Modified output Kubernetes resource filename")

	injectCmd.PersistentFlags().StringVar(&meshConfigMapName, "meshConfigMapName", defaultMeshConfigMapName,
		fmt.Sprintf("ConfigMap name for Istio mesh configuration, key should be %q", configMapKey))
	injectCmd.PersistentFlags().StringVar(&injectConfigMapName, "injectConfigMapName", defaultInjectConfigMapName,
		fmt.Sprintf("ConfigMap name for Istio sidecar injection, key should be %q.", injectConfigMapKey))

	return injectCmd
}
<|endoftext|>


<commit_before>package main

import "encoding/json"
import "flag"
import "fmt"
import "log"
import "net/http"
import "net/url"
import "os"
import "strings"
import "time"

import "lib/jetpack"

var Host *jetpack.Host

func getPod(ip string) *jetpack.Pod {
	for _, pod := range Host.Pods() {
		if podIp, _ := pod.Manifest.Annotations.Get("ip-address"); podIp == ip {
			return pod
		}
	}
	return nil
}

func clientIP(r *http.Request) string {
	return strings.SplitN(r.RemoteAddr, ":", 2)[0]
}

func resp200(v interface{}) (int, []byte) {
	return http.StatusOK, []byte(fmt.Sprintf("%v", v))
}

func resp404() (int, []byte) {
	return http.StatusNotFound, nil
}

func resp500(err error) (int, []byte) {
	return http.StatusInternalServerError, []byte(err.Error())
}

func doServeMetadata(r *http.Request) (int, []byte) {
	if r.URL.Path == "/" {
		// Root URL. We introduce ourselves, no questions asked.
		return http.StatusOK, []byte(fmt.Sprintf(
			"Jetpack metadata service version %v (%v) built on %v\n",
			jetpack.Version,
			jetpack.Revision,
			jetpack.BuildTimestamp))
	}

	if !strings.HasPrefix(r.URL.Path, "/acMetadata/v1/") {
		// Not a metadata service request.
		return resp404()
	}

	// API request. Ensure it has required `Metadata-Flavor:
	// AppContainter' header and it comes from a container's IP.

	if hdr, ok := r.Header["Metadata-Flavor"]; !ok || len(hdr) != 1 || hdr[0] != "AppContainer" {
		return http.StatusBadRequest, []byte("Metadata-Flavor header missing or invalid")
	}

	pod := getPod(clientIP(r))
	if pod == nil {
		return http.StatusTeapot, []byte("You are not a pod. For you, I am a teapot.")
	}

	// hack hack hack
	r.URL.User = url.User(pod.UUID.String())

	path := r.URL.Path[len("/acMetadata/v1/"):]
	switch {

	case path == "pod/uuid":
		return resp200(pod.UUID)

	case path == "pod/manifest":
		// Pod manifest
		if manifestJSON, err := json.Marshal(pod.Manifest); err != nil {
			panic(err)
		} else {
			return http.StatusOK, manifestJSON
		}

	case path == "pod/hmac/sign" || path == "pod/hmac/verify":
		// HMAC sign/verify service.
		return http.StatusNotImplemented, nil

	case strings.HasPrefix(path, "pod/annotations/"):
		// Pod annotation. 404 on nonexistent one.
		annName := path[len("pod/annotations/"):]
		if val, ok := pod.Manifest.Annotations.Get(annName); ok {
			return resp200(val)
		} else {
			return resp404()
		}
	case strings.HasPrefix(path, "apps/"):
		// App metadata.
		subpath := path[len("apps/"):]

		for _, app := range pod.Manifest.Apps {
			appPrefix := string(app.Name) + "/"
			if strings.HasPrefix(subpath, appPrefix) {
				switch appPath := subpath[len(appPrefix):]; appPath {

				case "image/id":
					return resp200(app.Image.ID)

				case "image/manifest":
					if img, err := Host.GetImageByHash(app.Image.ID); err != nil {
						panic(err)
					} else if manifestJSON, err := json.Marshal(img.Manifest); err != nil {
						panic(err)
					} else {
						return http.StatusOK, manifestJSON
					}

				default:
					if strings.HasPrefix(appPath, "annotations/") {
						annName := appPath[len("annotations/"):]
						if val, ok := app.Annotations.Get(annName); ok {
							return resp200(val)
						} else if img, err := Host.GetImageByHash(app.Image.ID); err != nil {
							panic(err)
						} else if val, ok := img.Manifest.Annotations.Get(annName); ok {
							return resp200(val)
						}
					}
				}
			}
		}
		return resp404()

	default:
		return resp404()
	}
}

func ServeMetadata(w http.ResponseWriter, r *http.Request) {
	status, body := doServeMetadata(r)

	if body == nil {
		body = []byte(http.StatusText(status))
	}

	// log_format combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"';
	remote_user := "-"
	if r.URL.User != nil {
		remote_user = r.URL.User.Username()
	}

	fmt.Printf("%v - %v [%v] \"%v %v\" %d %d \"-\" \"-\"\n",
		clientIP(r),
		remote_user,
		time.Now(),
		r.Method,
		r.RequestURI,
		status,
		len(body))

	w.WriteHeader(status)
	if _, err := w.Write(body); err != nil {
		panic(err)
	}
}

func main() {
	configPath := jetpack.DefaultConfigPath
	help := false

	if cfg := os.Getenv("JETPACK_CONF"); cfg != "" {
		configPath = cfg
	}

	flag.StringVar(&configPath, "config", configPath, "Configuration file")
	flag.BoolVar(&help, "h", false, "Show help")
	flag.BoolVar(&help, "help", false, "Show help")

	flag.Parse()
	// args := flag.Args()

	if host, err := jetpack.NewHost(configPath); err != nil {
		log.Fatalln("Error initializing host:", err)
	} else {
		Host = host
	}

	hostip, _, err := Host.HostIP()
	if err != nil {
		log.Fatalln("Error getting listen IP:", err)
	}

	addr := fmt.Sprintf("%v:%d", hostip, Host.Properties.MustGetInt("mds.port"))
	log.Println("Listening on:", addr)
	log.Fatal(http.ListenAndServe(addr, http.HandlerFunc(ServeMetadata)))
}
<commit_msg>Drop Metadata-Flavour header requirement.<commit_after>package main

import "encoding/json"
import "flag"
import "fmt"
import "log"
import "net/http"
import "net/url"
import "os"
import "strings"
import "time"

import "lib/jetpack"

var Host *jetpack.Host

func getPod(ip string) *jetpack.Pod {
	for _, pod := range Host.Pods() {
		if podIp, _ := pod.Manifest.Annotations.Get("ip-address"); podIp == ip {
			return pod
		}
	}
	return nil
}

func clientIP(r *http.Request) string {
	return strings.SplitN(r.RemoteAddr, ":", 2)[0]
}

func resp200(v interface{}) (int, []byte) {
	return http.StatusOK, []byte(fmt.Sprintf("%v", v))
}

func resp404() (int, []byte) {
	return http.StatusNotFound, nil
}

func resp500(err error) (int, []byte) {
	return http.StatusInternalServerError, []byte(err.Error())
}

func doServeMetadata(r *http.Request) (int, []byte) {
	if r.URL.Path == "/" {
		// Root URL. We introduce ourselves, no questions asked.
		return http.StatusOK, []byte(fmt.Sprintf(
			"Jetpack metadata service version %v (%v) built on %v\n",
			jetpack.Version,
			jetpack.Revision,
			jetpack.BuildTimestamp))
	}

	if !strings.HasPrefix(r.URL.Path, "/acMetadata/v1/") {
		// Not a metadata service request.
		return resp404()
	}

	pod := getPod(clientIP(r))
	if pod == nil {
		return http.StatusTeapot, []byte("You are not a pod. For you, I am a teapot.")
	}

	// hack hack hack
	r.URL.User = url.User(pod.UUID.String())

	path := r.URL.Path[len("/acMetadata/v1/"):]
	switch {

	case path == "pod/uuid":
		return resp200(pod.UUID)

	case path == "pod/manifest":
		// Pod manifest
		if manifestJSON, err := json.Marshal(pod.Manifest); err != nil {
			panic(err)
		} else {
			return http.StatusOK, manifestJSON
		}

	case path == "pod/hmac/sign" || path == "pod/hmac/verify":
		// HMAC sign/verify service.
		return http.StatusNotImplemented, nil

	case strings.HasPrefix(path, "pod/annotations/"):
		// Pod annotation. 404 on nonexistent one.
		annName := path[len("pod/annotations/"):]
		if val, ok := pod.Manifest.Annotations.Get(annName); ok {
			return resp200(val)
		} else {
			return resp404()
		}
	case strings.HasPrefix(path, "apps/"):
		// App metadata.
		subpath := path[len("apps/"):]

		for _, app := range pod.Manifest.Apps {
			appPrefix := string(app.Name) + "/"
			if strings.HasPrefix(subpath, appPrefix) {
				switch appPath := subpath[len(appPrefix):]; appPath {

				case "image/id":
					return resp200(app.Image.ID)

				case "image/manifest":
					if img, err := Host.GetImageByHash(app.Image.ID); err != nil {
						panic(err)
					} else if manifestJSON, err := json.Marshal(img.Manifest); err != nil {
						panic(err)
					} else {
						return http.StatusOK, manifestJSON
					}

				default:
					if strings.HasPrefix(appPath, "annotations/") {
						annName := appPath[len("annotations/"):]
						if val, ok := app.Annotations.Get(annName); ok {
							return resp200(val)
						} else if img, err := Host.GetImageByHash(app.Image.ID); err != nil {
							panic(err)
						} else if val, ok := img.Manifest.Annotations.Get(annName); ok {
							return resp200(val)
						}
					}
				}
			}
		}
		return resp404()

	default:
		return resp404()
	}
}

func ServeMetadata(w http.ResponseWriter, r *http.Request) {
	status, body := doServeMetadata(r)

	if body == nil {
		body = []byte(http.StatusText(status))
	}

	// log_format combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"';
	remote_user := "-"
	if r.URL.User != nil {
		remote_user = r.URL.User.Username()
	}

	fmt.Printf("%v - %v [%v] \"%v %v\" %d %d \"-\" \"-\"\n",
		clientIP(r),
		remote_user,
		time.Now(),
		r.Method,
		r.RequestURI,
		status,
		len(body))

	w.WriteHeader(status)
	if _, err := w.Write(body); err != nil {
		panic(err)
	}
}

func main() {
	configPath := jetpack.DefaultConfigPath
	help := false

	if cfg := os.Getenv("JETPACK_CONF"); cfg != "" {
		configPath = cfg
	}

	flag.StringVar(&configPath, "config", configPath, "Configuration file")
	flag.BoolVar(&help, "h", false, "Show help")
	flag.BoolVar(&help, "help", false, "Show help")

	flag.Parse()
	// args := flag.Args()

	if host, err := jetpack.NewHost(configPath); err != nil {
		log.Fatalln("Error initializing host:", err)
	} else {
		Host = host
	}

	hostip, _, err := Host.HostIP()
	if err != nil {
		log.Fatalln("Error getting listen IP:", err)
	}

	addr := fmt.Sprintf("%v:%d", hostip, Host.Properties.MustGetInt("mds.port"))
	log.Println("Listening on:", addr)
	log.Fatal(http.ListenAndServe(addr, http.HandlerFunc(ServeMetadata)))
}
<|endoftext|>


<commit_before>package git

import (
	"io"
	"math"
)

type PacketWriter struct {
	// buf is the internal buffer of bytes used to store data given in calls
	// to Write that don't warrant a protocol write.
	buf []byte
	// proto is the place where packets get written.
	proto *protocol
}

var _ io.Writer = new(PacketWriter)

// NewPacketWriter returns a new *PacketWriter, which will write to teh
// underlying data stream "w".
//
// If "w" is already a `*PacketWriter`, it will be returned as-is.
func NewPacketWriter(w io.Writer) *PacketWriter {
	if pw, ok := w.(*PacketWriter); ok {
		return pw
	}

	return &PacketWriter{proto: newProtocolRW(nil, w)}
}

// Write implements the io.Writer interface's `Write` method by providing a
// packet-based backend to the given buffer "p".
//
// As many bytes are removed from "p" as possible and stored in an internal
// buffer until the amount of data in the internal buffer is enough to write a
// single packet. Once the internal buffer is full, a packet is written to the
// underlying stream of data, and the process repeats.
//
// When the caller has no more data to write in the given chunk of packets, a
// subsequent call to `Write(p []byte)` MUST be made with an empty slice, to
// flush the remaining data in the buffer, and write the terminating bytes to
// the underlying packet stream.
//
// Write returns the number of bytes in "p" actually written to the underlying
// protocol stream, not including the number of bytes written in those packets
// headers. If any error was encountered while either buffering or writing, that
// error is returned, along with the number of bytes written to the underlying
// protocol stream, as described above.
func (w *PacketWriter) Write(p []byte) (int, error) {
	var n int

	if len(p) == 0 {
		// If we got an empty sequence of bytes, let's flush the data
		// stored in the buffer, and then write the a packet termination
		// sequence.

		flushed, err := w.flush()
		if err != nil {
			return 0, err
		}

		n = n + flushed

		if err = w.proto.writeFlush(); err != nil {
			return n, err
		}
	}

	for len(p) > 0 {
		// While there is still data left to process in "p", grab as
		// much of it as we can while not allowing the internal buffer
		// to exceed the MaxPacketLength const.
		m := int(math.Min(float64(len(p)), float64(MaxPacketLength-len(w.buf))))

		// Append on all of the data that we could into the internal
		// buffer.
		w.buf = append(w.buf, p[:m]...)
		// Truncate "p" such that it no longer includes the data that we
		// have in the internal buffer.
		p = p[m:]

		if len(w.buf) == MaxPacketLength {
			// If we were able to grab an entire packet's worth of
			// data, flush the buffer.

			flushed, err := w.flush()
			if err != nil {
				return n, err
			}

			n = n + flushed
		}
	}

	return n, nil
}

// flush writes any data in the internal buffer out to the underlying protocol
// stream. If the amount of data in the internal buffer exceeds the
// MaxPacketLength, the data will be written in multiple packets to accommodate.
//
// flush returns the number of bytes written to the underlying packet stream,
// and any error that it encountered along the way.
func (w *PacketWriter) flush() (int, error) {
	var n int

	for len(w.buf) > 0 {
		if err := w.proto.writePacket(w.buf); err != nil {
			return 0, err
		}

		m := int(math.Min(float64(len(w.buf)), float64(MaxPacketLength)))

		w.buf = w.buf[m:]

		n = n + m
	}

	return n, nil
}
<commit_msg>git/pw: use `tools.MinInt` instead of `math.Min`<commit_after>package git

import (
	"io"

	"github.com/github/git-lfs/tools"
)

type PacketWriter struct {
	// buf is the internal buffer of bytes used to store data given in calls
	// to Write that don't warrant a protocol write.
	buf []byte
	// proto is the place where packets get written.
	proto *protocol
}

var _ io.Writer = new(PacketWriter)

// NewPacketWriter returns a new *PacketWriter, which will write to teh
// underlying data stream "w".
//
// If "w" is already a `*PacketWriter`, it will be returned as-is.
func NewPacketWriter(w io.Writer) *PacketWriter {
	if pw, ok := w.(*PacketWriter); ok {
		return pw
	}

	return &PacketWriter{proto: newProtocolRW(nil, w)}
}

// Write implements the io.Writer interface's `Write` method by providing a
// packet-based backend to the given buffer "p".
//
// As many bytes are removed from "p" as possible and stored in an internal
// buffer until the amount of data in the internal buffer is enough to write a
// single packet. Once the internal buffer is full, a packet is written to the
// underlying stream of data, and the process repeats.
//
// When the caller has no more data to write in the given chunk of packets, a
// subsequent call to `Write(p []byte)` MUST be made with an empty slice, to
// flush the remaining data in the buffer, and write the terminating bytes to
// the underlying packet stream.
//
// Write returns the number of bytes in "p" actually written to the underlying
// protocol stream, not including the number of bytes written in those packets
// headers. If any error was encountered while either buffering or writing, that
// error is returned, along with the number of bytes written to the underlying
// protocol stream, as described above.
func (w *PacketWriter) Write(p []byte) (int, error) {
	var n int

	if len(p) == 0 {
		// If we got an empty sequence of bytes, let's flush the data
		// stored in the buffer, and then write the a packet termination
		// sequence.

		flushed, err := w.flush()
		if err != nil {
			return 0, err
		}

		n = n + flushed

		if err = w.proto.writeFlush(); err != nil {
			return n, err
		}
	}

	for len(p) > 0 {
		// While there is still data left to process in "p", grab as
		// much of it as we can while not allowing the internal buffer
		// to exceed the MaxPacketLength const.
		m := tools.MinInt(len(p), MaxPacketLength-len(w.buf))

		// Append on all of the data that we could into the internal
		// buffer.
		w.buf = append(w.buf, p[:m]...)
		// Truncate "p" such that it no longer includes the data that we
		// have in the internal buffer.
		p = p[m:]

		if len(w.buf) == MaxPacketLength {
			// If we were able to grab an entire packet's worth of
			// data, flush the buffer.

			flushed, err := w.flush()
			if err != nil {
				return n, err
			}

			n = n + flushed
		}
	}

	return n, nil
}

// flush writes any data in the internal buffer out to the underlying protocol
// stream. If the amount of data in the internal buffer exceeds the
// MaxPacketLength, the data will be written in multiple packets to accommodate.
//
// flush returns the number of bytes written to the underlying packet stream,
// and any error that it encountered along the way.
func (w *PacketWriter) flush() (int, error) {
	var n int

	for len(w.buf) > 0 {
		if err := w.proto.writePacket(w.buf); err != nil {
			return 0, err
		}

		m := tools.MinInt(len(w.buf), MaxPacketLength)

		w.buf = w.buf[m:]

		n = n + m
	}

	return n, nil
}
<|endoftext|>


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

package gcsproxy_test

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"testing"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/gcs/mock_gcs"
	"github.com/jacobsa/gcsfuse/gcsproxy"
	. "github.com/jacobsa/oglematchers"
	"github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

func TestOgletest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

// An oglemock.Matcher that accepts a predicate function and a description,
// making it easy to make anonymous matcher types.
type predicateMatcher struct {
	Desc      string
	Predicate func(interface{}) error
}

var _ Matcher = &predicateMatcher{}

func (m *predicateMatcher) Matches(candidate interface{}) error {
	return m.Predicate(candidate)
}

func (m *predicateMatcher) Description() string {
	return m.Desc
}

func nameIs(name string) Matcher {
	return &predicateMatcher{
		Desc: fmt.Sprintf("Name is: %s", name),
		Predicate: func(candidate interface{}) error {
			req := candidate.(*gcs.CreateObjectRequest)
			if req.Attrs.Name != name {
				return errors.New("")
			}

			return nil
		},
	}
}

func contentsAre(s string) Matcher {
	return &predicateMatcher{
		Desc: fmt.Sprintf("Object contents are: %s", s),
		Predicate: func(candidate interface{}) error {
			// Snarf the contents.
			req := candidate.(*gcs.CreateObjectRequest)
			contents, err := ioutil.ReadAll(req.Contents)
			if err != nil {
				panic(err)
			}

			// Compare
			if string(contents) != s {
				return errors.New("")
			}

			return nil
		},
	}
}

func generationIs(g int64) Matcher {
	pred := func(c interface{}) error {
		req := c.(*gcs.CreateObjectRequest)
		if req.GenerationPrecondition == nil {
			return errors.New("which has a nil GenerationPrecondition field.")
		}

		if *req.GenerationPrecondition != g {
			return fmt.Errorf(
				"Which has *GenerationPrecondition == %v",
				*req.GenerationPrecondition)
		}

		return nil
	}

	return NewMatcher(
		pred,
		fmt.Sprintf("*GenerationPrecondition == %v", g))
}

////////////////////////////////////////////////////////////////////////
// Invariant-checking object proxy
////////////////////////////////////////////////////////////////////////

// A wrapper around ObjectProxy that calls CheckInvariants whenever invariants
// should hold. For catching logic errors early in the test.
type checkingObjectProxy struct {
	wrapped *gcsproxy.ObjectProxy
}

func (op *checkingObjectProxy) Name() string {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Name()
}

func (op *checkingObjectProxy) Stat() (uint64, bool, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Stat(context.Background())
}

func (op *checkingObjectProxy) ReadAt(b []byte, o int64) (int, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.ReadAt(context.Background(), b, o)
}

func (op *checkingObjectProxy) WriteAt(b []byte, o int64) (int, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.WriteAt(context.Background(), b, o)
}

func (op *checkingObjectProxy) Truncate(n uint64) error {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Truncate(context.Background(), n)
}

func (op *checkingObjectProxy) Sync() (uint64, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Sync(context.Background())
}

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type ObjectProxyTest struct {
	objectName string
	bucket     mock_gcs.MockBucket
	op         checkingObjectProxy
}

func (t *ObjectProxyTest) setUp(ti *TestInfo, srcGeneration uint64) {
	t.objectName = "some/object"
	t.bucket = mock_gcs.NewMockBucket(ti.MockController, "bucket")

	var err error
	t.op.wrapped, err = gcsproxy.NewObjectProxy(
		context.Background(),
		t.bucket,
		t.objectName,
		srcGeneration)

	if err != nil {
		panic(err)
	}
}

////////////////////////////////////////////////////////////////////////
// No source object
////////////////////////////////////////////////////////////////////////

// A test whose initial conditions are a fresh object proxy without a source
// object set.
type NoSourceObjectTest struct {
	ObjectProxyTest
}

var _ SetUpInterface = &NoSourceObjectTest{}

func init() { RegisterTestSuite(&NoSourceObjectTest{}) }

func (t *NoSourceObjectTest) SetUp(ti *TestInfo) {
	t.ObjectProxyTest.setUp(ti, 0)
}

func (t *NoSourceObjectTest) Name() {
	ExpectEq(t.objectName, t.op.Name())
}

func (t *NoSourceObjectTest) Read_InitialState() {
	buf := make([]byte, 1024)
	n, err := t.op.ReadAt(buf, 0)

	ExpectEq(io.EOF, err)
	ExpectEq(0, n)
}

func (t *NoSourceObjectTest) WriteToEndOfObjectThenRead() {
	var buf []byte
	var n int
	var err error

	// Extend the object by writing twice.
	n, err = t.op.WriteAt([]byte("taco"), 0)
	AssertEq(nil, err)
	AssertEq(len("taco"), n)

	n, err = t.op.WriteAt([]byte("burrito"), int64(len("taco")))
	AssertEq(nil, err)
	AssertEq(len("burrito"), n)

	// Read the whole thing.
	buf = make([]byte, 1024)
	n, err = t.op.ReadAt(buf, 0)

	AssertEq(io.EOF, err)
	ExpectEq(len("tacoburrito"), n)
	ExpectEq("tacoburrito", string(buf[:n]))

	// Read a range in the middle.
	buf = make([]byte, 4)
	n, err = t.op.ReadAt(buf, 3)

	AssertEq(nil, err)
	ExpectEq(4, n)
	ExpectEq("obur", string(buf[:n]))
}

func (t *NoSourceObjectTest) WritePastEndOfObjectThenRead() {
	var n int
	var err error
	var buf []byte

	// Extend the object by writing past its end.
	n, err = t.op.WriteAt([]byte("taco"), 2)
	AssertEq(nil, err)
	AssertEq(len("taco"), n)

	// Read the whole thing.
	buf = make([]byte, 1024)
	n, err = t.op.ReadAt(buf, 0)

	AssertEq(io.EOF, err)
	ExpectEq(2+len("taco"), n)
	ExpectEq("\x00\x00taco", string(buf[:n]))

	// Read a range in the middle.
	buf = make([]byte, 4)
	n, err = t.op.ReadAt(buf, 1)

	AssertEq(nil, err)
	ExpectEq(4, n)
	ExpectEq("\x00tac", string(buf[:n]))
}

func (t *NoSourceObjectTest) WriteWithinObjectThenRead() {
	var n int
	var err error
	var buf []byte

	// Write several bytes to extend the object.
	n, err = t.op.WriteAt([]byte("00000"), 0)
	AssertEq(nil, err)
	AssertEq(len("00000"), n)

	// Overwrite some in the middle.
	n, err = t.op.WriteAt([]byte("11"), 1)
	AssertEq(nil, err)
	AssertEq(len("11"), n)

	// Read the whole thing.
	buf = make([]byte, 1024)
	n, err = t.op.ReadAt(buf, 0)

	AssertEq(io.EOF, err)
	ExpectEq(len("01100"), n)
	ExpectEq("01100", string(buf[:n]))
}

func (t *NoSourceObjectTest) GrowByTruncating() {
	var n int
	var err error
	var buf []byte

	// Truncate
	err = t.op.Truncate(4)
	AssertEq(nil, err)

	// Read the whole thing.
	buf = make([]byte, 1024)
	n, err = t.op.ReadAt(buf, 0)

	AssertEq(io.EOF, err)
	ExpectEq(4, n)
	ExpectEq("\x00\x00\x00\x00", string(buf[:n]))
}

func (t *NoSourceObjectTest) Sync_CallsCreateObject_NoInteractions() {
	// CreateObject -- should receive an empty string and a generation zero
	// precondition.
	ExpectCall(t.bucket, "CreateObject")(
		Any(),
		AllOf(nameIs(t.objectName), contentsAre(""), generationIs(0))).
		WillOnce(oglemock.Return(nil, errors.New("")))

	// Sync
	t.op.Sync()
}

func (t *NoSourceObjectTest) Sync_CallsCreateObject_AfterWriting() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Sync_CreateObjectFails() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Sync_CreateObjectSaysPreconditionFailed() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Sync_Successful() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_CallsBucket() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_BucketFails() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_InitialState() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_AfterShortening() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_AfterGrowing() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_AfterReading() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_AfterWriting() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_Clobbered() {
	AssertTrue(false, "TODO")
}

////////////////////////////////////////////////////////////////////////
// Source object present
////////////////////////////////////////////////////////////////////////

// A test whose initial conditions are an object proxy branching from a source
// object in the bucket.
type SourceObjectPresentTest struct {
	ObjectProxyTest
	sourceObject *storage.Object
}

var _ SetUpInterface = &SourceObjectPresentTest{}

func init() { RegisterTestSuite(&SourceObjectPresentTest{}) }

func (t *SourceObjectPresentTest) SetUp(ti *TestInfo) {
	t.ObjectProxyTest.setUp(ti, 123)
}

func (t *SourceObjectPresentTest) Read_CallsNewReader() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Read_NewReaderFails() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Read_NewReaderSucceeds() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Write_CallsNewReader() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Write_NewReaderFails() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Write_NewReaderSucceeds() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Truncate_CallsNewReader() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Truncate_NewReaderFails() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Truncate_NewReaderSucceeds() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_NoInteractions() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_AfterReading() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_AfterWriting() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_AfterTruncating() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_CallsCreateObject() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_CallsBucket() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_BucketFails() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_BucketSaysNotFound() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_InitialState() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_AfterShortening() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_AfterGrowing() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_AfterReading() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_AfterWriting() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_Clobbered() {
	AssertTrue(false, "TODO")
}
<commit_msg>Deleted predicateMatcher.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gcsproxy_test

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"testing"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/gcs/mock_gcs"
	"github.com/jacobsa/gcsfuse/gcsproxy"
	. "github.com/jacobsa/oglematchers"
	"github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

func TestOgletest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func nameIs(name string) Matcher {
	return NewMatcher(
		func(candidate interface{}) error {
			req := candidate.(*gcs.CreateObjectRequest)
			if req.Attrs.Name != name {
				return errors.New("")
			}

			return nil
		},
		fmt.Sprintf("Name is: %s", name))
}

func contentsAre(s string) Matcher {
	return NewMatcher(
		func(candidate interface{}) error {
			// Snarf the contents.
			req := candidate.(*gcs.CreateObjectRequest)
			contents, err := ioutil.ReadAll(req.Contents)
			if err != nil {
				panic(err)
			}

			// Compare
			if string(contents) != s {
				return errors.New("")
			}

			return nil
		},
		fmt.Sprintf("Object contents are: %s", s))
}

func generationIs(g int64) Matcher {
	pred := func(c interface{}) error {
		req := c.(*gcs.CreateObjectRequest)
		if req.GenerationPrecondition == nil {
			return errors.New("which has a nil GenerationPrecondition field.")
		}

		if *req.GenerationPrecondition != g {
			return fmt.Errorf(
				"Which has *GenerationPrecondition == %v",
				*req.GenerationPrecondition)
		}

		return nil
	}

	return NewMatcher(
		pred,
		fmt.Sprintf("*GenerationPrecondition == %v", g))
}

////////////////////////////////////////////////////////////////////////
// Invariant-checking object proxy
////////////////////////////////////////////////////////////////////////

// A wrapper around ObjectProxy that calls CheckInvariants whenever invariants
// should hold. For catching logic errors early in the test.
type checkingObjectProxy struct {
	wrapped *gcsproxy.ObjectProxy
}

func (op *checkingObjectProxy) Name() string {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Name()
}

func (op *checkingObjectProxy) Stat() (uint64, bool, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Stat(context.Background())
}

func (op *checkingObjectProxy) ReadAt(b []byte, o int64) (int, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.ReadAt(context.Background(), b, o)
}

func (op *checkingObjectProxy) WriteAt(b []byte, o int64) (int, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.WriteAt(context.Background(), b, o)
}

func (op *checkingObjectProxy) Truncate(n uint64) error {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Truncate(context.Background(), n)
}

func (op *checkingObjectProxy) Sync() (uint64, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Sync(context.Background())
}

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type ObjectProxyTest struct {
	objectName string
	bucket     mock_gcs.MockBucket
	op         checkingObjectProxy
}

func (t *ObjectProxyTest) setUp(ti *TestInfo, srcGeneration uint64) {
	t.objectName = "some/object"
	t.bucket = mock_gcs.NewMockBucket(ti.MockController, "bucket")

	var err error
	t.op.wrapped, err = gcsproxy.NewObjectProxy(
		context.Background(),
		t.bucket,
		t.objectName,
		srcGeneration)

	if err != nil {
		panic(err)
	}
}

////////////////////////////////////////////////////////////////////////
// No source object
////////////////////////////////////////////////////////////////////////

// A test whose initial conditions are a fresh object proxy without a source
// object set.
type NoSourceObjectTest struct {
	ObjectProxyTest
}

var _ SetUpInterface = &NoSourceObjectTest{}

func init() { RegisterTestSuite(&NoSourceObjectTest{}) }

func (t *NoSourceObjectTest) SetUp(ti *TestInfo) {
	t.ObjectProxyTest.setUp(ti, 0)
}

func (t *NoSourceObjectTest) Name() {
	ExpectEq(t.objectName, t.op.Name())
}

func (t *NoSourceObjectTest) Read_InitialState() {
	buf := make([]byte, 1024)
	n, err := t.op.ReadAt(buf, 0)

	ExpectEq(io.EOF, err)
	ExpectEq(0, n)
}

func (t *NoSourceObjectTest) WriteToEndOfObjectThenRead() {
	var buf []byte
	var n int
	var err error

	// Extend the object by writing twice.
	n, err = t.op.WriteAt([]byte("taco"), 0)
	AssertEq(nil, err)
	AssertEq(len("taco"), n)

	n, err = t.op.WriteAt([]byte("burrito"), int64(len("taco")))
	AssertEq(nil, err)
	AssertEq(len("burrito"), n)

	// Read the whole thing.
	buf = make([]byte, 1024)
	n, err = t.op.ReadAt(buf, 0)

	AssertEq(io.EOF, err)
	ExpectEq(len("tacoburrito"), n)
	ExpectEq("tacoburrito", string(buf[:n]))

	// Read a range in the middle.
	buf = make([]byte, 4)
	n, err = t.op.ReadAt(buf, 3)

	AssertEq(nil, err)
	ExpectEq(4, n)
	ExpectEq("obur", string(buf[:n]))
}

func (t *NoSourceObjectTest) WritePastEndOfObjectThenRead() {
	var n int
	var err error
	var buf []byte

	// Extend the object by writing past its end.
	n, err = t.op.WriteAt([]byte("taco"), 2)
	AssertEq(nil, err)
	AssertEq(len("taco"), n)

	// Read the whole thing.
	buf = make([]byte, 1024)
	n, err = t.op.ReadAt(buf, 0)

	AssertEq(io.EOF, err)
	ExpectEq(2+len("taco"), n)
	ExpectEq("\x00\x00taco", string(buf[:n]))

	// Read a range in the middle.
	buf = make([]byte, 4)
	n, err = t.op.ReadAt(buf, 1)

	AssertEq(nil, err)
	ExpectEq(4, n)
	ExpectEq("\x00tac", string(buf[:n]))
}

func (t *NoSourceObjectTest) WriteWithinObjectThenRead() {
	var n int
	var err error
	var buf []byte

	// Write several bytes to extend the object.
	n, err = t.op.WriteAt([]byte("00000"), 0)
	AssertEq(nil, err)
	AssertEq(len("00000"), n)

	// Overwrite some in the middle.
	n, err = t.op.WriteAt([]byte("11"), 1)
	AssertEq(nil, err)
	AssertEq(len("11"), n)

	// Read the whole thing.
	buf = make([]byte, 1024)
	n, err = t.op.ReadAt(buf, 0)

	AssertEq(io.EOF, err)
	ExpectEq(len("01100"), n)
	ExpectEq("01100", string(buf[:n]))
}

func (t *NoSourceObjectTest) GrowByTruncating() {
	var n int
	var err error
	var buf []byte

	// Truncate
	err = t.op.Truncate(4)
	AssertEq(nil, err)

	// Read the whole thing.
	buf = make([]byte, 1024)
	n, err = t.op.ReadAt(buf, 0)

	AssertEq(io.EOF, err)
	ExpectEq(4, n)
	ExpectEq("\x00\x00\x00\x00", string(buf[:n]))
}

func (t *NoSourceObjectTest) Sync_CallsCreateObject_NoInteractions() {
	// CreateObject -- should receive an empty string and a generation zero
	// precondition.
	ExpectCall(t.bucket, "CreateObject")(
		Any(),
		AllOf(nameIs(t.objectName), contentsAre(""), generationIs(0))).
		WillOnce(oglemock.Return(nil, errors.New("")))

	// Sync
	t.op.Sync()
}

func (t *NoSourceObjectTest) Sync_CallsCreateObject_AfterWriting() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Sync_CreateObjectFails() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Sync_CreateObjectSaysPreconditionFailed() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Sync_Successful() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_CallsBucket() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_BucketFails() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_InitialState() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_AfterShortening() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_AfterGrowing() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_AfterReading() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_AfterWriting() {
	AssertTrue(false, "TODO")
}

func (t *NoSourceObjectTest) Stat_Clobbered() {
	AssertTrue(false, "TODO")
}

////////////////////////////////////////////////////////////////////////
// Source object present
////////////////////////////////////////////////////////////////////////

// A test whose initial conditions are an object proxy branching from a source
// object in the bucket.
type SourceObjectPresentTest struct {
	ObjectProxyTest
	sourceObject *storage.Object
}

var _ SetUpInterface = &SourceObjectPresentTest{}

func init() { RegisterTestSuite(&SourceObjectPresentTest{}) }

func (t *SourceObjectPresentTest) SetUp(ti *TestInfo) {
	t.ObjectProxyTest.setUp(ti, 123)
}

func (t *SourceObjectPresentTest) Read_CallsNewReader() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Read_NewReaderFails() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Read_NewReaderSucceeds() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Write_CallsNewReader() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Write_NewReaderFails() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Write_NewReaderSucceeds() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Truncate_CallsNewReader() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Truncate_NewReaderFails() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Truncate_NewReaderSucceeds() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_NoInteractions() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_AfterReading() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_AfterWriting() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_AfterTruncating() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Sync_CallsCreateObject() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_CallsBucket() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_BucketFails() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_BucketSaysNotFound() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_InitialState() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_AfterShortening() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_AfterGrowing() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_AfterReading() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_AfterWriting() {
	AssertTrue(false, "TODO")
}

func (t *SourceObjectPresentTest) Stat_Clobbered() {
	AssertTrue(false, "TODO")
}
<|endoftext|>


<commit_before>package gomarquise

import (
	"fmt"
	"unsafe"
)

// #include <marquise.h>
// #include <stdint.h>
// #cgo LDFLAGS: -lmarquise
import "C"

// Maintains the ZeroMQ context
type MarquiseContext struct {
	consumer   C.marquise_consumer
	connection C.marquise_connection
}

func newMarquiseWriteError(value string) error {
	return fmt.Errorf("libmarquise returned -1 whilst trying to write frame with value %v", value)
}

func newMarquiseContextError(msg string) error {
	return fmt.Errorf("Error initializing libmarquise context: %v", msg)
}

// zmqBroker is a string taking the form of a ZeroMQ URI. batchPeriod
// is the interval at which the worker thread will poll/empty the queue
// of messages.
//
// Wraps C functions from anchor_stats.h:
//
// - as_consumer_new
// - as_connect
func Dial(zmqBroker string, batchPeriod float64) (MarquiseContext, error) {
	context := new(MarquiseContext)
	broker := C.CString(zmqBroker)
	defer C.free(unsafe.Pointer(broker))
	interval := C.double(batchPeriod)
	context.consumer = C.marquise_consumer_new(broker, interval)
	if context.consumer == nil {
		return *context, newMarquiseContextError(fmt.Sprintf("as_consumer_new(%v, %v) returned NULL", broker, interval))
	}
	context.connection = C.marquise_connect(context.consumer)
	if context.connection == nil {
		return *context, newMarquiseContextError(fmt.Sprintf("as_connect(%v) returned NULL", context.consumer))
	}
	return *context, nil
}

func (c MarquiseContext) Shutdown() {
	C.marquise_consumer_shutdown(c.consumer)
}

// Translates a map of source tags to an array of CStrings of fields,
// an array of CStrings of values and a size_t of the number of pairs.
//
// You need to free the two arrays of CStrings in the calling code,
// after you've finished using them.
func translateSource(source map[string]string) ([]*C.char, []*C.char, C.size_t) {
	nTags := len(source)
	tagFields := make([]*C.char, nTags)
	tagValues := make([]*C.char, nTags)
	idx := 0
	for field, value := range source {
		tagFields[idx] = C.CString(field)
		tagValues[idx] = C.CString(value)
		idx += 1
	}
	return tagFields, tagValues, C.size_t(nTags)
}

// Write a (UTF8) string value.
func (c MarquiseContext) WriteText(source map[string]string, data string, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cStr := C.CString(data)
	defer C.free(unsafe.Pointer(cStr))
	cLen := C.size_t(len(data))
	cTimestamp := C.uint64_t(timestamp)
	writeResult := C.marquise_send_text(c.connection, cFields, cValues, tagCount, cStr, cLen, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError(data)
	}
	return nil
}

// Write a 64-bit int value.
func (c MarquiseContext) WriteInt(source map[string]string, data int64, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cInt := C.int64_t(data)
	cTimestamp := C.uint64_t(timestamp)
	writeResult := C.marquise_send_int(c.connection, cFields, cValues, tagCount, cInt, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError(fmt.Sprintf("%v", data))
	}
	return nil
}

// Write a 64-bit float value.
func (c MarquiseContext) WriteReal(source map[string]string, data float64, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cFloat := C.double(data)
	cTimestamp := C.uint64_t(timestamp)
	writeResult := C.marquise_send_real(c.connection, cFields, cValues, tagCount, cFloat, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError(fmt.Sprintf("%v", data))
	}
	return nil
}

// Write an empty/'counter' value.
func (c MarquiseContext) WriteCounter(source map[string]string, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cTimestamp := C.uint64_t(timestamp)
	writeResult := C.marquise_send_counter(c.connection, cFields, cValues, tagCount, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError("<EMPTY>")
	}
	return nil
}

// Write a binary blob/byte array.
func (c MarquiseContext) WriteBinary(source map[string]string, data []byte, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cTimestamp := C.uint64_t(timestamp)
	// FIXME: do less wrong
	buf := make([]C.uint8_t, len(data))
	for i, val := range data {
		buf[i] = C.uint8_t(val)
	}
	nBytes := C.size_t(len(data))
	writeResult := C.marquise_send_binary(c.connection, cFields, cValues, tagCount, &buf[0], nBytes, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError(fmt.Sprintf("%v", data))
	}
	return nil
}
<commit_msg>Add const for version number<commit_after>package gomarquise

import (
	"fmt"
	"unsafe"
)

// #include <marquise.h>
// #include <stdint.h>
// #cgo LDFLAGS: -lmarquise
import "C"

const (
	Version = "1.0.2"
)

// Maintains the ZeroMQ context
type MarquiseContext struct {
	consumer   C.marquise_consumer
	connection C.marquise_connection
}

func newMarquiseWriteError(value string) error {
	return fmt.Errorf("libmarquise returned -1 whilst trying to write frame with value %v", value)
}

func newMarquiseContextError(msg string) error {
	return fmt.Errorf("Error initializing libmarquise context: %v", msg)
}

// zmqBroker is a string taking the form of a ZeroMQ URI. batchPeriod
// is the interval at which the worker thread will poll/empty the queue
// of messages.
//
// Wraps C functions from anchor_stats.h:
//
// - as_consumer_new
// - as_connect
func Dial(zmqBroker string, batchPeriod float64) (MarquiseContext, error) {
	context := new(MarquiseContext)
	broker := C.CString(zmqBroker)
	defer C.free(unsafe.Pointer(broker))
	interval := C.double(batchPeriod)
	context.consumer = C.marquise_consumer_new(broker, interval)
	if context.consumer == nil {
		return *context, newMarquiseContextError(fmt.Sprintf("as_consumer_new(%v, %v) returned NULL", broker, interval))
	}
	context.connection = C.marquise_connect(context.consumer)
	if context.connection == nil {
		return *context, newMarquiseContextError(fmt.Sprintf("as_connect(%v) returned NULL", context.consumer))
	}
	return *context, nil
}

func (c MarquiseContext) Shutdown() {
	C.marquise_consumer_shutdown(c.consumer)
}

// Translates a map of source tags to an array of CStrings of fields,
// an array of CStrings of values and a size_t of the number of pairs.
//
// You need to free the two arrays of CStrings in the calling code,
// after you've finished using them.
func translateSource(source map[string]string) ([]*C.char, []*C.char, C.size_t) {
	nTags := len(source)
	tagFields := make([]*C.char, nTags)
	tagValues := make([]*C.char, nTags)
	idx := 0
	for field, value := range source {
		tagFields[idx] = C.CString(field)
		tagValues[idx] = C.CString(value)
		idx += 1
	}
	return tagFields, tagValues, C.size_t(nTags)
}

// Write a (UTF8) string value.
func (c MarquiseContext) WriteText(source map[string]string, data string, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cStr := C.CString(data)
	defer C.free(unsafe.Pointer(cStr))
	cLen := C.size_t(len(data))
	cTimestamp := C.uint64_t(timestamp)
	writeResult := C.marquise_send_text(c.connection, cFields, cValues, tagCount, cStr, cLen, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError(data)
	}
	return nil
}

// Write a 64-bit int value.
func (c MarquiseContext) WriteInt(source map[string]string, data int64, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cInt := C.int64_t(data)
	cTimestamp := C.uint64_t(timestamp)
	writeResult := C.marquise_send_int(c.connection, cFields, cValues, tagCount, cInt, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError(fmt.Sprintf("%v", data))
	}
	return nil
}

// Write a 64-bit float value.
func (c MarquiseContext) WriteReal(source map[string]string, data float64, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cFloat := C.double(data)
	cTimestamp := C.uint64_t(timestamp)
	writeResult := C.marquise_send_real(c.connection, cFields, cValues, tagCount, cFloat, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError(fmt.Sprintf("%v", data))
	}
	return nil
}

// Write an empty/'counter' value.
func (c MarquiseContext) WriteCounter(source map[string]string, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cTimestamp := C.uint64_t(timestamp)
	writeResult := C.marquise_send_counter(c.connection, cFields, cValues, tagCount, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError("<EMPTY>")
	}
	return nil
}

// Write a binary blob/byte array.
func (c MarquiseContext) WriteBinary(source map[string]string, data []byte, timestamp uint64) error {
	tagFields, tagValues, tagCount := translateSource(source)
	for idx, _ := range tagFields {
		defer C.free(unsafe.Pointer(tagFields[idx]))
		defer C.free(unsafe.Pointer(tagValues[idx]))
	}
	cFields := &tagFields[0]
	cValues := &tagValues[0]
	cTimestamp := C.uint64_t(timestamp)
	// FIXME: do less wrong
	buf := make([]C.uint8_t, len(data))
	for i, val := range data {
		buf[i] = C.uint8_t(val)
	}
	nBytes := C.size_t(len(data))
	writeResult := C.marquise_send_binary(c.connection, cFields, cValues, tagCount, &buf[0], nBytes, cTimestamp)
	if writeResult == -1 {
		return newMarquiseWriteError(fmt.Sprintf("%v", data))
	}
	return nil
}
<|endoftext|>


<commit_before>package gitmedia

import (
	"errors"
	"fmt"
	"github.com/github/git-media/git"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
)

const Version = "0.3.1"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-media")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	LocalLinkDir       string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, 0774); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0744); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func LocalLinkPath(sha string) (string, error) {
	if len(sha) == 0 {
		return "", fmt.Errorf("Error trying to create local object directory, invalid sha: '%s'", sha)
	}
	path := filepath.Join(LocalLinkDir, sha[0:2])
	if err := os.MkdirAll(path, 0744); err != nil {
		return "", fmt.Errorf("Error trying to create local object directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha[2:len(sha)]), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 4, len(osEnviron)+4)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

var shaMatcher = regexp.MustCompile(`^[0-9a-f]{40}`)

func CurrentRef() (string, error) {
	head, err := ioutil.ReadFile(filepath.Join(LocalGitDir, "HEAD"))
	if err != nil {
		return "", err
	}

	if shaMatcher.Match(head) {
		return strings.TrimSpace(string(head)), nil
	}

	headString := string(head)
	parts := strings.Split(headString, " ")
	if len(parts) != 2 {
		return "", errors.New("Unable to parse HEAD")
	}

	refFile := strings.TrimSpace(parts[1])
	sha, err := ioutil.ReadFile(filepath.Join(LocalGitDir, refFile))
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(string(sha)), nil
}

func init() {
	var err error
	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "media")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		LocalLinkDir = filepath.Join(LocalMediaDir, "objects")
		TempDir = filepath.Join(LocalMediaDir, "tmp")

		if err := os.MkdirAll(TempDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

		if err := os.MkdirAll(LocalLinkDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalLinkDir, err))
		}
	}

	gitVersion, err := git.Config.Version()
	if err != nil {
		gitVersion = "unknown"
	}

	UserAgent = fmt.Sprintf("git-media/%s (GitHub; %s %s; git %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(gitVersion, "git version ", "", 1),
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return recursiveResolveGitDir(wd)
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		return filepath.Dir(dir), dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	if info, err := os.Stat(gitDir); err == nil {
		if info.IsDir() {
			return dir, gitDir, nil
		} else {
			return processDotGitFile(gitDir)
		}
	}

	return recursiveResolveGitDir(filepath.Dir(dir))
}

func processDotGitFile(file string) (string, string, error) {
	f, err := os.Open(file)
	defer f.Close()

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

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", "", err
	}

	contents := string(data[0:n])
	wd, _ := os.Getwd()
	if strings.HasPrefix(contents, gitPtrPrefix) {
		dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])
		absDir, _ := filepath.Abs(dir)
		return wd, absDir, nil
	}

	return wd, "", nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<commit_msg>Bump version<commit_after>package gitmedia

import (
	"errors"
	"fmt"
	"github.com/github/git-media/git"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
)

const Version = "0.3.2"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-media")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	LocalLinkDir       string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, 0774); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0744); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func LocalLinkPath(sha string) (string, error) {
	if len(sha) == 0 {
		return "", fmt.Errorf("Error trying to create local object directory, invalid sha: '%s'", sha)
	}
	path := filepath.Join(LocalLinkDir, sha[0:2])
	if err := os.MkdirAll(path, 0744); err != nil {
		return "", fmt.Errorf("Error trying to create local object directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha[2:len(sha)]), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 4, len(osEnviron)+4)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

var shaMatcher = regexp.MustCompile(`^[0-9a-f]{40}`)

func CurrentRef() (string, error) {
	head, err := ioutil.ReadFile(filepath.Join(LocalGitDir, "HEAD"))
	if err != nil {
		return "", err
	}

	if shaMatcher.Match(head) {
		return strings.TrimSpace(string(head)), nil
	}

	headString := string(head)
	parts := strings.Split(headString, " ")
	if len(parts) != 2 {
		return "", errors.New("Unable to parse HEAD")
	}

	refFile := strings.TrimSpace(parts[1])
	sha, err := ioutil.ReadFile(filepath.Join(LocalGitDir, refFile))
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(string(sha)), nil
}

func init() {
	var err error
	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "media")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		LocalLinkDir = filepath.Join(LocalMediaDir, "objects")
		TempDir = filepath.Join(LocalMediaDir, "tmp")

		if err := os.MkdirAll(TempDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

		if err := os.MkdirAll(LocalLinkDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalLinkDir, err))
		}
	}

	gitVersion, err := git.Config.Version()
	if err != nil {
		gitVersion = "unknown"
	}

	UserAgent = fmt.Sprintf("git-media/%s (GitHub; %s %s; git %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(gitVersion, "git version ", "", 1),
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return recursiveResolveGitDir(wd)
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		return filepath.Dir(dir), dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	if info, err := os.Stat(gitDir); err == nil {
		if info.IsDir() {
			return dir, gitDir, nil
		} else {
			return processDotGitFile(gitDir)
		}
	}

	return recursiveResolveGitDir(filepath.Dir(dir))
}

func processDotGitFile(file string) (string, string, error) {
	f, err := os.Open(file)
	defer f.Close()

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

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", "", err
	}

	contents := string(data[0:n])
	wd, _ := os.Getwd()
	if strings.HasPrefix(contents, gitPtrPrefix) {
		dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])
		absDir, _ := filepath.Abs(dir)
		return wd, absDir, nil
	}

	return wd, "", nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<|endoftext|>


<commit_before>package dropship

import (
	"errors"
	"os"
	"os/exec"
	"strings"
)

type ScriptHook struct{}

func (h ScriptHook) Execute(config HookConfig, service Config) error {
	if c := config["command"]; c != "" {

		// TODO(ChrisMcKenzie): Make this more secure by jailing it.
		var cwd string
		if len(service.Artifact) >= 1 {
			cwd = service.Artifact["destination"]
		}

		_, err := executeCommand(c, cwd)
		return err
	}
	return errors.New("Script: exiting no command was given")
}

func executeCommand(c, cwd string) (string, error) {
	sCmd := strings.Fields(c)
	cmd := exec.Command(sCmd[0], sCmd[1:]...)
	if _, err := os.Stat(cwd); !os.IsNotExist(err) {
		cmd.Dir = cwd
	}
	out, err := cmd.Output()
	return string(out), err
}
<commit_msg>added logging for hook_script<commit_after>package dropship

import (
	"errors"
	"log"
	"os"
	"os/exec"
	"strings"
)

type ScriptHook struct{}

func (h ScriptHook) Execute(config HookConfig, service Config) error {
	if c := config["command"]; c != "" {

		// TODO(ChrisMcKenzie): Make this more secure by jailing it.
		var cwd string
		if len(service.Artifact) >= 1 {
			cwd = service.Artifact["destination"]
		}

		out, err := executeCommand(c, cwd)
		log.Printf("[INFO]: %s", out)
		return err
	}
	return errors.New("Script: exiting no command was given")
}

func executeCommand(c, cwd string) (string, error) {
	sCmd := strings.Fields(c)
	cmd := exec.Command(sCmd[0], sCmd[1:]...)
	if _, err := os.Stat(cwd); !os.IsNotExist(err) {
		cmd.Dir = cwd
	}
	out, err := cmd.Output()
	return string(out), err
}
<|endoftext|>


<commit_before>package drouter

import (
	"fmt"
	"net"
	"testing"

	log "github.com/Sirupsen/logrus"
	logtest "github.com/Sirupsen/logrus/hooks/test"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	dockerTypes "github.com/docker/engine-api/types"
	dockerNTypes "github.com/docker/engine-api/types/network"
	"github.com/vishvananda/netlink"
)

const (
	NET_NAME  = "drntest_n%v"
	NET_GW    = "192.168.242.%v"
	NET_IPNET = "192.168.242.%v/29"
)

func createNetwork(n int, dr bool, t *testing.T) dockerTypes.NetworkResource {
	name := fmt.Sprintf(NET_NAME, n)
	opts := make(map[string]string)
	if dr {
		opts["drouter"] = DR_INST
	}
	r, err := dc.NetworkCreate(bg, name, dockerTypes.NetworkCreate{
		Options: opts,
		IPAM: dockerNTypes.IPAM{
			Config: []dockerNTypes.IPAMConfig{
				dockerNTypes.IPAMConfig{
					Subnet:  fmt.Sprintf(NET_IPNET, n*8),
					Gateway: fmt.Sprintf(NET_GW, n*8+1),
				},
			},
		},
	})
	require.Equal(t, err, nil, "Error creating network")

	nr, err := dc.NetworkInspect(bg, r.ID)
	require.Equal(t, err, nil, "Error inspecting network")
	return nr
}

func removeNetwork(id string, t *testing.T) {
	err := dc.NetworkRemove(bg, id)
	if err != nil {
		t.Fatalf("Error removing network: %v", err)
	}
}

func TestNetworkConnect(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)
	n0.connect()
	for _, e := range hook.Entries {
		assert.Equal(log.DebugLevel, e.Level, "All messages should be debug")
	}
	n0.disconnect()
	checkLogs(hook.Entries, t)
}

func TestIPOffset(t *testing.T) {
	assert := assert.New(t)
	ipOffset = 2
	defer func() { ipOffset = 0 }()

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)
	n0.connect()

	routes, err := netlink.RouteGet(net.ParseIP("192.168.242.1"))
	assert.Equal(err, nil, "Error getting routes")
	assert.True(routes[0].Src.Equal(net.ParseIP("192.168.242.2")), "IP not what was expected")

	n0.disconnect()
	checkLogs(hook.Entries, t)
}

func TestNegativeIPOffset(t *testing.T) {
	assert := assert.New(t)
	ipOffset = -1
	defer func() { ipOffset = 0 }()

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)
	n0.connect()

	routes, err := netlink.RouteGet(net.ParseIP("192.168.242.1"))
	assert.Equal(err, nil, "Error getting routes")
	assert.True(routes[0].Src.Equal(net.ParseIP("192.168.242.6")), "IP not what was expected")

	n0.disconnect()
	checkLogs(hook.Entries, t)
}

func TestMultipleConnectWarn(t *testing.T) {
	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)
	n0.connect()
	defer n0.disconnect()
	checkLogs(hook.Entries, t)

	n0.connect()
	// we should not get warnings anymore
	checkLogs(hook.Entries, t)
}

func TestIsConnected(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	n0 := newNetwork(&n0r)
	hook := logtest.NewGlobal()
	assert.False(n0.isConnected(), "Network should not be connected")
	checkLogs(hook.Entries, t)

	n0.connect()
	hook.Reset()
	assert.True(n0.isConnected(), "Network should be connected")
	checkLogs(hook.Entries, t)

	n0.disconnect()
	assert.False(n0.isConnected(), "Network should not be connected")
	checkLogs(hook.Entries, t)
}

func TestIsDrouterTrue(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)
	n0 := newNetwork(&n0r)

	assert.True(n0.isDRouter())
}

func TestIsDrouterFalse(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, false, t)
	defer removeNetwork(n0r.ID, t)
	n0 := newNetwork(&n0r)

	assert.False(n0.isDRouter())
}

func TestIsDrouterTransit(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)
	transitNetID = n0r.ID
	defer func() { transitNetID = "" }()
	n0 := newNetwork(&n0r)

	assert.True(n0.isDRouter())
}

func TestAdminDownNonAggressive(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)
	transitNetID = n0r.ID
	defer func() { transitNetID = "" }()
	n0 := newNetwork(&n0r)

	assert.False(n0.adminDown)
	err := n0.disconnectEvent()
	assert.Equal(err, nil, "Error with disconnectEvent")
	assert.False(n0.adminDown, "adminDown should be False")
}

func TestAdminDownAggressive(t *testing.T) {
	assert := assert.New(t)
	aggressive = true
	defer func() { aggressive = false }()

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)
	transitNetID = n0r.ID
	defer func() { transitNetID = "" }()
	n0 := newNetwork(&n0r)

	assert.False(n0.adminDown)
	err := n0.disconnectEvent()
	assert.Equal(err, nil, "Error with disconnectEvent")
	assert.True(n0.adminDown, "adminDown should be True")

	err = n0.connectEvent()
	assert.Equal(err, nil, "Error with connectEvent")
	assert.False(n0.adminDown, "adminDown should be False")
}

func createMultiSubnetNetwork(n int, dr bool, t *testing.T) dockerTypes.NetworkResource {
	name := fmt.Sprintf(NET_NAME, n)
	opts := make(map[string]string)
	if dr {
		opts["drouter"] = DR_INST
	}
	r, err := dc.NetworkCreate(bg, name, dockerTypes.NetworkCreate{
		Options: opts,
		IPAM: dockerNTypes.IPAM{
			Config: []dockerNTypes.IPAMConfig{
				dockerNTypes.IPAMConfig{
					Subnet:  fmt.Sprintf(NET_IPNET, n*8),
					Gateway: fmt.Sprintf(NET_GW, n*8+1),
				},
				dockerNTypes.IPAMConfig{
					Subnet:  fmt.Sprintf("192.168.243.%v/29", n*8),
					Gateway: fmt.Sprintf("192.168.243.%v", n*8+1),
				},
			},
		},
	})
	require.Equal(t, err, nil, "Error creating network")
	nr, err := dc.NetworkInspect(bg, r.ID)
	require.Equal(t, err, nil, "Error inspecting network")
	return nr
}

// disabled becasue bridge driver doesn't support multiple subnets
func testMultiSubnetIPOffset(t *testing.T) {
	assert := assert.New(t)
	ipOffset = 2
	defer func() { ipOffset = 0 }()

	n0r := createMultiSubnetNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)
	n0.connect()

	routes, err := netlink.RouteGet(net.ParseIP("192.168.242.1"))
	assert.Equal(err, nil, "Error getting routes")

	ip1 := false
	ip2 := false
	for _, r := range routes {
		if r.Src.Equal(net.ParseIP("192.168.242.2")) {
			ip1 = true
		}
		if r.Src.Equal(net.ParseIP("192.168.243.2")) {
			ip2 = true
		}
	}

	assert.True(ip1, "First ip not set")
	assert.True(ip2, "Second ip not set")

	n0.disconnect()
	checkLogs(hook.Entries, t)
}
<commit_msg>changed one line to checkLogs()<commit_after>package drouter

import (
	"fmt"
	"net"
	"testing"

	log "github.com/Sirupsen/logrus"
	logtest "github.com/Sirupsen/logrus/hooks/test"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	dockerTypes "github.com/docker/engine-api/types"
	dockerNTypes "github.com/docker/engine-api/types/network"
	"github.com/vishvananda/netlink"
)

const (
	NET_NAME  = "drntest_n%v"
	NET_GW    = "192.168.242.%v"
	NET_IPNET = "192.168.242.%v/29"
)

func createNetwork(n int, dr bool, t *testing.T) dockerTypes.NetworkResource {
	name := fmt.Sprintf(NET_NAME, n)
	opts := make(map[string]string)
	if dr {
		opts["drouter"] = DR_INST
	}
	r, err := dc.NetworkCreate(bg, name, dockerTypes.NetworkCreate{
		Options: opts,
		IPAM: dockerNTypes.IPAM{
			Config: []dockerNTypes.IPAMConfig{
				dockerNTypes.IPAMConfig{
					Subnet:  fmt.Sprintf(NET_IPNET, n*8),
					Gateway: fmt.Sprintf(NET_GW, n*8+1),
				},
			},
		},
	})
	require.Equal(t, err, nil, "Error creating network")

	nr, err := dc.NetworkInspect(bg, r.ID)
	require.Equal(t, err, nil, "Error inspecting network")
	return nr
}

func removeNetwork(id string, t *testing.T) {
	err := dc.NetworkRemove(bg, id)
	if err != nil {
		t.Fatalf("Error removing network: %v", err)
	}
}

func TestNetworkConnect(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)

	n0.connect()
	checkLogs(hook.Entries, t)

	n0.disconnect()
	checkLogs(hook.Entries, t)
}

func TestIPOffset(t *testing.T) {
	assert := assert.New(t)
	ipOffset = 2
	defer func() { ipOffset = 0 }()

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)
	n0.connect()

	routes, err := netlink.RouteGet(net.ParseIP("192.168.242.1"))
	assert.Equal(err, nil, "Error getting routes")
	assert.True(routes[0].Src.Equal(net.ParseIP("192.168.242.2")), "IP not what was expected")

	n0.disconnect()
	checkLogs(hook.Entries, t)
}

func TestNegativeIPOffset(t *testing.T) {
	assert := assert.New(t)
	ipOffset = -1
	defer func() { ipOffset = 0 }()

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)
	n0.connect()

	routes, err := netlink.RouteGet(net.ParseIP("192.168.242.1"))
	assert.Equal(err, nil, "Error getting routes")
	assert.True(routes[0].Src.Equal(net.ParseIP("192.168.242.6")), "IP not what was expected")

	n0.disconnect()
	checkLogs(hook.Entries, t)
}

func TestMultipleConnectWarn(t *testing.T) {
	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)
	n0.connect()
	defer n0.disconnect()
	checkLogs(hook.Entries, t)

	n0.connect()
	// we should not get warnings anymore
	checkLogs(hook.Entries, t)
}

func TestIsConnected(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	n0 := newNetwork(&n0r)
	hook := logtest.NewGlobal()
	assert.False(n0.isConnected(), "Network should not be connected")
	checkLogs(hook.Entries, t)

	n0.connect()
	hook.Reset()
	assert.True(n0.isConnected(), "Network should be connected")
	checkLogs(hook.Entries, t)

	n0.disconnect()
	assert.False(n0.isConnected(), "Network should not be connected")
	checkLogs(hook.Entries, t)
}

func TestIsDrouterTrue(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)
	n0 := newNetwork(&n0r)

	assert.True(n0.isDRouter())
}

func TestIsDrouterFalse(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, false, t)
	defer removeNetwork(n0r.ID, t)
	n0 := newNetwork(&n0r)

	assert.False(n0.isDRouter())
}

func TestIsDrouterTransit(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)
	transitNetID = n0r.ID
	defer func() { transitNetID = "" }()
	n0 := newNetwork(&n0r)

	assert.True(n0.isDRouter())
}

func TestAdminDownNonAggressive(t *testing.T) {
	assert := assert.New(t)

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)
	transitNetID = n0r.ID
	defer func() { transitNetID = "" }()
	n0 := newNetwork(&n0r)

	assert.False(n0.adminDown)
	err := n0.disconnectEvent()
	assert.Equal(err, nil, "Error with disconnectEvent")
	assert.False(n0.adminDown, "adminDown should be False")
}

func TestAdminDownAggressive(t *testing.T) {
	assert := assert.New(t)
	aggressive = true
	defer func() { aggressive = false }()

	n0r := createNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)
	transitNetID = n0r.ID
	defer func() { transitNetID = "" }()
	n0 := newNetwork(&n0r)

	assert.False(n0.adminDown)
	err := n0.disconnectEvent()
	assert.Equal(err, nil, "Error with disconnectEvent")
	assert.True(n0.adminDown, "adminDown should be True")

	err = n0.connectEvent()
	assert.Equal(err, nil, "Error with connectEvent")
	assert.False(n0.adminDown, "adminDown should be False")
}

func createMultiSubnetNetwork(n int, dr bool, t *testing.T) dockerTypes.NetworkResource {
	name := fmt.Sprintf(NET_NAME, n)
	opts := make(map[string]string)
	if dr {
		opts["drouter"] = DR_INST
	}
	r, err := dc.NetworkCreate(bg, name, dockerTypes.NetworkCreate{
		Options: opts,
		IPAM: dockerNTypes.IPAM{
			Config: []dockerNTypes.IPAMConfig{
				dockerNTypes.IPAMConfig{
					Subnet:  fmt.Sprintf(NET_IPNET, n*8),
					Gateway: fmt.Sprintf(NET_GW, n*8+1),
				},
				dockerNTypes.IPAMConfig{
					Subnet:  fmt.Sprintf("192.168.243.%v/29", n*8),
					Gateway: fmt.Sprintf("192.168.243.%v", n*8+1),
				},
			},
		},
	})
	require.Equal(t, err, nil, "Error creating network")
	nr, err := dc.NetworkInspect(bg, r.ID)
	require.Equal(t, err, nil, "Error inspecting network")
	return nr
}

// disabled becasue bridge driver doesn't support multiple subnets
func testMultiSubnetIPOffset(t *testing.T) {
	assert := assert.New(t)
	ipOffset = 2
	defer func() { ipOffset = 0 }()

	n0r := createMultiSubnetNetwork(0, true, t)
	defer removeNetwork(n0r.ID, t)

	hook := logtest.NewGlobal()
	n0 := newNetwork(&n0r)
	n0.connect()

	routes, err := netlink.RouteGet(net.ParseIP("192.168.242.1"))
	assert.Equal(err, nil, "Error getting routes")

	ip1 := false
	ip2 := false
	for _, r := range routes {
		if r.Src.Equal(net.ParseIP("192.168.242.2")) {
			ip1 = true
		}
		if r.Src.Equal(net.ParseIP("192.168.243.2")) {
			ip2 = true
		}
	}

	assert.True(ip1, "First ip not set")
	assert.True(ip2, "Second ip not set")

	n0.disconnect()
	checkLogs(hook.Entries, t)
}
<|endoftext|>


<commit_before>package builds

import (
	"net/http"
	"sync"
	"time"

	"github.com/winston-ci/redgreen/logbuffer"
)

type Build struct {
	Guid      string      `json:"guid"`
	CreatedAt time.Time   `json:"created_at"`
	Image     string      `json:"image"`
	Path      string      `json:"path"`
	Script    string      `json:"script"`
	Env       [][2]string `json:"env"`
	Status    string      `json:"status"`

	bits        chan *http.Request
	servingBits *sync.WaitGroup

	logBuffer *logbuffer.LogBuffer
}

type BuildResult struct {
	Status string `json:"status"`
}
<commit_msg>omit empty status field<commit_after>package builds

import (
	"net/http"
	"sync"
	"time"

	"github.com/winston-ci/redgreen/logbuffer"
)

type Build struct {
	Guid      string      `json:"guid"`
	CreatedAt time.Time   `json:"created_at"`
	Image     string      `json:"image"`
	Path      string      `json:"path"`
	Script    string      `json:"script"`
	Env       [][2]string `json:"env"`
	Status    string      `json:"status,omitempty"`

	bits        chan *http.Request
	servingBits *sync.WaitGroup

	logBuffer *logbuffer.LogBuffer
}

type BuildResult struct {
	Status string `json:"status"`
}
<|endoftext|>