<commit_before>package describe

import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/aws/aws-sdk-go/aws/session"
)

func Cloudformation(svc *cloudformation.CloudFormation) (cloudformations *cloudformation.DescribeStacksOutput){

  params := &cloudformation.DescribeStacksInput{}
  resp, err := svc.DescribeStacks(params)

  if err != nil {
      // Print the error, cast err to awserr.Error to get the Code and
      // Message from an error.
      fmt.Println(err.Error())
      return
  }

  // Pretty-print the response data.
  cloudformations = resp
  return
}

func Account(svc *ec2.EC2) (attributes *ec2.DescribeAccountAttributesOutput){

  params := &ec2.DescribeAccountAttributesInput{
    AttributeNames: []*string{
      aws.String("supported-platforms"),
      aws.String("default-vpc"),
      aws.String("max-instances"),
      aws.String("vpc-max-security-groups-per-interface"),
      aws.String("max-elastic-ips"),
      aws.String("vpc-max-elastic-ips"),
      },
      DryRun: aws.Bool(false),
      }
      resp, err := svc.DescribeAccountAttributes(params)

      if err != nil {
        fmt.Println(err.Error())
        return
      }

  attributes = resp
  return
}

func Acl(svc *ec2.EC2) (acls *ec2.DescribeNetworkAclsOutput){
	params := &ec2.DescribeNetworkAclsInput{
		DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeNetworkAcls(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	acls = resp
  return
}

func Az(svc *ec2.EC2) (azs *ec2.DescribeAvailabilityZonesOutput){

	params := &ec2.DescribeAvailabilityZonesInput{
		DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeAvailabilityZones(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	azs = resp
  return
}

func Customer_gateway(svc *ec2.EC2) (customer_gateways *ec2.DescribeCustomerGatewaysOutput){

  params := &ec2.DescribeCustomerGatewaysInput{
    DryRun: aws.Bool(false),
  }
  resp, err := svc.DescribeCustomerGateways(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  customer_gateways = resp
  return
}

func Dhcp(svc *ec2.EC2) (dhcps *ec2.DescribeDhcpOptionsOutput){

  params := &ec2.DescribeDhcpOptionsInput{
    DryRun: aws.Bool(false),
  }
  resp, err := svc.DescribeDhcpOptions(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  dhcps = resp
  return
}

func Eip(svc *ec2.EC2) (eips *ec2.DescribeAddressesOutput){

  params := &ec2.DescribeAddressesInput{
    DryRun: aws.Bool(false),
  }
  resp, err := svc.DescribeAddresses(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  eips = resp
  return
}

func Flowlog(svc *ec2.EC2) (flowlogs *ec2.DescribeFlowLogsOutput){

  params := &ec2.DescribeFlowLogsInput{
      MaxResults: aws.Int64(10),
  }
  resp, err := svc.DescribeFlowLogs(params)

  if err != nil {
      fmt.Println(err.Error())
      return
  }

  flowlogs = resp
  return
}

func Igw(svc *ec2.EC2) (igws *ec2.DescribeInternetGatewaysOutput){

	params := &ec2.DescribeInternetGatewaysInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeInternetGateways(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	igws = resp
  return
}

func Image(svc *ec2.EC2, owner string) (images *ec2.DescribeImagesOutput){

  params := &ec2.DescribeImagesInput{
    DryRun: aws.Bool(false),
    Owners: []*string{
      aws.String(owner),
    },
  }
  resp, err := svc.DescribeImages(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  images = resp
  return
}

func Instance(svc *ec2.EC2) (instances *ec2.DescribeInstancesOutput){

	params := &ec2.DescribeInstancesInput{
	  DryRun: aws.Bool(false),
	  MaxResults: aws.Int64(100),
    Filters: []*ec2.Filter{
        &ec2.Filter{
            Name: aws.String("instance-state-name"),
            Values: []*string{
                aws.String("running"),
                aws.String("pending"),
            },
        },
    },
	}
	resp, err := svc.DescribeInstances(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	instances = resp
  return
}

func Nat(svc *ec2.EC2) (nats *ec2.DescribeNatGatewaysOutput){

	params := &ec2.DescribeNatGatewaysInput{
		MaxResults: aws.Int64(100),
	}
	resp, err := svc.DescribeNatGateways(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	nats = resp
  return
}

func Nic(svc *ec2.EC2) (nics *ec2.DescribeNetworkInterfacesOutput){

	params := &ec2.DescribeNetworkInterfacesInput{
		DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeNetworkInterfaces(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	nics = resp
  return
}

func Placement_group(svc *ec2.EC2) (placement_groups *ec2.DescribePlacementGroupsOutput){

  params := &ec2.DescribePlacementGroupsInput{
    DryRun: aws.Bool(false),
  }
  resp, err := svc.DescribePlacementGroups(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  placement_groups = resp
  return
}

func Region() (regions *ec2.DescribeRegionsOutput){

<<<<<<< HEAD
  sess, err := session.NewSession(&aws.Config{Region: aws.String(`us-west-2`)})
=======
  sess, err := session.NewSession()
>>>>>>> b3d36fafb8044bd8b74830377c77d217ac409831
  if err != nil {
    fmt.Println("failed to create session,", err)
    return
  }

  svc := ec2.New(sess)

	params := &ec2.DescribeRegionsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeRegions(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	regions = resp
  return
}

func Route_table(svc *ec2.EC2) (route_tables *ec2.DescribeRouteTablesOutput){

	params := &ec2.DescribeRouteTablesInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeRouteTables(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	route_tables = resp
  return
}

func Security_group(svc *ec2.EC2) (security_groups *ec2.DescribeSecurityGroupsOutput){

	params := &ec2.DescribeSecurityGroupsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeSecurityGroups(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	security_groups = resp
  return
}

func Snapshot(svc *ec2.EC2) (snapshots *ec2.DescribeSnapshotsOutput){

	params := &ec2.DescribeSnapshotsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeSnapshots(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	snapshots = resp
  return
}

func Spot_price(svc *ec2.EC2) (spot_prices *ec2.DescribeSpotPriceHistoryOutput){

	params := &ec2.DescribeSpotPriceHistoryInput{
	  DryRun: aws.Bool(false),
	  MaxResults: aws.Int64(100),
	}
	resp, err := svc.DescribeSpotPriceHistory(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	spot_prices = resp
  return
}

func Volume(svc *ec2.EC2) (volumes *ec2.DescribeVolumesOutput){

	params := &ec2.DescribeVolumesInput{
	  DryRun: aws.Bool(false),
	  MaxResults: aws.Int64(100),
	}
	resp, err := svc.DescribeVolumes(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	volumes = resp
  return
}

func Subnet(svc *ec2.EC2) (subnets *ec2.DescribeSubnetsOutput){

	params := &ec2.DescribeSubnetsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeSubnets(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	subnets = resp
  return
}

func Tag(svc *ec2.EC2) (tags *ec2.DescribeTagsOutput){

	params := &ec2.DescribeTagsInput{
	  DryRun: aws.Bool(false),
	  MaxResults: aws.Int64(100),
	}
	resp, err := svc.DescribeTags(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	tags = resp
  return
}

func Vpn_gateway(svc *ec2.EC2) (vpn_gateways *ec2.DescribeVpnGatewaysOutput){

	params := &ec2.DescribeVpnGatewaysInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeVpnGateways(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	vpn_gateways = resp
  return
}

func Vpn_connection(svc *ec2.EC2) (vpn_connections *ec2.DescribeVpnConnectionsOutput){

	params := &ec2.DescribeVpnConnectionsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeVpnConnections(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	vpn_connections = resp
  return
}

func Vpc_peer(svc *ec2.EC2) (vpc_peers *ec2.DescribeVpcPeeringConnectionsOutput){

	params := &ec2.DescribeVpcPeeringConnectionsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeVpcPeeringConnections(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	vpc_peers = resp
  return
}

func Vpc(svc *ec2.EC2) (vpcs *ec2.DescribeVpcsOutput){

	params := &ec2.DescribeVpcsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeVpcs(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	vpcs = resp
  return
}
<commit_msg>fixed merge artifact<commit_after>package describe

import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/aws/aws-sdk-go/aws/session"
)

func Cloudformation(svc *cloudformation.CloudFormation) (cloudformations *cloudformation.DescribeStacksOutput){

  params := &cloudformation.DescribeStacksInput{}
  resp, err := svc.DescribeStacks(params)

  if err != nil {
      // Print the error, cast err to awserr.Error to get the Code and
      // Message from an error.
      fmt.Println(err.Error())
      return
  }

  // Pretty-print the response data.
  cloudformations = resp
  return
}

func Account(svc *ec2.EC2) (attributes *ec2.DescribeAccountAttributesOutput){

  params := &ec2.DescribeAccountAttributesInput{
    AttributeNames: []*string{
      aws.String("supported-platforms"),
      aws.String("default-vpc"),
      aws.String("max-instances"),
      aws.String("vpc-max-security-groups-per-interface"),
      aws.String("max-elastic-ips"),
      aws.String("vpc-max-elastic-ips"),
      },
      DryRun: aws.Bool(false),
      }
      resp, err := svc.DescribeAccountAttributes(params)

      if err != nil {
        fmt.Println(err.Error())
        return
      }

  attributes = resp
  return
}

func Acl(svc *ec2.EC2) (acls *ec2.DescribeNetworkAclsOutput){
	params := &ec2.DescribeNetworkAclsInput{
		DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeNetworkAcls(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	acls = resp
  return
}

func Az(svc *ec2.EC2) (azs *ec2.DescribeAvailabilityZonesOutput){

	params := &ec2.DescribeAvailabilityZonesInput{
		DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeAvailabilityZones(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	azs = resp
  return
}

func Customer_gateway(svc *ec2.EC2) (customer_gateways *ec2.DescribeCustomerGatewaysOutput){

  params := &ec2.DescribeCustomerGatewaysInput{
    DryRun: aws.Bool(false),
  }
  resp, err := svc.DescribeCustomerGateways(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  customer_gateways = resp
  return
}

func Dhcp(svc *ec2.EC2) (dhcps *ec2.DescribeDhcpOptionsOutput){

  params := &ec2.DescribeDhcpOptionsInput{
    DryRun: aws.Bool(false),
  }
  resp, err := svc.DescribeDhcpOptions(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  dhcps = resp
  return
}

func Eip(svc *ec2.EC2) (eips *ec2.DescribeAddressesOutput){

  params := &ec2.DescribeAddressesInput{
    DryRun: aws.Bool(false),
  }
  resp, err := svc.DescribeAddresses(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  eips = resp
  return
}

func Flowlog(svc *ec2.EC2) (flowlogs *ec2.DescribeFlowLogsOutput){

  params := &ec2.DescribeFlowLogsInput{
      MaxResults: aws.Int64(10),
  }
  resp, err := svc.DescribeFlowLogs(params)

  if err != nil {
      fmt.Println(err.Error())
      return
  }

  flowlogs = resp
  return
}

func Igw(svc *ec2.EC2) (igws *ec2.DescribeInternetGatewaysOutput){

	params := &ec2.DescribeInternetGatewaysInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeInternetGateways(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	igws = resp
  return
}

func Image(svc *ec2.EC2, owner string) (images *ec2.DescribeImagesOutput){

  params := &ec2.DescribeImagesInput{
    DryRun: aws.Bool(false),
    Owners: []*string{
      aws.String(owner),
    },
  }
  resp, err := svc.DescribeImages(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  images = resp
  return
}

func Instance(svc *ec2.EC2) (instances *ec2.DescribeInstancesOutput){

	params := &ec2.DescribeInstancesInput{
	  DryRun: aws.Bool(false),
	  MaxResults: aws.Int64(100),
    Filters: []*ec2.Filter{
        &ec2.Filter{
            Name: aws.String("instance-state-name"),
            Values: []*string{
                aws.String("running"),
                aws.String("pending"),
            },
        },
    },
	}
	resp, err := svc.DescribeInstances(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	instances = resp
  return
}

func Nat(svc *ec2.EC2) (nats *ec2.DescribeNatGatewaysOutput){

	params := &ec2.DescribeNatGatewaysInput{
		MaxResults: aws.Int64(100),
	}
	resp, err := svc.DescribeNatGateways(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	nats = resp
  return
}

func Nic(svc *ec2.EC2) (nics *ec2.DescribeNetworkInterfacesOutput){

	params := &ec2.DescribeNetworkInterfacesInput{
		DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeNetworkInterfaces(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	nics = resp
  return
}

func Placement_group(svc *ec2.EC2) (placement_groups *ec2.DescribePlacementGroupsOutput){

  params := &ec2.DescribePlacementGroupsInput{
    DryRun: aws.Bool(false),
  }
  resp, err := svc.DescribePlacementGroups(params)

  if err != nil {
    fmt.Println(err.Error())
    return
  }

  placement_groups = resp
  return
}

func Region() (regions *ec2.DescribeRegionsOutput){

  sess, err := session.NewSession(&aws.Config{Region: aws.String(`us-west-2`)})
  sess, err := session.NewSession()
  if err != nil {
    fmt.Println("failed to create session,", err)
    return
  }

  svc := ec2.New(sess)

	params := &ec2.DescribeRegionsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeRegions(params)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	regions = resp
  return
}

func Route_table(svc *ec2.EC2) (route_tables *ec2.DescribeRouteTablesOutput){

	params := &ec2.DescribeRouteTablesInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeRouteTables(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	route_tables = resp
  return
}

func Security_group(svc *ec2.EC2) (security_groups *ec2.DescribeSecurityGroupsOutput){

	params := &ec2.DescribeSecurityGroupsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeSecurityGroups(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	security_groups = resp
  return
}

func Snapshot(svc *ec2.EC2) (snapshots *ec2.DescribeSnapshotsOutput){

	params := &ec2.DescribeSnapshotsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeSnapshots(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	snapshots = resp
  return
}

func Spot_price(svc *ec2.EC2) (spot_prices *ec2.DescribeSpotPriceHistoryOutput){

	params := &ec2.DescribeSpotPriceHistoryInput{
	  DryRun: aws.Bool(false),
	  MaxResults: aws.Int64(100),
	}
	resp, err := svc.DescribeSpotPriceHistory(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	spot_prices = resp
  return
}

func Volume(svc *ec2.EC2) (volumes *ec2.DescribeVolumesOutput){

	params := &ec2.DescribeVolumesInput{
	  DryRun: aws.Bool(false),
	  MaxResults: aws.Int64(100),
	}
	resp, err := svc.DescribeVolumes(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	volumes = resp
  return
}

func Subnet(svc *ec2.EC2) (subnets *ec2.DescribeSubnetsOutput){

	params := &ec2.DescribeSubnetsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeSubnets(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	subnets = resp
  return
}

func Tag(svc *ec2.EC2) (tags *ec2.DescribeTagsOutput){

	params := &ec2.DescribeTagsInput{
	  DryRun: aws.Bool(false),
	  MaxResults: aws.Int64(100),
	}
	resp, err := svc.DescribeTags(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	tags = resp
  return
}

func Vpn_gateway(svc *ec2.EC2) (vpn_gateways *ec2.DescribeVpnGatewaysOutput){

	params := &ec2.DescribeVpnGatewaysInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeVpnGateways(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	vpn_gateways = resp
  return
}

func Vpn_connection(svc *ec2.EC2) (vpn_connections *ec2.DescribeVpnConnectionsOutput){

	params := &ec2.DescribeVpnConnectionsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeVpnConnections(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	vpn_connections = resp
  return
}

func Vpc_peer(svc *ec2.EC2) (vpc_peers *ec2.DescribeVpcPeeringConnectionsOutput){

	params := &ec2.DescribeVpcPeeringConnectionsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeVpcPeeringConnections(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	vpc_peers = resp
  return
}

func Vpc(svc *ec2.EC2) (vpcs *ec2.DescribeVpcsOutput){

	params := &ec2.DescribeVpcsInput{
	  DryRun: aws.Bool(false),
	}
	resp, err := svc.DescribeVpcs(params)

	if err != nil {
	  fmt.Println(err.Error())
	  return
	}

	vpcs = resp
  return
}
<|endoftext|>


<commit_before>package hash

import (
	"bytes"
	"fmt"
)

type Hash []byte

func xor(slice []byte) byte {
	value := slice[0]
	for _, s := range slice[1:] {
		value ^= s
	}
	return value
}

func (hash Hash) get(index int) byte {
	i := index % len(hash)
	return hash[i]
}

func (hash Hash) set(index int, value byte) {
	i := index % len(hash)
	hash[i] = value
}

func (hash Hash) slice(start, end int) []byte {
	values := make([]byte, 0)
	for i := start; i < end; i++ {
		values = append(values, hash.get(i))
	}
	return values
}

func (hash Hash) reverse(start, end int) {
	values := hash.slice(start, end)
	for i := start; i < end; i++ {
		value := values[end-i-1]
		hash.set(i, value)
	}
}

func (hash Hash) String() string {
	var buf bytes.Buffer
	for i := 0; i < 255; i += 16 {
		buf.WriteString(fmt.Sprintf("%02x", xor(hash[i:i+16])))
	}
	return buf.String()
}

func ComputeString(input string) Hash {
	lengths := []byte(input)
	for _, b := range []byte{17, 31, 73, 47, 23} {
		lengths = append(lengths, b)
	}
	return Compute(64, lengths)
}

func Compute(iterations int, lengths []byte) Hash {
	hash := make(Hash, 256)
	for i := 0; i < 256; i++ {
		hash[i] = byte(i)
	}

	skip := 0
	start := 0
	for i := 0; i < iterations; i++ {
		for _, length := range lengths {
			hash.reverse(start, start+int(length))
			start += int(length) + skip
			skip++
		}
	}

	return hash
}
<commit_msg>Updates for day 14<commit_after>package hash

import (
	"bytes"
	"fmt"
)

type Hash []byte

func xor(slice []byte) byte {
	value := slice[0]
	for _, s := range slice[1:] {
		value ^= s
	}
	return value
}

func (hash Hash) get(index int) byte {
	i := index % len(hash)
	return hash[i]
}

func (hash Hash) set(index int, value byte) {
	i := index % len(hash)
	hash[i] = value
}

func (hash Hash) slice(start, end int) []byte {
	values := make([]byte, 0)
	for i := start; i < end; i++ {
		values = append(values, hash.get(i))
	}
	return values
}

func (hash Hash) reverse(start, end int) {
	values := hash.slice(start, end)
	for i := start; i < end; i++ {
		value := values[end-i-1]
		hash.set(i, value)
	}
}

func (hash Hash) Hash() []byte {
	b := make([]byte, 16)
	for i := 0; i < 255; i += 16 {
		b[i/16] = xor(hash[i : i+16])
	}
	return b
}

func (hash Hash) String() string {
	var buf bytes.Buffer
	for _, b := range hash.Hash() {
		buf.WriteString(fmt.Sprintf("%02x", b))
	}
	return buf.String()
}

func ComputeString(input string) Hash {
	lengths := []byte(input)
	for _, b := range []byte{17, 31, 73, 47, 23} {
		lengths = append(lengths, b)
	}
	return Compute(64, lengths)
}

func Compute(iterations int, lengths []byte) Hash {
	hash := make(Hash, 256)
	for i := 0; i < 256; i++ {
		hash[i] = byte(i)
	}

	skip := 0
	start := 0
	for i := 0; i < iterations; i++ {
		for _, length := range lengths {
			hash.reverse(start, start+int(length))
			start += int(length) + skip
			skip++
		}
	}

	return hash
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"math/rand"
	"strings"
	"time"

	derpiSearch "github.com/PonyvilleFM/aura/cmd/aerial/derpi"
	"github.com/PonyvilleFM/aura/pvfm"
	"github.com/PonyvilleFM/aura/pvfm/pvl"
	pvfmschedule "github.com/PonyvilleFM/aura/pvfm/schedule"
	"github.com/PonyvilleFM/aura/pvfm/station"
	"github.com/bwmarrin/discordgo"
	"github.com/tebeka/strftime"
)

func init() {
	rand.Seed(time.Now().Unix())
}

// randomRange gives a random whole integer between the given integers [min, max)
func randomRange(min, max int) int {
	return rand.Intn(max-min) + min
}

func pesterLink(s *discordgo.Session, m *discordgo.MessageCreate) {
	if musicLinkRegex.Match([]byte(m.Content)) {
		i, err := pvfm.GetStats()
		if err != nil {
			log.Println(err)
			return
		}

		if i.IsDJLive() && m.ChannelID == youtubeSpamRoomID {
			s.ChannelMessageSend(m.ChannelID, "Please be mindful sharing links to music when a DJ is performing. Thanks!")
		}
	}
}

func np(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	i, err := pvfm.GetStats()
	if err != nil {
		log.Printf("Can't get info: %v, failing over to plan b", err)
		return doStationRequest(s, m, parv)
	}

	result := []string{}

	if i.Main.Nowplaying == "Fetching info..." {
		log.Println("Main information was bad, fetching from station directly...")

		err := doStationRequest(s, m, parv)
		if err != nil {
			return err
		}

		return nil
	} else {
		result = append(result, "📻 **Now Playing on PVFM**\n")

		result = append(result, fmt.Sprintf(
			"Main 🎵 %s\n",
			i.Main.Nowplaying,
		))
		result = append(result, fmt.Sprintf(
			"Chill 🎵 %s\n",
			i.Secondary.Nowplaying,
		))
		result = append(result, fmt.Sprintf(
			"Free! 🎵 %s",
			i.MusicOnly.Nowplaying,
		))
	}

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))
	return nil
}

func dj(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	cal, err := pvl.Get()
	if err != nil {
		return err
	}

	now := cal.Result[0]
	result := []string{}

	localTime := time.Now()
	thentime := time.Unix(now.StartTime, 0)
	if thentime.Unix() < localTime.Unix() {
		result = append(result, fmt.Sprintf("Currently live: %s\n", now.Title))
		now = cal.Result[1]
	}

	nowTime := time.Unix(now.StartTime, 0).UTC()
	zone, _ := nowTime.Zone()
	fmttime, _ := strftime.Format("%Y-%m-%d %H:%M:%S", nowTime)

	result = append(result, fmt.Sprintf("Next event: %s at %s \x02%s\x02",
		now.Title,
		fmttime,
		zone,
	))

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))
	return nil
}

func stats(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	i, err := pvfm.GetStats()
	if err != nil {
		log.Printf("Error getting the station info: %v, falling back to plan b", err)
		return doStatsFromStation(s, m, parv)
	}

	st, err := station.GetStats()
	if err != nil {
		return err
	}

	var l int
	var peak int

	for _, source := range st.Icestats.Source {
		l = l + source.Listeners
		peak = peak + source.ListenerPeak
	}

	result := []string{
		fmt.Sprintf(
			"Current listeners across all streams: %d with a maximum of %d!",
			i.Listeners.Listeners, peak,
		),
		fmt.Sprintf(
			"Detailed: Main: %d listeners, Two: %d listeners, Free: %d listeners",
			i.Main.Listeners, i.Secondary.Listeners, i.MusicOnly.Listeners,
		),
	}

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))

	return nil
}

func schedule(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	result := []string{}
	schEntries, err := pvfmschedule.Get()
	if err != nil {
		return err
	}

	for _, entry := range schEntries {
		result = append(result, entry.String())
	}

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))
	return nil
}

func doStationRequest(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	stats, err := station.GetStats()
	if err != nil {
		return err
	}

	result := fmt.Sprintf(
		"Now playing: %s - %s on Ponyville FM!",
		stats.Icestats.Source[0].Title,
		stats.Icestats.Source[0].Artist,
	)

	s.ChannelMessageSend(m.ChannelID, result)
	return nil
}

func doStatsFromStation(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	st, err := station.GetStats()
	if err != nil {
		return err
	}

	var l int
	var peak int

	for _, source := range st.Icestats.Source {
		l = l + source.Listeners
		peak = peak + source.ListenerPeak
	}

	result := []string{
		fmt.Sprintf("Current listeners: %d with a maximum of %d!", l, peak),
	}

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))
	return nil
}

func curTime(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("The time currently is %s", time.Now().UTC().Format("2006-01-02 15:04:05 UTC")))

	return nil
}

func streams(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	currentMeta, metaErr := station.GetStats()
	if metaErr != nil {
		s.ChannelMessageSend(m.ChannelID, "Error receiving pvfm metadata")
		return metaErr
	}

	outputString := "**PVFM Servers:**\n"

	for _, element := range currentMeta.Icestats.Source {
		outputString += ":musical_note: " + element.ServerDescription + ":\n<" + strings.Replace(element.Listenurl, "aerial", "dj.bronyradio.com", -1) + ">\n"
	}

	outputString += "\n:cd: DJ Recordings:\n<https://pvfmsets.cf/var/93252527679639552/>9" + "\n:cd: Legacy DJ Recordings:\n<http://darkling.darkwizards.com/wang/BronyRadio/?M=D>"

	s.ChannelMessageSend(m.ChannelID, outputString)

	return nil
}

func derpi(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	searchResults, err := derpiSearch.SearchDerpi(m.Content[7:len(m.Content)])
	if err != nil {
		s.ChannelMessageSend(m.ChannelID, "An error occured.")
		return err
	}
	if len(searchResults.Search) < 1 {
		s.ChannelMessageSend(m.ChannelID, "Error: No results")
		return nil
	}
	s.ChannelMessageSend(m.ChannelID, "http:"+searchResults.Search[randomRange(0, len(searchResults.Search))].Image)
	return nil
}
<commit_msg>Add Luna Radio stream links<commit_after>package main

import (
	"fmt"
	"log"
	"math/rand"
	"strings"
	"time"

	derpiSearch "github.com/PonyvilleFM/aura/cmd/aerial/derpi"
	"github.com/PonyvilleFM/aura/pvfm"
	"github.com/PonyvilleFM/aura/pvfm/pvl"
	pvfmschedule "github.com/PonyvilleFM/aura/pvfm/schedule"
	"github.com/PonyvilleFM/aura/pvfm/station"
	"github.com/bwmarrin/discordgo"
	"github.com/tebeka/strftime"
)

func init() {
	rand.Seed(time.Now().Unix())
}

// randomRange gives a random whole integer between the given integers [min, max)
func randomRange(min, max int) int {
	return rand.Intn(max-min) + min
}

func pesterLink(s *discordgo.Session, m *discordgo.MessageCreate) {
	if musicLinkRegex.Match([]byte(m.Content)) {
		i, err := pvfm.GetStats()
		if err != nil {
			log.Println(err)
			return
		}

		if i.IsDJLive() && m.ChannelID == youtubeSpamRoomID {
			s.ChannelMessageSend(m.ChannelID, "Please be mindful sharing links to music when a DJ is performing. Thanks!")
		}
	}
}

func np(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	i, err := pvfm.GetStats()
	if err != nil {
		log.Printf("Can't get info: %v, failing over to plan b", err)
		return doStationRequest(s, m, parv)
	}

	result := []string{}

	if i.Main.Nowplaying == "Fetching info..." {
		log.Println("Main information was bad, fetching from station directly...")

		err := doStationRequest(s, m, parv)
		if err != nil {
			return err
		}

		return nil
	} else {
		result = append(result, "📻 **Now Playing on PVFM**\n")

		result = append(result, fmt.Sprintf(
			"Main 🎵 %s\n",
			i.Main.Nowplaying,
		))
		result = append(result, fmt.Sprintf(
			"Chill 🎵 %s\n",
			i.Secondary.Nowplaying,
		))
		result = append(result, fmt.Sprintf(
			"Free! 🎵 %s",
			i.MusicOnly.Nowplaying,
		))
	}

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))
	return nil
}

func dj(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	cal, err := pvl.Get()
	if err != nil {
		return err
	}

	now := cal.Result[0]
	result := []string{}

	localTime := time.Now()
	thentime := time.Unix(now.StartTime, 0)
	if thentime.Unix() < localTime.Unix() {
		result = append(result, fmt.Sprintf("Currently live: %s\n", now.Title))
		now = cal.Result[1]
	}

	nowTime := time.Unix(now.StartTime, 0).UTC()
	zone, _ := nowTime.Zone()
	fmttime, _ := strftime.Format("%Y-%m-%d %H:%M:%S", nowTime)

	result = append(result, fmt.Sprintf("Next event: %s at %s \x02%s\x02",
		now.Title,
		fmttime,
		zone,
	))

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))
	return nil
}

func stats(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	i, err := pvfm.GetStats()
	if err != nil {
		log.Printf("Error getting the station info: %v, falling back to plan b", err)
		return doStatsFromStation(s, m, parv)
	}

	st, err := station.GetStats()
	if err != nil {
		return err
	}

	var l int
	var peak int

	for _, source := range st.Icestats.Source {
		l = l + source.Listeners
		peak = peak + source.ListenerPeak
	}

	result := []string{
		fmt.Sprintf(
			"Current listeners across all streams: %d with a maximum of %d!",
			i.Listeners.Listeners, peak,
		),
		fmt.Sprintf(
			"Detailed: Main: %d listeners, Two: %d listeners, Free: %d listeners",
			i.Main.Listeners, i.Secondary.Listeners, i.MusicOnly.Listeners,
		),
	}

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))

	return nil
}

func schedule(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	result := []string{}
	schEntries, err := pvfmschedule.Get()
	if err != nil {
		return err
	}

	for _, entry := range schEntries {
		result = append(result, entry.String())
	}

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))
	return nil
}

func doStationRequest(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	stats, err := station.GetStats()
	if err != nil {
		return err
	}

	result := fmt.Sprintf(
		"Now playing: %s - %s on Ponyville FM!",
		stats.Icestats.Source[0].Title,
		stats.Icestats.Source[0].Artist,
	)

	s.ChannelMessageSend(m.ChannelID, result)
	return nil
}

func doStatsFromStation(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	st, err := station.GetStats()
	if err != nil {
		return err
	}

	var l int
	var peak int

	for _, source := range st.Icestats.Source {
		l = l + source.Listeners
		peak = peak + source.ListenerPeak
	}

	result := []string{
		fmt.Sprintf("Current listeners: %d with a maximum of %d!", l, peak),
	}

	s.ChannelMessageSend(m.ChannelID, strings.Join(result, "\n"))
	return nil
}

func curTime(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("The time currently is %s", time.Now().UTC().Format("2006-01-02 15:04:05 UTC")))

	return nil
}

func streams(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	currentMeta, metaErr := station.GetStats()
	if metaErr != nil {
		s.ChannelMessageSend(m.ChannelID, "Error receiving pvfm metadata")
		return metaErr
	}

	outputString := "**PVFM Servers:**\n"

	for _, element := range currentMeta.Icestats.Source {
		outputString += ":musical_note: " + element.ServerDescription + ":\n<" + strings.Replace(element.Listenurl, "aerial", "dj.bronyradio.com", -1) + ">\n"
	}

	outputString += "**Luna Radio Server:**\n"
	outputString += "\n:musical_note: Luna Radio MP3 128Kbps Stream:\n<http://radio.ponyvillelive.com:8002/stream.mp3>\n:musical_note: Luna Radio Mobile MP3 64Kbps Stream:\n<http://radio.ponyvillelive.com:8002/mobile?;stream.mp3>\n"

	outputString += "\n:cd: DJ Recordings:\n<https://pvfmsets.cf/var/93252527679639552/>9" + "\n:cd: Legacy DJ Recordings:\n<http://darkling.darkwizards.com/wang/BronyRadio/?M=D>"

	s.ChannelMessageSend(m.ChannelID, outputString)

	return nil
}

func derpi(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	searchResults, err := derpiSearch.SearchDerpi(m.Content[7:len(m.Content)])
	if err != nil {
		s.ChannelMessageSend(m.ChannelID, "An error occured.")
		return err
	}
	if len(searchResults.Search) < 1 {
		s.ChannelMessageSend(m.ChannelID, "Error: No results")
		return nil
	}
	s.ChannelMessageSend(m.ChannelID, "http:"+searchResults.Search[randomRange(0, len(searchResults.Search))].Image)
	return nil
}
<|endoftext|>


<commit_before>/*
This package is just a collection of use-case for the various aspects of the RIPE API.
Consider this both as an example on how to use the API and a testing tool for the API wrapper.
*/
package main

import (
	"fmt"
	"github.com/keltia/ripe-atlas"
	"github.com/urfave/cli"
	"log"
	"os"
	"sort"
)

var (
	// CLI specific options
	fDebug   bool
	fLogfile string
	fVerbose bool

	// See flag.go for details

	// Global API options
	fFieldList string
	fFormat    string
	fInclude   string
	fOptFields string
	fPageNum   string
	fPageSize  string
	fSortOrder string
	fWantMine  bool

	// Probe-specific ones
	fAllProbes bool
	fIsAnchor  bool

	// Common measurement ones
	fAllMeasurements bool
	fAsn             string
	fAsnV4           string
	fAsnV6           string
	fCountry         string
	fProtocol        string
	fMeasureType     string
	fWant4           bool
	fWant6           bool

	// Create measurements
	fBillTo    string
	fIsOneOff  bool
	fStartTime string
	fStopTime  string

	// HTTP
	fHTTPMethod  string
	fUserAgent   string
	fHTTPVersion string

	// DNS
	fBitCD         bool
	fDisableDNSSEC bool

	// Traceroute
	fMaxHops    int
	fPacketSize int

	// ProbeSet parameters
	fPoolSize  int
	fAreaType  string
	fAreaValue string

	// Our configuration file
	cnf *Config

	// All possible commands
	cliCommands []cli.Command

	client *atlas.Client

	// Our tiple-valued synthesis of fWant4/fWant6
	wantAF string
)

const (
	atlasVersion = "0.25"
	// MyName is the application name
	MyName = "ripe-atlas"

	// WantBoth is the way to ask for both IPv4 & IPv6.
	WantBoth = "64"

	// Want4 only 4
	Want4 = "4"
	// Want6 only 6
	Want6 = "6"
)

func openlog(fn string) *log.Logger {
	fh, err := os.OpenFile(fn, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("error: can not open logfile %s: %v", fn, err)
	}

	mylog := log.New(fh, "", log.LstdFlags)
	verbose("Logfile: %s %#v", fn, mylog)

	return mylog
}

// -4 & -6 are special, if neither is specified, then we turn both as true
// Check a few other things while we are here
func finalcheck(c *cli.Context) error {

	var (
		err   error
		mylog *log.Logger
	)

	// Load main configuration
	cnf, err = LoadConfig("")
	if err != nil {
		verbose("No configuration file found.")
	}

	// Logical
	if fDebug {
		fVerbose = true
		verbose("config: %#v", cnf)
	}

	// Various messages
	if cnf.APIKey != "" {
		verbose("Found API key!")
	} else {
		verbose("No API key!")
	}

	if cnf.DefaultProbe != 0 {
		verbose("Found default probe: %d\n", cnf.DefaultProbe)
	}

	// Allow overwrite of a few parameters
	if fPoolSize != 0 {
		cnf.ProbeSet.PoolSize = fPoolSize
	}
	if fAreaType != "" {
		cnf.ProbeSet.Type = fAreaType
	}
	if fAreaValue != "" {
		cnf.ProbeSet.Value = fAreaValue
	}

	// Check whether we have proxy authentication (from a separate config file)
	auth, err := setupProxyAuth()
	if err != nil {
		verbose("Invalid or no proxy auth credentials")
	}

	// If we want a logfile, open one for the API to log into
	if fLogfile != "" {
		mylog = openlog(fLogfile)
	}

	// Wondering whether to move to the Functional options pattern
	// cf. https://dave.cheney.net/2016/11/13/do-not-fear-first-class-functions
	client, err = atlas.NewClient(atlas.Config{
		APIKey:       cnf.APIKey,
		DefaultProbe: cnf.DefaultProbe,
		IsOneOff:     fIsOneOff,
		PoolSize:     cnf.ProbeSet.PoolSize,
		AreaType:     cnf.ProbeSet.Type,
		AreaValue:    cnf.ProbeSet.Value,
		ProxyAuth:    auth,
		Verbose:      fVerbose,
		Log:          mylog,
	})

	// No need to continue if this fails
	if err != nil {
		log.Fatalf("Error creating the Atlas client: %v", err)
	}

	if fWant4 {
		wantAF = Want4
	}

	if fWant6 {
		wantAF = Want6
	}

	// Both are fine
	if fWant4 && fWant6 {
		wantAF = WantBoth
	}

	// So is neither — common case
	if !fWant4 && !fWant6 {
		wantAF = WantBoth
	}

	debug("wantAF=%s", wantAF)
	return nil
}

// main is the starting point (and everything)
func main() {
	cli.VersionFlag = cli.BoolFlag{Name: "version, V"}

	cli.VersionPrinter = func(c *cli.Context) {
		fmt.Printf("API wrapper: %s Atlas API: %s\n", c.App.Version, atlas.GetVersion())
	}

	app := cli.NewApp()
	app.Name = "atlas"
	app.Usage = "RIPE Atlas CLI interface"
	app.Author = "Ollivier Robert <roberto@keltia.net>"
	app.Version = atlasVersion
	//app.HideVersion = true

	// General flags
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "format,f",
			Usage:       "specify output format (NOT IMPLEMENTED)",
			Destination: &fFormat,
		},
		cli.BoolFlag{
			Name:        "debug,D",
			Usage:       "debug mode",
			Destination: &fDebug,
		},
		cli.BoolFlag{
			Name:        "verbose,v",
			Usage:       "verbose mode",
			Destination: &fVerbose,
		},
		cli.StringFlag{
			Name:        "fields,F",
			Usage:       "specify which fields are wanted",
			Destination: &fFieldList,
		},
		cli.StringFlag{
			Name:        "include,I",
			Usage:       "specify whether objects should be expanded",
			Destination: &fInclude,
		},
		cli.StringFlag{
			Name:        "logfile,L",
			Usage:       "specify a log file",
			Destination: &fLogfile,
		},
		cli.BoolFlag{
			Name:        "mine,M",
			Usage:       "limit output to my objects",
			Destination: &fWantMine,
		},
		cli.StringFlag{
			Name:        "opt-fields,O",
			Usage:       "specify which optional fields are wanted",
			Destination: &fOptFields,
		},
		cli.StringFlag{
			Name:        "page-size,P",
			Usage:       "page size for results",
			Destination: &fPageSize,
		},

		cli.StringFlag{
			Name:        "sort,S",
			Usage:       "sort results",
			Destination: &fSortOrder,
		},
		cli.BoolTFlag{
			Name:        "1,is-oneoff",
			Usage:       "one-time measurement",
			Destination: &fIsOneOff,
		},
		cli.BoolFlag{
			Name:        "6, ipv6",
			Usage:       "Only IPv6",
			Destination: &fWant6,
		},
		cli.BoolFlag{
			Name:        "4, ipv4",
			Usage:       "Only IPv4",
			Destination: &fWant4,
		},
		// These are not global parameters but it makes sense to define them only once
		// and not in every cmd_* files.
		cli.IntFlag{
			Name:        "pool-size,N",
			Usage:       "Number of probes to request",
			Destination: &fPoolSize,
		},
		cli.StringFlag{
			Name:        "area-type",
			Usage:       "Set type for probes (area, country, etc.)",
			Destination: &fAreaType,
		},
		cli.StringFlag{
			Name:        "area-value",
			Usage:       "Value for the probe set (WW, West, etc.)",
			Destination: &fAreaValue,
		},
	}

	// Ensure -4 & -6 are treated properly & initialization is done
	app.Before = finalcheck

	sort.Sort(ByAlphabet(cliCommands))
	app.Commands = cliCommands
	app.Run(os.Args)
}
<commit_msg>Add -C as global flag to specify a country for probe sets.<commit_after>/*
This package is just a collection of use-case for the various aspects of the RIPE API.
Consider this both as an example on how to use the API and a testing tool for the API wrapper.
*/
package main

import (
	"fmt"
	"github.com/keltia/ripe-atlas"
	"github.com/urfave/cli"
	"log"
	"os"
	"sort"
)

var (
	// CLI specific options
	fDebug   bool
	fLogfile string
	fVerbose bool

	// See flag.go for details

	// Global API options
	fFieldList string
	fFormat    string
	fInclude   string
	fOptFields string
	fPageNum   string
	fPageSize  string
	fSortOrder string
	fWantMine  bool

	// Probe-specific ones
	fAllProbes bool
	fIsAnchor  bool

	// Common measurement ones
	fAllMeasurements bool
	fAsn             string
	fAsnV4           string
	fAsnV6           string
	fCountry         string
	fProtocol        string
	fMeasureType     string
	fWant4           bool
	fWant6           bool

	// Create measurements
	fBillTo    string
	fIsOneOff  bool
	fStartTime string
	fStopTime  string

	// HTTP
	fHTTPMethod  string
	fUserAgent   string
	fHTTPVersion string

	// DNS
	fBitCD         bool
	fDisableDNSSEC bool

	// Traceroute
	fMaxHops    int
	fPacketSize int

	// ProbeSet parameters
	fPoolSize  int
	fAreaType  string
	fAreaValue string

	// Our configuration file
	cnf *Config

	// All possible commands
	cliCommands []cli.Command

	client *atlas.Client

	// Our tiple-valued synthesis of fWant4/fWant6
	wantAF string
)

const (
	atlasVersion = "0.25"
	// MyName is the application name
	MyName = "ripe-atlas"

	// WantBoth is the way to ask for both IPv4 & IPv6.
	WantBoth = "64"

	// Want4 only 4
	Want4 = "4"
	// Want6 only 6
	Want6 = "6"
)

func openlog(fn string) *log.Logger {
	fh, err := os.OpenFile(fn, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("error: can not open logfile %s: %v", fn, err)
	}

	mylog := log.New(fh, "", log.LstdFlags)
	verbose("Logfile: %s %#v", fn, mylog)

	return mylog
}

// -4 & -6 are special, if neither is specified, then we turn both as true
// Check a few other things while we are here
func finalcheck(c *cli.Context) error {

	var (
		err   error
		mylog *log.Logger
	)

	// Load main configuration
	cnf, err = LoadConfig("")
	if err != nil {
		verbose("No configuration file found.")
	}

	// Logical
	if fDebug {
		fVerbose = true
		verbose("config: %#v", cnf)
	}

	// Various messages
	if cnf.APIKey != "" {
		verbose("Found API key!")
	} else {
		verbose("No API key!")
	}

	if cnf.DefaultProbe != 0 {
		verbose("Found default probe: %d\n", cnf.DefaultProbe)
	}

	// Allow overwrite of a few parameters
	if fPoolSize != 0 {
		cnf.ProbeSet.PoolSize = fPoolSize
	}
	if fAreaType != "" {
		cnf.ProbeSet.Type = fAreaType
	}
	if fAreaValue != "" {
		cnf.ProbeSet.Value = fAreaValue
	}

	// Check whether we have proxy authentication (from a separate config file)
	auth, err := setupProxyAuth()
	if err != nil {
		verbose("Invalid or no proxy auth credentials")
	}

	// If we want a logfile, open one for the API to log into
	if fLogfile != "" {
		mylog = openlog(fLogfile)
	}

	// Check whether the -C <country> was specified then override configuration
	if fCountry != "" {
		cnf.ProbeSet.Type  = "country"
		cnf.ProbeSet.Value = fCountry
	}

	// Wondering whether to move to the Functional options pattern
	// cf. https://dave.cheney.net/2016/11/13/do-not-fear-first-class-functions
	client, err = atlas.NewClient(atlas.Config{
		APIKey:       cnf.APIKey,
		DefaultProbe: cnf.DefaultProbe,
		IsOneOff:     fIsOneOff,
		PoolSize:     cnf.ProbeSet.PoolSize,
		AreaType:     cnf.ProbeSet.Type,
		AreaValue:    cnf.ProbeSet.Value,
		ProxyAuth:    auth,
		Verbose:      fVerbose,
		Log:          mylog,
	})

	// No need to continue if this fails
	if err != nil {
		log.Fatalf("Error creating the Atlas client: %v", err)
	}

	if fWant4 {
		wantAF = Want4
	}

	if fWant6 {
		wantAF = Want6
	}

	// Both are fine
	if fWant4 && fWant6 {
		wantAF = WantBoth
	}

	// So is neither — common case
	if !fWant4 && !fWant6 {
		wantAF = WantBoth
	}

	debug("wantAF=%s", wantAF)
	return nil
}

// main is the starting point (and everything)
func main() {
	cli.VersionFlag = cli.BoolFlag{Name: "version, V"}

	cli.VersionPrinter = func(c *cli.Context) {
		fmt.Printf("API wrapper: %s Atlas API: %s\n", c.App.Version, atlas.GetVersion())
	}

	app := cli.NewApp()
	app.Name = "atlas"
	app.Usage = "RIPE Atlas CLI interface"
	app.Author = "Ollivier Robert <roberto@keltia.net>"
	app.Version = atlasVersion
	//app.HideVersion = true

	// General flags
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "format,f",
			Usage:       "specify output format (NOT IMPLEMENTED)",
			Destination: &fFormat,
		},
		cli.BoolFlag{
			Name:        "debug,D",
			Usage:       "debug mode",
			Destination: &fDebug,
		},
		cli.BoolFlag{
			Name:        "verbose,v",
			Usage:       "verbose mode",
			Destination: &fVerbose,
		},
		cli.StringFlag{
			Name:        "fields,F",
			Usage:       "specify which fields are wanted",
			Destination: &fFieldList,
		},
		cli.StringFlag{
			Name:        "include,I",
			Usage:       "specify whether objects should be expanded",
			Destination: &fInclude,
		},
		cli.StringFlag{
			Name:        "logfile,L",
			Usage:       "specify a log file",
			Destination: &fLogfile,
		},
		cli.BoolFlag{
			Name:        "mine,M",
			Usage:       "limit output to my objects",
			Destination: &fWantMine,
		},
		cli.StringFlag{
			Name:        "opt-fields,O",
			Usage:       "specify which optional fields are wanted",
			Destination: &fOptFields,
		},
		cli.StringFlag{
			Name:        "page-size,P",
			Usage:       "page size for results",
			Destination: &fPageSize,
		},

		cli.StringFlag{
			Name:        "sort,S",
			Usage:       "sort results",
			Destination: &fSortOrder,
		},
		cli.BoolTFlag{
			Name:        "1,is-oneoff",
			Usage:       "one-time measurement",
			Destination: &fIsOneOff,
		},
		cli.BoolFlag{
			Name:        "6, ipv6",
			Usage:       "Only IPv6",
			Destination: &fWant6,
		},
		cli.BoolFlag{
			Name:        "4, ipv4",
			Usage:       "Only IPv4",
			Destination: &fWant4,
		},
		// These are not global parameters but it makes sense to define them only once
		// and not in every cmd_* files.
		cli.IntFlag{
			Name:        "pool-size,N",
			Usage:       "Number of probes to request",
			Destination: &fPoolSize,
		},
		cli.StringFlag{
			Name:        "area-type",
			Usage:       "Set type for probes (area, country, etc.)",
			Destination: &fAreaType,
		},
		cli.StringFlag{
			Name:        "area-value",
			Usage:       "Value for the probe set (WW, West, etc.)",
			Destination: &fAreaValue,
		},
		cli.StringFlag{
			Name:        "--country,C",
			Usage:       "Short cut to specify a country",
			Destination: &fCountry,
		},
	}

	// Ensure -4 & -6 are treated properly & initialization is done
	app.Before = finalcheck

	sort.Sort(ByAlphabet(cliCommands))
	app.Commands = cliCommands
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package cmd

import (
	"github.com/cheekybits/is"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

/*
 =====================
  Environment Helpers
 =====================
*/

func CleanEnv() {
	// apparently os.Unsetenv doesn't exist in the version of go I'm using
	os.Setenv("BIGV_CONFIG_DIR", "")
	os.Setenv("BIGV_USER", "")
	os.Setenv("BIGV_ACCOUNT", "")
	os.Setenv("BIGV_ENDPOINT", "")
	os.Setenv("BIGV_AUTH_ENDPOINT", "")
	os.Setenv("BIGV_DEBUG_LEVEL", "")
}

func JunkEnv() {
	os.Setenv("BIGV_CONFIG_DIR", "junk-env-config-dir")
	os.Setenv("BIGV_USER", "junk-env-user")
	os.Setenv("BIGV_ACCOUNT", "junk-env-account")
	os.Setenv("BIGV_ENDPOINT", "junk-env-endpoint")
	os.Setenv("BIGV_AUTH_ENDPOINT", "junk-env-auth-endpoint")
	os.Setenv("BIGV_DEBUG_LEVEL", "junk-env-debug-level")
}

func FixtureEnv() (fixture map[string]string) {
	fixture = map[string]string{

		"endpoint":      "https://fixture.env.localhost.local",
		"user":          "fixture-env-user",
		"account":       "fixture-env-account",
		"auth-endpoint": "https://fixture.env.auth.localhost.local",
		"debug-level":   "fixture-env-debug-level",
	}
	os.Setenv("BIGV_CONFIG_DIR", fixture["config-dir"])
	os.Setenv("BIGV_USER", fixture["user"])
	os.Setenv("BIGV_ACCOUNT", fixture["account"])
	os.Setenv("BIGV_ENDPOINT", fixture["endpoint"])
	os.Setenv("BIGV_AUTH_ENDPOINT", fixture["auth-endpoint"])
	os.Setenv("BIGV_DEBUG_LEVEL", fixture["debug-level"])
	return fixture
}

/*
 ===================
  Directory Helpers
 ===================
*/

func CleanDir() (name string) {
	dir, err := ioutil.TempDir("", "bigv-client-test")
	if err != nil {
		panic("Couldn't create test dir.")
	}

	return dir

}

func JunkDir() (name string) {
	junk := map[string]string{
		"endpoint":      "https://junk.dir.localhost.local",
		"user":          "junk-dir-user",
		"account":       "junk-dir-account",
		"auth-endpoint": "https://junk.dir.auth.localhost.local",
		"debug-level":   "junk-dir-debug-level",
	}

	dir, err := ioutil.TempDir("", "bigv-client-test")
	if err != nil {
		panic("Couldn't create test dir.")
	}

	for name, value := range junk {
		ioutil.WriteFile(filepath.Join(dir, name), []byte(value), 0600)
	}
	return dir
}

func FixtureDir() (dir string, fixture map[string]string) {
	fixture = map[string]string{
		"endpoint":      "https://fixture.dir.localhost.local",
		"user":          "fixture-dir-user",
		"account":       "fixture-dir-account",
		"auth-endpoint": "https://fixture.dir.auth.localhost.local",
		"debug-level":   "fixture-dir-debug-level",
	}

	dir, err := ioutil.TempDir("", "bigv-client-test")
	if err != nil {
		panic("Couldn't create test dir.")
	}

	for name, value := range fixture {
		ioutil.WriteFile(filepath.Join(dir, name), []byte(value), 0600)
	}
	return dir, fixture
}

/*
 =========================
  Environment-based Tests
 =========================
*/

func TestDefaultConfigDir(t *testing.T) {
	is := is.New(t)

	CleanEnv()

	config := NewConfig("", nil)
	expected := filepath.Join(os.Getenv("HOME"), "/.go-bigv")
	is.Equal(expected, config.Dir)
}

func TestEnvConfigDir(t *testing.T) {
	is := is.New(t)

	CleanEnv()

	expected := "/tmp"
	os.Setenv("BIGV_CONFIG_DIR", expected)

	config := NewConfig("", nil)
	is.Equal(expected, config.Dir)
}

func TestPassedConfigDir(t *testing.T) {
	is := is.New(t)

	JunkEnv()

	expected := "/home"
	config := NewConfig(expected, nil)
	is.Equal(expected, config.Dir)
}

/*
 ================
  Defaulting Tests
 ================
*/
// Tests to make sure we get the right defaults given the environment

func TestConfigDefaultsCleanEnv(t *testing.T) {
	is := is.New(t)

	CleanEnv()
	dir := CleanDir()

	config := NewConfig(dir, nil)

	// TODO(telyn): Update me when we move to api.bigv.io
	is.Equal("https://uk0.bigv.io", config.Get("endpoint"))
	is.Equal("https://auth.bytemark.co.uk", config.Get("auth-endpoint"))

	is.Equal("", config.Get("user"))
	is.Equal("", config.Get("account"))

	os.RemoveAll(dir)
}

func TestConfigDefaultsWithEnvUser(t *testing.T) {
	is := is.New(t)

	CleanEnv()
	dir := CleanDir()

	expected := "test-username"
	os.Setenv("BIGV_USER", expected)

	config := NewConfig(dir, nil)

	is.Equal("https://uk0.bigv.io", config.Get("endpoint"))
	is.Equal("https://auth.bytemark.co.uk", config.Get("auth-endpoint"))
	is.Equal(expected, config.Get("user"))
	is.Equal(expected, config.Get("account"))

	os.RemoveAll(dir)
}

func TestConfigDefaultsFixtureEnv(t *testing.T) {
	is := is.New(t)

	fixture := FixtureEnv()
	dir := CleanDir()

	config := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))
	os.RemoveAll(dir)
}

/*
 =================
  Directory Tests
 =================
*/
// Tests to ensure that we get given the value in the directory if we didn't specify it as a flag

func TestConfigDir(t *testing.T) {
	is := is.New(t)

	JunkEnv()
	dir, fixture := FixtureDir()

	config := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))

	os.RemoveAll(dir)
}

/*
 ============
  Flag Tests
 ============
*/

// TODO(telyn): no i don't want to write flag tests today

/*
 ===========
  Set Tests
 ===========
*/

func TestSet(t *testing.T) {
	is := is.New(t)

	CleanEnv()
	dir, fixture := FixtureDir()
	config := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))

	config.Set("user", "test-user")
	fixture["user"] = "test-user"

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))
	os.RemoveAll(dir)
}

func TestSetPersistent(t *testing.T) {
	is := is.New(t)

	CleanEnv()
	dir, fixture := FixtureDir()
	config := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))

	config.SetPersistent("user", "test-user")
	fixture["user"] = "test-user"

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))

	CleanEnv() // in case for some wacky reason I write to the environment
	//create a new config (blanking the memo) to test the file in the directory has changed.
	config2 := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config2.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config2.Get("auth-endpoint"))
	is.Equal(fixture["user"], config2.Get("user"))
	is.Equal(fixture["account"], config2.Get("account"))
	is.Equal(fixture["debug-level"], config2.Get("debug-level"))

	os.RemoveAll(dir)
}
<commit_msg>Renamed tests in config.go to avoid clashes<commit_after>package cmd

import (
	"github.com/cheekybits/is"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

/*
 =====================
  Environment Helpers
 =====================
*/

func CleanEnv() {
	// apparently os.Unsetenv doesn't exist in the version of go I'm using
	os.Setenv("BIGV_CONFIG_DIR", "")
	os.Setenv("BIGV_USER", "")
	os.Setenv("BIGV_ACCOUNT", "")
	os.Setenv("BIGV_ENDPOINT", "")
	os.Setenv("BIGV_AUTH_ENDPOINT", "")
	os.Setenv("BIGV_DEBUG_LEVEL", "")
}

func JunkEnv() {
	os.Setenv("BIGV_CONFIG_DIR", "junk-env-config-dir")
	os.Setenv("BIGV_USER", "junk-env-user")
	os.Setenv("BIGV_ACCOUNT", "junk-env-account")
	os.Setenv("BIGV_ENDPOINT", "junk-env-endpoint")
	os.Setenv("BIGV_AUTH_ENDPOINT", "junk-env-auth-endpoint")
	os.Setenv("BIGV_DEBUG_LEVEL", "junk-env-debug-level")
}

func FixtureEnv() (fixture map[string]string) {
	fixture = map[string]string{

		"endpoint":      "https://fixture.env.localhost.local",
		"user":          "fixture-env-user",
		"account":       "fixture-env-account",
		"auth-endpoint": "https://fixture.env.auth.localhost.local",
		"debug-level":   "fixture-env-debug-level",
	}
	os.Setenv("BIGV_CONFIG_DIR", fixture["config-dir"])
	os.Setenv("BIGV_USER", fixture["user"])
	os.Setenv("BIGV_ACCOUNT", fixture["account"])
	os.Setenv("BIGV_ENDPOINT", fixture["endpoint"])
	os.Setenv("BIGV_AUTH_ENDPOINT", fixture["auth-endpoint"])
	os.Setenv("BIGV_DEBUG_LEVEL", fixture["debug-level"])
	return fixture
}

/*
 ===================
  Directory Helpers
 ===================
*/

func CleanDir() (name string) {
	dir, err := ioutil.TempDir("", "bigv-client-test")
	if err != nil {
		panic("Couldn't create test dir.")
	}

	return dir

}

func JunkDir() (name string) {
	junk := map[string]string{
		"endpoint":      "https://junk.dir.localhost.local",
		"user":          "junk-dir-user",
		"account":       "junk-dir-account",
		"auth-endpoint": "https://junk.dir.auth.localhost.local",
		"debug-level":   "junk-dir-debug-level",
	}

	dir, err := ioutil.TempDir("", "bigv-client-test")
	if err != nil {
		panic("Couldn't create test dir.")
	}

	for name, value := range junk {
		ioutil.WriteFile(filepath.Join(dir, name), []byte(value), 0600)
	}
	return dir
}

func FixtureDir() (dir string, fixture map[string]string) {
	fixture = map[string]string{
		"endpoint":      "https://fixture.dir.localhost.local",
		"user":          "fixture-dir-user",
		"account":       "fixture-dir-account",
		"auth-endpoint": "https://fixture.dir.auth.localhost.local",
		"debug-level":   "fixture-dir-debug-level",
	}

	dir, err := ioutil.TempDir("", "bigv-client-test")
	if err != nil {
		panic("Couldn't create test dir.")
	}

	for name, value := range fixture {
		ioutil.WriteFile(filepath.Join(dir, name), []byte(value), 0600)
	}
	return dir, fixture
}

/*
 =========================
  Environment-based Tests
 =========================
*/

func TestConfigDefaultConfigDir(t *testing.T) {
	is := is.New(t)

	CleanEnv()

	config := NewConfig("", nil)
	expected := filepath.Join(os.Getenv("HOME"), "/.go-bigv")
	is.Equal(expected, config.Dir)
}

func TestConfigEnvConfigDir(t *testing.T) {
	is := is.New(t)

	CleanEnv()

	expected := "/tmp"
	os.Setenv("BIGV_CONFIG_DIR", expected)

	config := NewConfig("", nil)
	is.Equal(expected, config.Dir)
}

func TestConfigPassedConfigDir(t *testing.T) {
	is := is.New(t)

	JunkEnv()

	expected := "/home"
	config := NewConfig(expected, nil)
	is.Equal(expected, config.Dir)
}

/*
 ================
  Defaulting Tests
 ================
*/
// Tests to make sure we get the right defaults given the environment

func TestConfigConfigDefaultsCleanEnv(t *testing.T) {
	is := is.New(t)

	CleanEnv()
	dir := CleanDir()

	config := NewConfig(dir, nil)

	// TODO(telyn): Update me when we move to api.bigv.io
	is.Equal("https://uk0.bigv.io", config.Get("endpoint"))
	is.Equal("https://auth.bytemark.co.uk", config.Get("auth-endpoint"))

	is.Equal("", config.Get("user"))
	is.Equal("", config.Get("account"))

	os.RemoveAll(dir)
}

func TestConfigDefaultsWithEnvUser(t *testing.T) {
	is := is.New(t)

	CleanEnv()
	dir := CleanDir()

	expected := "test-username"
	os.Setenv("BIGV_USER", expected)

	config := NewConfig(dir, nil)

	is.Equal("https://uk0.bigv.io", config.Get("endpoint"))
	is.Equal("https://auth.bytemark.co.uk", config.Get("auth-endpoint"))
	is.Equal(expected, config.Get("user"))
	is.Equal(expected, config.Get("account"))

	os.RemoveAll(dir)
}

func TestConfigDefaultsFixtureEnv(t *testing.T) {
	is := is.New(t)

	fixture := FixtureEnv()
	dir := CleanDir()

	config := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))
	os.RemoveAll(dir)
}

/*
 =================
  Directory Tests
 =================
*/
// Tests to ensure that we get given the value in the directory if we didn't specify it as a flag

func TestConfigDir(t *testing.T) {
	is := is.New(t)

	JunkEnv()
	dir, fixture := FixtureDir()

	config := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))

	os.RemoveAll(dir)
}

/*
 ============
  Flag Tests
 ============
*/

// TODO(telyn): no i don't want to write flag tests today

/*
 ===========
  Set Tests
 ===========
*/

func TestConfigSet(t *testing.T) {
	is := is.New(t)

	CleanEnv()
	dir, fixture := FixtureDir()
	config := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))

	config.Set("user", "test-user")
	fixture["user"] = "test-user"

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))
	os.RemoveAll(dir)
}

func TestConfigSetPersistent(t *testing.T) {
	is := is.New(t)

	CleanEnv()
	dir, fixture := FixtureDir()
	config := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))

	config.SetPersistent("user", "test-user")
	fixture["user"] = "test-user"

	is.Equal(fixture["endpoint"], config.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config.Get("auth-endpoint"))
	is.Equal(fixture["user"], config.Get("user"))
	is.Equal(fixture["account"], config.Get("account"))
	is.Equal(fixture["debug-level"], config.Get("debug-level"))

	CleanEnv() // in case for some wacky reason I write to the environment
	//create a new config (blanking the memo) to test the file in the directory has changed.
	config2 := NewConfig(dir, nil)

	is.Equal(fixture["endpoint"], config2.Get("endpoint"))
	is.Equal(fixture["auth-endpoint"], config2.Get("auth-endpoint"))
	is.Equal(fixture["user"], config2.Get("user"))
	is.Equal(fixture["account"], config2.Get("account"))
	is.Equal(fixture["debug-level"], config2.Get("debug-level"))

	os.RemoveAll(dir)
}
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"fmt"
	"log"
	"net"
	"os"
	"reflect"
	"strings"

	"github.com/exoscale/egoscale"
	"github.com/spf13/cobra"
)

// apiCmd represents the api command
var apiCmd = &cobra.Command{
	Use:   "api",
	Short: "Exoscale api",
}

const userDocumentationURL = "http://cloudstack.apache.org/api/apidocs-4.4/user/%s.html"

// global flags
var apiDebug bool
var apiDryRun bool

func init() {
	RootCmd.AddCommand(apiCmd)
	buildCommands(methods)
	apiCmd.PersistentFlags().BoolVarP(&apiDebug, "debug", "d", false, "debug mode on")
	apiCmd.PersistentFlags().BoolVarP(&apiDryRun, "dry-run", "D", false, "produce a cURL ready URL")
	if err := apiCmd.PersistentFlags().MarkHidden("dry-run"); err != nil {
		log.Fatal(err)
	}
}

func buildCommands(methods []category) {
	for _, category := range methods {

		cmd := cobra.Command{
			Use:     category.name,
			Aliases: category.alias,
			Short:   category.doc,
		}

		apiCmd.AddCommand(&cmd)

		for i := range category.cmd {
			s := category.cmd[i]

			realName := cs.APIName(s.command)
			description := cs.APIDescription(s.command)

			url := userDocumentationURL

			name := realName
			if s.name != "" {
				name = s.name
			}

			hiddenCMD := cobra.Command{
				Use:    realName,
				Short:  description,
				Long:   fmt.Sprintf("%s <%s>", description, fmt.Sprintf(url, realName)),
				Hidden: true,
			}

			subCMD := cobra.Command{
				Use:     name,
				Short:   description,
				Long:    fmt.Sprintf("%s <%s>", description, fmt.Sprintf(url, realName)),
				Aliases: append(s.alias, realName),
			}

			buildFlags(s.command, &subCMD)
			buildFlags(s.command, &hiddenCMD)

			runCMD := func(cmd *cobra.Command, args []string) error {

				// Show request and quit DEBUG
				if apiDebug {
					payload, err := cs.Payload(s.command)
					if err != nil {
						log.Fatal(err)
					}
					if _, err = fmt.Fprintf(os.Stdout, "%s\\\n?%s", cs.Endpoint, strings.Replace(payload, "&", "\\\n&", -1)); err != nil {
						log.Fatal(err)
					}

					if _, err := fmt.Fprintln(os.Stdout); err != nil {
						log.Fatal(err)
					}
					os.Exit(0)
				}

				if apiDryRun {
					payload, err := cs.Payload(s.command)
					if err != nil {
						log.Fatal(err)
					}
					signature, err := cs.Sign(payload)
					if err != nil {
						log.Fatal(err)
					}

					if _, err := fmt.Fprintf(os.Stdout, "%s?%s\n", cs.Endpoint, signature); err != nil {
						log.Fatal(err)
					}
					os.Exit(0)
				}

				// End debug section

				resp, err := cs.RequestWithContext(gContext, s.command)
				if err != nil {
					return err
				}

				data, err := json.MarshalIndent(&resp, "", "  ")
				if err != nil {
					return err
				}

				fmt.Println(string(data))

				return nil
			}

			subCMD.RunE = runCMD
			hiddenCMD.RunE = runCMD

			subCMD.Flags().SortFlags = false
			hiddenCMD.Flags().SortFlags = false

			cmd.AddCommand(&subCMD)
			apiCmd.AddCommand(&hiddenCMD)
		}
	}
}

func buildFlags(method egoscale.Command, cmd *cobra.Command) {
	val := reflect.ValueOf(method)
	// we've got a pointer
	value := val.Elem()

	if value.Kind() != reflect.Struct {
		log.Fatalf("struct was expected")
		return
	}

	ty := value.Type()
	for i := 0; i < value.NumField(); i++ {
		field := ty.Field(i)

		if field.Name == "_" {
			continue
		}

		// XXX refactor with request.go
		var argName string
		required := false
		if json, ok := field.Tag.Lookup("json"); ok {
			tags := strings.Split(json, ",")
			argName = tags[0]
			required = true
			for _, tag := range tags {
				if tag == "omitempty" {
					required = false
				}
			}
			if argName == "" || argName == "omitempty" {
				continue
			}
		}

		description := ""
		if required {
			description = "required"
		}

		if doc, ok := field.Tag.Lookup("doc"); ok {
			if description != "" {
				description = fmt.Sprintf("[%s] %s", description, doc)
			} else {
				description = doc
			}
		}

		val := value.Field(i)
		addr := val.Addr().Interface()
		switch val.Kind() {
		case reflect.Bool:
			cmd.Flags().BoolVarP(addr.(*bool), argName, "", false, description)
		case reflect.Int:
			cmd.Flags().IntVarP(addr.(*int), argName, "", 0, description)
		case reflect.Int64:
			cmd.Flags().Int64VarP(addr.(*int64), argName, "", 0, description)
		case reflect.Uint:
			cmd.Flags().UintVarP(addr.(*uint), argName, "", 0, description)
		case reflect.Uint64:
			cmd.Flags().Uint64VarP(addr.(*uint64), argName, "", 0, description)
		case reflect.Float64:
			cmd.Flags().Float64VarP(addr.(*float64), argName, "", 0, description)
		case reflect.Int16:
			typeName := field.Type.Name()
			if typeName != "int16" {
				cmd.Flags().VarP(&intTypeGeneric{addr: addr, base: 10, bitSize: 16, typ: field.Type}, argName, "", description)
			} else {
				cmd.Flags().Int16VarP(addr.(*int16), argName, "", 0, description)
			}
		case reflect.Uint8:
			cmd.Flags().Uint8VarP(addr.(*uint8), argName, "", 0, description)
		case reflect.Uint16:
			cmd.Flags().Uint16VarP(addr.(*uint16), argName, "", 0, description)
		case reflect.String:
			typeName := field.Type.Name()
			if typeName != "string" {
				cmd.Flags().VarP(&stringerTypeGeneric{addr: addr, typ: field.Type}, argName, "", description)
			} else {
				cmd.Flags().StringVarP(addr.(*string), argName, "", "", description)
			}
		case reflect.Slice:
			switch field.Type.Elem().Kind() {
			case reflect.Uint8:
				ip := addr.(*net.IP)
				if *ip == nil || (*ip).Equal(net.IPv4zero) || (*ip).Equal(net.IPv6zero) {
					cmd.Flags().IPP(argName, "", *ip, description)
				}
			case reflect.String:
				cmd.Flags().StringSliceP(argName, "", *addr.(*[]string), description)
			default:
				switch field.Type.Elem() {
				case reflect.TypeOf(egoscale.ResourceTag{}):
					cmd.Flags().VarP(&tagGeneric{addr.(*[]egoscale.ResourceTag)}, argName, "", description)
				case reflect.TypeOf(egoscale.CIDR{}):
					cmd.Flags().VarP(&cidrListGeneric{addr.(*[]egoscale.CIDR)}, argName, "", description)
				case reflect.TypeOf(egoscale.UUID{}):
					cmd.Flags().VarP(&uuidListGeneric{addr.(*[]egoscale.UUID)}, argName, "", description)
				default:
					//log.Printf("[SKIP] Slice of %s is not supported!", field.Name)
				}
			}
		case reflect.Map:
			key := reflect.TypeOf(val.Interface()).Key()
			switch key.Kind() {
			case reflect.String:
				cmd.Flags().VarP(&mapGeneric{addr.(*map[string]string)}, argName, "", description)
			default:
				log.Printf("[SKIP] Type map for %s is not supported!", field.Name)
			}
		case reflect.Ptr:
			switch field.Type.Elem() {
			case reflect.TypeOf(true):
				cmd.Flags().VarP(&boolFlag{(addr.(**bool))}, argName, "", description)
			case reflect.TypeOf(egoscale.CIDR{}):
				cmd.Flags().VarP(&cidr{addr.(**egoscale.CIDR)}, argName, "", description)
			case reflect.TypeOf(egoscale.UUID{}):
				cmd.Flags().VarP(&uuid{addr.(**egoscale.UUID)}, argName, "", description)

			default:
				log.Printf("[SKIP] Ptr type of %s is not supported!", field.Name)
			}
		default:
			log.Printf("[SKIP] Type of %s is not supported! %v", field.Name, val.Kind())
		}
	}
}
<commit_msg>Exo: fix api payload<commit_after>package cmd

import (
	"encoding/json"
	"fmt"
	"log"
	"net"
	"os"
	"reflect"
	"strings"

	"github.com/exoscale/egoscale"
	"github.com/spf13/cobra"
)

// apiCmd represents the api command
var apiCmd = &cobra.Command{
	Use:   "api",
	Short: "Exoscale api",
}

const userDocumentationURL = "http://cloudstack.apache.org/api/apidocs-4.4/user/%s.html"

// global flags
var apiDebug bool
var apiDryRun bool

func init() {
	RootCmd.AddCommand(apiCmd)
	buildCommands(methods)
	apiCmd.PersistentFlags().BoolVarP(&apiDebug, "debug", "d", false, "debug mode on")
	apiCmd.PersistentFlags().BoolVarP(&apiDryRun, "dry-run", "D", false, "produce a cURL ready URL")
	if err := apiCmd.PersistentFlags().MarkHidden("dry-run"); err != nil {
		log.Fatal(err)
	}
}

func buildCommands(methods []category) {
	for _, category := range methods {

		cmd := cobra.Command{
			Use:     category.name,
			Aliases: category.alias,
			Short:   category.doc,
		}

		apiCmd.AddCommand(&cmd)

		for i := range category.cmd {
			s := category.cmd[i]

			realName := cs.APIName(s.command)
			description := cs.APIDescription(s.command)

			url := userDocumentationURL

			name := realName
			if s.name != "" {
				name = s.name
			}

			hiddenCMD := cobra.Command{
				Use:    realName,
				Short:  description,
				Long:   fmt.Sprintf("%s <%s>", description, fmt.Sprintf(url, realName)),
				Hidden: true,
			}

			subCMD := cobra.Command{
				Use:     name,
				Short:   description,
				Long:    fmt.Sprintf("%s <%s>", description, fmt.Sprintf(url, realName)),
				Aliases: append(s.alias, realName),
			}

			buildFlags(s.command, &subCMD)
			buildFlags(s.command, &hiddenCMD)

			runCMD := func(cmd *cobra.Command, args []string) error {

				// Show request and quit DEBUG
				if apiDebug {
					payload, err := cs.Payload(s.command)
					if err != nil {
						log.Fatal(err)
					}
					qs := payload.Encode()
					if _, err = fmt.Fprintf(os.Stdout, "%s\\\n?%s", cs.Endpoint, strings.Replace(qs, "&", "\\\n&", -1)); err != nil {
						log.Fatal(err)
					}

					if _, err := fmt.Fprintln(os.Stdout); err != nil {
						log.Fatal(err)
					}
					os.Exit(0)
				}

				if apiDryRun {
					payload, err := cs.Payload(s.command)
					if err != nil {
						log.Fatal(err)
					}
					signature, err := cs.Sign(payload)
					if err != nil {
						log.Fatal(err)
					}

					if _, err := fmt.Fprintf(os.Stdout, "%s?%s\n", cs.Endpoint, signature); err != nil {
						log.Fatal(err)
					}
					os.Exit(0)
				}

				// End debug section

				resp, err := cs.RequestWithContext(gContext, s.command)
				if err != nil {
					return err
				}

				data, err := json.MarshalIndent(&resp, "", "  ")
				if err != nil {
					return err
				}

				fmt.Println(string(data))

				return nil
			}

			subCMD.RunE = runCMD
			hiddenCMD.RunE = runCMD

			subCMD.Flags().SortFlags = false
			hiddenCMD.Flags().SortFlags = false

			cmd.AddCommand(&subCMD)
			apiCmd.AddCommand(&hiddenCMD)
		}
	}
}

func buildFlags(method egoscale.Command, cmd *cobra.Command) {
	val := reflect.ValueOf(method)
	// we've got a pointer
	value := val.Elem()

	if value.Kind() != reflect.Struct {
		log.Fatalf("struct was expected")
		return
	}

	ty := value.Type()
	for i := 0; i < value.NumField(); i++ {
		field := ty.Field(i)

		if field.Name == "_" {
			continue
		}

		// XXX refactor with request.go
		var argName string
		required := false
		if json, ok := field.Tag.Lookup("json"); ok {
			tags := strings.Split(json, ",")
			argName = tags[0]
			required = true
			for _, tag := range tags {
				if tag == "omitempty" {
					required = false
				}
			}
			if argName == "" || argName == "omitempty" {
				continue
			}
		}

		description := ""
		if required {
			description = "required"
		}

		if doc, ok := field.Tag.Lookup("doc"); ok {
			if description != "" {
				description = fmt.Sprintf("[%s] %s", description, doc)
			} else {
				description = doc
			}
		}

		val := value.Field(i)
		addr := val.Addr().Interface()
		switch val.Kind() {
		case reflect.Bool:
			cmd.Flags().BoolVarP(addr.(*bool), argName, "", false, description)
		case reflect.Int:
			cmd.Flags().IntVarP(addr.(*int), argName, "", 0, description)
		case reflect.Int64:
			cmd.Flags().Int64VarP(addr.(*int64), argName, "", 0, description)
		case reflect.Uint:
			cmd.Flags().UintVarP(addr.(*uint), argName, "", 0, description)
		case reflect.Uint64:
			cmd.Flags().Uint64VarP(addr.(*uint64), argName, "", 0, description)
		case reflect.Float64:
			cmd.Flags().Float64VarP(addr.(*float64), argName, "", 0, description)
		case reflect.Int16:
			typeName := field.Type.Name()
			if typeName != "int16" {
				cmd.Flags().VarP(&intTypeGeneric{addr: addr, base: 10, bitSize: 16, typ: field.Type}, argName, "", description)
			} else {
				cmd.Flags().Int16VarP(addr.(*int16), argName, "", 0, description)
			}
		case reflect.Uint8:
			cmd.Flags().Uint8VarP(addr.(*uint8), argName, "", 0, description)
		case reflect.Uint16:
			cmd.Flags().Uint16VarP(addr.(*uint16), argName, "", 0, description)
		case reflect.String:
			typeName := field.Type.Name()
			if typeName != "string" {
				cmd.Flags().VarP(&stringerTypeGeneric{addr: addr, typ: field.Type}, argName, "", description)
			} else {
				cmd.Flags().StringVarP(addr.(*string), argName, "", "", description)
			}
		case reflect.Slice:
			switch field.Type.Elem().Kind() {
			case reflect.Uint8:
				ip := addr.(*net.IP)
				if *ip == nil || (*ip).Equal(net.IPv4zero) || (*ip).Equal(net.IPv6zero) {
					cmd.Flags().IPP(argName, "", *ip, description)
				}
			case reflect.String:
				cmd.Flags().StringSliceP(argName, "", *addr.(*[]string), description)
			default:
				switch field.Type.Elem() {
				case reflect.TypeOf(egoscale.ResourceTag{}):
					cmd.Flags().VarP(&tagGeneric{addr.(*[]egoscale.ResourceTag)}, argName, "", description)
				case reflect.TypeOf(egoscale.CIDR{}):
					cmd.Flags().VarP(&cidrListGeneric{addr.(*[]egoscale.CIDR)}, argName, "", description)
				case reflect.TypeOf(egoscale.UUID{}):
					cmd.Flags().VarP(&uuidListGeneric{addr.(*[]egoscale.UUID)}, argName, "", description)
				default:
					//log.Printf("[SKIP] Slice of %s is not supported!", field.Name)
				}
			}
		case reflect.Map:
			key := reflect.TypeOf(val.Interface()).Key()
			switch key.Kind() {
			case reflect.String:
				cmd.Flags().VarP(&mapGeneric{addr.(*map[string]string)}, argName, "", description)
			default:
				log.Printf("[SKIP] Type map for %s is not supported!", field.Name)
			}
		case reflect.Ptr:
			switch field.Type.Elem() {
			case reflect.TypeOf(true):
				cmd.Flags().VarP(&boolFlag{(addr.(**bool))}, argName, "", description)
			case reflect.TypeOf(egoscale.CIDR{}):
				cmd.Flags().VarP(&cidr{addr.(**egoscale.CIDR)}, argName, "", description)
			case reflect.TypeOf(egoscale.UUID{}):
				cmd.Flags().VarP(&uuid{addr.(**egoscale.UUID)}, argName, "", description)

			default:
				log.Printf("[SKIP] Ptr type of %s is not supported!", field.Name)
			}
		default:
			log.Printf("[SKIP] Type of %s is not supported! %v", field.Name, val.Kind())
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"runtime"

	"github.com/livesense-inc/fanlin/lib/conf"
	"github.com/livesense-inc/fanlin/lib/handler"
	"github.com/livesense-inc/fanlin/lib/logger"
	"github.com/sirupsen/logrus"
)

var confList = []string{
	"/etc/fanlin.json",
	"/etc/fanlin.cnf",
	"/etc/fanlin.conf",
	"/usr/local/etc/fanlin.json",
	"/usr/local/etc/fanlin.cnf",
	"/usr/local/etc/fanlin.conf",
	"/usr/local/fanlin/fanlin.json",
	"/usr/local/fanlin.json",
	"/usr/local/fanlin.conf",
	"./fanlin.json",
	"./fanlin.cnf",
	"./fanlin.conf",
	"./conf.json",
	"~/.fanlin.json",
	"~/.fanlin.cnf",
}

var (
	buildVersion string
	buildHash    string
	buildDate    string
	goversion    string
)

var (
	vOption bool
)

func showVersion() {
	fmt.Println()
	fmt.Println("build version: ", buildVersion)
	fmt.Println("build hash: ", buildVersion)
	fmt.Println("build date: ", buildDate)
	fmt.Println("GO version: ", goversion)
	os.Exit(128)
}

func main() {
	conf := func() *configure.Conf {
		for _, confName := range confList {
			conf := configure.NewConfigure(confName)
			if conf != nil {
				return conf
			}
		}
		return nil
	}()
	if conf == nil {
		log.Fatalln("Can not read configure.")
	}

	notFoundImagePath := flag.String("nfi", conf.NotFoundImagePath(), "not found image path")
	errorLogPath := flag.String("err", conf.ErrorLogPath(), "error log path")
	accessLogPath := flag.String("log", conf.AccessLogPath(), "access log path")
	port := flag.Int("p", conf.Port(), "port")
	port = flag.Int("port", conf.Port(), "port")
	localImagePath := flag.String("li", conf.LocalImagePath(), "local image path")
	maxProcess := flag.Int("cpu", conf.MaxProcess(), "max process.")
	debug := flag.Bool("debug", false, "debug mode.")
	flag.BoolVar(&vOption, "v", false, "version")
	flag.Parse()

	if vOption {
		showVersion()
	}

	conf.Set("404_img_path", *notFoundImagePath)
	conf.Set("error_log_path", *errorLogPath)
	conf.Set("access_log_path", *accessLogPath)
	conf.Set("port", *port)
	conf.Set("local_image_path", *localImagePath)
	conf.Set("max_process", *maxProcess)

	loggers := map[string]logrus.Logger{
		"err":    *logger.NewLogger(conf.ErrorLogPath()),
		"access": *logger.NewLogger(conf.AccessLogPath()),
	}

	if *debug {
		fmt.Println(conf)
	}

	runtime.GOMAXPROCS(conf.MaxProcess())

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		handler.MainHandler(w, r, conf, loggers)
	})
	http.HandleFunc("/healthCheck", handler.HealthCheckHandler)
	http.ListenAndServe(fmt.Sprintf(":%d", conf.Port()), nil)
}
<commit_msg>delete build version<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"runtime"

	"github.com/livesense-inc/fanlin/lib/conf"
	"github.com/livesense-inc/fanlin/lib/handler"
	"github.com/livesense-inc/fanlin/lib/logger"
	"github.com/sirupsen/logrus"
)

var confList = []string{
	"/etc/fanlin.json",
	"/etc/fanlin.cnf",
	"/etc/fanlin.conf",
	"/usr/local/etc/fanlin.json",
	"/usr/local/etc/fanlin.cnf",
	"/usr/local/etc/fanlin.conf",
	"/usr/local/fanlin/fanlin.json",
	"/usr/local/fanlin.json",
	"/usr/local/fanlin.conf",
	"./fanlin.json",
	"./fanlin.cnf",
	"./fanlin.conf",
	"./conf.json",
	"~/.fanlin.json",
	"~/.fanlin.cnf",
}

var (
	buildVersion string
	buildDate    string
	goversion    string
)

var (
	vOption bool
)

func showVersion() {
	fmt.Println()
	fmt.Println("build version: ", buildVersion)
	fmt.Println("build date: ", buildDate)
	fmt.Println("GO version: ", goversion)
	os.Exit(128)
}

func main() {
	conf := func() *configure.Conf {
		for _, confName := range confList {
			conf := configure.NewConfigure(confName)
			if conf != nil {
				return conf
			}
		}
		return nil
	}()
	if conf == nil {
		log.Fatalln("Can not read configure.")
	}

	notFoundImagePath := flag.String("nfi", conf.NotFoundImagePath(), "not found image path")
	errorLogPath := flag.String("err", conf.ErrorLogPath(), "error log path")
	accessLogPath := flag.String("log", conf.AccessLogPath(), "access log path")
	port := flag.Int("p", conf.Port(), "port")
	port = flag.Int("port", conf.Port(), "port")
	localImagePath := flag.String("li", conf.LocalImagePath(), "local image path")
	maxProcess := flag.Int("cpu", conf.MaxProcess(), "max process.")
	debug := flag.Bool("debug", false, "debug mode.")
	flag.BoolVar(&vOption, "v", false, "version")
	flag.Parse()

	if vOption {
		showVersion()
	}

	conf.Set("404_img_path", *notFoundImagePath)
	conf.Set("error_log_path", *errorLogPath)
	conf.Set("access_log_path", *accessLogPath)
	conf.Set("port", *port)
	conf.Set("local_image_path", *localImagePath)
	conf.Set("max_process", *maxProcess)

	loggers := map[string]logrus.Logger{
		"err":    *logger.NewLogger(conf.ErrorLogPath()),
		"access": *logger.NewLogger(conf.AccessLogPath()),
	}

	if *debug {
		fmt.Println(conf)
	}

	runtime.GOMAXPROCS(conf.MaxProcess())

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		handler.MainHandler(w, r, conf, loggers)
	})
	http.HandleFunc("/healthCheck", handler.HealthCheckHandler)
	http.ListenAndServe(fmt.Sprintf(":%d", conf.Port()), nil)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"

	"github.com/TimothyYe/godns/internal/handler"
	"github.com/TimothyYe/godns/internal/settings"
	"github.com/TimothyYe/godns/internal/utils"

	log "github.com/sirupsen/logrus"

	"github.com/fatih/color"
)

var (
	configuration settings.Settings
	optConf       = flag.String("c", "./config.json", "Specify a config file")
	optHelp       = flag.Bool("h", false, "Show help")

	// Version is current version of GoDNS.
	Version = "0.1"
)

func init() {
	log.SetOutput(os.Stdout)
}

func main() {
	flag.Parse()
	if *optHelp {
		color.Cyan(utils.Logo, Version)
		flag.Usage()
		return
	}

	// Load settings from configurations file
	if err := settings.LoadSettings(*optConf, &configuration); err != nil {
		log.Fatal(err)
	}

	if configuration.DebugInfo {
		log.SetLevel(log.DebugLevel)
	} else {
		log.SetLevel(log.InfoLevel)
	}

	if err := utils.CheckSettings(&configuration); err != nil {
		log.Fatal("Invalid settings: ", err.Error())
	}

	// Init log settings
	log.Info("GoDNS started, entering main loop...")
	dnsLoop()
}

func dnsLoop() {
	panicChan := make(chan settings.Domain)

	log.Infof("Creating DNS handler with provider: %s", configuration.Provider)
	h, err := handler.CreateHandler(&configuration)
	if err != nil {
		log.Fatal(err)
	}

	h.SetConfiguration(&configuration)
	for _, domain := range configuration.Domains {
		if configuration.RunOnce {
			h.DomainLoop(&domain, panicChan, configuration.RunOnce)
		} else {
			go h.DomainLoop(&domain, panicChan, configuration.RunOnce)
		}
	}

	if configuration.RunOnce {
		os.Exit(0)
	}

	panicCount := 0
	for {
		failDomain := <-panicChan
		log.Debug("Got panic in goroutine, will start a new one... :", panicCount)
		go h.DomainLoop(&failDomain, panicChan, configuration.RunOnce)

		panicCount++
		if panicCount >= utils.PanicMax {
			os.Exit(1)
		}
	}
}
<commit_msg>fix multi-domains issue<commit_after>package main

import (
	"flag"
	"os"

	"github.com/TimothyYe/godns/internal/handler"
	"github.com/TimothyYe/godns/internal/settings"
	"github.com/TimothyYe/godns/internal/utils"

	log "github.com/sirupsen/logrus"

	"github.com/fatih/color"
)

var (
	configuration settings.Settings
	optConf       = flag.String("c", "./config.json", "Specify a config file")
	optHelp       = flag.Bool("h", false, "Show help")

	// Version is current version of GoDNS.
	Version = "0.1"
)

func init() {
	log.SetOutput(os.Stdout)
}

func main() {
	flag.Parse()
	if *optHelp {
		color.Cyan(utils.Logo, Version)
		flag.Usage()
		return
	}

	// Load settings from configurations file
	if err := settings.LoadSettings(*optConf, &configuration); err != nil {
		log.Fatal(err)
	}

	if configuration.DebugInfo {
		log.SetLevel(log.DebugLevel)
	} else {
		log.SetLevel(log.InfoLevel)
	}

	if err := utils.CheckSettings(&configuration); err != nil {
		log.Fatal("Invalid settings: ", err.Error())
	}

	// Init log settings
	log.Info("GoDNS started, entering main loop...")
	dnsLoop()
}

func dnsLoop() {
	panicChan := make(chan settings.Domain)

	log.Infof("Creating DNS handler with provider: %s", configuration.Provider)
	h, err := handler.CreateHandler(&configuration)
	if err != nil {
		log.Fatal(err)
	}

	h.SetConfiguration(&configuration)
	for _, domain := range configuration.Domains {
		domain := domain
		if configuration.RunOnce {
			h.DomainLoop(&domain, panicChan, configuration.RunOnce)
		} else {
			go h.DomainLoop(&domain, panicChan, configuration.RunOnce)
		}
	}

	if configuration.RunOnce {
		os.Exit(0)
	}

	panicCount := 0
	for {
		failDomain := <-panicChan
		log.Debug("Got panic in goroutine, will start a new one... :", panicCount)
		go h.DomainLoop(&failDomain, panicChan, configuration.RunOnce)

		panicCount++
		if panicCount >= utils.PanicMax {
			os.Exit(1)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/codegangsta/cli"
	"github.com/sebest/hooky/restapi"
	"github.com/sebest/hooky/scheduler"
	"github.com/sebest/hooky/store"
	"github.com/stretchr/graceful"
)

func main() {
	app := cli.NewApp()
	app.Name = "hooky"
	app.Usage = "the webhooks scheduler"
	app.Version = "0.1"
	app.Author = "Sébastien Estienne"
	app.Email = "sebastien.estienne@gmail.com"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "bind",
			Value:  ":8000",
			Usage:  "address to bind on",
			EnvVar: "HOOKY_BIND",
		},
		cli.StringFlag{
			Name:   "mongo-uri",
			Value:  "localhost/hooky",
			Usage:  "MongoDB URI to connect to",
			EnvVar: "HOOKY_MONGO_URI",
		},
		cli.StringFlag{
			Name:   "admin-password",
			Value:  "admin",
			Usage:  "admin password",
			EnvVar: "HOOKY_ADMIN_PASSWORD",
		},
		cli.IntFlag{
			Name:   "max-mongo-query",
			Value:  1,
			Usage:  "maximum number of parallel queries on MongoDB",
			EnvVar: "HOOKY_MAX_MONGO_QUERY",
		},
		cli.IntFlag{
			Name:   "max-http-request",
			Value:  20,
			Usage:  "maximum number of parallel HTTP requests",
			EnvVar: "HOOKY_MAX_HTTP_REQUEST",
		},
		cli.IntFlag{
			Name:   "touch-interval",
			Value:  5,
			Usage:  "frequency to update the tasks reservation duration in seconds",
			EnvVar: "HOOKY_TOUCH_INTERVAL",
		},
	}
	app.Action = func(c *cli.Context) {
		s, err := store.New(c.String("mongo-uri"))
		if err != nil {
			log.Fatal(err)
		}
		sched := scheduler.New(s, c.Int("max-mongo-query"), c.Int("max-http-request"), c.Int("touch-interval"))
		sched.Start()
		ra, err := restapi.New(s, c.String("admin-password"))
		if err != nil {
			log.Fatal(err)
		}
		server := &graceful.Server{
			Timeout: 10 * time.Second,
			Server: &http.Server{
				Addr:    c.String("bind"),
				Handler: ra.MakeHandler(),
			},
		}
		server.ListenAndServe()
		fmt.Println("exiting")
		sched.Stop()
		fmt.Println("exited")
	}
	app.Run(os.Args)
}
<commit_msg>Change the bind address flags<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/codegangsta/cli"
	"github.com/sebest/hooky/restapi"
	"github.com/sebest/hooky/scheduler"
	"github.com/sebest/hooky/store"
	"github.com/stretchr/graceful"
)

func main() {
	app := cli.NewApp()
	app.Name = "hooky"
	app.Usage = "the webhooks scheduler"
	app.Version = "0.1"
	app.Author = "Sébastien Estienne"
	app.Email = "sebastien.estienne@gmail.com"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "bind-address",
			Value:  "",
			Usage:  "host address to bind on",
			EnvVar: "HOOKY_BIND_ADDRESS",
		},
		cli.StringFlag{
			Name:   "bind-port",
			Value:  "8000",
			Usage:  "port number to bind on",
			EnvVar: "HOOKY_BIND_PORT,PORT",
		},
		cli.StringFlag{
			Name:   "mongo-uri",
			Value:  "localhost/hooky",
			Usage:  "MongoDB URI to connect to",
			EnvVar: "HOOKY_MONGO_URI",
		},
		cli.StringFlag{
			Name:   "admin-password",
			Value:  "admin",
			Usage:  "admin password",
			EnvVar: "HOOKY_ADMIN_PASSWORD",
		},
		cli.IntFlag{
			Name:   "max-mongo-query",
			Value:  1,
			Usage:  "maximum number of parallel queries on MongoDB",
			EnvVar: "HOOKY_MAX_MONGO_QUERY",
		},
		cli.IntFlag{
			Name:   "max-http-request",
			Value:  20,
			Usage:  "maximum number of parallel HTTP requests",
			EnvVar: "HOOKY_MAX_HTTP_REQUEST",
		},
		cli.IntFlag{
			Name:   "touch-interval",
			Value:  5,
			Usage:  "frequency to update the tasks reservation duration in seconds",
			EnvVar: "HOOKY_TOUCH_INTERVAL",
		},
	}
	app.Action = func(c *cli.Context) {
		s, err := store.New(c.String("mongo-uri"))
		if err != nil {
			log.Fatal(err)
		}
		sched := scheduler.New(s, c.Int("max-mongo-query"), c.Int("max-http-request"), c.Int("touch-interval"))
		sched.Start()
		ra, err := restapi.New(s, c.String("admin-password"))
		if err != nil {
			log.Fatal(err)
		}
		server := &graceful.Server{
			Timeout: 10 * time.Second,
			Server: &http.Server{
				Addr:    c.String("bind-host") + ":" + c.String("bind-port"),
				Handler: ra.MakeHandler(),
			},
		}
		err = server.ListenAndServe()
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println("exiting")
		sched.Stop()
		fmt.Println("exited")
	}
	app.Run(os.Args)
}
<|endoftext|>