<commit_before>package annotate

import (
	// ensure all the ginkgo tests are loaded
	_ "k8s.io/kubernetes/openshift-hack/e2e"
)

var (
	TestMaps = map[string][]string{
		// alpha features that are not gated
		"[Disabled:Alpha]": {
			// ALPHA features in 1.20, disabled by default.
			// !!! Review their status as part of the 1.21 rebase.
			`\[Feature:CSIServiceAccountToken\]`,

			// BETA features in 1.20, enabled by default
			// Their enablement is tracked via bz's targeted at 4.8.
			`\[Feature:SCTPConnectivity\]`, // https://bugzilla.redhat.com/show_bug.cgi?id=1861606
		},
		// tests for features that are not implemented in openshift
		"[Disabled:Unimplemented]": {
			`\[Feature:Networking-IPv6\]`, // openshift-sdn doesn't support yet
			`Monitoring`,                  // Not installed, should be
			`Cluster level logging`,       // Not installed yet
			`Kibana`,                      // Not installed
			`Ubernetes`,                   // Can't set zone labels today
			`kube-ui`,                     // Not installed by default
			`Kubernetes Dashboard`,        // Not installed by default (also probably slow image pull)
			`should proxy to cadvisor`,    // we don't expose cAdvisor port directly for security reasons
		},
		// tests that rely on special configuration that we do not yet support
		"[Disabled:SpecialConfig]": {
			// GPU node needs to be available
			`\[Feature:GPUDevicePlugin\]`,
			`\[sig-scheduling\] GPUDevicePluginAcrossRecreate \[Feature:Recreate\]`,

			`\[Feature:ImageQuota\]`,                    // Quota isn't turned on by default, we should do that and then reenable these tests
			`\[Feature:Audit\]`,                         // Needs special configuration
			`\[Feature:LocalStorageCapacityIsolation\]`, // relies on a separate daemonset?
			`\[sig-cloud-provider-gcp\]`,                // these test require a different configuration - note that GCE tests from the sig-cluster-lifecycle were moved to the sig-cloud-provider-gcpcluster lifecycle see https://github.com/kubernetes/kubernetes/commit/0b3d50b6dccdc4bbd0b3e411c648b092477d79ac#diff-3b1910d08fb8fd8b32956b5e264f87cb

			`kube-dns-autoscaler`, // Don't run kube-dns
			`should check if Kubernetes master services is included in cluster-info`, // Don't run kube-dns
			`DNS configMap`, // this tests dns federation configuration via configmap, which we don't support yet

			`NodeProblemDetector`,                   // requires a non-master node to run on
			`Advanced Audit should audit API calls`, // expects to be able to call /logs

			`Firewall rule should have correct firewall rules for e2e cluster`, // Upstream-install specific
		},
		// tests that are known broken and need to be fixed upstream or in openshift
		// always add an issue here
		"[Disabled:Broken]": {
			`mount an API token into pods`,                              // We add 6 secrets, not 1
			`ServiceAccounts should ensure a single API token exists`,   // We create lots of secrets
			`unchanging, static URL paths for kubernetes api services`,  // the test needs to exclude URLs that are not part of conformance (/logs)
			`Services should be able to up and down services`,           // we don't have wget installed on nodes
			`KubeProxy should set TCP CLOSE_WAIT timeout`,               // the test require communication to port 11302 in the cluster nodes
			`\[NodeFeature:Sysctls\]`,                                   // needs SCC support
			`should check kube-proxy urls`,                              // previously this test was skipped b/c we reported -1 as the number of nodes, now we report proper number and test fails
			`SSH`,                                                       // TRIAGE
			`should implement service.kubernetes.io/service-proxy-name`, // this is an optional test that requires SSH. sig-network
			`recreate nodes and ensure they function upon restart`,      // https://bugzilla.redhat.com/show_bug.cgi?id=1756428
			`\[Driver: iscsi\]`,                                         // https://bugzilla.redhat.com/show_bug.cgi?id=1711627

			"RuntimeClass should reject",

			`Services should implement service.kubernetes.io/headless`,       // requires SSH access to function, needs to be refactored
			`ClusterDns \[Feature:Example\] should create pod that uses dns`, // doesn't use bindata, not part of kube test binary
			`Simple pod should handle in-cluster config`,                     // kubectl cp doesn't work or is not preserving executable bit, we have this test already

			// TODO(node): configure the cri handler for the runtime class to make this work
			"should run a Pod requesting a RuntimeClass with a configured handler",
			"should reject a Pod requesting a RuntimeClass with conflicting node selector",
			"should run a Pod requesting a RuntimeClass with scheduling",

			// A fix is in progress: https://github.com/openshift/origin/pull/24709
			`Multi-AZ Clusters should spread the pods of a replication controller across zones`,

			// Upstream assumes all control plane pods are in kube-system namespace and we should revert the change
			// https://github.com/kubernetes/kubernetes/commit/176c8e219f4c7b4c15d34b92c50bfa5ba02b3aba#diff-28a3131f96324063dd53e17270d435a3b0b3bd8f806ee0e33295929570eab209R78
			"MetricsGrabber should grab all metrics from a Kubelet",
			"MetricsGrabber should grab all metrics from API server",
			"MetricsGrabber should grab all metrics from a ControllerManager",
			"MetricsGrabber should grab all metrics from a Scheduler",

			// https://bugzilla.redhat.com/show_bug.cgi?id=1906808
			`ServiceAccounts should support OIDC discovery of service account issuer`,
		},
		// tests that may work, but we don't support them
		"[Disabled:Unsupported]": {
			`\[Driver: rbd\]`,               // OpenShift 4.x does not support Ceph RBD (use CSI instead)
			`\[Driver: ceph\]`,              // OpenShift 4.x does not support CephFS (use CSI instead)
			`\[Feature:PodSecurityPolicy\]`, // OpenShift 4.x does not enable PSP by default
		},
		// tests too slow to be part of conformance
		"[Slow]": {
			`\[sig-scalability\]`,                          // disable from the default set for now
			`should create and stop a working application`, // Inordinately slow tests

			`\[Feature:PerformanceDNS\]`, // very slow

			`validates that there exists conflict between pods with same hostPort and protocol but one using 0\.0\.0\.0 hostIP`, // 5m, really?
		},
		// tests that are known flaky
		"[Flaky]": {
			`Job should run a job to completion when tasks sometimes fail and are not locally restarted`, // seems flaky, also may require too many resources
			// TODO(node): test works when run alone, but not in the suite in CI
			`\[Feature:HPA\] Horizontal pod autoscaling \(scale resource: CPU\) \[sig-autoscaling\] ReplicationController light Should scale from 1 pod to 2 pods`,
		},
		// tests that must be run without competition
		"[Serial]": {
			`\[Disruptive\]`,
			`\[Feature:Performance\]`, // requires isolation

			`Service endpoints latency`, // requires low latency
			`Clean up pods on node`,     // schedules up to max pods per node
			`DynamicProvisioner should test that deleting a claim before the volume is provisioned deletes the volume`, // test is very disruptive to other tests

			`Should be able to support the 1\.7 Sample API Server using the current Aggregator`, // down apiservices break other clients today https://bugzilla.redhat.com/show_bug.cgi?id=1623195

			`\[Feature:HPA\] Horizontal pod autoscaling \(scale resource: CPU\) \[sig-autoscaling\] ReplicationController light Should scale from 1 pod to 2 pods`,

			`should prevent Ingress creation if more than 1 IngressClass marked as default`, // https://bugzilla.redhat.com/show_bug.cgi?id=1822286

			`\[sig-network\] IngressClass \[Feature:Ingress\] should set default value on new IngressClass`, //https://bugzilla.redhat.com/show_bug.cgi?id=1833583
		},
		"[Skipped:azure]": {
			"Networking should provide Internet connection for containers", // Azure does not allow ICMP traffic to internet.
		},
		"[Skipped:gce]": {
			// Requires creation of a different compute instance in a different zone and is not compatible with volumeBindingMode of WaitForFirstConsumer which we use in 4.x
			`\[sig-scheduling\] Multi-AZ Cluster Volumes \[sig-storage\] should only be allowed to provision PDs in zones where nodes exist`,

			// The following tests try to ssh directly to a node. None of our nodes have external IPs
			`\[k8s.io\] \[sig-node\] crictl should be able to run crictl on the node`,
			`\[sig-storage\] Flexvolumes should be mountable`,
			`\[sig-storage\] Detaching volumes should not work when mount is in progress`,

			// We are using openshift-sdn to conceal metadata
			`\[sig-auth\] Metadata Concealment should run a check-metadata-concealment job to completion`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1740959
			`\[sig-api-machinery\] AdmissionWebhook should be able to deny pod and configmap creation`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1745720
			`\[sig-storage\] CSI Volumes \[Driver: pd.csi.storage.gke.io\]\[Serial\]`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1749882
			`\[sig-storage\] CSI Volumes CSI Topology test using GCE PD driver \[Serial\]`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1751367
			`gce-localssd-scsi-fs`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1750851
			// should be serial if/when it's re-enabled
			`\[HPA\] Horizontal pod autoscaling \(scale resource: Custom Metrics from Stackdriver\)`,
		},
		"[sig-node]": {
			`\[NodeConformance\]`,
			`NodeLease`,
			`lease API`,
			`\[NodeFeature`,
			`\[NodeAlphaFeature`,
			`Probing container`,
			`Security Context When creating a`,
			`Downward API should create a pod that prints his name and namespace`,
			`Liveness liveness pods should be automatically restarted`,
			`Secret should create a pod that reads a secret`,
			`Pods should delete a collection of pods`,
			`Pods should run through the lifecycle of Pods and PodStatus`,
		},
		"[sig-cluster-lifecycle]": {
			`Feature:ClusterAutoscalerScalability`,
			`recreate nodes and ensure they function`,
		},
		"[sig-arch]": {
			// not run, assigned to arch as catch-all
			`\[Feature:GKELocalSSD\]`,
			`\[Feature:GKENodePool\]`,
		},
		// Tests that don't pass under openshift-sdn.
		// These are skipped explicitly by openshift-hack/test-kubernetes-e2e.sh,
		// but will also be skipped by openshift-tests in jobs that use openshift-sdn.
		"[Skipped:Network/OpenShiftSDN]": {
			`NetworkPolicy.*IPBlock`,    // feature is not supported by openshift-sdn
			`NetworkPolicy.*[Ee]gress`,  // feature is not supported by openshift-sdn
			`NetworkPolicy.*named port`, // feature is not supported by openshift-sdn

			`NetworkPolicy between server and client should support a 'default-deny-all' policy`, // uses egress feature
		},
	}

	// labelExcludes temporarily block tests out of a specific suite
	LabelExcludes = map[string][]string{}

	ExcludedTests = []string{
		`\[Disabled:`,
		`\[Disruptive\]`,
		`\[Skipped\]`,
		`\[Slow\]`,
		`\[Flaky\]`,
		`\[Local\]`,
	}
)
<commit_msg>UPSTREAM: <carry>: Skip "subPath should be able to unmount" NFS test<commit_after>package annotate

import (
	// ensure all the ginkgo tests are loaded
	_ "k8s.io/kubernetes/openshift-hack/e2e"
)

var (
	TestMaps = map[string][]string{
		// alpha features that are not gated
		"[Disabled:Alpha]": {
			// ALPHA features in 1.20, disabled by default.
			// !!! Review their status as part of the 1.21 rebase.
			`\[Feature:CSIServiceAccountToken\]`,

			// BETA features in 1.20, enabled by default
			// Their enablement is tracked via bz's targeted at 4.8.
			`\[Feature:SCTPConnectivity\]`, // https://bugzilla.redhat.com/show_bug.cgi?id=1861606
		},
		// tests for features that are not implemented in openshift
		"[Disabled:Unimplemented]": {
			`\[Feature:Networking-IPv6\]`, // openshift-sdn doesn't support yet
			`Monitoring`,                  // Not installed, should be
			`Cluster level logging`,       // Not installed yet
			`Kibana`,                      // Not installed
			`Ubernetes`,                   // Can't set zone labels today
			`kube-ui`,                     // Not installed by default
			`Kubernetes Dashboard`,        // Not installed by default (also probably slow image pull)
			`should proxy to cadvisor`,    // we don't expose cAdvisor port directly for security reasons
		},
		// tests that rely on special configuration that we do not yet support
		"[Disabled:SpecialConfig]": {
			// GPU node needs to be available
			`\[Feature:GPUDevicePlugin\]`,
			`\[sig-scheduling\] GPUDevicePluginAcrossRecreate \[Feature:Recreate\]`,

			`\[Feature:ImageQuota\]`,                    // Quota isn't turned on by default, we should do that and then reenable these tests
			`\[Feature:Audit\]`,                         // Needs special configuration
			`\[Feature:LocalStorageCapacityIsolation\]`, // relies on a separate daemonset?
			`\[sig-cloud-provider-gcp\]`,                // these test require a different configuration - note that GCE tests from the sig-cluster-lifecycle were moved to the sig-cloud-provider-gcpcluster lifecycle see https://github.com/kubernetes/kubernetes/commit/0b3d50b6dccdc4bbd0b3e411c648b092477d79ac#diff-3b1910d08fb8fd8b32956b5e264f87cb

			`kube-dns-autoscaler`, // Don't run kube-dns
			`should check if Kubernetes master services is included in cluster-info`, // Don't run kube-dns
			`DNS configMap`, // this tests dns federation configuration via configmap, which we don't support yet

			`NodeProblemDetector`,                   // requires a non-master node to run on
			`Advanced Audit should audit API calls`, // expects to be able to call /logs

			`Firewall rule should have correct firewall rules for e2e cluster`, // Upstream-install specific
		},
		// tests that are known broken and need to be fixed upstream or in openshift
		// always add an issue here
		"[Disabled:Broken]": {
			`mount an API token into pods`,                              // We add 6 secrets, not 1
			`ServiceAccounts should ensure a single API token exists`,   // We create lots of secrets
			`unchanging, static URL paths for kubernetes api services`,  // the test needs to exclude URLs that are not part of conformance (/logs)
			`Services should be able to up and down services`,           // we don't have wget installed on nodes
			`KubeProxy should set TCP CLOSE_WAIT timeout`,               // the test require communication to port 11302 in the cluster nodes
			`\[NodeFeature:Sysctls\]`,                                   // needs SCC support
			`should check kube-proxy urls`,                              // previously this test was skipped b/c we reported -1 as the number of nodes, now we report proper number and test fails
			`SSH`,                                                       // TRIAGE
			`should implement service.kubernetes.io/service-proxy-name`, // this is an optional test that requires SSH. sig-network
			`recreate nodes and ensure they function upon restart`,      // https://bugzilla.redhat.com/show_bug.cgi?id=1756428
			`\[Driver: iscsi\]`,                                         // https://bugzilla.redhat.com/show_bug.cgi?id=1711627

			"RuntimeClass should reject",

			`Services should implement service.kubernetes.io/headless`,       // requires SSH access to function, needs to be refactored
			`ClusterDns \[Feature:Example\] should create pod that uses dns`, // doesn't use bindata, not part of kube test binary
			`Simple pod should handle in-cluster config`,                     // kubectl cp doesn't work or is not preserving executable bit, we have this test already

			// TODO(node): configure the cri handler for the runtime class to make this work
			"should run a Pod requesting a RuntimeClass with a configured handler",
			"should reject a Pod requesting a RuntimeClass with conflicting node selector",
			"should run a Pod requesting a RuntimeClass with scheduling",

			// A fix is in progress: https://github.com/openshift/origin/pull/24709
			`Multi-AZ Clusters should spread the pods of a replication controller across zones`,

			// Upstream assumes all control plane pods are in kube-system namespace and we should revert the change
			// https://github.com/kubernetes/kubernetes/commit/176c8e219f4c7b4c15d34b92c50bfa5ba02b3aba#diff-28a3131f96324063dd53e17270d435a3b0b3bd8f806ee0e33295929570eab209R78
			"MetricsGrabber should grab all metrics from a Kubelet",
			"MetricsGrabber should grab all metrics from API server",
			"MetricsGrabber should grab all metrics from a ControllerManager",
			"MetricsGrabber should grab all metrics from a Scheduler",

			// https://bugzilla.redhat.com/show_bug.cgi?id=1906808
			`ServiceAccounts should support OIDC discovery of service account issuer`,

			// NFS umount is broken in kernels 5.7+
			// https://bugzilla.redhat.com/show_bug.cgi?id=1854379
			`\[sig-storage\].*\[Driver: nfs\] \[Testpattern: Dynamic PV \(default fs\)\].*subPath should be able to unmount after the subpath directory is deleted`,
		},
		// tests that may work, but we don't support them
		"[Disabled:Unsupported]": {
			`\[Driver: rbd\]`,               // OpenShift 4.x does not support Ceph RBD (use CSI instead)
			`\[Driver: ceph\]`,              // OpenShift 4.x does not support CephFS (use CSI instead)
			`\[Feature:PodSecurityPolicy\]`, // OpenShift 4.x does not enable PSP by default
		},
		// tests too slow to be part of conformance
		"[Slow]": {
			`\[sig-scalability\]`,                          // disable from the default set for now
			`should create and stop a working application`, // Inordinately slow tests

			`\[Feature:PerformanceDNS\]`, // very slow

			`validates that there exists conflict between pods with same hostPort and protocol but one using 0\.0\.0\.0 hostIP`, // 5m, really?
		},
		// tests that are known flaky
		"[Flaky]": {
			`Job should run a job to completion when tasks sometimes fail and are not locally restarted`, // seems flaky, also may require too many resources
			// TODO(node): test works when run alone, but not in the suite in CI
			`\[Feature:HPA\] Horizontal pod autoscaling \(scale resource: CPU\) \[sig-autoscaling\] ReplicationController light Should scale from 1 pod to 2 pods`,
		},
		// tests that must be run without competition
		"[Serial]": {
			`\[Disruptive\]`,
			`\[Feature:Performance\]`, // requires isolation

			`Service endpoints latency`, // requires low latency
			`Clean up pods on node`,     // schedules up to max pods per node
			`DynamicProvisioner should test that deleting a claim before the volume is provisioned deletes the volume`, // test is very disruptive to other tests

			`Should be able to support the 1\.7 Sample API Server using the current Aggregator`, // down apiservices break other clients today https://bugzilla.redhat.com/show_bug.cgi?id=1623195

			`\[Feature:HPA\] Horizontal pod autoscaling \(scale resource: CPU\) \[sig-autoscaling\] ReplicationController light Should scale from 1 pod to 2 pods`,

			`should prevent Ingress creation if more than 1 IngressClass marked as default`, // https://bugzilla.redhat.com/show_bug.cgi?id=1822286

			`\[sig-network\] IngressClass \[Feature:Ingress\] should set default value on new IngressClass`, //https://bugzilla.redhat.com/show_bug.cgi?id=1833583
		},
		"[Skipped:azure]": {
			"Networking should provide Internet connection for containers", // Azure does not allow ICMP traffic to internet.
		},
		"[Skipped:gce]": {
			// Requires creation of a different compute instance in a different zone and is not compatible with volumeBindingMode of WaitForFirstConsumer which we use in 4.x
			`\[sig-scheduling\] Multi-AZ Cluster Volumes \[sig-storage\] should only be allowed to provision PDs in zones where nodes exist`,

			// The following tests try to ssh directly to a node. None of our nodes have external IPs
			`\[k8s.io\] \[sig-node\] crictl should be able to run crictl on the node`,
			`\[sig-storage\] Flexvolumes should be mountable`,
			`\[sig-storage\] Detaching volumes should not work when mount is in progress`,

			// We are using openshift-sdn to conceal metadata
			`\[sig-auth\] Metadata Concealment should run a check-metadata-concealment job to completion`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1740959
			`\[sig-api-machinery\] AdmissionWebhook should be able to deny pod and configmap creation`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1745720
			`\[sig-storage\] CSI Volumes \[Driver: pd.csi.storage.gke.io\]\[Serial\]`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1749882
			`\[sig-storage\] CSI Volumes CSI Topology test using GCE PD driver \[Serial\]`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1751367
			`gce-localssd-scsi-fs`,

			// https://bugzilla.redhat.com/show_bug.cgi?id=1750851
			// should be serial if/when it's re-enabled
			`\[HPA\] Horizontal pod autoscaling \(scale resource: Custom Metrics from Stackdriver\)`,
		},
		"[sig-node]": {
			`\[NodeConformance\]`,
			`NodeLease`,
			`lease API`,
			`\[NodeFeature`,
			`\[NodeAlphaFeature`,
			`Probing container`,
			`Security Context When creating a`,
			`Downward API should create a pod that prints his name and namespace`,
			`Liveness liveness pods should be automatically restarted`,
			`Secret should create a pod that reads a secret`,
			`Pods should delete a collection of pods`,
			`Pods should run through the lifecycle of Pods and PodStatus`,
		},
		"[sig-cluster-lifecycle]": {
			`Feature:ClusterAutoscalerScalability`,
			`recreate nodes and ensure they function`,
		},
		"[sig-arch]": {
			// not run, assigned to arch as catch-all
			`\[Feature:GKELocalSSD\]`,
			`\[Feature:GKENodePool\]`,
		},
		// Tests that don't pass under openshift-sdn.
		// These are skipped explicitly by openshift-hack/test-kubernetes-e2e.sh,
		// but will also be skipped by openshift-tests in jobs that use openshift-sdn.
		"[Skipped:Network/OpenShiftSDN]": {
			`NetworkPolicy.*IPBlock`,    // feature is not supported by openshift-sdn
			`NetworkPolicy.*[Ee]gress`,  // feature is not supported by openshift-sdn
			`NetworkPolicy.*named port`, // feature is not supported by openshift-sdn

			`NetworkPolicy between server and client should support a 'default-deny-all' policy`, // uses egress feature
		},
	}

	// labelExcludes temporarily block tests out of a specific suite
	LabelExcludes = map[string][]string{}

	ExcludedTests = []string{
		`\[Disabled:`,
		`\[Disruptive\]`,
		`\[Skipped\]`,
		`\[Slow\]`,
		`\[Flaky\]`,
		`\[Local\]`,
	}
)
<|endoftext|>


<commit_before>// Package notify provides an implementation of the Freedesktop Notifications
// Specification using the DBus API.
package notify

import "github.com/godbus/dbus"

// Notification object paths and interfaces.
const (
	DbusObjectPath               = "/org/freedesktop/Notifications"
	DbusInterfacePath            = "org.freedesktop.Notifications"
	SignalNotificationClosed     = "org.freedesktop.Notifications.NotificationClosed"
	SignalActionInvoked          = "org.freedesktop.Notifications.ActionInvoked"
	CallGetCapabilities          = "org.freedesktop.Notifications.GetCapabilities"
	CallCloseNotification        = "org.freedesktop.Notifications.CloseNotification"
	CallNotify                   = "org.freedesktop.Notifications.Notify"
	CallGetServerInformation     = "org.freedesktop.Notifications.GetServerInformation"
	DbusMemberActionInvoked      = "ActionInvoked"
	DbusMemberNotificationClosed = "NotificationClosed"
)

// Notification expire timeout
const (
	ExpiresDefault = -1
	ExpiresNever   = 0
)

// Notification Categories
const (
	ClassDevice              = "device"
	ClassDeviceAdded         = "device.added"
	ClassDeviceError         = "device.error"
	ClassDeviceRemoved       = "device.removed"
	ClassEmail               = "email"
	ClassEmailArrived        = "email.arrived"
	ClassEmailBounced        = "email.bounced"
	ClassIm                  = "im"
	ClassImError             = "im.error"
	ClassImReceived          = "im.received"
	ClassNetwork             = "network"
	ClassNetworkConnected    = "network.connected"
	ClassNetworkDisconnected = "network.disconnected"
	ClassNetworkError        = "network.error"
	ClassPresence            = "presence"
	ClassPresenceOffline     = "presence.offline"
	ClassPresenceOnline      = "presence.online"
	ClassTransfer            = "transfer"
	ClassTransferComplete    = "transfer.complete"
	ClassTransferError       = "transfer.error"
)

// Urgency Levels
const (
	UrgencyLow      = byte(0)
	UrgencyNormal   = byte(1)
	UrgencyCritical = byte(2)
)

// Hints
const (
	HintActionIcons   = "action-icons"
	HintCategory      = "category"
	HintDesktopEntry  = "desktop-entry"
	HintImageData     = "image-data"
	HintImagePath     = "image-path"
	HintResident      = "resident"
	HintSoundFile     = "sound-file"
	HintSoundName     = "sound-name"
	HintSuppressSound = "suppress-sound"
	HintTransient     = "transient"
	HintX             = "x"
	HintY             = "y"
	HintUrgency       = "urgency"
)

// Capabilities is a struct containing the capabilities of the notification
// server.
type Capabilities struct {
	// Supports using icons instead of text for displaying actions.
	ActionIcons bool

	// The server will provide any specified actions to the user.
	Actions bool

	// Supports body text. Some implementations may only show the summary.
	Body bool

	// The server supports hyperlinks in the notifications.
	BodyHyperlinks bool

	// The server supports images in the notifications.
	BodyImages bool

	// Supports markup in the body text.
	BodyMarkup bool

	// The server will render an animation of all the frames in a given
	// image array.
	IconMulti bool

	// Supports display of exactly 1 frame of any given image array.
	IconStatic bool

	// The server supports persistence of notifications. Notifications will
	// be retained until they are acknowledged or removed by the user or
	// recalled by the sender.
	Persistence bool

	// The server supports sounds on notifications.
	Sound bool
}

// GetCapabilities returns the capabilities of the notification server.
func GetCapabilities() (c Capabilities, err error) {
	conn, err := dbus.SessionBus()
	if err != nil {
		return
	}

	obj := conn.Object(DbusInterfacePath, DbusObjectPath)
	call := obj.Call(CallGetCapabilities, 0)
	if err = call.Err; err != nil {
		return
	}

	s := []string{}
	if err = call.Store(&s); err != nil {
		return
	}

	for _, v := range s {
		switch v {
		case "action-icons":
			c.ActionIcons = true
			break
		case "actions":
			c.Actions = true
			break
		case "body":
			c.Body = true
			break
		case "body-hyperlinks":
			c.BodyHyperlinks = true
			break
		case "body-images":
			c.BodyImages = true
			break
		case "body-markup":
			c.BodyMarkup = true
			break
		case "icon-multi":
			c.IconMulti = true
			break
		case "icon-static":
			c.IconStatic = true
			break
		case "persistence":
			c.Persistence = true
			break
		case "sound":
			c.Sound = true
			break
		}
	}
	return
}

// ServerInformation is a struct containing information about the server such
// as its name and version.
type ServerInformation struct {
	// The name of the notification server daemon
	Name string

	// The vendor of the notification server
	Vendor string

	// Version of the notification server
	Version string

	// Spec version the notification server conforms to
	SpecVersion string
}

// GetServerInformation returns information about the notification server such
// as its name and version.
func GetServerInformation() (i ServerInformation, err error) {
	conn, err := dbus.SessionBus()
	if err != nil {
		return
	}

	obj := conn.Object(DbusInterfacePath, DbusObjectPath)
	call := obj.Call(CallGetServerInformation, 0)
	if err = call.Err; err != nil {
		return
	}

	err = call.Store(&i.Name, &i.Vendor, &i.Version, &i.SpecVersion)
	return
}

// Notification is a struct which describes the notification to be displayed
// by the notification server.
type Notification struct {
	// The optional name of the application sending the notification.
	// Can be blank.
	AppName string

	// The optional notification ID that this notification replaces.
	ReplacesID uint32

	// The optional program icon of the calling application.
	AppIcon string

	// The summary text briefly describing the notification.
	Summary string

	// The optional detailed body text.
	Body string

	// The actions send a request message back to the notification client
	// when invoked.
	Actions []string

	// Hints are a way to provide extra data to a notification server.
	Hints map[string]interface{}

	// The timeout time in milliseconds since the display of the
	// notification at which the notification should automatically close.
	Timeout int32
}

// NewNotification creates a new notification object with some basic
// information.
func NewNotification(summary, body string) Notification {
	return Notification{
		Summary: summary,
		Body:    body,
		Timeout: ExpiresDefault,
	}
}

// Show sends the information in the notification object to the server to be
// displayed.
func (n Notification) Show() (id uint32, err error) {
	conn, err := dbus.SessionBus()
	if err != nil {
		return
	}

	// We need to convert the interface type of the map to dbus.Variant as
	// people dont want to have to import the dbus package just to make use
	// of the notification hints.
	hints := map[string]dbus.Variant{}
	for k, v := range n.Hints {
		hints[k] = dbus.MakeVariant(v)
	}

	obj := conn.Object(DbusInterfacePath, DbusObjectPath)
	call := obj.Call(
		CallNotify,
		0,
		n.AppName,
		n.ReplacesID,
		n.AppIcon,
		n.Summary,
		n.Body,
		n.Actions,
		hints,
		n.Timeout)
	if err = call.Err; err != nil {
		return
	}

	err = call.Store(&id)
	return
}

// CloseNotification closes the notification if it exists using its id.
func CloseNotification(id uint32) (err error) {
	conn, err := dbus.SessionBus()
	if err != nil {
		return
	}

	obj := conn.Object(DbusInterfacePath, DbusObjectPath)
	call := obj.Call(CallCloseNotification, 0, id)
	err = call.Err
	return
}
<commit_msg>Add fullstop.<commit_after>// Package notify provides an implementation of the Freedesktop Notifications
// Specification using the DBus API.
package notify

import "github.com/godbus/dbus"

// Notification object paths and interfaces.
const (
	DbusObjectPath               = "/org/freedesktop/Notifications"
	DbusInterfacePath            = "org.freedesktop.Notifications"
	SignalNotificationClosed     = "org.freedesktop.Notifications.NotificationClosed"
	SignalActionInvoked          = "org.freedesktop.Notifications.ActionInvoked"
	CallGetCapabilities          = "org.freedesktop.Notifications.GetCapabilities"
	CallCloseNotification        = "org.freedesktop.Notifications.CloseNotification"
	CallNotify                   = "org.freedesktop.Notifications.Notify"
	CallGetServerInformation     = "org.freedesktop.Notifications.GetServerInformation"
	DbusMemberActionInvoked      = "ActionInvoked"
	DbusMemberNotificationClosed = "NotificationClosed"
)

// Notification expire timeout.
const (
	ExpiresDefault = -1
	ExpiresNever   = 0
)

// Notification Categories
const (
	ClassDevice              = "device"
	ClassDeviceAdded         = "device.added"
	ClassDeviceError         = "device.error"
	ClassDeviceRemoved       = "device.removed"
	ClassEmail               = "email"
	ClassEmailArrived        = "email.arrived"
	ClassEmailBounced        = "email.bounced"
	ClassIm                  = "im"
	ClassImError             = "im.error"
	ClassImReceived          = "im.received"
	ClassNetwork             = "network"
	ClassNetworkConnected    = "network.connected"
	ClassNetworkDisconnected = "network.disconnected"
	ClassNetworkError        = "network.error"
	ClassPresence            = "presence"
	ClassPresenceOffline     = "presence.offline"
	ClassPresenceOnline      = "presence.online"
	ClassTransfer            = "transfer"
	ClassTransferComplete    = "transfer.complete"
	ClassTransferError       = "transfer.error"
)

// Urgency Levels
const (
	UrgencyLow      = byte(0)
	UrgencyNormal   = byte(1)
	UrgencyCritical = byte(2)
)

// Hints
const (
	HintActionIcons   = "action-icons"
	HintCategory      = "category"
	HintDesktopEntry  = "desktop-entry"
	HintImageData     = "image-data"
	HintImagePath     = "image-path"
	HintResident      = "resident"
	HintSoundFile     = "sound-file"
	HintSoundName     = "sound-name"
	HintSuppressSound = "suppress-sound"
	HintTransient     = "transient"
	HintX             = "x"
	HintY             = "y"
	HintUrgency       = "urgency"
)

// Capabilities is a struct containing the capabilities of the notification
// server.
type Capabilities struct {
	// Supports using icons instead of text for displaying actions.
	ActionIcons bool

	// The server will provide any specified actions to the user.
	Actions bool

	// Supports body text. Some implementations may only show the summary.
	Body bool

	// The server supports hyperlinks in the notifications.
	BodyHyperlinks bool

	// The server supports images in the notifications.
	BodyImages bool

	// Supports markup in the body text.
	BodyMarkup bool

	// The server will render an animation of all the frames in a given
	// image array.
	IconMulti bool

	// Supports display of exactly 1 frame of any given image array.
	IconStatic bool

	// The server supports persistence of notifications. Notifications will
	// be retained until they are acknowledged or removed by the user or
	// recalled by the sender.
	Persistence bool

	// The server supports sounds on notifications.
	Sound bool
}

// GetCapabilities returns the capabilities of the notification server.
func GetCapabilities() (c Capabilities, err error) {
	conn, err := dbus.SessionBus()
	if err != nil {
		return
	}

	obj := conn.Object(DbusInterfacePath, DbusObjectPath)
	call := obj.Call(CallGetCapabilities, 0)
	if err = call.Err; err != nil {
		return
	}

	s := []string{}
	if err = call.Store(&s); err != nil {
		return
	}

	for _, v := range s {
		switch v {
		case "action-icons":
			c.ActionIcons = true
			break
		case "actions":
			c.Actions = true
			break
		case "body":
			c.Body = true
			break
		case "body-hyperlinks":
			c.BodyHyperlinks = true
			break
		case "body-images":
			c.BodyImages = true
			break
		case "body-markup":
			c.BodyMarkup = true
			break
		case "icon-multi":
			c.IconMulti = true
			break
		case "icon-static":
			c.IconStatic = true
			break
		case "persistence":
			c.Persistence = true
			break
		case "sound":
			c.Sound = true
			break
		}
	}
	return
}

// ServerInformation is a struct containing information about the server such
// as its name and version.
type ServerInformation struct {
	// The name of the notification server daemon
	Name string

	// The vendor of the notification server
	Vendor string

	// Version of the notification server
	Version string

	// Spec version the notification server conforms to
	SpecVersion string
}

// GetServerInformation returns information about the notification server such
// as its name and version.
func GetServerInformation() (i ServerInformation, err error) {
	conn, err := dbus.SessionBus()
	if err != nil {
		return
	}

	obj := conn.Object(DbusInterfacePath, DbusObjectPath)
	call := obj.Call(CallGetServerInformation, 0)
	if err = call.Err; err != nil {
		return
	}

	err = call.Store(&i.Name, &i.Vendor, &i.Version, &i.SpecVersion)
	return
}

// Notification is a struct which describes the notification to be displayed
// by the notification server.
type Notification struct {
	// The optional name of the application sending the notification.
	// Can be blank.
	AppName string

	// The optional notification ID that this notification replaces.
	ReplacesID uint32

	// The optional program icon of the calling application.
	AppIcon string

	// The summary text briefly describing the notification.
	Summary string

	// The optional detailed body text.
	Body string

	// The actions send a request message back to the notification client
	// when invoked.
	Actions []string

	// Hints are a way to provide extra data to a notification server.
	Hints map[string]interface{}

	// The timeout time in milliseconds since the display of the
	// notification at which the notification should automatically close.
	Timeout int32
}

// NewNotification creates a new notification object with some basic
// information.
func NewNotification(summary, body string) Notification {
	return Notification{
		Summary: summary,
		Body:    body,
		Timeout: ExpiresDefault,
	}
}

// Show sends the information in the notification object to the server to be
// displayed.
func (n Notification) Show() (id uint32, err error) {
	conn, err := dbus.SessionBus()
	if err != nil {
		return
	}

	// We need to convert the interface type of the map to dbus.Variant as
	// people dont want to have to import the dbus package just to make use
	// of the notification hints.
	hints := map[string]dbus.Variant{}
	for k, v := range n.Hints {
		hints[k] = dbus.MakeVariant(v)
	}

	obj := conn.Object(DbusInterfacePath, DbusObjectPath)
	call := obj.Call(
		CallNotify,
		0,
		n.AppName,
		n.ReplacesID,
		n.AppIcon,
		n.Summary,
		n.Body,
		n.Actions,
		hints,
		n.Timeout)
	if err = call.Err; err != nil {
		return
	}

	err = call.Store(&id)
	return
}

// CloseNotification closes the notification if it exists using its id.
func CloseNotification(id uint32) (err error) {
	conn, err := dbus.SessionBus()
	if err != nil {
		return
	}

	obj := conn.Object(DbusInterfacePath, DbusObjectPath)
	call := obj.Call(CallCloseNotification, 0, id)
	err = call.Err
	return
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"lib/models"
	"lib/mutualtls"
	"lib/policy_client"
	"math/rand"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/exec"
	"time"

	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"

	"code.cloudfoundry.org/lager"
)

var (
	config               Config
	testDuration         time.Duration
	pollInterval         time.Duration
	externalPolicyClient *policy_client.ExternalClient
	internalPolicyClient *policy_client.InternalClient
)

type Config struct {
	Api                 string `json:"api"`
	Apps                int    `json:"apps"`
	CreateNewPolicies   bool   `json:"create_new_policies"`
	TestDurationMinutes int    `json:"test_duration_minutes"`
	Logs                string `json:"logs"`
	NumCells            int    `json:"num_cells"`
	PoliciesPerApp      int    `json:"policies_per_app"`
	PollIntervalSeconds int    `json:"poll_interval_seconds"`

	ServerCACertFile            string `json:"ca_cert_file" validate:"nonzero"`
	ClientCertFile              string `json:"client_cert_file" validate:"nonzero"`
	ClientKeyFile               string `json:"client_key_file" validate:"nonzero"`
	PolicyServerInternalBaseURL string `json:"policy_server_internal_base_url"`
}

func loadTestConfig(logger lager.Logger) {
	configPath := helpers.ConfigPath()
	configBytes, err := ioutil.ReadFile(configPath)
	if err != nil {
		logger.Fatal("reading-config", err)
	}

	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		logger.Fatal("unmarshalling-config", err)
	}

	if config.Api == "" {
		logger.Fatal("reading-api-from-config", errors.New("API not specified in config"))
	}

	testDuration = time.Duration(config.TestDurationMinutes) * time.Minute
	pollInterval = time.Duration(config.PollIntervalSeconds) * time.Second
}

func getInternalPolicyClient(logger lager.Logger) *policy_client.InternalClient {
	clientTLSConfig, err := mutualtls.NewClientTLSConfig(config.ClientCertFile, config.ClientKeyFile, config.ServerCACertFile)
	if err != nil {
		logger.Fatal("mutual-tls", err)
	}
	clientTLSConfig.InsecureSkipVerify = true

	httpClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: clientTLSConfig,
		},
	}

	return policy_client.NewInternal(logger.Session("internal-policy-client"), httpClient, config.PolicyServerInternalBaseURL)
}

func getExternalPolicyClient(logger lager.Logger) *policy_client.ExternalClient {
	httpClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	policyServerAPI := fmt.Sprintf("https://%s", config.Api)
	return policy_client.NewExternal(logger.Session("external-policy-client"), httpClient, policyServerAPI)
}

func randomAppGUID(index int) string {
	return fmt.Sprintf("%08x", rand.Int63())
}

func addNewPolicies(logger lager.Logger, appGuids []string, token string) {
	logger.Info("creating-policies-for-each-application-guid")
	policies := []models.Policy{}
	for _ = range appGuids {
		for i := 0; i < config.PoliciesPerApp; i++ {
			dstGuid := appGuids[rand.Intn(len(appGuids))]
			srcGuid := appGuids[rand.Intn(len(appGuids))]

			policy := models.Policy{
				Source: models.Source{
					ID: srcGuid,
				},
				Destination: models.Destination{
					ID:       dstGuid,
					Protocol: "tcp",
					Port:     10000 + rand.Intn(10000),
				},
			}
			policies = append(policies, policy)
		}
	}

	logger.Info("adding-policies")
	err := externalPolicyClient.AddPolicies(token, policies)
	if err != nil {
		logger.Fatal("adding-policies", err)
	}
	logger.Info("finished-adding-policies-to-policy-server")
}

func getPoliciesForCell(logger lager.Logger, ids []string, index, numCalls int) {
	logger.Info("getting-policies-by-id", lager.Data{
		"index":    index,
		"numCalls": numCalls,
	})

	_, err := internalPolicyClient.GetPoliciesByID(ids...)
	if err != nil {
		logger.Fatal("getting-policies-by-id", err)
	} else {
		logger.Info(fmt.Sprintf("finished-request-from-cell-#%d-on-call-#%d", index, numCalls))
	}
}

func deleteOldPolicies(logger lager.Logger, token string) {
	logger.Info("getting-existing-policies")
	policies, err := externalPolicyClient.GetPolicies(token)
	if err != nil {
		logger.Fatal("get-policies", err)
	}
	logger.Info("number-of-existing-policies", lager.Data{"num-existing-policies": len(policies)})

	logger.Info("deleting-existing-policies")
	err = externalPolicyClient.DeletePolicies(token, policies)
	if err != nil {
		logger.Fatal("deleting-policies", err)
	}

	logger.Info("deleted-existing-policies")
}

func jitter(baseTime time.Duration, jitterAmount time.Duration) time.Duration {
	x := rand.Int63n(int64(jitterAmount)*2) - int64(jitterAmount)
	return baseTime + time.Duration(x)
}

func pollPolicyServer(logger lager.Logger, ids []string, index int) {
	numCalls := 0
	for {
		select {
		case <-time.After(jitter(pollInterval, 1*time.Second)):
			go getPoliciesForCell(logger, ids, index, numCalls)
			numCalls = numCalls + 1
			continue
		}
	}
}

func getCurrentToken(logger lager.Logger) string {
	cmd := exec.Command("cf", "oauth-token")

	tokenBytes, err := cmd.Output()
	if err != nil {
		logger.Fatal("running-command-cf-oauth-token`", err)
	}

	token := string(tokenBytes[0 : len(tokenBytes)-1]) // remove trailing \n
	logger.Info("parsed-cf-oauth-token", lager.Data{"token": token})

	return token
}

func main() {
	logger := lager.NewLogger("cf-networking.policy-server-test")

	loadTestConfig(logger)

	file, err := os.OpenFile(config.Logs, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		logger.Fatal("writing-to-log-file", err)
	}
	logger.RegisterSink(lager.NewWriterSink(file, lager.INFO))
	logger.Info("started")
	defer logger.Info("exited")

	token := getCurrentToken(logger)

	logger.Info("creating-application-guids")
	rand.Seed(1) // always use the same random sequence
	var guids []string
	for i := 0; i < config.Apps; i++ {
		guids = append(guids, randomAppGUID(i))
	}
	logger.Info(fmt.Sprintf("finished-creating-%d-application-guids", config.Apps))

	internalPolicyClient = getInternalPolicyClient(logger)
	externalPolicyClient = getExternalPolicyClient(logger)

	if config.CreateNewPolicies {
		deleteOldPolicies(logger, token)
		token = getCurrentToken(logger)
		addNewPolicies(logger, guids, token)
	} else {
		logger.Info("skipped-creating-policies")
	}

	appsPerCell := config.Apps / config.NumCells
	var cells [][]string
	for i := 0; i < config.NumCells; i++ {
		cells = append(cells, guids[i*appsPerCell:(i+1)*appsPerCell])
	}

	for i := 0; i < len(cells); i++ {
		go func(i int) {
			logger.Info(fmt.Sprintf("cell-%d-polling-policy-server", i))
			pollPolicyServer(logger, cells[i], i)
		}(i)
	}

	fmt.Println("Press CTRL-C to exit")
	select {
	case <-time.After(testDuration):
		logger.Info(fmt.Sprintf("exiting"))
		os.Exit(0)
	}
}
<commit_msg>policy server perf tester has client-side http timeout on internal api<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"lib/models"
	"lib/mutualtls"
	"lib/policy_client"
	"math/rand"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/exec"
	"time"

	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"

	"code.cloudfoundry.org/lager"
)

var (
	config               Config
	testDuration         time.Duration
	pollInterval         time.Duration
	externalPolicyClient *policy_client.ExternalClient
	internalPolicyClient *policy_client.InternalClient
)

type Config struct {
	Api                 string `json:"api"`
	Apps                int    `json:"apps"`
	CreateNewPolicies   bool   `json:"create_new_policies"`
	TestDurationMinutes int    `json:"test_duration_minutes"`
	Logs                string `json:"logs"`
	NumCells            int    `json:"num_cells"`
	PoliciesPerApp      int    `json:"policies_per_app"`
	PollIntervalSeconds int    `json:"poll_interval_seconds"`

	ServerCACertFile            string `json:"ca_cert_file" validate:"nonzero"`
	ClientCertFile              string `json:"client_cert_file" validate:"nonzero"`
	ClientKeyFile               string `json:"client_key_file" validate:"nonzero"`
	PolicyServerInternalBaseURL string `json:"policy_server_internal_base_url"`
}

func loadTestConfig(logger lager.Logger) {
	configPath := helpers.ConfigPath()
	configBytes, err := ioutil.ReadFile(configPath)
	if err != nil {
		logger.Fatal("reading-config", err)
	}

	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		logger.Fatal("unmarshalling-config", err)
	}

	if config.Api == "" {
		logger.Fatal("reading-api-from-config", errors.New("API not specified in config"))
	}

	testDuration = time.Duration(config.TestDurationMinutes) * time.Minute
	pollInterval = time.Duration(config.PollIntervalSeconds) * time.Second
}

func getInternalPolicyClient(logger lager.Logger) *policy_client.InternalClient {
	clientTLSConfig, err := mutualtls.NewClientTLSConfig(config.ClientCertFile, config.ClientKeyFile, config.ServerCACertFile)
	if err != nil {
		logger.Fatal("mutual-tls", err)
	}
	clientTLSConfig.InsecureSkipVerify = true

	httpClient := &http.Client{
		Timeout: pollInterval,
		Transport: &http.Transport{
			TLSClientConfig: clientTLSConfig,
		},
	}

	return policy_client.NewInternal(logger.Session("internal-policy-client"), httpClient, config.PolicyServerInternalBaseURL)
}

func getExternalPolicyClient(logger lager.Logger) *policy_client.ExternalClient {
	httpClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	policyServerAPI := fmt.Sprintf("https://%s", config.Api)
	return policy_client.NewExternal(logger.Session("external-policy-client"), httpClient, policyServerAPI)
}

func randomAppGUID(index int) string {
	return fmt.Sprintf("%08x", rand.Int63())
}

func addNewPolicies(logger lager.Logger, appGuids []string, token string) {
	logger.Info("creating-policies-for-each-application-guid")
	policies := []models.Policy{}
	for _ = range appGuids {
		for i := 0; i < config.PoliciesPerApp; i++ {
			dstGuid := appGuids[rand.Intn(len(appGuids))]
			srcGuid := appGuids[rand.Intn(len(appGuids))]

			policy := models.Policy{
				Source: models.Source{
					ID: srcGuid,
				},
				Destination: models.Destination{
					ID:       dstGuid,
					Protocol: "tcp",
					Port:     10000 + rand.Intn(10000),
				},
			}
			policies = append(policies, policy)
		}
	}

	logger.Info("adding-policies")
	err := externalPolicyClient.AddPolicies(token, policies)
	if err != nil {
		logger.Fatal("adding-policies", err)
	}
	logger.Info("finished-adding-policies-to-policy-server")
}

func getPoliciesForCell(logger lager.Logger, ids []string, index, numCalls int) {
	logger.Info("getting-policies-by-id", lager.Data{
		"index":    index,
		"numCalls": numCalls,
	})

	_, err := internalPolicyClient.GetPoliciesByID(ids...)
	if err != nil {
		logger.Fatal("getting-policies-by-id", err)
	} else {
		logger.Info(fmt.Sprintf("finished-request-from-cell-#%d-on-call-#%d", index, numCalls))
	}
}

func deleteOldPolicies(logger lager.Logger, token string) {
	logger.Info("getting-existing-policies")
	policies, err := externalPolicyClient.GetPolicies(token)
	if err != nil {
		logger.Fatal("get-policies", err)
	}
	logger.Info("number-of-existing-policies", lager.Data{"num-existing-policies": len(policies)})

	logger.Info("deleting-existing-policies")
	err = externalPolicyClient.DeletePolicies(token, policies)
	if err != nil {
		logger.Fatal("deleting-policies", err)
	}

	logger.Info("deleted-existing-policies")
}

func jitter(baseTime time.Duration, jitterAmount time.Duration) time.Duration {
	x := rand.Int63n(int64(jitterAmount)*2) - int64(jitterAmount)
	return baseTime + time.Duration(x)
}

func pollPolicyServer(logger lager.Logger, ids []string, index int) {
	numCalls := 0
	for {
		select {
		case <-time.After(jitter(pollInterval, 1*time.Second)):
			go getPoliciesForCell(logger, ids, index, numCalls)
			numCalls = numCalls + 1
			continue
		}
	}
}

func getCurrentToken(logger lager.Logger) string {
	cmd := exec.Command("cf", "oauth-token")

	tokenBytes, err := cmd.Output()
	if err != nil {
		logger.Fatal("running-command-cf-oauth-token`", err)
	}

	token := string(tokenBytes[0 : len(tokenBytes)-1]) // remove trailing \n
	logger.Info("parsed-cf-oauth-token", lager.Data{"token": token})

	return token
}

func main() {
	logger := lager.NewLogger("cf-networking.policy-server-test")

	loadTestConfig(logger)

	file, err := os.OpenFile(config.Logs, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		logger.Fatal("writing-to-log-file", err)
	}
	logger.RegisterSink(lager.NewWriterSink(file, lager.INFO))
	logger.Info("started")
	defer logger.Info("exited")

	token := getCurrentToken(logger)

	logger.Info("creating-application-guids")
	rand.Seed(1) // always use the same random sequence
	var guids []string
	for i := 0; i < config.Apps; i++ {
		guids = append(guids, randomAppGUID(i))
	}
	logger.Info(fmt.Sprintf("finished-creating-%d-application-guids", config.Apps))

	internalPolicyClient = getInternalPolicyClient(logger)
	externalPolicyClient = getExternalPolicyClient(logger)

	if config.CreateNewPolicies {
		deleteOldPolicies(logger, token)
		token = getCurrentToken(logger)
		addNewPolicies(logger, guids, token)
	} else {
		logger.Info("skipped-creating-policies")
	}

	appsPerCell := config.Apps / config.NumCells
	var cells [][]string
	for i := 0; i < config.NumCells; i++ {
		cells = append(cells, guids[i*appsPerCell:(i+1)*appsPerCell])
	}

	for i := 0; i < len(cells); i++ {
		go func(i int) {
			logger.Info(fmt.Sprintf("cell-%d-polling-policy-server", i))
			pollPolicyServer(logger, cells[i], i)
		}(i)
	}

	fmt.Println("Press CTRL-C to exit")
	select {
	case <-time.After(testDuration):
		logger.Info(fmt.Sprintf("exiting"))
		os.Exit(0)
	}
}
<|endoftext|>


<commit_before>/**
 * @file receiver.go
 * @author Mikhail Klementyev jollheef<AT>riseup.net
 * @license GNU GPLv3
 * @date September, 2015
 * @brief routine for receive flags from commands
 *
 * Provide tcp server for receive flags. After receive flag daemon perform
 * validate flag, check flag round and write result to db.
 */

package receiver

import (
	"bufio"
	"crypto/rsa"
	"database/sql"
	"errors"
	"fmt"
	"log"
	"net"
	"strings"
	"time"
)

import (
	"tinfoilhat/steward"
	"tinfoilhat/vexillary"
)

const (
	GreetingMsg         string = "IBST.PSU CTF Flag Receiver\nInput flag: "
	InvalidFlagMsg      string = "Invalid flag\n"
	AlreadyCapturedMsg  string = "Flag already captured\n"
	CapturedMsg         string = "Captured!\n"
	InternalErrorMsg    string = "Internal error\n"
	FlagDoesNotExistMsg string = "Flag does not exist\n"
	FlagExpiredMsg      string = "Flag expired\n"
	InvalidTeamMsg      string = "Team does not exist\n"
	AttemptsLimitMsg    string = "Attack attempts limit exceeded\n"
	FlagYoursMsg        string = "Flag belongs to the attacking team\n"
	ServiceNotUpMsg     string = "The attacking team service is not up\n"
)

func ParseAddr(addr string) (subnet_no int, err error) {

	_, err = fmt.Sscanf(strings.Split(addr, ".")[2], "%d", &subnet_no)

	return
}

func TeamByAddr(db *sql.DB, addr string) (team steward.Team, err error) {

	subnet_no, err := ParseAddr(addr)
	if err != nil {
		return
	}

	teams, err := steward.GetTeams(db)
	if err != nil {
		return
	}

	for i := 0; i < len(teams); i++ {

		team = teams[i]

		team_subnet_no, err := ParseAddr(team.Subnet)
		if err != nil {
			return team, err
		}

		if team_subnet_no == subnet_no {
			return team, err
		}
	}

	err = errors.New("team not found")

	return
}

func Handler(conn net.Conn, db *sql.DB, priv *rsa.PrivateKey) {

	addr := conn.RemoteAddr().String()

	defer conn.Close()

	fmt.Fprintf(conn, GreetingMsg)

	flag, err := bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		log.Println("Read error:", err)
	}

	flag = strings.Trim(flag, "\n")

	log.Printf("\tGet flag %s from %s", flag, addr)

	valid, err := vexillary.ValidFlag(flag, priv.PublicKey)
	if err != nil {
		log.Println("\tValidate flag failed:", err)
	}
	if !valid {
		fmt.Fprintf(conn, InvalidFlagMsg)
		return
	}

	exist, err := steward.FlagExist(db, flag)
	if err != nil {
		log.Println("\tExist flag check failed:", err)
		fmt.Fprintf(conn, InternalErrorMsg)
		return
	}
	if !exist {
		fmt.Fprintf(conn, FlagDoesNotExistMsg)
		return
	}

	flg, err := steward.GetFlagInfo(db, flag)
	if err != nil {
		log.Println("\tGet flag info failed:", err)
		fmt.Fprintf(conn, InternalErrorMsg)
		return
	}

	captured, err := steward.AlreadyCaptured(db, flg.Id)
	if err != nil {
		log.Println("\tAlready captured check failed:", err)
		fmt.Fprintf(conn, InternalErrorMsg)
		return
	}
	if captured {
		fmt.Fprintf(conn, AlreadyCapturedMsg)
		return
	}

	team, err := TeamByAddr(db, addr)
	if err != nil {
		log.Println("\tGet team by ip failed:", err)
		fmt.Fprintf(conn, InvalidTeamMsg)
		return
	}

	if flg.TeamId == team.Id {
		log.Printf("\tTeam %s try to send their flag", team.Name)
		fmt.Fprintf(conn, FlagYoursMsg)
		return
	}

	halfStatus := steward.Status{flg.Round, team.Id, flg.ServiceId,
		steward.STATUS_UNKNOWN}
	state, err := steward.GetState(db, halfStatus)

	if state != steward.STATUS_OK {
		log.Printf("\t%s service not ok, cannot capture", team.Name)
		fmt.Fprintf(conn, ServiceNotUpMsg)
		return
	}

	round, err := steward.CurrentRound(db)

	if round.Id != flg.Round {
		log.Printf("\t%s try to send flag from past round", team.Name)
		fmt.Fprintf(conn, FlagExpiredMsg)
		return
	}

	round_end_time := round.StartTime.Add(round.Len)

	if time.Now().After(round_end_time) {
		log.Printf("\t%s try to send flag from finished round", team.Name)
		fmt.Fprintf(conn, FlagExpiredMsg)
		return
	}

	err = steward.CaptureFlag(db, flg.Id, flg.TeamId)
	if err != nil {
		log.Println("\tCapture flag failed:", err)
		fmt.Fprintf(conn, InternalErrorMsg)
		return
	}

	fmt.Fprintf(conn, CapturedMsg)
}

func Receiver(db *sql.DB, priv *rsa.PrivateKey, addr string, timeout time.Duration) {

	log.Println("Launching receiver at", addr, "...")

	connects := make(map[string]time.Time) // { ip : last_connect_time }

	listener, _ := net.Listen("tcp", addr)

	for {
		conn, _ := listener.Accept()

		addr := conn.RemoteAddr().String()

		log.Printf("Connection accepted from %s", addr)

		ip, _, err := net.SplitHostPort(addr)
		if err != nil {
			log.Println("\tCannot split remote addr:", err)
			fmt.Fprintf(conn, InternalErrorMsg)
			conn.Close()
			continue
		}

		if time.Now().Before(connects[ip].Add(timeout)) {
			log.Println("\tToo fast connects by", ip)
			fmt.Fprintf(conn, AttemptsLimitMsg)
			conn.Close()
			continue
		}

		go Handler(conn, db, priv)

		connects[ip] = time.Now()
	}
}
<commit_msg>Fix mistake in capture flag<commit_after>/**
 * @file receiver.go
 * @author Mikhail Klementyev jollheef<AT>riseup.net
 * @license GNU GPLv3
 * @date September, 2015
 * @brief routine for receive flags from commands
 *
 * Provide tcp server for receive flags. After receive flag daemon perform
 * validate flag, check flag round and write result to db.
 */

package receiver

import (
	"bufio"
	"crypto/rsa"
	"database/sql"
	"errors"
	"fmt"
	"log"
	"net"
	"strings"
	"time"
)

import (
	"tinfoilhat/steward"
	"tinfoilhat/vexillary"
)

const (
	GreetingMsg         string = "IBST.PSU CTF Flag Receiver\nInput flag: "
	InvalidFlagMsg      string = "Invalid flag\n"
	AlreadyCapturedMsg  string = "Flag already captured\n"
	CapturedMsg         string = "Captured!\n"
	InternalErrorMsg    string = "Internal error\n"
	FlagDoesNotExistMsg string = "Flag does not exist\n"
	FlagExpiredMsg      string = "Flag expired\n"
	InvalidTeamMsg      string = "Team does not exist\n"
	AttemptsLimitMsg    string = "Attack attempts limit exceeded\n"
	FlagYoursMsg        string = "Flag belongs to the attacking team\n"
	ServiceNotUpMsg     string = "The attacking team service is not up\n"
)

func ParseAddr(addr string) (subnet_no int, err error) {

	_, err = fmt.Sscanf(strings.Split(addr, ".")[2], "%d", &subnet_no)

	return
}

func TeamByAddr(db *sql.DB, addr string) (team steward.Team, err error) {

	subnet_no, err := ParseAddr(addr)
	if err != nil {
		return
	}

	teams, err := steward.GetTeams(db)
	if err != nil {
		return
	}

	for i := 0; i < len(teams); i++ {

		team = teams[i]

		team_subnet_no, err := ParseAddr(team.Subnet)
		if err != nil {
			return team, err
		}

		if team_subnet_no == subnet_no {
			return team, err
		}
	}

	err = errors.New("team not found")

	return
}

func Handler(conn net.Conn, db *sql.DB, priv *rsa.PrivateKey) {

	addr := conn.RemoteAddr().String()

	defer conn.Close()

	fmt.Fprintf(conn, GreetingMsg)

	flag, err := bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		log.Println("Read error:", err)
	}

	flag = strings.Trim(flag, "\n")

	log.Printf("\tGet flag %s from %s", flag, addr)

	valid, err := vexillary.ValidFlag(flag, priv.PublicKey)
	if err != nil {
		log.Println("\tValidate flag failed:", err)
	}
	if !valid {
		fmt.Fprintf(conn, InvalidFlagMsg)
		return
	}

	exist, err := steward.FlagExist(db, flag)
	if err != nil {
		log.Println("\tExist flag check failed:", err)
		fmt.Fprintf(conn, InternalErrorMsg)
		return
	}
	if !exist {
		fmt.Fprintf(conn, FlagDoesNotExistMsg)
		return
	}

	flg, err := steward.GetFlagInfo(db, flag)
	if err != nil {
		log.Println("\tGet flag info failed:", err)
		fmt.Fprintf(conn, InternalErrorMsg)
		return
	}

	captured, err := steward.AlreadyCaptured(db, flg.Id)
	if err != nil {
		log.Println("\tAlready captured check failed:", err)
		fmt.Fprintf(conn, InternalErrorMsg)
		return
	}
	if captured {
		fmt.Fprintf(conn, AlreadyCapturedMsg)
		return
	}

	team, err := TeamByAddr(db, addr)
	if err != nil {
		log.Println("\tGet team by ip failed:", err)
		fmt.Fprintf(conn, InvalidTeamMsg)
		return
	}

	if flg.TeamId == team.Id {
		log.Printf("\tTeam %s try to send their flag", team.Name)
		fmt.Fprintf(conn, FlagYoursMsg)
		return
	}

	halfStatus := steward.Status{flg.Round, team.Id, flg.ServiceId,
		steward.STATUS_UNKNOWN}
	state, err := steward.GetState(db, halfStatus)

	if state != steward.STATUS_OK {
		log.Printf("\t%s service not ok, cannot capture", team.Name)
		fmt.Fprintf(conn, ServiceNotUpMsg)
		return
	}

	round, err := steward.CurrentRound(db)

	if round.Id != flg.Round {
		log.Printf("\t%s try to send flag from past round", team.Name)
		fmt.Fprintf(conn, FlagExpiredMsg)
		return
	}

	round_end_time := round.StartTime.Add(round.Len)

	if time.Now().After(round_end_time) {
		log.Printf("\t%s try to send flag from finished round", team.Name)
		fmt.Fprintf(conn, FlagExpiredMsg)
		return
	}

	err = steward.CaptureFlag(db, flg.Id, team.Id)
	if err != nil {
		log.Println("\tCapture flag failed:", err)
		fmt.Fprintf(conn, InternalErrorMsg)
		return
	}

	fmt.Fprintf(conn, CapturedMsg)
}

func Receiver(db *sql.DB, priv *rsa.PrivateKey, addr string, timeout time.Duration) {

	log.Println("Launching receiver at", addr, "...")

	connects := make(map[string]time.Time) // { ip : last_connect_time }

	listener, _ := net.Listen("tcp", addr)

	for {
		conn, _ := listener.Accept()

		addr := conn.RemoteAddr().String()

		log.Printf("Connection accepted from %s", addr)

		ip, _, err := net.SplitHostPort(addr)
		if err != nil {
			log.Println("\tCannot split remote addr:", err)
			fmt.Fprintf(conn, InternalErrorMsg)
			conn.Close()
			continue
		}

		if time.Now().Before(connects[ip].Add(timeout)) {
			log.Println("\tToo fast connects by", ip)
			fmt.Fprintf(conn, AttemptsLimitMsg)
			conn.Close()
			continue
		}

		go Handler(conn, db, priv)

		connects[ip] = time.Now()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/x509"
	"encoding/base64"
	"fmt"
	"log"
	"os"
	"strconv"

	"github.com/mozilla/tls-observatory/certificate"
	"github.com/mozilla/tls-observatory/database"
)

func main() {
	db, err := database.RegisterConnection(
		os.Getenv("TLSOBS_POSTGRESDB"),
		os.Getenv("TLSOBS_POSTGRESUSER"),
		os.Getenv("TLSOBS_POSTGRESPASS"),
		os.Getenv("TLSOBS_POSTGRES"),
		"require")
	defer db.Close()
	if err != nil {
		panic(err)
	}
	offset := 0
	limit := 100
	if len(os.Args) > 1 {
		offset, err = strconv.Atoi(os.Args[1])
		if err != nil {
			log.Fatal(err)
		}
	}
	for {
		fmt.Printf("\nProcessing offset %d to %d: ", offset, offset+limit)
		rows, err := db.Query(`SELECT id, raw_cert
					FROM certificates
					WHERE id > $1
					ORDER BY id ASC LIMIT $2`, offset, limit)
		if rows != nil {
			defer rows.Close()
		}
		if err != nil {
			panic(fmt.Errorf("Error while retrieving certs: '%v'", err))
		}
		i := 0
		for rows.Next() {
			i++
			var raw string
			var id int64
			err = rows.Scan(&id, &raw)
			if err != nil {
				fmt.Println("error while parsing cert", id, ":", err)
				continue
			}
			certdata, err := base64.StdEncoding.DecodeString(raw)
			if err != nil {
				fmt.Println("error decoding base64 of cert", id, ":", err)
				continue
			}
			c, err := x509.ParseCertificate(certdata)
			if err != nil {
				fmt.Println("error while x509 parsing cert", id, ":", err)
				continue
			}
			_, err = db.Exec(`UPDATE certificates SET sha256_subject_spki=$1 WHERE id=$2`,
				certificate.SHA256SubjectSPKI(c), id)
			if err != nil {
				fmt.Println("error while updating cert", id, "in database:", err)
			}
		}
		if i == 0 {
			fmt.Println("done!")
			break
		}
		//offset += limit
		offset += limit
	}
}
<commit_msg>tooling: use batch updates in fix SPKI script<commit_after>package main

import (
	"crypto/x509"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strconv"

	"github.com/mozilla/tls-observatory/certificate"
	"github.com/mozilla/tls-observatory/database"
)

func main() {
	db, err := database.RegisterConnection(
		os.Getenv("TLSOBS_POSTGRESDB"),
		os.Getenv("TLSOBS_POSTGRESUSER"),
		os.Getenv("TLSOBS_POSTGRESPASS"),
		os.Getenv("TLSOBS_POSTGRES"),
		"require")
	defer db.Close()
	if err != nil {
		panic(err)
	}
	offset := 0
	limit := 100
	if len(os.Args) > 1 {
		offset, err = strconv.Atoi(os.Args[1])
		if err != nil {
			log.Fatal(err)
		}
	}

	for {
		fmt.Printf("\nProcessing offset %d to %d: ", offset, offset+limit)
		rows, err := db.Query(`SELECT id, raw_cert
					FROM certificates
					WHERE id > $1
					ORDER BY id ASC LIMIT $2`, offset, limit)
		if rows != nil {
			defer rows.Close()
		}
		if err != nil {
			panic(fmt.Errorf("Error while retrieving certs: '%v'", err))
		}
		i := 0
		updates := make(map[int64]string)
		for rows.Next() {
			i++
			var raw string
			var id int64
			err = rows.Scan(&id, &raw)
			if err != nil {
				fmt.Println("error while parsing cert", id, ":", err)
				continue
			}
			certdata, err := base64.StdEncoding.DecodeString(raw)
			if err != nil {
				fmt.Println("error decoding base64 of cert", id, ":", err)
				continue
			}
			c, err := x509.ParseCertificate(certdata)
			if err != nil {
				fmt.Println("error while x509 parsing cert", id, ":", err)
				continue
			}
			updates[id] = certificate.SPKISHA256(c)
		}
		if i == 0 {
			fmt.Println("done!")
			break
		}
		// batch update
		sql := "UPDATE certificates SET sha256_subject_spki = newvalues.spki FROM ( VALUES "
		first := true
		for id, spki := range updates {
			if !first {
				sql += ","
			}
			sql += fmt.Sprintf("(%d, '%s')", id, spki)
			first = false
		}
		sql += ") AS newvalues (id, spki) WHERE certificates.id = newvalues.id"
		_, err = db.Exec(sql)
		if err != nil {
			fmt.Printf("error while updating certificates in database: %v\nSQL statement was:\n%s", err, sql)
		}
		offset += limit
		ioutil.WriteFile("/tmp/fixSHA256SubjectSPKI_offset", []byte(fmt.Sprintf("%d", offset)), 0700)
	}
}
<|endoftext|>


<commit_before>// Writing files in Go follows similar patterns to the
// ones we saw earlier for reading.

package main

import (
	"fmt"
	"math/rand"
	"os"
	"time"
)

const charset = "abcdefghijklmnopqrstuvwxyz" +
	"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

var seededRand *rand.Rand = rand.New(
	rand.NewSource(time.Now().UnixNano()))

func main() {

	f, err := os.OpenFile("data2.sql", os.O_APPEND|os.O_WRONLY, 0600)

	if err != nil {
		panic(err)
	}

	defer f.Close()

	for i := 1; i <= 100; i++ {
		datasetID := i
		dataset := "/" + String(3) + "/" + String(3) + "/" + String(3)
		putDataset := fmt.Sprintf("insert into DATASETS values (%d, \"%s\"); \n", datasetID, dataset)
		f.WriteString(putDataset)

		for j := 1; j <= 100; j++ {
			blockHash := String(4)
			block := fmt.Sprintf("%s#%s", dataset, blockHash)
			blockID := i*1000 + j
			putBlock := fmt.Sprintf("insert into BLOCKS values (%d, \"%s\", %d); \n", blockID, block, datasetID)
			f.WriteString(putBlock)

			for k := 1; k <= 100; k++ {
				lfn := dataset + "-" + block + "-" + String(5) + ".root"
				pfn := "/path/file3.root"
				id := i*1000000 + j*1000 + k
				putFile := fmt.Sprintf("insert into FILES values(%d, \"%s\", \"%s\", %d, %d, %d, \"%s\", %d, %d); \n", id, lfn, pfn, blockID, datasetID, 10, "hash", 123, 123)
				f.WriteString(putFile)
				break
			}
			break
		}
		break
	}

}

// Get max length of random string
func String(length int) string {
	return StringWithCharset(length, charset)
}

// Function to generate random string
func StringWithCharset(length int, charset string) string {
	b := make([]byte, length)
	for i := range b {
		b[i] = charset[seededRand.Intn(len(charset))]
	}
	return string(b)
}
<commit_msg>Remove break keyword<commit_after>// Writing files in Go follows similar patterns to the
// ones we saw earlier for reading.

package main

import (
	"fmt"
	"math/rand"
	"os"
	"time"
)

const charset = "abcdefghijklmnopqrstuvwxyz" +
	"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

var seededRand *rand.Rand = rand.New(
	rand.NewSource(time.Now().UnixNano()))

func main() {

	f, err := os.OpenFile("data2.sql", os.O_APPEND|os.O_WRONLY, 0600)

	if err != nil {
		panic(err)
	}

	defer f.Close()

	for i := 1; i <= 100; i++ {
		datasetID := i
		dataset := "/" + String(3) + "/" + String(3) + "/" + String(3)
		putDataset := fmt.Sprintf("insert into DATASETS values (%d, \"%s\"); \n", datasetID, dataset)
		f.WriteString(putDataset)

		for j := 1; j <= 100; j++ {
			blockHash := String(4)
			block := fmt.Sprintf("%s#%s", dataset, blockHash)
			blockID := i*1000 + j
			putBlock := fmt.Sprintf("insert into BLOCKS values (%d, \"%s\", %d); \n", blockID, block, datasetID)
			f.WriteString(putBlock)

			for k := 1; k <= 100; k++ {
				lfn := dataset + "-" + block + "-" + String(5) + ".root"
				pfn := "/path/file3.root"
				id := i*1000000 + j*1000 + k
				putFile := fmt.Sprintf("insert into FILES values(%d, \"%s\", \"%s\", %d, %d, %d, \"%s\", %d, %d); \n", id, lfn, pfn, blockID, datasetID, 10, "hash", 123, 123)
				f.WriteString(putFile)
			}
		}
	}

}

// Get max length of random string
func String(length int) string {
	return StringWithCharset(length, charset)
}

// Function to generate random string
func StringWithCharset(length int, charset string) string {
	b := make([]byte, length)
	for i := range b {
		b[i] = charset[seededRand.Intn(len(charset))]
	}
	return string(b)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// Package trace provides methods to submit Zipkin style Span to tcollector Server.
package trace

import (
	"encoding/base64"
	"encoding/binary"
	"net"
	"strconv"
	"strings"
	"time"

	tc "github.com/uber/tchannel/golang"
	"github.com/uber/tchannel/golang/thrift"
	"github.com/uber/tchannel/golang/trace/thrift/gen-go/tcollector"
)

const (
	tcollectorServiceName = "tcollector"
	chanBufferSize        = 100
)

type zipkinData struct {
	Span              tc.Span
	Annotations       []tc.Annotation
	BinaryAnnotations []tc.BinaryAnnotation
	TargetEndpoint    tc.TargetEndpoint
}

// ZipkinTraceReporter is a trace reporter that submits trace spans in to zipkin trace server.
type ZipkinTraceReporter struct {
	tchannel *tc.Channel
	client   tcollector.TChanTCollector
	c        chan zipkinData
	logger   tc.Logger
}

// NewZipkinTraceReporter returns a zipkin trace reporter that submits span to tcollector service.
func NewZipkinTraceReporter(ch *tc.Channel) *ZipkinTraceReporter {
	thriftClient := thrift.NewClient(ch, tcollectorServiceName, nil)
	client := tcollector.NewTChanTCollectorClient(thriftClient)
	// create the goroutine method to actually to the submit Span.
	reporter := &ZipkinTraceReporter{
		tchannel: ch,
		client:   client,
		c:        make(chan zipkinData, chanBufferSize),
		logger:   ch.Logger(),
	}
	go reporter.zipkinSpanWorker()
	return reporter
}

// Report method will submit trace span to tcollector server.
func (r *ZipkinTraceReporter) Report(
	span tc.Span, annotations []tc.Annotation, binaryAnnotations []tc.BinaryAnnotation, targetEndpoint tc.TargetEndpoint) {
	data := zipkinData{
		Span:              span,
		Annotations:       annotations,
		BinaryAnnotations: binaryAnnotations,
		TargetEndpoint:    targetEndpoint,
	}

	select {
	case r.c <- data:
	default:
		r.logger.Infof("Buffer channel for zipkin trace report is full.")
	}
}

func (r *ZipkinTraceReporter) zipkinReport(data *zipkinData) error {
	ctx, cancel := tc.NewContextBuilder(time.Second).
		SetShardKey(base64Encode(data.Span.TraceID())).Build()
	defer cancel()

	thriftSpan := buildZipkinSpan(data.Span, data.Annotations, data.BinaryAnnotations, data.TargetEndpoint)
	// client submit
	// ignore the response result because TChannel shouldn't care about it.
	_, err := r.client.Submit(ctx, thriftSpan)
	return err
}

func (r *ZipkinTraceReporter) zipkinSpanWorker() {
	for data := range r.c {
		if err := r.zipkinReport(&data); err != nil {
			r.logger.Infof("Zipkin Span submit failed. Get error: %v", err)
		}
	}
}

// buildZipkinSpan builds zipkin span based on tchannel span.
func buildZipkinSpan(span tc.Span, annotations []tc.Annotation, binaryAnnotations []tc.BinaryAnnotation, targetEndpoint tc.TargetEndpoint) *tcollector.Span {
	hostport := strings.Split(targetEndpoint.HostPort, ":")
	port, _ := strconv.ParseInt(hostport[1], 10, 32)
	host := tcollector.Endpoint{
		Ipv4:        int32(inetAton(hostport[0])),
		Port:        int32(port),
		ServiceName: targetEndpoint.ServiceName,
	}

	// TODO Add BinaryAnnotations
	thriftSpan := tcollector.Span{
		TraceId:     uint64ToBytes(span.TraceID()),
		Host:        &host,
		Name:        targetEndpoint.Operation,
		Id:          uint64ToBytes(span.SpanID()),
		ParentId:    uint64ToBytes(span.ParentID()),
		Annotations: buildZipkinAnnotations(annotations),
		Debug:       false,
	}

	return &thriftSpan
}

// buildZipkinAnnotations builds zipkin Annotations based on tchannel annotations.
func buildZipkinAnnotations(anns []tc.Annotation) []*tcollector.Annotation {
	zipkinAnns := make([]*tcollector.Annotation, len(anns))
	for i, ann := range anns {
		zipkinAnns[i] = &tcollector.Annotation{
			Timestamp: (float64)(ann.Timestamp.UnixNano() / 1e6),
			Value:     (string)(ann.Key),
		}
	}
	return zipkinAnns
}

// inetAton converts string Ipv4 to uint32
func inetAton(ip string) uint32 {
	ipBytes := net.ParseIP(ip).To4()
	return binary.BigEndian.Uint32(ipBytes)
}

// base64Encode encodes uint64 with base64 StdEncoding.
func base64Encode(data uint64) string {
	return base64.StdEncoding.EncodeToString(uint64ToBytes(data))
}

// uint64ToBytes converts uint64 to bytes.
func uint64ToBytes(i uint64) []byte {
	buf := make([]byte, 8)
	binary.BigEndian.PutUint64(buf, uint64(i))
	return buf
}

// ZipkinTraceReporterFactory builds ZipkinTraceReporter by given TChannel instance.
func ZipkinTraceReporterFactory(tchannel *tc.Channel) tc.TraceReporter {
	return NewZipkinTraceReporter(tchannel)
}
<commit_msg>Remove unneeded casts<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// Package trace provides methods to submit Zipkin style Span to tcollector Server.
package trace

import (
	"encoding/base64"
	"encoding/binary"
	"net"
	"strconv"
	"strings"
	"time"

	tc "github.com/uber/tchannel/golang"
	"github.com/uber/tchannel/golang/thrift"
	"github.com/uber/tchannel/golang/trace/thrift/gen-go/tcollector"
)

const (
	tcollectorServiceName = "tcollector"
	chanBufferSize        = 100
)

type zipkinData struct {
	Span              tc.Span
	Annotations       []tc.Annotation
	BinaryAnnotations []tc.BinaryAnnotation
	TargetEndpoint    tc.TargetEndpoint
}

// ZipkinTraceReporter is a trace reporter that submits trace spans in to zipkin trace server.
type ZipkinTraceReporter struct {
	tchannel *tc.Channel
	client   tcollector.TChanTCollector
	c        chan zipkinData
	logger   tc.Logger
}

// NewZipkinTraceReporter returns a zipkin trace reporter that submits span to tcollector service.
func NewZipkinTraceReporter(ch *tc.Channel) *ZipkinTraceReporter {
	thriftClient := thrift.NewClient(ch, tcollectorServiceName, nil)
	client := tcollector.NewTChanTCollectorClient(thriftClient)
	// create the goroutine method to actually to the submit Span.
	reporter := &ZipkinTraceReporter{
		tchannel: ch,
		client:   client,
		c:        make(chan zipkinData, chanBufferSize),
		logger:   ch.Logger(),
	}
	go reporter.zipkinSpanWorker()
	return reporter
}

// Report method will submit trace span to tcollector server.
func (r *ZipkinTraceReporter) Report(
	span tc.Span, annotations []tc.Annotation, binaryAnnotations []tc.BinaryAnnotation, targetEndpoint tc.TargetEndpoint) {
	data := zipkinData{
		Span:              span,
		Annotations:       annotations,
		BinaryAnnotations: binaryAnnotations,
		TargetEndpoint:    targetEndpoint,
	}

	select {
	case r.c <- data:
	default:
		r.logger.Infof("Buffer channel for zipkin trace report is full.")
	}
}

func (r *ZipkinTraceReporter) zipkinReport(data *zipkinData) error {
	ctx, cancel := tc.NewContextBuilder(time.Second).
		SetShardKey(base64Encode(data.Span.TraceID())).Build()
	defer cancel()

	thriftSpan := buildZipkinSpan(data.Span, data.Annotations, data.BinaryAnnotations, data.TargetEndpoint)
	// client submit
	// ignore the response result because TChannel shouldn't care about it.
	_, err := r.client.Submit(ctx, thriftSpan)
	return err
}

func (r *ZipkinTraceReporter) zipkinSpanWorker() {
	for data := range r.c {
		if err := r.zipkinReport(&data); err != nil {
			r.logger.Infof("Zipkin Span submit failed. Get error: %v", err)
		}
	}
}

// buildZipkinSpan builds zipkin span based on tchannel span.
func buildZipkinSpan(span tc.Span, annotations []tc.Annotation, binaryAnnotations []tc.BinaryAnnotation, targetEndpoint tc.TargetEndpoint) *tcollector.Span {
	hostport := strings.Split(targetEndpoint.HostPort, ":")
	port, _ := strconv.ParseInt(hostport[1], 10, 32)
	host := tcollector.Endpoint{
		Ipv4:        int32(inetAton(hostport[0])),
		Port:        int32(port),
		ServiceName: targetEndpoint.ServiceName,
	}

	// TODO Add BinaryAnnotations
	thriftSpan := tcollector.Span{
		TraceId:     uint64ToBytes(span.TraceID()),
		Host:        &host,
		Name:        targetEndpoint.Operation,
		Id:          uint64ToBytes(span.SpanID()),
		ParentId:    uint64ToBytes(span.ParentID()),
		Annotations: buildZipkinAnnotations(annotations),
		Debug:       false,
	}

	return &thriftSpan
}

// buildZipkinAnnotations builds zipkin Annotations based on tchannel annotations.
func buildZipkinAnnotations(anns []tc.Annotation) []*tcollector.Annotation {
	zipkinAnns := make([]*tcollector.Annotation, len(anns))
	for i, ann := range anns {
		zipkinAnns[i] = &tcollector.Annotation{
			Timestamp: float64(ann.Timestamp.UnixNano() / 1e6),
			Value:     string(ann.Key),
		}
	}
	return zipkinAnns
}

// inetAton converts string Ipv4 to uint32
func inetAton(ip string) uint32 {
	ipBytes := net.ParseIP(ip).To4()
	return binary.BigEndian.Uint32(ipBytes)
}

// base64Encode encodes uint64 with base64 StdEncoding.
func base64Encode(data uint64) string {
	return base64.StdEncoding.EncodeToString(uint64ToBytes(data))
}

// uint64ToBytes converts uint64 to bytes.
func uint64ToBytes(i uint64) []byte {
	buf := make([]byte, 8)
	binary.BigEndian.PutUint64(buf, uint64(i))
	return buf
}

// ZipkinTraceReporterFactory builds ZipkinTraceReporter by given TChannel instance.
func ZipkinTraceReporterFactory(tchannel *tc.Channel) tc.TraceReporter {
	return NewZipkinTraceReporter(tchannel)
}
<|endoftext|>


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

package environment

import (
	"github.com/juju/cmd"
	"launchpad.net/gnuflag"

	"github.com/juju/juju/cmd/juju/common"
	"github.com/juju/juju/constraints"
)

const getConstraintsDoc = `
environment get-constraints returns a list of constraints that have been set on the
environment using juju environment set-constraints.  You can also view constraints
set for a specific service by using juju service get-constraints <service>.

See Also:
   juju help constraints
   juju environment help set-constraints
`

const setConstraintsDoc = `
set-constraints sets machine constraints on the system, which are used as the
default constraints for all new machines provisioned in the environment (unless
overridden).  You can also set constraints on a specific service by using
juju service set-constraints.

Constraints set on a service are combined with environment constraints for
commands (such as juju deploy) that provision machines for services.  Where
environment and service constraints overlap, the service constraints take
precedence.

Example:

   juju environment set-constraints mem=8G                         (all new machines in the environment must have at least 8GB of RAM)

See Also:
   juju help constraints
   juju environment help get-constraints
   juju help deploy
   juju machine help add
   juju help add-unit
`

// EnvGetConstraintsCommand shows the constraints for an environment.
// It is just a wrapper for the common GetConstraintsCommand and
// enforces that no service arguments are passed in.
type EnvGetConstraintsCommand struct {
	common.GetConstraintsCommand
}

func (c *EnvGetConstraintsCommand) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "get-constraints",
		Purpose: "view constraints on the environment",
		Doc:     getConstraintsDoc,
	}
}

func (c *EnvGetConstraintsCommand) Init(args []string) error {
	return cmd.CheckEmpty(args)
}

// EnvSetConstraintsCommand sets the constraints for an environment.
// It is just a wrapper for the common SetConstraintsCommand and
// enforces that no service arguments are passed in.
type EnvSetConstraintsCommand struct {
	common.SetConstraintsCommand
}

func (c *EnvSetConstraintsCommand) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "set-constraints",
		Args:    "[key=[value] ...]",
		Purpose: "set constraints on the environment",
		Doc:     setConstraintsDoc,
	}
}

// SetFlags overrides SetFlags for SetConstraintsCommand since that
// will register a flag to specify the service.
func (c *EnvSetConstraintsCommand) SetFlags(f *gnuflag.FlagSet) {}

func (c *EnvSetConstraintsCommand) Init(args []string) (err error) {
	c.Constraints, err = constraints.Parse(args...)
	return err
}
<commit_msg>Addressing review comments.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package environment

import (
	"github.com/juju/cmd"
	"launchpad.net/gnuflag"

	"github.com/juju/juju/cmd/juju/common"
	"github.com/juju/juju/constraints"
)

const getConstraintsDoc = `
Shows a list of constraints that have been set on the environment
using juju environment set-constraints.  You can also view constraints
set for a specific service by using juju service get-constraints <service>.

Constraints set on a service are combined with environment constraints for
commands (such as juju deploy) that provision machines for services.  Where
environment and service constraints overlap, the service constraints take
precedence.

See Also:
   juju help constraints
   juju environment help set-constraints
   juju help deploy
   juju machine help add
   juju help add-unit
`

const setConstraintsDoc = `
Sets machine constraints on the environment, which are used as the default
constraints for all new machines provisioned in the environment (unless
overridden).  You can also set constraints on a specific service by using
juju service set-constraints.

Constraints set on a service are combined with environment constraints for
commands (such as juju deploy) that provision machines for services.  Where
environment and service constraints overlap, the service constraints take
precedence.

Example:

   juju environment set-constraints mem=8G                         (all new machines in the environment must have at least 8GB of RAM)

See Also:
   juju help constraints
   juju environment help get-constraints
   juju help deploy
   juju machine help add
   juju help add-unit
`

// EnvGetConstraintsCommand shows the constraints for an environment.
// It is just a wrapper for the common GetConstraintsCommand and
// enforces that no service arguments are passed in.
type EnvGetConstraintsCommand struct {
	common.GetConstraintsCommand
}

func (c *EnvGetConstraintsCommand) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "get-constraints",
		Purpose: "view constraints on the environment",
		Doc:     getConstraintsDoc,
	}
}

func (c *EnvGetConstraintsCommand) Init(args []string) error {
	return cmd.CheckEmpty(args)
}

// EnvSetConstraintsCommand sets the constraints for an environment.
// It is just a wrapper for the common SetConstraintsCommand and
// enforces that no service arguments are passed in.
type EnvSetConstraintsCommand struct {
	common.SetConstraintsCommand
}

func (c *EnvSetConstraintsCommand) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "set-constraints",
		Args:    "[key=[value] ...]",
		Purpose: "set constraints on the environment",
		Doc:     setConstraintsDoc,
	}
}

// SetFlags overrides SetFlags for SetConstraintsCommand since that
// will register a flag to specify the service.
func (c *EnvSetConstraintsCommand) SetFlags(f *gnuflag.FlagSet) {}

func (c *EnvSetConstraintsCommand) Init(args []string) (err error) {
	c.Constraints, err = constraints.Parse(args...)
	return err
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// import-boss enforces import restrictions in a given repository.
//
// When a directory is verified, import-boss looks for a file called
// ".import-restrictions". If this file is not found, parent directories will be
// recursively searched.
//
// If an ".import-restrictions" file is found, then all imports of the package
// are checked against each "rule" in the file. A rule consists of three parts:
// * A SelectorRegexp, to select the import paths that the rule applies to.
// * A list of AllowedPrefixes
// * A list of ForbiddenPrefixes
// An import is allowed if it matches at least one allowed prefix and does not
// match any forbidden prefix. An example file looks like this:
//
// {
//   "Rules": [
//     {
//       "SelectorRegexp": "k8s[.]io",
//       "AllowedPrefixes": [
//         "k8s.io/gengo/examples",
//         "k8s.io/kubernetes/third_party"
//       ],
//       "ForbiddenPrefixes": [
//         "k8s.io/kubernetes/pkg/third_party/deprecated"
//       ]
//     },
//     {
//       "SelectorRegexp": "^unsafe$",
//       "AllowedPrefixes": [
//       ],
//       "ForbiddenPrefixes": [
//         ""
//       ]
//     }
//   ]
// }
//
// Note the secound block explicitly matches the unsafe package, and forbids it
// ("" is a prefix of everything).
package main

import (
	"os"
	"path/filepath"

	"k8s.io/gengo/args"
	"k8s.io/gengo/examples/import-boss/generators"

	"github.com/golang/glog"
)

func main() {
	arguments := args.Default()

	// Override defaults. These are Kubernetes specific input and output
	// locations.
	arguments.InputDirs = []string{
		"k8s.io/kubernetes/pkg/...",
		"k8s.io/kubernetes/cmd/...",
		"k8s.io/kubernetes/plugin/...",
	}
	arguments.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt")
	// arguments.VerifyOnly = true

	if err := arguments.Execute(
		generators.NameSystems(),
		generators.DefaultNameSystem(),
		generators.Packages,
	); err != nil {
		glog.Errorf("Error: %v", err)
		os.Exit(1)
	}
	glog.V(2).Info("Completed successfully.")
}
<commit_msg>fix second typo<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// import-boss enforces import restrictions in a given repository.
//
// When a directory is verified, import-boss looks for a file called
// ".import-restrictions". If this file is not found, parent directories will be
// recursively searched.
//
// If an ".import-restrictions" file is found, then all imports of the package
// are checked against each "rule" in the file. A rule consists of three parts:
// * A SelectorRegexp, to select the import paths that the rule applies to.
// * A list of AllowedPrefixes
// * A list of ForbiddenPrefixes
// An import is allowed if it matches at least one allowed prefix and does not
// match any forbidden prefix. An example file looks like this:
//
// {
//   "Rules": [
//     {
//       "SelectorRegexp": "k8s[.]io",
//       "AllowedPrefixes": [
//         "k8s.io/gengo/examples",
//         "k8s.io/kubernetes/third_party"
//       ],
//       "ForbiddenPrefixes": [
//         "k8s.io/kubernetes/pkg/third_party/deprecated"
//       ]
//     },
//     {
//       "SelectorRegexp": "^unsafe$",
//       "AllowedPrefixes": [
//       ],
//       "ForbiddenPrefixes": [
//         ""
//       ]
//     }
//   ]
// }
//
// Note the second block explicitly matches the unsafe package, and forbids it
// ("" is a prefix of everything).
package main

import (
	"os"
	"path/filepath"

	"k8s.io/gengo/args"
	"k8s.io/gengo/examples/import-boss/generators"

	"github.com/golang/glog"
)

func main() {
	arguments := args.Default()

	// Override defaults. These are Kubernetes specific input and output
	// locations.
	arguments.InputDirs = []string{
		"k8s.io/kubernetes/pkg/...",
		"k8s.io/kubernetes/cmd/...",
		"k8s.io/kubernetes/plugin/...",
	}
	arguments.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt")
	// arguments.VerifyOnly = true

	if err := arguments.Execute(
		generators.NameSystems(),
		generators.DefaultNameSystem(),
		generators.Packages,
	); err != nil {
		glog.Errorf("Error: %v", err)
		os.Exit(1)
	}
	glog.V(2).Info("Completed successfully.")
}
<|endoftext|>