<commit_before>/*
Copyright 2017 Google Inc.

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

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

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

package main

import (
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"

	"github.com/golang/glog"
	log "github.com/golang/glog"
	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"

	v3 "google.golang.org/api/monitoring/v3"

	"github.com/GoogleCloudPlatform/k8s-stackdriver/kubelet-to-gcm/monitor"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/kubelet-to-gcm/monitor/config"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/kubelet-to-gcm/monitor/controller"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/kubelet-to-gcm/monitor/kubelet"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

const (
	scope = "https://www.googleapis.com/auth/monitoring.write"
	//testPath = "https://test-monitoring.sandbox.googleapis.com"
)

var (
	schemaPrefix            = flag.String("schema-prefix", "k8s_", "MonitoredResource type prefix, to be appended by 'container', 'pod', and 'node'.")
	monitoredResourceLabels = flag.String("monitored-resource-labels", "", "Manually specified MonitoredResource labels.")
	// Flags to identify the Kubelet.
	zone            = flag.String("zone", "use-gce", "The zone where this kubelet lives.")
	project         = flag.String("project", "use-gce", "The project where this kubelet's host lives.")
	cluster         = flag.String("cluster", "use-gce", "The cluster where this kubelet holds membership.")
	clusterLocation = flag.String("cluster-location", "use-gce", "The location of the cluster where this kubelet holds membership.")
	kubeletInstance = flag.String("kubelet-instance", "use-gce", "The instance name the kubelet resides on.")
	kubeletHost     = flag.String("kubelet-host", "use-gce", "The kubelet's host name.")
	kubeletPort     = flag.Uint("kubelet-port", 10255, "The kubelet's port.")
	ctrlPort        = flag.Uint("controller-manager-port", 10252, "The kube-controller's port.")
	// Flags to control runtime behavior.
	res         = flag.Uint("resolution", 10, "The time, in seconds, to poll the Kubelet.")
	gcmEndpoint = flag.String("gcm-endpoint", "", "The GCM endpoint to hit. Defaults to the default endpoint.")
	port        = flag.Uint("port", 6062, "Port number used to expose metrics.")
)

func main() {
	flag.Set("logtostderr", "true") // This spoofs glog into teeing logs to stderr.

	defer log.Flush()
	flag.Parse()
	log.Infof("Invoked by %v", os.Args)

	resolution := time.Second * time.Duration(*res)

	monitoredResourceLabels := parseMonitoredResourceLabels(*monitoredResourceLabels)
	// Initialize the configuration.
	kubeletCfg, ctrlCfg, err := config.NewConfigs(*zone, *project, *cluster, *clusterLocation, *kubeletHost, *kubeletInstance, *schemaPrefix, monitoredResourceLabels, *kubeletPort, *ctrlPort, resolution)
	if err != nil {
		log.Fatalf("Failed to initialize configuration: %v", err)
	}

	// Create objects for kubelet monitoring.
	kubeletSrc, err := kubelet.NewSource(kubeletCfg)
	if err != nil {
		log.Fatalf("Failed to create a kubelet source with config %v: %v", kubeletCfg, err)
	}
	log.Infof("The kubelet source is initialized with config %v.", kubeletCfg)

	// Create objects for kube-controller monitoring.
	ctrlSrc, err := controller.NewSource(ctrlCfg)
	if err != nil {
		log.Fatalf("Failed to create a kube-controller source with config %v: %v", ctrlCfg, err)
	}
	log.Infof("The kube-controller source is initialized with config %v.", ctrlCfg)

	// Create a GCM client.
	client, err := google.DefaultClient(context.Background(), scope)
	if err != nil {
		log.Fatalf("Failed to create a client with default context and scope %s, err: %v", scope, err)
	}
	service, err := v3.New(client)
	if err != nil {
		log.Fatalf("Failed to create a GCM v3 API service object: %v", err)
	}
	// Determine the GCE endpoint.
	if *gcmEndpoint != "" {
		service.BasePath = *gcmEndpoint
	}
	log.Infof("Using GCM endpoint %q", service.BasePath)

	go func() {
		http.Handle("/metrics", promhttp.Handler())
		log.Error(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil))
	}()

	for {
		go monitor.Once(kubeletSrc, service)
		go monitor.Once(ctrlSrc, service)
		time.Sleep(resolution)
	}
}

func parseMonitoredResourceLabels(monitoredResourceLabelsStr string) map[string]string {
	labels := make(map[string]string)
	m, err := url.ParseQuery(monitoredResourceLabelsStr)
	if err != nil {
		glog.Fatalf("Error parsing 'monitored-resource-labels' field: '%v', with error message: '%s'.", monitoredResourceLabelsStr, err)
	}
	for k, v := range m {
		if len(v) != 1 {
			glog.Fatalf("Key '%v' in 'monitored-resource-labels' doesn't have exactly one value (it has '%v' now).", k, v)
		}
		labels[k] = v[0]
	}
	return labels
}
<commit_msg>Change default schemaPrefix flag in kubelet-to-gcm<commit_after>/*
Copyright 2017 Google Inc.

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

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

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

package main

import (
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"

	"github.com/golang/glog"
	log "github.com/golang/glog"
	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"

	v3 "google.golang.org/api/monitoring/v3"

	"github.com/GoogleCloudPlatform/k8s-stackdriver/kubelet-to-gcm/monitor"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/kubelet-to-gcm/monitor/config"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/kubelet-to-gcm/monitor/controller"
	"github.com/GoogleCloudPlatform/k8s-stackdriver/kubelet-to-gcm/monitor/kubelet"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

const (
	scope = "https://www.googleapis.com/auth/monitoring.write"
	//testPath = "https://test-monitoring.sandbox.googleapis.com"
)

var (
	schemaPrefix            = flag.String("schema-prefix", "", "MonitoredResource type prefix, to be appended by 'container', 'pod', and 'node'.")
	monitoredResourceLabels = flag.String("monitored-resource-labels", "", "Manually specified MonitoredResource labels.")
	// Flags to identify the Kubelet.
	zone            = flag.String("zone", "use-gce", "The zone where this kubelet lives.")
	project         = flag.String("project", "use-gce", "The project where this kubelet's host lives.")
	cluster         = flag.String("cluster", "use-gce", "The cluster where this kubelet holds membership.")
	clusterLocation = flag.String("cluster-location", "use-gce", "The location of the cluster where this kubelet holds membership.")
	kubeletInstance = flag.String("kubelet-instance", "use-gce", "The instance name the kubelet resides on.")
	kubeletHost     = flag.String("kubelet-host", "use-gce", "The kubelet's host name.")
	kubeletPort     = flag.Uint("kubelet-port", 10255, "The kubelet's port.")
	ctrlPort        = flag.Uint("controller-manager-port", 10252, "The kube-controller's port.")
	// Flags to control runtime behavior.
	res         = flag.Uint("resolution", 10, "The time, in seconds, to poll the Kubelet.")
	gcmEndpoint = flag.String("gcm-endpoint", "", "The GCM endpoint to hit. Defaults to the default endpoint.")
	port        = flag.Uint("port", 6062, "Port number used to expose metrics.")
)

func main() {
	flag.Set("logtostderr", "true") // This spoofs glog into teeing logs to stderr.

	defer log.Flush()
	flag.Parse()
	log.Infof("Invoked by %v", os.Args)

	resolution := time.Second * time.Duration(*res)

	monitoredResourceLabels := parseMonitoredResourceLabels(*monitoredResourceLabels)
	// Initialize the configuration.
	kubeletCfg, ctrlCfg, err := config.NewConfigs(*zone, *project, *cluster, *clusterLocation, *kubeletHost, *kubeletInstance, *schemaPrefix, monitoredResourceLabels, *kubeletPort, *ctrlPort, resolution)
	if err != nil {
		log.Fatalf("Failed to initialize configuration: %v", err)
	}

	// Create objects for kubelet monitoring.
	kubeletSrc, err := kubelet.NewSource(kubeletCfg)
	if err != nil {
		log.Fatalf("Failed to create a kubelet source with config %v: %v", kubeletCfg, err)
	}
	log.Infof("The kubelet source is initialized with config %v.", kubeletCfg)

	// Create objects for kube-controller monitoring.
	ctrlSrc, err := controller.NewSource(ctrlCfg)
	if err != nil {
		log.Fatalf("Failed to create a kube-controller source with config %v: %v", ctrlCfg, err)
	}
	log.Infof("The kube-controller source is initialized with config %v.", ctrlCfg)

	// Create a GCM client.
	client, err := google.DefaultClient(context.Background(), scope)
	if err != nil {
		log.Fatalf("Failed to create a client with default context and scope %s, err: %v", scope, err)
	}
	service, err := v3.New(client)
	if err != nil {
		log.Fatalf("Failed to create a GCM v3 API service object: %v", err)
	}
	// Determine the GCE endpoint.
	if *gcmEndpoint != "" {
		service.BasePath = *gcmEndpoint
	}
	log.Infof("Using GCM endpoint %q", service.BasePath)

	go func() {
		http.Handle("/metrics", promhttp.Handler())
		log.Error(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil))
	}()

	for {
		go monitor.Once(kubeletSrc, service)
		go monitor.Once(ctrlSrc, service)
		time.Sleep(resolution)
	}
}

func parseMonitoredResourceLabels(monitoredResourceLabelsStr string) map[string]string {
	labels := make(map[string]string)
	m, err := url.ParseQuery(monitoredResourceLabelsStr)
	if err != nil {
		glog.Fatalf("Error parsing 'monitored-resource-labels' field: '%v', with error message: '%s'.", monitoredResourceLabelsStr, err)
	}
	for k, v := range m {
		if len(v) != 1 {
			glog.Fatalf("Key '%v' in 'monitored-resource-labels' doesn't have exactly one value (it has '%v' now).", k, v)
		}
		labels[k] = v[0]
	}
	return labels
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"sync"
	"time"

	"github.com/Sirupsen/logrus"

	"github.com/TykTechnologies/tyk/config"
)

type NodeResponseOK struct {
	Status  string
	Message map[string]string
	Nonce   string
}

type DashboardServiceSender interface {
	Init() error
	Register() error
	DeRegister() error
	StartBeating() error
	StopBeating()
}

type HTTPDashboardHandler struct {
	RegistrationEndpoint   string
	DeRegistrationEndpoint string
	HeartBeatEndpoint      string
	Secret                 string

	heartBeatStopSentinel bool
}

func reLogin() {
	if !config.Global().UseDBAppConfigs {
		return
	}

	log.WithFields(logrus.Fields{
		"prefix": "main",
	}).Info("Registering node (again).")
	DashService.StopBeating()
	if err := DashService.DeRegister(); err != nil {
		log.WithFields(logrus.Fields{
			"prefix": "main",
		}).Error("Could not deregister: ", err)
	}

	time.Sleep(30 * time.Second)

	if err := DashService.Register(); err != nil {
		log.WithFields(logrus.Fields{
			"prefix": "main",
		}).Error("Could not register: ", err)
	} else {
		go DashService.StartBeating()
	}

	log.WithFields(logrus.Fields{
		"prefix": "main",
	}).Info("Recovering configurations, reloading...")
	var wg sync.WaitGroup
	wg.Add(1)
	reloadURLStructure(wg.Done)
	wg.Wait()
}

func (h *HTTPDashboardHandler) Init() error {
	h.RegistrationEndpoint = buildConnStr("/register/node")
	h.DeRegistrationEndpoint = buildConnStr("/system/node")
	h.HeartBeatEndpoint = buildConnStr("/register/ping")
	if h.Secret = config.Global().NodeSecret; h.Secret == "" {
		log.WithFields(logrus.Fields{
			"prefix": "main",
		}).Fatal("Node secret is not set, required for dashboard connection")
	}
	return nil
}

func (h *HTTPDashboardHandler) Register() error {
	req := h.newRequest(h.RegistrationEndpoint)

	c := &http.Client{Timeout: 5 * time.Second}
	resp, err := c.Do(req)

	if err != nil {
		log.Errorf("Request failed with error %v; retrying in 5s", err)
		time.Sleep(time.Second * 5)
		return h.Register()
	} else if resp != nil && resp.StatusCode != 200 {
		log.Errorf("Response failed with code %d; retrying in 5s", resp.StatusCode)
		time.Sleep(time.Second * 5)
		return h.Register()
	}

	defer resp.Body.Close()
	val := NodeResponseOK{}
	if err := json.NewDecoder(resp.Body).Decode(&val); err != nil {
		return err
	}

	// Set the NodeID
	var found bool
	NodeID, found = val.Message["NodeID"]
	if !found {
		log.Error("Failed to register node, retrying in 5s")
		time.Sleep(time.Second * 5)
		return h.Register()
	}

	log.WithFields(logrus.Fields{
		"prefix": "dashboard",
		"id":     NodeID,
	}).Info("Node registered")

	// Set the nonce
	ServiceNonce = val.Nonce
	log.Debug("Registration Finished: Nonce Set: ", ServiceNonce)

	return nil
}

func (h *HTTPDashboardHandler) StartBeating() error {
	for !h.heartBeatStopSentinel {
		if err := h.sendHeartBeat(); err != nil {
			log.Warning(err)
		}
		time.Sleep(time.Second * 2)
	}

	log.Info("Stopped Heartbeat")
	h.heartBeatStopSentinel = false
	return nil
}

func (h *HTTPDashboardHandler) StopBeating() {
	h.heartBeatStopSentinel = true
}

func (h *HTTPDashboardHandler) newRequest(endpoint string) *http.Request {
	req, err := http.NewRequest("GET", endpoint, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("authorization", h.Secret)
	req.Header.Set("x-tyk-hostname", hostDetails.Hostname)
	return req
}

func (h *HTTPDashboardHandler) sendHeartBeat() error {
	req := h.newRequest(h.HeartBeatEndpoint)
	req.Header.Set("x-tyk-nodeid", NodeID)
	req.Header.Set("x-tyk-nonce", ServiceNonce)

	c := &http.Client{Timeout: 5 * time.Second}
	resp, err := c.Do(req)
	if err != nil || resp.StatusCode != 200 {
		return errors.New("dashboard is down? Heartbeat is failing")
	}

	defer resp.Body.Close()
	val := NodeResponseOK{}
	if err := json.NewDecoder(resp.Body).Decode(&val); err != nil {
		return err
	}

	// Set the nonce
	ServiceNonce = val.Nonce
	//log.Debug("Heartbeat Finished: Nonce Set: ", ServiceNonce)

	return nil
}

func (h *HTTPDashboardHandler) DeRegister() error {
	req := h.newRequest(h.DeRegistrationEndpoint)

	req.Header.Set("x-tyk-nodeid", NodeID)
	req.Header.Set("x-tyk-nonce", ServiceNonce)

	c := &http.Client{Timeout: 5 * time.Second}
	resp, err := c.Do(req)
	if err != nil || resp.StatusCode != 200 {
		return fmt.Errorf("request failed with code %d and error %v", resp.StatusCode, err)
	}

	defer resp.Body.Close()
	val := NodeResponseOK{}
	if err := json.NewDecoder(resp.Body).Decode(&val); err != nil {
		return err
	}

	// Set the nonce
	ServiceNonce = val.Nonce
	log.Info("De-registered.")

	return nil
}
<commit_msg>add nil check to prevent panic<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"sync"
	"time"

	"github.com/Sirupsen/logrus"

	"github.com/TykTechnologies/tyk/config"
)

type NodeResponseOK struct {
	Status  string
	Message map[string]string
	Nonce   string
}

type DashboardServiceSender interface {
	Init() error
	Register() error
	DeRegister() error
	StartBeating() error
	StopBeating()
}

type HTTPDashboardHandler struct {
	RegistrationEndpoint   string
	DeRegistrationEndpoint string
	HeartBeatEndpoint      string
	Secret                 string

	heartBeatStopSentinel bool
}

func reLogin() {
	if !config.Global().UseDBAppConfigs {
		return
	}

	log.WithFields(logrus.Fields{
		"prefix": "main",
	}).Info("Registering node (again).")
	DashService.StopBeating()
	if err := DashService.DeRegister(); err != nil {
		log.WithFields(logrus.Fields{
			"prefix": "main",
		}).Error("Could not deregister: ", err)
	}

	time.Sleep(30 * time.Second)

	if err := DashService.Register(); err != nil {
		log.WithFields(logrus.Fields{
			"prefix": "main",
		}).Error("Could not register: ", err)
	} else {
		go DashService.StartBeating()
	}

	log.WithFields(logrus.Fields{
		"prefix": "main",
	}).Info("Recovering configurations, reloading...")
	var wg sync.WaitGroup
	wg.Add(1)
	reloadURLStructure(wg.Done)
	wg.Wait()
}

func (h *HTTPDashboardHandler) Init() error {
	h.RegistrationEndpoint = buildConnStr("/register/node")
	h.DeRegistrationEndpoint = buildConnStr("/system/node")
	h.HeartBeatEndpoint = buildConnStr("/register/ping")
	if h.Secret = config.Global().NodeSecret; h.Secret == "" {
		log.WithFields(logrus.Fields{
			"prefix": "main",
		}).Fatal("Node secret is not set, required for dashboard connection")
	}
	return nil
}

func (h *HTTPDashboardHandler) Register() error {
	req := h.newRequest(h.RegistrationEndpoint)

	c := &http.Client{Timeout: 5 * time.Second}
	resp, err := c.Do(req)

	if err != nil {
		log.Errorf("Request failed with error %v; retrying in 5s", err)
		time.Sleep(time.Second * 5)
		return h.Register()
	} else if resp != nil && resp.StatusCode != 200 {
		log.Errorf("Response failed with code %d; retrying in 5s", resp.StatusCode)
		time.Sleep(time.Second * 5)
		return h.Register()
	}

	defer resp.Body.Close()
	val := NodeResponseOK{}
	if err := json.NewDecoder(resp.Body).Decode(&val); err != nil {
		return err
	}

	// Set the NodeID
	var found bool
	NodeID, found = val.Message["NodeID"]
	if !found {
		log.Error("Failed to register node, retrying in 5s")
		time.Sleep(time.Second * 5)
		return h.Register()
	}

	log.WithFields(logrus.Fields{
		"prefix": "dashboard",
		"id":     NodeID,
	}).Info("Node registered")

	// Set the nonce
	ServiceNonce = val.Nonce
	log.Debug("Registration Finished: Nonce Set: ", ServiceNonce)

	return nil
}

func (h *HTTPDashboardHandler) StartBeating() error {
	for !h.heartBeatStopSentinel {
		if err := h.sendHeartBeat(); err != nil {
			log.Warning(err)
		}
		time.Sleep(time.Second * 2)
	}

	log.Info("Stopped Heartbeat")
	h.heartBeatStopSentinel = false
	return nil
}

func (h *HTTPDashboardHandler) StopBeating() {
	h.heartBeatStopSentinel = true
}

func (h *HTTPDashboardHandler) newRequest(endpoint string) *http.Request {
	req, err := http.NewRequest("GET", endpoint, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("authorization", h.Secret)
	req.Header.Set("x-tyk-hostname", hostDetails.Hostname)
	return req
}

func (h *HTTPDashboardHandler) sendHeartBeat() error {
	req := h.newRequest(h.HeartBeatEndpoint)
	req.Header.Set("x-tyk-nodeid", NodeID)
	req.Header.Set("x-tyk-nonce", ServiceNonce)

	c := &http.Client{Timeout: 5 * time.Second}
	resp, err := c.Do(req)
	if err != nil || resp.StatusCode != 200 {
		return errors.New("dashboard is down? Heartbeat is failing")
	}

	defer resp.Body.Close()
	val := NodeResponseOK{}
	if err := json.NewDecoder(resp.Body).Decode(&val); err != nil {
		return err
	}

	// Set the nonce
	ServiceNonce = val.Nonce
	//log.Debug("Heartbeat Finished: Nonce Set: ", ServiceNonce)

	return nil
}

func (h *HTTPDashboardHandler) DeRegister() error {
	req := h.newRequest(h.DeRegistrationEndpoint)

	req.Header.Set("x-tyk-nodeid", NodeID)
	req.Header.Set("x-tyk-nonce", ServiceNonce)

	c := &http.Client{Timeout: 5 * time.Second}
	resp, err := c.Do(req)

	if err != nil {
		return fmt.Errorf("deregister request failed with error %v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("deregister request failed with status %v", resp.StatusCode)
	}

	val := NodeResponseOK{}
	if err := json.NewDecoder(resp.Body).Decode(&val); err != nil {
		return err
	}

	// Set the nonce
	ServiceNonce = val.Nonce
	log.Info("De-registered.")

	return nil
}
<|endoftext|>


<commit_before>// Package reflector extends standard package reflect with useful utilities.
package reflector

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Converts value to kind. Panics if it can't be done.
type Converter func(value interface{}, kind reflect.Kind) interface{}

// Converter: requires value to be exactly of specified kind.
func NoConvert(value interface{}, kind reflect.Kind) interface{} {
	switch kind {
	case reflect.Bool:
		return value.(bool)

	case reflect.Int:
		return int64(value.(int))
	case reflect.Int8:
		return int64(value.(int8))
	case reflect.Int16:
		return int64(value.(int16))
	case reflect.Int32:
		return int64(value.(int32))
	case reflect.Int64:
		return value.(int64)

	case reflect.Uint:
		return uint64(value.(uint))
	case reflect.Uint8:
		return uint64(value.(uint8))
	case reflect.Uint16:
		return uint64(value.(uint16))
	case reflect.Uint32:
		return uint64(value.(uint32))
	case reflect.Uint64:
		return value.(uint64)
	case reflect.Uintptr:
		return uint64(value.(uintptr))

	case reflect.Float32:
		return float64(value.(float32))
	case reflect.Float64:
		return value.(float64)

	case reflect.String:
		return value.(string)
	}

	panic(fmt.Errorf("NoConvert: can't convert %#v to %s", value, kind))
}

// Converter: uses strconv.Parse* functions.
func Strconv(value interface{}, kind reflect.Kind) (res interface{}) {
	e := fmt.Errorf("Strconv: can't convert %#v to %s", value, kind)
	s := fmt.Sprint(value)

	switch kind {
	case reflect.Bool:
		res, e = strconv.ParseBool(s)
		if e != nil {
			panic(e)
		}
		return

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		res, e = strconv.ParseInt(s, 10, 64)
		if e != nil {
			panic(e)
		}
		return

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		res, e = strconv.ParseUint(s, 10, 64)
		if e != nil {
			panic(e)
		}
		return

	case reflect.Float32, reflect.Float64:
		res, e = strconv.ParseFloat(s, 64)
		if e != nil {
			panic(e)
		}
		return

	case reflect.String:
		return s
	}

	panic(e)
}

// Converts a struct to map.
// First argument is a pointer to struct.
// Second argument is a not-nil map which will be modified.
// Only exported struct fields are used.
// Tag may be used to change mapping between struct field and map key.
// Currently supports bool, ints, uints, floats, strings.
// Panics in case of error.
func StructToMap(StructPointer interface{}, Map map[string]interface{}, tag string) {
	structPointerType := reflect.TypeOf(StructPointer)
	if structPointerType.Kind() != reflect.Ptr {
		panic(fmt.Errorf("StructToMap: expected pointer to struct as first argument, got %s", structPointerType.Kind()))
	}

	structType := structPointerType.Elem()
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("StructToMap: expected pointer to struct as first argument, got pointer to %s", structType.Kind()))
	}

	s := reflect.ValueOf(StructPointer).Elem()

	var name string
	for i := 0; i < structType.NumField(); i++ {
		stf := structType.Field(i)
		if stf.PkgPath != "" {
			continue
		}

		name = ""
		if tag != "" {
			name = strings.Split(stf.Tag.Get(tag), ",")[0]
		}
		if name == "" {
			name = stf.Name
		}

		Map[name] = s.Field(i).Interface()
	}
}

// Converts a struct to map. Uses StructToMap().
// First argument is a struct.
// Second argument is a not-nil map which will be modified.
// Only exported struct fields are used.
// Tag may be used to change mapping between struct field and map key.
// Currently supports bool, ints, uints, floats, strings.
// Panics in case of error.
func StructValueToMap(Struct interface{}, Map map[string]interface{}, tag string) {
	structType := reflect.TypeOf(Struct)
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("StructValueToMap: expected struct as first argument, got %s", structType.Kind()))
	}

	v := reflect.New(reflect.TypeOf(Struct))
	v.Elem().Set(reflect.ValueOf(Struct))
	StructToMap(v.Interface(), Map, tag)
}

// Converts a slice of structs to a slice of maps. Uses StructValueToMap().
// First argument is a slice of structs.
// Second argument is a pointer to (possibly nil) slice of maps which will be set.
func StructsToMaps(Structs interface{}, Maps *[]map[string]interface{}, tag string) {
	sliceType := reflect.TypeOf(Structs)
	if sliceType.Kind() != reflect.Slice {
		panic(fmt.Errorf("Expected slice of structs as first argument, got %s", sliceType.Kind()))
	}

	structType := sliceType.Elem()
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("Expected slice of structs as first argument, got slice of %s", structType.Kind()))
	}

	structs := reflect.ValueOf(Structs)
	l := structs.Len()
	maps := reflect.MakeSlice(reflect.TypeOf([]map[string]interface{}{}), 0, l)

	for i := 0; i < l; i++ {
		m := make(map[string]interface{})
		StructValueToMap(structs.Index(i).Interface(), m, tag)
		maps = reflect.Append(maps, reflect.ValueOf(m))
	}

	reflect.ValueOf(Maps).Elem().Set(maps)
}

// Converts a map to struct using converter function.
// First argument is a map.
// Second argument is a not-nil pointer to struct which will be modified.
// Only exported struct fields are set. Omitted or extra values in map are ignored.
// Tag may be used to change mapping between struct field and map key.
// Currently supports bool, ints, uints, floats, strings.
// Panics in case of error.
func MapToStruct(Map map[string]interface{}, StructPointer interface{}, converter Converter, tag string) {
	structPointerType := reflect.TypeOf(StructPointer)
	if structPointerType.Kind() != reflect.Ptr {
		panic(fmt.Errorf("MapToStruct: expected pointer to struct as second argument, got %s", structPointerType.Kind()))
	}

	structType := structPointerType.Elem()
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("MapToStruct: expected pointer to struct as second argument, got pointer to %s", structType.Kind()))
	}
	s := reflect.ValueOf(StructPointer).Elem()

	var name string
	defer func() {
		e := recover()
		if e == nil {
			return
		}

		panic(fmt.Errorf("MapToStruct, field %s: %s", name, e))
	}()

	for i := 0; i < structType.NumField(); i++ {
		f := s.Field(i)
		if !f.CanSet() {
			continue
		}

		stf := structType.Field(i)
		name = ""
		if tag != "" {
			name = strings.Split(stf.Tag.Get(tag), ",")[0]
		}
		if name == "" {
			name = stf.Name
		}
		v, ok := Map[name]
		if !ok {
			continue
		}

		kind := f.Kind()
		switch kind {
		case reflect.Bool:
			f.SetBool(converter(v, kind).(bool))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			f.SetInt(converter(v, kind).(int64))

		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			f.SetUint(converter(v, kind).(uint64))

		case reflect.Float32, reflect.Float64:
			f.SetFloat(converter(v, kind).(float64))

		case reflect.String:
			f.SetString(converter(v, kind).(string))

		default:
			// not implemented
		}
	}

	return
}

// Converts a slice of maps to a slice of structs. Uses MapToStruct().
// First argument is a slice of maps.
// Second argument is a pointer to (possibly nil) slice of structs which will be set.
func MapsToStructs(Maps []map[string]interface{}, SlicePointer interface{}, converter Converter, tag string) {
	slicePointerType := reflect.TypeOf(SlicePointer)
	if slicePointerType.Kind() != reflect.Ptr {
		panic(fmt.Errorf("MapsToStructs: expected pointer to slice of structs as second argument, got %s", slicePointerType.Kind()))
	}

	sliceType := slicePointerType.Elem()
	if sliceType.Kind() != reflect.Slice {
		panic(fmt.Errorf("MapsToStructs: expected pointer to slice of structs as second argument, got pointer to %s", sliceType.Kind()))
	}

	structType := sliceType.Elem()
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("MapsToStructs: expected pointer to slice of structs as second argument, got pointer to slice of %s", structType.Kind()))
	}

	slice := reflect.MakeSlice(sliceType, 0, len(Maps))
	for _, m := range Maps {
		s := reflect.New(structType)
		MapToStruct(m, s.Interface(), converter, tag)
		slice = reflect.Append(slice, s.Elem())
	}
	reflect.ValueOf(SlicePointer).Elem().Set(slice)
}

// Variant of MapsToStructs() with relaxed signature.
func MapsToStructs2(Maps []interface{}, SlicePointer interface{}, converter Converter, tag string) {
	m := make([]map[string]interface{}, len(Maps))
	for index, i := range Maps {
		m[index] = i.(map[string]interface{})
	}
	MapsToStructs(m, SlicePointer, converter, tag)
}
<commit_msg>Skip "-" tags.<commit_after>// Package reflector extends standard package reflect with useful utilities.
package reflector

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Converts value to kind. Panics if it can't be done.
type Converter func(value interface{}, kind reflect.Kind) interface{}

// Converter: requires value to be exactly of specified kind.
func NoConvert(value interface{}, kind reflect.Kind) interface{} {
	switch kind {
	case reflect.Bool:
		return value.(bool)

	case reflect.Int:
		return int64(value.(int))
	case reflect.Int8:
		return int64(value.(int8))
	case reflect.Int16:
		return int64(value.(int16))
	case reflect.Int32:
		return int64(value.(int32))
	case reflect.Int64:
		return value.(int64)

	case reflect.Uint:
		return uint64(value.(uint))
	case reflect.Uint8:
		return uint64(value.(uint8))
	case reflect.Uint16:
		return uint64(value.(uint16))
	case reflect.Uint32:
		return uint64(value.(uint32))
	case reflect.Uint64:
		return value.(uint64)
	case reflect.Uintptr:
		return uint64(value.(uintptr))

	case reflect.Float32:
		return float64(value.(float32))
	case reflect.Float64:
		return value.(float64)

	case reflect.String:
		return value.(string)
	}

	panic(fmt.Errorf("NoConvert: can't convert %#v to %s", value, kind))
}

// Converter: uses strconv.Parse* functions.
func Strconv(value interface{}, kind reflect.Kind) (res interface{}) {
	e := fmt.Errorf("Strconv: can't convert %#v to %s", value, kind)
	s := fmt.Sprint(value)

	switch kind {
	case reflect.Bool:
		res, e = strconv.ParseBool(s)
		if e != nil {
			panic(e)
		}
		return

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		res, e = strconv.ParseInt(s, 10, 64)
		if e != nil {
			panic(e)
		}
		return

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		res, e = strconv.ParseUint(s, 10, 64)
		if e != nil {
			panic(e)
		}
		return

	case reflect.Float32, reflect.Float64:
		res, e = strconv.ParseFloat(s, 64)
		if e != nil {
			panic(e)
		}
		return

	case reflect.String:
		return s
	}

	panic(e)
}

// Converts a struct to map.
// First argument is a pointer to struct.
// Second argument is a not-nil map which will be modified.
// Only exported struct fields are used.
// Tag may be used to change mapping between struct field and map key.
// Currently supports bool, ints, uints, floats, strings.
// Panics in case of error.
func StructToMap(StructPointer interface{}, Map map[string]interface{}, tag string) {
	structPointerType := reflect.TypeOf(StructPointer)
	if structPointerType.Kind() != reflect.Ptr {
		panic(fmt.Errorf("StructToMap: expected pointer to struct as first argument, got %s", structPointerType.Kind()))
	}

	structType := structPointerType.Elem()
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("StructToMap: expected pointer to struct as first argument, got pointer to %s", structType.Kind()))
	}

	s := reflect.ValueOf(StructPointer).Elem()

	var name string
	for i := 0; i < structType.NumField(); i++ {
		stf := structType.Field(i)
		if stf.PkgPath != "" {
			continue
		}

		name = ""
		if tag != "" {
			name = strings.Split(stf.Tag.Get(tag), ",")[0]
			if name == "-" {
				continue
			}
		}
		if name == "" {
			name = stf.Name
		}

		Map[name] = s.Field(i).Interface()
	}
}

// Converts a struct to map. Uses StructToMap().
// First argument is a struct.
// Second argument is a not-nil map which will be modified.
// Only exported struct fields are used.
// Tag may be used to change mapping between struct field and map key.
// Currently supports bool, ints, uints, floats, strings.
// Panics in case of error.
func StructValueToMap(Struct interface{}, Map map[string]interface{}, tag string) {
	structType := reflect.TypeOf(Struct)
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("StructValueToMap: expected struct as first argument, got %s", structType.Kind()))
	}

	v := reflect.New(reflect.TypeOf(Struct))
	v.Elem().Set(reflect.ValueOf(Struct))
	StructToMap(v.Interface(), Map, tag)
}

// Converts a slice of structs to a slice of maps. Uses StructValueToMap().
// First argument is a slice of structs.
// Second argument is a pointer to (possibly nil) slice of maps which will be set.
func StructsToMaps(Structs interface{}, Maps *[]map[string]interface{}, tag string) {
	sliceType := reflect.TypeOf(Structs)
	if sliceType.Kind() != reflect.Slice {
		panic(fmt.Errorf("Expected slice of structs as first argument, got %s", sliceType.Kind()))
	}

	structType := sliceType.Elem()
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("Expected slice of structs as first argument, got slice of %s", structType.Kind()))
	}

	structs := reflect.ValueOf(Structs)
	l := structs.Len()
	maps := reflect.MakeSlice(reflect.TypeOf([]map[string]interface{}{}), 0, l)

	for i := 0; i < l; i++ {
		m := make(map[string]interface{})
		StructValueToMap(structs.Index(i).Interface(), m, tag)
		maps = reflect.Append(maps, reflect.ValueOf(m))
	}

	reflect.ValueOf(Maps).Elem().Set(maps)
}

// Converts a map to struct using converter function.
// First argument is a map.
// Second argument is a not-nil pointer to struct which will be modified.
// Only exported struct fields are set. Omitted or extra values in map are ignored.
// Tag may be used to change mapping between struct field and map key.
// Currently supports bool, ints, uints, floats, strings.
// Panics in case of error.
func MapToStruct(Map map[string]interface{}, StructPointer interface{}, converter Converter, tag string) {
	structPointerType := reflect.TypeOf(StructPointer)
	if structPointerType.Kind() != reflect.Ptr {
		panic(fmt.Errorf("MapToStruct: expected pointer to struct as second argument, got %s", structPointerType.Kind()))
	}

	structType := structPointerType.Elem()
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("MapToStruct: expected pointer to struct as second argument, got pointer to %s", structType.Kind()))
	}
	s := reflect.ValueOf(StructPointer).Elem()

	var name string
	defer func() {
		e := recover()
		if e == nil {
			return
		}

		panic(fmt.Errorf("MapToStruct, field %s: %s", name, e))
	}()

	for i := 0; i < structType.NumField(); i++ {
		f := s.Field(i)
		if !f.CanSet() {
			continue
		}

		stf := structType.Field(i)
		name = ""
		if tag != "" {
			name = strings.Split(stf.Tag.Get(tag), ",")[0]
			if name == "-" {
				continue
			}
		}
		if name == "" {
			name = stf.Name
		}
		v, ok := Map[name]
		if !ok {
			continue
		}

		kind := f.Kind()
		switch kind {
		case reflect.Bool:
			f.SetBool(converter(v, kind).(bool))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			f.SetInt(converter(v, kind).(int64))

		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			f.SetUint(converter(v, kind).(uint64))

		case reflect.Float32, reflect.Float64:
			f.SetFloat(converter(v, kind).(float64))

		case reflect.String:
			f.SetString(converter(v, kind).(string))

		default:
			// not implemented
		}
	}

	return
}

// Converts a slice of maps to a slice of structs. Uses MapToStruct().
// First argument is a slice of maps.
// Second argument is a pointer to (possibly nil) slice of structs which will be set.
func MapsToStructs(Maps []map[string]interface{}, SlicePointer interface{}, converter Converter, tag string) {
	slicePointerType := reflect.TypeOf(SlicePointer)
	if slicePointerType.Kind() != reflect.Ptr {
		panic(fmt.Errorf("MapsToStructs: expected pointer to slice of structs as second argument, got %s", slicePointerType.Kind()))
	}

	sliceType := slicePointerType.Elem()
	if sliceType.Kind() != reflect.Slice {
		panic(fmt.Errorf("MapsToStructs: expected pointer to slice of structs as second argument, got pointer to %s", sliceType.Kind()))
	}

	structType := sliceType.Elem()
	if structType.Kind() != reflect.Struct {
		panic(fmt.Errorf("MapsToStructs: expected pointer to slice of structs as second argument, got pointer to slice of %s", structType.Kind()))
	}

	slice := reflect.MakeSlice(sliceType, 0, len(Maps))
	for _, m := range Maps {
		s := reflect.New(structType)
		MapToStruct(m, s.Interface(), converter, tag)
		slice = reflect.Append(slice, s.Elem())
	}
	reflect.ValueOf(SlicePointer).Elem().Set(slice)
}

// Variant of MapsToStructs() with relaxed signature.
func MapsToStructs2(Maps []interface{}, SlicePointer interface{}, converter Converter, tag string) {
	m := make([]map[string]interface{}, len(Maps))
	for index, i := range Maps {
		m[index] = i.(map[string]interface{})
	}
	MapsToStructs(m, SlicePointer, converter, tag)
}
<|endoftext|>


<commit_before>package main

import (
  "log"
)

func Registrar(input chan []*FileEvent) {
  for events := range input {
    state := make(map[string]*FileState)
    log.Printf("Registrar received %d events\n", len(events))
    // Take the last event found for each file source
    for _, event := range events {
      // skip stdin
      if *event.Source == "-" {
        continue
      }
      // have to dereference the FileInfo here because os.FileInfo is an
      // interface, not a struct, so Go doesn't have smarts to call the Sys()
      // method on a pointer to os.FileInfo. :(
      ino, dev := file_ids(event.fileinfo)
      state[*event.Source] = &FileState{
        Source: event.Source,
        // take the offset + length of the line + newline char and
        // save it as the new starting offset.
        Offset: event.Offset + int64(len(*event.Text)) + 1,
        Inode: ino,
        Device: dev,
      }
      log.Printf("State %s: %d\n", *event.Source, event.Offset)
    }

    if len(state) > 0 {
      WriteRegistry(state, ".lumberjack")
    }
  }
}

<commit_msg>- comment out a log message nobody wants to see anyway ;)<commit_after>package main

import (
  "log"
)

func Registrar(input chan []*FileEvent) {
  for events := range input {
    state := make(map[string]*FileState)
    log.Printf("Registrar received %d events\n", len(events))
    // Take the last event found for each file source
    for _, event := range events {
      // skip stdin
      if *event.Source == "-" {
        continue
      }
      // have to dereference the FileInfo here because os.FileInfo is an
      // interface, not a struct, so Go doesn't have smarts to call the Sys()
      // method on a pointer to os.FileInfo. :(
      ino, dev := file_ids(event.fileinfo)
      state[*event.Source] = &FileState{
        Source: event.Source,
        // take the offset + length of the line + newline char and
        // save it as the new starting offset.
        Offset: event.Offset + int64(len(*event.Text)) + 1,
        Inode: ino,
        Device: dev,
      }
      //log.Printf("State %s: %d\n", *event.Source, event.Offset)
    }

    if len(state) > 0 {
      WriteRegistry(state, ".lumberjack")
    }
  }
}

<|endoftext|>


<commit_before>package resp

import (
	"bytes"
	"fmt"
	"io"
	"strconv"
	"strings"
	"time"

	"github.com/segmentio/objconv"
)

var (
	crlfBytes  = [...]byte{'\r', '\n'}
	nullBytes  = [...]byte{'$', '-', '1', '\r', '\n'}
	trueBytes  = [...]byte{'+', 't', 'r', 'u', 'e', '\r', '\n'}
	falseBytes = [...]byte{'+', 'f', 'a', 'l', 's', 'e', '\r', '\n'}
)

// Emitter implements a RESP emitter that satisfies the objconv.Emitter
// interface.
type Emitter struct {
	w io.Writer

	// This byte slice is used as a local buffer to format values before they
	// are written to the output.
	s []byte

	// This array acts as the initial buffer for s to avoid dynamic memory
	// allocations for the most common use cases.
	a [128]byte

	// This stack is used to cache arrays that are emitted in streaming mode,
	// where the length of the array is not known before outputing all the
	// elements.
	stack []context

	// sback is used as the initial backing array for the stack slice to avoid
	// dynamic memory allocations for the most common use cases.
	sback [8]context
}

type context struct {
	b bytes.Buffer // buffer where the array elements are cached
	w io.Writer    // the previous writer where b will be flushed
	n int          // the length of the array as initially set by the encoder
	i int          // the number of elements written to the array
}

func NewEmitter(w io.Writer) *Emitter {
	e := &Emitter{w: w}
	e.s = e.a[:0]
	e.stack = e.sback[:0]
	return e
}

func (e *Emitter) Reset(w io.Writer) {
	e.w = w
}

func (e *Emitter) EmitNil() (err error) {
	_, err = e.w.Write(nullBytes[:])
	return
}

func (e *Emitter) EmitBool(v bool) (err error) {
	if v {
		_, err = e.w.Write(trueBytes[:])
	} else {
		_, err = e.w.Write(falseBytes[:])
	}
	return
}

func (e *Emitter) EmitInt(v int64, _ int) (err error) {
	s := e.s[:0]

	s = append(s, ':')
	s = appendInt(s, v)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitUint(v uint64, _ int) (err error) {
	if v > objconv.Int64Max {
		return fmt.Errorf("objconv/resp: %d overflows the maximum integer value of %d", v, objconv.Int64Max)
	}

	s := e.s[:0]

	s = append(s, ':')
	s = appendUint(s, v)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitFloat(v float64, bitSize int) (err error) {
	s := e.s[:0]

	s = append(s, '+')
	s = appendFloat(s, v, bitSize)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitString(v string) (err error) {
	s := e.s[:0]

	if indexCRLF(v) < 0 {
		s = append(s, '+')
		s = append(s, v...)
		s = appendCRLF(s)
	} else {
		s = append(s, '$')
		s = appendUint(s, uint64(len(v)))
		s = appendCRLF(s)
		s = append(s, v...)
		s = appendCRLF(s)
	}

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitBytes(v []byte) (err error) {
	s := e.s[:0]

	s = append(s, '$')
	s = appendUint(s, uint64(len(v)))
	s = appendCRLF(s)

	if (len(v) + 2) <= (cap(s) - len(s)) { // if it fits in the buffer
		s = append(s, v...)
		s = appendCRLF(s)
		e.s = s[:0]

		_, err = e.w.Write(s)
		return
	}

	e.s = s[:0]

	if _, err = e.w.Write(s); err != nil {
		return
	}

	if _, err = e.w.Write(v); err != nil {
		return
	}

	_, err = e.w.Write(crlfBytes[:])
	return
}

func (e *Emitter) EmitTime(v time.Time) (err error) {
	s := e.s[:0]

	s = append(s, '+')
	s = v.AppendFormat(s, time.RFC3339Nano)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitDuration(v time.Duration) (err error) {
	s := e.s[:0]

	s = append(s, '+')
	s = objconv.AppendDuration(s, v)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitError(v error) (err error) {
	x := v.Error()
	s := e.s[:0]

	if i := indexCRLF(x); i >= 0 {
		x = x[:i] // only keep the first line
	}

	s = append(s, '-')
	s = append(s, x...)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitArrayBegin(n int) (err error) {
	e.stack = append(e.stack, context{n: n})
	c := &e.stack[len(e.stack)-1]

	if n < 0 {
		c.w = e.w
		e.w = &c.b
	} else {
		err = e.emitArray(n)
	}

	return
}

func (e *Emitter) EmitArrayEnd() (err error) {
	i := len(e.stack) - 1
	c := e.stack[i]
	e.stack = e.stack[:i]

	if c.n < 0 {
		e.w = c.w

		if c.b.Len() != 0 {
			c.i++
		}

		if err = e.emitArray(c.i); err != nil {
			return
		}

		if _, err = c.b.WriteTo(c.w); err != nil {
			return
		}
	}

	return
}

func (e *Emitter) EmitArrayNext() (err error) {
	e.stack[len(e.stack)-1].i++
	return
}

func (e *Emitter) EmitMapBegin(n int) (err error) {
	return e.emitArray(n + n)
}

func (e *Emitter) EmitMapEnd() (err error) {
	return
}

func (e *Emitter) EmitMapValue() (err error) {
	return
}

func (e *Emitter) EmitMapNext() (err error) {
	return
}

func (e *Emitter) emitArray(n int) (err error) {
	s := e.s[:0]

	s = append(s, '*')
	s = appendUint(s, uint64(n))
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func appendInt(b []byte, v int64) []byte {
	return strconv.AppendInt(b, v, 10)
}

func appendUint(b []byte, v uint64) []byte {
	return strconv.AppendUint(b, v, 10)
}

func appendFloat(b []byte, v float64, bitSize int) []byte {
	return strconv.AppendFloat(b, v, 'g', -1, bitSize)
}

func appendCRLF(b []byte) []byte {
	return append(b, '\r', '\n')
}

func indexCRLF(s string) int {
	for i, n := 0, len(s); i != n; i++ {
		j := strings.IndexByte(s[i:], '\r')

		if j < 0 {
			break
		}

		if j++; j == n {
			break
		}

		if s[j] == '\n' {
			return j - 1
		}
	}
	return -1
}
<commit_msg>optimize resp emitter<commit_after>package resp

import (
	"bytes"
	"fmt"
	"io"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/segmentio/objconv"
)

var (
	crlfBytes  = [...]byte{'\r', '\n'}
	nullBytes  = [...]byte{'$', '-', '1', '\r', '\n'}
	trueBytes  = [...]byte{'+', 't', 'r', 'u', 'e', '\r', '\n'}
	falseBytes = [...]byte{'+', 'f', 'a', 'l', 's', 'e', '\r', '\n'}
)

// Emitter implements a RESP emitter that satisfies the objconv.Emitter
// interface.
type Emitter struct {
	w io.Writer

	// This byte slice is used as a local buffer to format values before they
	// are written to the output.
	s []byte

	// This array acts as the initial buffer for s to avoid dynamic memory
	// allocations for the most common use cases.
	a [128]byte

	// This stack is used to cache arrays that are emitted in streaming mode,
	// where the length of the array is not known before outputing all the
	// elements.
	stack []*context

	// sback is used as the initial backing array for the stack slice to avoid
	// dynamic memory allocations for the most common use cases.
	sback [8]*context
}

type context struct {
	b bytes.Buffer // buffer where the array elements are cached
	w io.Writer    // the previous writer where b will be flushed
	n int          // the length of the array as initially set by the encoder
	i int          // the number of elements written to the array
}

func NewEmitter(w io.Writer) *Emitter {
	e := &Emitter{w: w}
	e.s = e.a[:0]
	e.stack = e.sback[:0]
	return e
}

func (e *Emitter) Reset(w io.Writer) {
	e.w = w
}

func (e *Emitter) EmitNil() (err error) {
	_, err = e.w.Write(nullBytes[:])
	return
}

func (e *Emitter) EmitBool(v bool) (err error) {
	if v {
		_, err = e.w.Write(trueBytes[:])
	} else {
		_, err = e.w.Write(falseBytes[:])
	}
	return
}

func (e *Emitter) EmitInt(v int64, _ int) (err error) {
	s := e.s[:0]

	s = append(s, ':')
	s = appendInt(s, v)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitUint(v uint64, _ int) (err error) {
	if v > objconv.Int64Max {
		return fmt.Errorf("objconv/resp: %d overflows the maximum integer value of %d", v, objconv.Int64Max)
	}

	s := e.s[:0]

	s = append(s, ':')
	s = appendUint(s, v)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitFloat(v float64, bitSize int) (err error) {
	s := e.s[:0]

	s = append(s, '+')
	s = appendFloat(s, v, bitSize)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitString(v string) (err error) {
	s := e.s[:0]

	if indexCRLF(v) < 0 {
		s = append(s, '+')
		s = append(s, v...)
		s = appendCRLF(s)
	} else {
		s = append(s, '$')
		s = appendUint(s, uint64(len(v)))
		s = appendCRLF(s)
		s = append(s, v...)
		s = appendCRLF(s)
	}

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitBytes(v []byte) (err error) {
	s := e.s[:0]

	s = append(s, '$')
	s = appendUint(s, uint64(len(v)))
	s = appendCRLF(s)

	if (len(v) + 2) <= (cap(s) - len(s)) { // if it fits in the buffer
		s = append(s, v...)
		s = appendCRLF(s)
		e.s = s[:0]

		_, err = e.w.Write(s)
		return
	}

	e.s = s[:0]

	if _, err = e.w.Write(s); err != nil {
		return
	}

	if _, err = e.w.Write(v); err != nil {
		return
	}

	_, err = e.w.Write(crlfBytes[:])
	return
}

func (e *Emitter) EmitTime(v time.Time) (err error) {
	s := e.s[:0]

	s = append(s, '+')
	s = v.AppendFormat(s, time.RFC3339Nano)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitDuration(v time.Duration) (err error) {
	s := e.s[:0]

	s = append(s, '+')
	s = objconv.AppendDuration(s, v)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitError(v error) (err error) {
	x := v.Error()
	s := e.s[:0]

	if i := indexCRLF(x); i >= 0 {
		x = x[:i] // only keep the first line
	}

	s = append(s, '-')
	s = append(s, x...)
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func (e *Emitter) EmitArrayBegin(n int) (err error) {
	var c *context

	if n < 0 {
		c = contextPool.Get().(*context)
		c.b.Truncate(0)
		c.n = 0
		c.w = e.w
		e.w = &c.b
	} else {
		err = e.emitArray(n)
	}

	e.stack = append(e.stack, c)
	return
}

func (e *Emitter) EmitArrayEnd() (err error) {
	i := len(e.stack) - 1
	c := e.stack[i]
	e.stack = e.stack[:i]

	if c != nil {
		e.w = c.w

		if c.b.Len() != 0 {
			c.n++
		}

		if err = e.emitArray(c.n); err == nil {
			_, err = c.b.WriteTo(c.w)
		}

		contextPool.Put(c)
	}

	return
}

func (e *Emitter) EmitArrayNext() (err error) {
	if c := e.stack[len(e.stack)-1]; c != nil {
		c.n++
	}
	return
}

func (e *Emitter) EmitMapBegin(n int) (err error) {
	return e.emitArray(n + n)
}

func (e *Emitter) EmitMapEnd() (err error) {
	return
}

func (e *Emitter) EmitMapValue() (err error) {
	return
}

func (e *Emitter) EmitMapNext() (err error) {
	return
}

func (e *Emitter) emitArray(n int) (err error) {
	s := e.s[:0]

	s = append(s, '*')
	s = appendUint(s, uint64(n))
	s = appendCRLF(s)

	e.s = s[:0]
	_, err = e.w.Write(s)
	return
}

func appendInt(b []byte, v int64) []byte {
	return strconv.AppendInt(b, v, 10)
}

func appendUint(b []byte, v uint64) []byte {
	return strconv.AppendUint(b, v, 10)
}

func appendFloat(b []byte, v float64, bitSize int) []byte {
	return strconv.AppendFloat(b, v, 'g', -1, bitSize)
}

func appendCRLF(b []byte) []byte {
	return append(b, '\r', '\n')
}

func indexCRLF(s string) int {
	for i, n := 0, len(s); i != n; i++ {
		j := strings.IndexByte(s[i:], '\r')

		if j < 0 {
			break
		}

		if j++; j == n {
			break
		}

		if s[j] == '\n' {
			return j - 1
		}
	}
	return -1
}

var contextPool = sync.Pool{
	New: func() interface{} { return &context{} },
}
<|endoftext|>


<commit_before>package statuscake

type autheticationErrorResponse struct {
	ErrNo int
	Error string
}

type updateResponse struct {
	Issues   interface{} `json:"Issues"`
	Success  bool        `json:"Success"`
	Message  string      `json:"Message"`
	InsertID int         `json:"InsertID"`
}

type deleteResponse struct {
	Success bool   `json:"Success"`
	Error   string `json:"Error"`
}

type detailResponse struct {
	Method          string   `json:"Method"`
	TestID          int      `json:"TestID"`
	TestType        string   `json:"TestType"`
	Paused          bool     `json:"Paused"`
	WebsiteName     string   `json:"WebsiteName"`
	URI             string   `json:"URI"`
	ContactID       int      `json:"ContactID"`
	Status          string   `json:"Status"`
	Uptime          float64  `json:"Uptime"`
	CheckRate       int      `json:"CheckRate"`
	Timeout         int      `json:"Timeout"`
	LogoImage       string   `json:"LogoImage"`
	Confirmation    int      `json:"Confirmation,string"`
	WebsiteHost     string   `json:"WebsiteHost"`
	NodeLocations   []string `json:"NodeLocations"`
	FindString      string   `json:"FindString"`
	DoNotFind       bool     `json:"DoNotFind"`
	LastTested      string   `json:"LastTested"`
	NextLocation    string   `json:"NextLocation"`
	Port            int      `json:"Port"`
	Processing      bool     `json:"Processing"`
	ProcessingState string   `json:"ProcessingState"`
	ProcessingOn    string   `json:"ProcessingOn"`
	DownTimes       int      `json:"DownTimes,string"`
	Sensitive       bool     `json:"Sensitive"`
}

func (d *detailResponse) test() *Test {
	return &Test{
		TestID:        d.TestID,
		TestType:      d.TestType,
		Paused:        d.Paused,
		WebsiteName:   d.WebsiteName,
		WebsiteURL:    d.URI,
		ContactID:     d.ContactID,
		Status:        d.Status,
		Uptime:        d.Uptime,
		CheckRate:     d.CheckRate,
		Timeout:       d.Timeout,
		LogoImage:     d.LogoImage,
		Confirmation:  d.Confirmation,
		WebsiteHost:   d.WebsiteHost,
		NodeLocations: d.NodeLocations,
		FindString:    d.FindString,
		DoNotFind:     d.DoNotFind,
		Port:          d.Port,
	}
}
<commit_msg>responses: Adds TriggerRate as a response from the API that can be ingested in Terraform<commit_after>package statuscake

type autheticationErrorResponse struct {
	ErrNo int
	Error string
}

type updateResponse struct {
	Issues   interface{} `json:"Issues"`
	Success  bool        `json:"Success"`
	Message  string      `json:"Message"`
	InsertID int         `json:"InsertID"`
}

type deleteResponse struct {
	Success bool   `json:"Success"`
	Error   string `json:"Error"`
}

type detailResponse struct {
	Method          string   `json:"Method"`
	TestID          int      `json:"TestID"`
	TestType        string   `json:"TestType"`
	Paused          bool     `json:"Paused"`
	WebsiteName     string   `json:"WebsiteName"`
	URI             string   `json:"URI"`
	ContactID       int      `json:"ContactID"`
	Status          string   `json:"Status"`
	Uptime          float64  `json:"Uptime"`
	CheckRate       int      `json:"CheckRate"`
	Timeout         int      `json:"Timeout"`
	LogoImage       string   `json:"LogoImage"`
	Confirmation    int      `json:"Confirmation,string"`
	WebsiteHost     string   `json:"WebsiteHost"`
	NodeLocations   []string `json:"NodeLocations"`
	FindString      string   `json:"FindString"`
	DoNotFind       bool     `json:"DoNotFind"`
	LastTested      string   `json:"LastTested"`
	NextLocation    string   `json:"NextLocation"`
	Port            int      `json:"Port"`
	Processing      bool     `json:"Processing"`
	ProcessingState string   `json:"ProcessingState"`
	ProcessingOn    string   `json:"ProcessingOn"`
	DownTimes       int      `json:"DownTimes,string"`
	Sensitive       bool     `json:"Sensitive"`
	TriggerRate     int      `json:"TriggerRate"`
}

func (d *detailResponse) test() *Test {
	return &Test{
		TestID:        d.TestID,
		TestType:      d.TestType,
		Paused:        d.Paused,
		WebsiteName:   d.WebsiteName,
		WebsiteURL:    d.URI,
		ContactID:     d.ContactID,
		Status:        d.Status,
		Uptime:        d.Uptime,
		CheckRate:     d.CheckRate,
		Timeout:       d.Timeout,
		LogoImage:     d.LogoImage,
		Confirmation:  d.Confirmation,
		WebsiteHost:   d.WebsiteHost,
		NodeLocations: d.NodeLocations,
		FindString:    d.FindString,
		DoNotFind:     d.DoNotFind,
		Port:          d.Port,
		TriggerRate:   d.TriggerRate,
	}
}
<|endoftext|>


<commit_before>package rest

import (
	"fmt"
	"log"
	"reflect"
	"strconv"
)

// Type is a data type to coerce a value to specified with a Rule.
type Type uint

const (
	// Interface represents the interface{} data type.
	Interface Type = iota

	// Int represents the int data type.
	Int

	// Int8 represents the int8 data type.
	Int8

	// Int16 represents the int16 data type.
	Int16

	// Int32 represents the int32 data type.
	Int32

	// Int64 represents the int64 data type.
	Int64

	// Uint represents the uint data type.
	Uint

	// Uint8 represents the uint8 data type.
	Uint8

	// Uint16 represents the uint16 data type.
	Uint16

	// Uint32 represents the uint32 data type.
	Uint32

	// Uint64 represents the uint64 data type.
	Uint64

	// Float32 represents the float32 data type.
	Float32

	// Float64 represents the float64 data type.
	Float64

	// String represents the string data type.
	String

	// Bool represents the bool data type.
	Bool

	// Array represents the []interface{} data type.
	Array

	// Map represents the map[string]interface{} data type.
	Map

	// Byte represents the byte data type.
	Byte = Uint8

	// Unspecified represents the interface{} data type.
	Unspecified = Interface
)

// typeName maps Types to their human-readable names.
var typeName = map[Type]string{
	Interface: "interface{}",
	Int:       "int",
	Int8:      "int8",
	Int16:     "int16",
	Int32:     "int32",
	Int64:     "int64",
	Uint:      "uint",
	Uint8:     "uint8",
	Uint16:    "uint16",
	Uint32:    "uint32",
	Uint64:    "uint64",
	Float32:   "float32",
	Float64:   "float64",
	String:    "string",
	Bool:      "bool",
	Array:     "[]interface{}",
	Map:       "map[string]interface{}",
}

// Rule provides schema validation and type coercion for request input and fine-grained
// control over response output. If a ResourceHandler provides input Rules which specify
// types, input fields will attempt to be coerced to those types. If coercion fails, an
// error will be returned in the response. If a ResourceHandler provides output Rules,
// only the fields corresponding to those Rules will be sent back. This prevents new
// fields from leaking into old API versions.
type Rule struct {
	// Name of the resource field. This is the name as it appears in the struct
	// definition.
	Field string

	// Name of the input/output field. Defaults to resource field name if not specified.
	ValueName string

	// Type to coerce field value to. If the value cannot be coerced, an error will be
	// returned in the response. Defaults to Unspecified, which is the equivalent of
	// an interface{} value.
	Type Type

	// Indicates if the Rule should only be applied to requests.
	InputOnly bool

	// Indicates if the Rule should only be applied to responses.
	OutputOnly bool

	// Function which produces the field value to receive.
	InputHandler func(interface{}) interface{}

	// Function which produces the field value to send.
	OutputHandler func(interface{}) interface{}
}

// applyInboundRules applies Rules which are not specified as output only to the provided
// Payload. If the Payload is nil, an empty Payload will be returned. If no Rules are
// provided, this acts as an identity function. If Rules are provided, any incoming
// fields which are not specified will be discarded. If Rules specify types, incoming
// values will attempted to be coerced. If coercion fails, an error will be returned.
func applyInboundRules(payload Payload, rules []Rule) (Payload, error) {
	if payload == nil {
		return Payload{}, nil
	}

	if len(rules) == 0 {
		return payload, nil
	}

	newPayload := Payload{}

fieldLoop:
	for field, value := range payload {
		for _, rule := range rules {
			if rule.OutputOnly {
				// Apply only inbound Rules.
				continue
			}

			if rule.ValueName == field {
				if rule.Type != Unspecified {
					// Coerce to specified type.
					coerced, err := coerceType(value, rule.Type)
					if err != nil {
						return nil, err
					}
					value = coerced
				}
				if rule.InputHandler != nil {
					value = rule.InputHandler(value)
				}
				newPayload[field] = value
				continue fieldLoop
			}
		}

		log.Printf("Discarding field '%s'", field)
	}

	return newPayload, nil
}

// applyOutboundRules applies Rules which are not specified as input only to the provided
// Resource. If the Resource is nil, not a struct, or no Rules are provided, this acts as
// an identity function. If Rules are provided, only the fields specified by them will be
// included in the returned Resource. This is to prevent new fields from leaking into old
// API versions.
func applyOutboundRules(resource Resource, rules []Rule) Resource {
	if resource == nil || len(rules) == 0 {
		// Return resource as-is if no Rules are provided.
		return resource
	}

	// Get the underlying value by dereferencing the pointer if there is one.
	resourceValue := reflect.Indirect(reflect.ValueOf(resource))
	resource = resourceValue.Interface()
	resourceType := reflect.TypeOf(resource)

	if resourceType.Kind() != reflect.Struct {
		// Only apply Rules to structs.
		// TODO: Can probably apply them to maps as well.
		return resource
	}

	payload := Payload{}

	for _, rule := range rules {
		if rule.InputOnly {
			// Apply only outbound Rules.
			continue
		}

		field := resourceValue.FieldByName(rule.Field)
		if !field.IsValid() {
			// The field doesn't exist.
			log.Printf("%s has no field '%s'", reflect.TypeOf(resource).Name(), rule.Field)
			continue
		}

		valueName := rule.ValueName
		if valueName == "" {
			// Use field name if value name isn't specified.
			valueName = rule.Field
		}

		fieldValue := field.Interface()
		if rule.OutputHandler != nil {
			fieldValue = rule.OutputHandler(fieldValue)
		}
		payload[valueName] = fieldValue
	}

	return payload
}

// coerceType attempts to convert the given value to the specified Type. If it cannot
// be coerced, nil will be returned along with an error.
func coerceType(value interface{}, coerceTo Type) (interface{}, error) {
	if coerceTo == Interface {
		return value, nil
	}

	// json.Unmarshal converts values to bool, float64, string, nil, array, and map.
	switch value.(type) {
	case bool:
		return coerceFromBool(value.(bool), coerceTo)
	case float64:
		return coerceFromFloat(value.(float64), coerceTo)
	case string:
		return coerceFromString(value.(string), coerceTo)
	case nil:
		return value, nil
	case []interface{}:
		return coerceFromArray(value.([]interface{}), coerceTo)
	case map[string]interface{}:
		return coerceFromMap(value.(map[string]interface{}), coerceTo)
	default:
		return nil, fmt.Errorf("Unable to coerce %s to %s",
			reflect.TypeOf(value), typeName[coerceTo])
	}
}

// coerceFromBool attempts to convert the given bool to the specified Type. If it
// cannot be coerced, nil will be returned along with an error.
func coerceFromBool(value bool, coerceTo Type) (interface{}, error) {
	if coerceTo == Bool {
		return value, nil
	}
	if coerceTo == String {
		if value {
			return "true", nil
		}
		return "false", nil
	}

	return nil, fmt.Errorf("Unable to coerce bool to %s", typeName[coerceTo])
}

// coerceFromFloat attempts to convert the given float64 to the specified Type.
// If it cannot be coerced, nil will be returned along with an error.
func coerceFromFloat(value float64, coerceTo Type) (interface{}, error) {
	switch coerceTo {
	// To int.
	case Int:
		return int(value), nil
	case Int8:
		return int8(value), nil
	case Int16:
		return int16(value), nil
	case Int32:
		return int32(value), nil
	case Int64:
		return int64(value), nil

	// To unsigned int.
	case Uint:
		return uint(value), nil
	case Uint8:
		return uint8(value), nil
	case Uint16:
		return uint16(value), nil
	case Uint32:
		return uint32(value), nil
	case Uint64:
		return uint64(value), nil

	// To float.
	case Float32:
		return float32(value), nil
	case Float64:
		return value, nil

	// To string.
	case String:
		return strconv.FormatFloat(value, 'f', -1, 64), nil

	// Bool case left off intentionally.
	default:
		return nil, fmt.Errorf("Unable to coerce float to %s", typeName[coerceTo])
	}
}

// coerceFromString attempts to convert the given string to the specified Type. If
// it cannot be coerced, nil will be returned along with an error.
func coerceFromString(value string, coerceTo Type) (interface{}, error) {
	switch coerceTo {
	// To int.
	case Int:
		val, err := strconv.ParseInt(value, 0, 0)
		if err != nil {
			return nil, err
		}
		return int(val), nil
	case Int8:
		val, err := strconv.ParseInt(value, 0, 8)
		if err != nil {
			return nil, err
		}
		return int8(val), nil
	case Int16:
		val, err := strconv.ParseInt(value, 0, 16)
		if err != nil {
			return nil, err
		}
		return int16(val), nil
	case Int32:
		val, err := strconv.ParseInt(value, 0, 32)
		if err != nil {
			return nil, err
		}
		return int32(val), nil
	case Int64:
		val, err := strconv.ParseInt(value, 0, 64)
		if err != nil {
			return nil, err
		}
		return int64(val), nil

	// To unsigned int.
	case Uint:
		val, err := strconv.ParseUint(value, 0, 0)
		if err != nil {
			return nil, err
		}
		return uint(val), nil
	case Uint8:
		val, err := strconv.ParseUint(value, 0, 8)
		if err != nil {
			return nil, err
		}
		return uint8(val), nil
	case Uint16:
		val, err := strconv.ParseUint(value, 0, 16)
		if err != nil {
			return nil, err
		}
		return uint16(val), nil
	case Uint32:
		val, err := strconv.ParseUint(value, 0, 32)
		if err != nil {
			return nil, err
		}
		return uint32(val), nil
	case Uint64:
		val, err := strconv.ParseUint(value, 0, 64)
		if err != nil {
			return nil, err
		}
		return uint64(val), nil

	// To float.
	case Float32:
		val, err := strconv.ParseFloat(value, 32)
		if err != nil {
			return nil, err
		}
		return float32(val), nil
	case Float64:
		val, err := strconv.ParseFloat(value, 64)
		if err != nil {
			return nil, err
		}
		return float64(val), nil

	// To string.
	case String:
		return value, nil

	// To bool.
	case Bool:
		val, err := strconv.ParseBool(value)
		if err != nil {
			return nil, err
		}
		return val, nil

	default:
		return nil, fmt.Errorf("Unable to coerce string to %s", typeName[coerceTo])
	}
}

// coerceFromArray attempts to convert the given array to the specified Type. Currently,
// arrays can only be coerced to arrays (identity). If it cannot be coerced, nil will be
// returned along with an error.
func coerceFromArray(value []interface{}, coerceTo Type) (interface{}, error) {
	if coerceTo == Array {
		return value, nil
	}

	return nil, fmt.Errorf("Unable to coerce array to %s", typeName[coerceTo])
}

// coerceFromMap attempts to convert the given map to the specified Type. Currently,
// maps can only be coerced to maps (identity). If it cannot be coerced, nil will be
// returned along with an error.
func coerceFromMap(value map[string]interface{}, coerceTo Type) (interface{}, error) {
	if coerceTo == Map {
		return value, nil
	}

	return nil, fmt.Errorf("Unable to coerce map to %s", typeName[coerceTo])
}
<commit_msg>Filter rules before calculating rules length<commit_after>package rest

import (
	"fmt"
	"log"
	"reflect"
	"strconv"
)

// Type is a data type to coerce a value to specified with a Rule.
type Type uint

const (
	// Interface represents the interface{} data type.
	Interface Type = iota

	// Int represents the int data type.
	Int

	// Int8 represents the int8 data type.
	Int8

	// Int16 represents the int16 data type.
	Int16

	// Int32 represents the int32 data type.
	Int32

	// Int64 represents the int64 data type.
	Int64

	// Uint represents the uint data type.
	Uint

	// Uint8 represents the uint8 data type.
	Uint8

	// Uint16 represents the uint16 data type.
	Uint16

	// Uint32 represents the uint32 data type.
	Uint32

	// Uint64 represents the uint64 data type.
	Uint64

	// Float32 represents the float32 data type.
	Float32

	// Float64 represents the float64 data type.
	Float64

	// String represents the string data type.
	String

	// Bool represents the bool data type.
	Bool

	// Array represents the []interface{} data type.
	Array

	// Map represents the map[string]interface{} data type.
	Map

	// Byte represents the byte data type.
	Byte = Uint8

	// Unspecified represents the interface{} data type.
	Unspecified = Interface
)

// typeName maps Types to their human-readable names.
var typeName = map[Type]string{
	Interface: "interface{}",
	Int:       "int",
	Int8:      "int8",
	Int16:     "int16",
	Int32:     "int32",
	Int64:     "int64",
	Uint:      "uint",
	Uint8:     "uint8",
	Uint16:    "uint16",
	Uint32:    "uint32",
	Uint64:    "uint64",
	Float32:   "float32",
	Float64:   "float64",
	String:    "string",
	Bool:      "bool",
	Array:     "[]interface{}",
	Map:       "map[string]interface{}",
}

// Rule provides schema validation and type coercion for request input and fine-grained
// control over response output. If a ResourceHandler provides input Rules which specify
// types, input fields will attempt to be coerced to those types. If coercion fails, an
// error will be returned in the response. If a ResourceHandler provides output Rules,
// only the fields corresponding to those Rules will be sent back. This prevents new
// fields from leaking into old API versions.
type Rule struct {
	// Name of the resource field. This is the name as it appears in the struct
	// definition.
	Field string

	// Name of the input/output field. Defaults to resource field name if not specified.
	ValueName string

	// Type to coerce field value to. If the value cannot be coerced, an error will be
	// returned in the response. Defaults to Unspecified, which is the equivalent of
	// an interface{} value.
	Type Type

	// Indicates if the Rule should only be applied to requests.
	InputOnly bool

	// Indicates if the Rule should only be applied to responses.
	OutputOnly bool

	// Function which produces the field value to receive.
	InputHandler func(interface{}) interface{}

	// Function which produces the field value to send.
	OutputHandler func(interface{}) interface{}
}

// applyInboundRules applies Rules which are not specified as output only to the provided
// Payload. If the Payload is nil, an empty Payload will be returned. If no Rules are
// provided, this acts as an identity function. If Rules are provided, any incoming
// fields which are not specified will be discarded. If Rules specify types, incoming
// values will attempted to be coerced. If coercion fails, an error will be returned.
func applyInboundRules(payload Payload, rules []Rule) (Payload, error) {
	if payload == nil {
		return Payload{}, nil
	}

	// Apply only inbound Rules.
	rules = filterRules(rules, true)

	if len(rules) == 0 {
		return payload, nil
	}

	newPayload := Payload{}

fieldLoop:
	for field, value := range payload {
		for _, rule := range rules {
			if rule.ValueName == field {
				if rule.Type != Unspecified {
					// Coerce to specified type.
					coerced, err := coerceType(value, rule.Type)
					if err != nil {
						return nil, err
					}
					value = coerced
				}
				if rule.InputHandler != nil {
					value = rule.InputHandler(value)
				}
				newPayload[field] = value
				continue fieldLoop
			}
		}

		log.Printf("Discarding field '%s'", field)
	}

	return newPayload, nil
}

// applyOutboundRules applies Rules which are not specified as input only to the provided
// Resource. If the Resource is nil, not a struct, or no Rules are provided, this acts as
// an identity function. If Rules are provided, only the fields specified by them will be
// included in the returned Resource. This is to prevent new fields from leaking into old
// API versions.
func applyOutboundRules(resource Resource, rules []Rule) Resource {
	// Apply only outbound Rules.
	rules = filterRules(rules, false)

	if resource == nil || len(rules) == 0 {
		// Return resource as-is if no Rules are provided.
		return resource
	}

	// Get the underlying value by dereferencing the pointer if there is one.
	resourceValue := reflect.Indirect(reflect.ValueOf(resource))
	resource = resourceValue.Interface()
	resourceType := reflect.TypeOf(resource)

	if resourceType.Kind() != reflect.Struct {
		// Only apply Rules to structs.
		// TODO: Can probably apply them to maps as well.
		return resource
	}

	payload := Payload{}

	for _, rule := range rules {
		field := resourceValue.FieldByName(rule.Field)
		if !field.IsValid() {
			// The field doesn't exist.
			log.Printf("%s has no field '%s'", reflect.TypeOf(resource).Name(), rule.Field)
			continue
		}

		valueName := rule.ValueName
		if valueName == "" {
			// Use field name if value name isn't specified.
			valueName = rule.Field
		}

		fieldValue := field.Interface()
		if rule.OutputHandler != nil {
			fieldValue = rule.OutputHandler(fieldValue)
		}
		payload[valueName] = fieldValue
	}

	return payload
}

// filterRules filters the array of Rules based on the specified bool. True means to
// filter out outbound Rules such that the returned array contains only inbound Rules.
// False means to filter out inbound Rules such that the returned array contains only
// outbound Rules.
func filterRules(rules []Rule, inbound bool) []Rule {
	filtered := make([]Rule, 0, len(rules))
	for _, rule := range rules {
		if inbound && rule.OutputOnly {
			// Filter out outbound Rules.
			continue
		} else if !inbound && rule.InputOnly {
			// Filter out inbound Rules.
			continue
		}
		filtered = append(filtered, rule)
	}

	return filtered
}

// coerceType attempts to convert the given value to the specified Type. If it cannot
// be coerced, nil will be returned along with an error.
func coerceType(value interface{}, coerceTo Type) (interface{}, error) {
	if coerceTo == Interface {
		return value, nil
	}

	// json.Unmarshal converts values to bool, float64, string, nil, array, and map.
	switch value.(type) {
	case bool:
		return coerceFromBool(value.(bool), coerceTo)
	case float64:
		return coerceFromFloat(value.(float64), coerceTo)
	case string:
		return coerceFromString(value.(string), coerceTo)
	case nil:
		return value, nil
	case []interface{}:
		return coerceFromArray(value.([]interface{}), coerceTo)
	case map[string]interface{}:
		return coerceFromMap(value.(map[string]interface{}), coerceTo)
	default:
		return nil, fmt.Errorf("Unable to coerce %s to %s",
			reflect.TypeOf(value), typeName[coerceTo])
	}
}

// coerceFromBool attempts to convert the given bool to the specified Type. If it
// cannot be coerced, nil will be returned along with an error.
func coerceFromBool(value bool, coerceTo Type) (interface{}, error) {
	if coerceTo == Bool {
		return value, nil
	}
	if coerceTo == String {
		if value {
			return "true", nil
		}
		return "false", nil
	}

	return nil, fmt.Errorf("Unable to coerce bool to %s", typeName[coerceTo])
}

// coerceFromFloat attempts to convert the given float64 to the specified Type.
// If it cannot be coerced, nil will be returned along with an error.
func coerceFromFloat(value float64, coerceTo Type) (interface{}, error) {
	switch coerceTo {
	// To int.
	case Int:
		return int(value), nil
	case Int8:
		return int8(value), nil
	case Int16:
		return int16(value), nil
	case Int32:
		return int32(value), nil
	case Int64:
		return int64(value), nil

	// To unsigned int.
	case Uint:
		return uint(value), nil
	case Uint8:
		return uint8(value), nil
	case Uint16:
		return uint16(value), nil
	case Uint32:
		return uint32(value), nil
	case Uint64:
		return uint64(value), nil

	// To float.
	case Float32:
		return float32(value), nil
	case Float64:
		return value, nil

	// To string.
	case String:
		return strconv.FormatFloat(value, 'f', -1, 64), nil

	// Bool case left off intentionally.
	default:
		return nil, fmt.Errorf("Unable to coerce float to %s", typeName[coerceTo])
	}
}

// coerceFromString attempts to convert the given string to the specified Type. If
// it cannot be coerced, nil will be returned along with an error.
func coerceFromString(value string, coerceTo Type) (interface{}, error) {
	switch coerceTo {
	// To int.
	case Int:
		val, err := strconv.ParseInt(value, 0, 0)
		if err != nil {
			return nil, err
		}
		return int(val), nil
	case Int8:
		val, err := strconv.ParseInt(value, 0, 8)
		if err != nil {
			return nil, err
		}
		return int8(val), nil
	case Int16:
		val, err := strconv.ParseInt(value, 0, 16)
		if err != nil {
			return nil, err
		}
		return int16(val), nil
	case Int32:
		val, err := strconv.ParseInt(value, 0, 32)
		if err != nil {
			return nil, err
		}
		return int32(val), nil
	case Int64:
		val, err := strconv.ParseInt(value, 0, 64)
		if err != nil {
			return nil, err
		}
		return int64(val), nil

	// To unsigned int.
	case Uint:
		val, err := strconv.ParseUint(value, 0, 0)
		if err != nil {
			return nil, err
		}
		return uint(val), nil
	case Uint8:
		val, err := strconv.ParseUint(value, 0, 8)
		if err != nil {
			return nil, err
		}
		return uint8(val), nil
	case Uint16:
		val, err := strconv.ParseUint(value, 0, 16)
		if err != nil {
			return nil, err
		}
		return uint16(val), nil
	case Uint32:
		val, err := strconv.ParseUint(value, 0, 32)
		if err != nil {
			return nil, err
		}
		return uint32(val), nil
	case Uint64:
		val, err := strconv.ParseUint(value, 0, 64)
		if err != nil {
			return nil, err
		}
		return uint64(val), nil

	// To float.
	case Float32:
		val, err := strconv.ParseFloat(value, 32)
		if err != nil {
			return nil, err
		}
		return float32(val), nil
	case Float64:
		val, err := strconv.ParseFloat(value, 64)
		if err != nil {
			return nil, err
		}
		return float64(val), nil

	// To string.
	case String:
		return value, nil

	// To bool.
	case Bool:
		val, err := strconv.ParseBool(value)
		if err != nil {
			return nil, err
		}
		return val, nil

	default:
		return nil, fmt.Errorf("Unable to coerce string to %s", typeName[coerceTo])
	}
}

// coerceFromArray attempts to convert the given array to the specified Type. Currently,
// arrays can only be coerced to arrays (identity). If it cannot be coerced, nil will be
// returned along with an error.
func coerceFromArray(value []interface{}, coerceTo Type) (interface{}, error) {
	if coerceTo == Array {
		return value, nil
	}

	return nil, fmt.Errorf("Unable to coerce array to %s", typeName[coerceTo])
}

// coerceFromMap attempts to convert the given map to the specified Type. Currently,
// maps can only be coerced to maps (identity). If it cannot be coerced, nil will be
// returned along with an error.
func coerceFromMap(value map[string]interface{}, coerceTo Type) (interface{}, error) {
	if coerceTo == Map {
		return value, nil
	}

	return nil, fmt.Errorf("Unable to coerce map to %s", typeName[coerceTo])
}
<|endoftext|>


<commit_before>package ripe

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
)

type ASN struct {
	Number string
	Data   map[string]interface{}
}

func flag() {

}

func (a *ASN) GetData() {
	resp, err := http.Get("https://stat.ripe.net/data/as-overview/data.json?resource=AS" + a.Number)
	if err != nil {
		println(err)
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	json.Unmarshal(body, &a.Data)
}

func (a *ASN) PrettyPrint() {
	data, ok := a.Data["data"].(map[string]interface{})
	if ok {
		println(string(data["holder"].(string)))
	} else {
		println("error")
	}
}
<commit_msg>fixed comments<commit_after>// Package ripe provides ASN and IP information
package ripe

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
)

// ASN represents ASN information
type ASN struct {
	Number string
	Data   map[string]interface{}
}

// GetData gets ASN information from RIPE NCC
func (a *ASN) GetData() {
	resp, err := http.Get("https://stat.ripe.net/data/as-overview/data.json?resource=AS" + a.Number)
	if err != nil {
		println(err)
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	json.Unmarshal(body, &a.Data)
}

// PrettyPrint print ASN information (holder)
func (a *ASN) PrettyPrint() {
	data, ok := a.Data["data"].(map[string]interface{})
	if ok {
		println(string(data["holder"].(string)))
	} else {
		println("error")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"math"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/ziutek/rrd"
)

const (
	step      = 10
	heartbeat = 2 * step
)

type QueryResponse struct {
	Target     string      `json:"target"`
	DataPoints [][]float64 `json:"datapoints"`
}

type QueryRequest struct {
	PanelId int `json:"panelId"`
	Range   struct {
		From string `json:"from"`
		To   string `jsong:"to"`
		Raw  struct {
			From string `json:"from"`
			To   string `json:"to"`
		} `json:"raw"`
	} `json:"range"`
	RangeRaw struct {
		From string `json:"from"`
		To   string `jsong:"to"`
	} `json:"rangeRaw"`
	Interval   string `json:"interval"`
	IntervalMs int    `json:"intervalMs"`
	Targets    []struct {
		Target string `json:"target"`
		RefId  string `json:"refId"`
	} `json:"targets"`
	Format        string `json:"format"`
	MaxDataPoints int    `json:"maxDataPoints"`
}

type Temp struct {
	Message string `json:"message"`
}

func hello(w http.ResponseWriter, r *http.Request) {
	result := Temp{Message: "hello"}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
	w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
	json, _ := json.Marshal(result)
	w.Write([]byte(json))
}

func search(w http.ResponseWriter, r *http.Request) {
	var result []string
	directories, _ := filepath.Glob(os.Args[1] + "*")
	for _, d := range directories {
		dName := filepath.Base(d)
		files, _ := filepath.Glob(d + "/*.rrd")
		for _, f := range files {
			fName := strings.Replace(filepath.Base(f), ".rrd", "", 1)
			result = append(result, dName+":"+fName)
		}
	}

	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
	w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
	json, _ := json.Marshal(result)
	w.Write([]byte(json))
}

func query(w http.ResponseWriter, r *http.Request) {
	if r.Method == "OPTIONS" {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
		w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
		w.Write(nil)
		return
	}
	decoder := json.NewDecoder(r.Body)
	var queryRequest QueryRequest
	err := decoder.Decode(&queryRequest)
	if err != nil {
		fmt.Println("error in query 1")
		fmt.Println(err)
	}
	defer r.Body.Close()

	from, _ := time.Parse(time.RFC3339Nano, queryRequest.Range.From)
	to, _ := time.Parse(time.RFC3339Nano, queryRequest.Range.To)

	var result []QueryResponse
	for _, target := range queryRequest.Targets {
		var points [][]float64
		splitTarget := strings.Split(target.Target, ":")
		fPath := os.Args[1] + splitTarget[0] + "/" + splitTarget[1] + ".rrd"
		infoRes, err := rrd.Info(fPath)
		if err != nil {
			fmt.Println("error in query 2")
			fmt.Println(err)
		}
		lastUpdate := time.Unix(int64(infoRes["last_update"].(uint)), 0)
		fmt.Println(from, " ", to, " ", lastUpdate)
		if to.After(lastUpdate) && lastUpdate.After(from) {
			to = lastUpdate
		}
		fmt.Println(from, " ", to, " ", lastUpdate)
		fetchRes, err := rrd.Fetch(fPath, "AVERAGE", from, to, step*time.Second)
		if err != nil {
			fmt.Println("error in query 3")
			fmt.Println(err)
		}
		timestamp := fetchRes.Start
		for _, value := range fetchRes.Values() {
			if math.IsNaN(value) {
				value = 0
			}
			points = append(points, []float64{value, float64(timestamp.Unix()) * 1000})
			timestamp = timestamp.Add(fetchRes.Step)
		}
		defer fetchRes.FreeValues()

		result = append(result, QueryResponse{Target: target.Target, DataPoints: points})
	}
	json, err := json.Marshal(result)
	if err != nil {
		fmt.Println("error when json.Marshal")
		fmt.Println(err)
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
	w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
	w.Write([]byte(json))
}

// no need to support
func annotations(w http.ResponseWriter, r *http.Request) {
	result := Temp{Message: "annotations"}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
	w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
	json, _ := json.Marshal(result)
	w.Write([]byte(json))
}

func main() {
	http.HandleFunc("/search", search)
	http.HandleFunc("/query", query)
	http.HandleFunc("/annotations", annotations)
	http.HandleFunc("/", hello)

	http.ListenAndServe(":8810", nil)
}
<commit_msg>Add a config file support<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"math"
	"net/http"
	"path/filepath"
	"strings"
	"time"

	"github.com/BurntSushi/toml"
	"github.com/ziutek/rrd"
)

var config Config

type QueryResponse struct {
	Target     string      `json:"target"`
	DataPoints [][]float64 `json:"datapoints"`
}

type QueryRequest struct {
	PanelId int `json:"panelId"`
	Range   struct {
		From string `json:"from"`
		To   string `jsong:"to"`
		Raw  struct {
			From string `json:"from"`
			To   string `json:"to"`
		} `json:"raw"`
	} `json:"range"`
	RangeRaw struct {
		From string `json:"from"`
		To   string `jsong:"to"`
	} `json:"rangeRaw"`
	Interval   string `json:"interval"`
	IntervalMs int    `json:"intervalMs"`
	Targets    []struct {
		Target string `json:"target"`
		RefId  string `json:"refId"`
	} `json:"targets"`
	Format        string `json:"format"`
	MaxDataPoints int    `json:"maxDataPoints"`
}

type Config struct {
	Server ServerConfig
}

type ServerConfig struct {
	RrdPath string
	Step    int
	Port    int
}

type Temp struct {
	Message string `json:"message"`
}

func hello(w http.ResponseWriter, r *http.Request) {
	result := Temp{Message: "hello"}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
	w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
	json, _ := json.Marshal(result)
	w.Write([]byte(json))
}

func search(w http.ResponseWriter, r *http.Request) {
	var result []string
	directories, _ := filepath.Glob(config.Server.RrdPath + "*")
	for _, d := range directories {
		dName := filepath.Base(d)
		files, _ := filepath.Glob(d + "/*.rrd")
		for _, f := range files {
			fName := strings.Replace(filepath.Base(f), ".rrd", "", 1)
			result = append(result, dName+":"+fName)
		}
	}

	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
	w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
	json, _ := json.Marshal(result)
	w.Write([]byte(json))
}

func query(w http.ResponseWriter, r *http.Request) {
	if r.Method == "OPTIONS" {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
		w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
		w.Write(nil)
		return
	}
	decoder := json.NewDecoder(r.Body)
	var queryRequest QueryRequest
	err := decoder.Decode(&queryRequest)
	if err != nil {
		fmt.Println("error in query 1")
		fmt.Println(err)
	}
	defer r.Body.Close()

	from, _ := time.Parse(time.RFC3339Nano, queryRequest.Range.From)
	to, _ := time.Parse(time.RFC3339Nano, queryRequest.Range.To)

	var result []QueryResponse
	for _, target := range queryRequest.Targets {
		var points [][]float64
		splitTarget := strings.Split(target.Target, ":")
		fPath := config.Server.RrdPath + splitTarget[0] + "/" + splitTarget[1] + ".rrd"
		infoRes, err := rrd.Info(fPath)
		if err != nil {
			fmt.Println("error in query 2")
			fmt.Println(err)
		}
		lastUpdate := time.Unix(int64(infoRes["last_update"].(uint)), 0)
		fmt.Println(from, " ", to, " ", lastUpdate)
		if to.After(lastUpdate) && lastUpdate.After(from) {
			to = lastUpdate
		}
		fmt.Println(from, " ", to, " ", lastUpdate)
		fetchRes, err := rrd.Fetch(fPath, "AVERAGE", from, to, time.Duration(config.Server.Step)*time.Second)
		if err != nil {
			fmt.Println("error in query 3")
			fmt.Println(err)
		}
		timestamp := fetchRes.Start
		for _, value := range fetchRes.Values() {
			if math.IsNaN(value) {
				value = 0
			}
			points = append(points, []float64{value, float64(timestamp.Unix()) * 1000})
			timestamp = timestamp.Add(fetchRes.Step)
		}
		defer fetchRes.FreeValues()

		result = append(result, QueryResponse{Target: target.Target, DataPoints: points})
	}
	json, err := json.Marshal(result)
	if err != nil {
		fmt.Println("error when json.Marshal")
		fmt.Println(err)
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
	w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
	w.Write([]byte(json))
}

// no need to support
func annotations(w http.ResponseWriter, r *http.Request) {
	result := Temp{Message: "annotations"}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "accept, content-type")
	w.Header().Set("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS")
	json, _ := json.Marshal(result)
	w.Write([]byte(json))
}

func main() {
	_, err := toml.DecodeFile("config.toml", &config)
	if err != nil {
		panic(err)
	}
	http.HandleFunc("/search", search)
	http.HandleFunc("/query", query)
	http.HandleFunc("/annotations", annotations)
	http.HandleFunc("/", hello)

	http.ListenAndServe(":8810", nil)
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Tigera, 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 rules

import (
	"fmt"
	"sort"

	"github.com/projectcalico/felix/iptables"
)

func (r *DefaultRuleRenderer) MakeNatOutgoingRule(protocol string, action iptables.Action, ipVersion uint8) iptables.Rule {
	ipConf := r.ipSetConfig(ipVersion)
	allIPsSetName := ipConf.NameForMainIPSet(IPSetIDNATOutgoingAllPools)
	masqIPsSetName := ipConf.NameForMainIPSet(IPSetIDNATOutgoingMasqPools)
	match := iptables.Match()

	match = iptables.Match().
		SourceIPSet(masqIPsSetName).
		NotDestIPSet(allIPsSetName)

	if protocol != "" {
		match = match.Protocol(protocol)
	}

	if r.Config.IptablesNATOutgoingInterfaceFilter != "" {
		match = match.OutInterface(r.Config.IptablesNATOutgoingInterfaceFilter)
	}

	rule := iptables.Rule{
		Action: action,
		Match:  match,
	}
	return rule
}

func (r *DefaultRuleRenderer) NATOutgoingChain(natOutgoingActive bool, ipVersion uint8) *iptables.Chain {
	var rules []iptables.Rule
	if natOutgoingActive {
		if r.Config.NATPortRange.MaxPort > 0 {
			toPorts := fmt.Sprintf("%d-%d", r.Config.NATPortRange.MinPort, r.Config.NATPortRange.MaxPort)
			rules = []iptables.Rule{
				r.MakeNatOutgoingRule("tcp", iptables.MasqAction{ToPorts: toPorts}, ipVersion),
				r.MakeNatOutgoingRule("tcp", iptables.ReturnAction{}, ipVersion),
				r.MakeNatOutgoingRule("udp", iptables.MasqAction{ToPorts: toPorts}, ipVersion),
				r.MakeNatOutgoingRule("udp", iptables.ReturnAction{}, ipVersion),
				r.MakeNatOutgoingRule("", iptables.MasqAction{}, ipVersion),
			}
		} else {
			rules = []iptables.Rule{
				r.MakeNatOutgoingRule("", iptables.MasqAction{}, ipVersion),
			}
		}
	}
	return &iptables.Chain{
		Name:  ChainNATOutgoing,
		Rules: rules,
	}
}

func (r *DefaultRuleRenderer) DNATsToIptablesChains(dnats map[string]string) []*iptables.Chain {
	// Extract and sort map keys so we can program rules in a determined order.
	sortedExtIps := make([]string, 0, len(dnats))
	for extIp := range dnats {
		sortedExtIps = append(sortedExtIps, extIp)
	}
	sort.Strings(sortedExtIps)

	rules := []iptables.Rule{}
	for _, extIp := range sortedExtIps {
		intIp := dnats[extIp]
		rules = append(rules, iptables.Rule{
			Match:  iptables.Match().DestNet(extIp),
			Action: iptables.DNATAction{DestAddr: intIp},
		})
	}
	return []*iptables.Chain{{
		Name:  ChainFIPDnat,
		Rules: rules,
	}}
}

func (r *DefaultRuleRenderer) SNATsToIptablesChains(snats map[string]string) []*iptables.Chain {
	// Extract and sort map keys so we can program rules in a determined order.
	sortedIntIps := make([]string, 0, len(snats))
	for intIp := range snats {
		sortedIntIps = append(sortedIntIps, intIp)
	}
	sort.Strings(sortedIntIps)

	rules := []iptables.Rule{}
	for _, intIp := range sortedIntIps {
		extIp := snats[intIp]
		rules = append(rules, iptables.Rule{
			Match:  iptables.Match().DestNet(intIp).SourceNet(intIp),
			Action: iptables.SNATAction{ToAddr: extIp},
		})
	}
	return []*iptables.Chain{{
		Name:  ChainFIPSnat,
		Rules: rules,
	}}
}
<commit_msg>linter fix<commit_after>// Copyright (c) 2016-2017 Tigera, 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 rules

import (
	"fmt"
	"sort"

	"github.com/projectcalico/felix/iptables"
)

func (r *DefaultRuleRenderer) MakeNatOutgoingRule(protocol string, action iptables.Action, ipVersion uint8) iptables.Rule {
	ipConf := r.ipSetConfig(ipVersion)
	allIPsSetName := ipConf.NameForMainIPSet(IPSetIDNATOutgoingAllPools)
	masqIPsSetName := ipConf.NameForMainIPSet(IPSetIDNATOutgoingMasqPools)

	match := iptables.Match().
		SourceIPSet(masqIPsSetName).
		NotDestIPSet(allIPsSetName)

	if protocol != "" {
		match = match.Protocol(protocol)
	}

	if r.Config.IptablesNATOutgoingInterfaceFilter != "" {
		match = match.OutInterface(r.Config.IptablesNATOutgoingInterfaceFilter)
	}

	rule := iptables.Rule{
		Action: action,
		Match:  match,
	}
	return rule
}

func (r *DefaultRuleRenderer) NATOutgoingChain(natOutgoingActive bool, ipVersion uint8) *iptables.Chain {
	var rules []iptables.Rule
	if natOutgoingActive {
		if r.Config.NATPortRange.MaxPort > 0 {
			toPorts := fmt.Sprintf("%d-%d", r.Config.NATPortRange.MinPort, r.Config.NATPortRange.MaxPort)
			rules = []iptables.Rule{
				r.MakeNatOutgoingRule("tcp", iptables.MasqAction{ToPorts: toPorts}, ipVersion),
				r.MakeNatOutgoingRule("tcp", iptables.ReturnAction{}, ipVersion),
				r.MakeNatOutgoingRule("udp", iptables.MasqAction{ToPorts: toPorts}, ipVersion),
				r.MakeNatOutgoingRule("udp", iptables.ReturnAction{}, ipVersion),
				r.MakeNatOutgoingRule("", iptables.MasqAction{}, ipVersion),
			}
		} else {
			rules = []iptables.Rule{
				r.MakeNatOutgoingRule("", iptables.MasqAction{}, ipVersion),
			}
		}
	}
	return &iptables.Chain{
		Name:  ChainNATOutgoing,
		Rules: rules,
	}
}

func (r *DefaultRuleRenderer) DNATsToIptablesChains(dnats map[string]string) []*iptables.Chain {
	// Extract and sort map keys so we can program rules in a determined order.
	sortedExtIps := make([]string, 0, len(dnats))
	for extIp := range dnats {
		sortedExtIps = append(sortedExtIps, extIp)
	}
	sort.Strings(sortedExtIps)

	rules := []iptables.Rule{}
	for _, extIp := range sortedExtIps {
		intIp := dnats[extIp]
		rules = append(rules, iptables.Rule{
			Match:  iptables.Match().DestNet(extIp),
			Action: iptables.DNATAction{DestAddr: intIp},
		})
	}
	return []*iptables.Chain{{
		Name:  ChainFIPDnat,
		Rules: rules,
	}}
}

func (r *DefaultRuleRenderer) SNATsToIptablesChains(snats map[string]string) []*iptables.Chain {
	// Extract and sort map keys so we can program rules in a determined order.
	sortedIntIps := make([]string, 0, len(snats))
	for intIp := range snats {
		sortedIntIps = append(sortedIntIps, intIp)
	}
	sort.Strings(sortedIntIps)

	rules := []iptables.Rule{}
	for _, intIp := range sortedIntIps {
		extIp := snats[intIp]
		rules = append(rules, iptables.Rule{
			Match:  iptables.Match().DestNet(intIp).SourceNet(intIp),
			Action: iptables.SNATAction{ToAddr: extIp},
		})
	}
	return []*iptables.Chain{{
		Name:  ChainFIPSnat,
		Rules: rules,
	}}
}
<|endoftext|>


<commit_before>package safe

import (
	"fmt"
)

func (s *Safe) SyncWith(otherSafe *Safe) error {
	localAccounts := s.Accounts
	remoteAccounts := otherSafe.Accounts

	for name, remoteAccount := range remoteAccounts {
		// If we don't have an remote account yet, simply add it
		if localAccount, ok := localAccounts[name]; !ok {
			fmt.Printf("Importing new account '%s'..\n", name)
			localAccounts[name] = remoteAccount
		} else {
			// We already have this account, now sync current state & history
			fmt.Printf("Syncing '%s'.. ", name)
			synced, err := localAccount.SyncWith(&remoteAccount, name)
			if err != nil {
				fmt.Printf("error: %s\n", err)
				continue
			}
			if !synced {
				fmt.Printf("account already up-to-date\n")
			} else {
				fmt.Printf("done\n")
				// Save it
				localAccounts[name] = localAccount
			}
		}
	}
	// TODO(leon): Should we also sync in the reverse direction, i.e. local -> remote?
	return s.save()
}
<commit_msg>Add method doc for 'SyncWith'<commit_after>package safe

import (
	"fmt"
)

// SyncWith syncs the current safe with another safe if they're branching off the same
// safe, i.e. are not completely different safes. It simply imports non-existing
// accounts into the current safe and updates existing accounts if the other safe has
// a more recent version of the account. A backup is made when updating existing accounts
func (s *Safe) SyncWith(otherSafe *Safe) error {
	localAccounts := s.Accounts
	remoteAccounts := otherSafe.Accounts

	for name, remoteAccount := range remoteAccounts {
		// If we don't have an remote account yet, simply add it
		if localAccount, ok := localAccounts[name]; !ok {
			fmt.Printf("Importing new account '%s'..\n", name)
			localAccounts[name] = remoteAccount
		} else {
			// We already have this account, now sync current state & history
			fmt.Printf("Syncing '%s'.. ", name)
			synced, err := localAccount.SyncWith(&remoteAccount, name)
			if err != nil {
				fmt.Printf("error: %s\n", err)
				continue
			}
			if !synced {
				fmt.Printf("account already up-to-date\n")
			} else {
				fmt.Printf("done\n")
				// Save it
				localAccounts[name] = localAccount
			}
		}
	}
	// TODO(leon): Should we also sync in the reverse direction, i.e. local -> remote?
	return s.save()
}
<|endoftext|>