<commit_before>package main

import (
	"crypto/rand"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/kdomanski/tenus"
)

const constInterfaceName string = "engitlab0"

func getDefaultInterface() (string, error) {
	cmd := exec.Command("ip", "route", "get", "8.8.8.8")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", err
	}

	reg, err := regexp.Compile("dev e[nt]+[0-9a-z_]+")
	if err != nil {
		return "", err
	}

	found := reg.Find(out)
	if found == nil {
		return "", fmt.Errorf("getDefaultInterface(): error parsing the output of `ip`")
	}

	split := strings.Split(string(found), " ")
	if len(split) != 2 {
		return "", fmt.Errorf("getDefaultInterface(): error parsing the output of `ip`")
	}

	return split[1], nil
}

func createMac() string {
	r := make([]byte, 3)
	_, err := rand.Read(r)
	if err != nil {
		panic(fmt.Sprintf("createMac(): Failed to generate random MAC bytes: %s", err.Error()))
	}

	return fmt.Sprintf("00:11:22:%x:%x:%x", r[0:1], r[1:2], r[2:3])
}

func getMac() string {
	// if the MAC file doesn't exist
	if _, err := os.Stat("/etc/protonet/gitlab/mac"); os.IsNotExist(err) {

		// create the parent folder, if they are missing
		if os.Stat("/etc/protonet"); os.IsNotExist(err) {
			err = os.Mkdir("/etc/protonet/gitlab", 0755)
			if err != nil {
				panic(err)
			}
		}

		if os.Stat("/etc/protonet/gitlab"); os.IsNotExist(err) {
			err := os.Mkdir("/etc/protonet/gitlab", 0755)
			if err != nil {
				panic(err)
			}
		}

		newMac := createMac()

		err := ioutil.WriteFile("/etc/protonet/gitlab/mac", []byte(newMac), 0644)
		if err != nil {
			panic(err)
		}
		return string(newMac)
	}

	data, err := ioutil.ReadFile("/etc/protonet/gitlab/mac")
	if err != nil {
		panic(err)
	}
	return string(data)
}

func createInterface(ifName string) error {
	_, err := net.InterfaceByName(ifName)
	if err == nil {
		log.Printf("Interface '%s' already exists.", ifName)
		return nil
	}

	mac := getMac()

	defaultInterface, err := getDefaultInterface()
	if err != nil {
		return err
	}

	link, err := tenus.NewMacVlanLinkWithOptions(defaultInterface, tenus.MacVlanOptions{Dev: ifName, MacAddr: mac})
	if err != nil {
		return err
	}

	err = link.SetLinkUp()
	if err != nil {
		return err
	}

	return nil
}

func getInterfaceIP(ifName string) (string, error) {
	interf, err := net.InterfaceByName(ifName)
	if err != nil {
		return "", err
	}

	addrs, err := interf.Addrs()
	if err != nil {
		return "", err
	}

	// TODO: what about len(addr) > 1 ?
	if len(addrs) == 0 {
		return "", fmt.Errorf("the device %s has no network addresses", ifName)
	}

	cidr := addrs[0].String()
	ip, _, err := net.ParseCIDR(cidr)
	if err != nil {
		return "", fmt.Errorf("error parsing CIDR '%s'", cidr)
	}

	return ip.String(), nil
}

func printUsage() {
	fmt.Printf("Usage: %s start|stop|show\n", os.Args[0])
	fmt.Printf("\tstart:\tcreate the gitlab interface if it does not yet exist.\n")
	fmt.Printf("\tstop:\tdestroy the gitlab interface if it does exist.\n")
	fmt.Printf("\tshow:\tshow the ipv4 address if the interface has one.\n")
}

func main() {
	if len(os.Args) != 2 {
		printUsage()
		os.Exit(1)
	}

	switch os.Args[1] {
	case "start":
		err := createInterface(constInterfaceName)
		if err != nil {
			log.Fatalf("failed to create interface: %s\n", err.Error())
		}
		break
	case "stop":
		err := tenus.DeleteLink(constInterfaceName)
		if err != nil {
			log.Fatalf("failed to delete interface: %s\n", err.Error())
		}
		break
	case "show":
		ip, err := getInterfaceIP(constInterfaceName)
		if err != nil {
			log.Fatalf("failed to get interface IP: %s\n", err.Error())
		}

		fmt.Print(ip)
		break
	default:
		printUsage()
		os.Exit(1)
	}
}
<commit_msg>fix a bug in gitlab-network<commit_after>package main

import (
	"crypto/rand"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/kdomanski/tenus"
)

const constInterfaceName string = "engitlab0"

func getDefaultInterface() (string, error) {
	cmd := exec.Command("ip", "route", "get", "8.8.8.8")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", err
	}

	reg, err := regexp.Compile("dev e[nt]+[0-9a-z_]+")
	if err != nil {
		return "", err
	}

	found := reg.Find(out)
	if found == nil {
		return "", fmt.Errorf("getDefaultInterface(): error parsing the output of `ip`")
	}

	split := strings.Split(string(found), " ")
	if len(split) != 2 {
		return "", fmt.Errorf("getDefaultInterface(): error parsing the output of `ip`")
	}

	return split[1], nil
}

func createMac() string {
	r := make([]byte, 3)
	_, err := rand.Read(r)
	if err != nil {
		panic(fmt.Sprintf("createMac(): Failed to generate random MAC bytes: %s", err.Error()))
	}

	return fmt.Sprintf("00:11:22:%x:%x:%x", r[0:1], r[1:2], r[2:3])
}

func getMac() string {
	// if the MAC file doesn't exist
	if _, err := os.Stat("/etc/protonet/gitlab/mac"); os.IsNotExist(err) {

		// create the parent folder, if they are missing
		if _, err = os.Stat("/etc/protonet"); os.IsNotExist(err) {
			err = os.Mkdir("/etc/protonet/gitlab", 0755)
			if err != nil {
				panic(err)
			}
		}

		if _, err = os.Stat("/etc/protonet/gitlab"); os.IsNotExist(err) {
			err := os.Mkdir("/etc/protonet/gitlab", 0755)
			if err != nil {
				panic(err)
			}
		}

		newMac := createMac()

		err := ioutil.WriteFile("/etc/protonet/gitlab/mac", []byte(newMac), 0644)
		if err != nil {
			panic(err)
		}
		return string(newMac)
	}

	data, err := ioutil.ReadFile("/etc/protonet/gitlab/mac")
	if err != nil {
		panic(err)
	}
	return string(data)
}

func createInterface(ifName string) error {
	_, err := net.InterfaceByName(ifName)
	if err == nil {
		log.Printf("Interface '%s' already exists.", ifName)
		return nil
	}

	mac := getMac()

	defaultInterface, err := getDefaultInterface()
	if err != nil {
		return err
	}

	link, err := tenus.NewMacVlanLinkWithOptions(defaultInterface, tenus.MacVlanOptions{Dev: ifName, MacAddr: mac})
	if err != nil {
		return err
	}

	err = link.SetLinkUp()
	if err != nil {
		return err
	}

	return nil
}

func getInterfaceIP(ifName string) (string, error) {
	interf, err := net.InterfaceByName(ifName)
	if err != nil {
		return "", err
	}

	addrs, err := interf.Addrs()
	if err != nil {
		return "", err
	}

	// TODO: what about len(addr) > 1 ?
	if len(addrs) == 0 {
		return "", fmt.Errorf("the device %s has no network addresses", ifName)
	}

	cidr := addrs[0].String()
	ip, _, err := net.ParseCIDR(cidr)
	if err != nil {
		return "", fmt.Errorf("error parsing CIDR '%s'", cidr)
	}

	return ip.String(), nil
}

func printUsage() {
	fmt.Printf("Usage: %s start|stop|show\n", os.Args[0])
	fmt.Printf("\tstart:\tcreate the gitlab interface if it does not yet exist.\n")
	fmt.Printf("\tstop:\tdestroy the gitlab interface if it does exist.\n")
	fmt.Printf("\tshow:\tshow the ipv4 address if the interface has one.\n")
}

func main() {
	if len(os.Args) != 2 {
		printUsage()
		os.Exit(1)
	}

	switch os.Args[1] {
	case "start":
		err := createInterface(constInterfaceName)
		if err != nil {
			log.Fatalf("failed to create interface: %s\n", err.Error())
		}
		break
	case "stop":
		err := tenus.DeleteLink(constInterfaceName)
		if err != nil {
			log.Fatalf("failed to delete interface: %s\n", err.Error())
		}
		break
	case "show":
		ip, err := getInterfaceIP(constInterfaceName)
		if err != nil {
			log.Fatalf("failed to get interface IP: %s\n", err.Error())
		}

		fmt.Print(ip)
		break
	default:
		printUsage()
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// Copyright 2020 Anapaya Systems
//
// 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 gateway

import (
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"

	"github.com/scionproto/scion/go/lib/addr"
	"github.com/scionproto/scion/go/lib/metrics"
	"github.com/scionproto/scion/go/lib/snet"
	snetmetrics "github.com/scionproto/scion/go/lib/snet/metrics"
)

// These are the metrics that should be exposed by any gateway implementation.
var (
	IPPktBytesSentTotalMeta = MetricMeta{
		Name:   "gateway_ippkt_bytes_sent_total",
		Help:   "Total IP packet bytes sent to remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id"},
	}
	IPPktsSentTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_sent_total",
		Help:   "Total number of IP packets sent to remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id"},
	}
	IPPktBytesReceivedTotalMeta = MetricMeta{
		Name:   "gateway_ippkt_bytes_received_total",
		Help:   "Total IP packet bytes received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	IPPktsReceivedTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_received_total",
		Help:   "Total number of IP packets received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	IPPktBytesLocalSentTotalMeta = MetricMeta{
		Name:   "gateway_ippkt_bytes_local_sent_total",
		Help:   "Total IP packet bytes sent to the local network.",
		Labels: []string{"isd_as"},
	}
	IPPktsLocalSentTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_local_sent_total",
		Help:   "Total number of IP packets sent to the local network.",
		Labels: []string{"isd_as"},
	}
	IPPktBytesLocalReceivedTotalMeta = MetricMeta{
		Name:   "gateway_ippkt_bytes_local_received_total",
		Help:   "Total IP packet bytes received from the local network.",
		Labels: []string{"isd_as"},
	}
	IPPktsLocalReceivedTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_local_received_total",
		Help:   "Total number of IP packets received from the local network.",
		Labels: []string{"isd_as"},
	}
	FrameBytesSentTotalMeta = MetricMeta{
		Name:   "gateway_frame_bytes_sent_total",
		Help:   "Total frame bytes sent to remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id"},
	}
	FramesSentTotalMeta = MetricMeta{
		Name:   "gateway_frames_sent_total",
		Help:   "Total number of frames sent to remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id"},
	}
	FrameBytesReceivedTotalMeta = MetricMeta{
		Name:   "gateway_frame_bytes_received_total",
		Help:   "Total frame bytes received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	FramesReceivedTotalMeta = MetricMeta{
		Name:   "gateway_frames_received_total",
		Help:   "Total number of frames received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	FramesDiscardedTotalMeta = MetricMeta{
		Name:   "gateway_frames_discarded_total",
		Help:   "Total number of discarded frames received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "reason"},
	}
	IPPktsDiscardedTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_discarded_total",
		Help:   "Total number of discarded IP packets received from the local network.",
		Labels: []string{"isd_as", "reason"},
	}
	SendExternalErrorsTotalMeta = MetricMeta{
		Name:   "gateway_send_external_errors_total",
		Help:   "Total number of errors when sending frames to the network (WAN).",
		Labels: []string{"isd_as"},
	}
	SendLocalErrorsTotalMeta = MetricMeta{
		Name:   "gateway_send_local_errors_total",
		Help:   "Total number of errors when sending IP packets to the network (LAN).",
		Labels: []string{"isd_as"},
	}
	ReceiveExternalErrorsTotalMeta = MetricMeta{
		Name:   "gateway_receive_external_errors_total",
		Help:   "Total number of errors when receiving frames from the network (WAN).",
		Labels: []string{"isd_as"},
	}
	ReceiveLocalErrorsTotalMeta = MetricMeta{
		Name:   "gateway_receive_local_errors_total",
		Help:   "Total number of errors when receiving IP packets from the network (LAN).",
		Labels: []string{"isd_as"},
	}
	PathsMonitoredMeta = MetricMeta{
		Name:   "gateway_paths_monitored",
		Help:   "Total number of paths being monitored by the gateway.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PathProbesSentMeta = MetricMeta{
		Name:   "gateway_path_probes_sent",
		Help:   "Number of path probes being sent.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PathProbesReceivedMeta = MetricMeta{
		Name:   "gateway_path_probes_received",
		Help:   "Number of replies to the path probes being received.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PathProbesSendErrorsMeta = MetricMeta{
		Name:   "gateway_path_probes_send_errors",
		Help:   "Number of send error for path probes.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	SessionProbesMeta = MetricMeta{
		Name:   "gateway_session_probes",
		Help:   "Number of probes sent per session.",
		Labels: []string{"isd_as", "remote_isd_as", "session_id", "policy_id"},
	}
	SessionProbeRepliesMeta = MetricMeta{
		Name:   "gateway_session_probe_replies",
		Help:   "Number of probes received per session.",
		Labels: []string{"isd_as", "remote_isd_as", "session_id", "policy_id"},
	}
	SessionIsHealthyMeta = MetricMeta{
		Name:   "gateway_session_is_healthy",
		Help:   "Flag reflecting session healthiness.",
		Labels: []string{"isd_as", "remote_isd_as", "session_id", "policy_id"},
	}
	SessionPathsAvailableMeta = MetricMeta{
		Name:   "gateway_session_paths_available",
		Help:   "Total number of paths available per session policy.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id", "status"},
	}
	RemotesMeta = MetricMeta{
		Name:   "gateway_remotes",
		Help:   "Total number of discovered remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	RemoteDiscoveryErrorsMeta = MetricMeta{
		Name:   "gateway_remote_discovery_errors_total",
		Help:   "Total number of errors discovering remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PrefixFetchErrorsMeta = MetricMeta{
		Name:   "gateway_prefix_fetch_errors_total",
		Help:   "Total number of errors fetching prefixes.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PrefixesAdvertisedMeta = MetricMeta{
		Name:   "gateway_prefixes_advertised",
		Help:   "Total number of advertised IP prefixes (outgoing).",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PrefixesAcceptedMeta = MetricMeta{
		Name:   "gateway_prefixes_accepted",
		Help:   "Total number of accepted IP prefixes (incoming).",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PrefixesRejectedMeta = MetricMeta{
		Name:   "gateway_prefixes_rejected",
		Help:   "Total number of rejected IP prefixes (incoming).",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
)

type MetricMeta struct {
	Name   string
	Help   string
	Labels []string
}

func (mm *MetricMeta) NewCounterVec() *prometheus.CounterVec {
	return promauto.NewCounterVec(
		prometheus.CounterOpts{
			Name: mm.Name,
			Help: mm.Help,
		},
		mm.Labels,
	)
}

func (mm *MetricMeta) NewGaugeVec() *prometheus.GaugeVec {
	return promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: mm.Name,
			Help: mm.Help,
		},
		mm.Labels,
	)
}

// Metrics defines the metrics exported by the gateway.
type Metrics struct {
	// Traffic Metrics
	IPPktBytesSentTotal          *prometheus.CounterVec
	IPPktBytesReceivedTotal      *prometheus.CounterVec
	IPPktsSentTotal              *prometheus.CounterVec
	IPPktsReceivedTotal          *prometheus.CounterVec
	IPPktBytesLocalSentTotal     *prometheus.CounterVec
	IPPktBytesLocalReceivedTotal *prometheus.CounterVec
	IPPktsLocalSentTotal         *prometheus.CounterVec
	IPPktsLocalReceivedTotal     *prometheus.CounterVec
	FrameBytesSentTotal          *prometheus.CounterVec
	FrameBytesReceivedTotal      *prometheus.CounterVec
	FramesSentTotal              *prometheus.CounterVec
	FramesReceivedTotal          *prometheus.CounterVec

	// Error Metrics
	FramesDiscardedTotal       *prometheus.CounterVec
	IPPktsDiscardedTotal       *prometheus.CounterVec
	SendExternalErrorsTotal    *prometheus.CounterVec
	SendLocalErrorsTotal       *prometheus.CounterVec
	ReceiveExternalErrorsTotal *prometheus.CounterVec
	ReceiveLocalErrorsTotal    *prometheus.CounterVec

	// Path Monitoring Metrics
	PathsMonitored        *prometheus.GaugeVec
	SessionPathsAvailable *prometheus.GaugeVec
	PathProbesSent        *prometheus.CounterVec
	PathProbesReceived    *prometheus.CounterVec
	PathProbesSendErrors  *prometheus.CounterVec

	// Discovery Metrics
	Remotes               *prometheus.GaugeVec
	RemoteDiscoveryErrors *prometheus.CounterVec
	PrefixFetchErrors     *prometheus.CounterVec
	PrefixesAdvertised    *prometheus.GaugeVec
	PrefixesAccepted      *prometheus.GaugeVec
	PrefixesRejected      *prometheus.GaugeVec

	// SessionMonitor Metrics
	SessionProbes       *prometheus.CounterVec
	SessionProbeReplies *prometheus.CounterVec
	SessionIsHealthy    *prometheus.GaugeVec

	// Scion Network Metrics
	SCIONNetworkMetrics    snet.SCIONNetworkMetrics
	SCMPErrors             metrics.Counter
	SCIONPacketConnMetrics snet.SCIONPacketConnMetrics
}

// NewMetrics initializes the metrics for the gateway and registers them with the default registry.
func NewMetrics(ia addr.IA) *Metrics {
	labels := map[string]string{
		"isd_as": ia.String(),
	}
	scionPacketConnMetrics := snetmetrics.NewSCIONPacketConnMetrics()
	return &Metrics{
		IPPktBytesSentTotal: IPPktBytesSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktsSentTotal: IPPktsSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktBytesReceivedTotal: IPPktBytesReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktsReceivedTotal: IPPktsReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktBytesLocalSentTotal: IPPktBytesLocalSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktsLocalSentTotal: IPPktsLocalSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktBytesLocalReceivedTotal: IPPktBytesLocalReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktsLocalReceivedTotal: IPPktsLocalReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		FrameBytesSentTotal: FrameBytesSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		FramesSentTotal: FramesSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		FrameBytesReceivedTotal: FrameBytesReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		FramesReceivedTotal: FramesReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		FramesDiscardedTotal: FramesDiscardedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktsDiscardedTotal: IPPktsDiscardedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		SendExternalErrorsTotal: SendExternalErrorsTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		SendLocalErrorsTotal: SendLocalErrorsTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		ReceiveExternalErrorsTotal: ReceiveExternalErrorsTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		ReceiveLocalErrorsTotal: ReceiveLocalErrorsTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		PathsMonitored: PathsMonitoredMeta.
			NewGaugeVec().MustCurryWith(labels),
		PathProbesSent: PathProbesSentMeta.
			NewCounterVec().MustCurryWith(labels),
		PathProbesReceived: PathProbesReceivedMeta.
			NewCounterVec().MustCurryWith(labels),
		PathProbesSendErrors: PathProbesSendErrorsMeta.
			NewCounterVec().MustCurryWith(labels),
		SessionIsHealthy: SessionIsHealthyMeta.
			NewGaugeVec().MustCurryWith(labels),
		SessionProbes: SessionProbesMeta.
			NewCounterVec().MustCurryWith(labels),
		SessionProbeReplies: SessionProbeRepliesMeta.
			NewCounterVec().MustCurryWith(labels),
		SessionPathsAvailable: SessionPathsAvailableMeta.
			NewGaugeVec().MustCurryWith(labels),
		Remotes: RemotesMeta.
			NewGaugeVec().MustCurryWith(labels),
		RemoteDiscoveryErrors: RemoteDiscoveryErrorsMeta.
			NewCounterVec().MustCurryWith(labels),
		PrefixFetchErrors: PrefixFetchErrorsMeta.
			NewCounterVec().MustCurryWith(labels),
		PrefixesAdvertised: PrefixesAdvertisedMeta.
			NewGaugeVec().MustCurryWith(labels),
		PrefixesAccepted: PrefixesAcceptedMeta.
			NewGaugeVec().MustCurryWith(labels),
		PrefixesRejected: PrefixesRejectedMeta.
			NewGaugeVec().MustCurryWith(labels),
		SCIONNetworkMetrics:    snetmetrics.NewSCIONNetworkMetrics(),
		SCMPErrors:             scionPacketConnMetrics.SCMPErrors,
		SCIONPacketConnMetrics: scionPacketConnMetrics,
	}
}
<commit_msg>remove `isd_as` label from IP metrics<commit_after>// Copyright 2020 Anapaya Systems
//
// 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 gateway

import (
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"

	"github.com/scionproto/scion/go/lib/addr"
	"github.com/scionproto/scion/go/lib/metrics"
	"github.com/scionproto/scion/go/lib/snet"
	snetmetrics "github.com/scionproto/scion/go/lib/snet/metrics"
)

// These are the metrics that should be exposed by any gateway implementation.
var (
	IPPktBytesSentTotalMeta = MetricMeta{
		Name:   "gateway_ippkt_bytes_sent_total",
		Help:   "Total IP packet bytes sent to remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id"},
	}
	IPPktsSentTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_sent_total",
		Help:   "Total number of IP packets sent to remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id"},
	}
	IPPktBytesReceivedTotalMeta = MetricMeta{
		Name:   "gateway_ippkt_bytes_received_total",
		Help:   "Total IP packet bytes received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	IPPktsReceivedTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_received_total",
		Help:   "Total number of IP packets received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	IPPktBytesLocalSentTotalMeta = MetricMeta{
		Name:   "gateway_ippkt_bytes_local_sent_total",
		Help:   "Total IP packet bytes sent to the local network.",
		Labels: []string{"isd_as"},
	}
	IPPktsLocalSentTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_local_sent_total",
		Help:   "Total number of IP packets sent to the local network.",
		Labels: []string{"isd_as"},
	}
	IPPktBytesLocalReceivedTotalMeta = MetricMeta{
		Name:   "gateway_ippkt_bytes_local_received_total",
		Help:   "Total IP packet bytes received from the local network.",
		Labels: []string{},
	}
	IPPktsLocalReceivedTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_local_received_total",
		Help:   "Total number of IP packets received from the local network.",
		Labels: []string{},
	}
	FrameBytesSentTotalMeta = MetricMeta{
		Name:   "gateway_frame_bytes_sent_total",
		Help:   "Total frame bytes sent to remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id"},
	}
	FramesSentTotalMeta = MetricMeta{
		Name:   "gateway_frames_sent_total",
		Help:   "Total number of frames sent to remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id"},
	}
	FrameBytesReceivedTotalMeta = MetricMeta{
		Name:   "gateway_frame_bytes_received_total",
		Help:   "Total frame bytes received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	FramesReceivedTotalMeta = MetricMeta{
		Name:   "gateway_frames_received_total",
		Help:   "Total number of frames received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	FramesDiscardedTotalMeta = MetricMeta{
		Name:   "gateway_frames_discarded_total",
		Help:   "Total number of discarded frames received from remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as", "reason"},
	}
	IPPktsDiscardedTotalMeta = MetricMeta{
		Name:   "gateway_ippkts_discarded_total",
		Help:   "Total number of discarded IP packets received from the local network.",
		Labels: []string{"reason"},
	}
	SendExternalErrorsTotalMeta = MetricMeta{
		Name:   "gateway_send_external_errors_total",
		Help:   "Total number of errors when sending frames to the network (WAN).",
		Labels: []string{"isd_as"},
	}
	SendLocalErrorsTotalMeta = MetricMeta{
		Name:   "gateway_send_local_errors_total",
		Help:   "Total number of errors when sending IP packets to the network (LAN).",
		Labels: []string{"isd_as"},
	}
	ReceiveExternalErrorsTotalMeta = MetricMeta{
		Name:   "gateway_receive_external_errors_total",
		Help:   "Total number of errors when receiving frames from the network (WAN).",
		Labels: []string{"isd_as"},
	}
	ReceiveLocalErrorsTotalMeta = MetricMeta{
		Name:   "gateway_receive_local_errors_total",
		Help:   "Total number of errors when receiving IP packets from the network (LAN).",
		Labels: []string{"isd_as"},
	}
	PathsMonitoredMeta = MetricMeta{
		Name:   "gateway_paths_monitored",
		Help:   "Total number of paths being monitored by the gateway.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PathProbesSentMeta = MetricMeta{
		Name:   "gateway_path_probes_sent",
		Help:   "Number of path probes being sent.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PathProbesReceivedMeta = MetricMeta{
		Name:   "gateway_path_probes_received",
		Help:   "Number of replies to the path probes being received.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PathProbesSendErrorsMeta = MetricMeta{
		Name:   "gateway_path_probes_send_errors",
		Help:   "Number of send error for path probes.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	SessionProbesMeta = MetricMeta{
		Name:   "gateway_session_probes",
		Help:   "Number of probes sent per session.",
		Labels: []string{"isd_as", "remote_isd_as", "session_id", "policy_id"},
	}
	SessionProbeRepliesMeta = MetricMeta{
		Name:   "gateway_session_probe_replies",
		Help:   "Number of probes received per session.",
		Labels: []string{"isd_as", "remote_isd_as", "session_id", "policy_id"},
	}
	SessionIsHealthyMeta = MetricMeta{
		Name:   "gateway_session_is_healthy",
		Help:   "Flag reflecting session healthiness.",
		Labels: []string{"isd_as", "remote_isd_as", "session_id", "policy_id"},
	}
	SessionPathsAvailableMeta = MetricMeta{
		Name:   "gateway_session_paths_available",
		Help:   "Total number of paths available per session policy.",
		Labels: []string{"isd_as", "remote_isd_as", "policy_id", "status"},
	}
	RemotesMeta = MetricMeta{
		Name:   "gateway_remotes",
		Help:   "Total number of discovered remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	RemoteDiscoveryErrorsMeta = MetricMeta{
		Name:   "gateway_remote_discovery_errors_total",
		Help:   "Total number of errors discovering remote gateways.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PrefixFetchErrorsMeta = MetricMeta{
		Name:   "gateway_prefix_fetch_errors_total",
		Help:   "Total number of errors fetching prefixes.",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PrefixesAdvertisedMeta = MetricMeta{
		Name:   "gateway_prefixes_advertised",
		Help:   "Total number of advertised IP prefixes (outgoing).",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PrefixesAcceptedMeta = MetricMeta{
		Name:   "gateway_prefixes_accepted",
		Help:   "Total number of accepted IP prefixes (incoming).",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
	PrefixesRejectedMeta = MetricMeta{
		Name:   "gateway_prefixes_rejected",
		Help:   "Total number of rejected IP prefixes (incoming).",
		Labels: []string{"isd_as", "remote_isd_as"},
	}
)

type MetricMeta struct {
	Name   string
	Help   string
	Labels []string
}

func (mm *MetricMeta) NewCounterVec() *prometheus.CounterVec {
	return promauto.NewCounterVec(
		prometheus.CounterOpts{
			Name: mm.Name,
			Help: mm.Help,
		},
		mm.Labels,
	)
}

func (mm *MetricMeta) NewGaugeVec() *prometheus.GaugeVec {
	return promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: mm.Name,
			Help: mm.Help,
		},
		mm.Labels,
	)
}

// Metrics defines the metrics exported by the gateway.
type Metrics struct {
	// Traffic Metrics
	IPPktBytesSentTotal          *prometheus.CounterVec
	IPPktBytesReceivedTotal      *prometheus.CounterVec
	IPPktsSentTotal              *prometheus.CounterVec
	IPPktsReceivedTotal          *prometheus.CounterVec
	IPPktBytesLocalSentTotal     *prometheus.CounterVec
	IPPktBytesLocalReceivedTotal *prometheus.CounterVec
	IPPktsLocalSentTotal         *prometheus.CounterVec
	IPPktsLocalReceivedTotal     *prometheus.CounterVec
	FrameBytesSentTotal          *prometheus.CounterVec
	FrameBytesReceivedTotal      *prometheus.CounterVec
	FramesSentTotal              *prometheus.CounterVec
	FramesReceivedTotal          *prometheus.CounterVec

	// Error Metrics
	FramesDiscardedTotal       *prometheus.CounterVec
	IPPktsDiscardedTotal       *prometheus.CounterVec
	SendExternalErrorsTotal    *prometheus.CounterVec
	SendLocalErrorsTotal       *prometheus.CounterVec
	ReceiveExternalErrorsTotal *prometheus.CounterVec
	ReceiveLocalErrorsTotal    *prometheus.CounterVec

	// Path Monitoring Metrics
	PathsMonitored        *prometheus.GaugeVec
	SessionPathsAvailable *prometheus.GaugeVec
	PathProbesSent        *prometheus.CounterVec
	PathProbesReceived    *prometheus.CounterVec
	PathProbesSendErrors  *prometheus.CounterVec

	// Discovery Metrics
	Remotes               *prometheus.GaugeVec
	RemoteDiscoveryErrors *prometheus.CounterVec
	PrefixFetchErrors     *prometheus.CounterVec
	PrefixesAdvertised    *prometheus.GaugeVec
	PrefixesAccepted      *prometheus.GaugeVec
	PrefixesRejected      *prometheus.GaugeVec

	// SessionMonitor Metrics
	SessionProbes       *prometheus.CounterVec
	SessionProbeReplies *prometheus.CounterVec
	SessionIsHealthy    *prometheus.GaugeVec

	// Scion Network Metrics
	SCIONNetworkMetrics    snet.SCIONNetworkMetrics
	SCMPErrors             metrics.Counter
	SCIONPacketConnMetrics snet.SCIONPacketConnMetrics
}

// NewMetrics initializes the metrics for the gateway and registers them with the default registry.
func NewMetrics(ia addr.IA) *Metrics {
	labels := map[string]string{
		"isd_as": ia.String(),
	}
	scionPacketConnMetrics := snetmetrics.NewSCIONPacketConnMetrics()
	return &Metrics{
		IPPktBytesSentTotal: IPPktBytesSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktsSentTotal: IPPktsSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktBytesReceivedTotal: IPPktBytesReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktsReceivedTotal: IPPktsReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktBytesLocalSentTotal: IPPktBytesLocalSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktsLocalSentTotal: IPPktsLocalSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktBytesLocalReceivedTotal: IPPktBytesLocalReceivedTotalMeta.
			NewCounterVec(),
		IPPktsLocalReceivedTotal: IPPktsLocalReceivedTotalMeta.
			NewCounterVec(),
		FrameBytesSentTotal: FrameBytesSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		FramesSentTotal: FramesSentTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		FrameBytesReceivedTotal: FrameBytesReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		FramesReceivedTotal: FramesReceivedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		FramesDiscardedTotal: FramesDiscardedTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		IPPktsDiscardedTotal: IPPktsDiscardedTotalMeta.
			NewCounterVec(),
		SendExternalErrorsTotal: SendExternalErrorsTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		SendLocalErrorsTotal: SendLocalErrorsTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		ReceiveExternalErrorsTotal: ReceiveExternalErrorsTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		ReceiveLocalErrorsTotal: ReceiveLocalErrorsTotalMeta.
			NewCounterVec().MustCurryWith(labels),
		PathsMonitored: PathsMonitoredMeta.
			NewGaugeVec().MustCurryWith(labels),
		PathProbesSent: PathProbesSentMeta.
			NewCounterVec().MustCurryWith(labels),
		PathProbesReceived: PathProbesReceivedMeta.
			NewCounterVec().MustCurryWith(labels),
		PathProbesSendErrors: PathProbesSendErrorsMeta.
			NewCounterVec().MustCurryWith(labels),
		SessionIsHealthy: SessionIsHealthyMeta.
			NewGaugeVec().MustCurryWith(labels),
		SessionProbes: SessionProbesMeta.
			NewCounterVec().MustCurryWith(labels),
		SessionProbeReplies: SessionProbeRepliesMeta.
			NewCounterVec().MustCurryWith(labels),
		SessionPathsAvailable: SessionPathsAvailableMeta.
			NewGaugeVec().MustCurryWith(labels),
		Remotes: RemotesMeta.
			NewGaugeVec().MustCurryWith(labels),
		RemoteDiscoveryErrors: RemoteDiscoveryErrorsMeta.
			NewCounterVec().MustCurryWith(labels),
		PrefixFetchErrors: PrefixFetchErrorsMeta.
			NewCounterVec().MustCurryWith(labels),
		PrefixesAdvertised: PrefixesAdvertisedMeta.
			NewGaugeVec().MustCurryWith(labels),
		PrefixesAccepted: PrefixesAcceptedMeta.
			NewGaugeVec().MustCurryWith(labels),
		PrefixesRejected: PrefixesRejectedMeta.
			NewGaugeVec().MustCurryWith(labels),
		SCIONNetworkMetrics:    snetmetrics.NewSCIONNetworkMetrics(),
		SCMPErrors:             scionPacketConnMetrics.SCMPErrors,
		SCIONPacketConnMetrics: scionPacketConnMetrics,
	}
}
<|endoftext|>


<commit_before>package vtctl

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestGenerateShardRanges(t *testing.T) {
	type args struct {
		shards int
	}

	tests := []struct {
		name    string
		args    args
		want    []string
		wantErr bool
	}{
		{
			"errors for shards less than 0",
			args{0},
			nil,
			true,
		},
		{
			"errors for shards more than 65536",
			args{65537},
			nil,
			true,
		},
		{
			"works for a single shard",
			args{1},
			[]string{"-"},
			false,
		},
		{
			"works for more than one shard",
			args{2},
			[]string{"-80", "80-"},
			false,
		},
		{
			"works for an odd number of shards",
			args{7},
			[]string{"-24", "24-49", "49-6d", "6d-92", "92-b6", "b6-db", "db-"},
			false,
		},
		{
			"works for large number of shards",
			args{256},
			[]string{"-01", "01-02", "02-03", "03-04", "04-05", "05-06", "06-07", "07-08", "08-09", "09-0a", "0a-0b", "0b-0c", "0c-0d", "0d-0e", "0e-0f", "0f-10", "10-11", "11-12", "12-13", "13-14", "14-15", "15-16", "16-17", "17-18", "18-19", "19-1a", "1a-1b", "1b-1c", "1c-1d", "1d-1e", "1e-1f", "1f-20", "20-21", "21-22", "22-23", "23-24", "24-25", "25-26", "26-27", "27-28", "28-29", "29-2a", "2a-2b", "2b-2c", "2c-2d", "2d-2e", "2e-2f", "2f-30", "30-31", "31-32", "32-33", "33-34", "34-35", "35-36", "36-37", "37-38", "38-39", "39-3a", "3a-3b", "3b-3c", "3c-3d", "3d-3e", "3e-3f", "3f-40", "40-41", "41-42", "42-43", "43-44", "44-45", "45-46", "46-47", "47-48", "48-49", "49-4a", "4a-4b", "4b-4c", "4c-4d", "4d-4e", "4e-4f", "4f-50", "50-51", "51-52", "52-53", "53-54", "54-55", "55-56", "56-57", "57-58", "58-59", "59-5a", "5a-5b", "5b-5c", "5c-5d", "5d-5e", "5e-5f", "5f-60", "60-61", "61-62", "62-63", "63-64", "64-65", "65-66", "66-67", "67-68", "68-69", "69-6a", "6a-6b", "6b-6c", "6c-6d", "6d-6e", "6e-6f", "6f-70", "70-71", "71-72", "72-73", "73-74", "74-75", "75-76", "76-77", "77-78", "78-79", "79-7a", "7a-7b", "7b-7c", "7c-7d", "7d-7e", "7e-7f", "7f-80", "80-81", "81-82", "82-83", "83-84", "84-85", "85-86", "86-87", "87-88", "88-89", "89-8a", "8a-8b", "8b-8c", "8c-8d", "8d-8e", "8e-8f", "8f-90", "90-91", "91-92", "92-93", "93-94", "94-95", "95-96", "96-97", "97-98", "98-99", "99-9a", "9a-9b", "9b-9c", "9c-9d", "9d-9e", "9e-9f", "9f-a0", "a0-a1", "a1-a2", "a2-a3", "a3-a4", "a4-a5", "a5-a6", "a6-a7", "a7-a8", "a8-a9", "a9-aa", "aa-ab", "ab-ac", "ac-ad", "ad-ae", "ae-af", "af-b0", "b0-b1", "b1-b2", "b2-b3", "b3-b4", "b4-b5", "b5-b6", "b6-b7", "b7-b8", "b8-b9", "b9-ba", "ba-bb", "bb-bc", "bc-bd", "bd-be", "be-bf", "bf-c0", "c0-c1", "c1-c2", "c2-c3", "c3-c4", "c4-c5", "c5-c6", "c6-c7", "c7-c8", "c8-c9", "c9-ca", "ca-cb", "cb-cc", "cc-cd", "cd-ce", "ce-cf", "cf-d0", "d0-d1", "d1-d2", "d2-d3", "d3-d4", "d4-d5", "d5-d6", "d6-d7", "d7-d8", "d8-d9", "d9-da", "da-db", "db-dc", "dc-dd", "dd-de", "de-df", "df-e0", "e0-e1", "e1-e2", "e2-e3", "e3-e4", "e4-e5", "e5-e6", "e6-e7", "e7-e8", "e8-e9", "e9-ea", "ea-eb", "eb-ec", "ec-ed", "ed-ee", "ee-ef", "ef-f0", "f0-f1", "f1-f2", "f2-f3", "f3-f4", "f4-f5", "f5-f6", "f6-f7", "f7-f8", "f8-f9", "f9-fa", "fa-fb", "fb-fc", "fc-fd", "fd-fe", "fe-ff", "ff-"},
			false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := generateShardRanges(tt.args.shards)
			if tt.wantErr {
				require.Error(t, err)
			} else {
				require.NoError(t, err)
			}

			assert.Equal(t, got, tt.want)
		})
	}
}

func TestShardCalculatorForShardsGreaterThan512(t *testing.T) {
	got, err := generateShardRanges(512)
	if err != nil {
		t.Errorf("listShardRanges() error = %v", err)
	}

	want := "ff80-"

	if got[511] != want {
		t.Errorf("Invalid mapping for a 512 shard keyspace. Expected %v, want %v", got[511], want)
	}
}
<commit_msg>Use require/assert in the rest of the tests<commit_after>package vtctl

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestGenerateShardRanges(t *testing.T) {
	type args struct {
		shards int
	}

	tests := []struct {
		name    string
		args    args
		want    []string
		wantErr bool
	}{
		{
			"errors for shards less than 0",
			args{0},
			nil,
			true,
		},
		{
			"errors for shards more than 65536",
			args{65537},
			nil,
			true,
		},
		{
			"works for a single shard",
			args{1},
			[]string{"-"},
			false,
		},
		{
			"works for more than one shard",
			args{2},
			[]string{"-80", "80-"},
			false,
		},
		{
			"works for an odd number of shards",
			args{7},
			[]string{"-24", "24-49", "49-6d", "6d-92", "92-b6", "b6-db", "db-"},
			false,
		},
		{
			"works for large number of shards",
			args{256},
			[]string{"-01", "01-02", "02-03", "03-04", "04-05", "05-06", "06-07", "07-08", "08-09", "09-0a", "0a-0b", "0b-0c", "0c-0d", "0d-0e", "0e-0f", "0f-10", "10-11", "11-12", "12-13", "13-14", "14-15", "15-16", "16-17", "17-18", "18-19", "19-1a", "1a-1b", "1b-1c", "1c-1d", "1d-1e", "1e-1f", "1f-20", "20-21", "21-22", "22-23", "23-24", "24-25", "25-26", "26-27", "27-28", "28-29", "29-2a", "2a-2b", "2b-2c", "2c-2d", "2d-2e", "2e-2f", "2f-30", "30-31", "31-32", "32-33", "33-34", "34-35", "35-36", "36-37", "37-38", "38-39", "39-3a", "3a-3b", "3b-3c", "3c-3d", "3d-3e", "3e-3f", "3f-40", "40-41", "41-42", "42-43", "43-44", "44-45", "45-46", "46-47", "47-48", "48-49", "49-4a", "4a-4b", "4b-4c", "4c-4d", "4d-4e", "4e-4f", "4f-50", "50-51", "51-52", "52-53", "53-54", "54-55", "55-56", "56-57", "57-58", "58-59", "59-5a", "5a-5b", "5b-5c", "5c-5d", "5d-5e", "5e-5f", "5f-60", "60-61", "61-62", "62-63", "63-64", "64-65", "65-66", "66-67", "67-68", "68-69", "69-6a", "6a-6b", "6b-6c", "6c-6d", "6d-6e", "6e-6f", "6f-70", "70-71", "71-72", "72-73", "73-74", "74-75", "75-76", "76-77", "77-78", "78-79", "79-7a", "7a-7b", "7b-7c", "7c-7d", "7d-7e", "7e-7f", "7f-80", "80-81", "81-82", "82-83", "83-84", "84-85", "85-86", "86-87", "87-88", "88-89", "89-8a", "8a-8b", "8b-8c", "8c-8d", "8d-8e", "8e-8f", "8f-90", "90-91", "91-92", "92-93", "93-94", "94-95", "95-96", "96-97", "97-98", "98-99", "99-9a", "9a-9b", "9b-9c", "9c-9d", "9d-9e", "9e-9f", "9f-a0", "a0-a1", "a1-a2", "a2-a3", "a3-a4", "a4-a5", "a5-a6", "a6-a7", "a7-a8", "a8-a9", "a9-aa", "aa-ab", "ab-ac", "ac-ad", "ad-ae", "ae-af", "af-b0", "b0-b1", "b1-b2", "b2-b3", "b3-b4", "b4-b5", "b5-b6", "b6-b7", "b7-b8", "b8-b9", "b9-ba", "ba-bb", "bb-bc", "bc-bd", "bd-be", "be-bf", "bf-c0", "c0-c1", "c1-c2", "c2-c3", "c3-c4", "c4-c5", "c5-c6", "c6-c7", "c7-c8", "c8-c9", "c9-ca", "ca-cb", "cb-cc", "cc-cd", "cd-ce", "ce-cf", "cf-d0", "d0-d1", "d1-d2", "d2-d3", "d3-d4", "d4-d5", "d5-d6", "d6-d7", "d7-d8", "d8-d9", "d9-da", "da-db", "db-dc", "dc-dd", "dd-de", "de-df", "df-e0", "e0-e1", "e1-e2", "e2-e3", "e3-e4", "e4-e5", "e5-e6", "e6-e7", "e7-e8", "e8-e9", "e9-ea", "ea-eb", "eb-ec", "ec-ed", "ed-ee", "ee-ef", "ef-f0", "f0-f1", "f1-f2", "f2-f3", "f3-f4", "f4-f5", "f5-f6", "f6-f7", "f7-f8", "f8-f9", "f9-fa", "fa-fb", "fb-fc", "fc-fd", "fd-fe", "fe-ff", "ff-"},
			false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := generateShardRanges(tt.args.shards)
			if tt.wantErr {
				require.Error(t, err)
			} else {
				require.NoError(t, err)
			}

			assert.Equal(t, got, tt.want)
		})
	}
}

func TestShardCalculatorForShardsGreaterThan512(t *testing.T) {
	got, err := generateShardRanges(512)
	require.NoError(t, err)

	want := "ff80-"

	assert.Equal(t, want, got[511], "Invalid mapping for a 512-shard keyspace. Expected %v, got %v", want, got[511])
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"regexp"
)

var (
	mainlogPattern = createPattern(`^(TASK\:|PLAY|FATAL\:|ok\:|changed\:|failed\:)`)
	playPattern    = createPattern(`^PLAY\s*\[*([a-zA-Z0-9]*)\]*`)
	taskPattern    = createPattern(`^TASK\:\s*\[([^\]]*)|([^\]]*)\]`)
	fatalPattern   = createPattern(`^FATAL:\s*(.*)`)
	okPattern      = createPattern(`^ok:\s*\[([^\]]*)|([^\]]*)\]`)
	changedPattern = createPattern(`^changed:\s*\[([^\]]*)|([^\]]*)\]`)
	failedPattern  = createPattern(`^failed:\s*\[([^\]]*)|([^\]]*)\]`)
)

func createPattern(pattern string) *regexp.Regexp {
	regex, err := regexp.Compile(pattern)
	if err != nil {
		panic("There was a problem with the regular expression.")
	}
	return regex
}

func lineToDetails(line, line_type string) {
	switch line_type {
	case "PLAY":
		playbook := playPattern.FindStringSubmatch(line)
		fmt.Printf("PLAYBOOK: %q\n", playbook[1])
	case "TASK:":
		task := taskPattern.FindStringSubmatch(line)
		fmt.Printf("TASK: %q\n", task[1])
	case "FATAL:":
		fatal := fatalPattern.FindStringSubmatch(line)
		fmt.Printf("FATAL: %q\n", fatal)
	case "ok:":
		ok := okPattern.FindStringSubmatch(line)
		fmt.Printf("ok: %q\n", ok)
	case "changed:":
		changed := changedPattern.FindStringSubmatch(line)
		fmt.Printf("changed: %q\n", changed)
	case "failed:":
		failed := failedPattern.FindStringSubmatch(line)
		fmt.Printf("failed: %q\n", failed)
	}

}

func grep(regex *regexp.Regexp, filename string) {
	fh, err := os.Open(filename)
	f := bufio.NewReader(fh)

	if err != nil {
		fmt.Println("ERROR: There was a problem opening the file.")
		return
	}
	defer fh.Close()

	buf := make([]byte, 1024)
	for {
		buf, _, err = f.ReadLine()
		if err != nil {
			return
		}

		line := string(buf)
		match_line := regex.FindStringSubmatch((line))
		if len(match_line) > 0 {
			lineToDetails(line, match_line[1])
		}
	}
}

func main() {
	flag.Parse()
	if flag.NArg() == 1 {
		logfile := flag.Arg(0)
		grep(mainlogPattern, logfile)
	} else {
		fmt.Printf("Wrong number of arguments.\n")
	}
}
<commit_msg>[goansible] analyzer updated to have tokenized status for type,node,detail-dict<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"regexp"
)

var (
	mainlogPattern      = createPattern(`^(PLAY|TASK\:|FATAL\:|ok\:|changed\:|failed\:)`)
	playPattern         = createPattern(`^PLAY\s*\[*([a-zA-Z0-9]*)\]*`)
	taskPattern         = createPattern(`^TASK\:\s*\[\s*([^|\]]*)\s*|\s*([^|\]]*)\s*\]`)
	fatalPattern        = createPattern(`^FATAL:\s*(.*)`)
	statusPattern       = createPattern(`^(ok|changed|failed):\s*\[([^\]]*)\](.*)`)
	statusDetailPattern = createPattern(`\s*=>\s*(.*)\s*`)
)

func createPattern(pattern string) *regexp.Regexp {
	regex, err := regexp.Compile(pattern)
	if err != nil {
		panic("There was a problem with the regular expression.")
	}
	return regex
}

func lineToDetails(line, line_type string) {
	switch line_type {
	case "PLAY":
		playbook := playPattern.FindStringSubmatch(line)
		fmt.Printf("PLAYBOOK: %q\n", playbook[1])
	case "TASK:":
		task := taskPattern.FindStringSubmatch(line)
		fmt.Printf("TASK: %q\n", task[1])
	case "FATAL:":
		fatal := fatalPattern.FindStringSubmatch(line)
		fmt.Printf("FATAL: %q\n", fatal[1])
	case "ok:", "changed:", "failed:":
		status := statusPattern.FindStringSubmatch(line)
		var statusDetail string
		if statusDetailPattern.MatchString(status[3]) {
			statusDetail = statusDetailPattern.FindStringSubmatch(status[3])[1]
		}
		fmt.Printf("status: %q\n%q\n%q\n", status[1], status[2], statusDetail)
	}
}

func updateStatus(status []string) {
	switch status[1] {
	case "ok:":
		fmt.Printf("ok:\n")
	case "changed:":
		fmt.Printf("changed:\n")
	case "failed:":
		fmt.Printf("failed:\n")
	}

}

func grep(regex *regexp.Regexp, filename string) {
	fh, err := os.Open(filename)
	f := bufio.NewReader(fh)

	if err != nil {
		fmt.Println("ERROR: There was a problem opening the file.")
		return
	}
	defer fh.Close()

	buf := make([]byte, 1024)
	for {
		buf, _, err = f.ReadLine()
		if err != nil {
			return
		}

		line := string(buf)
		match_line := regex.FindStringSubmatch((line))
		if len(match_line) > 0 {
			lineToDetails(line, match_line[1])
		}
	}
}

func main() {
	flag.Parse()
	if flag.NArg() == 1 {
		logfile := flag.Arg(0)
		grep(mainlogPattern, logfile)
	} else {
		fmt.Printf("Wrong number of arguments.\n")
	}
}
<|endoftext|>


<commit_before>package lists

const listHelp = `The list plugin allows you to manage simple lists of items, such as a todo
list, lunch spots, etc. Lists default to per-channel scope, but can be
configured with global scope. Note that 'lists' is a context aware plugin, and
will remember the list or item being discussed; so e.g. you can follow 'add milk
to the grocery list' with 'add hamburgers to the list' and the robot will
know you mean the grocery list; also, 'add it to the dinner list' would add
hamburgers to the dinner list. List names are always lower cased by the robot.`

const defaultConfig = `
# For keeping simple shared lists of things
Help:
- Keywords: [ "list", "lists" ]
  Helptext: [ "(bot), help with lists - give general help for using lists"]
- Keywords: [ "list", "lists", "add" ]
  Helptext: [ "(bot), add <item> to the <type> list - add something to a list" ]
- Keywords: [ "list", "lists", "remove" ]
  Helptext: [ "(bot), remove <item> from the <type> list - remove something from a list" ]
- Keywords: [ "list", "lists", "empty" ]
  Helptext: [ "(bot), empty the <type> list - remove all items from a list" ]
- Keywords: [ "list", "lists", "delete" ]
  Helptext: [ "(bot), delete the <type> list - remove the list altogether" ]
- Keywords: [ "list", "lists" ]
  Helptext: [ "(bot), list lists - give a list of all the lists the robot knows about" ]
- Keywords: [ "list", "lists", "email", "send" ]
  Helptext: [ "(bot), send me the <type> list - send a copy of the list by email" ]
- Keywords: [ "list", "lists", "show", "view" ]
  Helptext: [ "(bot), show the <type> list - show the contents of a list" ]
- Keywords: [ "pick", "random", "lists", "list" ]
  Helptext: [ "(bot), pick a random item from the <type> list"]
CommandMatchers:
- Command: 'help'
  Regex: '(?i:help with lists?)'
- Command: 'add'
  Regex: '(?i:add ([-\w .,!?:\/]+) to (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "item", "list" ]
- Command: 'list'
  Regex: '(?i:list lists)'
- Command: 'remove'
  Regex: '(?i:(?:remove|delete) ([-\w .,!?:\/]+) from (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "item", "list" ]
- Command: 'empty'
  Regex: '(?i:(?:empty|clear) (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "list" ]
- Command: 'delete'
  Regex: '(?i:delete (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "list" ]
- Command: 'show'
  Regex: '(?i:show (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "list" ]
- Command: 'pick'
  Regex: '(?i:(?:pick )(?:an? )?random (?:item )?(?:from )(?:the )?([~\w-'' ]+)?(?: list))'
  Contexts: [ "list" ]
- Command: 'send'
  Regex: '(?i:(?:send me|email) (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "list" ]
Config:
  Scope: channel # or "global"
`
<commit_msg>Command synonyms for lists<commit_after>package lists

const listHelp = `The list plugin allows you to manage simple lists of items, such as a todo
list, lunch spots, etc. Lists default to per-channel scope, but can be
configured with global scope. Note that 'lists' is a context aware plugin, and
will remember the list or item being discussed; so e.g. you can follow 'add milk
to the grocery list' with 'add hamburgers to the list' and the robot will
know you mean the grocery list; also, 'add it to the dinner list' would add
hamburgers to the dinner list. List names are always lower cased by the robot.`

const defaultConfig = `
# For keeping simple shared lists of things
Help:
- Keywords: [ "list", "lists" ]
  Helptext: [ "(bot), help with lists - give general help for using lists"]
- Keywords: [ "list", "lists", "add" ]
  Helptext: [ "(bot), add <item> to the <type> list - add something to a list" ]
- Keywords: [ "list", "lists", "remove" ]
  Helptext: [ "(bot), remove <item> from the <type> list - remove something from a list" ]
- Keywords: [ "list", "lists", "empty" ]
  Helptext: [ "(bot), empty the <type> list - remove all items from a list" ]
- Keywords: [ "list", "lists", "delete" ]
  Helptext: [ "(bot), delete the <type> list - remove the list altogether" ]
- Keywords: [ "list", "lists" ]
  Helptext: [ "(bot), list lists - give a list of all the lists the robot knows about" ]
- Keywords: [ "list", "lists", "email", "send" ]
  Helptext: [ "(bot), send me the <type> list - send a copy of the list by email" ]
- Keywords: [ "list", "lists", "show", "view" ]
  Helptext:
  - "(bot), show the <type> list - show the contents of a list"
  - "(bot), (show) list <type> - show the contents of a list"
- Keywords: [ "pick", "random", "lists", "list" ]
  Helptext: [ "(bot), pick a random item from the <type> list"]
CommandMatchers:
- Command: 'help'
  Regex: '(?i:help with lists?)'
- Command: 'add'
  Regex: '(?i:add ([-\w .,!?:\/]+) to (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "item", "list" ]
- Command: 'list'
  Regex: '(?i:list lists)'
- Command: 'remove'
  Regex: '(?i:(?:remove|delete) ([-\w .,!?:\/]+) from (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "item", "list" ]
- Command: 'empty'
  Regex: '(?i:(?:empty|clear) (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "list" ]
- Command: 'delete'
  Regex: '(?i:delete (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "list" ]
- Command: 'show'
  Regex: '(?i:show (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "list" ]
- Command: 'show'
  Regex: '(?i:(?:show )?list ([~\w-'' ]+))'
  Contexts: [ "list" ]
- Command: 'pick'
  Regex: '(?i:(?:pick )(?:an? )?random (?:item )?(?:from )(?:the )?([~\w-'' ]+)?(?: list))'
  Contexts: [ "list" ]
- Command: 'send'
  Regex: '(?i:(?:send me|email) (?:the )?(?:([~\w-'' ]+) )?list)'
  Contexts: [ "list" ]
Config:
  Scope: channel # or "global"
`
<|endoftext|>


<commit_before>package terraform

import (
	"github.com/hashicorp/terraform/dag"
	"github.com/hashicorp/terraform/tfdiags"
	"github.com/zclconf/go-cty/cty"
)

// NodeRefreshableDataResource represents a resource that is "refreshable".
type NodeRefreshableDataResource struct {
	*NodeAbstractResource
}

var (
	_ GraphNodeSubPath              = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeDynamicExpandable    = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeReferenceable        = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeReferencer           = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeResource             = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeAttachResourceConfig = (*NodeRefreshableDataResource)(nil)
)

// GraphNodeDynamicExpandable
func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
	var diags tfdiags.Diagnostics

	count, countDiags := evaluateResourceCountExpression(n.Config.Count, ctx)
	diags = diags.Append(countDiags)
	if countDiags.HasErrors() {
		return nil, diags.Err()
	}

	// Next we need to potentially rename an instance address in the state
	// if we're transitioning whether "count" is set at all.
	fixResourceCountSetTransition(ctx, n.ResourceAddr().Resource, count != -1)

	// Grab the state which we read
	state, lock := ctx.State()
	lock.RLock()
	defer lock.RUnlock()

	// The concrete resource factory we'll use
	concreteResource := func(a *NodeAbstractResourceInstance) dag.Vertex {
		// Add the config and state since we don't do that via transforms
		a.Config = n.Config
		a.ResolvedProvider = n.ResolvedProvider

		return &NodeRefreshableDataResourceInstance{
			NodeAbstractResourceInstance: a,
		}
	}

	// We also need a destroyable resource for orphans that are a result of a
	// scaled-in count.
	concreteResourceDestroyable := func(a *NodeAbstractResourceInstance) dag.Vertex {
		// Add the config since we don't do that via transforms
		a.Config = n.Config

		return &NodeDestroyableDataResource{
			NodeAbstractResourceInstance: a,
		}
	}

	// Start creating the steps
	steps := []GraphTransformer{
		// Expand the count.
		&ResourceCountTransformer{
			Concrete: concreteResource,
			Schema:   n.Schema,
			Count:    count,
			Addr:     n.ResourceAddr(),
		},

		// Add the count orphans. As these are orphaned refresh nodes, we add them
		// directly as NodeDestroyableDataResource.
		&OrphanResourceCountTransformer{
			Concrete: concreteResourceDestroyable,
			Count:    count,
			Addr:     n.ResourceAddr(),
			State:    state,
		},

		// Attach the state
		&AttachStateTransformer{State: state},

		// Targeting
		&TargetsTransformer{Targets: n.Targets},

		// Connect references so ordering is correct
		&ReferenceTransformer{},

		// Make sure there is a single root
		&RootTransformer{},
	}

	// Build the graph
	b := &BasicGraphBuilder{
		Steps:    steps,
		Validate: true,
		Name:     "NodeRefreshableDataResource",
	}

	graph, diags := b.Build(ctx.Path())
	return graph, diags.ErrWithWarnings()
}

// NodeRefreshableDataResourceInstance represents a single resource instance
// that is refreshable.
type NodeRefreshableDataResourceInstance struct {
	*NodeAbstractResourceInstance
}

// GraphNodeEvalable
func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
	addr := n.ResourceInstanceAddr()

	// State still uses legacy-style internal ids, so we need to shim to get
	// a suitable key to use.
	stateId := NewLegacyResourceInstanceAddress(addr).stateId()

	// Get the state if we have it. If not, we'll build it.
	rs := n.ResourceState
	if rs == nil {
		rs = &ResourceState{
			Type:     addr.Resource.Resource.Type,
			Provider: n.ResolvedProvider.String(),
		}
	}

	// If we have a configuration then we'll build a fresh state.
	if n.Config != nil {
		rs = &ResourceState{
			Type:         addr.Resource.Resource.Type,
			Provider:     n.ResolvedProvider.String(),
			Dependencies: n.StateReferences(),
		}
	}

	// These variables are the state for the eval sequence below, and are
	// updated through pointers.
	var provider ResourceProvider
	var providerSchema *ProviderSchema
	var diff *InstanceDiff
	var state *InstanceState
	var configVal cty.Value

	return &EvalSequence{
		Nodes: []EvalNode{
			// Always destroy the existing state first, since we must
			// make sure that values from a previous read will not
			// get interpolated if we end up needing to defer our
			// loading until apply time.
			&EvalWriteState{
				Name:         stateId,
				ResourceType: rs.Type,
				Provider:     n.ResolvedProvider,
				Dependencies: rs.Dependencies,
				State:        &state, // state is nil here
			},

			&EvalGetProvider{
				Addr:   n.ResolvedProvider,
				Output: &provider,
			},

			&EvalReadDataDiff{
				Addr:           addr.Resource,
				Config:         n.Config,
				Provider:       &provider,
				ProviderSchema: &providerSchema,
				Output:         &diff,
				OutputValue:    &configVal,
				OutputState:    &state,
			},

			// The rest of this pass can proceed only if there are no
			// computed values in our config.
			// (If there are, we'll deal with this during the plan and
			// apply phases.)
			&EvalIf{
				If: func(ctx EvalContext) (bool, error) {
					if !configVal.IsWhollyKnown() {
						return true, EvalEarlyExitError{}
					}

					// If the config explicitly has a depends_on for this
					// data source, assume the intention is to prevent
					// refreshing ahead of that dependency.
					if len(n.Config.DependsOn) > 0 {
						return true, EvalEarlyExitError{}
					}

					return true, nil
				},
				Then: EvalNoop{},
			},

			&EvalReadDataApply{
				Addr:     addr.Resource,
				Diff:     &diff,
				Provider: &provider,
				Output:   &state,
			},

			&EvalWriteState{
				Name:         stateId,
				ResourceType: rs.Type,
				Provider:     n.ResolvedProvider,
				Dependencies: rs.Dependencies,
				State:        &state,
			},

			&EvalUpdateStateHook{},
		},
	}
}
<commit_msg>core: Actually read provider schema for data resources<commit_after>package terraform

import (
	"github.com/hashicorp/terraform/dag"
	"github.com/hashicorp/terraform/tfdiags"
	"github.com/zclconf/go-cty/cty"
)

// NodeRefreshableDataResource represents a resource that is "refreshable".
type NodeRefreshableDataResource struct {
	*NodeAbstractResource
}

var (
	_ GraphNodeSubPath              = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeDynamicExpandable    = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeReferenceable        = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeReferencer           = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeResource             = (*NodeRefreshableDataResource)(nil)
	_ GraphNodeAttachResourceConfig = (*NodeRefreshableDataResource)(nil)
)

// GraphNodeDynamicExpandable
func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
	var diags tfdiags.Diagnostics

	count, countDiags := evaluateResourceCountExpression(n.Config.Count, ctx)
	diags = diags.Append(countDiags)
	if countDiags.HasErrors() {
		return nil, diags.Err()
	}

	// Next we need to potentially rename an instance address in the state
	// if we're transitioning whether "count" is set at all.
	fixResourceCountSetTransition(ctx, n.ResourceAddr().Resource, count != -1)

	// Grab the state which we read
	state, lock := ctx.State()
	lock.RLock()
	defer lock.RUnlock()

	// The concrete resource factory we'll use
	concreteResource := func(a *NodeAbstractResourceInstance) dag.Vertex {
		// Add the config and state since we don't do that via transforms
		a.Config = n.Config
		a.ResolvedProvider = n.ResolvedProvider

		return &NodeRefreshableDataResourceInstance{
			NodeAbstractResourceInstance: a,
		}
	}

	// We also need a destroyable resource for orphans that are a result of a
	// scaled-in count.
	concreteResourceDestroyable := func(a *NodeAbstractResourceInstance) dag.Vertex {
		// Add the config since we don't do that via transforms
		a.Config = n.Config

		return &NodeDestroyableDataResource{
			NodeAbstractResourceInstance: a,
		}
	}

	// Start creating the steps
	steps := []GraphTransformer{
		// Expand the count.
		&ResourceCountTransformer{
			Concrete: concreteResource,
			Schema:   n.Schema,
			Count:    count,
			Addr:     n.ResourceAddr(),
		},

		// Add the count orphans. As these are orphaned refresh nodes, we add them
		// directly as NodeDestroyableDataResource.
		&OrphanResourceCountTransformer{
			Concrete: concreteResourceDestroyable,
			Count:    count,
			Addr:     n.ResourceAddr(),
			State:    state,
		},

		// Attach the state
		&AttachStateTransformer{State: state},

		// Targeting
		&TargetsTransformer{Targets: n.Targets},

		// Connect references so ordering is correct
		&ReferenceTransformer{},

		// Make sure there is a single root
		&RootTransformer{},
	}

	// Build the graph
	b := &BasicGraphBuilder{
		Steps:    steps,
		Validate: true,
		Name:     "NodeRefreshableDataResource",
	}

	graph, diags := b.Build(ctx.Path())
	return graph, diags.ErrWithWarnings()
}

// NodeRefreshableDataResourceInstance represents a single resource instance
// that is refreshable.
type NodeRefreshableDataResourceInstance struct {
	*NodeAbstractResourceInstance
}

// GraphNodeEvalable
func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
	addr := n.ResourceInstanceAddr()

	// State still uses legacy-style internal ids, so we need to shim to get
	// a suitable key to use.
	stateId := NewLegacyResourceInstanceAddress(addr).stateId()

	// Get the state if we have it. If not, we'll build it.
	rs := n.ResourceState
	if rs == nil {
		rs = &ResourceState{
			Type:     addr.Resource.Resource.Type,
			Provider: n.ResolvedProvider.String(),
		}
	}

	// If we have a configuration then we'll build a fresh state.
	if n.Config != nil {
		rs = &ResourceState{
			Type:         addr.Resource.Resource.Type,
			Provider:     n.ResolvedProvider.String(),
			Dependencies: n.StateReferences(),
		}
	}

	// These variables are the state for the eval sequence below, and are
	// updated through pointers.
	var provider ResourceProvider
	var providerSchema *ProviderSchema
	var diff *InstanceDiff
	var state *InstanceState
	var configVal cty.Value

	return &EvalSequence{
		Nodes: []EvalNode{
			// Always destroy the existing state first, since we must
			// make sure that values from a previous read will not
			// get interpolated if we end up needing to defer our
			// loading until apply time.
			&EvalWriteState{
				Name:         stateId,
				ResourceType: rs.Type,
				Provider:     n.ResolvedProvider,
				Dependencies: rs.Dependencies,
				State:        &state, // state is nil here
			},

			&EvalGetProvider{
				Addr:   n.ResolvedProvider,
				Output: &provider,
				Schema: &providerSchema,
			},

			&EvalReadDataDiff{
				Addr:           addr.Resource,
				Config:         n.Config,
				Provider:       &provider,
				ProviderSchema: &providerSchema,
				Output:         &diff,
				OutputValue:    &configVal,
				OutputState:    &state,
			},

			// The rest of this pass can proceed only if there are no
			// computed values in our config.
			// (If there are, we'll deal with this during the plan and
			// apply phases.)
			&EvalIf{
				If: func(ctx EvalContext) (bool, error) {
					if !configVal.IsWhollyKnown() {
						return true, EvalEarlyExitError{}
					}

					// If the config explicitly has a depends_on for this
					// data source, assume the intention is to prevent
					// refreshing ahead of that dependency.
					if len(n.Config.DependsOn) > 0 {
						return true, EvalEarlyExitError{}
					}

					return true, nil
				},
				Then: EvalNoop{},
			},

			&EvalReadDataApply{
				Addr:     addr.Resource,
				Diff:     &diff,
				Provider: &provider,
				Output:   &state,
			},

			&EvalWriteState{
				Name:         stateId,
				ResourceType: rs.Type,
				Provider:     n.ResolvedProvider,
				Dependencies: rs.Dependencies,
				State:        &state,
			},

			&EvalUpdateStateHook{},
		},
	}
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"sync"

	"github.com/hashicorp/terraform/helper/shadow"
)

// newShadowComponentFactory creates a shadowed contextComponentFactory
// so that requests to create new components result in both a real and
// shadow side.
func newShadowComponentFactory(
	f contextComponentFactory) (contextComponentFactory, *shadowComponentFactory) {
	// Create the shared data
	shared := &shadowComponentFactoryShared{contextComponentFactory: f}

	// Create the real side
	real := &shadowComponentFactoryReal{
		shadowComponentFactoryShared: shared,
	}

	// Create the shadow
	shadow := &shadowComponentFactory{
		shadowComponentFactoryShared: shared,
	}

	return real, shadow
}

// shadowComponentFactory is the shadow side. Any components created
// with this factory are fake and will not cause real work to happen.
type shadowComponentFactory struct {
	*shadowComponentFactoryShared
}

func (f *shadowComponentFactory) ResourceProvider(
	n, uid string) (ResourceProvider, error) {
	_, shadow, err := f.shadowComponentFactoryShared.ResourceProvider(n, uid)
	return shadow, err
}

func (f *shadowComponentFactory) ResourceProvisioner(
	n, uid string) (ResourceProvisioner, error) {
	_, shadow, err := f.shadowComponentFactoryShared.ResourceProvisioner(n, uid)
	return shadow, err
}

// shadowComponentFactoryReal is the real side of the component factory.
// Operations here result in real components that do real work.
type shadowComponentFactoryReal struct {
	*shadowComponentFactoryShared
}

func (f *shadowComponentFactoryReal) ResourceProvider(
	n, uid string) (ResourceProvider, error) {
	real, _, err := f.shadowComponentFactoryShared.ResourceProvider(n, uid)
	return real, err
}

func (f *shadowComponentFactoryReal) ResourceProvisioner(
	n, uid string) (ResourceProvisioner, error) {
	real, _, err := f.shadowComponentFactoryShared.ResourceProvisioner(n, uid)
	return real, err
}

// shadowComponentFactoryShared is shared data between the two factories.
type shadowComponentFactoryShared struct {
	contextComponentFactory

	providers    shadow.KeyedValue
	provisioners shadow.KeyedValue
	lock         sync.Mutex
}

// shadowResourceProviderFactoryEntry is the entry that is stored in
// the Shadows key/value for a provider.
type shadowComponentFactoryProviderEntry struct {
	Real   ResourceProvider
	Shadow shadowResourceProvider
	Err    error
}

type shadowComponentFactoryProvisionerEntry struct {
	Real   ResourceProvisioner
	Shadow ResourceProvisioner
	Err    error
}

func (f *shadowComponentFactoryShared) ResourceProvider(
	n, uid string) (ResourceProvider, shadowResourceProvider, error) {
	f.lock.Lock()
	defer f.lock.Unlock()

	// Determine if we already have a value
	raw, ok := f.providers.ValueOk(uid)
	if !ok {
		// Build the entry
		var entry shadowComponentFactoryProviderEntry

		// No value, initialize. Create the original
		p, err := f.contextComponentFactory.ResourceProvider(n, uid)
		if err != nil {
			entry.Err = err
			p = nil // Just to be sure
		}

		if p != nil {
			// Create the shadow
			real, shadow := newShadowResourceProvider(p)
			entry.Real = real
			entry.Shadow = shadow
		}

		// Store the value
		f.providers.SetValue(uid, &entry)
		raw = &entry
	}

	// Read the entry
	entry, ok := raw.(*shadowComponentFactoryProviderEntry)
	if !ok {
		return nil, nil, fmt.Errorf("Unknown value for shadow provider: %#v", raw)
	}

	// Return
	return entry.Real, entry.Shadow, entry.Err
}

func (f *shadowComponentFactoryShared) ResourceProvisioner(
	n, uid string) (ResourceProvisioner, ResourceProvisioner, error) {
	f.lock.Lock()
	defer f.lock.Unlock()

	// Determine if we already have a value
	raw, ok := f.provisioners.ValueOk(uid)
	if !ok {
		// Build the entry
		var entry shadowComponentFactoryProvisionerEntry

		// No value, initialize. Create the original
		p, err := f.contextComponentFactory.ResourceProvisioner(n, uid)
		if err != nil {
			entry.Err = err
			p = nil // Just to be sure
		}

		if p != nil {
			// For now, just create a mock since we don't support provisioners yet
			real := p
			shadow := new(MockResourceProvisioner)
			entry.Real = real
			entry.Shadow = shadow
		}

		// Store the value
		f.provisioners.SetValue(uid, &entry)
		raw = &entry
	}

	// Read the entry
	entry, ok := raw.(*shadowComponentFactoryProvisionerEntry)
	if !ok {
		return nil, nil, fmt.Errorf("Unknown value for shadow provisioner: %#v", raw)
	}

	// Return
	return entry.Real, entry.Shadow, entry.Err
}
<commit_msg>terraform: simplify the shadow component factory<commit_after>package terraform

import (
	"fmt"
	"sync"

	"github.com/hashicorp/terraform/helper/shadow"
)

// newShadowComponentFactory creates a shadowed contextComponentFactory
// so that requests to create new components result in both a real and
// shadow side.
func newShadowComponentFactory(
	f contextComponentFactory) (contextComponentFactory, *shadowComponentFactory) {
	// Create the shared data
	shared := &shadowComponentFactoryShared{contextComponentFactory: f}

	// Create the real side
	real := &shadowComponentFactory{
		shadowComponentFactoryShared: shared,
	}

	// Create the shadow
	shadow := &shadowComponentFactory{
		shadowComponentFactoryShared: shared,
		Shadow: true,
	}

	return real, shadow
}

// shadowComponentFactory is the shadow side. Any components created
// with this factory are fake and will not cause real work to happen.
type shadowComponentFactory struct {
	*shadowComponentFactoryShared

	Shadow bool // True if this should return the shadow
}

func (f *shadowComponentFactory) ResourceProvider(
	n, uid string) (ResourceProvider, error) {
	real, shadow, err := f.shadowComponentFactoryShared.ResourceProvider(n, uid)
	var result ResourceProvider = real
	if f.Shadow {
		result = shadow
	}

	return result, err
}

func (f *shadowComponentFactory) ResourceProvisioner(
	n, uid string) (ResourceProvisioner, error) {
	real, shadow, err := f.shadowComponentFactoryShared.ResourceProvisioner(n, uid)
	var result ResourceProvisioner = real
	if f.Shadow {
		result = shadow
	}

	return result, err
}

// shadowComponentFactoryShared is shared data between the two factories.
type shadowComponentFactoryShared struct {
	contextComponentFactory

	providers    shadow.KeyedValue
	provisioners shadow.KeyedValue
	lock         sync.Mutex
}

// shadowResourceProviderFactoryEntry is the entry that is stored in
// the Shadows key/value for a provider.
type shadowComponentFactoryProviderEntry struct {
	Real   ResourceProvider
	Shadow shadowResourceProvider
	Err    error
}

type shadowComponentFactoryProvisionerEntry struct {
	Real   ResourceProvisioner
	Shadow ResourceProvisioner
	Err    error
}

func (f *shadowComponentFactoryShared) ResourceProvider(
	n, uid string) (ResourceProvider, shadowResourceProvider, error) {
	f.lock.Lock()
	defer f.lock.Unlock()

	// Determine if we already have a value
	raw, ok := f.providers.ValueOk(uid)
	if !ok {
		// Build the entry
		var entry shadowComponentFactoryProviderEntry

		// No value, initialize. Create the original
		p, err := f.contextComponentFactory.ResourceProvider(n, uid)
		if err != nil {
			entry.Err = err
			p = nil // Just to be sure
		}

		if p != nil {
			// Create the shadow
			real, shadow := newShadowResourceProvider(p)
			entry.Real = real
			entry.Shadow = shadow
		}

		// Store the value
		f.providers.SetValue(uid, &entry)
		raw = &entry
	}

	// Read the entry
	entry, ok := raw.(*shadowComponentFactoryProviderEntry)
	if !ok {
		return nil, nil, fmt.Errorf("Unknown value for shadow provider: %#v", raw)
	}

	// Return
	return entry.Real, entry.Shadow, entry.Err
}

func (f *shadowComponentFactoryShared) ResourceProvisioner(
	n, uid string) (ResourceProvisioner, ResourceProvisioner, error) {
	f.lock.Lock()
	defer f.lock.Unlock()

	// Determine if we already have a value
	raw, ok := f.provisioners.ValueOk(uid)
	if !ok {
		// Build the entry
		var entry shadowComponentFactoryProvisionerEntry

		// No value, initialize. Create the original
		p, err := f.contextComponentFactory.ResourceProvisioner(n, uid)
		if err != nil {
			entry.Err = err
			p = nil // Just to be sure
		}

		if p != nil {
			// For now, just create a mock since we don't support provisioners yet
			real := p
			shadow := new(MockResourceProvisioner)
			entry.Real = real
			entry.Shadow = shadow
		}

		// Store the value
		f.provisioners.SetValue(uid, &entry)
		raw = &entry
	}

	// Read the entry
	entry, ok := raw.(*shadowComponentFactoryProvisionerEntry)
	if !ok {
		return nil, nil, fmt.Errorf("Unknown value for shadow provisioner: %#v", raw)
	}

	// Return
	return entry.Real, entry.Shadow, entry.Err
}
<|endoftext|>


<commit_before>package terraform

import (
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

func TestStateFilterFilter(t *testing.T) {
	cases := map[string]struct {
		State    string
		Filters  []string
		Expected []string
	}{
		"all": {
			"small.tfstate",
			[]string{},
			[]string{
				"*terraform.ResourceState: aws_key_pair.onprem",
				"*terraform.InstanceState: aws_key_pair.onprem",
				"*terraform.ModuleState: module.bootstrap",
				"*terraform.ResourceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-a",
				"*terraform.InstanceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-a",
				"*terraform.ResourceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-ns",
				"*terraform.InstanceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-ns",
				"*terraform.ResourceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
				"*terraform.InstanceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
			},
		},

		"single resource": {
			"small.tfstate",
			[]string{"aws_key_pair.onprem"},
			[]string{
				"*terraform.ResourceState: aws_key_pair.onprem",
				"*terraform.InstanceState: aws_key_pair.onprem",
			},
		},

		"single resource with similar names": {
			"small_test_instance.tfstate",
			[]string{"test_instance.foo"},
			[]string{
				"*terraform.ResourceState: test_instance.foo",
				"*terraform.InstanceState: test_instance.foo",
			},
		},

		"single instance": {
			"small.tfstate",
			[]string{"aws_key_pair.onprem.primary"},
			[]string{
				"*terraform.InstanceState: aws_key_pair.onprem",
			},
		},

		"module filter": {
			"complete.tfstate",
			[]string{"module.bootstrap"},
			[]string{
				"*terraform.ModuleState: module.bootstrap",
				"*terraform.ResourceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-a",
				"*terraform.InstanceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-a",
				"*terraform.ResourceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-ns",
				"*terraform.InstanceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-ns",
				"*terraform.ResourceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
				"*terraform.InstanceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
			},
		},

		"resource in module": {
			"complete.tfstate",
			[]string{"module.bootstrap.aws_route53_zone.oasis-consul-bootstrap"},
			[]string{
				"*terraform.ResourceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
				"*terraform.InstanceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
			},
		},

		"resource in module 2": {
			"resource-in-module-2.tfstate",
			[]string{"module.foo.aws_instance.foo"},
			[]string{},
		},

		"single count index": {
			"complete.tfstate",
			[]string{"module.consul.aws_instance.consul-green[0]"},
			[]string{
				"*terraform.ResourceState: module.consul.aws_instance.consul-green[0]",
				"*terraform.InstanceState: module.consul.aws_instance.consul-green[0]",
			},
		},

		"nested modules": {
			"nested-modules.tfstate",
			[]string{"module.outer"},
			[]string{
				"*terraform.ModuleState: module.outer",
				"*terraform.ModuleState: module.outer.module.child1",
				"*terraform.ResourceState: module.outer.module.child1.aws_instance.foo",
				"*terraform.InstanceState: module.outer.module.child1.aws_instance.foo",
				"*terraform.ModuleState: module.outer.module.child2",
				"*terraform.ResourceState: module.outer.module.child2.aws_instance.foo",
				"*terraform.InstanceState: module.outer.module.child2.aws_instance.foo",
			},
		},
	}

	for n, tc := range cases {
		// Load our state
		f, err := os.Open(filepath.Join("./test-fixtures", "state-filter", tc.State))
		if err != nil {
			t.Fatalf("%q: err: %s", n, err)
		}

		state, err := ReadState(f)
		f.Close()
		if err != nil {
			t.Fatalf("%q: err: %s", n, err)
		}

		// Create the filter
		filter := &StateFilter{State: state}

		// Filter!
		results, err := filter.Filter(tc.Filters...)
		if err != nil {
			t.Fatalf("%q: err: %s", n, err)
		}

		actual := make([]string, len(results))
		for i, result := range results {
			actual[i] = result.String()
		}

		if !reflect.DeepEqual(actual, tc.Expected) {
			t.Fatalf("%q: expected, then actual\n\n%#v\n\n%#v", n, tc.Expected, actual)
		}
	}
}
<commit_msg>terraform: test for querying count resources<commit_after>package terraform

import (
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

func TestStateFilterFilter(t *testing.T) {
	cases := map[string]struct {
		State    string
		Filters  []string
		Expected []string
	}{
		"all": {
			"small.tfstate",
			[]string{},
			[]string{
				"*terraform.ResourceState: aws_key_pair.onprem",
				"*terraform.InstanceState: aws_key_pair.onprem",
				"*terraform.ModuleState: module.bootstrap",
				"*terraform.ResourceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-a",
				"*terraform.InstanceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-a",
				"*terraform.ResourceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-ns",
				"*terraform.InstanceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-ns",
				"*terraform.ResourceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
				"*terraform.InstanceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
			},
		},

		"single resource": {
			"small.tfstate",
			[]string{"aws_key_pair.onprem"},
			[]string{
				"*terraform.ResourceState: aws_key_pair.onprem",
				"*terraform.InstanceState: aws_key_pair.onprem",
			},
		},

		"single resource with similar names": {
			"small_test_instance.tfstate",
			[]string{"test_instance.foo"},
			[]string{
				"*terraform.ResourceState: test_instance.foo",
				"*terraform.InstanceState: test_instance.foo",
			},
		},

		"single instance": {
			"small.tfstate",
			[]string{"aws_key_pair.onprem.primary"},
			[]string{
				"*terraform.InstanceState: aws_key_pair.onprem",
			},
		},

		"module filter": {
			"complete.tfstate",
			[]string{"module.bootstrap"},
			[]string{
				"*terraform.ModuleState: module.bootstrap",
				"*terraform.ResourceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-a",
				"*terraform.InstanceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-a",
				"*terraform.ResourceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-ns",
				"*terraform.InstanceState: module.bootstrap.aws_route53_record.oasis-consul-bootstrap-ns",
				"*terraform.ResourceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
				"*terraform.InstanceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
			},
		},

		"resource in module": {
			"complete.tfstate",
			[]string{"module.bootstrap.aws_route53_zone.oasis-consul-bootstrap"},
			[]string{
				"*terraform.ResourceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
				"*terraform.InstanceState: module.bootstrap.aws_route53_zone.oasis-consul-bootstrap",
			},
		},

		"resource in module 2": {
			"resource-in-module-2.tfstate",
			[]string{"module.foo.aws_instance.foo"},
			[]string{},
		},

		"single count index": {
			"complete.tfstate",
			[]string{"module.consul.aws_instance.consul-green[0]"},
			[]string{
				"*terraform.ResourceState: module.consul.aws_instance.consul-green[0]",
				"*terraform.InstanceState: module.consul.aws_instance.consul-green[0]",
			},
		},

		"no count index": {
			"complete.tfstate",
			[]string{"module.consul.aws_instance.consul-green"},
			[]string{
				"*terraform.ResourceState: module.consul.aws_instance.consul-green[0]",
				"*terraform.InstanceState: module.consul.aws_instance.consul-green[0]",
				"*terraform.ResourceState: module.consul.aws_instance.consul-green[1]",
				"*terraform.InstanceState: module.consul.aws_instance.consul-green[1]",
				"*terraform.ResourceState: module.consul.aws_instance.consul-green[2]",
				"*terraform.InstanceState: module.consul.aws_instance.consul-green[2]",
			},
		},

		"nested modules": {
			"nested-modules.tfstate",
			[]string{"module.outer"},
			[]string{
				"*terraform.ModuleState: module.outer",
				"*terraform.ModuleState: module.outer.module.child1",
				"*terraform.ResourceState: module.outer.module.child1.aws_instance.foo",
				"*terraform.InstanceState: module.outer.module.child1.aws_instance.foo",
				"*terraform.ModuleState: module.outer.module.child2",
				"*terraform.ResourceState: module.outer.module.child2.aws_instance.foo",
				"*terraform.InstanceState: module.outer.module.child2.aws_instance.foo",
			},
		},
	}

	for n, tc := range cases {
		// Load our state
		f, err := os.Open(filepath.Join("./test-fixtures", "state-filter", tc.State))
		if err != nil {
			t.Fatalf("%q: err: %s", n, err)
		}

		state, err := ReadState(f)
		f.Close()
		if err != nil {
			t.Fatalf("%q: err: %s", n, err)
		}

		// Create the filter
		filter := &StateFilter{State: state}

		// Filter!
		results, err := filter.Filter(tc.Filters...)
		if err != nil {
			t.Fatalf("%q: err: %s", n, err)
		}

		actual := make([]string, len(results))
		for i, result := range results {
			actual[i] = result.String()
		}

		if !reflect.DeepEqual(actual, tc.Expected) {
			t.Fatalf("%q: expected, then actual\n\n%#v\n\n%#v", n, tc.Expected, actual)
		}
	}
}
<|endoftext|>


<commit_before>package eventbus

type future struct{
	notify chan struct{}
}<commit_msg>rm future<commit_after><|endoftext|>


<commit_before>package main

import (
	"./gaurun"
	"flag"
	"github.com/Sirupsen/logrus"
	statsGo "github.com/fukata/golang-stats-api-handler"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"strings"
)

func main() {
	versionPrinted := flag.Bool("v", false, "gaurun version")
	confPath := flag.String("c", "", "configuration file path for gaurun")
	listenPort := flag.String("p", "", "port number or unix socket path")
	flag.Parse()

	if *versionPrinted {
		gaurun.PrintGaurunVersion()
		os.Exit(0)
	}

	// set concurrency
	runtime.GOMAXPROCS(runtime.NumCPU())

	// set default parameters
	gaurun.ConfGaurun = gaurun.BuildDefaultConfGaurun()

	// init logger
	gaurun.LogAccess = logrus.New()
	gaurun.LogError = logrus.New()

	gaurun.LogAccess.Formatter = new(gaurun.GaurunFormatter)
	gaurun.LogError.Formatter = new(gaurun.GaurunFormatter)

	// load configuration
	conf, err := gaurun.LoadConfGaurun(gaurun.ConfGaurun, *confPath)
	if err != nil {
		gaurun.LogError.Fatal(err)
	}
	gaurun.ConfGaurun = conf

	// overwrite if port is specified by flags
	if *listenPort != "" {
		gaurun.ConfGaurun.Core.Port = *listenPort
	}

	// set logger
	err = gaurun.SetLogLevel(gaurun.LogAccess, "info")
	if err != nil {
		log.Fatal(err)
	}
	err = gaurun.SetLogLevel(gaurun.LogError, gaurun.ConfGaurun.Log.Level)
	if err != nil {
		log.Fatal(err)
	}
	err = gaurun.SetLogOut(gaurun.LogAccess, gaurun.ConfGaurun.Log.AccessLog)
	if err != nil {
		log.Fatal(err)
	}
	err = gaurun.SetLogOut(gaurun.LogError, gaurun.ConfGaurun.Log.ErrorLog)
	if err != nil {
		log.Fatal(err)
	}

	if !gaurun.ConfGaurun.Ios.Enabled && !gaurun.ConfGaurun.Android.Enabled {
		gaurun.LogError.Fatal("What do you want to do?")
	}

	if gaurun.ConfGaurun.Ios.Enabled {
		gaurun.CertificatePemIos.Cert, err = ioutil.ReadFile(gaurun.ConfGaurun.Ios.PemCertPath)
		if err != nil {
			gaurun.LogError.Fatal("A certification file for iOS is not found.")
		}

		gaurun.CertificatePemIos.Key, err = ioutil.ReadFile(gaurun.ConfGaurun.Ios.PemKeyPath)
		if err != nil {
			gaurun.LogError.Fatal("A key file for iOS is not found.")
		}

	}

	if gaurun.ConfGaurun.Android.Enabled {
		if gaurun.ConfGaurun.Android.ApiKey == "" {
			gaurun.LogError.Fatal("APIKey for Android is empty.")
		}
	}

	gaurun.InitGCMClient()
	gaurun.InitStatGaurun()
	statsGo.PrettyPrintEnabled()
	gaurun.StartPushWorkers(gaurun.ConfGaurun.Core.WorkerNum, gaurun.ConfGaurun.Core.QueueNum)

	http.HandleFunc(gaurun.ConfGaurun.Api.PushUri, gaurun.PushNotificationHandler)
	http.HandleFunc(gaurun.ConfGaurun.Api.StatGoUri, statsGo.Handler)
	http.HandleFunc(gaurun.ConfGaurun.Api.StatAppUri, gaurun.StatsGaurunHandler)
	http.HandleFunc(gaurun.ConfGaurun.Api.ConfigAppUri, gaurun.ConfigGaurunHandler)

	// Listen TCP Port
	if _, err := strconv.Atoi(gaurun.ConfGaurun.Core.Port); err == nil {
		http.ListenAndServe(":"+gaurun.ConfGaurun.Core.Port, nil)
	}

	// Listen UNIX Socket
	if strings.HasPrefix(gaurun.ConfGaurun.Core.Port, "unix:/") {
		sockPath := gaurun.ConfGaurun.Core.Port[5:]
		fi, err := os.Lstat(sockPath)
		if err == nil && (fi.Mode()&os.ModeSocket) == os.ModeSocket {
			err := os.Remove(sockPath)
			if err != nil {
				log.Fatal("failed to remove " + sockPath)
			}
		}
		l, err := net.Listen("unix", sockPath)
		if err != nil {
			log.Fatal("failed to listen: " + sockPath)
		}
		http.Serve(l, nil)
	}

	log.Fatal("port parameter is invalid: " + gaurun.ConfGaurun.Core.Port)
}
<commit_msg>refactored: used return instead of os.Exit(0).<commit_after>package main

import (
	"./gaurun"
	"flag"
	"github.com/Sirupsen/logrus"
	statsGo "github.com/fukata/golang-stats-api-handler"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"strings"
)

func main() {
	versionPrinted := flag.Bool("v", false, "gaurun version")
	confPath := flag.String("c", "", "configuration file path for gaurun")
	listenPort := flag.String("p", "", "port number or unix socket path")
	flag.Parse()

	if *versionPrinted {
		gaurun.PrintGaurunVersion()
		return
	}

	// set concurrency
	runtime.GOMAXPROCS(runtime.NumCPU())

	// set default parameters
	gaurun.ConfGaurun = gaurun.BuildDefaultConfGaurun()

	// init logger
	gaurun.LogAccess = logrus.New()
	gaurun.LogError = logrus.New()

	gaurun.LogAccess.Formatter = new(gaurun.GaurunFormatter)
	gaurun.LogError.Formatter = new(gaurun.GaurunFormatter)

	// load configuration
	conf, err := gaurun.LoadConfGaurun(gaurun.ConfGaurun, *confPath)
	if err != nil {
		gaurun.LogError.Fatal(err)
	}
	gaurun.ConfGaurun = conf

	// overwrite if port is specified by flags
	if *listenPort != "" {
		gaurun.ConfGaurun.Core.Port = *listenPort
	}

	// set logger
	err = gaurun.SetLogLevel(gaurun.LogAccess, "info")
	if err != nil {
		log.Fatal(err)
	}
	err = gaurun.SetLogLevel(gaurun.LogError, gaurun.ConfGaurun.Log.Level)
	if err != nil {
		log.Fatal(err)
	}
	err = gaurun.SetLogOut(gaurun.LogAccess, gaurun.ConfGaurun.Log.AccessLog)
	if err != nil {
		log.Fatal(err)
	}
	err = gaurun.SetLogOut(gaurun.LogError, gaurun.ConfGaurun.Log.ErrorLog)
	if err != nil {
		log.Fatal(err)
	}

	if !gaurun.ConfGaurun.Ios.Enabled && !gaurun.ConfGaurun.Android.Enabled {
		gaurun.LogError.Fatal("What do you want to do?")
	}

	if gaurun.ConfGaurun.Ios.Enabled {
		gaurun.CertificatePemIos.Cert, err = ioutil.ReadFile(gaurun.ConfGaurun.Ios.PemCertPath)
		if err != nil {
			gaurun.LogError.Fatal("A certification file for iOS is not found.")
		}

		gaurun.CertificatePemIos.Key, err = ioutil.ReadFile(gaurun.ConfGaurun.Ios.PemKeyPath)
		if err != nil {
			gaurun.LogError.Fatal("A key file for iOS is not found.")
		}

	}

	if gaurun.ConfGaurun.Android.Enabled {
		if gaurun.ConfGaurun.Android.ApiKey == "" {
			gaurun.LogError.Fatal("APIKey for Android is empty.")
		}
	}

	gaurun.InitGCMClient()
	gaurun.InitStatGaurun()
	statsGo.PrettyPrintEnabled()
	gaurun.StartPushWorkers(gaurun.ConfGaurun.Core.WorkerNum, gaurun.ConfGaurun.Core.QueueNum)

	http.HandleFunc(gaurun.ConfGaurun.Api.PushUri, gaurun.PushNotificationHandler)
	http.HandleFunc(gaurun.ConfGaurun.Api.StatGoUri, statsGo.Handler)
	http.HandleFunc(gaurun.ConfGaurun.Api.StatAppUri, gaurun.StatsGaurunHandler)
	http.HandleFunc(gaurun.ConfGaurun.Api.ConfigAppUri, gaurun.ConfigGaurunHandler)

	// Listen TCP Port
	if _, err := strconv.Atoi(gaurun.ConfGaurun.Core.Port); err == nil {
		http.ListenAndServe(":"+gaurun.ConfGaurun.Core.Port, nil)
	}

	// Listen UNIX Socket
	if strings.HasPrefix(gaurun.ConfGaurun.Core.Port, "unix:/") {
		sockPath := gaurun.ConfGaurun.Core.Port[5:]
		fi, err := os.Lstat(sockPath)
		if err == nil && (fi.Mode()&os.ModeSocket) == os.ModeSocket {
			err := os.Remove(sockPath)
			if err != nil {
				log.Fatal("failed to remove " + sockPath)
			}
		}
		l, err := net.Listen("unix", sockPath)
		if err != nil {
			log.Fatal("failed to listen: " + sockPath)
		}
		http.Serve(l, nil)
	}

	log.Fatal("port parameter is invalid: " + gaurun.ConfGaurun.Core.Port)
}
<|endoftext|>