<commit_before>// +build unittest

package storkctl

import (
	"strings"
	"testing"

	storkv1 "github.com/libopenstorage/stork/pkg/apis/stork/v1alpha1"
	"github.com/portworx/sched-ops/k8s"
	"github.com/stretchr/testify/require"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestGetMigrationsNoMigration(t *testing.T) {
	cmdArgs := []string{"get", "migrations"}

	var migrationList storkv1.MigrationList
	expected := "No resources found.\n"
	testCommon(t, cmdArgs, &migrationList, expected, false)
}

func createMigrationAndVerify(
	t *testing.T,
	name string,
	namespace string,
	clusterpair string,
	namespaces []string,
	preExecRule string,
	postExecRule string,
) {
	cmdArgs := []string{"create", "migrations", "-n", namespace, "-c", clusterpair, "--namespaces", strings.Join(namespaces, ","), name}
	if preExecRule != "" {
		cmdArgs = append(cmdArgs, "--preExecRule", preExecRule)
	}
	if postExecRule != "" {
		cmdArgs = append(cmdArgs, "--postExecRule", postExecRule)
	}

	expected := "Migration " + name + " created successfully\n"
	testCommon(t, cmdArgs, nil, expected, false)

	// Make sure it was created correctly
	migration, err := k8s.Instance().GetMigration(name, namespace)
	require.NoError(t, err, "Error getting migration")
	require.Equal(t, name, migration.Name, "Migration name mismatch")
	require.Equal(t, namespace, migration.Namespace, "Migration namespace mismatch")
	require.Equal(t, clusterpair, migration.Spec.ClusterPair, "Migration clusterpair mismatch")
	require.Equal(t, namespaces, migration.Spec.Namespaces, "Migration namespace mismatch")
	require.Equal(t, preExecRule, migration.Spec.PreExecRule, "Migration preExecRule mismatch")
	require.Equal(t, postExecRule, migration.Spec.PostExecRule, "Migration postExecRule mismatch")
}

func TestGetMigrationsOneMigration(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "getmigrationtest", "test", "clusterpair1", []string{"namespace1"}, "preExec", "postExec")

	expected := "NAME               CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationtest   clusterpair1                       0/0       0/0         \n"

	cmdArgs := []string{"get", "migrations", "-n", "test"}
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestGetMigrationsMultiple(t *testing.T) {
	defer resetTest()
	_, err := k8s.Instance().CreateNamespace("default", nil)
	require.NoError(t, err, "Error creating default namespace")

	createMigrationAndVerify(t, "getmigrationtest1", "default", "clusterpair1", []string{"namespace1"}, "", "")
	createMigrationAndVerify(t, "getmigrationtest2", "default", "clusterpair2", []string{"namespace1"}, "", "")

	expected := "NAME                CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationtest1   clusterpair1                       0/0       0/0         \n" +
		"getmigrationtest2   clusterpair2                       0/0       0/0         \n"

	cmdArgs := []string{"get", "migrations", "getmigrationtest1", "getmigrationtest2"}
	testCommon(t, cmdArgs, nil, expected, false)

	// Should get all migrations if no name given
	cmdArgs = []string{"get", "migrations"}
	testCommon(t, cmdArgs, nil, expected, false)

	expected = "NAME                CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationtest1   clusterpair1                       0/0       0/0         \n"
	// Should get only one migration if name given
	cmdArgs = []string{"get", "migrations", "getmigrationtest1"}
	testCommon(t, cmdArgs, nil, expected, false)

	_, err = k8s.Instance().CreateNamespace("ns1", nil)
	require.NoError(t, err, "Error creating ns1 namespace")
	createMigrationAndVerify(t, "getmigrationtest21", "ns1", "clusterpair2", []string{"namespace1"}, "", "")
	cmdArgs = []string{"get", "migrations", "--all-namespaces"}
	expected = "NAMESPACE   NAME                 CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"default     getmigrationtest1    clusterpair1                       0/0       0/0         \n" +
		"default     getmigrationtest2    clusterpair2                       0/0       0/0         \n" +
		"ns1         getmigrationtest21   clusterpair2                       0/0       0/0         \n"
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestGetMigrationsWithClusterPair(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "getmigrationtest1", "default", "clusterpair1", []string{"namespace1"}, "", "")
	createMigrationAndVerify(t, "getmigrationtest2", "default", "clusterpair2", []string{"namespace1"}, "", "")

	expected := "NAME                CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationtest1   clusterpair1                       0/0       0/0         \n"

	cmdArgs := []string{"get", "migrations", "-c", "clusterpair1"}
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestGetMigrationsWithStatusAndProgress(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "getmigrationstatustest", "default", "clusterpair1", []string{"namespace1"}, "", "")
	migration, err := k8s.Instance().GetMigration("getmigrationstatustest", "default")
	require.NoError(t, err, "Error getting migration")

	// Update the status of the migration
	migration.CreationTimestamp = metav1.Now()
	migration.Status.Stage = storkv1.MigrationStageFinal
	migration.Status.Status = storkv1.MigrationStatusSuccessful
	migration.Status.Volumes = []*storkv1.VolumeInfo{}
	migration, err = k8s.Instance().UpdateMigration(migration)

	expected := "NAME                     CLUSTERPAIR    STAGE     STATUS       VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationstatustest   clusterpair1   Final     Successful   0/0       0/0         " + toTimeString(migration.CreationTimestamp.Time) + "\n"
	cmdArgs := []string{"get", "migrations", "getmigrationstatustest"}
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestCreateMigrationsNoNamespace(t *testing.T) {
	cmdArgs := []string{"create", "migrations", "-c", "clusterPair1", "migration1"}

	expected := "error: Need to provide atleast one namespace to migrate"
	testCommon(t, cmdArgs, nil, expected, true)
}

func TestCreateMigrationsNoClusterPair(t *testing.T) {
	cmdArgs := []string{"create", "migrations", "migration1"}

	expected := "error: ClusterPair name needs to be provided for migration"
	testCommon(t, cmdArgs, nil, expected, true)
}

func TestCreateMigrationsNoName(t *testing.T) {
	cmdArgs := []string{"create", "migrations"}

	expected := "error: Exactly one name needs to be provided for migration name"
	testCommon(t, cmdArgs, nil, expected, true)
}

func TestCreateMigrations(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "createmigration", "default", "clusterpair1", []string{"namespace1"}, "", "")
}

func TestCreateDuplicateMigrations(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "createmigration", "default", "clusterpair1", []string{"namespace1"}, "", "")
	cmdArgs := []string{"create", "migrations", "-c", "clusterpair1", "--namespaces", "namespace1", "createmigration"}

	expected := "Error from server (AlreadyExists): migrations.stork.libopenstorage.org \"createmigration\" already exists"
	testCommon(t, cmdArgs, nil, expected, true)
}

func TestDeleteMigrationsNoMigrationName(t *testing.T) {
	cmdArgs := []string{"delete", "migrations"}

	var migrationList storkv1.MigrationList
	expected := "error: At least one argument needs to be provided for migration name"
	testCommon(t, cmdArgs, &migrationList, expected, true)
}

func TestDeleteMigrationsNoMigration(t *testing.T) {
	cmdArgs := []string{"delete", "migrations", "-c", "migration1"}

	expected := "No resources found.\n"
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestDeleteMigrations(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "deletemigration", "default", "clusterpair1", []string{"namespace1"}, "", "")

	cmdArgs := []string{"delete", "migrations", "deletemigration"}
	expected := "Migration deletemigration deleted successfully\n"
	testCommon(t, cmdArgs, nil, expected, false)

	cmdArgs = []string{"delete", "migrations", "deletemigration"}
	expected = "Error from server (NotFound): migrations.stork.libopenstorage.org \"deletemigration\" not found"
	testCommon(t, cmdArgs, nil, expected, true)

	createMigrationAndVerify(t, "deletemigration1", "default", "clusterpair1", []string{"namespace1"}, "", "")
	createMigrationAndVerify(t, "deletemigration2", "default", "clusterpair2", []string{"namespace1"}, "", "")

	cmdArgs = []string{"delete", "migrations", "deletemigration1", "deletemigration2"}
	expected = "Migration deletemigration1 deleted successfully\n"
	expected += "Migration deletemigration2 deleted successfully\n"
	testCommon(t, cmdArgs, nil, expected, false)

	createMigrationAndVerify(t, "deletemigration1", "default", "clusterpair1", []string{"namespace1"}, "", "")
	createMigrationAndVerify(t, "deletemigration2", "default", "clusterpair1", []string{"namespace1"}, "", "")

	cmdArgs = []string{"delete", "migrations", "-c", "clusterpair1"}
	expected = "Migration deletemigration1 deleted successfully\n"
	expected += "Migration deletemigration2 deleted successfully\n"
	testCommon(t, cmdArgs, nil, expected, false)
}
<commit_msg>Added UTs for activate/deactivate subcommands<commit_after>// +build unittest

package storkctl

import (
	"strings"
	"testing"

	storkv1 "github.com/libopenstorage/stork/pkg/apis/stork/v1alpha1"
	migration "github.com/libopenstorage/stork/pkg/migration/controllers"
	"github.com/portworx/sched-ops/k8s"
	"github.com/stretchr/testify/require"
	appv1 "k8s.io/api/apps/v1beta2"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestGetMigrationsNoMigration(t *testing.T) {
	cmdArgs := []string{"get", "migrations"}

	var migrationList storkv1.MigrationList
	expected := "No resources found.\n"
	testCommon(t, cmdArgs, &migrationList, expected, false)
}

func createMigrationAndVerify(
	t *testing.T,
	name string,
	namespace string,
	clusterpair string,
	namespaces []string,
	preExecRule string,
	postExecRule string,
) {
	cmdArgs := []string{"create", "migrations", "-n", namespace, "-c", clusterpair, "--namespaces", strings.Join(namespaces, ","), name}
	if preExecRule != "" {
		cmdArgs = append(cmdArgs, "--preExecRule", preExecRule)
	}
	if postExecRule != "" {
		cmdArgs = append(cmdArgs, "--postExecRule", postExecRule)
	}

	expected := "Migration " + name + " created successfully\n"
	testCommon(t, cmdArgs, nil, expected, false)

	// Make sure it was created correctly
	migration, err := k8s.Instance().GetMigration(name, namespace)
	require.NoError(t, err, "Error getting migration")
	require.Equal(t, name, migration.Name, "Migration name mismatch")
	require.Equal(t, namespace, migration.Namespace, "Migration namespace mismatch")
	require.Equal(t, clusterpair, migration.Spec.ClusterPair, "Migration clusterpair mismatch")
	require.Equal(t, namespaces, migration.Spec.Namespaces, "Migration namespace mismatch")
	require.Equal(t, preExecRule, migration.Spec.PreExecRule, "Migration preExecRule mismatch")
	require.Equal(t, postExecRule, migration.Spec.PostExecRule, "Migration postExecRule mismatch")
}

func TestGetMigrationsOneMigration(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "getmigrationtest", "test", "clusterpair1", []string{"namespace1"}, "preExec", "postExec")

	expected := "NAME               CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationtest   clusterpair1                       0/0       0/0         \n"

	cmdArgs := []string{"get", "migrations", "-n", "test"}
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestGetMigrationsMultiple(t *testing.T) {
	defer resetTest()
	_, err := k8s.Instance().CreateNamespace("default", nil)
	require.NoError(t, err, "Error creating default namespace")

	createMigrationAndVerify(t, "getmigrationtest1", "default", "clusterpair1", []string{"namespace1"}, "", "")
	createMigrationAndVerify(t, "getmigrationtest2", "default", "clusterpair2", []string{"namespace1"}, "", "")

	expected := "NAME                CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationtest1   clusterpair1                       0/0       0/0         \n" +
		"getmigrationtest2   clusterpair2                       0/0       0/0         \n"

	cmdArgs := []string{"get", "migrations", "getmigrationtest1", "getmigrationtest2"}
	testCommon(t, cmdArgs, nil, expected, false)

	// Should get all migrations if no name given
	cmdArgs = []string{"get", "migrations"}
	testCommon(t, cmdArgs, nil, expected, false)

	expected = "NAME                CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationtest1   clusterpair1                       0/0       0/0         \n"
	// Should get only one migration if name given
	cmdArgs = []string{"get", "migrations", "getmigrationtest1"}
	testCommon(t, cmdArgs, nil, expected, false)

	_, err = k8s.Instance().CreateNamespace("ns1", nil)
	require.NoError(t, err, "Error creating ns1 namespace")
	createMigrationAndVerify(t, "getmigrationtest21", "ns1", "clusterpair2", []string{"namespace1"}, "", "")
	cmdArgs = []string{"get", "migrations", "--all-namespaces"}
	expected = "NAMESPACE   NAME                 CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"default     getmigrationtest1    clusterpair1                       0/0       0/0         \n" +
		"default     getmigrationtest2    clusterpair2                       0/0       0/0         \n" +
		"ns1         getmigrationtest21   clusterpair2                       0/0       0/0         \n"
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestGetMigrationsWithClusterPair(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "getmigrationtest1", "default", "clusterpair1", []string{"namespace1"}, "", "")
	createMigrationAndVerify(t, "getmigrationtest2", "default", "clusterpair2", []string{"namespace1"}, "", "")

	expected := "NAME                CLUSTERPAIR    STAGE     STATUS    VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationtest1   clusterpair1                       0/0       0/0         \n"

	cmdArgs := []string{"get", "migrations", "-c", "clusterpair1"}
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestGetMigrationsWithStatusAndProgress(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "getmigrationstatustest", "default", "clusterpair1", []string{"namespace1"}, "", "")
	migration, err := k8s.Instance().GetMigration("getmigrationstatustest", "default")
	require.NoError(t, err, "Error getting migration")

	// Update the status of the migration
	migration.CreationTimestamp = metav1.Now()
	migration.Status.Stage = storkv1.MigrationStageFinal
	migration.Status.Status = storkv1.MigrationStatusSuccessful
	migration.Status.Volumes = []*storkv1.VolumeInfo{}
	migration, err = k8s.Instance().UpdateMigration(migration)

	expected := "NAME                     CLUSTERPAIR    STAGE     STATUS       VOLUMES   RESOURCES   CREATED\n" +
		"getmigrationstatustest   clusterpair1   Final     Successful   0/0       0/0         " + toTimeString(migration.CreationTimestamp.Time) + "\n"
	cmdArgs := []string{"get", "migrations", "getmigrationstatustest"}
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestCreateMigrationsNoNamespace(t *testing.T) {
	cmdArgs := []string{"create", "migrations", "-c", "clusterPair1", "migration1"}

	expected := "error: Need to provide atleast one namespace to migrate"
	testCommon(t, cmdArgs, nil, expected, true)
}

func TestCreateMigrationsNoClusterPair(t *testing.T) {
	cmdArgs := []string{"create", "migrations", "migration1"}

	expected := "error: ClusterPair name needs to be provided for migration"
	testCommon(t, cmdArgs, nil, expected, true)
}

func TestCreateMigrationsNoName(t *testing.T) {
	cmdArgs := []string{"create", "migrations"}

	expected := "error: Exactly one name needs to be provided for migration name"
	testCommon(t, cmdArgs, nil, expected, true)
}

func TestCreateMigrations(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "createmigration", "default", "clusterpair1", []string{"namespace1"}, "", "")
}

func TestCreateDuplicateMigrations(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "createmigration", "default", "clusterpair1", []string{"namespace1"}, "", "")
	cmdArgs := []string{"create", "migrations", "-c", "clusterpair1", "--namespaces", "namespace1", "createmigration"}

	expected := "Error from server (AlreadyExists): migrations.stork.libopenstorage.org \"createmigration\" already exists"
	testCommon(t, cmdArgs, nil, expected, true)
}

func TestDeleteMigrationsNoMigrationName(t *testing.T) {
	cmdArgs := []string{"delete", "migrations"}

	var migrationList storkv1.MigrationList
	expected := "error: At least one argument needs to be provided for migration name"
	testCommon(t, cmdArgs, &migrationList, expected, true)
}

func TestDeleteMigrationsNoMigration(t *testing.T) {
	cmdArgs := []string{"delete", "migrations", "-c", "migration1"}

	expected := "No resources found.\n"
	testCommon(t, cmdArgs, nil, expected, false)
}

func TestDeleteMigrations(t *testing.T) {
	defer resetTest()
	createMigrationAndVerify(t, "deletemigration", "default", "clusterpair1", []string{"namespace1"}, "", "")

	cmdArgs := []string{"delete", "migrations", "deletemigration"}
	expected := "Migration deletemigration deleted successfully\n"
	testCommon(t, cmdArgs, nil, expected, false)

	cmdArgs = []string{"delete", "migrations", "deletemigration"}
	expected = "Error from server (NotFound): migrations.stork.libopenstorage.org \"deletemigration\" not found"
	testCommon(t, cmdArgs, nil, expected, true)

	createMigrationAndVerify(t, "deletemigration1", "default", "clusterpair1", []string{"namespace1"}, "", "")
	createMigrationAndVerify(t, "deletemigration2", "default", "clusterpair2", []string{"namespace1"}, "", "")

	cmdArgs = []string{"delete", "migrations", "deletemigration1", "deletemigration2"}
	expected = "Migration deletemigration1 deleted successfully\n"
	expected += "Migration deletemigration2 deleted successfully\n"
	testCommon(t, cmdArgs, nil, expected, false)

	createMigrationAndVerify(t, "deletemigration1", "default", "clusterpair1", []string{"namespace1"}, "", "")
	createMigrationAndVerify(t, "deletemigration2", "default", "clusterpair1", []string{"namespace1"}, "", "")

	cmdArgs = []string{"delete", "migrations", "-c", "clusterpair1"}
	expected = "Migration deletemigration1 deleted successfully\n"
	expected += "Migration deletemigration2 deleted successfully\n"
	testCommon(t, cmdArgs, nil, expected, false)
}

func createMigratedDeployment(t *testing.T) {
	replicas := int32(0)
	_, err := k8s.Instance().CreateNamespace("dep", nil)
	require.NoError(t, err, "Error creating dep namespace")

	deployment := &appv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "migratedDeployment",
			Namespace: "dep",
			Annotations: map[string]string{
				migration.StorkMigrationReplicasAnnotation: "1",
			},
		},
		Spec: appv1.DeploymentSpec{
			Replicas: &replicas,
		},
	}
	_, err = k8s.Instance().CreateDeployment(deployment)
	require.NoError(t, err, "Error creating deployment")

}
func createMigratedStatefulSet(t *testing.T) {
	replicas := int32(0)
	_, err := k8s.Instance().CreateNamespace("sts", nil)
	require.NoError(t, err, "Error creating sts namespace")

	statefulSet := &appv1.StatefulSet{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "migratedStatefulSet",
			Namespace: "sts",
			Annotations: map[string]string{
				migration.StorkMigrationReplicasAnnotation: "3",
			},
		},
		Spec: appv1.StatefulSetSpec{
			Replicas: &replicas,
		},
	}
	_, err = k8s.Instance().CreateStatefulSet(statefulSet)
	require.NoError(t, err, "Error creating statefulset")

}
func TestActivateDeactivateMigrations(t *testing.T) {

	createMigratedDeployment(t)
	createMigratedStatefulSet(t)
	cmdArgs := []string{"activate", "migrations", "-n", "dep"}
	expected := "Updated replicas for deployment dep/migratedDeployment to 1\n"
	testCommon(t, cmdArgs, nil, expected, false)

	cmdArgs = []string{"activate", "migrations", "-n", "sts"}
	expected = "Updated replicas for statefulset sts/migratedStatefulSet to 3\n"
	testCommon(t, cmdArgs, nil, expected, false)

	cmdArgs = []string{"deactivate", "migrations", "-n", "dep"}
	expected = "Updated replicas for deployment dep/migratedDeployment to 0\n"
	testCommon(t, cmdArgs, nil, expected, false)

	cmdArgs = []string{"deactivate", "migrations", "-n", "sts"}
	expected = "Updated replicas for statefulset sts/migratedStatefulSet to 0\n"
	testCommon(t, cmdArgs, nil, expected, false)

	cmdArgs = []string{"activate", "migrations", "-a"}
	expected = "Updated replicas for deployment dep/migratedDeployment to 1\n"
	expected += "Updated replicas for statefulset sts/migratedStatefulSet to 3\n"
	testCommon(t, cmdArgs, nil, expected, false)

	cmdArgs = []string{"deactivate", "migrations", "-a"}
	expected = "Updated replicas for deployment dep/migratedDeployment to 0\n"
	expected += "Updated replicas for statefulset sts/migratedStatefulSet to 0\n"
	testCommon(t, cmdArgs, nil, expected, false)
}
<|endoftext|>


<commit_before>package datadog

import (
	"io"
	"strings"

	"github.com/containous/traefik/pkg/log"
	"github.com/opentracing/opentracing-go"
	ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer"
	datadog "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

// Name sets the name of this tracer
const Name = "datadog"

// Config provides configuration settings for a datadog tracer
type Config struct {
	LocalAgentHostPort string `description:"Set datadog-agent's host:port that the reporter will used. Defaults to localhost:8126" export:"false"`
	GlobalTag          string `description:"Key:Value tag to be set on all the spans." export:"true"`
	Debug              bool   `description:"Enable DataDog debug." export:"true"`
	PrioritySampling   bool   `description:"Enable priority sampling. When using distributed tracing, this option must be enabled in order to get all the parts of a distributed trace sampled."`
}

// Setup sets up the tracer
func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) {
	tag := strings.SplitN(c.GlobalTag, ":", 2)

	value := ""
	if len(tag) == 2 {
		value = tag[1]
	}

	opts := []datadog.StartOption{
		datadog.WithAgentAddr(c.LocalAgentHostPort),
		datadog.WithServiceName(serviceName),
		datadog.WithGlobalTag(tag[0], value),
		datadog.WithDebugMode(c.Debug),
	}
	if c.PrioritySampling {
		opts = append(opts, datadog.WithPrioritySampling())
	}
	tracer := ddtracer.New(opts...)

	// Without this, child spans are getting the NOOP tracer
	opentracing.SetGlobalTracer(tracer)

	log.WithoutContext().Debug("DataDog tracer configured")

	return tracer, nil, nil
}
<commit_msg>Added support for configuring trace headers for DataDog tracing<commit_after>package datadog

import (
	"io"
	"strings"

	"github.com/containous/traefik/pkg/log"
	"github.com/opentracing/opentracing-go"
	ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer"
	datadog "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

// Name sets the name of this tracer
const Name = "datadog"

// Config provides configuration settings for a datadog tracer
type Config struct {
	LocalAgentHostPort         string `description:"Set datadog-agent's host:port that the reporter will used. Defaults to localhost:8126" export:"false"`
	GlobalTag                  string `description:"Key:Value tag to be set on all the spans." export:"true"`
	Debug                      bool   `description:"Enable DataDog debug." export:"true"`
	PrioritySampling           bool   `description:"Enable priority sampling. When using distributed tracing, this option must be enabled in order to get all the parts of a distributed trace sampled."`
	TraceIDHeaderName          string `description:"Specifies the header name that will be used to store the trace ID." export:"true"`
	ParentIDHeaderName         string `description:"Specifies the header name that will be used to store the parent ID." export:"true"`
	SamplingPriorityHeaderName string `description:"Specifies the header name that will be used to store the sampling priority." export:"true"`
	BagagePrefixHeaderName     string `description:"specifies the header name prefix that will be used to store baggage items in a map." export:"true"`
}

// Setup sets up the tracer
func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) {
	tag := strings.SplitN(c.GlobalTag, ":", 2)

	value := ""
	if len(tag) == 2 {
		value = tag[1]
	}

	opts := []datadog.StartOption{
		datadog.WithAgentAddr(c.LocalAgentHostPort),
		datadog.WithServiceName(serviceName),
		datadog.WithGlobalTag(tag[0], value),
		datadog.WithDebugMode(c.Debug),
		datadog.WithPropagator(datadog.NewPropagator(&datadog.PropagatorConfig{
			TraceHeader:    c.TraceIDHeaderName,
			ParentHeader:   c.ParentIDHeaderName,
			PriorityHeader: c.SamplingPriorityHeaderName,
			BaggagePrefix:  c.BagagePrefixHeaderName,
		})),
	}
	if c.PrioritySampling {
		opts = append(opts, datadog.WithPrioritySampling())
	}
	tracer := ddtracer.New(opts...)

	// Without this, child spans are getting the NOOP tracer
	opentracing.SetGlobalTracer(tracer)

	log.WithoutContext().Debug("DataDog tracer configured")

	return tracer, nil, nil
}
<|endoftext|>


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

// package todo implements a parser for my minimal todo list format.
package todo

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"strings"
	"time"
)

// A TaskList is a list of tasks
type TaskList []Task

func (l TaskList) Len() int      { return len(l) }
func (l TaskList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l TaskList) Less(i, j int) bool {
	// sort by:
	// not done before done
	// then by due date
	// then by start date
	// then alphabetically
	if l[i].Done && !l[j].Done {
		return false
	}
	if !l[i].Done && l[j].Done {
		return true
	}

	dbefore, eq := before(l[i].Due, l[j].Due)
	if !eq {
		return dbefore
	}

	sbefore, eq := before(l[i].Start, l[j].Start)
	if !eq {
		return sbefore
	}

	return l[i].Title < l[j].Title
}

// returns before, equal
func before(a, b time.Time) (bool, bool) {
	if a.Equal(b) {
		return false, true
	}
	if a.IsZero() && !b.IsZero() {
		return false, false
	}
	if !a.IsZero() && b.IsZero() {
		return true, false
	}
	if a.Before(b) {
		return true, false
	} else {
		return false, false
	}
}

func FromReader(r io.Reader) (TaskList, error) {
	s := bufio.NewScanner(r)
	var ret TaskList
	lno := 1
	for s.Scan() {
		line := s.Text()
		todo, err := Parse(line)
		if err != nil {
			return nil, fmt.Errorf("%v on line %v", err, lno)
		}
		ret = append(ret, todo)
		lno++
	}
	return ret, nil
}

// A Task is represents a item in a todo list
type Task struct {
	Title    string
	Start    time.Time
	Due      time.Time
	Tags     []string
	Contexts []string
	index    int // line in file
	Raw      string
	Done     bool

	original string
}

// DateFormat is YY-MM-DD, with no times, time zone, etc.
const DateFormat = "2006-1-2"

// Parse takes a string and parses it as todo.txt formatted todo item
func Parse(r string) (Task, error) {
	if len(r) == 0 {
		return Task{}, errors.New("todo: parse empty string")
	}

	t := Task{Raw: r}
	tokens := strings.Fields(r)
	if len(tokens) == 0 {
		return Task{}, errors.New("todo: parse only whitespace")
	}

	if len(tokens) > 0 && tokens[0] == "x" {
		t.Done = true
		tokens = tokens[1:]
	}

	if len(tokens) == 0 {
		return Task{}, errors.New("todo: line contains only completion marker")
	}

	for _, token := range tokens {
		date, err := time.ParseInLocation(DateFormat, token, time.Local)
		switch {
		case err == nil:
			t.Due = date
		case strings.HasPrefix(token, "@"):
			if len(token[1:]) > 0 {
				t.Contexts = append(t.Contexts, token[1:])
			} else {
				t.Title = addToTitle(t.Title, token)
			}
		case strings.HasPrefix(token, "+"):
			if len(token[1:]) > 0 {
				t.Tags = append(t.Tags, token[1:])
			} else {
				t.Title = addToTitle(t.Title, token)
			}
		case strings.HasPrefix(token, "s:"):
			start, err := time.ParseInLocation(DateFormat, token[2:], time.Local)
			if err == nil {
				t.Start = start
			} else {
				t.Title = addToTitle(t.Title, token)
			}
		default:
			t.Title = addToTitle(t.Title, token)
		}
	}
	return t, nil
}

func addToTitle(title string, a string) string {
	if len(title) > 0 {
		title += " "
	}
	return title + a
}

func (t Task) String() string {
	out := ""
	if t.Done {
		out = "x"
	}
	out += "\t"
	due := ""
	if !t.Due.IsZero() {
		due = t.Due.Format(DateFormat)
	}
	start := ""
	if !t.Start.IsZero() {
		start = t.Start.Format(DateFormat)
	}
	out += fmt.Sprintf(
		"%v\t%v\t%v\t",
		t.Title,
		due,
		start,
	)

	return out
}
<commit_msg>Add line number to print<commit_after>// Copyright 2014 Ethan Miller. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// package todo implements a parser for my minimal todo list format.
package todo

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"strings"
	"time"
)

// A TaskList is a list of tasks
type TaskList []Task

func (l TaskList) Len() int      { return len(l) }
func (l TaskList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l TaskList) Less(i, j int) bool {
	// sort by:
	// not done before done
	// then by due date
	// then by start date
	// then alphabetically
	if l[i].Done && !l[j].Done {
		return false
	}
	if !l[i].Done && l[j].Done {
		return true
	}

	dbefore, eq := before(l[i].Due, l[j].Due)
	if !eq {
		return dbefore
	}

	sbefore, eq := before(l[i].Start, l[j].Start)
	if !eq {
		return sbefore
	}

	return l[i].Title < l[j].Title
}

// returns before, equal
func before(a, b time.Time) (bool, bool) {
	if a.Equal(b) {
		return false, true
	}
	if a.IsZero() && !b.IsZero() {
		return false, false
	}
	if !a.IsZero() && b.IsZero() {
		return true, false
	}
	if a.Before(b) {
		return true, false
	} else {
		return false, false
	}
}

func FromReader(r io.Reader) (TaskList, error) {
	s := bufio.NewScanner(r)
	var ret TaskList
	lno := 1
	for s.Scan() {
		line := s.Text()
		todo, err := Parse(line)
		if err != nil {
			return nil, fmt.Errorf("%v on line %v", err, lno)
		}
		todo.index = lno
		ret = append(ret, todo)
		lno++
	}
	return ret, nil
}

// A Task is represents a item in a todo list
type Task struct {
	Title    string
	Start    time.Time
	Due      time.Time
	Tags     []string
	Contexts []string
	index    int // line in file
	Raw      string
	Done     bool

	original string
}

// DateFormat is YY-MM-DD, with no times, time zone, etc.
const DateFormat = "2006-1-2"

// Parse takes a string and parses it as todo.txt formatted todo item
func Parse(r string) (Task, error) {
	if len(r) == 0 {
		return Task{}, errors.New("todo: parse empty string")
	}

	t := Task{Raw: r}
	tokens := strings.Fields(r)
	if len(tokens) == 0 {
		return Task{}, errors.New("todo: parse only whitespace")
	}

	if len(tokens) > 0 && tokens[0] == "x" {
		t.Done = true
		tokens = tokens[1:]
	}

	if len(tokens) == 0 {
		return Task{}, errors.New("todo: line contains only completion marker")
	}

	for _, token := range tokens {
		date, err := time.ParseInLocation(DateFormat, token, time.Local)
		switch {
		case err == nil:
			t.Due = date
		case strings.HasPrefix(token, "@"):
			if len(token[1:]) > 0 {
				t.Contexts = append(t.Contexts, token[1:])
			} else {
				t.Title = addToTitle(t.Title, token)
			}
		case strings.HasPrefix(token, "+"):
			if len(token[1:]) > 0 {
				t.Tags = append(t.Tags, token[1:])
			} else {
				t.Title = addToTitle(t.Title, token)
			}
		case strings.HasPrefix(token, "s:"):
			start, err := time.ParseInLocation(DateFormat, token[2:], time.Local)
			if err == nil {
				t.Start = start
			} else {
				t.Title = addToTitle(t.Title, token)
			}
		default:
			t.Title = addToTitle(t.Title, token)
		}
	}
	return t, nil
}

func addToTitle(title string, a string) string {
	if len(title) > 0 {
		title += " "
	}
	return title + a
}

func (t Task) String() string {
	done := ""
	if t.Done {
		done = "x"
	}
	due := ""
	if !t.Due.IsZero() {
		due = t.Due.Format(DateFormat)
	}
	start := ""
	if !t.Start.IsZero() {
		start = t.Start.Format(DateFormat)
	}
	out := fmt.Sprintf(
		"%v\t%v\t%v\t%v\t%v\t",
		t.index,
		done,
		t.Title,
		due,
		start,
	)

	return out
}
<|endoftext|>


<commit_before>// Package tool wraps the go tool.
package tool

import (
	"bytes"
	"fmt"
	"os/exec"
	"strings"
)

// Defines an Build command.
type Options struct {
	GoBin       string
	ImportPaths []string
	Output      string
	ForceAll    bool
	Parallel    uint
	Compiler    string
	GccGoFlags  string
	GcFlags     string
	LdFlags     string
	Tags        string
	Verbose     bool
}

type CommandError struct {
	command string
	options *Options
	out     []byte
	err     []byte
}

// Default fallback.
var goBinFallback string

func goBin(explicit string) (string, error) {
	if explicit != "" {
		return explicit, nil
	}
	if goBinFallback != "" {
		return goBinFallback, nil
	}
	var err error
	goBinFallback, err = exec.LookPath("go")
	if err != nil {
		return "", fmt.Errorf("Error finding go binary: %s", err)
	}
	return goBinFallback, nil
}

func (e *CommandError) Error() string {
	return fmt.Sprintf(
		"%s Failed %+v: %s\n%s", strings.Title(e.command), e.options, e.out, e.err)
}

func (e *CommandError) StdErr() []byte {
	return e.err
}

func (e *CommandError) StdOut() []byte {
	return e.out
}

func (o *Options) Command(command string) (affected []string, err error) {
	args := []string{command}
	if o.Output != "" {
		args = append(args, "-o", o.Output)
	}
	if o.ForceAll {
		args = append(args, "-a")
	}
	if o.Parallel != 0 {
		args = append(args, "-p", fmt.Sprintf("%d", o.Parallel))
	}
	if o.Compiler != "" {
		args = append(args, "-compiler", o.Compiler)
	}
	if o.GccGoFlags != "" {
		args = append(args, "-gccgoflags", o.GccGoFlags)
	}
	if o.GcFlags != "" {
		args = append(args, "-gcflags", o.GcFlags)
	}
	if o.LdFlags != "" {
		args = append(args, "-ldflags", o.LdFlags)
	}
	if o.Tags != "" {
		args = append(args, "-tags", o.Tags)
	}
	if o.Verbose {
		args = append(args, "-v")
	}
	for _, importPath := range o.ImportPaths {
		args = append(args, importPath)
	}
	bin, err := goBin(o.GoBin)
	if err != nil {
		return nil, err
	}
	cmd := exec.Command(bin, args...)
	var bufOut, bufErr bytes.Buffer
	cmd.Stdout = &bufOut
	cmd.Stderr = &bufErr
	err = cmd.Run()
	if err != nil {
		return nil, &CommandError{
			command: command,
			options: o,
			out:     bufOut.Bytes(),
			err:     bufErr.Bytes(),
		}
	}
	affectedBytes := bytes.Split(bufErr.Bytes(), []byte("\n"))
	affected = make([]string, 0, len(affectedBytes))
	for _, importPath := range affectedBytes {
		if len(importPath) == 0 {
			continue
		}
		affected = append(affected, string(importPath))
	}
	return affected, nil
}
<commit_msg>improve error message for command failures<commit_after>// Package tool wraps the go tool.
package tool

import (
	"bytes"
	"fmt"
	"os/exec"
	"strings"
)

// Defines an Build command.
type Options struct {
	GoBin       string
	ImportPaths []string
	Output      string
	ForceAll    bool
	Parallel    uint
	Compiler    string
	GccGoFlags  string
	GcFlags     string
	LdFlags     string
	Tags        string
	Verbose     bool
}

type CommandError struct {
	fullCommand string
	out         []byte
	err         []byte
}

// Default fallback.
var goBinFallback string

func goBin(explicit string) (string, error) {
	if explicit != "" {
		return explicit, nil
	}
	if goBinFallback != "" {
		return goBinFallback, nil
	}
	var err error
	goBinFallback, err = exec.LookPath("go")
	if err != nil {
		return "", fmt.Errorf("Error finding go binary: %s", err)
	}
	return goBinFallback, nil
}

func (e *CommandError) Error() string {
	return fmt.Sprintf(
		"error executing: %s:\n%s\n%s",
		e.fullCommand,
		e.err,
		bytes.TrimSpace(e.out),
	)
}

func (e *CommandError) StdErr() []byte {
	return e.err
}

func (e *CommandError) StdOut() []byte {
	return e.out
}

func (o *Options) Command(command string) (affected []string, err error) {
	args := []string{command}
	if o.Output != "" {
		args = append(args, "-o", o.Output)
	}
	if o.ForceAll {
		args = append(args, "-a")
	}
	if o.Parallel != 0 {
		args = append(args, "-p", fmt.Sprintf("%d", o.Parallel))
	}
	if o.Compiler != "" {
		args = append(args, "-compiler", o.Compiler)
	}
	if o.GccGoFlags != "" {
		args = append(args, "-gccgoflags", o.GccGoFlags)
	}
	if o.GcFlags != "" {
		args = append(args, "-gcflags", o.GcFlags)
	}
	if o.LdFlags != "" {
		args = append(args, "-ldflags", o.LdFlags)
	}
	if o.Tags != "" {
		args = append(args, "-tags", o.Tags)
	}
	if o.Verbose {
		args = append(args, "-v")
	}
	for _, importPath := range o.ImportPaths {
		args = append(args, importPath)
	}
	bin, err := goBin(o.GoBin)
	if err != nil {
		return nil, err
	}
	cmd := exec.Command(bin, args...)
	var bufOut, bufErr bytes.Buffer
	cmd.Stdout = &bufOut
	cmd.Stderr = &bufErr
	err = cmd.Run()
	if err != nil {
		return nil, &CommandError{
			fullCommand: bin + " " + strings.Join(args, " "),
			out:         bufOut.Bytes(),
			err:         bufErr.Bytes(),
		}
	}
	affectedBytes := bytes.Split(bufErr.Bytes(), []byte("\n"))
	affected = make([]string, 0, len(affectedBytes))
	for _, importPath := range affectedBytes {
		if len(importPath) == 0 {
			continue
		}
		affected = append(affected, string(importPath))
	}
	return affected, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"sync"
	"time"
)

var (
	addr         = flag.String("addr", "localhost:7702", "The address on which netprint listens.")
	tcp          = flag.Bool("tcp", false, "Accept raw TCP requests instead of HTTP.")
	udp          = flag.Bool("udp", false, "Accept raw UDP packets instead of HTTP.")
	delay        = flag.Duration("delay", 0, "How long to delay before responding (HTTP only).")
	responseCode = flag.Int("response-code", http.StatusOK, "Response code for HTTP requests.")
	responseText = flag.String("response-text", "", "Response body for HTTP requests.")
	mode         = modeHTTP
	mut          = &sync.Mutex{}
)

func fatal(args ...interface{}) {
	fmt.Println(args...)
	os.Exit(1)
}

func fatalf(format string, args ...interface{}) {
	fmt.Printf(format, args...)
	os.Exit(1)
}

type modeType int

const (
	modeHTTP modeType = iota
	modeTCP
	modeUDP
)

// copyRecordNewline is like io.Copy, but says whether the copied data ended in a newline.
func copyRecordNewline(dst io.Writer, src io.Reader) (written int64, err error, endingNewline bool) {
	buf := make([]byte, 32*1024)
	for {
		nr, er := src.Read(buf)
		if nr > 0 {
			nw, ew := dst.Write(buf[:nr])
			if nw > 0 {
				written += int64(nw)
			}
			if ew != nil {
				err = ew
				break
			}
			if nr != nw {
				err = io.ErrShortWrite
				break
			}
			endingNewline = buf[nr-1] == '\n'
		}
		if er == io.EOF {
			break
		}
		if er != nil {
			err = er
			break
		}
	}
	return written, err, endingNewline
}

func handleHTTP(w http.ResponseWriter, r *http.Request) {
	// It's pretty dumb to synchronize all the HTTP handlers when net/http is doing such a good job of
	// multiplexing requests onto goroutines for me, but this approach is simpler than constructing a
	// non-concurrent HTTP server.
	mut.Lock()
	defer mut.Unlock()

	fmt.Printf(">>>>> Request: %s\n", r.URL)
	written, err, endingNewline := copyRecordNewline(os.Stdout, r.Body)
	if err != nil {
		return
	}
	if written == 0 {
		fmt.Println("(Empty body.)")
	} else if !endingNewline {
		fmt.Println()
	}

	time.Sleep(*delay)

	w.WriteHeader(*responseCode)
	w.Write([]byte(*responseText))
}

func runHTTP() error {
	mux := http.NewServeMux()
	mux.HandleFunc("/", handleHTTP)
	fmt.Println("Now accepting HTTP requests on", *addr)
	return http.ListenAndServe(*addr, mux)
}

func handleTCP(conn net.Conn) {
	fmt.Printf(">>>>> %s connected.\n", conn.RemoteAddr())
	written, err, endingNewline := copyRecordNewline(os.Stdout, conn)
	if err != nil {
		return
	}
	if written == 0 {
		fmt.Println("(No data transmitted.)")
	} else if !endingNewline {
		fmt.Println()
	}
	fmt.Printf(">>>>> %s disconnected.\n", conn.RemoteAddr())
}

func runTCP() error {
	l, err := net.Listen("tcp", *addr)
	if err != nil {
		return err
	}
	fmt.Println("Now accepting raw TCP requests on", *addr)
	for {
		conn, err := l.Accept()
		if err != nil {
			return err
		}
		handleTCP(conn)
	}
}

func handleUDP(conn *net.UDPConn) {
	buf := make([]byte, 10*1024) // 10KB buffer to handle pretty damn big UDP packets
	for {
		n, addr, err := conn.ReadFromUDP(buf)
		if err != nil {
			return
		}
		fmt.Printf(">>>>> Received a packet from %s\n", addr)
		if n == 0 {
			fmt.Println("(No data transmitted.)")
		} else {
			os.Stdout.Write(buf[:n])
			if buf[n-1] != '\n' {
				fmt.Println()
			}
		}
	}
}

func runUDP() error {
	u, err := net.ResolveUDPAddr("udp", *addr)
	if err != nil {
		return err
	}
	conn, err := net.ListenUDP("udp", u)
	if err != nil {
		return err
	}
	fmt.Println("Now accepting raw UDP requests on", *addr)
	handleUDP(conn)
	return nil
}

func main() {
	flag.Parse()
	if *tcp {
		if *udp {
			fatal("Cannot specify both -tcp and -udp.")
		}
		mode = modeTCP
	}
	if *udp {
		mode = modeUDP
	}

	setFlags := make(map[string]bool)
	flag.Visit(func(f *flag.Flag) { setFlags[f.Name] = true })

	for _, f := range []string{"response-code", "response-text", "delay"} {
		if setFlags[f] && mode != modeHTTP {
			fatalf("Cannot specify -%s except in HTTP mode.", f)
		}
	}
	if setFlags["response-code"] && (*responseCode < 100 || *responseCode >= 600) {
		fatal("Invalid HTTP response code:", *responseCode)
	}
	switch mode {
	case modeHTTP:
		fatal(runHTTP())
	case modeTCP:
		fatal(runTCP())
	case modeUDP:
		fatal(runUDP())
	}
}
<commit_msg>Clean up style<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"sync"
	"time"
)

var (
	addr         = flag.String("addr", "localhost:7702", "The address on which netprint listens.")
	tcp          = flag.Bool("tcp", false, "Accept raw TCP requests instead of HTTP.")
	udp          = flag.Bool("udp", false, "Accept raw UDP packets instead of HTTP.")
	delay        = flag.Duration("delay", 0, "How long to delay before responding (HTTP only).")
	responseCode = flag.Int("response-code", http.StatusOK, "Response code for HTTP requests.")
	responseText = flag.String("response-text", "", "Response body for HTTP requests.")
	mode         = modeHTTP
	mut          = &sync.Mutex{}
)

func fatal(args ...interface{}) {
	fmt.Println(args...)
	os.Exit(1)
}

func fatalf(format string, args ...interface{}) {
	fmt.Printf(format, args...)
	os.Exit(1)
}

type modeType int

const (
	modeHTTP modeType = iota
	modeTCP
	modeUDP
)

// copyRecordNewline is like io.Copy, but says whether the copied data ended in
// a newline.
func copyRecordNewline(dst io.Writer, src io.Reader) (n int64, newline bool, err error) {
	w := &lastByteWriter{w: dst}
	n, err = io.Copy(w, src)
	if n > 0 {
		newline = w.c == '\n'
	}
	return
}

type lastByteWriter struct {
	w io.Writer
	c byte
}

func (w *lastByteWriter) Write(b []byte) (int, error) {
	n, err := w.w.Write(b)
	if n > 0 {
		w.c = b[n-1]
	}
	return n, err
}

func handleHTTP(w http.ResponseWriter, r *http.Request) {
	mut.Lock()
	defer mut.Unlock()

	fmt.Printf(">>>>> Request: %s\n", r.URL)
	n, newline, err := copyRecordNewline(os.Stdout, r.Body)
	if err != nil {
		return
	}
	if n == 0 {
		fmt.Println("(Empty body.)")
	} else if !newline {
		fmt.Println()
	}

	time.Sleep(*delay)

	w.WriteHeader(*responseCode)
	w.Write([]byte(*responseText))
}

func runHTTP() error {
	mux := http.NewServeMux()
	mux.HandleFunc("/", handleHTTP)
	fmt.Println("Now accepting HTTP requests on", *addr)
	return http.ListenAndServe(*addr, mux)
}

func handleTCP(conn net.Conn) {
	fmt.Printf(">>>>> %s connected.\n", conn.RemoteAddr())
	n, newline, err := copyRecordNewline(os.Stdout, conn)
	if err != nil {
		return
	}
	if n == 0 {
		fmt.Println("(No data transmitted.)")
	} else if !newline {
		fmt.Println()
	}
	fmt.Printf(">>>>> %s disconnected.\n", conn.RemoteAddr())
}

func runTCP() error {
	l, err := net.Listen("tcp", *addr)
	if err != nil {
		return err
	}
	fmt.Println("Now accepting raw TCP requests on", *addr)
	for {
		conn, err := l.Accept()
		if err != nil {
			return err
		}
		handleTCP(conn)
	}
}

func handleUDP(conn *net.UDPConn) {
	buf := make([]byte, 10*1024) // 10KB buffer to handle pretty damn big UDP packets
	for {
		n, addr, err := conn.ReadFromUDP(buf)
		if err != nil {
			return
		}
		fmt.Printf(">>>>> Received a packet from %s\n", addr)
		if n == 0 {
			fmt.Println("(No data transmitted.)")
		} else {
			os.Stdout.Write(buf[:n])
			if buf[n-1] != '\n' {
				fmt.Println()
			}
		}
	}
}

func runUDP() error {
	u, err := net.ResolveUDPAddr("udp", *addr)
	if err != nil {
		return err
	}
	conn, err := net.ListenUDP("udp", u)
	if err != nil {
		return err
	}
	fmt.Println("Now accepting raw UDP requests on", *addr)
	handleUDP(conn)
	return nil
}

func main() {
	flag.Parse()
	if *tcp {
		if *udp {
			fatal("Cannot specify both -tcp and -udp.")
		}
		mode = modeTCP
	}
	if *udp {
		mode = modeUDP
	}

	setFlags := make(map[string]bool)
	flag.Visit(func(f *flag.Flag) { setFlags[f.Name] = true })

	for _, f := range []string{"response-code", "response-text", "delay"} {
		if setFlags[f] && mode != modeHTTP {
			fatalf("Cannot specify -%s except in HTTP mode.", f)
		}
	}
	if setFlags["response-code"] && (*responseCode < 100 || *responseCode >= 600) {
		fatal("Invalid HTTP response code:", *responseCode)
	}
	switch mode {
	case modeHTTP:
		fatal(runHTTP())
	case modeTCP:
		fatal(runTCP())
	case modeUDP:
		fatal(runUDP())
	}
}
<|endoftext|>


<commit_before><commit_msg>Not all Kinds should be registered to RESTMapper<commit_after><|endoftext|>


<commit_before><commit_msg>[Federation][kubefed] Create a dedicated service account for federation controller manager in the host cluster and give it appropriate permissions.<commit_after><|endoftext|>


<commit_before>// Package netstate provides routines to obtain the available set of
// of network addresess, for determining changes to those addresses and for
// selecting from amongst them according to some set of policies that are
// implemented by applying simple predicates (functions with names of the form
// Is<condition>) to filter or find the first matching address from a list
// of addresses. The intent is to make it easy to create policies that do
// things like 'find the first IPv4 unicast address that is globally routable,
// failing that use a private IPv4 address, and failing that, an IPv6 address'.
//
// A simple usage would be:
//
//   state, _ := netstate.GetAccessibleIPs()
//   ipv4 := state.Filter(netstate.IsPublicUnicastIPv4)
//   // ipv4 will contain all of the public IPv4 addresses, if any.
//
// The example policy described above would be implemented using a
// series of calls to Filter with appropriate predicates.
//
// In some cases, it may be necessary to take IP routing information
// into account and hence interface hosting the address. The interface
// hosting each address is provided in the AddrIfc structure used to represent
// addresses and the IP routing information is provided by the GetAccessibleIPs
// function which will typically be used to obtain the available IP addresses.
//
// Although most commercial networking hardware supports IPv6, some consumer
// devices and more importantly many ISPs do not, so routines are provided
// to allow developers to easily distinguish between the two and to use
// whichever is appropriate for their product/situation.
//
// The term 'accessible' is used to refer to any non-loopback IP address.
// The term 'public' is used to refer to any globally routable IP address.
//
// All IPv6 addresses are intended to be 'public', but any starting with
// fc00::/7 (RFC4193) are reserved for private use, but the go
// net libraries do not appear to recognise this. Similarly fe80::/10
// (RFC 4291) are reserved for 'site-local' usage, but again this is not
// implemented in the go libraries. Any developer who needs to distinguish
// these cases will need to write their own routines to test for them.
//
// When using the go net package it is important to remember that IPv6
// addresses subsume IPv4 and hence in many cases the same internal
// representation is used for both, thus testing for the length of the IP
// address is unreliable. The reliable test is to use the net.To4() which
// will return a non-nil result if can be used as an IPv4 one. Any address
// can be used as an IPv6 and hence the only reliable way to test for an IPv6
// address that is not an IPv4 one also is for the To4 call to return nil for
// it.
package netstate

import (
	"fmt"
	"net"
	"strings"

	"v.io/core/veyron2/ipc"

	"v.io/core/veyron/lib/netconfig"
)

// AddrIfc represents a network address and the network interface that
// hosts it.
type AddrIfc struct {
	// Network address
	Addr net.Addr

	// The name of the network interface this address is hosted on, empty
	// if this information is not available.
	Name string

	// The IPRoutes of the network interface this address is hosted on,
	// nil if this information is not available.
	IPRoutes []*netconfig.IPRoute
}

func (a *AddrIfc) String() string {
	if a.IPRoutes != nil {
		r := fmt.Sprintf("%s: %s[", a.Addr, a.Name)
		for _, rt := range a.IPRoutes {
			src := ""
			if rt.PreferredSource != nil {
				src = ", src: " + rt.PreferredSource.String()
			}
			r += fmt.Sprintf("{%d: net: %s, gw: %s%s}, ", rt.IfcIndex, rt.Net, rt.Gateway, src)
		}
		r = strings.TrimSuffix(r, ", ")
		r += "]"
		return r
	}
	return a.Addr.String()
}

func (a *AddrIfc) Address() net.Addr {
	return a.Addr
}

func (a *AddrIfc) InterfaceIndex() int {
	if len(a.IPRoutes) == 0 {
		return -1
	}
	return a.IPRoutes[0].IfcIndex
}

func (a *AddrIfc) InterfaceName() string {
	return a.Name
}

func (a *AddrIfc) Networks() []net.Addr {
	nets := []net.Addr{}
	for _, r := range a.IPRoutes {
		nets = append(nets, &r.Net)
	}
	return nets
}

type AddrList []ipc.Address

func (al AddrList) String() string {
	r := ""
	for _, v := range al {
		r += fmt.Sprintf("(%s) ", v)
	}
	return strings.TrimRight(r, " ")
}

// GetAll gets all of the available addresses on the device, including
// loopback addresses, non-IP protocols etc.
func GetAll() (AddrList, error) {
	interfaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	routes := netconfig.GetIPRoutes(false)
	routeTable := make(map[int][]*netconfig.IPRoute)
	for _, r := range routes {
		routeTable[r.IfcIndex] = append(routeTable[r.IfcIndex], r)
	}
	var all AddrList
	for _, ifc := range interfaces {
		addrs, err := ifc.Addrs()
		if err != nil {
			continue
		}
		for _, a := range addrs {
			all = append(all, &AddrIfc{a, ifc.Name, routeTable[ifc.Index]})
		}
	}
	return all, nil
}

// GetAccessibleIPs returns all of the accessible IP addresses on the device
// - i.e. excluding loopback and unspecified addresses.
// The IP addresses returned will be host addresses.
func GetAccessibleIPs() (AddrList, error) {
	all, err := GetAll()
	if err != nil {
		return nil, err
	}
	return all.Map(ConvertAccessibleIPHost), nil
}

// AddressPredicate defines the function signature for predicate functions
// to be used with AddrList
type AddressPredicate func(a ipc.Address) bool

// Filter returns all of the addresses for which the predicate
// function is true.
func (al AddrList) Filter(predicate AddressPredicate) AddrList {
	r := AddrList{}
	for _, a := range al {
		if predicate(a) {
			r = append(r, a)
		}
	}
	return r
}

type Mapper func(a ipc.Address) ipc.Address

// Map will apply the Mapper function to all of the items in its receiver
// and return a new AddrList containing all of the non-nil results from
// said calls.
func (al AddrList) Map(mapper Mapper) AddrList {
	var ral AddrList
	for _, a := range al {
		if na := mapper(a); na != nil {
			ral = append(ral, na)
		}
	}
	return ral
}

// ConvertToIPHost converts the network address component of an ipc.Address into
// an instance with a net.Addr that contains an IP host address (as opposed to a
// network CIDR for example).
func ConvertToIPHost(a ipc.Address) ipc.Address {
	aifc, ok := a.(*AddrIfc)
	if !ok {
		return nil
	}
	aifc.Addr = AsIPAddr(aifc.Addr)
	return aifc
}

// ConvertAccessibleIPHost converts the network address component of an ipc.Address
// into an instance with a net.Addr that contains an IP host address (as opposed to a
// network CIDR for example) with filtering out a loopback or non-accessible IPs.
func ConvertAccessibleIPHost(a ipc.Address) ipc.Address {
	if !IsAccessibleIP(a) {
		return nil
	}
	aifc, ok := a.(*AddrIfc)
	if !ok {
		return nil
	}
	if ip := AsIPAddr(aifc.Addr); ip != nil {
		aifc.Addr = ip
	}
	return aifc
}

// IsIPProtocol returns true if its parameter is one of the allowed
// network/protocol values for IP.
func IsIPProtocol(n string) bool {
	switch n {
	case "ip+net", "ip", "tcp", "tcp4", "tcp6", "udp":
		return true
	default:
		return false
	}
}

// AsIPAddr returns its argument as a net.IPAddr if that's possible.
func AsIPAddr(a net.Addr) *net.IPAddr {
	if v, ok := a.(*net.IPAddr); ok {
		return v
	}
	if ipn, ok := a.(*net.IPNet); ok {
		return &net.IPAddr{IP: ipn.IP}
	}
	if IsIPProtocol(a.Network()) {
		if r := net.ParseIP(a.String()); r != nil {
			return &net.IPAddr{IP: r}
		}
	}
	return nil
}

// AsIP returns its argument as a net.IP if that's possible.
func AsIP(a net.Addr) net.IP {
	ipAddr := AsIPAddr(a)
	if ipAddr == nil {
		return nil
	}
	return ipAddr.IP
}

// IsUnspecified returns true if its argument is an unspecified IP address
func IsUnspecifiedIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil {
		return ip.IsUnspecified()
	}
	return false
}

// IsLoopback returns true if its argument is a loopback IP address
func IsLoopbackIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && !ip.IsUnspecified() {
		return ip.IsLoopback()
	}
	return false
}

// IsAccessible returns true if its argument is an accessible (non-loopback)
// IP address.
func IsAccessibleIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && !ip.IsUnspecified() {
		return !ip.IsLoopback()
	}
	return false
}

// IsUnicastIP returns true if its argument is a unicast IP address.
func IsUnicastIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && !ip.IsUnspecified() {
		// ipv4 or v6
		return !(ip.IsMulticast() || ip.IsLinkLocalMulticast() || ip.IsInterfaceLocalMulticast())
	}
	return false
}

// IsUnicastIPv4 returns true if its argument is a unicast IP4 address
func IsUnicastIPv4(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && ip.To4() != nil {
		return !ip.IsUnspecified() && !ip.IsMulticast()
	}
	return false
}

// IsPublicUnicastIPv4 returns true if its argument is a globally routable,
// public IPv4 unicast address.
func IsPublicUnicastIPv4(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && !ip.IsUnspecified() {
		if t := ip.To4(); t != nil && IsGloballyRoutableIP(t) {
			return !ip.IsMulticast()
		}
	}
	return false
}

// IsUnicastIPv6 returns true if its argument is a unicast IPv6 address
func IsUnicastIPv6(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && ip.To4() == nil {
		return !ip.IsUnspecified() && !(ip.IsLinkLocalMulticast() || ip.IsInterfaceLocalMulticast())
	}
	return false
}

// IsUnicastIPv6 returns true if its argument is a globally routable IP6
// address
func IsPublicUnicastIPv6(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && ip.To4() == nil {
		if t := ip.To16(); t != nil && IsGloballyRoutableIP(t) {
			return true
		}
	}
	return false
}

// IsPublicUnicastIP returns true if its argument is a global routable IPv4
// or 6 address.
func IsPublicUnicastIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil {
		if t := ip.To4(); t != nil && IsGloballyRoutableIP(t) {
			return true
		}
		if t := ip.To16(); t != nil && IsGloballyRoutableIP(t) {
			return true
		}
	}
	return false
}

func diffAB(a, b AddrList) AddrList {
	diff := AddrList{}
	for _, av := range a {
		found := false
		for _, bv := range b {
			if av.Address().Network() == bv.Address().Network() &&
				av.Address().String() == bv.Address().String() {
				found = true
				break
			}
		}
		if !found {
			diff = append(diff, av)
		}
	}
	return diff
}

// FindAdded returns the set addresses that are present in b, but not
// in a - i.e. have been added.
func FindAdded(a, b AddrList) AddrList {
	return diffAB(b, a)
}

// FindRemoved returns the set of addresses that are present in a, but not
// in b - i.e. have been removed.
func FindRemoved(a, b AddrList) AddrList {
	return diffAB(a, b)
}

// SameMachine returns true if the provided addr is on the device executing this
// function.
func SameMachine(addr net.Addr) (bool, error) {
	// The available interfaces may change between calls.
	addrs, err := GetAll()
	if err != nil {
		return false, err
	}
	ips := make(map[string]struct{})
	for _, a := range addrs {
		ip, _, err := net.ParseCIDR(a.Address().String())
		if err != nil {
			return false, err
		}
		ips[ip.String()] = struct{}{}
	}

	client, _, err := net.SplitHostPort(addr.String())
	if err != nil {
		return false, err
	}
	_, islocal := ips[client]
	return islocal, nil
}
<commit_msg>veyron/lib/netstate: Add "wsh" as recognized protocol in IsIPProtocol.<commit_after>// Package netstate provides routines to obtain the available set of
// of network addresess, for determining changes to those addresses and for
// selecting from amongst them according to some set of policies that are
// implemented by applying simple predicates (functions with names of the form
// Is<condition>) to filter or find the first matching address from a list
// of addresses. The intent is to make it easy to create policies that do
// things like 'find the first IPv4 unicast address that is globally routable,
// failing that use a private IPv4 address, and failing that, an IPv6 address'.
//
// A simple usage would be:
//
//   state, _ := netstate.GetAccessibleIPs()
//   ipv4 := state.Filter(netstate.IsPublicUnicastIPv4)
//   // ipv4 will contain all of the public IPv4 addresses, if any.
//
// The example policy described above would be implemented using a
// series of calls to Filter with appropriate predicates.
//
// In some cases, it may be necessary to take IP routing information
// into account and hence interface hosting the address. The interface
// hosting each address is provided in the AddrIfc structure used to represent
// addresses and the IP routing information is provided by the GetAccessibleIPs
// function which will typically be used to obtain the available IP addresses.
//
// Although most commercial networking hardware supports IPv6, some consumer
// devices and more importantly many ISPs do not, so routines are provided
// to allow developers to easily distinguish between the two and to use
// whichever is appropriate for their product/situation.
//
// The term 'accessible' is used to refer to any non-loopback IP address.
// The term 'public' is used to refer to any globally routable IP address.
//
// All IPv6 addresses are intended to be 'public', but any starting with
// fc00::/7 (RFC4193) are reserved for private use, but the go
// net libraries do not appear to recognise this. Similarly fe80::/10
// (RFC 4291) are reserved for 'site-local' usage, but again this is not
// implemented in the go libraries. Any developer who needs to distinguish
// these cases will need to write their own routines to test for them.
//
// When using the go net package it is important to remember that IPv6
// addresses subsume IPv4 and hence in many cases the same internal
// representation is used for both, thus testing for the length of the IP
// address is unreliable. The reliable test is to use the net.To4() which
// will return a non-nil result if can be used as an IPv4 one. Any address
// can be used as an IPv6 and hence the only reliable way to test for an IPv6
// address that is not an IPv4 one also is for the To4 call to return nil for
// it.
package netstate

import (
	"fmt"
	"net"
	"strings"

	"v.io/core/veyron2/ipc"

	"v.io/core/veyron/lib/netconfig"
)

// AddrIfc represents a network address and the network interface that
// hosts it.
type AddrIfc struct {
	// Network address
	Addr net.Addr

	// The name of the network interface this address is hosted on, empty
	// if this information is not available.
	Name string

	// The IPRoutes of the network interface this address is hosted on,
	// nil if this information is not available.
	IPRoutes []*netconfig.IPRoute
}

func (a *AddrIfc) String() string {
	if a.IPRoutes != nil {
		r := fmt.Sprintf("%s: %s[", a.Addr, a.Name)
		for _, rt := range a.IPRoutes {
			src := ""
			if rt.PreferredSource != nil {
				src = ", src: " + rt.PreferredSource.String()
			}
			r += fmt.Sprintf("{%d: net: %s, gw: %s%s}, ", rt.IfcIndex, rt.Net, rt.Gateway, src)
		}
		r = strings.TrimSuffix(r, ", ")
		r += "]"
		return r
	}
	return a.Addr.String()
}

func (a *AddrIfc) Address() net.Addr {
	return a.Addr
}

func (a *AddrIfc) InterfaceIndex() int {
	if len(a.IPRoutes) == 0 {
		return -1
	}
	return a.IPRoutes[0].IfcIndex
}

func (a *AddrIfc) InterfaceName() string {
	return a.Name
}

func (a *AddrIfc) Networks() []net.Addr {
	nets := []net.Addr{}
	for _, r := range a.IPRoutes {
		nets = append(nets, &r.Net)
	}
	return nets
}

type AddrList []ipc.Address

func (al AddrList) String() string {
	r := ""
	for _, v := range al {
		r += fmt.Sprintf("(%s) ", v)
	}
	return strings.TrimRight(r, " ")
}

// GetAll gets all of the available addresses on the device, including
// loopback addresses, non-IP protocols etc.
func GetAll() (AddrList, error) {
	interfaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	routes := netconfig.GetIPRoutes(false)
	routeTable := make(map[int][]*netconfig.IPRoute)
	for _, r := range routes {
		routeTable[r.IfcIndex] = append(routeTable[r.IfcIndex], r)
	}
	var all AddrList
	for _, ifc := range interfaces {
		addrs, err := ifc.Addrs()
		if err != nil {
			continue
		}
		for _, a := range addrs {
			all = append(all, &AddrIfc{a, ifc.Name, routeTable[ifc.Index]})
		}
	}
	return all, nil
}

// GetAccessibleIPs returns all of the accessible IP addresses on the device
// - i.e. excluding loopback and unspecified addresses.
// The IP addresses returned will be host addresses.
func GetAccessibleIPs() (AddrList, error) {
	all, err := GetAll()
	if err != nil {
		return nil, err
	}
	return all.Map(ConvertAccessibleIPHost), nil
}

// AddressPredicate defines the function signature for predicate functions
// to be used with AddrList
type AddressPredicate func(a ipc.Address) bool

// Filter returns all of the addresses for which the predicate
// function is true.
func (al AddrList) Filter(predicate AddressPredicate) AddrList {
	r := AddrList{}
	for _, a := range al {
		if predicate(a) {
			r = append(r, a)
		}
	}
	return r
}

type Mapper func(a ipc.Address) ipc.Address

// Map will apply the Mapper function to all of the items in its receiver
// and return a new AddrList containing all of the non-nil results from
// said calls.
func (al AddrList) Map(mapper Mapper) AddrList {
	var ral AddrList
	for _, a := range al {
		if na := mapper(a); na != nil {
			ral = append(ral, na)
		}
	}
	return ral
}

// ConvertToIPHost converts the network address component of an ipc.Address into
// an instance with a net.Addr that contains an IP host address (as opposed to a
// network CIDR for example).
func ConvertToIPHost(a ipc.Address) ipc.Address {
	aifc, ok := a.(*AddrIfc)
	if !ok {
		return nil
	}
	aifc.Addr = AsIPAddr(aifc.Addr)
	return aifc
}

// ConvertAccessibleIPHost converts the network address component of an ipc.Address
// into an instance with a net.Addr that contains an IP host address (as opposed to a
// network CIDR for example) with filtering out a loopback or non-accessible IPs.
func ConvertAccessibleIPHost(a ipc.Address) ipc.Address {
	if !IsAccessibleIP(a) {
		return nil
	}
	aifc, ok := a.(*AddrIfc)
	if !ok {
		return nil
	}
	if ip := AsIPAddr(aifc.Addr); ip != nil {
		aifc.Addr = ip
	}
	return aifc
}

// IsIPProtocol returns true if its parameter is one of the allowed
// network/protocol values for IP.
func IsIPProtocol(n string) bool {
	switch n {
	case "ip+net", "ip", "tcp", "tcp4", "tcp6", "udp", "wsh":
		return true
	default:
		return false
	}
}

// AsIPAddr returns its argument as a net.IPAddr if that's possible.
func AsIPAddr(a net.Addr) *net.IPAddr {
	if v, ok := a.(*net.IPAddr); ok {
		return v
	}
	if ipn, ok := a.(*net.IPNet); ok {
		return &net.IPAddr{IP: ipn.IP}
	}
	if IsIPProtocol(a.Network()) {
		if r := net.ParseIP(a.String()); r != nil {
			return &net.IPAddr{IP: r}
		}
	}
	return nil
}

// AsIP returns its argument as a net.IP if that's possible.
func AsIP(a net.Addr) net.IP {
	ipAddr := AsIPAddr(a)
	if ipAddr == nil {
		return nil
	}
	return ipAddr.IP
}

// IsUnspecified returns true if its argument is an unspecified IP address
func IsUnspecifiedIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil {
		return ip.IsUnspecified()
	}
	return false
}

// IsLoopback returns true if its argument is a loopback IP address
func IsLoopbackIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && !ip.IsUnspecified() {
		return ip.IsLoopback()
	}
	return false
}

// IsAccessible returns true if its argument is an accessible (non-loopback)
// IP address.
func IsAccessibleIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && !ip.IsUnspecified() {
		return !ip.IsLoopback()
	}
	return false
}

// IsUnicastIP returns true if its argument is a unicast IP address.
func IsUnicastIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && !ip.IsUnspecified() {
		// ipv4 or v6
		return !(ip.IsMulticast() || ip.IsLinkLocalMulticast() || ip.IsInterfaceLocalMulticast())
	}
	return false
}

// IsUnicastIPv4 returns true if its argument is a unicast IP4 address
func IsUnicastIPv4(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && ip.To4() != nil {
		return !ip.IsUnspecified() && !ip.IsMulticast()
	}
	return false
}

// IsPublicUnicastIPv4 returns true if its argument is a globally routable,
// public IPv4 unicast address.
func IsPublicUnicastIPv4(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && !ip.IsUnspecified() {
		if t := ip.To4(); t != nil && IsGloballyRoutableIP(t) {
			return !ip.IsMulticast()
		}
	}
	return false
}

// IsUnicastIPv6 returns true if its argument is a unicast IPv6 address
func IsUnicastIPv6(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && ip.To4() == nil {
		return !ip.IsUnspecified() && !(ip.IsLinkLocalMulticast() || ip.IsInterfaceLocalMulticast())
	}
	return false
}

// IsUnicastIPv6 returns true if its argument is a globally routable IP6
// address
func IsPublicUnicastIPv6(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil && ip.To4() == nil {
		if t := ip.To16(); t != nil && IsGloballyRoutableIP(t) {
			return true
		}
	}
	return false
}

// IsPublicUnicastIP returns true if its argument is a global routable IPv4
// or 6 address.
func IsPublicUnicastIP(a ipc.Address) bool {
	if ip := AsIP(a.Address()); ip != nil {
		if t := ip.To4(); t != nil && IsGloballyRoutableIP(t) {
			return true
		}
		if t := ip.To16(); t != nil && IsGloballyRoutableIP(t) {
			return true
		}
	}
	return false
}

func diffAB(a, b AddrList) AddrList {
	diff := AddrList{}
	for _, av := range a {
		found := false
		for _, bv := range b {
			if av.Address().Network() == bv.Address().Network() &&
				av.Address().String() == bv.Address().String() {
				found = true
				break
			}
		}
		if !found {
			diff = append(diff, av)
		}
	}
	return diff
}

// FindAdded returns the set addresses that are present in b, but not
// in a - i.e. have been added.
func FindAdded(a, b AddrList) AddrList {
	return diffAB(b, a)
}

// FindRemoved returns the set of addresses that are present in a, but not
// in b - i.e. have been removed.
func FindRemoved(a, b AddrList) AddrList {
	return diffAB(a, b)
}

// SameMachine returns true if the provided addr is on the device executing this
// function.
func SameMachine(addr net.Addr) (bool, error) {
	// The available interfaces may change between calls.
	addrs, err := GetAll()
	if err != nil {
		return false, err
	}
	ips := make(map[string]struct{})
	for _, a := range addrs {
		ip, _, err := net.ParseCIDR(a.Address().String())
		if err != nil {
			return false, err
		}
		ips[ip.String()] = struct{}{}
	}

	client, _, err := net.SplitHostPort(addr.String())
	if err != nil {
		return false, err
	}
	_, islocal := ips[client]
	return islocal, nil
}
<|endoftext|>


<commit_before><commit_msg>Implement chassis control operations.<commit_after><|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache version 2.0 license. See LICENSE file for terms.

package zmscli

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/yahoo/athenz/clients/go/zms"
)

func (cli Zms) ListServerTemplates() (*string, error) {
	var buf bytes.Buffer
	templates, err := cli.Zms.GetServerTemplateList()
	if err != nil {
		return nil, err
	}
	buf.WriteString("templates:\n")
	for _, name := range templates.TemplateNames {
		buf.WriteString(indent_level1_dash + string(name) + "\n")
	}
	s := buf.String()
	return &s, nil
}

func (cli Zms) ListDomainTemplates(dn string) (*string, error) {
	var buf bytes.Buffer
	templates, err := cli.Zms.GetDomainTemplateList(zms.DomainName(dn))
	if err != nil {
		return nil, err
	}
	buf.WriteString("templates:\n")
	for _, name := range templates.TemplateNames {
		buf.WriteString(indent_level1_dash + string(name) + "\n")
	}
	s := buf.String()
	return &s, nil
}

func (cli Zms) ShowServerTemplate(templateName string) (*string, error) {
	template, err := cli.Zms.GetTemplate(zms.SimpleName(templateName))
	if err != nil {
		return nil, err
	}
	var buf bytes.Buffer
	buf.WriteString("template:\n")
	buf.WriteString(indent_level1 + "roles:\n")
	for _, role := range template.Roles {
		cli.dumpRole(&buf, *role, false, indent_level2_dash, indent_level2_dash_lvl)
	}
	buf.WriteString(indent_level1 + "policies:\n")
	for _, policy := range template.Policies {
		cli.dumpPolicy(&buf, *policy, indent_level2_dash, indent_level2_dash_lvl)
	}

	s := buf.String()
	return &s, nil
}

func (cli Zms) SetDomainTemplate(dn string, templateArgs []string) (*string, error) {
	templateNames := make([]zms.SimpleName, 0)
	templateParams := make([]*zms.TemplateParam, 0)
	for _, value := range templateArgs {
		idx := strings.Index(value, "=")
		if idx < 0 {
			templateNames = append(templateNames, zms.SimpleName(value))
		} else {
			param := zms.TemplateParam{
				Name:  zms.SimpleName(value[0:idx]),
				Value: zms.CompoundName(value[idx+1:]),
			}
			templateParams = append(templateParams, &param)
		}
	}
	//make sure we have some templates specified
	if len(templateNames) == 0 {
		return nil, fmt.Errorf("No template names specified")
	}
	var domainTemplateList zms.DomainTemplate
	domainTemplateList.TemplateNames = templateNames
	if len(templateParams) > 0 {
		domainTemplateList.Params = templateParams
	}
	err := cli.Zms.PutDomainTemplate(zms.DomainName(dn), cli.AuditRef, &domainTemplateList)
	if err != nil {
		return nil, err
	}
	s := "[Template(s) successfully applied to domain]"
	return &s, nil
}

func (cli Zms) DeleteDomainTemplate(dn string, template string) (*string, error) {
	err := cli.Zms.DeleteDomainTemplate(zms.DomainName(dn), zms.SimpleName(template), cli.AuditRef)
	if err != nil {
		return nil, err
	}
	s := "[Deleted template: " + template + "]"
	return &s, nil
}
<commit_msg>display service info from a template using zms-cli (#827)<commit_after>// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache version 2.0 license. See LICENSE file for terms.

package zmscli

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/yahoo/athenz/clients/go/zms"
)

func (cli Zms) ListServerTemplates() (*string, error) {
	var buf bytes.Buffer
	templates, err := cli.Zms.GetServerTemplateList()
	if err != nil {
		return nil, err
	}
	buf.WriteString("templates:\n")
	for _, name := range templates.TemplateNames {
		buf.WriteString(indent_level1_dash + string(name) + "\n")
	}
	s := buf.String()
	return &s, nil
}

func (cli Zms) ListDomainTemplates(dn string) (*string, error) {
	var buf bytes.Buffer
	templates, err := cli.Zms.GetDomainTemplateList(zms.DomainName(dn))
	if err != nil {
		return nil, err
	}
	buf.WriteString("templates:\n")
	for _, name := range templates.TemplateNames {
		buf.WriteString(indent_level1_dash + string(name) + "\n")
	}
	s := buf.String()
	return &s, nil
}

func (cli Zms) ShowServerTemplate(templateName string) (*string, error) {
	template, err := cli.Zms.GetTemplate(zms.SimpleName(templateName))
	if err != nil {
		return nil, err
	}
	var buf bytes.Buffer
	buf.WriteString("template:\n")
	buf.WriteString(indent_level1 + "roles:\n")
	for _, role := range template.Roles {
		cli.dumpRole(&buf, *role, false, indent_level2_dash, indent_level2_dash_lvl)
	}
	buf.WriteString(indent_level1 + "policies:\n")
	for _, policy := range template.Policies {
		cli.dumpPolicy(&buf, *policy, indent_level2_dash, indent_level2_dash_lvl)
	}
	if len(template.Services) > 0 {
		buf.WriteString(indent_level1 + "services:\n")
		for _, service := range template.Services {
			cli.dumpService(&buf, *service, indent_level2_dash, indent_level2_dash_lvl)
		}
	}
	s := buf.String()
	return &s, nil
}

func (cli Zms) SetDomainTemplate(dn string, templateArgs []string) (*string, error) {
	templateNames := make([]zms.SimpleName, 0)
	templateParams := make([]*zms.TemplateParam, 0)
	for _, value := range templateArgs {
		idx := strings.Index(value, "=")
		if idx < 0 {
			templateNames = append(templateNames, zms.SimpleName(value))
		} else {
			param := zms.TemplateParam{
				Name:  zms.SimpleName(value[0:idx]),
				Value: zms.CompoundName(value[idx+1:]),
			}
			templateParams = append(templateParams, &param)
		}
	}
	//make sure we have some templates specified
	if len(templateNames) == 0 {
		return nil, fmt.Errorf("No template names specified")
	}
	var domainTemplateList zms.DomainTemplate
	domainTemplateList.TemplateNames = templateNames
	if len(templateParams) > 0 {
		domainTemplateList.Params = templateParams
	}
	err := cli.Zms.PutDomainTemplate(zms.DomainName(dn), cli.AuditRef, &domainTemplateList)
	if err != nil {
		return nil, err
	}
	s := "[Template(s) successfully applied to domain]"
	return &s, nil
}

func (cli Zms) DeleteDomainTemplate(dn string, template string) (*string, error) {
	err := cli.Zms.DeleteDomainTemplate(zms.DomainName(dn), zms.SimpleName(template), cli.AuditRef)
	if err != nil {
		return nil, err
	}
	s := "[Deleted template: " + template + "]"
	return &s, nil
}
<|endoftext|>


<commit_before>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

package parse

import (
	"fmt"
	"github.com/demizer/go-elog"
	"reflect"
)

type systemMessageLevel int

const (
	levelInfo systemMessageLevel = iota
	levelWarning
	levelError
	levelSevere
)

var systemMessageLevels = [...]string{
	"INFO",
	"WARNING",
	"ERROR",
	"SEVERE",
}

func (s systemMessageLevel) String() string {
	return systemMessageLevels[s]
}

type systemMessage struct {
	level  systemMessageLevel
	line   int
	source string
	items  []item
}

type sectionLevel struct {
	char     rune // The adornment character used to describe the section
	overline bool // The section contains an overline
	length   int  // The length of the adornment lines
}

type sectionLevels []sectionLevel

func (s *sectionLevels) String() string {
	var out string
	for lvl, sec := range *s {
		out += fmt.Sprintf("level: %d, rune: %q, overline: %t, length: %d\n",
			lvl+1, sec.char, sec.overline, sec.length)
	}
	return out
}

func (s *sectionLevels) Add(adornChar rune, overline bool, length int) int {
	lvl := s.Find(adornChar)
	if lvl > 0 {
		return lvl
	}
	*s = append(*s, sectionLevel{char: adornChar, overline: overline, length: length})
	return len(*s)
}

// Returns -1 if not found
func (s *sectionLevels) Find(adornChar rune) int {
	for lvl, sec := range *s {
		if sec.char == adornChar {
			return lvl + 1
		}
	}
	return -1
}

func (s *sectionLevels) Level() int {
	return len(*s)
}

// Parse is the entry point for the reStructuredText parser.
func Parse(name, text string) (t *Tree, errors []error) {
	t = New(name)
	t.text = text
	_, errors = t.Parse(text, t)
	return
}

func New(name string) *Tree {
	return &Tree{Name: name, sectionLevels: new(sectionLevels)}
}

type Tree struct {
	Name          string
	Nodes         *NodeList // The root node list
	Errors        []error
	text          string
	lex           *lexer
	peekCount     int
	token         [3]item        // three-token look-ahead for parser.
	sectionLevel  int            // The current section level of parsing
	sectionLevels *sectionLevels // Encountered section levels
	id            int            // The unique id of the node in the tree
}

func (t *Tree) errorf(format string, args ...interface{}) {
	format = fmt.Sprintf("go-rst: %s:%d: %s\n", t.Name, t.lex.lineNumber(), format)
	t.Errors = append(t.Errors, fmt.Errorf(format, args...))
}

func (t *Tree) error(err error) {
	t.errorf("%s\n", err)
}

// startParse initializes the parser, using the lexer.
func (t *Tree) startParse(lex *lexer) {
	t.Nodes = nil
	t.lex = lex
}

// stopParse terminates parsing.
func (t *Tree) stopParse() {
	t.lex = nil
}

func (t *Tree) Parse(text string, treeSet *Tree) (tree *Tree, errors []error) {
	log.Debugln("Start")
	t.startParse(lex(t.Name, text))
	t.text = text
	t.parse(treeSet)
	log.Debugln("End")
	return t, t.Errors
}

func (t *Tree) parse(tree *Tree) {
	log.Debugln("Start")

	t.Nodes = newList()

	nodeBranch := t.Nodes

	for t.peek().Type != itemEOF {
		var n Node
		token := t.next()
		log.Debugf("Got token: %#+v\n", token)
		switch token.Type {
		case itemTitle: // Section includes overline/underline
			n = t.section(token)
			log.Infof("New Node: %#+v\n", n)
		case itemBlankLine:
			n = newBlankLine(token, &t.id)
			log.Infof("New Node: %#+v\n", n)
		case itemParagraph:
			n = newParagraph(token, &t.id)
			log.Infof("New Node: %#+v\n", n)
		default:
			t.errorf("%q Not implemented!", token.Type)
			continue
		}

		nodeBranch.append(n)
		if n.NodeType() == NodeSection {
			nodeBranch =
			reflect.ValueOf(n).Elem().FieldByName("NodeList").Addr().Interface().(*NodeList)
		}
	}

	log.Debugln("End")
}

func (t *Tree) backup() {
	t.peekCount++
}

// peekBack returns the last item sent from the lexer.
func (t *Tree) peekBack() item {
	return *t.lex.lastItem
}

// peek returns but does not consume the next token.
func (t *Tree) peek() item {
	if t.peekCount > 0 {
		return t.token[t.peekCount-1]

	}
	t.peekCount = 1
	t.token[0] = t.lex.nextItem()
	return t.token[0]
}

func (t *Tree) next() item {
	if t.peekCount > 0 {
		t.peekCount--
	} else {
		t.token[0] = t.lex.nextItem()
	}
	return t.token[t.peekCount]
}

func (t *Tree) section(i item) Node {
	log.Debugln("Start")
	var overAdorn, title, underAdorn item
	var overline bool

	if t.peekBack().Type == itemSectionAdornment {
		overline = true
		overAdorn = t.peekBack()
	}

	title = i
	underAdorn = t.next() // Grab the section underline

	// Check adornment for proper syntax
	if title.Length != underAdorn.Length {
		t.errorf("Section under line  not equal to title length!")
	} else if overline && title.Length != overAdorn.Length {
		t.errorf("Section over line not equal to title length!")
	} else if overline && overAdorn.Text != underAdorn.Text {
		t.errorf("Section title over line does not match section title under line.")
	}

	// Check section levels to make sure the order of sections seen has not been violated
	if level := t.sectionLevels.Find(rune(underAdorn.Text.(string)[0])); level > 0 {
		if t.sectionLevel == t.sectionLevels.Level() {
			t.sectionLevel++
		} else {
			// The current section level of the parser does not match the previously
			// found section level. This means the user has used incorrect section
			// syntax.
			t.errorf("Incorrect section adornment \"%q\" for section level %d",
				underAdorn.Text.(string)[0], t.sectionLevel)
		}
	} else {
		t.sectionLevel++
	}

	t.sectionLevels.Add(rune(underAdorn.Text.(string)[0]), overline, len(underAdorn.Text.(string)))
	ret := newSection(title, &t.id, t.sectionLevel, overAdorn, underAdorn)

	log.Debugln("End")
	return ret
}
<commit_msg>parse.go: Remove sectionLevel struct<commit_after>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

package parse

import (
	"fmt"
	"github.com/demizer/go-elog"
	"reflect"
)

type systemMessageLevel int

const (
	levelInfo systemMessageLevel = iota
	levelWarning
	levelError
	levelSevere
)

var systemMessageLevels = [...]string{
	"INFO",
	"WARNING",
	"ERROR",
	"SEVERE",
}

func (s systemMessageLevel) String() string {
	return systemMessageLevels[s]
}

type systemMessage struct {
	level  systemMessageLevel
	line   int
	source string
	items  []item
}

type sectionLevels []*SectionNode

func (s *sectionLevels) String() string {
	var out string
	for lvl, sec := range *s {
		out += fmt.Sprintf("level: %d, rune: %q, overline: %t, length: %d\n",
			lvl+1, sec.char, sec.overline, sec.length)
	}
	return out
}

func (s *sectionLevels) Add(adornChar rune, overline bool, length int) int {
	lvl := s.Find(adornChar)
	if lvl > 0 {
		return lvl
	}
	*s = append(*s, sectionLevel{char: adornChar, overline: overline, length: length})
	return len(*s)
}

// Returns -1 if not found
func (s *sectionLevels) Find(adornChar rune) int {
	for lvl, sec := range *s {
		if sec.char == adornChar {
			return lvl + 1
		}
	}
	return -1
}

func (s *sectionLevels) Level() int {
	return len(*s)
}

// Parse is the entry point for the reStructuredText parser.
func Parse(name, text string) (t *Tree, errors []error) {
	t = New(name)
	t.text = text
	_, errors = t.Parse(text, t)
	return
}

func New(name string) *Tree {
	return &Tree{Name: name, sectionLevels: new(sectionLevels)}
}

type Tree struct {
	Name          string
	Nodes         *NodeList // The root node list
	Errors        []error
	text          string
	lex           *lexer
	peekCount     int
	token         [3]item        // three-token look-ahead for parser.
	sectionLevel  int            // The current section level of parsing
	sectionLevels *sectionLevels // Encountered section levels
	id            int            // The unique id of the node in the tree
}

func (t *Tree) errorf(format string, args ...interface{}) {
	format = fmt.Sprintf("go-rst: %s:%d: %s\n", t.Name, t.lex.lineNumber(), format)
	t.Errors = append(t.Errors, fmt.Errorf(format, args...))
}

func (t *Tree) error(err error) {
	t.errorf("%s\n", err)
}

// startParse initializes the parser, using the lexer.
func (t *Tree) startParse(lex *lexer) {
	t.Nodes = nil
	t.lex = lex
}

// stopParse terminates parsing.
func (t *Tree) stopParse() {
	t.lex = nil
}

func (t *Tree) Parse(text string, treeSet *Tree) (tree *Tree, errors []error) {
	log.Debugln("Start")
	t.startParse(lex(t.Name, text))
	t.text = text
	t.parse(treeSet)
	log.Debugln("End")
	return t, t.Errors
}

func (t *Tree) parse(tree *Tree) {
	log.Debugln("Start")

	t.Nodes = newList()

	nodeBranch := t.Nodes

	for t.peek().Type != itemEOF {
		var n Node
		token := t.next()
		log.Debugf("Got token: %#+v\n", token)
		switch token.Type {
		case itemTitle: // Section includes overline/underline
			n = t.section(token)
			log.Infof("New Node: %#+v\n", n)
		case itemBlankLine:
			n = newBlankLine(token, &t.id)
			log.Infof("New Node: %#+v\n", n)
		case itemParagraph:
			n = newParagraph(token, &t.id)
			log.Infof("New Node: %#+v\n", n)
		default:
			t.errorf("%q Not implemented!", token.Type)
			continue
		}

		nodeBranch.append(n)
		if n.NodeType() == NodeSection {
			nodeBranch =
			reflect.ValueOf(n).Elem().FieldByName("NodeList").Addr().Interface().(*NodeList)
		}
	}

	log.Debugln("End")
}

func (t *Tree) backup() {
	t.peekCount++
}

// peekBack returns the last item sent from the lexer.
func (t *Tree) peekBack() item {
	return *t.lex.lastItem
}

// peek returns but does not consume the next token.
func (t *Tree) peek() item {
	if t.peekCount > 0 {
		return t.token[t.peekCount-1]

	}
	t.peekCount = 1
	t.token[0] = t.lex.nextItem()
	return t.token[0]
}

func (t *Tree) next() item {
	if t.peekCount > 0 {
		t.peekCount--
	} else {
		t.token[0] = t.lex.nextItem()
	}
	return t.token[t.peekCount]
}

func (t *Tree) section(i item) Node {
	log.Debugln("Start")
	var overAdorn, title, underAdorn item
	var overline bool

	if t.peekBack().Type == itemSectionAdornment {
		overline = true
		overAdorn = t.peekBack()
	}

	title = i
	underAdorn = t.next() // Grab the section underline

	// Check adornment for proper syntax
	if title.Length != underAdorn.Length {
		t.errorf("Section under line  not equal to title length!")
	} else if overline && title.Length != overAdorn.Length {
		t.errorf("Section over line not equal to title length!")
	} else if overline && overAdorn.Text != underAdorn.Text {
		t.errorf("Section title over line does not match section title under line.")
	}

	// Check section levels to make sure the order of sections seen has not been violated
	if level := t.sectionLevels.Find(rune(underAdorn.Text.(string)[0])); level > 0 {
		if t.sectionLevel == t.sectionLevels.Level() {
			t.sectionLevel++
		} else {
			// The current section level of the parser does not match the previously
			// found section level. This means the user has used incorrect section
			// syntax.
			t.errorf("Incorrect section adornment \"%q\" for section level %d",
				underAdorn.Text.(string)[0], t.sectionLevel)
		}
	} else {
		t.sectionLevel++
	}

	t.sectionLevels.Add(rune(underAdorn.Text.(string)[0]), overline, len(underAdorn.Text.(string)))
	ret := newSection(title, &t.id, t.sectionLevel, overAdorn, underAdorn)

	log.Debugln("End")
	return ret
}
<|endoftext|>


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

package environment

import (
	"github.com/jkellerer/jenkins-client-launcher/launcher/util"
	"github.com/jkellerer/jenkins-client-launcher/launcher/modes"
	"fmt"
	"encoding/xml"
	"time"
)

const (
	NodeMonitoringURI = "computer/%s/api/xml"
)

// The interval when the jenkins node is monitored.
var nodeMonitoringInterval = time.Minute * 2

// The max number of offline results in a row until a reconnect is forced.
var maxOfflineCountBeforeRestart = int16(2)

type JenkinsNodeStatus struct {
	XMLName              xml.Name  `xml:"slaveComputer"`
	DisplayName          string `xml:"displayName"`
	Idle                 bool `xml:"idle"`
	Offline              bool `xml:"offline"`
	TemporarilyOffline   bool `xml:"temporarilyOffline"`
}

// Returns the current offline and idle status of this Jenkins node from the Jenkins server.
func GetJenkinsNodeStatus(config *util.Config) (*JenkinsNodeStatus, error) {
	response, err := config.CIGet(fmt.Sprintf(NodeMonitoringURI, config.ClientName))
	if err == nil && response.StatusCode == 200 {
		defer response.Body.Close()
		status := &JenkinsNodeStatus{}
		err = xml.NewDecoder(response.Body).Decode(status)
		return status, err
	} else {
		if err == nil && response != nil {
			err = fmt.Errorf(response.Status)
		}
		return nil, err
	}
}

// Implements a monitor that issues a rest call on jenkins to see whether the node is online within jenkins.
type JenkinsNodeMonitor struct {
	ticker *time.Ticker
	onlineShown  bool
	offlineCount int16
}

func (self *JenkinsNodeMonitor) IsConfigAcceptable(config *util.Config) (bool) {
	if config.ClientMonitorStateOnServer && !config.HasCIConnection() {
		util.GOut("monitor", "No Jenkins URI defined. Cannot monitor this node within Jenkins.");
		return false;
	}
	return true;
}

func (self *JenkinsNodeMonitor) Name() string {
	return "Jenkins Node Monitor"
}

func (self *JenkinsNodeMonitor) Prepare(config *util.Config) {
	if self.ticker != nil {
		self.ticker.Stop()
	}

	if config.ClientMonitorStateOnServer {
		maxOfflineCountBeforeRestart = config.ClientMonitorStateOnServerMaxFailures

		self.ticker = time.NewTicker(nodeMonitoringInterval)

		go func() {
			// Run in schedule
			for _ = range self.ticker.C {
				self.monitor(config)
			}
		}()
	}
}

// Checks if both, this side and the remote side show the node as connected and increments a offline count if not.
// Forces a restart of the connector when offline count reaches the threshold.
func (self *JenkinsNodeMonitor) monitor(config *util.Config) {
	if self.isThisSideConnected(config) {
		if self.isServerSideConnected(config) {
			self.offlineCount = 0

			if !self.onlineShown {
				util.GOut("monitor", "Node is online in Jenkins.")
				self.onlineShown = true
			}
		} else {
			self.offlineCount++

			if self.offlineCount == maxOfflineCountBeforeRestart {
				self.forceReconnect(config)
			}

			util.GOut("monitor", "Node is OFFLINE in Jenkins.")
			self.onlineShown = false
		}
	} else {
		self.offlineCount = 0

		self.onlineShown = false
	}
}

// Checks if the run mode is in started state.
func (self *JenkinsNodeMonitor) isThisSideConnected(config *util.Config) bool {
	return modes.GetConfiguredMode(config).Status().Get() == modes.ModeStarted
}

// Checks if Jenkins shows this node as connected.
// Also updates the global "util.NodeIsIdle" state.
func (self *JenkinsNodeMonitor) isServerSideConnected(config *util.Config) bool {
	if status, err := GetJenkinsNodeStatus(config); err == nil {
		util.NodeIsIdle.Set(status.Idle)
		return !status.Offline
	} else {
		util.GOut("monitor", "Failed to monitor node %v using %v. Cause: %v", config.ClientName, config.CIHostURI, err)
		return false
	}
}

// Forces a reconnect with Jenkins by stopping the current mode.
func (self *JenkinsNodeMonitor) forceReconnect(config *util.Config) {
	if self.isThisSideConnected(config) {
		util.GOut("monitor", "This node appears dead in Jenkins, forcing a reconnect.")
		modes.GetConfiguredMode(config).Stop()
	}
}

// Registering the monitor.
var _ = RegisterPreparer(new(JenkinsNodeMonitor))
<commit_msg>Fix/Monitor: Monitor was no longer triggering restarts when the last restart failed.<commit_after>// Copyright 2014 The jenkins-client-launcher Authors. All rights reserved.
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.

package environment

import (
	"github.com/jkellerer/jenkins-client-launcher/launcher/util"
	"github.com/jkellerer/jenkins-client-launcher/launcher/modes"
	"fmt"
	"encoding/xml"
	"time"
)

const (
	NodeMonitoringURI = "computer/%s/api/xml"
)

// The interval when the jenkins node is monitored.
var nodeMonitoringInterval = time.Minute * 2

// The max number of offline results in a row until a reconnect is forced.
var maxOfflineCountBeforeRestart = int16(2)

type JenkinsNodeStatus struct {
	XMLName              xml.Name  `xml:"slaveComputer"`
	DisplayName          string `xml:"displayName"`
	Idle                 bool `xml:"idle"`
	Offline              bool `xml:"offline"`
	TemporarilyOffline   bool `xml:"temporarilyOffline"`
}

// Returns the current offline and idle status of this Jenkins node from the Jenkins server.
func GetJenkinsNodeStatus(config *util.Config) (*JenkinsNodeStatus, error) {
	response, err := config.CIGet(fmt.Sprintf(NodeMonitoringURI, config.ClientName))
	if err == nil && response.StatusCode == 200 {
		defer response.Body.Close()
		status := &JenkinsNodeStatus{}
		err = xml.NewDecoder(response.Body).Decode(status)
		return status, err
	} else {
		if err == nil && response != nil {
			err = fmt.Errorf(response.Status)
		}
		return nil, err
	}
}

// Implements a monitor that issues a rest call on jenkins to see whether the node is online within jenkins.
type JenkinsNodeMonitor struct {
	ticker *time.Ticker
	onlineShown  bool
	offlineCount int16
}

func (self *JenkinsNodeMonitor) IsConfigAcceptable(config *util.Config) (bool) {
	if config.ClientMonitorStateOnServer && !config.HasCIConnection() {
		util.GOut("monitor", "No Jenkins URI defined. Cannot monitor this node within Jenkins.");
		return false;
	}
	return true;
}

func (self *JenkinsNodeMonitor) Name() string {
	return "Jenkins Node Monitor"
}

func (self *JenkinsNodeMonitor) Prepare(config *util.Config) {
	if self.ticker != nil {
		self.ticker.Stop()
	}

	if config.ClientMonitorStateOnServer {
		maxOfflineCountBeforeRestart = config.ClientMonitorStateOnServerMaxFailures

		self.ticker = time.NewTicker(nodeMonitoringInterval)

		go func() {
			// Run in schedule
			for _ = range self.ticker.C {
				self.monitor(config)
			}
		}()
	}
}

// Checks if both, this side and the remote side show the node as connected and increments a offline count if not.
// Forces a restart of the connector when offline count reaches the threshold.
func (self *JenkinsNodeMonitor) monitor(config *util.Config) {
	if self.isThisSideConnected(config) {
		if self.isServerSideConnected(config) {
			self.offlineCount = 0

			if !self.onlineShown {
				util.GOut("monitor", "Node is online in Jenkins.")
				self.onlineShown = true
			}
		} else {
			self.offlineCount++

			if self.offlineCount > 3 * maxOfflineCountBeforeRestart {
				self.offlineCount = maxOfflineCountBeforeRestart
			}

			if self.offlineCount == maxOfflineCountBeforeRestart {
				self.forceReconnect(config)
			}

			util.GOut("monitor", "Node is OFFLINE in Jenkins.")
			self.onlineShown = false
		}
	} else {
		self.offlineCount = 0

		self.onlineShown = false
	}
}

// Checks if the run mode is in started state.
func (self *JenkinsNodeMonitor) isThisSideConnected(config *util.Config) bool {
	return modes.GetConfiguredMode(config).Status().Get() == modes.ModeStarted
}

// Checks if Jenkins shows this node as connected.
// Also updates the global "util.NodeIsIdle" state.
func (self *JenkinsNodeMonitor) isServerSideConnected(config *util.Config) bool {
	if status, err := GetJenkinsNodeStatus(config); err == nil {
		util.NodeIsIdle.Set(status.Idle)
		return !status.Offline
	} else {
		util.GOut("monitor", "Failed to monitor node %v using %v. Cause: %v", config.ClientName, config.CIHostURI, err)
		return false
	}
}

// Forces a reconnect with Jenkins by stopping the current mode.
func (self *JenkinsNodeMonitor) forceReconnect(config *util.Config) {
	if self.isThisSideConnected(config) {
		util.GOut("monitor", "This node appears dead in Jenkins, forcing a reconnect.")
		modes.GetConfiguredMode(config).Stop()
	}
}

// Registering the monitor.
var _ = RegisterPreparer(new(JenkinsNodeMonitor))
<|endoftext|>


<commit_before>package flash

import "strings"

type leaf struct {
	route *Route
	param string
	leafs leafs
}

type leafs map[string]*leaf

type match struct {
	route  *Route
	params map[string]string
}

func (l *leaf) match(s string) match {
	parts := strings.Split(strings.Trim(s, "/"), "/")
	res := match{params: make(map[string]string)}

	for _, k := range parts {
		p, ok := l.leafs[k]
		if !ok {
			p, ok = l.leafs["*"]
			if !ok {
				break
			}
			res.params[p.param] = k
		}
		l = p
	}

	res.route = l.route

	return res
}

func (l *leaf) assign(r *Route, path string, params ...string) {
	parts := strings.Split(strings.Trim(path, "/"), "/")
	curPath := l
	for k := range parts {
		v := parts[k]
		n := ""
		// check if part is a template
		if parts[k] != "" {
			if parts[k][0] == ':' {
				v = "*"
				n = parts[k][1:]
			}
		}
		_, ok := curPath.leafs[v]
		if !ok {
			curPath.leafs[v] = &leaf{
				param: n,
				leafs: leafs{},
			}
		}
		curPath = curPath.leafs[v]
	}
	curPath.route = r

	cp := curPath
	for _, v := range params {
		cp.leafs["*"] = &leaf{
			param: v,
			route: r,
			leafs: leafs{},
		}
		cp = cp.leafs["*"]
	}
}
<commit_msg>adding comments<commit_after>package flash

import "strings"

// leaf contains part of route
type leaf struct {
	route *Route
	param string
	leafs leafs
}

type leafs map[string]*leaf

type match struct {
	route  *Route
	params map[string]string
}

// match returns route if found and route params
func (l *leaf) match(s string) match {
	parts := strings.Split(strings.Trim(s, "/"), "/")
	res := match{params: make(map[string]string)}

	for _, k := range parts {
		p, ok := l.leafs[k]
		if !ok {
			p, ok = l.leafs["*"]
			if !ok {
				break
			}
			res.params[p.param] = k
		}
		l = p
	}

	res.route = l.route

	return res
}

// assign creating route structure
func (l *leaf) assign(r *Route, path string, params ...string) {
	parts := strings.Split(strings.Trim(path, "/"), "/")
	curPath := l
	for k := range parts {
		v := parts[k]
		n := ""
		// check if part is a template
		if parts[k] != "" {
			if parts[k][0] == ':' {
				v = "*"
				n = parts[k][1:]
			}
		}
		_, ok := curPath.leafs[v]
		if !ok {
			curPath.leafs[v] = &leaf{
				param: n,
				leafs: leafs{},
			}
		}
		curPath = curPath.leafs[v]
	}
	curPath.route = r

	cp := curPath
	for _, v := range params {
		cp.leafs["*"] = &leaf{
			param: v,
			route: r,
			leafs: leafs{},
		}
		cp = cp.leafs["*"]
	}
}
<|endoftext|>