<commit_before>/*
Copyright 2019 The Skaffold 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 debug

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"

	appsv1 "k8s.io/api/apps/v1"
	batchv1 "k8s.io/api/batch/v1"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

// portAllocator is a function that takes a desired port and returns an available port
// Ports are normally uint16 but Kubernetes ContainerPort.containerPort is an integer
type portAllocator func(int32) int32

// configurationRetriever retrieves an container image configuration
type configurationRetriever func(string) (imageConfiguration, error)

// imageConfiguration captures information from a docker/oci image configuration
type imageConfiguration struct {
	labels     map[string]string
	env        map[string]string
	entrypoint []string
	arguments  []string
}

// containerTransformer transforms a container definition
type containerTransformer interface {
	// IsApplicable determines if this container is suitable to be transformed.
	IsApplicable(config imageConfiguration) bool

	// RuntimeSupportImage returns the associated duct-tape helper image required or empty string
	RuntimeSupportImage() string

	// Apply configures a container definition for debugging, returning a simple map describing the debug configuration details or `nil` if it could not be done
	Apply(container *v1.Container, config imageConfiguration, portAlloc portAllocator) map[string]interface{}
}

var containerTransforms []containerTransformer

// transformManifest attempts to configure a manifest for debugging.
// Returns true if changed, false otherwise.
func transformManifest(obj runtime.Object, retrieveImageConfiguration configurationRetriever) bool {
	one := int32(1)
	switch o := obj.(type) {
	case *v1.Pod:
		return transformPodSpec(&o.ObjectMeta, &o.Spec, retrieveImageConfiguration)
	case *v1.PodList:
		changed := false
		for i := range o.Items {
			if transformPodSpec(&o.Items[i].ObjectMeta, &o.Items[i].Spec, retrieveImageConfiguration) {
				changed = true
			}
		}
		return changed
	case *v1.ReplicationController:
		if o.Spec.Replicas != nil {
			o.Spec.Replicas = &one
		}
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *appsv1.Deployment:
		if o.Spec.Replicas != nil {
			o.Spec.Replicas = &one
		}
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *appsv1.DaemonSet:
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *appsv1.ReplicaSet:
		if o.Spec.Replicas != nil {
			o.Spec.Replicas = &one
		}
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *appsv1.StatefulSet:
		if o.Spec.Replicas != nil {
			o.Spec.Replicas = &one
		}
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *batchv1.Job:
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)

	default:
		group, version, _, description := describe(obj)
		if group == "apps" || group == "batch" {
			if version != "v1" {
				// treat deprecated objects as errors
				logrus.Errorf("deprecated versions not supported by debug: %s (%s)", description, version)
			} else {
				logrus.Warnf("no debug transformation for: %s", description)
			}
		} else {
			logrus.Debugf("no debug transformation for: %s", description)
		}
		return false
	}
}

// transformPodSpec attempts to configure a podspec for debugging.
// Returns true if changed, false otherwise.
func transformPodSpec(metadata *metav1.ObjectMeta, podSpec *v1.PodSpec, retrieveImageConfiguration configurationRetriever) bool {
	portAlloc := func(desiredPort int32) int32 {
		return allocatePort(podSpec, desiredPort)
	}
	// containers are required to have unique name within a pod
	configurations := make(map[string]map[string]interface{})
	requiredSupportImages := make(map[string]string)
	var supportFilesRequired []*v1.Container
	for i := range podSpec.Containers {
		container := &podSpec.Containers[i]
		// we only reconfigure build artifacts
		if configuration, requiredSupportImage, err := transformContainer(container, retrieveImageConfiguration, portAlloc); err == nil {
			configurations[container.Name] = configuration
			if len(requiredSupportImage) > 0 {
				logrus.Infof("%q requires debugging support image %s", container.Name, requiredSupportImage)
				supportFilesRequired = append(supportFilesRequired, container)
				requiredSupportImages[requiredSupportImage] = requiredSupportImage
			}
			// todo: add this artifact to the watch list?
		} else {
			logrus.Infof("Image %q not configured for debugging: %v", container.Name, err)
		}
	}
	if len(supportFilesRequired) > 0 {
		logrus.Infof("Configuring installation of debugging support files")
		supportVolume := v1.Volume{Name: "debugging-support-files", VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}}
		podSpec.Volumes = append(podSpec.Volumes, supportVolume)
		supportVolumeMount := v1.VolumeMount{Name: "debugging-support-files", MountPath: "/dbg"}
		for _, container := range supportFilesRequired {
			container.VolumeMounts = append(container.VolumeMounts, supportVolumeMount)
		}
		// TODO make this pluggable for airgapped clusters? or is making container `imagePullPolicy:IfNotPresent` sufficient?
		for imageID, _ := range requiredSupportImages {
			supportFilesInitContainer := v1.Container{
				Name:         fmt.Sprintf("install-%s-support", imageId),
				Image:        fmt.Sprintf("gcr.io/gcp-dev-tools/duct-tape/%s", imageId),
				VolumeMounts: []v1.VolumeMount{supportVolumeMount},
			}
			podSpec.InitContainers = append(podSpec.InitContainers, supportFilesInitContainer)
		}
	}

	if len(configurations) > 0 {
		if metadata.Annotations == nil {
			metadata.Annotations = make(map[string]string)
		}
		metadata.Annotations["debug.cloud.google.com/config"] = encodeConfigurations(configurations)
		return true
	}
	return false
}

// allocatePort walks the podSpec's containers looking for an available port that is close to desiredPort.
// We deal with wrapping and avoid allocating ports < 1024
func allocatePort(podSpec *v1.PodSpec, desiredPort int32) int32 {
	var maxPort int32 = 65535 // ports are normally [1-65535]
	if desiredPort < 1024 || desiredPort > maxPort {
		desiredPort = 1024 // skip reserved ports
	}
	// We assume ports are rather sparsely allocated, so even if desiredPort
	// is allocated, desiredPort+1 or desiredPort+2 are likely to be free
	for port := desiredPort; port < maxPort; port++ {
		if isPortAvailable(podSpec, port) {
			return port
		}
	}
	for port := desiredPort; port > 1024; port-- {
		if isPortAvailable(podSpec, port) {
			return port
		}
	}
	panic("cannot find available port") // exceedingly unlikely
}

// isPortAvailable returns true if none of the pod's containers specify the given port.
func isPortAvailable(podSpec *v1.PodSpec, port int32) bool {
	for _, container := range podSpec.Containers {
		for _, portSpec := range container.Ports {
			if portSpec.ContainerPort == port {
				return false
			}
		}
	}
	return true
}

// transformContainer rewrites the container definition to enable debugging.
// Returns a debugging configuration description with associated language runtime support
// container image, or an error if the rewrite was unsuccessful.
func transformContainer(container *v1.Container, retrieveImageConfiguration configurationRetriever, portAlloc portAllocator) (map[string]interface{}, string, error) {
	var config imageConfiguration
	config, err := retrieveImageConfiguration(container.Image)
	if err != nil {
		return nil, "", err
	}

	// update image configuration values with those set in the k8s manifest
	for _, envVar := range container.Env {
		// FIXME handle ValueFrom?
		config.env[envVar.Name] = envVar.Value
	}

	if len(container.Command) > 0 {
		config.entrypoint = container.Command
	}
	if len(container.Args) > 0 {
		config.arguments = container.Args
	}

	for _, transform := range containerTransforms {
		if transform.IsApplicable(config) {
			return transform.Apply(container, config, portAlloc), transform.RuntimeSupportImage(), nil
		}
	}
	return nil, "", errors.Errorf("unable to determine runtime for %q", container.Name)
}

func encodeConfigurations(configurations map[string]map[string]interface{}) string {
	bytes, err := json.Marshal(configurations)
	if err != nil {
		return ""
	}
	return string(bytes)
}

func describe(obj runtime.Object) (group, version, kind, description string) {
	// get metadata/name; shamelessly stolen from from k8s.io/cli-runtime/pkg/printers/name.go
	name := "<unknown>"
	if acc, err := meta.Accessor(obj); err == nil {
		if n := acc.GetName(); len(n) > 0 {
			name = n
		}
	}

	gvk := obj.GetObjectKind().GroupVersionKind()
	group = gvk.Group
	version = gvk.Version
	kind = gvk.Kind
	if group == "" {
		description = fmt.Sprintf("%s/%s", strings.ToLower(kind), name)
	} else {
		description = fmt.Sprintf("%s.%s/%s", strings.ToLower(kind), group, name)
	}
	return
}
<commit_msg>make golint really happy<commit_after>/*
Copyright 2019 The Skaffold 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 debug

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"

	appsv1 "k8s.io/api/apps/v1"
	batchv1 "k8s.io/api/batch/v1"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

// portAllocator is a function that takes a desired port and returns an available port
// Ports are normally uint16 but Kubernetes ContainerPort.containerPort is an integer
type portAllocator func(int32) int32

// configurationRetriever retrieves an container image configuration
type configurationRetriever func(string) (imageConfiguration, error)

// imageConfiguration captures information from a docker/oci image configuration
type imageConfiguration struct {
	labels     map[string]string
	env        map[string]string
	entrypoint []string
	arguments  []string
}

// containerTransformer transforms a container definition
type containerTransformer interface {
	// IsApplicable determines if this container is suitable to be transformed.
	IsApplicable(config imageConfiguration) bool

	// RuntimeSupportImage returns the associated duct-tape helper image required or empty string
	RuntimeSupportImage() string

	// Apply configures a container definition for debugging, returning a simple map describing the debug configuration details or `nil` if it could not be done
	Apply(container *v1.Container, config imageConfiguration, portAlloc portAllocator) map[string]interface{}
}

var containerTransforms []containerTransformer

// transformManifest attempts to configure a manifest for debugging.
// Returns true if changed, false otherwise.
func transformManifest(obj runtime.Object, retrieveImageConfiguration configurationRetriever) bool {
	one := int32(1)
	switch o := obj.(type) {
	case *v1.Pod:
		return transformPodSpec(&o.ObjectMeta, &o.Spec, retrieveImageConfiguration)
	case *v1.PodList:
		changed := false
		for i := range o.Items {
			if transformPodSpec(&o.Items[i].ObjectMeta, &o.Items[i].Spec, retrieveImageConfiguration) {
				changed = true
			}
		}
		return changed
	case *v1.ReplicationController:
		if o.Spec.Replicas != nil {
			o.Spec.Replicas = &one
		}
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *appsv1.Deployment:
		if o.Spec.Replicas != nil {
			o.Spec.Replicas = &one
		}
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *appsv1.DaemonSet:
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *appsv1.ReplicaSet:
		if o.Spec.Replicas != nil {
			o.Spec.Replicas = &one
		}
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *appsv1.StatefulSet:
		if o.Spec.Replicas != nil {
			o.Spec.Replicas = &one
		}
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)
	case *batchv1.Job:
		return transformPodSpec(&o.Spec.Template.ObjectMeta, &o.Spec.Template.Spec, retrieveImageConfiguration)

	default:
		group, version, _, description := describe(obj)
		if group == "apps" || group == "batch" {
			if version != "v1" {
				// treat deprecated objects as errors
				logrus.Errorf("deprecated versions not supported by debug: %s (%s)", description, version)
			} else {
				logrus.Warnf("no debug transformation for: %s", description)
			}
		} else {
			logrus.Debugf("no debug transformation for: %s", description)
		}
		return false
	}
}

// transformPodSpec attempts to configure a podspec for debugging.
// Returns true if changed, false otherwise.
func transformPodSpec(metadata *metav1.ObjectMeta, podSpec *v1.PodSpec, retrieveImageConfiguration configurationRetriever) bool {
	portAlloc := func(desiredPort int32) int32 {
		return allocatePort(podSpec, desiredPort)
	}
	// containers are required to have unique name within a pod
	configurations := make(map[string]map[string]interface{})
	requiredSupportImages := make(map[string]string)
	var supportFilesRequired []*v1.Container
	for i := range podSpec.Containers {
		container := &podSpec.Containers[i]
		// we only reconfigure build artifacts
		if configuration, requiredSupportImage, err := transformContainer(container, retrieveImageConfiguration, portAlloc); err == nil {
			configurations[container.Name] = configuration
			if len(requiredSupportImage) > 0 {
				logrus.Infof("%q requires debugging support image %q", container.Name, requiredSupportImage)
				supportFilesRequired = append(supportFilesRequired, container)
				requiredSupportImages[requiredSupportImage] = requiredSupportImage
			}
			// todo: add this artifact to the watch list?
		} else {
			logrus.Infof("Image %q not configured for debugging: %v", container.Name, err)
		}
	}
	if len(supportFilesRequired) > 0 {
		logrus.Infof("Configuring installation of debugging support files")
		supportVolume := v1.Volume{Name: "debugging-support-files", VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}}
		podSpec.Volumes = append(podSpec.Volumes, supportVolume)
		supportVolumeMount := v1.VolumeMount{Name: "debugging-support-files", MountPath: "/dbg"}
		for _, container := range supportFilesRequired {
			container.VolumeMounts = append(container.VolumeMounts, supportVolumeMount)
		}
		// TODO make this pluggable for airgapped clusters? or is making container `imagePullPolicy:IfNotPresent` sufficient?
		for imageID := range requiredSupportImages {
			supportFilesInitContainer := v1.Container{
				Name:         fmt.Sprintf("install-%s-support", imageID),
				Image:        fmt.Sprintf("gcr.io/gcp-dev-tools/duct-tape/%s", imageID),
				VolumeMounts: []v1.VolumeMount{supportVolumeMount},
			}
			podSpec.InitContainers = append(podSpec.InitContainers, supportFilesInitContainer)
		}
	}

	if len(configurations) > 0 {
		if metadata.Annotations == nil {
			metadata.Annotations = make(map[string]string)
		}
		metadata.Annotations["debug.cloud.google.com/config"] = encodeConfigurations(configurations)
		return true
	}
	return false
}

// allocatePort walks the podSpec's containers looking for an available port that is close to desiredPort.
// We deal with wrapping and avoid allocating ports < 1024
func allocatePort(podSpec *v1.PodSpec, desiredPort int32) int32 {
	var maxPort int32 = 65535 // ports are normally [1-65535]
	if desiredPort < 1024 || desiredPort > maxPort {
		desiredPort = 1024 // skip reserved ports
	}
	// We assume ports are rather sparsely allocated, so even if desiredPort
	// is allocated, desiredPort+1 or desiredPort+2 are likely to be free
	for port := desiredPort; port < maxPort; port++ {
		if isPortAvailable(podSpec, port) {
			return port
		}
	}
	for port := desiredPort; port > 1024; port-- {
		if isPortAvailable(podSpec, port) {
			return port
		}
	}
	panic("cannot find available port") // exceedingly unlikely
}

// isPortAvailable returns true if none of the pod's containers specify the given port.
func isPortAvailable(podSpec *v1.PodSpec, port int32) bool {
	for _, container := range podSpec.Containers {
		for _, portSpec := range container.Ports {
			if portSpec.ContainerPort == port {
				return false
			}
		}
	}
	return true
}

// transformContainer rewrites the container definition to enable debugging.
// Returns a debugging configuration description with associated language runtime support
// container image, or an error if the rewrite was unsuccessful.
func transformContainer(container *v1.Container, retrieveImageConfiguration configurationRetriever, portAlloc portAllocator) (map[string]interface{}, string, error) {
	var config imageConfiguration
	config, err := retrieveImageConfiguration(container.Image)
	if err != nil {
		return nil, "", err
	}

	// update image configuration values with those set in the k8s manifest
	for _, envVar := range container.Env {
		// FIXME handle ValueFrom?
		config.env[envVar.Name] = envVar.Value
	}

	if len(container.Command) > 0 {
		config.entrypoint = container.Command
	}
	if len(container.Args) > 0 {
		config.arguments = container.Args
	}

	for _, transform := range containerTransforms {
		if transform.IsApplicable(config) {
			return transform.Apply(container, config, portAlloc), transform.RuntimeSupportImage(), nil
		}
	}
	return nil, "", errors.Errorf("unable to determine runtime for %q", container.Name)
}

func encodeConfigurations(configurations map[string]map[string]interface{}) string {
	bytes, err := json.Marshal(configurations)
	if err != nil {
		return ""
	}
	return string(bytes)
}

func describe(obj runtime.Object) (group, version, kind, description string) {
	// get metadata/name; shamelessly stolen from from k8s.io/cli-runtime/pkg/printers/name.go
	name := "<unknown>"
	if acc, err := meta.Accessor(obj); err == nil {
		if n := acc.GetName(); len(n) > 0 {
			name = n
		}
	}

	gvk := obj.GetObjectKind().GroupVersionKind()
	group = gvk.Group
	version = gvk.Version
	kind = gvk.Kind
	if group == "" {
		description = fmt.Sprintf("%s/%s", strings.ToLower(kind), name)
	} else {
		description = fmt.Sprintf("%s.%s/%s", strings.ToLower(kind), group, name)
	}
	return
}
<|endoftext|>


<commit_before>// +build linux freebsd

package system

import (
	"strings"
	"testing"

	"github.com/docker/go-units"
)

// TestMemInfo tests parseMemInfo with a static meminfo string
func TestMemInfo(t *testing.T) {
	const input = `
	MemTotal:      1 kB
	MemFree:       2 kB
	SwapTotal:     3 kB
	SwapFree:      4 kB
	Malformed1:
	Malformed2:    1
	Malformed3:    2 MB
	Malformed4:    X kB
	`
	meminfo, err := parseMemInfo(strings.NewReader(input))
	if err != nil {
		t.Fatal(err)
	}
	if meminfo.MemTotal != 1*units.KiB {
		t.Fatalf("Unexpected MemTotal: %d", meminfo.MemTotal)
	}
	if meminfo.MemFree != 2*units.KiB {
		t.Fatalf("Unexpected MemFree: %d", meminfo.MemFree)
	}
	if meminfo.SwapTotal != 3*units.KiB {
		t.Fatalf("Unexpected SwapTotal: %d", meminfo.SwapTotal)
	}
	if meminfo.SwapFree != 4*units.KiB {
		t.Fatalf("Unexpected SwapFree: %d", meminfo.SwapFree)
	}
}
<commit_msg>Disable meminfo_unix_test on FreeBSD<commit_after>//go:build linux
// +build linux

package system

import (
	"strings"
	"testing"

	"github.com/docker/go-units"
)

// TestMemInfo tests parseMemInfo with a static meminfo string
func TestMemInfo(t *testing.T) {
	const input = `
	MemTotal:      1 kB
	MemFree:       2 kB
	SwapTotal:     3 kB
	SwapFree:      4 kB
	Malformed1:
	Malformed2:    1
	Malformed3:    2 MB
	Malformed4:    X kB
	`
	meminfo, err := parseMemInfo(strings.NewReader(input))
	if err != nil {
		t.Fatal(err)
	}
	if meminfo.MemTotal != 1*units.KiB {
		t.Fatalf("Unexpected MemTotal: %d", meminfo.MemTotal)
	}
	if meminfo.MemFree != 2*units.KiB {
		t.Fatalf("Unexpected MemFree: %d", meminfo.MemFree)
	}
	if meminfo.SwapTotal != 3*units.KiB {
		t.Fatalf("Unexpected SwapTotal: %d", meminfo.SwapTotal)
	}
	if meminfo.SwapFree != 4*units.KiB {
		t.Fatalf("Unexpected SwapFree: %d", meminfo.SwapFree)
	}
}
<|endoftext|>


<commit_before>package constants

const (
	//Constants
	TPRName                   = "postgresql"
	TPRVendor                 = "acid.zalan.do"
	TPRDescription            = "Managed PostgreSQL clusters"
	TPRApiVersion             = "v1"
	DataVolumeName            = "pgdata"
	PasswordLength            = 64
	UserSecretTemplate        = "%s.%s.credentials.%s.%s" // Username, ClusterName, TPRName, TPRVendor
	ZalandoDnsNameAnnotation  = "zalando.org/dnsname"
	ElbTimeoutAnnotationName  = "service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout"
	ElbTimeoutAnnotationValue = "3600"
	KubeIAmAnnotation         = "iam.amazonaws.com/role"
	ResourceName              = TPRName + "s"
	PodRoleMaster             = "master"
	PodRoleReplica            = "replica"
)
<commit_msg>update annotation for ExternalDNS (#115)<commit_after>package constants

const (
	//Constants
	TPRName                   = "postgresql"
	TPRVendor                 = "acid.zalan.do"
	TPRDescription            = "Managed PostgreSQL clusters"
	TPRApiVersion             = "v1"
	DataVolumeName            = "pgdata"
	PasswordLength            = 64
	UserSecretTemplate        = "%s.%s.credentials.%s.%s" // Username, ClusterName, TPRName, TPRVendor
	ZalandoDnsNameAnnotation  = "external-dns.alpha.kubernetes.io/hostname"
	ElbTimeoutAnnotationName  = "service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout"
	ElbTimeoutAnnotationValue = "3600"
	KubeIAmAnnotation         = "iam.amazonaws.com/role"
	ResourceName              = TPRName + "s"
	PodRoleMaster             = "master"
	PodRoleReplica            = "replica"
)
<|endoftext|>


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

// Read system port mappings from /etc/services

package net

import (
	"os"
	"sync"
)

var services map[string]map[string]int
var servicesError os.Error
var onceReadServices sync.Once

func readServices() {
	services = make(map[string]map[string]int)
	var file *file
	file, servicesError = open("/etc/services")
	for line, ok := file.readLine(); ok; line, ok = file.readLine() {
		// "http 80/tcp www www-http # World Wide Web HTTP"
		if i := byteIndex(line, '#'); i >= 0 {
			line = line[0:i]
		}
		f := getFields(line)
		if len(f) < 2 {
			continue
		}
		portnet := f[1] // "tcp/80"
		port, j, ok := dtoi(portnet, 0)
		if !ok || port <= 0 || j >= len(portnet) || portnet[j] != '/' {
			continue
		}
		netw := portnet[j+1:] // "tcp"
		m, ok1 := services[netw]
		if !ok1 {
			m = make(map[string]int)
			services[netw] = m
		}
		for i := 0; i < len(f); i++ {
			if i != 1 { // f[1] was port/net
				m[f[i]] = port
			}
		}
	}
	file.close()
}

// LookupPort looks up the port for the given network and service.
func LookupPort(network, service string) (port int, err os.Error) {
	onceReadServices.Do(readServices)

	switch network {
	case "tcp4", "tcp6":
		network = "tcp"
	case "udp4", "udp6":
		network = "udp"
	}

	if m, ok := services[network]; ok {
		if port, ok = m[service]; ok {
			return
		}
	}
	return 0, &AddrError{"unknown port", network + "/" + service}
}
<commit_msg>net: avoid nil dereference if /etc/services can't be opened<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Read system port mappings from /etc/services

package net

import (
	"os"
	"sync"
)

var services map[string]map[string]int
var servicesError os.Error
var onceReadServices sync.Once

func readServices() {
	services = make(map[string]map[string]int)
	var file *file
	if file, servicesError = open("/etc/services"); servicesError != nil {
		return
	}
	for line, ok := file.readLine(); ok; line, ok = file.readLine() {
		// "http 80/tcp www www-http # World Wide Web HTTP"
		if i := byteIndex(line, '#'); i >= 0 {
			line = line[0:i]
		}
		f := getFields(line)
		if len(f) < 2 {
			continue
		}
		portnet := f[1] // "tcp/80"
		port, j, ok := dtoi(portnet, 0)
		if !ok || port <= 0 || j >= len(portnet) || portnet[j] != '/' {
			continue
		}
		netw := portnet[j+1:] // "tcp"
		m, ok1 := services[netw]
		if !ok1 {
			m = make(map[string]int)
			services[netw] = m
		}
		for i := 0; i < len(f); i++ {
			if i != 1 { // f[1] was port/net
				m[f[i]] = port
			}
		}
	}
	file.close()
}

// LookupPort looks up the port for the given network and service.
func LookupPort(network, service string) (port int, err os.Error) {
	onceReadServices.Do(readServices)

	switch network {
	case "tcp4", "tcp6":
		network = "tcp"
	case "udp4", "udp6":
		network = "udp"
	}

	if m, ok := services[network]; ok {
		if port, ok = m[service]; ok {
			return
		}
	}
	return 0, &AddrError{"unknown port", network + "/" + service}
}
<|endoftext|>


<commit_before>package v2

import (
	"strconv"
	"strings"
	"testing"
)

var (
	// regexpTestcases is a unified set of testcases for
	// TestValidateRepositoryName and TestRepositoryNameRegexp.
	// Some of them are valid inputs for one and not the other.
	regexpTestcases = []struct {
		// input is the repository name or name component testcase
		input string
		// err is the error expected from ValidateRepositoryName, or nil
		err error
		// invalid should be true if the testcase is *not* expected to
		// match RepositoryNameRegexp
		invalid bool
	}{
		{
			input: "",
			err:   ErrRepositoryNameEmpty,
		},
		{
			input: "short",
		},
		{
			input: "simple/name",
		},
		{
			input: "library/ubuntu",
		},
		{
			input: "docker/stevvooe/app",
		},
		{
			input: "aa/aa/aa/aa/aa/aa/aa/aa/aa/bb/bb/bb/bb/bb/bb",
		},
		{
			input: "aa/aa/bb/bb/bb",
		},
		{
			input: "a/a/a/b/b",
		},
		{
			input:   "a/a/a/a/",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "a//a/a",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input: "a",
		},
		{
			input: "a/aa",
		},
		{
			input: "aa/a",
		},
		{
			input: "a/aa/a",
		},
		{
			input:   "foo.com/",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			// TODO: this testcase should be valid once we switch to
			// the reference package.
			input:   "foo.com:8080/bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input: "foo.com/bar",
		},
		{
			input: "foo.com/bar/baz",
		},
		{
			input: "foo.com/bar/baz/quux",
		},
		{
			input: "blog.foo.com/bar/baz",
		},
		{
			input: "asdf",
		},
		{
			input:   "asdf$$^/aa",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input: "aa-a/aa",
		},
		{
			input: "aa/aa",
		},
		{
			input: "a-a/a-a",
		},
		{
			input:   "a-/a/a/a",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input: strings.Repeat("a", 255),
		},
		{
			input: strings.Repeat("a", 256),
			err:   ErrRepositoryNameLong,
		},
		{
			input:   "-foo/bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "foo/bar-",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "foo-/bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "foo/-bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "_foo/bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "foo/bar_",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "____/____",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "_docker/_docker",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "docker_/docker_",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
	}
)

// TestValidateRepositoryName tests the ValidateRepositoryName function,
// which uses RepositoryNameComponentAnchoredRegexp for validation
func TestValidateRepositoryName(t *testing.T) {
	for _, testcase := range regexpTestcases {
		failf := func(format string, v ...interface{}) {
			t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
			t.Fail()
		}

		if err := ValidateRepositoryName(testcase.input); err != testcase.err {
			if testcase.err != nil {
				if err != nil {
					failf("unexpected error for invalid repository: got %v, expected %v", err, testcase.err)
				} else {
					failf("expected invalid repository: %v", testcase.err)
				}
			} else {
				if err != nil {
					// Wrong error returned.
					failf("unexpected error validating repository name: %v, expected %v", err, testcase.err)
				} else {
					failf("unexpected error validating repository name: %v", err)
				}
			}
		}
	}
}

func TestRepositoryNameRegexp(t *testing.T) {
	for _, testcase := range regexpTestcases {
		failf := func(format string, v ...interface{}) {
			t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
			t.Fail()
		}

		matches := RepositoryNameRegexp.FindString(testcase.input) == testcase.input
		if matches == testcase.invalid {
			if testcase.invalid {
				failf("expected invalid repository name %s", testcase.input)
			} else {
				failf("expected valid repository name %s", testcase.input)
			}
		}
	}
}
<commit_msg>Add image name tests around hostnames<commit_after>package v2

import (
	"strconv"
	"strings"
	"testing"
)

var (
	// regexpTestcases is a unified set of testcases for
	// TestValidateRepositoryName and TestRepositoryNameRegexp.
	// Some of them are valid inputs for one and not the other.
	regexpTestcases = []struct {
		// input is the repository name or name component testcase
		input string
		// err is the error expected from ValidateRepositoryName, or nil
		err error
		// invalid should be true if the testcase is *not* expected to
		// match RepositoryNameRegexp
		invalid bool
	}{
		{
			input: "",
			err:   ErrRepositoryNameEmpty,
		},
		{
			input: "short",
		},
		{
			input: "simple/name",
		},
		{
			input: "library/ubuntu",
		},
		{
			input: "docker/stevvooe/app",
		},
		{
			input: "aa/aa/aa/aa/aa/aa/aa/aa/aa/bb/bb/bb/bb/bb/bb",
		},
		{
			input: "aa/aa/bb/bb/bb",
		},
		{
			input: "a/a/a/b/b",
		},
		{
			input:   "a/a/a/a/",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "a//a/a",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input: "a",
		},
		{
			input: "a/aa",
		},
		{
			input: "aa/a",
		},
		{
			input: "a/aa/a",
		},
		{
			input:   "foo.com/",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			// TODO: this testcase should be valid once we switch to
			// the reference package.
			input:   "foo.com:8080/bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input: "foo.com/bar",
		},
		{
			input: "foo.com/bar/baz",
		},
		{
			input: "foo.com/bar/baz/quux",
		},
		{
			input: "blog.foo.com/bar/baz",
		},
		{
			input: "asdf",
		},
		{
			input:   "asdf$$^/aa",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input: "aa-a/aa",
		},
		{
			input: "aa/aa",
		},
		{
			input: "a-a/a-a",
		},
		{
			input:   "a-/a/a/a",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input: strings.Repeat("a", 255),
		},
		{
			input: strings.Repeat("a", 256),
			err:   ErrRepositoryNameLong,
		},
		{
			input:   "-foo/bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "foo/bar-",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "foo-/bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "foo/-bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "_foo/bar",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "foo/bar_",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "____/____",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "_docker/_docker",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "docker_/docker_",
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input: "b.gcr.io/test.example.com/my-app", // embedded domain component
		},
		// TODO(stevvooe): The following is a punycode domain name that we may
		// want to allow in the future. Currently, this is not allowed but we
		// may want to change this in the future. Adding this here as invalid
		// for the time being.
		{
			input:   "xn--n3h.com/myimage", // http://☃.com in punycode
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
		{
			input:   "xn--7o8h.com/myimage", // http://🐳.com in punycode
			err:     ErrRepositoryNameComponentInvalid,
			invalid: true,
		},
	}
)

// TestValidateRepositoryName tests the ValidateRepositoryName function,
// which uses RepositoryNameComponentAnchoredRegexp for validation
func TestValidateRepositoryName(t *testing.T) {
	for _, testcase := range regexpTestcases {
		failf := func(format string, v ...interface{}) {
			t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
			t.Fail()
		}

		if err := ValidateRepositoryName(testcase.input); err != testcase.err {
			if testcase.err != nil {
				if err != nil {
					failf("unexpected error for invalid repository: got %v, expected %v", err, testcase.err)
				} else {
					failf("expected invalid repository: %v", testcase.err)
				}
			} else {
				if err != nil {
					// Wrong error returned.
					failf("unexpected error validating repository name: %v, expected %v", err, testcase.err)
				} else {
					failf("unexpected error validating repository name: %v", err)
				}
			}
		}
	}
}

func TestRepositoryNameRegexp(t *testing.T) {
	for _, testcase := range regexpTestcases {
		failf := func(format string, v ...interface{}) {
			t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
			t.Fail()
		}

		matches := RepositoryNameRegexp.FindString(testcase.input) == testcase.input
		if matches == testcase.invalid {
			if testcase.invalid {
				failf("expected invalid repository name %s", testcase.input)
			} else {
				failf("expected valid repository name %s", testcase.input)
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes 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 main

import (
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/golang/glog"

	"k8s.io/ingress/core/pkg/ingress/controller"
)

func main() {
	// start a new nginx controller
	ngx := newNGINXController()
	// create a custom Ingress controller using NGINX as backend
	ic := controller.NewIngressController(ngx)
	go handleSigterm(ic)
	// start the controller
	ic.Start()
	// wait
	glog.Infof("shutting down Ingress controller...")
	for {
		glog.Infof("Handled quit, awaiting pod deletion")
		time.Sleep(30 * time.Second)
	}
}

func handleSigterm(ic *controller.GenericController) {
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGTERM)
	<-signalChan
	glog.Infof("Received SIGTERM, shutting down")

	exitCode := 0
	if err := ic.Stop(); err != nil {
		glog.Infof("Error during shutdown %v", err)
		exitCode = 1
	}

	glog.Infof("Exiting with %v", exitCode)
	os.Exit(exitCode)
}
<commit_msg><commit_after>/*
Copyright 2015 The Kubernetes 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 main

import (
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/golang/glog"

	"k8s.io/ingress/core/pkg/ingress/controller"
)

func main() {
	callback := func(pid int, wstatus syscall.WaitStatus) {
		glog.V(2).Infof("removing child process pid %d, wstatus: %+v\n", pid, wstatus)
	}

	sig := make(chan os.Signal, 1024)
	signal.Notify(sig, syscall.SIGCHLD)
	go reapChildren(sig, callback)

	// start a new nginx controller
	ngx := newNGINXController()
	// create a custom Ingress controller using NGINX as backend
	ic := controller.NewIngressController(ngx)
	go handleSigterm(ic)
	// start the controller
	ic.Start()
	// wait
	glog.Infof("shutting down Ingress controller...")
	for {
		glog.Infof("Handled quit, awaiting pod deletion")
		time.Sleep(30 * time.Second)
	}
}

func handleSigterm(ic *controller.GenericController) {
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGTERM)
	<-signalChan
	glog.Infof("Received SIGTERM, shutting down")

	exitCode := 0
	if err := ic.Stop(); err != nil {
		glog.Infof("Error during shutdown %v", err)
		exitCode = 1
	}

	glog.Infof("Exiting with %v", exitCode)
	os.Exit(exitCode)
}

func reapChildren(signal chan os.Signal, callback func(int, syscall.WaitStatus)) {
	for {
		<-signal
		for {
			var status syscall.WaitStatus
			pid, _ := syscall.Wait4(-1, &status, 0, nil)
			if pid <= 0 {
				break
			}
			callback(pid, status)
			break
		}
	}
}
<|endoftext|>


<commit_before>package templates

import "text/template"

var templates = map[string]string{"field.tmpl": `{{initialCap .Name}} {{.Type}} {{jsonTag .Name .Required}} {{asComment .Definition.Description}}
`,
	"funcs.tmpl": `{{$Name := .Name}}
{{$Def := .Definition}}
{{range .Definition.Links}}
  {{if eq .Rel "update" "create" }}
   type {{printf "%s-%s-Opts" $Name .Title | initialCap}} {{.GoType}}
  {{end}}

  {{asComment .Description}}
  func (s *Service) {{printf "%s-%s" $Name .Title | initialCap}}({{params .}}) ({{values $Name $Def .}}) {
    {{if eq .Rel "destroy"}}
      return s.Delete(fmt.Sprintf("{{.HRef}}", {{args .HRef}}))
    {{else if eq .Rel "self"}}
      {{$Var := initialLow $Name}}var {{$Var}} {{initialCap $Name}}
      return {{if $Def.IsCustomType}}&{{end}}{{$Var}}, s.Get(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{args .HRef}}), nil)
    {{else if eq .Rel "instances"}}
      {{$Var := printf "%s-%s" $Name "List" | initialLow}}
      var {{$Var}} []*{{initialCap $Name}}
      return {{$Var}}, s.Get(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{args .HRef}}), lr)
    {{else if eq .Rel "empty"}}
      return s.{{methodCap .Method}}(fmt.Sprintf("{{.HRef}}", {{args .HRef}}))
    {{else}}
      {{$Var := initialLow $Name}}var {{$Var}} {{initialCap $Name}}
      return {{if $Def.IsCustomType}}&{{end}}{{$Var}}, s.{{methodCap .Method}}(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{args .HRef}}), o)
    {{end}}
  }
{{end}}

`,
	"imports.tmpl": `{{if .}}
  {{if len . | eq 1}}
    import {{range .}}"{{.}}"{{end}}
  {{else}}
    import (
      {{range .}}
				"{{.}}"
			{{end}}
		)
	{{end}}
{{end}}`,
	"package.tmpl": `// Generated service client for {{.}} API.
//
// To be able to interact with this API, you have to
// create a new service:
//
//     s := {{.}}.NewService(nil)
//
// The Service struct has all the methods you need
// to interact with {{.}} API.
//
package {{.}}
`,
	"service.tmpl": `const (
	Version          = "{{.Version}}"
	DefaultAPIURL    = "{{.URL}}"
	DefaultUserAgent = "{{.Name}}/" + Version + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")"
)

// Service represents your API.
type Service struct {
	client *http.Client
}

// NewService creates a Service using the given, if none is provided
// it uses http.DefaultClient.
func NewService(c *http.Client) *Service {
	if c == nil {
		c = http.DefaultClient
	}
	return &Service{
		client: c,
	}
}

// NewRequest generates an HTTP request, but does not perform the request.
func (s *Service) NewRequest(method, path string, body interface{}) (*http.Request, error) {
	var ctype string
	var rbody io.Reader

	switch t := body.(type) {
	case nil:
	case string:
		rbody = bytes.NewBufferString(t)
	case io.Reader:
		rbody = t
	default:
		v := reflect.ValueOf(body)
		if !v.IsValid() {
			break
		}
		if v.Type().Kind() == reflect.Ptr {
			v = reflect.Indirect(v)
			if !v.IsValid() {
				break
			}
		}

		j, err := json.Marshal(body)
		if err != nil {
			return nil, err
		}
		rbody = bytes.NewReader(j)
		ctype = "application/json"
	}
	req, err := http.NewRequest(method, DefaultAPIURL+path, rbody)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", DefaultUserAgent)
	if ctype != "" {
		req.Header.Set("Content-Type", ctype)
	}
	return req, nil
}

// Do sends a request and decodes the response into v.
func (s *Service) Do(v interface{}, method, path string, body interface{}, lr *ListRange) error {
	req, err := s.NewRequest(method, path, body)
	if err != nil {
		return err
	}
	if lr != nil {
		lr.SetHeader(req)
	}
	resp, err := s.client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	switch t := v.(type) {
	case nil:
	case io.Writer:
		_, err = io.Copy(t, resp.Body)
	default:
		err = json.NewDecoder(resp.Body).Decode(v)
	}
	return err
}

func (s *Service) Get(v interface{}, path string, lr *ListRange) error {
	return s.Do(v, "GET", path, nil, lr)
}

func (s *Service) Patch(v interface{}, path string, body interface{}) error {
	return s.Do(v, "PATCH", path, body, nil)
}

func (s *Service) Post(v interface{}, path string, body interface{}) error {
	return s.Do(v, "POST", path, body, nil)
}

func (s *Service) Put(v interface{}, path string, body interface{}) error {
	return s.Do(v, "PUT", path, body, nil)
}

func (s *Service) Delete(path string) error {
	return s.Do(nil, "DELETE", path, nil, nil)
}

type ListRange struct {
	Field      string
	Max        int
	Descending bool
	FirstID    string
	LastID     string
}

func (lr *ListRange) SetHeader(req *http.Request) {
	var hdrval string
	if lr.Field != "" {
		hdrval += lr.Field + " "
	}
	hdrval += lr.FirstID + ".." + lr.LastID
	if lr.Max != 0 {
		hdrval += fmt.Sprintf("; max=%d", lr.Max)
		if lr.Descending {
			hdrval += ", "
		}
	}

	if lr.Descending {
		hdrval += ", order=desc"
	}

	req.Header.Set("Range", hdrval)
	return
}

// Bool allocates a new int value returns a pointer to it.
func Bool(v bool) *bool {
	p := new(bool)
	*p = v
	return p
}

// Int allocates a new int value returns a pointer to it.
func Int(v int) *int {
	p := new(int)
	*p = v
	return p
}

// Float64 allocates a new float64 value returns a pointer to it.
func Float64(v float64) *float64 {
	p := new(float64)
	*p = v
	return p
}

// String allocates a new string value returns a pointer to it.
func String(v string) *string {
	p := new(string)
	*p = v
	return p
}
`,
	"struct.tmpl": `{{asComment .Definition.Description}}
type {{initialCap .Name}} {{goType .Definition}}
`,
}

func Parse(t *template.Template) (*template.Template, error) {
	for name, s := range templates {
		var tmpl *template.Template
		if t == nil {
			t = template.New(name)
		}
		if name == t.Name() {
			tmpl = t
		} else {
			tmpl = t.New(name)
		}
		if _, err := tmpl.Parse(s); err != nil {
			return nil, err
		}
	}
	return t, nil
}

<commit_msg>update templates<commit_after>package templates

import "text/template"

var templates = map[string]string{"field.tmpl": `{{initialCap .Name}} {{.Type}} {{jsonTag .Name .Required}} {{asComment .Definition.Description}}
`,
	"funcs.tmpl": `{{$Name := .Name}}
{{$Def := .Definition}}
{{range .Definition.Links}}
  {{if eq .Rel "update" "create" }}
   type {{printf "%s-%s-Opts" $Name .Title | initialCap}} {{.GoType}}
  {{end}}

  {{asComment .Description}}
  func (s *Service) {{printf "%s-%s" $Name .Title | initialCap}}({{params .}}) ({{values $Name $Def .}}) {
    {{if eq .Rel "destroy"}}
      return s.Delete(fmt.Sprintf("{{.HRef}}", {{args .HRef}}))
    {{else if eq .Rel "self"}}
      {{$Var := initialLow $Name}}var {{$Var}} {{initialCap $Name}}
      return {{if $Def.IsCustomType}}&{{end}}{{$Var}}, s.Get(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{args .HRef}}), nil)
    {{else if eq .Rel "instances"}}
      {{$Var := printf "%s-%s" $Name "List" | initialLow}}
      var {{$Var}} []*{{initialCap $Name}}
      return {{$Var}}, s.Get(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{args .HRef}}), lr)
    {{else if eq .Rel "empty"}}
      return s.{{methodCap .Method}}(fmt.Sprintf("{{.HRef}}", {{args .HRef}}))
    {{else}}
      {{$Var := initialLow $Name}}var {{$Var}} {{initialCap $Name}}
      return {{if $Def.IsCustomType}}&{{end}}{{$Var}}, s.{{methodCap .Method}}(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{args .HRef}}), o)
    {{end}}
  }
{{end}}

`,
	"imports.tmpl": `{{if .}}
  {{if len . | eq 1}}
    import {{range .}}"{{.}}"{{end}}
  {{else}}
    import (
      {{range .}}
				"{{.}}"
			{{end}}
		)
	{{end}}
{{end}}`,
	"package.tmpl": `// Generated service client for {{.}} API.
//
// To be able to interact with this API, you have to
// create a new service:
//
//     s := {{.}}.NewService(nil)
//
// The Service struct has all the methods you need
// to interact with {{.}} API.
//
package {{.}}
`,
	"service.tmpl": `const (
	Version          = "{{.Version}}"
	DefaultAPIURL    = "{{.URL}}"
	DefaultUserAgent = "{{.Name}}/" + Version + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")"
)

// Service represents your API.
type Service struct {
	client *http.Client
}

// NewService creates a Service using the given, if none is provided
// it uses http.DefaultClient.
func NewService(c *http.Client) *Service {
	if c == nil {
		c = http.DefaultClient
	}
	return &Service{
		client: c,
	}
}

// NewRequest generates an HTTP request, but does not perform the request.
func (s *Service) NewRequest(method, path string, body interface{}) (*http.Request, error) {
	var ctype string
	var rbody io.Reader

	switch t := body.(type) {
	case nil:
	case string:
		rbody = bytes.NewBufferString(t)
	case io.Reader:
		rbody = t
	default:
		v := reflect.ValueOf(body)
		if !v.IsValid() {
			break
		}
		if v.Type().Kind() == reflect.Ptr {
			v = reflect.Indirect(v)
			if !v.IsValid() {
				break
			}
		}

		j, err := json.Marshal(body)
		if err != nil {
			return nil, err
		}
		rbody = bytes.NewReader(j)
		ctype = "application/json"
	}
	req, err := http.NewRequest(method, DefaultAPIURL+path, rbody)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", DefaultUserAgent)
	if ctype != "" {
		req.Header.Set("Content-Type", ctype)
	}
	return req, nil
}

// Do sends a request and decodes the response into v.
func (s *Service) Do(v interface{}, method, path string, body interface{}, lr *ListRange) error {
	req, err := s.NewRequest(method, path, body)
	if err != nil {
		return err
	}
	if lr != nil {
		lr.SetHeader(req)
	}
	resp, err := s.client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	switch t := v.(type) {
	case nil:
	case io.Writer:
		_, err = io.Copy(t, resp.Body)
	default:
		err = json.NewDecoder(resp.Body).Decode(v)
	}
	return err
}

func (s *Service) Get(v interface{}, path string, lr *ListRange) error {
	return s.Do(v, "GET", path, nil, lr)
}

func (s *Service) Patch(v interface{}, path string, body interface{}) error {
	return s.Do(v, "PATCH", path, body, nil)
}

func (s *Service) Post(v interface{}, path string, body interface{}) error {
	return s.Do(v, "POST", path, body, nil)
}

func (s *Service) Put(v interface{}, path string, body interface{}) error {
	return s.Do(v, "PUT", path, body, nil)
}

func (s *Service) Delete(path string) error {
	return s.Do(nil, "DELETE", path, nil, nil)
}

type ListRange struct {
	Field      string
	Max        int
	Descending bool
	FirstID    string
	LastID     string
}

func (lr *ListRange) SetHeader(req *http.Request) {
	var hdrval string
	if lr.Field != "" {
		hdrval += lr.Field + " "
	}
	hdrval += lr.FirstID + ".." + lr.LastID
	if lr.Max != 0 {
		hdrval += fmt.Sprintf("; max=%d", lr.Max)
		if lr.Descending {
			hdrval += ", "
		}
	}

	if lr.Descending {
		hdrval += ", order=desc"
	}

	req.Header.Set("Range", hdrval)
	return
}

// Bool allocates a new int value returns a pointer to it.
func Bool(v bool) *bool {
	p := new(bool)
	*p = v
	return p
}

// Int allocates a new int value returns a pointer to it.
func Int(v int) *int {
	p := new(int)
	*p = v
	return p
}

// Float64 allocates a new float64 value returns a pointer to it.
func Float64(v float64) *float64 {
	p := new(float64)
	*p = v
	return p
}

// String allocates a new string value returns a pointer to it.
func String(v string) *string {
	p := new(string)
	*p = v
	return p
}
`,
	"struct.tmpl": `{{asComment .Definition.Description}}
type {{initialCap .Name}} {{goType .Definition}}
`,
}

// Parse parses declared templates.
func Parse(t *template.Template) (*template.Template, error) {
	for name, s := range templates {
		var tmpl *template.Template
		if t == nil {
			t = template.New(name)
		}
		if name == t.Name() {
			tmpl = t
		} else {
			tmpl = t.New(name)
		}
		if _, err := tmpl.Parse(s); err != nil {
			return nil, err
		}
	}
	return t, nil
}

<|endoftext|>


<commit_before>package main

import "fmt"

func main() {
		solution := 0
		i := 1
    for i <= 10 {
        fmt.Println(i)
        i = i + 1
    }
    fmt.Println("Solution")
}
<commit_msg>Added Go solution<commit_after>package main

import "fmt"

func main() {
		solution := 0
		i := 1
    for i < 1000 {
        if i % 3 == 0 || i % 5 == 0 {
          solution = solution + i
        }
        i = i + 1
    }
    fmt.Println(solution)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/igm/sockjs-go/sockjs"
	"log"
	"net/http"
)

func main() {
	log.Println("server started")

	http.Handle("/echo/", sockjs.SockJSHandler{
		Handler: SockJSHandler,
		Config: sockjs.Config{
			SockjsUrl:     "http://cdn.sockjs.org/sockjs-0.3.2.min.js",
			Websocket:     true,
			ResponseLimit: 4096,
			Prefix:        "/echo",
		},
	})

	http.Handle("/disabled_websocket_echo/", sockjs.SockJSHandler{
		Handler: SockJSHandler,
		Config: sockjs.Config{
			SockjsUrl:     "http://cdn.sockjs.org/sockjs-0.3.2.min.js",
			Websocket:     false,
			ResponseLimit: 4096,
			Prefix:        "/disabled_websocket_echo",
		},
	})

	http.Handle("/close/", sockjs.SockJSHandler{
		Handler: SockJSCloseHandler,
		Config: sockjs.Config{
			SockjsUrl:      "http://cdn.sockjs.org/sockjs-0.3.2.min.js",
			Websocket:      false,
			Prefix:         "/close",
			HeartbeatDelay: 5000,
		},
	})

	http.Handle("/", http.FileServer(http.Dir("./www")))
	err := http.ListenAndServe(":8080", nil)
	log.Fatal(err)
}

func SockJSCloseHandler(session *sockjs.SockJsConn) {
	session.Close()
}

func SockJSHandler(session *sockjs.SockJsConn) {
	log.Println("Session created")
	for {
		val, err := session.Read()
		if err != nil {
			break
		}
		go func() { session.Write(val) }()
	}

	log.Println("session closed")
}
<commit_msg>test server update to handle wrong URLs from sockjs protocol tests<commit_after>package main

import (
	"github.com/igm/sockjs-go/sockjs"
	"log"
	"net/http"
	"path"
)

func main() {
	log.Println("server started")

	http.Handle("/echo/", sockjs.SockJSHandler{
		Handler: SockJSHandler,
		Config: sockjs.Config{
			SockjsUrl:     "http://cdn.sockjs.org/sockjs-0.3.2.min.js",
			Websocket:     true,
			ResponseLimit: 4096,
			Prefix:        "/echo",
		},
	})
	http.Handle("/disabled_websocket_echo/", sockjs.SockJSHandler{
		Handler: SockJSHandler,
		Config: sockjs.Config{
			SockjsUrl:     "http://cdn.sockjs.org/sockjs-0.3.2.min.js",
			Websocket:     false,
			ResponseLimit: 4096,
			Prefix:        "/disabled_websocket_echo",
		},
	})

	http.Handle("/close/", sockjs.SockJSHandler{
		Handler: SockJSCloseHandler,
		Config: sockjs.Config{
			SockjsUrl:      "http://cdn.sockjs.org/sockjs-0.3.2.min.js",
			Websocket:      false,
			Prefix:         "/close",
			HeartbeatDelay: 5000,
		},
	})

	http.Handle("/", http.FileServer(http.Dir("./www")))
	err := http.ListenAndServe(":8080", &TestServer{})
	log.Fatal(err)
}

func SockJSCloseHandler(session *sockjs.SockJsConn) {
	session.Close()
}

func SockJSHandler(session *sockjs.SockJsConn) {
	log.Println("Session created")
	for {
		val, err := session.Read()
		if err != nil {
			break
		}
		go func() { session.Write(val) }()
	}

	log.Println("session closed")
}

// Stolen from http package
func cleanPath(p string) string {
	if p == "" {
		return "/"
	}
	if p[0] != '/' {
		p = "/" + p
	}
	np := path.Clean(p)
	// path.Clean removes trailing slash except for root;
	// put the trailing slash back if necessary.
	if p[len(p)-1] == '/' && np != "/" {
		np += "/"
	}
	return np
}

type TestServer struct {
	*http.ServeMux
}

func (m *TestServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// To get the sockjs-protocol tests to work, barf if the path is not already clean.
	if req.URL.Path != cleanPath(req.URL.Path) {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}
	http.DefaultServeMux.ServeHTTP(w, req)
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package ticketbuyer

import (
	"context"
	"sync"

	"github.com/decred/dcrd/chaincfg/chainhash"
	"github.com/decred/dcrd/dcrutil"
	"github.com/decred/dcrwallet/errors"
	"github.com/decred/dcrwallet/wallet"
)

const minconf = 1

// Config modifies the behavior of TB.
type Config struct {
	// Account to buy tickets from
	Account uint32

	// Account to derive voting addresses from; overridden by VotingAddr
	VotingAccount uint32

	// Minimum amount to maintain in purchasing account
	Maintain dcrutil.Amount

	// Address to assign voting rights; overrides VotingAccount
	VotingAddr dcrutil.Address

	// Commitment address for stakepool fees
	PoolFeeAddr dcrutil.Address

	// Stakepool fee percentage (between 0-100)
	PoolFees float64
}

// TB is an automated ticket buyer, buying as many tickets as possible given an
// account's available balance.  TB may be configured to buy tickets for any
// arbitrary voting address or (optional) stakepool.
type TB struct {
	wallet *wallet.Wallet

	cfg Config
	mu  sync.Mutex
}

// New returns a new TB to buy tickets from a wallet using the default config.
func New(w *wallet.Wallet) *TB {
	return &TB{wallet: w}
}

// Run executes the ticket buyer.  If the private passphrase is incorrect, or
// ever becomes incorrect due to a wallet passphrase change, Run exits with an
// errors.Passphrase error.
func (tb *TB) Run(ctx context.Context, passphrase []byte) error {
	err := tb.wallet.Unlock(passphrase, nil)
	if err != nil {
		return err
	}

	c := tb.wallet.NtfnServer.MainTipChangedNotifications()
	defer c.Done()
	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case n := <-c.C:
			if len(n.AttachedBlocks) == 0 {
				continue
			}
			err := tb.buy(ctx, passphrase, n.AttachedBlocks[len(n.AttachedBlocks)-1])
			if err != nil {
				log.Errorf("Ticket purchasing failed: %v", err)
				if errors.Is(errors.Passphrase, err) {
					return err
				}
			}
		}
	}
}

func (tb *TB) buy(ctx context.Context, passphrase []byte, tip *chainhash.Hash) error {
	w := tb.wallet

	// Don't buy tickets for this attached block when transactions are not
	// synced through the tip block.
	rp, err := w.RescanPoint()
	if err != nil {
		return err
	}
	if rp != nil {
		log.Debugf("Skipping purchase: transactions are not synced")
		return nil
	}

	// Unable to publish any transactions if the network backend is unset.
	_, err = w.NetworkBackend()
	if err != nil {
		return err
	}

	// Ensure wallet is unlocked with the current passphrase.  If the passphase
	// is changed, the Run exits and TB must be restarted with the new
	// passphrase.
	err = w.Unlock(passphrase, nil)
	if err != nil {
		return err
	}

	header, err := w.BlockHeader(tip)
	if err != nil {
		return err
	}
	height := int32(header.Height)

	intervalSize := int32(w.ChainParams().StakeDiffWindowSize)
	currentInterval := height / intervalSize
	nextIntervalStart := (currentInterval + 1) * intervalSize
	// Skip purchase when no more tickets may be purchased in this interval and
	// the next sdiff is unknown.  The earliest any ticket may be mined is two
	// blocks from now, with the next block containing the split transaction
	// that the ticket purchase spends.
	if height+2 == nextIntervalStart {
		log.Debugf("Skipping purchase: next sdiff interval starts soon")
		return nil
	}
	// Set expiry to prevent tickets from being mined in the next
	// sdiff interval.  When the next block begins the new interval,
	// the ticket is being purchased for the next interval; therefore
	// increment expiry by a full sdiff window size to prevent it
	// being mined in the interval after the next.
	expiry := nextIntervalStart
	if height+1 == nextIntervalStart {
		expiry += intervalSize
	}

	// Read config
	tb.mu.Lock()
	account := tb.cfg.Account
	votingAccount := tb.cfg.VotingAccount
	maintain := tb.cfg.Maintain
	votingAddr := tb.cfg.VotingAddr
	poolFeeAddr := tb.cfg.PoolFeeAddr
	poolFees := tb.cfg.PoolFees
	tb.mu.Unlock()

	// Determine how many tickets to buy
	bal, err := w.CalculateAccountBalance(account, minconf)
	if err != nil {
		return err
	}
	spendable := bal.Spendable
	if spendable < maintain {
		log.Debugf("Skipping purchase: low available balance")
		return nil
	}
	spendable -= maintain
	sdiff, err := w.NextStakeDifficultyAfterHeader(header)
	if err != nil {
		return err
	}
	buy := int(spendable / sdiff)
	if buy == 0 {
		log.Debugf("Skipping purchase: low available balance")
		return nil
	}
	if max := int(w.ChainParams().TicketsPerBlock); buy > max {
		buy = max
	}

	// Derive a voting address from voting account when address is unset.
	if votingAddr == nil {
		votingAddr, err = w.NewInternalAddress(votingAccount, wallet.WithGapPolicyWrap())
		if err != nil {
			return err
		}
	}

	feeRate := w.RelayFee()
	tix, err := w.PurchaseTickets(maintain, -1, minconf, votingAddr, account,
		buy, poolFeeAddr, poolFees, expiry, feeRate, feeRate)
	for _, hash := range tix {
		log.Infof("Purchased ticket %v at stake difficulty %v", hash, sdiff)
	}
	if err != nil {
		// Invalid passphrase errors must be returned so Run exits.
		if errors.Is(errors.Passphrase, err) {
			return err
		}
		log.Errorf("One or more tickets could not be purchased: %v", err)
	}
	return nil
}

// AccessConfig runs f with the current config passed as a parameter.  The
// config is protected by a mutex and this function is safe for concurrent
// access to read or modify the config.  It is unsafe to leak a pointer to the
// config, but a copy of *cfg is legal.
func (tb *TB) AccessConfig(f func(cfg *Config)) {
	tb.mu.Lock()
	f(&tb.cfg)
	tb.mu.Unlock()
}
<commit_msg>Avoid ticketbuyer deadlock<commit_after>// Copyright (c) 2018 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package ticketbuyer

import (
	"context"
	"sync"

	"github.com/decred/dcrd/chaincfg/chainhash"
	"github.com/decred/dcrd/dcrutil"
	"github.com/decred/dcrwallet/errors"
	"github.com/decred/dcrwallet/wallet"
)

const minconf = 1

// Config modifies the behavior of TB.
type Config struct {
	// Account to buy tickets from
	Account uint32

	// Account to derive voting addresses from; overridden by VotingAddr
	VotingAccount uint32

	// Minimum amount to maintain in purchasing account
	Maintain dcrutil.Amount

	// Address to assign voting rights; overrides VotingAccount
	VotingAddr dcrutil.Address

	// Commitment address for stakepool fees
	PoolFeeAddr dcrutil.Address

	// Stakepool fee percentage (between 0-100)
	PoolFees float64
}

// TB is an automated ticket buyer, buying as many tickets as possible given an
// account's available balance.  TB may be configured to buy tickets for any
// arbitrary voting address or (optional) stakepool.
type TB struct {
	wallet *wallet.Wallet

	cfg Config
	mu  sync.Mutex
}

// New returns a new TB to buy tickets from a wallet using the default config.
func New(w *wallet.Wallet) *TB {
	return &TB{wallet: w}
}

// Run executes the ticket buyer.  If the private passphrase is incorrect, or
// ever becomes incorrect due to a wallet passphrase change, Run exits with an
// errors.Passphrase error.
func (tb *TB) Run(ctx context.Context, passphrase []byte) error {
	err := tb.wallet.Unlock(passphrase, nil)
	if err != nil {
		return err
	}

	c := tb.wallet.NtfnServer.MainTipChangedNotifications()
	defer c.Done()

	var mu sync.Mutex
	var done bool
	var errc = make(chan error, 1)
	for {
		select {
		case <-ctx.Done():
			mu.Lock()
			done = true
			mu.Unlock()
			return ctx.Err()
		case n := <-c.C:
			if len(n.AttachedBlocks) == 0 {
				continue
			}
			go func() {
				defer mu.Unlock()
				mu.Lock()
				if done {
					return
				}
				b := n.AttachedBlocks[len(n.AttachedBlocks)-1]
				err := tb.buy(ctx, passphrase, b)
				if err != nil {
					log.Errorf("Ticket purchasing failed: %v", err)
					if errors.Is(errors.Passphrase, err) {
						errc <- err
						done = true
					}
				}
			}()
		case err := <-errc:
			return err
		}
	}
}

func (tb *TB) buy(ctx context.Context, passphrase []byte, tip *chainhash.Hash) error {
	w := tb.wallet

	// Don't buy tickets for this attached block when transactions are not
	// synced through the tip block.
	rp, err := w.RescanPoint()
	if err != nil {
		return err
	}
	if rp != nil {
		log.Debugf("Skipping purchase: transactions are not synced")
		return nil
	}

	// Unable to publish any transactions if the network backend is unset.
	_, err = w.NetworkBackend()
	if err != nil {
		return err
	}

	// Ensure wallet is unlocked with the current passphrase.  If the passphase
	// is changed, the Run exits and TB must be restarted with the new
	// passphrase.
	err = w.Unlock(passphrase, nil)
	if err != nil {
		return err
	}

	header, err := w.BlockHeader(tip)
	if err != nil {
		return err
	}
	height := int32(header.Height)

	intervalSize := int32(w.ChainParams().StakeDiffWindowSize)
	currentInterval := height / intervalSize
	nextIntervalStart := (currentInterval + 1) * intervalSize
	// Skip purchase when no more tickets may be purchased in this interval and
	// the next sdiff is unknown.  The earliest any ticket may be mined is two
	// blocks from now, with the next block containing the split transaction
	// that the ticket purchase spends.
	if height+2 == nextIntervalStart {
		log.Debugf("Skipping purchase: next sdiff interval starts soon")
		return nil
	}
	// Set expiry to prevent tickets from being mined in the next
	// sdiff interval.  When the next block begins the new interval,
	// the ticket is being purchased for the next interval; therefore
	// increment expiry by a full sdiff window size to prevent it
	// being mined in the interval after the next.
	expiry := nextIntervalStart
	if height+1 == nextIntervalStart {
		expiry += intervalSize
	}

	// Read config
	tb.mu.Lock()
	account := tb.cfg.Account
	votingAccount := tb.cfg.VotingAccount
	maintain := tb.cfg.Maintain
	votingAddr := tb.cfg.VotingAddr
	poolFeeAddr := tb.cfg.PoolFeeAddr
	poolFees := tb.cfg.PoolFees
	tb.mu.Unlock()

	// Determine how many tickets to buy
	bal, err := w.CalculateAccountBalance(account, minconf)
	if err != nil {
		return err
	}
	spendable := bal.Spendable
	if spendable < maintain {
		log.Debugf("Skipping purchase: low available balance")
		return nil
	}
	spendable -= maintain
	sdiff, err := w.NextStakeDifficultyAfterHeader(header)
	if err != nil {
		return err
	}
	buy := int(spendable / sdiff)
	if buy == 0 {
		log.Debugf("Skipping purchase: low available balance")
		return nil
	}
	if max := int(w.ChainParams().TicketsPerBlock); buy > max {
		buy = max
	}

	// Derive a voting address from voting account when address is unset.
	if votingAddr == nil {
		votingAddr, err = w.NewInternalAddress(votingAccount, wallet.WithGapPolicyWrap())
		if err != nil {
			return err
		}
	}

	feeRate := w.RelayFee()
	tix, err := w.PurchaseTickets(maintain, -1, minconf, votingAddr, account,
		buy, poolFeeAddr, poolFees, expiry, feeRate, feeRate)
	for _, hash := range tix {
		log.Infof("Purchased ticket %v at stake difficulty %v", hash, sdiff)
	}
	if err != nil {
		// Invalid passphrase errors must be returned so Run exits.
		if errors.Is(errors.Passphrase, err) {
			return err
		}
		log.Errorf("One or more tickets could not be purchased: %v", err)
	}
	return nil
}

// AccessConfig runs f with the current config passed as a parameter.  The
// config is protected by a mutex and this function is safe for concurrent
// access to read or modify the config.  It is unsafe to leak a pointer to the
// config, but a copy of *cfg is legal.
func (tb *TB) AccessConfig(f func(cfg *Config)) {
	tb.mu.Lock()
	f(&tb.cfg)
	tb.mu.Unlock()
}
<|endoftext|>


<commit_before>// Copyright 2014, The Serviced Authors. All rights reserved.
// Use of this source code is governed by a
// license that can be found in the LICENSE file.

package servicestate

import (
	"bytes"

	"github.com/zenoss/glog"
	"github.com/zenoss/serviced/domain/service"

	"fmt"
	"regexp"
	"strconv"
	"strings"
	"text/template"
	"time"

	"github.com/zenoss/serviced/domain"
	"github.com/zenoss/serviced/utils"
)

// Function map for evaluating PortTemplate fields
var funcmap = template.FuncMap{
	"plus": func(a, b int) int {
		return a + b
	},
}

// An instantiation of a Service.
type ServiceState struct {
	ID          string
	ServiceID   string
	HostID      string
	DockerID    string
	PrivateIP   string
	Scheduled   time.Time
	Terminated  time.Time
	Started     time.Time
	PortMapping map[string][]domain.HostIPAndPort // protocol -> container port (internal) -> host port (external)
	// remove list?  PortMapping:map[6379/tcp:[{HostIP:0.0.0.0 HostPort:49195}]]
	//  i.e. redis:  PortMapping:map[6379/tcp: {HostIP:0.0.0.0 HostPort:49195} ]
	Endpoints  []service.ServiceEndpoint
	HostIP     string
	InstanceID int
}

//A new service instance (ServiceState)
func BuildFromService(service *service.Service, hostId string) (serviceState *ServiceState, err error) {
	serviceState = &ServiceState{}
	serviceState.ID, err = utils.NewUUID36()
	if err == nil {
		serviceState.ServiceID = service.ID
		serviceState.HostID = hostId
		serviceState.Scheduled = time.Now()
		serviceState.Endpoints = service.Endpoints
		for j, ep := range serviceState.Endpoints {
			if ep.PortTemplate != "" {
				t := template.Must(template.New("PortTemplate").Funcs(funcmap).Parse(ep.PortTemplate))
				b := bytes.Buffer{}
				err := t.Execute(&b, serviceState)
				if err == nil {
					i, err := strconv.Atoi(b.String())
					if err == nil {
						ep.PortNumber = uint16(i)
					}
				}
				serviceState.Endpoints[j] = ep
			}
		}
	}
	return serviceState, err
}

// Retrieve service container port info.
func (ss *ServiceState) GetHostEndpointInfo(applicationRegex *regexp.Regexp) (hostPort, containerPort uint16, protocol string, match bool) {
	for _, ep := range ss.Endpoints {

		if ep.Purpose == "export" {
			if applicationRegex.MatchString(ep.Application) {
				if ep.PortTemplate != "" {
					t := template.Must(template.New("PortTemplate").Funcs(funcmap).Parse(ep.PortTemplate))
					b := bytes.Buffer{}
					err := t.Execute(&b, ss)
					if err == nil {
						i, err := strconv.Atoi(b.String())
						if err != nil {
							glog.Errorf("%+v", err)
						} else {
							ep.PortNumber = uint16(i)
						}
					}
				}
				portS := fmt.Sprintf("%d/%s", ep.PortNumber, strings.ToLower(ep.Protocol))

				external := ss.PortMapping[portS]
				if len(external) == 0 {
					glog.Warningf("Found match for %s:%s, but no portmapping is available", applicationRegex, portS)
					break
				}

				extPort, err := strconv.ParseUint(external[0].HostPort, 10, 16)
				if err != nil {
					glog.Errorf("Portmap parsing failed for %s:%s %v", applicationRegex, portS, err)
					break
				}
				return uint16(extPort), ep.PortNumber, ep.Protocol, true
			}
		}
	}

	return 0, 0, "", false
}
<commit_msg>Clean up some template eval code<commit_after>// Copyright 2014, The Serviced Authors. All rights reserved.
// Use of this source code is governed by a
// license that can be found in the LICENSE file.

package servicestate

import (
	"bytes"

	"github.com/zenoss/glog"
	"github.com/zenoss/serviced/domain/service"

	"fmt"
	"regexp"
	"strconv"
	"strings"
	"text/template"
	"time"

	"github.com/zenoss/serviced/domain"
	"github.com/zenoss/serviced/utils"
)

// Function map for evaluating PortTemplate fields
var funcmap = template.FuncMap{
	"plus": func(a, b int) int {
		return a + b
	},
}

// An instantiation of a Service.
type ServiceState struct {
	ID          string
	ServiceID   string
	HostID      string
	DockerID    string
	PrivateIP   string
	Scheduled   time.Time
	Terminated  time.Time
	Started     time.Time
	PortMapping map[string][]domain.HostIPAndPort // protocol -> container port (internal) -> host port (external)
	// remove list?  PortMapping:map[6379/tcp:[{HostIP:0.0.0.0 HostPort:49195}]]
	//  i.e. redis:  PortMapping:map[6379/tcp: {HostIP:0.0.0.0 HostPort:49195} ]
	Endpoints  []service.ServiceEndpoint
	HostIP     string
	InstanceID int
}

func (ss *ServiceState) evalPortTemplate(portTemplate string) (int, error) {
	t := template.Must(template.New("PortTemplate").Funcs(funcmap).Parse(portTemplate))
	b := bytes.Buffer{}
	if err := t.Execute(&b, ss); err != nil {
		return 0, err
	}
	i, err := strconv.Atoi(b.String())
	if err != nil {
		return 0, err
	}
	return i, nil
}

//A new service instance (ServiceState)
func BuildFromService(service *service.Service, hostId string) (serviceState *ServiceState, err error) {
	serviceState = &ServiceState{}
	serviceState.ID, err = utils.NewUUID36()
	if err == nil {
		serviceState.ServiceID = service.ID
		serviceState.HostID = hostId
		serviceState.Scheduled = time.Now()
		serviceState.Endpoints = service.Endpoints
		for j, ep := range serviceState.Endpoints {
			if ep.PortTemplate != "" {
				port, err := serviceState.evalPortTemplate(ep.PortTemplate)
				if err != nil {
					return nil, err
				}
				ep.PortNumber = uint16(port)
				serviceState.Endpoints[j] = ep
			}
		}
	}
	return serviceState, err
}

// Retrieve service container port info.
func (ss *ServiceState) GetHostEndpointInfo(applicationRegex *regexp.Regexp) (hostPort, containerPort uint16, protocol string, match bool) {
	for _, ep := range ss.Endpoints {

		if ep.Purpose == "export" {
			if applicationRegex.MatchString(ep.Application) {
				if ep.PortTemplate != "" {
					port, err := ss.evalPortTemplate(ep.PortTemplate)
					if err != nil {
						glog.Errorf("%+v", err)
						break
					}
					ep.PortNumber = uint16(port)
				}
				portS := fmt.Sprintf("%d/%s", ep.PortNumber, strings.ToLower(ep.Protocol))

				external := ss.PortMapping[portS]
				if len(external) == 0 {
					glog.Warningf("Found match for %s:%s, but no portmapping is available", applicationRegex, portS)
					break
				}

				extPort, err := strconv.ParseUint(external[0].HostPort, 10, 16)
				if err != nil {
					glog.Errorf("Portmap parsing failed for %s:%s %v", applicationRegex, portS, err)
					break
				}
				return uint16(extPort), ep.PortNumber, ep.Protocol, true
			}
		}
	}

	return 0, 0, "", false
}
<|endoftext|>


<commit_before>package tokenize

import (
	"regexp"
	"strings"
)

// TreebankWordTokenizer splits a sentence into words.
//
// This implementation is a port of the Sed script written by Robert McIntyre,
// which is available at https://goo.gl/UGZrAc.
type TreebankWordTokenizer struct {
}

// NewTreebankWordTokenizer is a TreebankWordTokenizer constructor.
func NewTreebankWordTokenizer() *TreebankWordTokenizer {
	return new(TreebankWordTokenizer)
}

var startingQuotes = map[string]*regexp.Regexp{
	"$1 `` ": regexp.MustCompile(`'([ (\[{<])"`),
	"``":     regexp.MustCompile(`^(")`),
	" ``":    regexp.MustCompile(`( ")`),
}
var startingQuotes2 = map[string]*regexp.Regexp{
	" $1 ": regexp.MustCompile("(``)"),
}
var punctuation = map[string]*regexp.Regexp{
	" $1 $2":   regexp.MustCompile(`([:,])([^\d])`),
	" ... ":    regexp.MustCompile(`\.\.\.`),
	"$1 $2$3 ": regexp.MustCompile(`([^\.])(\.)([\]\)}>"\']*)\s*$`),
	"$1 ' ":    regexp.MustCompile(`([^'])' `),
}
var punctuation2 = []*regexp.Regexp{
	regexp.MustCompile(`([:,])$`),
	regexp.MustCompile(`([;@#$%&?!])`),
}
var brackets = map[string]*regexp.Regexp{
	" $1 ": regexp.MustCompile(`([\]\[\(\)\{\}\<\>])`),
	" -- ": regexp.MustCompile(`--`),
}
var endingQuotes = map[string]*regexp.Regexp{
	" '' ": regexp.MustCompile(`"`),
}
var endingQuotes2 = []*regexp.Regexp{
	regexp.MustCompile(`'(\S)(\'\')'`),
	regexp.MustCompile(`([^' ])('[sS]|'[mM]|'[dD]|') `),
	regexp.MustCompile(`([^' ])('ll|'LL|'re|'RE|'ve|'VE|n't|N'T) `),
}
var contractions = []*regexp.Regexp{
	regexp.MustCompile(`(?i)\b(can)(not)\b`),
	regexp.MustCompile(`(?i)\b(d)('ye)\b`),
	regexp.MustCompile(`(?i)\b(gim)(me)\b`),
	regexp.MustCompile(`(?i)\b(gon)(na)\b`),
	regexp.MustCompile(`(?i)\b(got)(ta)\b`),
	regexp.MustCompile(`(?i)\b(lem)(me)\b`),
	regexp.MustCompile(`(?i)\b(mor)('n)\b`),
	regexp.MustCompile(`(?i)\b(wan)(na) `),
	regexp.MustCompile(`(?i) ('t)(is)\b`),
	regexp.MustCompile(`(?i) ('t)(was)\b`),
}
var newlines = regexp.MustCompile(`(?:\n|\n\r|\r)`)
var spaces = regexp.MustCompile(`(?: {2,})`)

// Tokenize splits a sentence into a slice of words.
//
// This tokenizer performs the following steps: (1) split on contractions (e.g.,
// "don't" -> [do n't]), (2) split on non-terminating punctuation, (3) split on
// single quotes when followed by whitespace, and (4) split on periods that
// appear at the end of lines.
//
// NOTE: As mentioned above, this function expects a sentence (not raw text) as
// input.
func (t TreebankWordTokenizer) Tokenize(text string) []string {
	for substitution, r := range startingQuotes {
		text = r.ReplaceAllString(text, substitution)
	}

	for substitution, r := range startingQuotes2 {
		text = r.ReplaceAllString(text, substitution)
	}

	for substitution, r := range punctuation {
		text = r.ReplaceAllString(text, substitution)
	}

	for _, r := range punctuation2 {
		text = r.ReplaceAllString(text, " $1 ")
	}

	for substitution, r := range brackets {
		text = r.ReplaceAllString(text, substitution)
	}

	text = " " + text + " "

	for substitution, r := range endingQuotes {
		text = r.ReplaceAllString(text, substitution)
	}

	for _, r := range endingQuotes2 {
		text = r.ReplaceAllString(text, "$1 $2 ")
	}

	for _, r := range contractions {
		text = r.ReplaceAllString(text, " $1 $2 ")
	}

	text = newlines.ReplaceAllString(text, " ")
	text = strings.TrimSpace(spaces.ReplaceAllString(text, " "))
	return strings.Split(text, " ")
}
<commit_msg>Update link to TreebankWordTokenizer source<commit_after>package tokenize

import (
	"regexp"
	"strings"
)

// TreebankWordTokenizer splits a sentence into words.
//
// This implementation is a port of the Sed script written by Robert McIntyre,
// which is available at https://gist.github.com/jdkato/fc8b8c4266dba22d45ac85042ae53b1e.
type TreebankWordTokenizer struct {
}

// NewTreebankWordTokenizer is a TreebankWordTokenizer constructor.
func NewTreebankWordTokenizer() *TreebankWordTokenizer {
	return new(TreebankWordTokenizer)
}

var startingQuotes = map[string]*regexp.Regexp{
	"$1 `` ": regexp.MustCompile(`'([ (\[{<])"`),
	"``":     regexp.MustCompile(`^(")`),
	" ``":    regexp.MustCompile(`( ")`),
}
var startingQuotes2 = map[string]*regexp.Regexp{
	" $1 ": regexp.MustCompile("(``)"),
}
var punctuation = map[string]*regexp.Regexp{
	" $1 $2":   regexp.MustCompile(`([:,])([^\d])`),
	" ... ":    regexp.MustCompile(`\.\.\.`),
	"$1 $2$3 ": regexp.MustCompile(`([^\.])(\.)([\]\)}>"\']*)\s*$`),
	"$1 ' ":    regexp.MustCompile(`([^'])' `),
}
var punctuation2 = []*regexp.Regexp{
	regexp.MustCompile(`([:,])$`),
	regexp.MustCompile(`([;@#$%&?!])`),
}
var brackets = map[string]*regexp.Regexp{
	" $1 ": regexp.MustCompile(`([\]\[\(\)\{\}\<\>])`),
	" -- ": regexp.MustCompile(`--`),
}
var endingQuotes = map[string]*regexp.Regexp{
	" '' ": regexp.MustCompile(`"`),
}
var endingQuotes2 = []*regexp.Regexp{
	regexp.MustCompile(`'(\S)(\'\')'`),
	regexp.MustCompile(`([^' ])('[sS]|'[mM]|'[dD]|') `),
	regexp.MustCompile(`([^' ])('ll|'LL|'re|'RE|'ve|'VE|n't|N'T) `),
}
var contractions = []*regexp.Regexp{
	regexp.MustCompile(`(?i)\b(can)(not)\b`),
	regexp.MustCompile(`(?i)\b(d)('ye)\b`),
	regexp.MustCompile(`(?i)\b(gim)(me)\b`),
	regexp.MustCompile(`(?i)\b(gon)(na)\b`),
	regexp.MustCompile(`(?i)\b(got)(ta)\b`),
	regexp.MustCompile(`(?i)\b(lem)(me)\b`),
	regexp.MustCompile(`(?i)\b(mor)('n)\b`),
	regexp.MustCompile(`(?i)\b(wan)(na) `),
	regexp.MustCompile(`(?i) ('t)(is)\b`),
	regexp.MustCompile(`(?i) ('t)(was)\b`),
}
var newlines = regexp.MustCompile(`(?:\n|\n\r|\r)`)
var spaces = regexp.MustCompile(`(?: {2,})`)

// Tokenize splits a sentence into a slice of words.
//
// This tokenizer performs the following steps: (1) split on contractions (e.g.,
// "don't" -> [do n't]), (2) split on non-terminating punctuation, (3) split on
// single quotes when followed by whitespace, and (4) split on periods that
// appear at the end of lines.
//
// NOTE: As mentioned above, this function expects a sentence (not raw text) as
// input.
func (t TreebankWordTokenizer) Tokenize(text string) []string {
	for substitution, r := range startingQuotes {
		text = r.ReplaceAllString(text, substitution)
	}

	for substitution, r := range startingQuotes2 {
		text = r.ReplaceAllString(text, substitution)
	}

	for substitution, r := range punctuation {
		text = r.ReplaceAllString(text, substitution)
	}

	for _, r := range punctuation2 {
		text = r.ReplaceAllString(text, " $1 ")
	}

	for substitution, r := range brackets {
		text = r.ReplaceAllString(text, substitution)
	}

	text = " " + text + " "

	for substitution, r := range endingQuotes {
		text = r.ReplaceAllString(text, substitution)
	}

	for _, r := range endingQuotes2 {
		text = r.ReplaceAllString(text, "$1 $2 ")
	}

	for _, r := range contractions {
		text = r.ReplaceAllString(text, " $1 $2 ")
	}

	text = newlines.ReplaceAllString(text, " ")
	text = strings.TrimSpace(spaces.ReplaceAllString(text, " "))
	return strings.Split(text, " ")
}
<|endoftext|>


<commit_before>package services

import (
	"encoding/json"
	"errors"
	"github.com/franela/goreq"
	"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
	m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
	"path"
)

var IoHelper m.IoUtil = IoUtilImp{}

func ListAllPlugins(repoUrl string) (m.PluginRepo, error) {
	res, _ := goreq.Request{Uri: repoUrl}.Do()

	var resp m.PluginRepo
	err := res.Body.FromJsonTo(&resp)
	if err != nil {
		return m.PluginRepo{}, errors.New("Could not load plugin data")
	}

	return resp, nil
}

func ReadPlugin(pluginDir, pluginName string) (m.InstalledPlugin, error) {
	pluginDataPath := path.Join(pluginDir, pluginName, "plugin.json")
	pluginData, _ := IoHelper.ReadFile(pluginDataPath)

	res := m.InstalledPlugin{}
	json.Unmarshal(pluginData, &res)

	if res.Info.Version == "" {
		res.Info.Version = "0.0.0"
	}

	if res.Id == "" {
		return m.InstalledPlugin{}, errors.New("could not read find plugin " + pluginName)
	}

	return res, nil
}

func GetLocalPlugins(pluginDir string) []m.InstalledPlugin {
	result := make([]m.InstalledPlugin, 0)
	files, _ := IoHelper.ReadDir(pluginDir)
	for _, f := range files {
		res, err := ReadPlugin(pluginDir, f.Name())
		if err == nil {
			result = append(result, res)
		}
	}

	return result
}

func RemoveInstalledPlugin(pluginPath, id string) error {
	log.Infof("Removing plugin: %v\n", id)
	return IoHelper.RemoveAll(path.Join(pluginPath, id))
}

func GetPlugin(pluginId, repoUrl string) (m.Plugin, error) {
	resp, err := ListAllPlugins(repoUrl)
	if err != nil {
	}

	for _, i := range resp.Plugins {
		if i.Id == pluginId {
			return i, nil
		}
	}

	return m.Plugin{}, errors.New("could not find plugin named \"" + pluginId + "\"")
}
<commit_msg>feat(cli): allow redirect for plugin-repo.json<commit_after>package services

import (
	"encoding/json"
	"errors"
	"github.com/franela/goreq"
	"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
	m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
	"path"
)

var IoHelper m.IoUtil = IoUtilImp{}

func ListAllPlugins(repoUrl string) (m.PluginRepo, error) {
	res, _ := goreq.Request{Uri: repoUrl, MaxRedirects: 3}.Do()

	var resp m.PluginRepo
	err := res.Body.FromJsonTo(&resp)
	if err != nil {
		return m.PluginRepo{}, errors.New("Could not load plugin data")
	}

	return resp, nil
}

func ReadPlugin(pluginDir, pluginName string) (m.InstalledPlugin, error) {
	pluginDataPath := path.Join(pluginDir, pluginName, "plugin.json")
	pluginData, _ := IoHelper.ReadFile(pluginDataPath)

	res := m.InstalledPlugin{}
	json.Unmarshal(pluginData, &res)

	if res.Info.Version == "" {
		res.Info.Version = "0.0.0"
	}

	if res.Id == "" {
		return m.InstalledPlugin{}, errors.New("could not read find plugin " + pluginName)
	}

	return res, nil
}

func GetLocalPlugins(pluginDir string) []m.InstalledPlugin {
	result := make([]m.InstalledPlugin, 0)
	files, _ := IoHelper.ReadDir(pluginDir)
	for _, f := range files {
		res, err := ReadPlugin(pluginDir, f.Name())
		if err == nil {
			result = append(result, res)
		}
	}

	return result
}

func RemoveInstalledPlugin(pluginPath, id string) error {
	log.Infof("Removing plugin: %v\n", id)
	return IoHelper.RemoveAll(path.Join(pluginPath, id))
}

func GetPlugin(pluginId, repoUrl string) (m.Plugin, error) {
	resp, err := ListAllPlugins(repoUrl)
	if err != nil {
	}

	for _, i := range resp.Plugins {
		if i.Id == pluginId {
			return i, nil
		}
	}

	return m.Plugin{}, errors.New("could not find plugin named \"" + pluginId + "\"")
}
<|endoftext|>


<commit_before>package webircgateway

import (
	"net"
	"strings"
	"sync"

	"golang.org/x/net/websocket"
)

type TransportWebsocket struct {
	gateway *Gateway
}

func (t *TransportWebsocket) Init(g *Gateway) {
	t.gateway = g
	t.gateway.HttpRouter.Handle("/webirc/websocket/", websocket.Handler(t.websocketHandler))
}

func (t *TransportWebsocket) websocketHandler(ws *websocket.Conn) {
	client := t.gateway.NewClient()

	originHeader := strings.ToLower(ws.Request().Header.Get("Origin"))
	if !t.gateway.isClientOriginAllowed(originHeader) {
		client.Log(2, "Origin %s not allowed. Closing connection", originHeader)
		ws.Close()
		return
	}

	client.RemoteAddr = t.gateway.GetRemoteAddressFromRequest(ws.Request()).String()

	clientHostnames, err := net.LookupAddr(client.RemoteAddr)
	if err != nil {
		client.RemoteHostname = client.RemoteAddr
	} else {
		// FQDNs include a . at the end. Strip it out
		potentialHostname := strings.Trim(clientHostnames[0], ".")

		// Must check that the resolved hostname also resolves back to the users IP
		addr, err := net.LookupIP(potentialHostname)
		if err == nil && len(addr) == 1 && addr[0].String() == client.RemoteAddr {
			client.RemoteHostname = potentialHostname
		} else {
			client.RemoteHostname = client.RemoteAddr
		}
	}

	if t.gateway.isRequestSecure(ws.Request()) {
		client.Tags["secure"] = ""
	}

	_, remoteAddrPort, _ := net.SplitHostPort(ws.Request().RemoteAddr)
	client.Tags["remote-port"] = remoteAddrPort

	client.Log(2, "New client from %s %s", client.RemoteAddr, client.RemoteHostname)

	// We wait until the client send queue has been drained
	var sendDrained sync.WaitGroup
	sendDrained.Add(1)

	// Read from websocket
	go func() {
		for {
			r := make([]byte, 1024)
			len, err := ws.Read(r)
			if err == nil && len > 0 {
				message := string(r[:len])
				client.Log(1, "client->: %s", message)
				select {
				case client.Recv <- message:
				default:
					client.Log(3, "Recv queue full. Dropping data")
					// TODO: Should this really just drop the data or close the connection?
				}

			} else if err != nil {
				client.Log(1, "Websocket connection closed (%s)", err.Error())
				break

			} else if len == 0 {
				client.Log(1, "Got 0 bytes from websocket")
			}
		}

		close(client.Recv)
		client.StartShutdown("client_closed")
	}()

	// Process signals for the client
	for {
		signal, ok := <-client.Signals
		if !ok {
			sendDrained.Done()
			break
		}

		if signal[0] == "data" {
			line := strings.Trim(signal[1], "\r\n")
			client.Log(1, "->ws: %s", line)
			ws.Write([]byte(line))
		}
	}

	sendDrained.Wait()
	ws.Close()
}
<commit_msg>stop unconditionally rejecting originless websocket connection requests<commit_after>package webircgateway

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

	"golang.org/x/net/websocket"
)

type TransportWebsocket struct {
	gateway  *Gateway
	wsServer *websocket.Server
}

func (t *TransportWebsocket) Init(g *Gateway) {
	t.gateway = g
	t.wsServer = &websocket.Server{Handler: t.websocketHandler, Handshake: t.checkOrigin}
	t.gateway.HttpRouter.Handle("/webirc/websocket/", t.wsServer)
}

func (t *TransportWebsocket) checkOrigin(config *websocket.Config, req *http.Request) (err error) {
	config.Origin, err = websocket.Origin(config, req)

	var origin string
	if config.Origin != nil {
		origin = config.Origin.String()
	} else {
		origin = ""
	}

	if !t.gateway.isClientOriginAllowed(origin) {
		err = fmt.Errorf("Origin %#v not allowed", origin)
		t.gateway.Log(2, "%s. Closing connection", err)
		return err
	}

	return err
}

func (t *TransportWebsocket) websocketHandler(ws *websocket.Conn) {
	client := t.gateway.NewClient()

	client.RemoteAddr = t.gateway.GetRemoteAddressFromRequest(ws.Request()).String()

	clientHostnames, err := net.LookupAddr(client.RemoteAddr)
	if err != nil {
		client.RemoteHostname = client.RemoteAddr
	} else {
		// FQDNs include a . at the end. Strip it out
		potentialHostname := strings.Trim(clientHostnames[0], ".")

		// Must check that the resolved hostname also resolves back to the users IP
		addr, err := net.LookupIP(potentialHostname)
		if err == nil && len(addr) == 1 && addr[0].String() == client.RemoteAddr {
			client.RemoteHostname = potentialHostname
		} else {
			client.RemoteHostname = client.RemoteAddr
		}
	}

	if t.gateway.isRequestSecure(ws.Request()) {
		client.Tags["secure"] = ""
	}

	_, remoteAddrPort, _ := net.SplitHostPort(ws.Request().RemoteAddr)
	client.Tags["remote-port"] = remoteAddrPort

	client.Log(2, "New client from %s %s", client.RemoteAddr, client.RemoteHostname)

	// We wait until the client send queue has been drained
	var sendDrained sync.WaitGroup
	sendDrained.Add(1)

	// Read from websocket
	go func() {
		for {
			r := make([]byte, 1024)
			len, err := ws.Read(r)
			if err == nil && len > 0 {
				message := string(r[:len])
				client.Log(1, "client->: %s", message)
				select {
				case client.Recv <- message:
				default:
					client.Log(3, "Recv queue full. Dropping data")
					// TODO: Should this really just drop the data or close the connection?
				}

			} else if err != nil {
				client.Log(1, "Websocket connection closed (%s)", err.Error())
				break

			} else if len == 0 {
				client.Log(1, "Got 0 bytes from websocket")
			}
		}

		close(client.Recv)
		client.StartShutdown("client_closed")
	}()

	// Process signals for the client
	for {
		signal, ok := <-client.Signals
		if !ok {
			sendDrained.Done()
			break
		}

		if signal[0] == "data" {
			line := strings.Trim(signal[1], "\r\n")
			client.Log(1, "->ws: %s", line)
			ws.Write([]byte(line))
		}
	}

	sendDrained.Wait()
	ws.Close()
}
<|endoftext|>


<commit_before>//+build ignore

package main

import (
	"bufio"
	"go/format"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strconv"
	"strings"
)

func main() {
	mi := make(map[string]string, 0)
	md := make(map[int]string, 0)

	file, err := os.Open(middlewareFile)
	fatalIfErr(err)

	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if !strings.HasPrefix(line, `//`) && !strings.HasPrefix(line, "#") {
			items := strings.Split(line, ":")
			if len(items) == 3 {
				if priority, err := strconv.Atoi(items[0]); err == nil {
					md[priority] = items[1]
				}

				if items[2] != "" {
					if strings.Contains(items[2], "/") {
						mi[items[1]] = items[2]
					} else {
						mi[items[1]] = middlewarePath + items[2]
					}
				}

			}
		}
	}

	genImports("core/zmiddleware.go", "core", mi)
	genDirectives("core/dnsserver/zdirectives.go", "dnsserver", md)
}

func genImports(file, pack string, mi map[string]string) {
	outs := header + "package " + pack + "\n\n" + "import ("

	if len(mi) > 0 {
		outs += "\n"
	}

	for _, v := range mi {
		outs += `_ "` + v + `\` + "\n"
	}
	outs += ")\n"

	res, err := format.Source([]byte(outs))
	fatalIfErr(err)

	err = ioutil.WriteFile(file, res, 0644)
	fatalIfErr(err)
}

func genDirectives(file, pack string, md map[int]string) {

	outs := header + "package " + pack + "\n\n"
	outs += `
// Directives are registered in the order they should be
// executed.
//
// Ordering is VERY important. Every middleware will
// feel the effects of all other middleware below
// (after) them during a request, but they must not
// care what middleware above them are doing.

var directives = []string{
`

	var orders []int
	for k := range md {
		orders = append(orders, k)
	}
	sort.Ints(orders)

	for _, k := range orders {
		outs += `"` + md[k] + `",` + "\n"
	}

	outs += "}\n"

	res, err := format.Source([]byte(outs))
	fatalIfErr(err)

	err = ioutil.WriteFile(file, res, 0644)
	fatalIfErr(err)
}

func fatalIfErr(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

const (
	middlewarePath = "github.com/miekg/coredns/middleware/"
	middlewareFile = "middleware.cfg"
	header         = "// generated by directives_generate.go; DO NOT EDIT\n"
)
<commit_msg>Fix make gen (#526)<commit_after>//+build ignore

package main

import (
	"bufio"
	"go/format"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strconv"
	"strings"
)

func main() {
	mi := make(map[string]string, 0)
	md := make(map[int]string, 0)

	file, err := os.Open(middlewareFile)
	fatalIfErr(err)

	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if !strings.HasPrefix(line, `//`) && !strings.HasPrefix(line, "#") {
			items := strings.Split(line, ":")
			if len(items) == 3 {
				if priority, err := strconv.Atoi(items[0]); err == nil {
					md[priority] = items[1]
				}

				if items[2] != "" {
					if strings.Contains(items[2], "/") {
						mi[items[1]] = items[2]
					} else {
						mi[items[1]] = middlewarePath + items[2]
					}
				}

			}
		}
	}

	genImports("core/zmiddleware.go", "core", mi)
	genDirectives("core/dnsserver/zdirectives.go", "dnsserver", md)
}

func genImports(file, pack string, mi map[string]string) {
	outs := header + "package " + pack + "\n\n" + "import ("

	if len(mi) > 0 {
		outs += "\n"
	}

	for _, v := range mi {
		outs += `_ "` + v + `"` + "\n"
	}
	outs += ")\n"

	res, err := format.Source([]byte(outs))
	fatalIfErr(err)

	err = ioutil.WriteFile(file, res, 0644)
	fatalIfErr(err)
}

func genDirectives(file, pack string, md map[int]string) {

	outs := header + "package " + pack + "\n\n"
	outs += `
// Directives are registered in the order they should be
// executed.
//
// Ordering is VERY important. Every middleware will
// feel the effects of all other middleware below
// (after) them during a request, but they must not
// care what middleware above them are doing.

var directives = []string{
`

	var orders []int
	for k := range md {
		orders = append(orders, k)
	}
	sort.Ints(orders)

	for _, k := range orders {
		outs += `"` + md[k] + `",` + "\n"
	}

	outs += "}\n"

	res, err := format.Source([]byte(outs))
	fatalIfErr(err)

	err = ioutil.WriteFile(file, res, 0644)
	fatalIfErr(err)
}

func fatalIfErr(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

const (
	middlewarePath = "github.com/miekg/coredns/middleware/"
	middlewareFile = "middleware.cfg"
	header         = "// generated by directives_generate.go; DO NOT EDIT\n"
)
<|endoftext|>