<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.
*/

package model

import (
	"fmt"
	"strings"

	"github.com/golang/glog"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
	"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/aws"
)

// NetworkModelBuilder configures network objects
type NetworkModelBuilder struct {
	*KopsModelContext
	Lifecycle *fi.Lifecycle
}

var _ fi.ModelBuilder = &NetworkModelBuilder{}

func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
	sharedVPC := b.Cluster.SharedVPC()
	vpcName := b.ClusterName()
	tags := b.CloudTags(vpcName, sharedVPC)

	// VPC that holds everything for the cluster
	{
		vpcTags := tags
		if sharedVPC {
			// We don't tag a shared VPC - we can identify it by its ID anyway.  Issue #4265
			vpcTags = nil
		}
		t := &awstasks.VPC{
			Name:             s(vpcName),
			Lifecycle:        b.Lifecycle,
			Shared:           fi.Bool(sharedVPC),
			EnableDNSSupport: fi.Bool(true),
			Tags:             vpcTags,
		}

		if sharedVPC && b.IsKubernetesGTE("1.5") {
			// If we're running k8s 1.5, and we have e.g.  --kubelet-preferred-address-types=InternalIP,Hostname,ExternalIP,LegacyHostIP
			// then we don't need EnableDNSHostnames any more
			glog.V(4).Infof("Kubernetes version %q; skipping EnableDNSHostnames requirement on VPC", b.KubernetesVersion())
		} else {
			// In theory we don't need to enable it for >= 1.5,
			// but seems safer to stick with existing behaviour

			t.EnableDNSHostnames = fi.Bool(true)
		}

		if b.Cluster.Spec.NetworkID != "" {
			t.ID = s(b.Cluster.Spec.NetworkID)
		}

		if b.Cluster.Spec.NetworkCIDR != "" {
			t.CIDR = s(b.Cluster.Spec.NetworkCIDR)
		}
		c.AddTask(t)
	}

	if !sharedVPC {
		dhcp := &awstasks.DHCPOptions{
			Name:              s(b.ClusterName()),
			Lifecycle:         b.Lifecycle,
			DomainNameServers: s("AmazonProvidedDNS"),

			Tags:   tags,
			Shared: fi.Bool(sharedVPC),
		}
		if b.Region == "us-east-1" {
			dhcp.DomainName = s("ec2.internal")
		} else {
			dhcp.DomainName = s(b.Region + ".compute.internal")
		}
		c.AddTask(dhcp)

		c.AddTask(&awstasks.VPCDHCPOptionsAssociation{
			Name:        s(b.ClusterName()),
			Lifecycle:   b.Lifecycle,
			VPC:         b.LinkToVPC(),
			DHCPOptions: dhcp,
		})
	} else {
		// TODO: would be good to create these as shared, to verify them
	}

	allSubnetsShared := true
	allSubnetsSharedInZone := make(map[string]bool)
	for i := range b.Cluster.Spec.Subnets {
		subnetSpec := &b.Cluster.Spec.Subnets[i]
		allSubnetsSharedInZone[subnetSpec.Zone] = true
	}

	for i := range b.Cluster.Spec.Subnets {
		subnetSpec := &b.Cluster.Spec.Subnets[i]
		sharedSubnet := subnetSpec.ProviderID != ""
		if !sharedSubnet {
			allSubnetsShared = false
			allSubnetsSharedInZone[subnetSpec.Zone] = false
		}
	}

	// We always have a public route table, though for private networks it is only used for NGWs and ELBs
	var publicRouteTable *awstasks.RouteTable
	{
		// The internet gateway is the main entry point to the cluster.
		igw := &awstasks.InternetGateway{
			Name:      s(b.ClusterName()),
			Lifecycle: b.Lifecycle,
			VPC:       b.LinkToVPC(),
			Shared:    fi.Bool(sharedVPC),
		}
		igw.Tags = b.CloudTags(*igw.Name, *igw.Shared)
		c.AddTask(igw)

		if !allSubnetsShared {
			// The route table is not shared if we're creating a subnet for our cluster
			// That subnet will be owned, and will be associated with our RouteTable.
			// On deletion we delete the subnet & the route table.
			sharedRouteTable := false
			routeTableTags := b.CloudTags(vpcName, sharedRouteTable)
			routeTableTags[awsup.TagNameKopsRole] = "public"
			publicRouteTable = &awstasks.RouteTable{
				Name:      s(b.ClusterName()),
				Lifecycle: b.Lifecycle,

				VPC: b.LinkToVPC(),

				Tags:   routeTableTags,
				Shared: fi.Bool(sharedRouteTable),
			}
			c.AddTask(publicRouteTable)

			// TODO: Validate when allSubnetsShared
			c.AddTask(&awstasks.Route{
				Name:            s("0.0.0.0/0"),
				Lifecycle:       b.Lifecycle,
				CIDR:            s("0.0.0.0/0"),
				RouteTable:      publicRouteTable,
				InternetGateway: igw,
			})
		}
	}

	privateZones := sets.NewString()

	for i := range b.Cluster.Spec.Subnets {
		subnetSpec := &b.Cluster.Spec.Subnets[i]
		sharedSubnet := subnetSpec.ProviderID != ""
		subnetName := subnetSpec.Name + "." + b.ClusterName()
		tags := b.CloudTags(subnetName, sharedSubnet)

		// Apply tags so that Kubernetes knows which subnets should be used for internal/external ELBs
		switch subnetSpec.Type {
		case kops.SubnetTypePublic, kops.SubnetTypeUtility:
			tags[aws.TagNameSubnetPublicELB] = "1"

		case kops.SubnetTypePrivate:
			tags[aws.TagNameSubnetInternalELB] = "1"

		default:
			glog.V(2).Infof("unable to properly tag subnet %q because it has unknown type %q. Load balancers may be created in incorrect subnets", subnetSpec.Name, subnetSpec.Type)
		}

		tags["SubnetType"] = string(subnetSpec.Type)

		subnet := &awstasks.Subnet{
			Name:             s(subnetName),
			Lifecycle:        b.Lifecycle,
			VPC:              b.LinkToVPC(),
			AvailabilityZone: s(subnetSpec.Zone),
			CIDR:             s(subnetSpec.CIDR),
			Shared:           fi.Bool(sharedSubnet),
			Tags:             tags,
		}

		if subnetSpec.ProviderID != "" {
			subnet.ID = s(subnetSpec.ProviderID)
		}
		c.AddTask(subnet)

		switch subnetSpec.Type {
		case kops.SubnetTypePublic, kops.SubnetTypeUtility:
			if !sharedSubnet {
				c.AddTask(&awstasks.RouteTableAssociation{
					Name:       s(subnetSpec.Name + "." + b.ClusterName()),
					Lifecycle:  b.Lifecycle,
					RouteTable: publicRouteTable,
					Subnet:     subnet,
				})
			}

		case kops.SubnetTypePrivate:
			// Private subnets get a Network Gateway, and their own route table to associate them with the network gateway

			if !sharedSubnet {
				// Private Subnet Route Table Associations
				//
				// Map the Private subnet to the Private route table
				c.AddTask(&awstasks.RouteTableAssociation{
					Name:       s("private-" + subnetSpec.Name + "." + b.ClusterName()),
					Lifecycle:  b.Lifecycle,
					RouteTable: b.LinkToPrivateRouteTableInZone(subnetSpec.Zone),
					Subnet:     subnet,
				})

				// TODO: validate even if shared?
				privateZones.Insert(subnetSpec.Zone)
			}
		default:
			return fmt.Errorf("subnet %q has unknown type %q", subnetSpec.Name, subnetSpec.Type)
		}
	}

	// Loop over zones
	for i, zone := range privateZones.List() {

		utilitySubnet, err := b.LinkToUtilitySubnetInZone(zone)
		if err != nil {
			return err
		}

		var ngw *awstasks.NatGateway
		if b.Cluster.Spec.Subnets[i].Egress != "" {
			if strings.HasPrefix(b.Cluster.Spec.Subnets[i].Egress, "nat-") {

				ngw = &awstasks.NatGateway{
					Name:                 s(zone + "." + b.ClusterName()),
					Lifecycle:            b.Lifecycle,
					Subnet:               utilitySubnet,
					ID:                   s(b.Cluster.Spec.Subnets[i].Egress),
					AssociatedRouteTable: b.LinkToPrivateRouteTableInZone(zone),
					// If we're here, it means this NatGateway was specified, so we are Shared
					Shared: fi.Bool(true),
					Tags:   b.CloudTags(zone+"."+b.ClusterName(), true),
				}

				c.AddTask(ngw)

			} else {
				return fmt.Errorf("kops currently only supports re-use of NAT Gateways. We will support more eventually! Please see https://github.com/kubernetes/kops/issues/1530")
			}

		} else {

			// Every NGW needs a public (Elastic) IP address, every private
			// subnet needs a NGW, lets create it. We tie it to a subnet
			// so we can track it in AWS
			eip := &awstasks.ElasticIP{
				Name:                           s(zone + "." + b.ClusterName()),
				Lifecycle:                      b.Lifecycle,
				AssociatedNatGatewayRouteTable: b.LinkToPrivateRouteTableInZone(zone),
			}

			if b.Cluster.Spec.Subnets[i].PublicIP != "" {
				eip.PublicIP = s(b.Cluster.Spec.Subnets[i].PublicIP)
				eip.Tags = b.CloudTags(*eip.Name, true)
			} else {
				eip.Tags = b.CloudTags(*eip.Name, false)
			}

			c.AddTask(eip)
			// NAT Gateway
			//
			// All private subnets will need a NGW, one per zone
			//
			// The instances in the private subnet can access the Internet by
			// using a network address translation (NAT) gateway that resides
			// in the public subnet.

			//var ngw = &awstasks.NatGateway{}
			ngw = &awstasks.NatGateway{
				Name:                 s(zone + "." + b.ClusterName()),
				Lifecycle:            b.Lifecycle,
				Subnet:               utilitySubnet,
				ElasticIP:            eip,
				AssociatedRouteTable: b.LinkToPrivateRouteTableInZone(zone),
				Tags:                 b.CloudTags(zone+"."+b.ClusterName(), false),
			}
			c.AddTask(ngw)
		}

		// Private Route Table
		//
		// The private route table that will route to the NAT Gateway
		// We create an owned route table if we created any subnet in that zone.
		// Otherwise we consider it shared.
		routeTableShared := allSubnetsSharedInZone[zone]
		routeTableTags := b.CloudTags(b.NamePrivateRouteTableInZone(zone), routeTableShared)
		routeTableTags[awsup.TagNameKopsRole] = "private-" + zone
		rt := &awstasks.RouteTable{
			Name:      s(b.NamePrivateRouteTableInZone(zone)),
			VPC:       b.LinkToVPC(),
			Lifecycle: b.Lifecycle,

			Shared: fi.Bool(routeTableShared),
			Tags:   routeTableTags,
		}
		c.AddTask(rt)

		// Private Routes
		//
		// Routes for the private route table.
		// Will route to the NAT Gateway
		c.AddTask(&awstasks.Route{
			Name:       s("private-" + zone + "-0.0.0.0/0"),
			Lifecycle:  b.Lifecycle,
			CIDR:       s("0.0.0.0/0"),
			RouteTable: rt,
			NatGateway: ngw,
		})

	}

	return nil
}
<commit_msg>Map AdditionalCIDRs from spec<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.
*/

package model

import (
	"fmt"
	"strings"

	"github.com/golang/glog"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
	"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/aws"
)

// NetworkModelBuilder configures network objects
type NetworkModelBuilder struct {
	*KopsModelContext
	Lifecycle *fi.Lifecycle
}

var _ fi.ModelBuilder = &NetworkModelBuilder{}

func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
	sharedVPC := b.Cluster.SharedVPC()
	vpcName := b.ClusterName()
	tags := b.CloudTags(vpcName, sharedVPC)

	// VPC that holds everything for the cluster
	{
		vpcTags := tags
		if sharedVPC {
			// We don't tag a shared VPC - we can identify it by its ID anyway.  Issue #4265
			vpcTags = nil
		}
		t := &awstasks.VPC{
			Name:             s(vpcName),
			Lifecycle:        b.Lifecycle,
			Shared:           fi.Bool(sharedVPC),
			EnableDNSSupport: fi.Bool(true),
			Tags:             vpcTags,
		}

		if sharedVPC && b.IsKubernetesGTE("1.5") {
			// If we're running k8s 1.5, and we have e.g.  --kubelet-preferred-address-types=InternalIP,Hostname,ExternalIP,LegacyHostIP
			// then we don't need EnableDNSHostnames any more
			glog.V(4).Infof("Kubernetes version %q; skipping EnableDNSHostnames requirement on VPC", b.KubernetesVersion())
		} else {
			// In theory we don't need to enable it for >= 1.5,
			// but seems safer to stick with existing behaviour

			t.EnableDNSHostnames = fi.Bool(true)
		}

		if b.Cluster.Spec.NetworkID != "" {
			t.ID = s(b.Cluster.Spec.NetworkID)
		}

		if b.Cluster.Spec.NetworkCIDR != "" {
			t.CIDR = s(b.Cluster.Spec.NetworkCIDR)
		}

		for _, cidr := range b.Cluster.Spec.AdditionalNetworkCIDRs {
			t.AdditionalCIDR = append(t.AdditionalCIDR, cidr)
		}

		c.AddTask(t)
	}

	if !sharedVPC {
		dhcp := &awstasks.DHCPOptions{
			Name:              s(b.ClusterName()),
			Lifecycle:         b.Lifecycle,
			DomainNameServers: s("AmazonProvidedDNS"),

			Tags:   tags,
			Shared: fi.Bool(sharedVPC),
		}
		if b.Region == "us-east-1" {
			dhcp.DomainName = s("ec2.internal")
		} else {
			dhcp.DomainName = s(b.Region + ".compute.internal")
		}
		c.AddTask(dhcp)

		c.AddTask(&awstasks.VPCDHCPOptionsAssociation{
			Name:        s(b.ClusterName()),
			Lifecycle:   b.Lifecycle,
			VPC:         b.LinkToVPC(),
			DHCPOptions: dhcp,
		})
	} else {
		// TODO: would be good to create these as shared, to verify them
	}

	allSubnetsShared := true
	allSubnetsSharedInZone := make(map[string]bool)
	for i := range b.Cluster.Spec.Subnets {
		subnetSpec := &b.Cluster.Spec.Subnets[i]
		allSubnetsSharedInZone[subnetSpec.Zone] = true
	}

	for i := range b.Cluster.Spec.Subnets {
		subnetSpec := &b.Cluster.Spec.Subnets[i]
		sharedSubnet := subnetSpec.ProviderID != ""
		if !sharedSubnet {
			allSubnetsShared = false
			allSubnetsSharedInZone[subnetSpec.Zone] = false
		}
	}

	// We always have a public route table, though for private networks it is only used for NGWs and ELBs
	var publicRouteTable *awstasks.RouteTable
	{
		// The internet gateway is the main entry point to the cluster.
		igw := &awstasks.InternetGateway{
			Name:      s(b.ClusterName()),
			Lifecycle: b.Lifecycle,
			VPC:       b.LinkToVPC(),
			Shared:    fi.Bool(sharedVPC),
		}
		igw.Tags = b.CloudTags(*igw.Name, *igw.Shared)
		c.AddTask(igw)

		if !allSubnetsShared {
			// The route table is not shared if we're creating a subnet for our cluster
			// That subnet will be owned, and will be associated with our RouteTable.
			// On deletion we delete the subnet & the route table.
			sharedRouteTable := false
			routeTableTags := b.CloudTags(vpcName, sharedRouteTable)
			routeTableTags[awsup.TagNameKopsRole] = "public"
			publicRouteTable = &awstasks.RouteTable{
				Name:      s(b.ClusterName()),
				Lifecycle: b.Lifecycle,

				VPC: b.LinkToVPC(),

				Tags:   routeTableTags,
				Shared: fi.Bool(sharedRouteTable),
			}
			c.AddTask(publicRouteTable)

			// TODO: Validate when allSubnetsShared
			c.AddTask(&awstasks.Route{
				Name:            s("0.0.0.0/0"),
				Lifecycle:       b.Lifecycle,
				CIDR:            s("0.0.0.0/0"),
				RouteTable:      publicRouteTable,
				InternetGateway: igw,
			})
		}
	}

	privateZones := sets.NewString()

	for i := range b.Cluster.Spec.Subnets {
		subnetSpec := &b.Cluster.Spec.Subnets[i]
		sharedSubnet := subnetSpec.ProviderID != ""
		subnetName := subnetSpec.Name + "." + b.ClusterName()
		tags := b.CloudTags(subnetName, sharedSubnet)

		// Apply tags so that Kubernetes knows which subnets should be used for internal/external ELBs
		switch subnetSpec.Type {
		case kops.SubnetTypePublic, kops.SubnetTypeUtility:
			tags[aws.TagNameSubnetPublicELB] = "1"

		case kops.SubnetTypePrivate:
			tags[aws.TagNameSubnetInternalELB] = "1"

		default:
			glog.V(2).Infof("unable to properly tag subnet %q because it has unknown type %q. Load balancers may be created in incorrect subnets", subnetSpec.Name, subnetSpec.Type)
		}

		tags["SubnetType"] = string(subnetSpec.Type)

		subnet := &awstasks.Subnet{
			Name:             s(subnetName),
			Lifecycle:        b.Lifecycle,
			VPC:              b.LinkToVPC(),
			AvailabilityZone: s(subnetSpec.Zone),
			CIDR:             s(subnetSpec.CIDR),
			Shared:           fi.Bool(sharedSubnet),
			Tags:             tags,
		}

		if subnetSpec.ProviderID != "" {
			subnet.ID = s(subnetSpec.ProviderID)
		}
		c.AddTask(subnet)

		switch subnetSpec.Type {
		case kops.SubnetTypePublic, kops.SubnetTypeUtility:
			if !sharedSubnet {
				c.AddTask(&awstasks.RouteTableAssociation{
					Name:       s(subnetSpec.Name + "." + b.ClusterName()),
					Lifecycle:  b.Lifecycle,
					RouteTable: publicRouteTable,
					Subnet:     subnet,
				})
			}

		case kops.SubnetTypePrivate:
			// Private subnets get a Network Gateway, and their own route table to associate them with the network gateway

			if !sharedSubnet {
				// Private Subnet Route Table Associations
				//
				// Map the Private subnet to the Private route table
				c.AddTask(&awstasks.RouteTableAssociation{
					Name:       s("private-" + subnetSpec.Name + "." + b.ClusterName()),
					Lifecycle:  b.Lifecycle,
					RouteTable: b.LinkToPrivateRouteTableInZone(subnetSpec.Zone),
					Subnet:     subnet,
				})

				// TODO: validate even if shared?
				privateZones.Insert(subnetSpec.Zone)
			}
		default:
			return fmt.Errorf("subnet %q has unknown type %q", subnetSpec.Name, subnetSpec.Type)
		}
	}

	// Loop over zones
	for i, zone := range privateZones.List() {

		utilitySubnet, err := b.LinkToUtilitySubnetInZone(zone)
		if err != nil {
			return err
		}

		var ngw *awstasks.NatGateway
		if b.Cluster.Spec.Subnets[i].Egress != "" {
			if strings.HasPrefix(b.Cluster.Spec.Subnets[i].Egress, "nat-") {

				ngw = &awstasks.NatGateway{
					Name:                 s(zone + "." + b.ClusterName()),
					Lifecycle:            b.Lifecycle,
					Subnet:               utilitySubnet,
					ID:                   s(b.Cluster.Spec.Subnets[i].Egress),
					AssociatedRouteTable: b.LinkToPrivateRouteTableInZone(zone),
					// If we're here, it means this NatGateway was specified, so we are Shared
					Shared: fi.Bool(true),
					Tags:   b.CloudTags(zone+"."+b.ClusterName(), true),
				}

				c.AddTask(ngw)

			} else {
				return fmt.Errorf("kops currently only supports re-use of NAT Gateways. We will support more eventually! Please see https://github.com/kubernetes/kops/issues/1530")
			}

		} else {

			// Every NGW needs a public (Elastic) IP address, every private
			// subnet needs a NGW, lets create it. We tie it to a subnet
			// so we can track it in AWS
			eip := &awstasks.ElasticIP{
				Name:                           s(zone + "." + b.ClusterName()),
				Lifecycle:                      b.Lifecycle,
				AssociatedNatGatewayRouteTable: b.LinkToPrivateRouteTableInZone(zone),
			}

			if b.Cluster.Spec.Subnets[i].PublicIP != "" {
				eip.PublicIP = s(b.Cluster.Spec.Subnets[i].PublicIP)
				eip.Tags = b.CloudTags(*eip.Name, true)
			} else {
				eip.Tags = b.CloudTags(*eip.Name, false)
			}

			c.AddTask(eip)
			// NAT Gateway
			//
			// All private subnets will need a NGW, one per zone
			//
			// The instances in the private subnet can access the Internet by
			// using a network address translation (NAT) gateway that resides
			// in the public subnet.

			//var ngw = &awstasks.NatGateway{}
			ngw = &awstasks.NatGateway{
				Name:                 s(zone + "." + b.ClusterName()),
				Lifecycle:            b.Lifecycle,
				Subnet:               utilitySubnet,
				ElasticIP:            eip,
				AssociatedRouteTable: b.LinkToPrivateRouteTableInZone(zone),
				Tags:                 b.CloudTags(zone+"."+b.ClusterName(), false),
			}
			c.AddTask(ngw)
		}

		// Private Route Table
		//
		// The private route table that will route to the NAT Gateway
		// We create an owned route table if we created any subnet in that zone.
		// Otherwise we consider it shared.
		routeTableShared := allSubnetsSharedInZone[zone]
		routeTableTags := b.CloudTags(b.NamePrivateRouteTableInZone(zone), routeTableShared)
		routeTableTags[awsup.TagNameKopsRole] = "private-" + zone
		rt := &awstasks.RouteTable{
			Name:      s(b.NamePrivateRouteTableInZone(zone)),
			VPC:       b.LinkToVPC(),
			Lifecycle: b.Lifecycle,

			Shared: fi.Bool(routeTableShared),
			Tags:   routeTableTags,
		}
		c.AddTask(rt)

		// Private Routes
		//
		// Routes for the private route table.
		// Will route to the NAT Gateway
		c.AddTask(&awstasks.Route{
			Name:       s("private-" + zone + "-0.0.0.0/0"),
			Lifecycle:  b.Lifecycle,
			CIDR:       s("0.0.0.0/0"),
			RouteTable: rt,
			NatGateway: ngw,
		})

	}

	return nil
}
<|endoftext|>


<commit_before>package monitor

import (
	"context"
	"fmt"
	"regexp"
	"strings"
	"time"

	"github.com/openshift/origin/pkg/monitor/monitorapi"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes"
)

func startEventMonitoring(ctx context.Context, m Recorder, client kubernetes.Interface) {
	reMatchFirstQuote := regexp.MustCompile(`"([^"]+)"( in (\d+(\.\d+)?(s|ms)$))?`)

	go func() {
		for {
			select {
			case <-ctx.Done():
				return
			default:
			}

			// filter out events written "now" but with significantly older start times (events
			// created in test jobs are the most common)
			significantlyBeforeNow := time.Now().UTC().Add(-15 * time.Minute)

			events, err := client.CoreV1().Events("").List(ctx, metav1.ListOptions{Limit: 1})
			if err != nil {
				continue
			}
			rv := events.ResourceVersion

			for i := range events.Items {
				m.RecordResource("events", &events.Items[i])
			}

			for expired := false; !expired; {
				w, err := client.CoreV1().Events("").Watch(ctx, metav1.ListOptions{ResourceVersion: rv})
				if err != nil {
					if errors.IsResourceExpired(err) {
						break
					}
					continue
				}
				w = watch.Filter(w, func(in watch.Event) (watch.Event, bool) {
					// TODO: gathering all events results in a 4x increase in e2e.log size, but is is
					//       valuable enough to gather that the cost is worth it
					// return in, filterToSystemNamespaces(in.Object)
					return in, true
				})
				func() {
					defer w.Stop()
					for event := range w.ResultChan() {
						switch event.Type {
						case watch.Added, watch.Modified:
							obj, ok := event.Object.(*corev1.Event)
							if !ok {
								continue
							}
							m.RecordResource("events", obj)

							// Temporary hack by dgoodwin, we're missing events here that show up later in
							// gather-extra/events.json. Adding some output to see if we can isolate what we saw
							// and where it might have been filtered out.
							osEvent := false
							if obj.Reason == "OSUpdateStaged" || obj.Reason == "OSUpdateStarted" {
								osEvent = true
								fmt.Printf("Watch received OS update event: %s - %s - %s\n",
									obj.Reason, obj.InvolvedObject.Name, obj.LastTimestamp.Format(time.RFC3339))

							}
							t := obj.LastTimestamp.Time
							if t.IsZero() {
								t = obj.EventTime.Time
							}
							if t.IsZero() {
								t = obj.CreationTimestamp.Time
							}
							if t.Before(significantlyBeforeNow) {
								if osEvent {
									fmt.Printf("OS update event filtered for being too old: %s - %s - %s (now: %s)\n",
										obj.Reason, obj.InvolvedObject.Name, obj.LastTimestamp.Format(time.RFC3339),
										time.Now().Format(time.RFC3339))
								}
								break
							}

							message := obj.Message
							if obj.Count > 1 {
								message += fmt.Sprintf(" (%d times)", obj.Count)
							}

							if obj.InvolvedObject.Kind == "Node" {
								if node, err := client.CoreV1().Nodes().Get(ctx, obj.InvolvedObject.Name, metav1.GetOptions{}); err == nil {
									message = fmt.Sprintf("roles/%s %s", nodeRoles(node), message)
								}
							}

							// special case some very common events
							switch obj.Reason {
							case "":
							case "Scheduled":
								if obj.InvolvedObject.Kind == "Pod" {
									if strings.HasPrefix(message, "Successfully assigned ") {
										if i := strings.Index(message, " to "); i != -1 {
											node := message[i+4:]
											message = fmt.Sprintf("node/%s reason/%s", node, obj.Reason)
											break
										}
									}
								}
								message = fmt.Sprintf("reason/%s %s", obj.Reason, message)
							case "Started", "Created", "Killing":
								if obj.InvolvedObject.Kind == "Pod" {
									if containerName, ok := eventForContainer(obj.InvolvedObject.FieldPath); ok {
										message = fmt.Sprintf("container/%s reason/%s", containerName, obj.Reason)
										break
									}
								}
								message = fmt.Sprintf("reason/%s %s", obj.Reason, message)
							case "Pulling", "Pulled":
								if obj.InvolvedObject.Kind == "Pod" {
									if containerName, ok := eventForContainer(obj.InvolvedObject.FieldPath); ok {
										if m := reMatchFirstQuote.FindStringSubmatch(obj.Message); m != nil {
											if len(m) > 3 {
												if d, err := time.ParseDuration(m[3]); err == nil {
													message = fmt.Sprintf("container/%s reason/%s duration/%.3fs image/%s", containerName, obj.Reason, d.Seconds(), m[1])
													break
												}
											}
											message = fmt.Sprintf("container/%s reason/%s image/%s", containerName, obj.Reason, m[1])
											break
										}
									}
								}
								message = fmt.Sprintf("reason/%s %s", obj.Reason, message)
							default:
								message = fmt.Sprintf("reason/%s %s", obj.Reason, message)
							}
							condition := monitorapi.Condition{
								Level:   monitorapi.Info,
								Locator: locateEvent(obj),
								Message: message,
							}
							if obj.Type == corev1.EventTypeWarning {
								condition.Level = monitorapi.Warning
							}
							m.RecordAt(t, condition)
						case watch.Error:
							var message string
							if status, ok := event.Object.(*metav1.Status); ok {
								if err := errors.FromObject(status); err != nil && errors.IsResourceExpired(err) {
									expired = true
									return
								}
								message = status.Message
							} else {
								message = fmt.Sprintf("event object was not a Status: %T", event.Object)
							}
							m.Record(monitorapi.Condition{
								Level:   monitorapi.Info,
								Locator: "kube-apiserver",
								Message: fmt.Sprintf("received an error while watching events: %s", message),
							})
							return
						default:
						}
					}
				}()
			}
		}
	}()
}

func eventForContainer(fieldPath string) (string, bool) {
	if !strings.HasSuffix(fieldPath, "}") {
		return "", false
	}
	fieldPath = strings.TrimSuffix(fieldPath, "}")
	switch {
	case strings.HasPrefix(fieldPath, "spec.containers{"):
		return strings.TrimPrefix(fieldPath, "spec.containers{"), true
	case strings.HasPrefix(fieldPath, "spec.initContainers{"):
		return strings.TrimPrefix(fieldPath, "spec.initContainers{"), true
	default:
		return "", false
	}
}
<commit_msg>Attempt to fix lost events with improved watch resource version handling.<commit_after>package monitor

import (
	"context"
	"fmt"
	"regexp"
	"strings"
	"time"

	"github.com/openshift/origin/pkg/monitor/monitorapi"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes"
)

func startEventMonitoring(ctx context.Context, m Recorder, client kubernetes.Interface) {
	reMatchFirstQuote := regexp.MustCompile(`"([^"]+)"( in (\d+(\.\d+)?(s|ms)$))?`)

	go func() {
		// Track our last observed resource version from each event, used to re-establish the watch
		// when it's requested rv gets too old for the server. (which may happen when apiservers cycle)
		var rv string
		for {
			select {
			case <-ctx.Done():
				return
			default:
			}

			// filter out events written "now" but with significantly older start times (events
			// created in test jobs are the most common)
			significantlyBeforeNow := time.Now().UTC().Add(-15 * time.Minute)

			// Doing our own List + Watch here, cannot use an Informer as it will group similar events, when we need
			// each individual.

			if rv == "" {
				events, err := client.CoreV1().Events("").List(ctx, metav1.ListOptions{Limit: 1})
				if err != nil {
					continue
				}
				rv = events.ResourceVersion
				fmt.Printf("Using initial resource version from event list: %s\n", rv)
				for i := range events.Items {
					m.RecordResource("events", &events.Items[i])
				}
			} else {
				// Re-use the last resource version we observed.
				fmt.Printf("Using last observed resource version: %s\n", rv)
			}

			for expired := false; !expired; {
				w, err := client.CoreV1().Events("").Watch(ctx, metav1.ListOptions{ResourceVersion: rv})
				if err != nil {
					if errors.IsResourceExpired(err) {
						break
					}
					continue
				}
				w = watch.Filter(w, func(in watch.Event) (watch.Event, bool) {
					// TODO: gathering all events results in a 4x increase in e2e.log size, but is is
					//       valuable enough to gather that the cost is worth it
					// return in, filterToSystemNamespaces(in.Object)
					return in, true
				})
				func() {
					defer w.Stop()
					for event := range w.ResultChan() {
						switch event.Type {
						case watch.Added, watch.Modified:
							obj, ok := event.Object.(*corev1.Event)
							if !ok {
								continue
							}
							// Record the observed rv version, re-used if we lose our watch connection and re-establish
							// to prevent missed events.
							rv = obj.ResourceVersion
							m.RecordResource("events", obj)

							// Temporary hack by dgoodwin, we're missing events here that show up later in
							// gather-extra/events.json. Adding some output to see if we can isolate what we saw
							// and where it might have been filtered out.
							// TODO: monitor for occurrences of this string, may no longer be needed given the
							// new rv handling logic added above.
							osEvent := false
							if obj.Reason == "OSUpdateStaged" || obj.Reason == "OSUpdateStarted" {
								osEvent = true
								fmt.Printf("Watch received OS update event: %s - %s - %s\n",
									obj.Reason, obj.InvolvedObject.Name, obj.LastTimestamp.Format(time.RFC3339))

							}
							t := obj.LastTimestamp.Time
							if t.IsZero() {
								t = obj.EventTime.Time
							}
							if t.IsZero() {
								t = obj.CreationTimestamp.Time
							}
							if t.Before(significantlyBeforeNow) {
								if osEvent {
									fmt.Printf("OS update event filtered for being too old: %s - %s - %s (now: %s)\n",
										obj.Reason, obj.InvolvedObject.Name, obj.LastTimestamp.Format(time.RFC3339),
										time.Now().Format(time.RFC3339))
								}
								break
							}

							message := obj.Message
							if obj.Count > 1 {
								message += fmt.Sprintf(" (%d times)", obj.Count)
							}

							if obj.InvolvedObject.Kind == "Node" {
								if node, err := client.CoreV1().Nodes().Get(ctx, obj.InvolvedObject.Name, metav1.GetOptions{}); err == nil {
									message = fmt.Sprintf("roles/%s %s", nodeRoles(node), message)
								}
							}

							// special case some very common events
							switch obj.Reason {
							case "":
							case "Scheduled":
								if obj.InvolvedObject.Kind == "Pod" {
									if strings.HasPrefix(message, "Successfully assigned ") {
										if i := strings.Index(message, " to "); i != -1 {
											node := message[i+4:]
											message = fmt.Sprintf("node/%s reason/%s", node, obj.Reason)
											break
										}
									}
								}
								message = fmt.Sprintf("reason/%s %s", obj.Reason, message)
							case "Started", "Created", "Killing":
								if obj.InvolvedObject.Kind == "Pod" {
									if containerName, ok := eventForContainer(obj.InvolvedObject.FieldPath); ok {
										message = fmt.Sprintf("container/%s reason/%s", containerName, obj.Reason)
										break
									}
								}
								message = fmt.Sprintf("reason/%s %s", obj.Reason, message)
							case "Pulling", "Pulled":
								if obj.InvolvedObject.Kind == "Pod" {
									if containerName, ok := eventForContainer(obj.InvolvedObject.FieldPath); ok {
										if m := reMatchFirstQuote.FindStringSubmatch(obj.Message); m != nil {
											if len(m) > 3 {
												if d, err := time.ParseDuration(m[3]); err == nil {
													message = fmt.Sprintf("container/%s reason/%s duration/%.3fs image/%s", containerName, obj.Reason, d.Seconds(), m[1])
													break
												}
											}
											message = fmt.Sprintf("container/%s reason/%s image/%s", containerName, obj.Reason, m[1])
											break
										}
									}
								}
								message = fmt.Sprintf("reason/%s %s", obj.Reason, message)
							default:
								message = fmt.Sprintf("reason/%s %s", obj.Reason, message)
							}
							condition := monitorapi.Condition{
								Level:   monitorapi.Info,
								Locator: locateEvent(obj),
								Message: message,
							}
							if obj.Type == corev1.EventTypeWarning {
								condition.Level = monitorapi.Warning
							}
							m.RecordAt(t, condition)
						case watch.Error:
							var message string
							if status, ok := event.Object.(*metav1.Status); ok {
								if err := errors.FromObject(status); err != nil && errors.IsResourceExpired(err) {
									expired = true
									return
								}
								message = status.Message
							} else {
								message = fmt.Sprintf("event object was not a Status: %T", event.Object)
							}
							m.Record(monitorapi.Condition{
								Level:   monitorapi.Info,
								Locator: "kube-apiserver",
								Message: fmt.Sprintf("received an error while watching events: %s", message),
							})
							return
						default:
						}
					}
				}()
			}
		}
	}()
}

func eventForContainer(fieldPath string) (string, bool) {
	if !strings.HasSuffix(fieldPath, "}") {
		return "", false
	}
	fieldPath = strings.TrimSuffix(fieldPath, "}")
	switch {
	case strings.HasPrefix(fieldPath, "spec.containers{"):
		return strings.TrimPrefix(fieldPath, "spec.containers{"), true
	case strings.HasPrefix(fieldPath, "spec.initContainers{"):
		return strings.TrimPrefix(fieldPath, "spec.initContainers{"), true
	default:
		return "", false
	}
}
<|endoftext|>


<commit_before>package nginx

import (
	"github.com/dynport/urknall"
	"github.com/dynport/urknall/cmd"
	"github.com/dynport/urknall/utils"
)

func New(version string) *Package {
	return &Package{Version: version}
}

type Package struct {
	Version            string `urknall:"default=1.4.4"`
	HeadersMoreVersion string `urknall:"default=0.24"`
	SyslogPatchVersion string `urknall:"default=1.3.14"`
}

func (pkg *Package) Package(r *urknall.Runlist) {
	//srcDir := "/opt/src/nginx-" + pkg.Version
	syslogPatchPath := "/tmp/nginx_syslog_patch"
	fileName := "syslog_{{ .SyslogPatchVersion }}.patch"
	r.Add(
		cmd.InstallPackages("build-essential", "curl", "libpcre3", "libpcre3-dev", "libssl-dev", "libpcrecpp0", "zlib1g-dev", "libgd2-xpm-dev"),
		cmd.DownloadAndExtract(pkg.url(), "/opt/src"),
		cmd.Mkdir(syslogPatchPath, "root", 0755),
		cmd.DownloadToFile("https://raw.github.com/yaoweibin/nginx_syslog_patch/master/config", syslogPatchPath+"/config", "root", 0644),
		cmd.DownloadToFile("https://raw.github.com/yaoweibin/nginx_syslog_patch/master/"+fileName, syslogPatchPath+"/"+fileName, "root", 0644),
		cmd.And(
			"cd /opt/src/nginx-{{ .Version }}",
			"patch -p1 < "+syslogPatchPath+"/"+fileName,
		),
		cmd.DownloadToFile("https://github.com/agentzh/headers-more-nginx-module/archive/v{{ .HeadersMoreVersion }}.tar.gz", "/opt/src/headers-more-nginx-module-{{ .HeadersMoreVersion }}.tar.gz", "root", 0644),
		cmd.And(
			"cd /opt/src",
			"tar xvfz headers-more-nginx-module-{{ .HeadersMoreVersion }}.tar.gz",
		),
		cmd.And(
			"cd /opt/src/nginx-{{ .Version }}",
			"./configure --with-http_ssl_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_spdy_module --add-module=/tmp/nginx_syslog_patch --add-module=/opt/src/headers-more-nginx-module-{{ .HeadersMoreVersion }} --prefix=/opt/nginx-{{ .Version }}",
			"make",
			"make install",
		),
		cmd.WriteFile("/etc/init/nginx.conf", utils.MustRenderTemplate(upstartScript, pkg), "root", 0644),
	)
}

func (pkg *Package) WriteConfigCommand(b []byte) cmd.Command {
	return cmd.WriteFile(pkg.InstallPath()+"/conf/nginx.conf", string(b), "root", 0644)
}

func (pkg *Package) BinPath() string {
	return pkg.InstallPath() + "/sbin/nginx"
}

func (pkg *Package) ReloadCommand() string {
	return utils.MustRenderTemplate("{{ . }} -t && {{ . }} -s reload", pkg.BinPath())
}

const upstartScript = `# nginx

description "nginx http daemon"
author "George Shammas <georgyo@gmail.com>"

start on (filesystem and net-device-up IFACE=lo)
stop on runlevel [!2345]

env DAEMON={{ .InstallPath }}/sbin/nginx
env PID=/var/run/nginx.pid

expect fork
respawn
respawn limit 10 5
#oom never

pre-start script
        $DAEMON -t
        if [ $? -ne 0 ]
                then exit $?
        fi
end script

exec $DAEMON
`

func (pkg *Package) url() string {
	return "http://nginx.org/download/" + pkg.fileName()
}

func (pkg *Package) InstallPath() string {
	return "/opt/nginx-" + pkg.Version
}

func (pkg *Package) fileName() string {
	return pkg.name() + ".tar.gz"
}

func (pkg *Package) name() string {
	return "nginx-" + pkg.Version
}
<commit_msg>allow installing nginx to /usr/local/nginx (also nice for docker)<commit_after>package nginx

import (
	"github.com/dynport/urknall"
	"github.com/dynport/urknall/cmd"
	"github.com/dynport/urknall/utils"
)

func New(version string) *Package {
	return &Package{Version: version}
}

type Package struct {
	Version            string `urknall:"default=1.4.4"`
	HeadersMoreVersion string `urknall:"default=0.24"`
	SyslogPatchVersion string `urknall:"default=1.3.14"`
	Local              bool   // install to /usr/local/nginx
}

func (pkg *Package) Package(r *urknall.Runlist) {
	syslogPatchPath := "/tmp/nginx_syslog_patch"
	fileName := "syslog_{{ .SyslogPatchVersion }}.patch"
	r.Add(
		cmd.InstallPackages("build-essential", "curl", "libpcre3", "libpcre3-dev", "libssl-dev", "libpcrecpp0", "zlib1g-dev", "libgd2-xpm-dev"),
		cmd.DownloadAndExtract(pkg.url(), "/opt/src"),
		cmd.Mkdir(syslogPatchPath, "root", 0755),
		cmd.DownloadToFile("https://raw.github.com/yaoweibin/nginx_syslog_patch/master/config", syslogPatchPath+"/config", "root", 0644),
		cmd.DownloadToFile("https://raw.github.com/yaoweibin/nginx_syslog_patch/master/"+fileName, syslogPatchPath+"/"+fileName, "root", 0644),
		cmd.And(
			"cd /opt/src/nginx-{{ .Version }}",
			"patch -p1 < "+syslogPatchPath+"/"+fileName,
		),
		cmd.DownloadToFile("https://github.com/agentzh/headers-more-nginx-module/archive/v{{ .HeadersMoreVersion }}.tar.gz", "/opt/src/headers-more-nginx-module-{{ .HeadersMoreVersion }}.tar.gz", "root", 0644),
		cmd.And(
			"cd /opt/src",
			"tar xvfz headers-more-nginx-module-{{ .HeadersMoreVersion }}.tar.gz",
		),
		cmd.And(
			"cd /opt/src/nginx-{{ .Version }}",
			"./configure --with-http_ssl_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_spdy_module --add-module=/tmp/nginx_syslog_patch --add-module=/opt/src/headers-more-nginx-module-{{ .HeadersMoreVersion }} --prefix={{ .InstallPath }}",
			"make",
			"make install",
		),
		cmd.WriteFile("/etc/init/nginx.conf", utils.MustRenderTemplate(upstartScript, pkg), "root", 0644),
	)
}

func (pkg *Package) InstallPath() string {
	if pkg.Local {
		return "/usr/local/nginx"
	}
	return "/opt/nginx-{{ .Version }}"
}

func (pkg *Package) WriteConfigCommand(b []byte) cmd.Command {
	return cmd.WriteFile(pkg.InstallPath()+"/conf/nginx.conf", string(b), "root", 0644)
}

func (pkg *Package) BinPath() string {
	return pkg.InstallPath() + "/sbin/nginx"
}

func (pkg *Package) ReloadCommand() string {
	return utils.MustRenderTemplate("{{ . }} -t && {{ . }} -s reload", pkg.BinPath())
}

const upstartScript = `# nginx

description "nginx http daemon"
author "George Shammas <georgyo@gmail.com>"

start on (filesystem and net-device-up IFACE=lo)
stop on runlevel [!2345]

env DAEMON={{ .InstallPath }}/sbin/nginx
env PID=/var/run/nginx.pid

expect fork
respawn
respawn limit 10 5
#oom never

pre-start script
        $DAEMON -t
        if [ $? -ne 0 ]
                then exit $?
        fi
end script

exec $DAEMON
`

func (pkg *Package) url() string {
	return "http://nginx.org/download/" + pkg.fileName()
}

func (pkg *Package) fileName() string {
	return pkg.name() + ".tar.gz"
}

func (pkg *Package) name() string {
	return "nginx-" + pkg.Version
}
<|endoftext|>


<commit_before>package paxos

import (
	"log"
)

type Result struct {
	seqn uint64
	v string
}

type instReq struct {
	seqn uint64
	ch chan *Instance
}

type Manager struct{
	self string
	nodes []string
	learned chan Result
	reqs chan instReq
	logger *log.Logger
}

func (m *Manager) process(next uint64, outs Putter) {
	instances := make(map[uint64]*Instance)
	for {
		select {
		case req := <-m.reqs:
			if req.seqn == 0 {
				req.seqn = next
			}
			inst, ok := instances[req.seqn]
			if !ok {
				// TODO read list of nodes from the data store
				cx := NewCluster(m.self, m.nodes, PutWrapper{req.seqn, 1, outs})
				inst = NewInstance(cx, m.logger)
				instances[req.seqn] = inst
				go func() {
					m.learned <- Result{req.seqn, inst.Value()}
				}()
			}
			req.ch <- inst
			if req.seqn >= next {
				next = req.seqn + 1
			}
		}
	}
}

func NewManager(start uint64, self string, nodes []string, outs Putter, logger *log.Logger) *Manager {
	m := &Manager{
		self: self,
		nodes: nodes,
		learned: make(chan Result),
		reqs: make(chan instReq),
		logger: logger,
	}

	go m.process(start, outs)

	return m
}

func (m *Manager) getInstance(seqn uint64) *Instance {
	ch := make(chan *Instance)
	m.reqs <- instReq{seqn, ch}
	return <-ch
}

func (m *Manager) Put(msg Message) {
	m.getInstance(msg.Seqn()).Put(msg)
}

func (m *Manager) Propose(v string) string {
	inst := m.getInstance(0)
	m.logger.Logf("paxos propose -> %q", v)
	inst.Propose(v)
	return inst.Value()
}

func (m *Manager) Recv() (uint64, string) {
	result := <-m.learned
	m.logger.Logf("paxos %d learned <- %q", result.seqn, result.v)
	return result.seqn, result.v
}

<commit_msg>refactor<commit_after>package paxos

import (
	"log"
)

type Result struct {
	seqn uint64
	v string
}

type instReq struct {
	seqn uint64
	ch chan *Instance
}

type Manager struct{
	self string
	nodes []string
	learned chan Result
	reqs chan instReq
	logger *log.Logger
}

func (m *Manager) process(next uint64, outs Putter) {
	instances := make(map[uint64]*Instance)
	for req := range m.reqs {
		if req.seqn == 0 {
			req.seqn = next
		}
		inst, ok := instances[req.seqn]
		if !ok {
			// TODO read list of nodes from the data store
			cx := NewCluster(m.self, m.nodes, PutWrapper{req.seqn, 1, outs})
			inst = NewInstance(cx, m.logger)
			instances[req.seqn] = inst
			go func() {
				m.learned <- Result{req.seqn, inst.Value()}
			}()
		}
		req.ch <- inst
		if req.seqn >= next {
			next = req.seqn + 1
		}
	}
}

func NewManager(start uint64, self string, nodes []string, outs Putter, logger *log.Logger) *Manager {
	m := &Manager{
		self: self,
		nodes: nodes,
		learned: make(chan Result),
		reqs: make(chan instReq),
		logger: logger,
	}

	go m.process(start, outs)

	return m
}

func (m *Manager) getInstance(seqn uint64) *Instance {
	ch := make(chan *Instance)
	m.reqs <- instReq{seqn, ch}
	return <-ch
}

func (m *Manager) Put(msg Message) {
	m.getInstance(msg.Seqn()).Put(msg)
}

func (m *Manager) Propose(v string) string {
	inst := m.getInstance(0)
	m.logger.Logf("paxos propose -> %q", v)
	inst.Propose(v)
	return inst.Value()
}

func (m *Manager) Recv() (uint64, string) {
	result := <-m.learned
	m.logger.Logf("paxos %d learned <- %q", result.seqn, result.v)
	return result.seqn, result.v
}

<|endoftext|>


<commit_before>// Package pod provides the logic for mapping a Kubernetes Pod to a
// LogicMonitor w.
package pod

import (
	"github.com/logicmonitor/k8s-argus/pkg/constants"
	"github.com/logicmonitor/k8s-argus/pkg/types"
	"github.com/logicmonitor/k8s-argus/pkg/utilities"
	log "github.com/sirupsen/logrus"
	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

const (
	resource = "pods"
)

// Watcher represents a watcher type that watches pods.
type Watcher struct {
	types.DeviceManager
}

// Resource is a function that implements the Watcher interface.
func (w *Watcher) Resource() string {
	return resource
}

// ObjType is a function that implements the Watcher interface.
func (w *Watcher) ObjType() runtime.Object {
	return &v1.Pod{}
}

// AddFunc is a function that implements the Watcher interface.
func (w *Watcher) AddFunc() func(obj interface{}) {
	return func(obj interface{}) {
		pod := obj.(*v1.Pod)
		// Require an IP address.
		if pod.Status.PodIP == "" {
			return
		}
		w.add(pod)
	}
}

// UpdateFunc is a function that implements the Watcher interface.
func (w *Watcher) UpdateFunc() func(oldObj, newObj interface{}) {
	return func(oldObj, newObj interface{}) {
		old := oldObj.(*v1.Pod)
		new := newObj.(*v1.Pod)

		// If the old pod does not have an IP, then there is no way we could
		// have added it to LogicMonitor. Therefore, it must be a new w.
		if old.Status.PodIP == "" && new.Status.PodIP != "" {
			w.add(new)
			return
		}

		if old.Status.PodIP != new.Status.PodIP {
			w.update(old, new)
		}

		if new.Status.Phase == v1.PodSucceeded {
			if err := w.DeleteByName(old.Name); err != nil {
				log.Errorf("Failed to delete pod: %v", err)
				return
			}
			log.Infof("Deleted pod %s", old.Name)
		}
	}
}

// DeleteFunc is a function that implements the Watcher interface.
// nolint: dupl
func (w *Watcher) DeleteFunc() func(obj interface{}) {
	return func(obj interface{}) {
		pod := obj.(*v1.Pod)

		// Delete the pod.
		if w.Config().DeleteDevices {
			if err := w.DeleteByName(pod.Name); err != nil {
				log.Errorf("Failed to delete pod: %v", err)
				return
			}
			log.Infof("Deleted pod %s", pod.Name)
			return
		}

		// Move the pod.
		w.move(pod)
	}
}

// nolint: dupl
func (w *Watcher) add(pod *v1.Pod) {
	if _, err := w.Add(
		w.args(pod, constants.PodCategory)...,
	); err != nil {
		log.Errorf("Failed to add pod %q: %v", pod.Name, err)
		return
	}
	log.Infof("Added pod %q", pod.Name)
}

func (w *Watcher) update(old, new *v1.Pod) {
	if _, err := w.UpdateAndReplaceByName(
		old.Name,
		w.args(new, constants.PodCategory)...,
	); err != nil {
		log.Errorf("Failed to update pod %q: %v", new.Name, err)
		return
	}
	log.Infof("Updated pod %q", old.Name)
}

func (w *Watcher) move(pod *v1.Pod) {
	if _, err := w.UpdateAndReplaceFieldByName(pod.Name, constants.CustomPropertiesFieldName, w.args(pod, constants.PodDeletedCategory)...); err != nil {
		log.Errorf("Failed to move pod %q: %v", pod.Name, err)
		return
	}
	log.Infof("Moved pod %q", pod.Name)
}

func (w *Watcher) args(pod *v1.Pod, category string) []types.DeviceOption {
	categories := utilities.BuildSystemCategoriesFromLabels(category, pod.Labels)
	return []types.DeviceOption{
		w.Name(pod.Name),
		w.DisplayName(pod.Name),
		w.SystemCategories(categories),
		w.Auto("name", pod.Name),
		w.Auto("namespace", pod.Namespace),
		w.Auto("nodename", pod.Spec.NodeName),
		w.Auto("selflink", pod.SelfLink),
		w.Auto("uid", string(pod.UID)),
		w.System("ips", pod.Status.PodIP),
	}
}
<commit_msg>fix(pods): check pod success before status (#71)<commit_after>// Package pod provides the logic for mapping a Kubernetes Pod to a
// LogicMonitor w.
package pod

import (
	"github.com/logicmonitor/k8s-argus/pkg/constants"
	"github.com/logicmonitor/k8s-argus/pkg/types"
	"github.com/logicmonitor/k8s-argus/pkg/utilities"
	log "github.com/sirupsen/logrus"
	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

const (
	resource = "pods"
)

// Watcher represents a watcher type that watches pods.
type Watcher struct {
	types.DeviceManager
}

// Resource is a function that implements the Watcher interface.
func (w *Watcher) Resource() string {
	return resource
}

// ObjType is a function that implements the Watcher interface.
func (w *Watcher) ObjType() runtime.Object {
	return &v1.Pod{}
}

// AddFunc is a function that implements the Watcher interface.
func (w *Watcher) AddFunc() func(obj interface{}) {
	return func(obj interface{}) {
		pod := obj.(*v1.Pod)
		// Require an IP address.
		if pod.Status.PodIP == "" {
			return
		}
		w.add(pod)
	}
}

// UpdateFunc is a function that implements the Watcher interface.
func (w *Watcher) UpdateFunc() func(oldObj, newObj interface{}) {
	return func(oldObj, newObj interface{}) {
		old := oldObj.(*v1.Pod)
		new := newObj.(*v1.Pod)

		// If the old pod does not have an IP, then there is no way we could
		// have added it to LogicMonitor. Therefore, it must be a new w.
		if old.Status.PodIP == "" && new.Status.PodIP != "" {
			w.add(new)
			return
		}

		if new.Status.Phase == v1.PodSucceeded {
			if err := w.DeleteByName(old.Name); err != nil {
				log.Errorf("Failed to delete pod: %v", err)
				return
			}
			log.Infof("Deleted pod %s", old.Name)
			return
		}

		if old.Status.PodIP != new.Status.PodIP {
			w.update(old, new)
		}
	}
}

// DeleteFunc is a function that implements the Watcher interface.
// nolint: dupl
func (w *Watcher) DeleteFunc() func(obj interface{}) {
	return func(obj interface{}) {
		pod := obj.(*v1.Pod)

		// Delete the pod.
		if w.Config().DeleteDevices {
			if err := w.DeleteByName(pod.Name); err != nil {
				log.Errorf("Failed to delete pod: %v", err)
				return
			}
			log.Infof("Deleted pod %s", pod.Name)
			return
		}

		// Move the pod.
		w.move(pod)
	}
}

// nolint: dupl
func (w *Watcher) add(pod *v1.Pod) {
	if _, err := w.Add(
		w.args(pod, constants.PodCategory)...,
	); err != nil {
		log.Errorf("Failed to add pod %q: %v", pod.Name, err)
		return
	}
	log.Infof("Added pod %q", pod.Name)
}

func (w *Watcher) update(old, new *v1.Pod) {
	if _, err := w.UpdateAndReplaceByName(
		old.Name,
		w.args(new, constants.PodCategory)...,
	); err != nil {
		log.Errorf("Failed to update pod %q: %v", new.Name, err)
		return
	}
	log.Infof("Updated pod %q", old.Name)
}

func (w *Watcher) move(pod *v1.Pod) {
	if _, err := w.UpdateAndReplaceFieldByName(pod.Name, constants.CustomPropertiesFieldName, w.args(pod, constants.PodDeletedCategory)...); err != nil {
		log.Errorf("Failed to move pod %q: %v", pod.Name, err)
		return
	}
	log.Infof("Moved pod %q", pod.Name)
}

func (w *Watcher) args(pod *v1.Pod, category string) []types.DeviceOption {
	categories := utilities.BuildSystemCategoriesFromLabels(category, pod.Labels)
	return []types.DeviceOption{
		w.Name(pod.Name),
		w.DisplayName(pod.Name),
		w.SystemCategories(categories),
		w.Auto("name", pod.Name),
		w.Auto("namespace", pod.Namespace),
		w.Auto("nodename", pod.Spec.NodeName),
		w.Auto("selflink", pod.SelfLink),
		w.Auto("uid", string(pod.UID)),
		w.System("ips", pod.Status.PodIP),
	}
}
<|endoftext|>


<commit_before>package txtdirect

import (
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestParsePlaceholders(t *testing.T) {
	tests := []struct {
		url       string
		requested string
		expected  string
	}{
		{
			"example.com{uri}",
			"https://example.com/?test=test",
			"example.com/?test=test",
		},
		{
			"example.com{uri}/{~test}",
			"https://example.com/?test=test",
			"example.com/?test=test/test",
		},
		{
			"example.com{uri}/{>Test}",
			"https://example.com/?test=test",
			"example.com/?test=test/test-header",
		},
		{
			"example.com{uri}/{?test}",
			"https://example.com/?test=test",
			"example.com/?test=test/test",
		},
		{
			"subdomain.example.com/{label1}",
			"https://subdomain.example.com/subdomain",
			"subdomain.example.com/subdomain",
		},
		{
			"subdomain.example.com/{label2}",
			"https://subdomain.example.com/example",
			"subdomain.example.com/example",
		},
		{
			"subdomain.example.com/{label3}",
			"https://subdomain.example.com/com",
			"subdomain.example.com/com",
		},
	}
	for _, test := range tests {
		req := httptest.NewRequest("GET", test.requested, nil)
		req.AddCookie(&http.Cookie{Name: "test", Value: "test"})
		req.Header.Add("Test", "test-header")
		result, err := parsePlaceholders(test.url, req)
		if err != nil {
			t.Fatal(err)
		}
		if result != test.expected {
			t.Errorf("Expected %s, got %s", test.expected, result)
		}
	}
}

func TestParseLabelLessThanOneFails(t *testing.T) {
	url := "example.com/{label0}"
	req := httptest.NewRequest("GET", "https://example.com/test", nil)
	_, err := parsePlaceholders(url, req)
	if err == nil {
		t.Errorf("Expected error, got nil")
	}
}

func TestParseLabelTooHighFails(t *testing.T) {
	url := "example.com/{label9000}"
	req := httptest.NewRequest("GET", "https://example.com/test", nil)
	_, err := parsePlaceholders(url, req)
	if err == nil {
		t.Errorf("Expected error, got nil")
	}
}
<commit_msg>Add {dir} placeholder test<commit_after>package txtdirect

import (
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestParsePlaceholders(t *testing.T) {
	tests := []struct {
		url       string
		requested string
		expected  string
	}{
		{
			"example.com{uri}",
			"https://example.com/?test=test",
			"example.com/?test=test",
		},
		{
			"example.com{uri}/{~test}",
			"https://example.com/?test=test",
			"example.com/?test=test/test",
		},
		{
			"example.com{uri}/{>Test}",
			"https://example.com/?test=test",
			"example.com/?test=test/test-header",
		},
		{
			"example.com{uri}/{?test}",
			"https://example.com/?test=test",
			"example.com/?test=test/test",
		},
		{
			"example.com{dir}",
			"https://example.com/directory/test",
			"example.com/directory/",
		},
		{
			"subdomain.example.com/{label1}",
			"https://subdomain.example.com/subdomain",
			"subdomain.example.com/subdomain",
		},
		{
			"subdomain.example.com/{label2}",
			"https://subdomain.example.com/example",
			"subdomain.example.com/example",
		},
		{
			"subdomain.example.com/{label3}",
			"https://subdomain.example.com/com",
			"subdomain.example.com/com",
		},
	}
	for _, test := range tests {
		req := httptest.NewRequest("GET", test.requested, nil)
		req.AddCookie(&http.Cookie{Name: "test", Value: "test"})
		req.Header.Add("Test", "test-header")
		result, err := parsePlaceholders(test.url, req)
		if err != nil {
			t.Fatal(err)
		}
		if result != test.expected {
			t.Errorf("Expected %s, got %s", test.expected, result)
		}
	}
}

func TestParseLabelLessThanOneFails(t *testing.T) {
	url := "example.com/{label0}"
	req := httptest.NewRequest("GET", "https://example.com/test", nil)
	_, err := parsePlaceholders(url, req)
	if err == nil {
		t.Errorf("Expected error, got nil")
	}
}

func TestParseLabelTooHighFails(t *testing.T) {
	url := "example.com/{label9000}"
	req := httptest.NewRequest("GET", "https://example.com/test", nil)
	_, err := parsePlaceholders(url, req)
	if err == nil {
		t.Errorf("Expected error, got nil")
	}
}
<|endoftext|>


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

package fuseops

import (
	"reflect"
	"sync"

	"github.com/jacobsa/bazilfuse"
	"golang.org/x/net/context"
)

// A helper for embedding common behavior.
type commonOp struct {
	opType      string
	ctx         context.Context
	r           bazilfuse.Request
	log         func(int, string, ...interface{})
	opsInFlight *sync.WaitGroup
}

func describeOpType(t reflect.Type) (desc string) {
	// TODO(jacobsa): Make this nicer.
	desc = t.String()
	return
}

func (o *commonOp) init(
	opType reflect.Type,
	r bazilfuse.Request,
	log func(int, string, ...interface{}),
	opsInFlight *sync.WaitGroup) {
	o.opType = describeOpType(opType)
	o.ctx = context.Background()
	o.r = r
	o.log = log
	o.opsInFlight = opsInFlight
}

func (o *commonOp) Header() OpHeader {
	bh := o.r.Hdr()
	return OpHeader{
		Uid: bh.Uid,
		Gid: bh.Gid,
	}
}

func (o *commonOp) Context() context.Context {
	return o.ctx
}

func (o *commonOp) Logf(format string, v ...interface{}) {
	const calldepth = 2
	o.log(calldepth, format, v...)
}

func (o *commonOp) respondErr(err error) {
	if err == nil {
		panic("Expect non-nil here.")
	}

	o.Logf(
		"-> (%s) error: %v",
		o.opType,
		err)

	o.r.RespondError(err)
}

// Respond with the supplied response struct, which must be accepted by a
// method called Respond on o.r.
//
// Special case: nil means o.r.Respond accepts no parameters.
func (o *commonOp) respond(resp interface{}) {
	// Find the Respond method.
	v := reflect.ValueOf(o.r)
	respond := v.MethodByName("Respond")

	// Special case: handle successful ops with no response struct.
	if resp == nil {
		o.Logf("-> (%s) OK", o.opType)
		respond.Call([]reflect.Value{})
		return
	}

	// Otherwise, pass along the response struct.
	o.Logf("-> %v", resp)
	respond.Call([]reflect.Value{reflect.ValueOf(resp)})
}
<commit_msg>Added reqtrace spans for fuse ops.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package fuseops

import (
	"reflect"
	"sync"

	"github.com/jacobsa/bazilfuse"
	"github.com/jacobsa/reqtrace"
	"golang.org/x/net/context"
)

// A helper for embedding common behavior.
type commonOp struct {
	ctx         context.Context
	opType      string
	r           bazilfuse.Request
	log         func(int, string, ...interface{})
	opsInFlight *sync.WaitGroup
	report      reqtrace.ReportFunc
}

func describeOpType(t reflect.Type) (desc string) {
	// TODO(jacobsa): Make this nicer.
	desc = t.String()
	return
}

func (o *commonOp) init(
	opType reflect.Type,
	r bazilfuse.Request,
	log func(int, string, ...interface{}),
	opsInFlight *sync.WaitGroup) {
	// Initialize basic fields.
	o.opType = describeOpType(opType)
	o.ctx = context.Background()
	o.r = r
	o.log = log
	o.opsInFlight = opsInFlight

	// Set up a trace span for this op.
	o.ctx, o.report = reqtrace.StartSpan(o.ctx, o.opType)
}

func (o *commonOp) Header() OpHeader {
	bh := o.r.Hdr()
	return OpHeader{
		Uid: bh.Uid,
		Gid: bh.Gid,
	}
}

func (o *commonOp) Context() context.Context {
	return o.ctx
}

func (o *commonOp) Logf(format string, v ...interface{}) {
	const calldepth = 2
	o.log(calldepth, format, v...)
}

func (o *commonOp) respondErr(err error) {
	if err == nil {
		panic("Expect non-nil here.")
	}

	o.report(err)

	o.Logf(
		"-> (%s) error: %v",
		o.opType,
		err)

	o.r.RespondError(err)
}

// Respond with the supplied response struct, which must be accepted by a
// method called Respond on o.r.
//
// Special case: nil means o.r.Respond accepts no parameters.
func (o *commonOp) respond(resp interface{}) {
	// We were successful.
	o.report(nil)

	// Find the Respond method.
	v := reflect.ValueOf(o.r)
	respond := v.MethodByName("Respond")

	// Special case: handle successful ops with no response struct.
	if resp == nil {
		o.Logf("-> (%s) OK", o.opType)
		respond.Call([]reflect.Value{})
		return
	}

	// Otherwise, pass along the response struct.
	o.Logf("-> %v", resp)
	respond.Call([]reflect.Value{reflect.ValueOf(resp)})
}
<|endoftext|>


<commit_before>package compress

import (
	"bytes"
	"compress/flate"
	"io"

	log "github.com/schollz/logger"
)

// CompressWithOption returns compressed data using the specified level
func CompressWithOption(src []byte, level int) []byte {
	compressedData := new(bytes.Buffer)
	compress(src, compressedData, level)
	return compressedData.Bytes()
}

// Compress returns a compressed byte slice.
func Compress(src []byte) []byte {
	compressedData := new(bytes.Buffer)
	compress(src, compressedData, -2)
	return compressedData.Bytes()
}

// Decompress returns a decompressed byte slice.
func Decompress(src []byte) []byte {
	compressedData := bytes.NewBuffer(src)
	deCompressedData := new(bytes.Buffer)
	decompress(compressedData, deCompressedData)
	return deCompressedData.Bytes()
}

// compress uses flate to compress a byte slice to a corresponding level
func compress(src []byte, dest io.Writer, level int) {
	compressor, err := flate.NewWriter(dest, level)
	if err != nil {
		log.Debugf("error level data: %v", err)
	}
	if _, err := compressor.Write(src); err != nil {
		log.Debugf("error writing data: %v", err)
	}
	compressor.Close()
}

// compress uses flate to decompress an io.Reader
func decompress(src io.Reader, dest io.Writer) {
	decompressor := flate.NewReader(src)
	if _, err := io.Copy(dest, decompressor); err != nil {
		log.Debugf("error copying data: %v", err)
	}
	decompressor.Close()
}
<commit_msg>fix possible panic of nil compressor<commit_after>package compress

import (
	"bytes"
	"compress/flate"
	"io"

	log "github.com/schollz/logger"
)

// CompressWithOption returns compressed data using the specified level
func CompressWithOption(src []byte, level int) []byte {
	compressedData := new(bytes.Buffer)
	compress(src, compressedData, level)
	return compressedData.Bytes()
}

// Compress returns a compressed byte slice.
func Compress(src []byte) []byte {
	compressedData := new(bytes.Buffer)
	compress(src, compressedData, -2)
	return compressedData.Bytes()
}

// Decompress returns a decompressed byte slice.
func Decompress(src []byte) []byte {
	compressedData := bytes.NewBuffer(src)
	deCompressedData := new(bytes.Buffer)
	decompress(compressedData, deCompressedData)
	return deCompressedData.Bytes()
}

// compress uses flate to compress a byte slice to a corresponding level
func compress(src []byte, dest io.Writer, level int) {
	compressor, err := flate.NewWriter(dest, level)
	if err != nil {
		log.Debugf("error level data: %v", err)
		return
	}
	if _, err := compressor.Write(src); err != nil {
		log.Debugf("error writing data: %v", err)
	}
	compressor.Close()
}

// compress uses flate to decompress an io.Reader
func decompress(src io.Reader, dest io.Writer) {
	decompressor := flate.NewReader(src)
	if _, err := io.Copy(dest, decompressor); err != nil {
		log.Debugf("error copying data: %v", err)
	}
	decompressor.Close()
}
<|endoftext|>


<commit_before>package the_platinum_searcher

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"

	"github.com/monochromegane/conflag"
	"github.com/monochromegane/go-home"
	"github.com/monochromegane/terminal"
)

const version = "2.1.1"

const (
	ExitCodeOK = iota
	ExitCodeError
)

var opts Option

type PlatinumSearcher struct {
	Out, Err io.Writer
}

func (p PlatinumSearcher) Run(args []string) int {

	parser := newOptionParser(&opts)

	conflag.LongHyphen = true
	conflag.BoolValue = false
	for _, c := range []string{
		filepath.Join(os.Getenv("XDG_CONFIG_HOME"), "pt", "config.toml"),
		filepath.Join(home.Dir(), ".ptconfig.toml"),
		".ptconfig.toml",
	} {
		if args, err := conflag.ArgsFrom(c); err == nil {
			parser.ParseArgs(args)
		}
	}

	args, err := parser.ParseArgs(args)
	if err != nil {
		return ExitCodeError
	}

	if opts.Version {
		fmt.Printf("pt version %s\n", version)
		return ExitCodeOK
	}

	if len(args) == 0 && !opts.SearchOption.EnableFilesWithRegexp {
		parser.WriteHelp(p.Err)
		return ExitCodeError
	}

	if !terminal.IsTerminal(os.Stdout) {
		if !opts.OutputOption.ForceColor {
			opts.OutputOption.EnableColor = false
		}
		if !opts.OutputOption.ForceGroup {
			opts.OutputOption.EnableGroup = false
		}
	}

	if p.givenStdin() && p.noRootPathIn(args) {
		opts.SearchOption.SearchStream = true
	}

	if opts.SearchOption.EnableFilesWithRegexp {
		args = append([]string{""}, args...)
	}

	if opts.OutputOption.Count {
		opts.OutputOption.Before = 0
		opts.OutputOption.After = 0
		opts.OutputOption.Context = 0
	}

	search := search{
		roots: p.rootsFrom(args),
		out:   p.Out,
	}
	if err = search.start(p.patternFrom(args)); err != nil {
		fmt.Fprintf(p.Err, "%s\n", err)
		return ExitCodeError
	}
	return ExitCodeOK
}

func (p PlatinumSearcher) patternFrom(args []string) string {
	return args[0]
}

func (p PlatinumSearcher) rootsFrom(args []string) []string {
	if len(args) > 1 {
		return args[1:]
	} else {
		return []string{"."}
	}
}

func (p PlatinumSearcher) givenStdin() bool {
	fi, err := os.Stdin.Stat()
	if runtime.GOOS == "windows" {
		if err == nil {
			return true
		}
	} else {
		if err != nil {
			return false
		}

		mode := fi.Mode()
		if (mode&os.ModeNamedPipe != 0) || mode.IsRegular() {
			return true
		}
	}
	return false
}

func (p PlatinumSearcher) noRootPathIn(args []string) bool {
	return len(args) == 1
}
<commit_msg>Bumped version to 2.1.2.<commit_after>package the_platinum_searcher

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"

	"github.com/monochromegane/conflag"
	"github.com/monochromegane/go-home"
	"github.com/monochromegane/terminal"
)

const version = "2.1.2"

const (
	ExitCodeOK = iota
	ExitCodeError
)

var opts Option

type PlatinumSearcher struct {
	Out, Err io.Writer
}

func (p PlatinumSearcher) Run(args []string) int {

	parser := newOptionParser(&opts)

	conflag.LongHyphen = true
	conflag.BoolValue = false
	for _, c := range []string{
		filepath.Join(os.Getenv("XDG_CONFIG_HOME"), "pt", "config.toml"),
		filepath.Join(home.Dir(), ".ptconfig.toml"),
		".ptconfig.toml",
	} {
		if args, err := conflag.ArgsFrom(c); err == nil {
			parser.ParseArgs(args)
		}
	}

	args, err := parser.ParseArgs(args)
	if err != nil {
		return ExitCodeError
	}

	if opts.Version {
		fmt.Printf("pt version %s\n", version)
		return ExitCodeOK
	}

	if len(args) == 0 && !opts.SearchOption.EnableFilesWithRegexp {
		parser.WriteHelp(p.Err)
		return ExitCodeError
	}

	if !terminal.IsTerminal(os.Stdout) {
		if !opts.OutputOption.ForceColor {
			opts.OutputOption.EnableColor = false
		}
		if !opts.OutputOption.ForceGroup {
			opts.OutputOption.EnableGroup = false
		}
	}

	if p.givenStdin() && p.noRootPathIn(args) {
		opts.SearchOption.SearchStream = true
	}

	if opts.SearchOption.EnableFilesWithRegexp {
		args = append([]string{""}, args...)
	}

	if opts.OutputOption.Count {
		opts.OutputOption.Before = 0
		opts.OutputOption.After = 0
		opts.OutputOption.Context = 0
	}

	search := search{
		roots: p.rootsFrom(args),
		out:   p.Out,
	}
	if err = search.start(p.patternFrom(args)); err != nil {
		fmt.Fprintf(p.Err, "%s\n", err)
		return ExitCodeError
	}
	return ExitCodeOK
}

func (p PlatinumSearcher) patternFrom(args []string) string {
	return args[0]
}

func (p PlatinumSearcher) rootsFrom(args []string) []string {
	if len(args) > 1 {
		return args[1:]
	} else {
		return []string{"."}
	}
}

func (p PlatinumSearcher) givenStdin() bool {
	fi, err := os.Stdin.Stat()
	if runtime.GOOS == "windows" {
		if err == nil {
			return true
		}
	} else {
		if err != nil {
			return false
		}

		mode := fi.Mode()
		if (mode&os.ModeNamedPipe != 0) || mode.IsRegular() {
			return true
		}
	}
	return false
}

func (p PlatinumSearcher) noRootPathIn(args []string) bool {
	return len(args) == 1
}
<|endoftext|>


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

package format

import (
	"bytes"
	"github.com/trivago/gollum/core"
)

// Trim is a formatter that removes part of the message.
// Configuration example
//
//    - format.Trim:
//        LeftSeparator: ""
//        RightSeparator: ""
//        LeftOffset: 0
//        RightOffset: 0
//        ApplyTo: "payload" # payload or <metaKey>
//
type Trim struct {
	core.SimpleFormatter `gollumdoc:"embed_type"`
	leftSeparator        []byte `config:"LeftSeparator"`
	rightSeparator       []byte `config:"RightSeparator"`
	leftOffset           int    `config:"LeftOffset" default:"0"`
	rightOffset          int    `config:"RightOffset" default:"0"`
}

func init() {
	core.TypeRegistry.Register(Trim{})
}

// Configure initializes this formatter with values from a plugin config.
func (format *Trim) Configure(conf core.PluginConfigReader) {
}

// ApplyFormatter update message payload
func (format *Trim) ApplyFormatter(msg *core.Message) error {
	content := format.GetAppliedContent(msg)
	offset := len(content)

	if len(format.rightSeparator) > 0 {
		rightIdx := bytes.LastIndex(content, format.rightSeparator)
		if rightIdx > 0 {
			offset = rightIdx
		}
	}
	format.extendContent(&content, offset-format.rightOffset)

	offset = format.leftOffset
	if len(format.leftSeparator) > 0 {
		leftIdx := bytes.Index(msg.GetPayload(), format.leftSeparator)
		leftIdx++
		if leftIdx > 0 {
			offset += leftIdx
		}
	}
	content = content[offset:]

	format.SetAppliedContent(msg, content)
	return nil
}

func (format *Trim) extendContent(content *[]byte, size int) {
	switch {
	case size == len(*content):
	case size <= cap(*content):
		*content = (*content)[:size]
	default:
		old := *content
		*content = core.MessageDataPool.Get(size)
		copy(*content, old)
	}

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

package format

import (
	"bytes"
	"github.com/trivago/gollum/core"
)

// Trim formatter
//
// This formatter searches for separator strings and removes all data left or
// right of this separator.
//
// Parameters
//
// - LeftSeparator: The string to search for. Searching starts from the left
// side of the data. If an empty string is given this parameter is ignored.
// By default this parameter is set to "".
//
// - RightSeparator: The string to search for. Searching starts from the right
// side of the data. If an empty string is given this parameter is ignored.
// By default this parameter is set to "".
//
// - LeftOffset: Defines the search start index when using LeftSeparator.
// By default this parameter is set to 0.
//
// - RightOffset: Defines the search start index when using RightSeparator.
// Counting starts from the right side of the message.
// By default this parameter is set to 0.
//
// Examples
//
// This example will reduce data like "foo[bar[foo]bar]foo" to "bar[foo]bar".
//
//  exampleConsumer:
//    Type: consumer.Console
//    Streams: "*"
//    Modulators:
//      - format.Trim:
//	      LeftSeparator: "["
//	      RightSeparator: "]"
type Trim struct {
	core.SimpleFormatter `gollumdoc:"embed_type"`
	leftSeparator        []byte `config:"LeftSeparator"`
	rightSeparator       []byte `config:"RightSeparator"`
	leftOffset           int    `config:"LeftOffset" default:"0"`
	rightOffset          int    `config:"RightOffset" default:"0"`
}

func init() {
	core.TypeRegistry.Register(Trim{})
}

// Configure initializes this formatter with values from a plugin config.
func (format *Trim) Configure(conf core.PluginConfigReader) {
}

// ApplyFormatter update message payload
func (format *Trim) ApplyFormatter(msg *core.Message) error {
	content := format.GetAppliedContent(msg)
	offset := len(content)

	if len(format.rightSeparator) > 0 {
		rightIdx := bytes.LastIndex(content, format.rightSeparator)
		if rightIdx > 0 {
			offset = rightIdx
		}
	}
	format.extendContent(&content, offset-format.rightOffset)

	offset = format.leftOffset
	if len(format.leftSeparator) > 0 {
		leftIdx := bytes.Index(msg.GetPayload(), format.leftSeparator)
		leftIdx++
		if leftIdx > 0 {
			offset += leftIdx
		}
	}
	content = content[offset:]

	format.SetAppliedContent(msg, content)
	return nil
}

func (format *Trim) extendContent(content *[]byte, size int) {
	switch {
	case size == len(*content):
	case size <= cap(*content):
		*content = (*content)[:size]
	default:
		old := *content
		*content = core.MessageDataPool.Get(size)
		copy(*content, old)
	}

	return
}
<|endoftext|>


<commit_before>package formats

import (
	"io"

	"github.com/anaminus/rbxmk"
	"github.com/anaminus/rbxmk/dump"
	"github.com/anaminus/rbxmk/rtypes"
	"github.com/robloxapi/types"
)

func decodeScript(r io.Reader, className string) (v types.Value, err error) {
	script := rtypes.NewInstance(className, nil)
	s, err := io.ReadAll(r)
	if err != nil {
		return nil, err
	}
	script.Set("Source", types.ProtectedString(s))
	return script, nil
}

func canDecodeInstance(g rbxmk.Global, f rbxmk.FormatOptions, typeName string) bool {
	return typeName == "Instance"
}

func encodeScript(g rbxmk.Global, f rbxmk.FormatOptions, w io.Writer, v types.Value) error {
	s, ok := rtypes.Stringable(v)
	if !ok {
		return cannotEncode(v)
	}
	_, err := w.Write([]byte(s))
	return err
}

func init() { register(ModuleScriptLua) }
func ModuleScriptLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "modulescript.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "ModuleScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/modulescript.lua:Summary",
				Description: "Formats/modulescript.lua:Description",
			}
		},
	}
}

func init() { register(ScriptLua) }
func ScriptLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "script.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "Script")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/script.lua:Summary",
				Description: "Formats/script.lua:Description",
			}
		},
	}
}

func init() { register(LocalScriptLua) }
func LocalScriptLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "localscript.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "LocalScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/localscript.lua:Summary",
				Description: "Formats/localscript.lua:Description",
			}
		},
	}
}

func init() { register(Lua) }
func Lua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "ModuleScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/lua:Summary",
				Description: "Formats/lua:Description",
			}
		},
	}
}

func init() { register(ServerLua) }
func ServerLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "server.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "Script")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/server.lua:Summary",
				Description: "Formats/server.lua:Description",
			}
		},
	}
}

func init() { register(ClientLua) }
func ClientLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "client.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "LocalScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/client.lua:Summary",
				Description: "Formats/client.lua:Description",
			}
		},
	}
}

////////////////////////////////////////////////////////////////////////////////
// Luau

func init() { register(ModuleScriptLuau) }
func ModuleScriptLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "modulescript.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "ModuleScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/modulescript.luau:Summary",
				Description: "Formats/modulescript.luau:Description",
			}
		},
	}
}

func init() { register(ScriptLuau) }
func ScriptLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "script.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "Script")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/script.luau:Summary",
				Description: "Formats/script.luau:Description",
			}
		},
	}
}

func init() { register(LocalScriptLuau) }
func LocalScriptLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "localscript.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "LocalScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/localscript.luau:Summary",
				Description: "Formats/localscript.luau:Description",
			}
		},
	}
}

func init() { register(Luau) }
func Luau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "ModuleScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/lua:Summary",
				Description: "Formats/lua:Description",
			}
		},
	}
}

func init() { register(ServerLuau) }
func ServerLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "server.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "Script")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/server.luau:Summary",
				Description: "Formats/server.luau:Description",
			}
		},
	}
}

func init() { register(ClientLuau) }
func ClientLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "client.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "LocalScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/client.luau:Summary",
				Description: "Formats/client.luau:Description",
			}
		},
	}
}
<commit_msg>Fix incorrect name for Luau format.<commit_after>package formats

import (
	"io"

	"github.com/anaminus/rbxmk"
	"github.com/anaminus/rbxmk/dump"
	"github.com/anaminus/rbxmk/rtypes"
	"github.com/robloxapi/types"
)

func decodeScript(r io.Reader, className string) (v types.Value, err error) {
	script := rtypes.NewInstance(className, nil)
	s, err := io.ReadAll(r)
	if err != nil {
		return nil, err
	}
	script.Set("Source", types.ProtectedString(s))
	return script, nil
}

func canDecodeInstance(g rbxmk.Global, f rbxmk.FormatOptions, typeName string) bool {
	return typeName == "Instance"
}

func encodeScript(g rbxmk.Global, f rbxmk.FormatOptions, w io.Writer, v types.Value) error {
	s, ok := rtypes.Stringable(v)
	if !ok {
		return cannotEncode(v)
	}
	_, err := w.Write([]byte(s))
	return err
}

func init() { register(ModuleScriptLua) }
func ModuleScriptLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "modulescript.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "ModuleScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/modulescript.lua:Summary",
				Description: "Formats/modulescript.lua:Description",
			}
		},
	}
}

func init() { register(ScriptLua) }
func ScriptLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "script.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "Script")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/script.lua:Summary",
				Description: "Formats/script.lua:Description",
			}
		},
	}
}

func init() { register(LocalScriptLua) }
func LocalScriptLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "localscript.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "LocalScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/localscript.lua:Summary",
				Description: "Formats/localscript.lua:Description",
			}
		},
	}
}

func init() { register(Lua) }
func Lua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "ModuleScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/lua:Summary",
				Description: "Formats/lua:Description",
			}
		},
	}
}

func init() { register(ServerLua) }
func ServerLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "server.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "Script")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/server.lua:Summary",
				Description: "Formats/server.lua:Description",
			}
		},
	}
}

func init() { register(ClientLua) }
func ClientLua() rbxmk.Format {
	return rbxmk.Format{
		Name:       "client.lua",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "LocalScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/client.lua:Summary",
				Description: "Formats/client.lua:Description",
			}
		},
	}
}

////////////////////////////////////////////////////////////////////////////////
// Luau

func init() { register(ModuleScriptLuau) }
func ModuleScriptLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "modulescript.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "ModuleScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/modulescript.luau:Summary",
				Description: "Formats/modulescript.luau:Description",
			}
		},
	}
}

func init() { register(ScriptLuau) }
func ScriptLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "script.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "Script")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/script.luau:Summary",
				Description: "Formats/script.luau:Description",
			}
		},
	}
}

func init() { register(LocalScriptLuau) }
func LocalScriptLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "localscript.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "LocalScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/localscript.luau:Summary",
				Description: "Formats/localscript.luau:Description",
			}
		},
	}
}

func init() { register(Luau) }
func Luau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "ModuleScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/lua:Summary",
				Description: "Formats/lua:Description",
			}
		},
	}
}

func init() { register(ServerLuau) }
func ServerLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "server.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "Script")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/server.luau:Summary",
				Description: "Formats/server.luau:Description",
			}
		},
	}
}

func init() { register(ClientLuau) }
func ClientLuau() rbxmk.Format {
	return rbxmk.Format{
		Name:       "client.luau",
		MediaTypes: []string{"application/lua", "text/plain"},
		CanDecode:  canDecodeInstance,
		Decode: func(g rbxmk.Global, f rbxmk.FormatOptions, r io.Reader) (v types.Value, err error) {
			return decodeScript(r, "LocalScript")
		},
		Encode: encodeScript,
		Dump: func() dump.Format {
			return dump.Format{
				Summary:     "Formats/client.luau:Summary",
				Description: "Formats/client.luau:Description",
			}
		},
	}
}
<|endoftext|>


<commit_before>package components

import (
	"crypto/sha512"
	"encoding/hex"
	"log"
	"net/http"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/julienschmidt/httprouter"
)

//AuthHandler Handles authorization
func AuthHandler(response http.ResponseWriter, request *http.Request, routeParams httprouter.Params, jsonParams map[string]interface{}) {

	if username, usernameExists := jsonParams["username"]; usernameExists {
		if _, passwordExists := jsonParams["password"]; passwordExists {

			user, userErr := GetUser(username.(string))

			if userErr != nil {
				response.WriteHeader(http.StatusInternalServerError)
				response.Write([]byte(http.StatusText(http.StatusInternalServerError)))

				return
			}

			sha512Password := sha512.Sum512([]byte(jsonParams["password"].(string)))
			hexSha512Password := hex.EncodeToString(sha512Password[:])

			if hexSha512Password == user.Password {
				JWTToken := jwt.New(jwt.SigningMethodHS256)

				JWTToken.Claims["iat"] = time.Now()
				JWTToken.Claims["exp"] = time.Now().Add(time.Hour * 2)
				JWTToken.Claims["identity"] = user.Hash

				tokenString, tokenErr := JWTToken.SignedString([]byte("asdasdasd"))

				if tokenErr == nil {
					response.Write([]byte(tokenString))
				} else {
					response.WriteHeader(http.StatusInternalServerError)
					response.Write([]byte(tokenErr.Error()))
				}

				return
			}
		}
	}

	log.Println("Else")
	response.WriteHeader(http.StatusBadRequest)
	response.Write([]byte(http.StatusText(http.StatusBadRequest)))
}
<commit_msg>Fast as it can be<commit_after>package components

import (
	"crypto/sha512"
	"encoding/hex"
	"encoding/json"
	"log"
	"net/http"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/julienschmidt/httprouter"
)

//AccessToken Representation for the return of AuthHandler
type AccessToken struct {
	AccessToken string
}

//AuthHandler Handles authorization
func AuthHandler(response http.ResponseWriter, request *http.Request, routeParams httprouter.Params, jsonParams map[string]interface{}) {
	if username, usernameExists := jsonParams["username"]; usernameExists {
		if _, passwordExists := jsonParams["password"]; passwordExists {

			user, userErr := GetUser(username.(string))

			if userErr != nil {
				response.WriteHeader(http.StatusInternalServerError)
				response.Write([]byte(http.StatusText(http.StatusInternalServerError)))

				return
			}

			sha512Password := sha512.Sum512([]byte(jsonParams["password"].(string)))
			hexSha512Password := hex.EncodeToString(sha512Password[:])

			if hexSha512Password == user.Password {
				JWTToken := jwt.New(jwt.SigningMethodHS256)

				JWTToken.Claims["iat"] = time.Now()
				JWTToken.Claims["exp"] = time.Now().Add(time.Hour * 2)
				JWTToken.Claims["identity"] = user.Hash

				tokenString, tokenErr := JWTToken.SignedString([]byte("asdasdasd"))

				if tokenErr == nil {
					tokenString, _ := json.Marshal(AccessToken{AccessToken: tokenString})
					response.WriteHeader(http.StatusOK)
					response.Write([]byte(tokenString))
				} else {
					response.WriteHeader(http.StatusInternalServerError)
					response.Write([]byte(tokenErr.Error()))
				}

				return
			}
		}
	}

	log.Println("Else")
	response.WriteHeader(http.StatusBadRequest)
	response.Write([]byte(http.StatusText(http.StatusBadRequest)))
}
<|endoftext|>