<commit_before>package aws

import (
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceAwsRoute() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsRouteRead,

		Schema: map[string]*schema.Schema{
			"route_table_id": {
				Type:     schema.TypeString,
				Required: true,
			},
			"destination_cidr_block": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"destination_ipv6_cidr_block": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"egress_only_gateway_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"gateway_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"instance_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"nat_gateway_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"vpc_peering_connection_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"network_interface_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
		},
	}
}

func dataSourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	req := &ec2.DescribeRouteTablesInput{}
	rtbId, rtbOk := d.GetOk("route_table_id")
	cidr := d.Get("destination_cidr_block")
	ipv6Cidr := d.Get("destination_ipv6_cidr_block")

	if !rtbOk {
		return fmt.Errorf("Route table must be assigned")
	}
	req.Filters = buildEC2AttributeFilterList(
		map[string]string{
			"route-table-id":                    rtbId.(string),
			"route.destination-cidr-block":      cidr.(string),
			"route.destination-ipv6-cidr-block": ipv6Cidr.(string),
		},
	)

	log.Printf("[DEBUG] Reading Route Table: %s", req)
	resp, err := conn.DescribeRouteTables(req)
	if err != nil {
		return err
	}
	if resp == nil || len(resp.RouteTables) == 0 {
		return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
	}
	if len(resp.RouteTables) > 1 {
		return fmt.Errorf("Your query returned more than one route table. Please change your search criteria and try again.")
	}

	results := getRoutes(resp.RouteTables[0], d)

	if len(results) == 0 {
		return fmt.Errorf("No routes matching supplied arguments found in table(s)")
	}
	if len(results) > 1 {
		return fmt.Errorf("Multiple routes matched; use additional constraints to reduce matches to a single route")
	}
	route := results[0]

	d.SetId(routeIDHash(d, route)) // using function from "resource_aws_route.go"
	d.Set("destination_cidr_block", route.DestinationCidrBlock)
	d.Set("destination_ipv6_cidr_block", route.DestinationIpv6CidrBlock)
	d.Set("egress_only_gateway_id", route.EgressOnlyInternetGatewayId)
	d.Set("gateway_id", route.GatewayId)
	d.Set("instance_id", route.InstanceId)
	d.Set("nat_gateway_id", route.NatGatewayId)
	d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId)
	d.Set("network_interface_id", route.NetworkInterfaceId)

	return nil
}

func getRoutes(table *ec2.RouteTable, d *schema.ResourceData) []*ec2.Route {
	ec2Routes := table.Routes
	routes := make([]*ec2.Route, 0, len(ec2Routes))
	// Loop through the routes and add them to the set
	for _, r := range ec2Routes {

		if r.Origin != nil && *r.Origin == "EnableVgwRoutePropagation" {
			continue
		}

		if r.DestinationPrefixListId != nil {
			// Skipping because VPC endpoint routes are handled separately
			// See aws_vpc_endpoint
			continue
		}

		if v, ok := d.GetOk("destination_cidr_block"); ok {
			if r.DestinationCidrBlock == nil || *r.DestinationCidrBlock != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok {
			if r.DestinationIpv6CidrBlock == nil || *r.DestinationIpv6CidrBlock != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("egress_only_gateway_id"); ok {
			if r.EgressOnlyInternetGatewayId == nil || *r.EgressOnlyInternetGatewayId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("gateway_id"); ok {
			if r.GatewayId == nil || *r.GatewayId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("instance_id"); ok {
			if r.InstanceId == nil || *r.InstanceId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("nat_gateway_id"); ok {
			if r.NatGatewayId == nil || *r.NatGatewayId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("vpc_peering_connection_id"); ok {
			if r.VpcPeeringConnectionId == nil || *r.VpcPeeringConnectionId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("network_interface_id"); ok {
			if r.NetworkInterfaceId == nil || *r.NetworkInterfaceId != v.(string) {
				continue
			}
		}
		routes = append(routes, r)
	}
	return routes
}
<commit_msg>Remove unnecesary guard on required schema attribute<commit_after>package aws

import (
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceAwsRoute() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsRouteRead,

		Schema: map[string]*schema.Schema{
			"route_table_id": {
				Type:     schema.TypeString,
				Required: true,
			},
			"destination_cidr_block": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"destination_ipv6_cidr_block": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"egress_only_gateway_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"gateway_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"instance_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"nat_gateway_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"vpc_peering_connection_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"network_interface_id": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
		},
	}
}

func dataSourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	req := &ec2.DescribeRouteTablesInput{}
	rtbId := d.Get("route_table_id")
	cidr := d.Get("destination_cidr_block")
	ipv6Cidr := d.Get("destination_ipv6_cidr_block")

	req.Filters = buildEC2AttributeFilterList(
		map[string]string{
			"route-table-id":                    rtbId.(string),
			"route.destination-cidr-block":      cidr.(string),
			"route.destination-ipv6-cidr-block": ipv6Cidr.(string),
		},
	)

	log.Printf("[DEBUG] Reading Route Table: %s", req)
	resp, err := conn.DescribeRouteTables(req)
	if err != nil {
		return err
	}
	if resp == nil || len(resp.RouteTables) == 0 {
		return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
	}
	if len(resp.RouteTables) > 1 {
		return fmt.Errorf("Your query returned more than one route table. Please change your search criteria and try again.")
	}

	results := getRoutes(resp.RouteTables[0], d)

	if len(results) == 0 {
		return fmt.Errorf("No routes matching supplied arguments found in table(s)")
	}
	if len(results) > 1 {
		return fmt.Errorf("Multiple routes matched; use additional constraints to reduce matches to a single route")
	}
	route := results[0]

	d.SetId(routeIDHash(d, route)) // using function from "resource_aws_route.go"
	d.Set("destination_cidr_block", route.DestinationCidrBlock)
	d.Set("destination_ipv6_cidr_block", route.DestinationIpv6CidrBlock)
	d.Set("egress_only_gateway_id", route.EgressOnlyInternetGatewayId)
	d.Set("gateway_id", route.GatewayId)
	d.Set("instance_id", route.InstanceId)
	d.Set("nat_gateway_id", route.NatGatewayId)
	d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId)
	d.Set("network_interface_id", route.NetworkInterfaceId)

	return nil
}

func getRoutes(table *ec2.RouteTable, d *schema.ResourceData) []*ec2.Route {
	ec2Routes := table.Routes
	routes := make([]*ec2.Route, 0, len(ec2Routes))
	// Loop through the routes and add them to the set
	for _, r := range ec2Routes {

		if r.Origin != nil && *r.Origin == "EnableVgwRoutePropagation" {
			continue
		}

		if r.DestinationPrefixListId != nil {
			// Skipping because VPC endpoint routes are handled separately
			// See aws_vpc_endpoint
			continue
		}

		if v, ok := d.GetOk("destination_cidr_block"); ok {
			if r.DestinationCidrBlock == nil || *r.DestinationCidrBlock != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok {
			if r.DestinationIpv6CidrBlock == nil || *r.DestinationIpv6CidrBlock != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("egress_only_gateway_id"); ok {
			if r.EgressOnlyInternetGatewayId == nil || *r.EgressOnlyInternetGatewayId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("gateway_id"); ok {
			if r.GatewayId == nil || *r.GatewayId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("instance_id"); ok {
			if r.InstanceId == nil || *r.InstanceId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("nat_gateway_id"); ok {
			if r.NatGatewayId == nil || *r.NatGatewayId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("vpc_peering_connection_id"); ok {
			if r.VpcPeeringConnectionId == nil || *r.VpcPeeringConnectionId != v.(string) {
				continue
			}
		}

		if v, ok := d.GetOk("network_interface_id"); ok {
			if r.NetworkInterfaceId == nil || *r.NetworkInterfaceId != v.(string) {
				continue
			}
		}
		routes = append(routes, r)
	}
	return routes
}
<|endoftext|>


<commit_before>// +build linux

package udp_test

import (
	"syscall"
	"testing"

	"github.com/v2ray/v2ray-core/common/alloc"
	v2net "github.com/v2ray/v2ray-core/common/net"
	"github.com/v2ray/v2ray-core/proxy"
	"github.com/v2ray/v2ray-core/testing/assert"
	"github.com/v2ray/v2ray-core/transport/internet/internal"
	. "github.com/v2ray/v2ray-core/transport/internet/udp"
)

func TestHubSocksOption(t *testing.T) {
	assert := assert.On(t)

	hub, err := ListenUDP(v2net.LocalHostIP, v2net.Port(0), ListenOption{
		Callback:            func(*alloc.Buffer, *proxy.SessionInfo) {},
		ReceiveOriginalDest: true,
	})
	assert.Error(err).IsNil()
	conn := hub.Connection()

	sysfd, err := internal.GetSysFd(conn)
	assert.Error(err).IsNil()

	fd, err := sysfd.SysFd()
	assert.Error(err).IsNil()

	v, err := syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT)
	assert.Error(err).IsNil()
	assert.Int(v).Equals(1)

	v, err = syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR)
	assert.Error(err).IsNil()
	assert.Int(v).Equals(1)
}
<commit_msg>fix test break<commit_after>// +build linux

package udp_test

import (
	"syscall"
	"testing"

	"github.com/v2ray/v2ray-core/common/alloc"
	v2net "github.com/v2ray/v2ray-core/common/net"
	"github.com/v2ray/v2ray-core/proxy"
	"github.com/v2ray/v2ray-core/testing/assert"
	"github.com/v2ray/v2ray-core/transport/internet/internal"
	. "github.com/v2ray/v2ray-core/transport/internet/udp"
)

func TestHubSocksOption(t *testing.T) {
	assert := assert.On(t)

	hub, err := ListenUDP(v2net.LocalHostIP, v2net.Port(0), ListenOption{
		Callback:            func(*alloc.Buffer, *proxy.SessionInfo) {},
		ReceiveOriginalDest: true,
	})
	assert.Error(err).IsNil()
	conn := hub.Connection()

	fd, err := internal.GetSysFd(conn)
	assert.Error(err).IsNil()

	v, err := syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT)
	assert.Error(err).IsNil()
	assert.Int(v).Equals(1)

	v, err = syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR)
	assert.Error(err).IsNil()
	assert.Int(v).Equals(1)
}
<|endoftext|>


<commit_before>package zookeeper

import (
	"strings"
	"time"

	zk "github.com/samuel/go-zookeeper/zk"
)

// Client provides a wrapper around the zookeeper client
type Client struct {
	client *zk.Conn
}

func NewZookeeperClient(machines []string) (*Client, error) {
	c, _, err := zk.Connect(machines, time.Second) //*10)
	if err != nil {
		panic(err)
	}
	return &Client{c}, nil
}

func node_walk(prefix string, c *Client, vars map[string]string) error {
	l, stat, err := c.client.Children(prefix)
	if err != nil {
		return err
	}

	if stat.NumChildren == 0 {
		b, _, err := c.client.Get(prefix)
		if err != nil {
			return err
		}
		vars[prefix] = string(b)

	} else {
		for _, key := range l {
			s := prefix + "/" + key
			_, stat, err := c.client.Exists(s)
			if err != nil {
				return err
			}
			if stat.NumChildren == 0 {
				b, _, err := c.client.Get(s)
				if err != nil {
					return err
				}
				vars[s] = string(b)
			} else {
				node_walk(s, c, vars)
			}
		}
	}
	return nil
}

func (c *Client) GetValues(keys []string) (map[string]string, error) {
	vars := make(map[string]string)
	for _, v := range keys {
		v = strings.Replace(v, "/*", "", -1)
		_, _, err := c.client.Exists(v)
		if err != nil {
			return vars, err
		}
		if v == "/" {
			v = ""
		}
		err = node_walk(v, c, vars)
		if err != nil {
			return vars, err
		}
	}
	return vars, nil
}

// WatchPrefix is not yet implemented. There's a WIP.
// Since zookeeper doesn't handle recursive watch, we need to create a *lot* of watches.
// Implementation should take care of this.
// A good start is bamboo
// URL https://github.com/QubitProducts/bamboo/blob/master/qzk/qzk.go
// We also need to encourage users to set prefix and add a flag to enale support for "" prefix (aka "/")
//

func (c *Client) WatchPrefix(prefix string, waitIndex uint64, stopChan chan bool) (uint64, error) {
	<-stopChan
	return 0, nil
}
<commit_msg>Update client.go<commit_after>package zookeeper

import (
	"strings"
	"time"

	zk "github.com/samuel/go-zookeeper/zk"
)

// Client provides a wrapper around the zookeeper client
type Client struct {
	client *zk.Conn
}

func NewZookeeperClient(machines []string) (*Client, error) {
	c, _, err := zk.Connect(machines, time.Second) //*10)
	if err != nil {
		panic(err)
	}
	return &Client{c}, nil
}

func nodeWalk(prefix string, c *Client, vars map[string]string) error {
	l, stat, err := c.client.Children(prefix)
	if err != nil {
		return err
	}

	if stat.NumChildren == 0 {
		b, _, err := c.client.Get(prefix)
		if err != nil {
			return err
		}
		vars[prefix] = string(b)

	} else {
		for _, key := range l {
			s := prefix + "/" + key
			_, stat, err := c.client.Exists(s)
			if err != nil {
				return err
			}
			if stat.NumChildren == 0 {
				b, _, err := c.client.Get(s)
				if err != nil {
					return err
				}
				vars[s] = string(b)
			} else {
				nodeWalk(s, c, vars)
			}
		}
	}
	return nil
}

func (c *Client) GetValues(keys []string) (map[string]string, error) {
	vars := make(map[string]string)
	for _, v := range keys {
		v = strings.Replace(v, "/*", "", -1)
		_, _, err := c.client.Exists(v)
		if err != nil {
			return vars, err
		}
		if v == "/" {
			v = ""
		}
		err = nodeWalk(v, c, vars)
		if err != nil {
			return vars, err
		}
	}
	return vars, nil
}

// WatchPrefix is not yet implemented. There's a WIP.
// Since zookeeper doesn't handle recursive watch, we need to create a *lot* of watches.
// Implementation should take care of this.
// A good start is bamboo
// URL https://github.com/QubitProducts/bamboo/blob/master/qzk/qzk.go
// We also need to encourage users to set prefix and add a flag to enale support for "" prefix (aka "/")
//

func (c *Client) WatchPrefix(prefix string, waitIndex uint64, stopChan chan bool) (uint64, error) {
	<-stopChan
	return 0, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os/exec"
	"strings"
	"testing"

	"github.com/containerops/dockyard/test"
)

func TestPullInit(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest", "1.0", "2.0"}
	repoBase := reponame + ":" + repotags[0]

	if err = exec.Command(test.DockerBinary, "inspect", repoBase).Run(); err != nil {
		cmd = exec.Command(test.DockerBinary, "pull", repoBase)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Pull testing preparation is failed: [Info]%v, [Error]%v", out, err)
		}
	}

	repoDest := test.Domains + "/" + test.UserName + "/" + reponame
	for _, v := range repotags {
		tag := repoDest + ":" + v
		cmd = exec.Command(test.DockerBinary, "tag", "-f", repoBase, tag)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Tag %v failed: [Info]%v, [Error]%v", repoBase, out, err)
		}
		cmd = exec.Command(test.DockerBinary, "push", tag)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Push all tags %v failed: [Info]%v, [Error]%v", tag, out, err)
		}
	}
}

func getCurrentVersion() (string, string, error) {
	cmd := exec.Command(test.DockerBinary, "-v")
	out, err := test.ParseCmdCtx(cmd)
	if err != nil {
		return "", "", fmt.Errorf("Get docker version failed")
	}

	curVer := strings.Split(strings.Split(out, ",")[0], " ")[2]
	val := test.Compare(curVer, "1.6.0")
	if val < 0 {
		return curVer, "V1", nil
	} else {
		return curVer, "V2", nil
	}
}

func chkAndDelAllRepoTags(repoBase string, repotags []string) error {
	for _, v := range repotags {
		repotag := repoBase + ":" + v
		if err := exec.Command(test.DockerBinary, "inspect", repotag).Run(); err != nil {
			return fmt.Errorf(err.Error())
		}

		cmd := exec.Command(test.DockerBinary, "rmi", repotag)
		if _, err := test.ParseCmdCtx(cmd); err != nil {
			return fmt.Errorf(err.Error())
		}
	}
	return nil
}

func TestPullRepoSingleTag(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest"}
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	for i := 1; i <= 2; i++ {
		cmd = exec.Command(test.DockerBinary, "pull", repoDest+":"+repotags[0])
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest+":"+repotags[0], out, err)
		}
	}

	if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
		t.Fatalf("Pull %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
	}
}

//if there are multiple tags in registry,if protocol V2 pulling is not specified tag, default to get latest tag,different from protocol V1
func TestPullV2RepoWithoutTags(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	_, registry, err := getCurrentVersion()
	if err != nil {
		t.Fatal(err.Error())
	}

	if registry == "V2" {
		for i := 1; i <= 2; i++ {
			cmd = exec.Command(test.DockerBinary, "pull", repoDest)
			if out, err = test.ParseCmdCtx(cmd); err != nil {
				t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest, out, err)
			}
			/*
				if !strings.Contains(out, "Using default tag: latest") {
					t.Fatalf("Not expected result")
				}
			*/
		}

		repotags := []string{"latest"}
		if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
			t.Fatalf("Pull %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
		}
	}
}

func TestPullRepoMultipleTags(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest", "1.0", "2.0"}
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	curVer, registry, err := getCurrentVersion()
	if err != nil {
		t.Fatal(err.Error())
	}

	if !strings.Contains(curVer, "1.6") {
		//Pull Repository Multiple Tags with option "-a",protocol V1 and V2 are all the same except Docker 1.6.x
		for i := 1; i <= 2; i++ {
			cmd = exec.Command(test.DockerBinary, "pull", "-a", repoDest)
			if out, err = test.ParseCmdCtx(cmd); err != nil {
				t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
			}
		}
		if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
			t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
		}

		if registry == "V1" {
			//Docker daemon support to pull Repository Multiple Tags without option "-a"
			for i := 1; i <= 2; i++ {
				cmd = exec.Command(test.DockerBinary, "pull", repoDest)
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
				}
			}
			if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
				t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
			}

			//if there are multiple tags in registry,pull specified tag will get all tags of repository
			for i := 1; i <= 2; i++ {
				cmd = exec.Command(test.DockerBinary, "pull", repoDest+":"+repotags[0])
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
				}
			}
			if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
				t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
			}
		}
	} else {
		//There is a bug about "pull -a" in Docker 1.6.x,it will be change from protocol V2 to V1 if using "pull -a"
	}
}

func TestPullNonExistentRepo(t *testing.T) {
	repoDest := test.Domains + "/" + test.UserName + "/" + "nonexistentrepo"
	cmd := exec.Command(test.DockerBinary, "pull", repoDest)
	if out, err := test.ParseCmdCtx(cmd); err == nil {
		t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest, out, err)
	}
}

/*
func Example_random() {
	fmt.Println("mabintest")
	//output:
	//mabintest
}
*/
<commit_msg>Modify pull Test suite<commit_after>package main

import (
	"fmt"
	"os/exec"
	"strings"
	"testing"

	"github.com/containerops/dockyard/test"
)

func TestPullInit(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest", "1.0", "2.0"}
	repoBase := reponame + ":" + repotags[0]

	if err = exec.Command(test.DockerBinary, "inspect", repoBase).Run(); err != nil {
		cmd = exec.Command(test.DockerBinary, "pull", repoBase)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Pull testing preparation is failed: [Info]%v, [Error]%v", out, err)
		}
	}

	repoDest := test.Domains + "/" + test.UserName + "/" + reponame
	for _, v := range repotags {
		tag := repoDest + ":" + v
		cmd = exec.Command(test.DockerBinary, "tag", "-f", repoBase, tag)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Tag %v failed: [Info]%v, [Error]%v", repoBase, out, err)
		}
		cmd = exec.Command(test.DockerBinary, "push", tag)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Push all tags %v failed: [Info]%v, [Error]%v", tag, out, err)
		}
	}
}

func getCurrentVersion() (string, string, error) {
	cmd := exec.Command(test.DockerBinary, "-v")
	out, err := test.ParseCmdCtx(cmd)
	if err != nil {
		return "", "", fmt.Errorf("Get docker version failed")
	}

	curVer := strings.Split(strings.Split(out, ",")[0], " ")[2]
	val := test.Compare(curVer, "1.6.0")
	if val < 0 {
		return curVer, "V1", nil
	} else {
		return curVer, "V2", nil
	}
}

func chkAndDelAllRepoTags(repoBase string, repotags []string) error {
	for _, v := range repotags {
		repotag := repoBase + ":" + v
		if err := exec.Command(test.DockerBinary, "inspect", repotag).Run(); err != nil {
			return fmt.Errorf(err.Error())
		}

		cmd := exec.Command(test.DockerBinary, "rmi", repotag)
		if _, err := test.ParseCmdCtx(cmd); err != nil {
			return fmt.Errorf(err.Error())
		}
	}
	return nil
}

func TestPullRepoSingleTag(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest"}
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	for i := 1; i <= 2; i++ {
		cmd = exec.Command(test.DockerBinary, "pull", repoDest+":"+repotags[0])
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest+":"+repotags[0], out, err)
		}
	}

	if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
		t.Fatalf("Pull %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
	}
}

//if there are multiple tags in registry,if protocol V2 pulling is not specified tag, default to get latest tag,different from protocol V1
func TestPullV2RepoWithoutTags(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame
	repotags := []string{"latest", "1.0", "2.0"}

	_, registry, err := getCurrentVersion()
	if err != nil {
		t.Fatal(err.Error())
	}

	if registry == "V2" {
		for _, v := range repotags {
			tag := repoDest + ":" + v
			if err = exec.Command(test.DockerBinary, "inspect", tag).Run(); err == nil {
				cmd = exec.Command(test.DockerBinary, "rmi", tag)
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull testing preparation is failed: [Info]%v, [Error]%v", out, err)
				}
			}
		}

		for i := 1; i <= 2; i++ {
			cmd = exec.Command(test.DockerBinary, "pull", repoDest)
			if out, err = test.ParseCmdCtx(cmd); err != nil {
				t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest, out, err)
			}
		}

		for _, v := range repotags {
			if v != "latest" {
				tag := repoDest + ":" + v
				if err = exec.Command(test.DockerBinary, "inspect", tag).Run(); err == nil {
					t.Fatalf("Not expect result")
				}
			}
		}

		if err := chkAndDelAllRepoTags(repoDest, []string{"latest"}); err != nil {
			t.Fatalf("Pull %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
		}
	}
}

func TestPullRepoMultipleTags(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest", "1.0", "2.0"}
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	curVer, registry, err := getCurrentVersion()
	if err != nil {
		t.Fatal(err.Error())
	}

	if !strings.Contains(curVer, "1.6") {
		//Pull Repository Multiple Tags with option "-a",protocol V1 and V2 are all the same except Docker 1.6.x
		for i := 1; i <= 2; i++ {
			cmd = exec.Command(test.DockerBinary, "pull", "-a", repoDest)
			if out, err = test.ParseCmdCtx(cmd); err != nil {
				t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
			}
		}
		if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
			t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
		}

		if registry == "V1" {
			//Docker daemon support to pull Repository Multiple Tags without option "-a"
			for i := 1; i <= 2; i++ {
				cmd = exec.Command(test.DockerBinary, "pull", repoDest)
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
				}
			}
			if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
				t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
			}

			//if there are multiple tags in registry,pull specified tag will get all tags of repository
			for i := 1; i <= 2; i++ {
				cmd = exec.Command(test.DockerBinary, "pull", repoDest+":"+repotags[0])
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
				}
			}
			if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
				t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
			}
		}
	} else {
		//There is a bug about "pull -a" in Docker 1.6.x,it will be change from protocol V2 to V1 if using "pull -a"
	}
}

func TestPullNonExistentRepo(t *testing.T) {
	repoDest := test.Domains + "/" + test.UserName + "/" + "nonexistentrepo"
	cmd := exec.Command(test.DockerBinary, "pull", repoDest)
	if out, err := test.ParseCmdCtx(cmd); err == nil {
		t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest, out, err)
	}
}

/*
func Example_random() {
	fmt.Println("mabintest")
	//output:
	//mabintest
}
*/
<|endoftext|>


<commit_before>package interceptor

import (
	"bufio"
	"io"
	"net"
	"net/http"
	"time"

	"github.com/squaremo/ambergreen/balancer/interceptor/events"
)

func httpShim(inbound, outbound *net.TCPConn, eh events.Handler) error {
	reqrd := bufio.NewReader(inbound)
	resprd := bufio.NewReader(outbound)
	defer inbound.Close()
	defer outbound.Close()

	inboundAddr := inbound.RemoteAddr().(*net.TCPAddr)
	outboundAddr := outbound.RemoteAddr().(*net.TCPAddr)

	for {
		// XXX timeout on no request
		req, err := http.ReadRequest(reqrd)
		t1 := time.Now()
		if err != nil {
			if err == io.EOF {
				return nil
			}

			return err
		}

		req.Write(outbound)
		resp, err := http.ReadResponse(resprd, req)
		t2 := time.Now()
		if err != nil {
			return err
		}

		resp.Write(inbound)
		t3 := time.Now()

		eh.HttpExchange(&events.HttpExchange{
			Inbound:   inboundAddr,
			Outbound:  outboundAddr,
			Request:   req,
			Response:  resp,
			RoundTrip: t2.Sub(t1),
			TotalTime: t3.Sub(t1),
		})
	}
}
<commit_msg>Decouple http request and response handling<commit_after>package interceptor

import (
	"bufio"
	"io"
	"net"
	"net/http"
	"time"

	"github.com/squaremo/ambergreen/balancer/interceptor/events"
)

func httpShim(inbound, outbound *net.TCPConn, eh events.Handler) error {
	defer inbound.Close()
	defer outbound.Close()

	inboundAddr := inbound.RemoteAddr().(*net.TCPAddr)
	outboundAddr := outbound.RemoteAddr().(*net.TCPAddr)

	// Request handling and response handling take place in
	// separate goroutines.  This is not to support pipelining
	// (although it could easily be extended to do so).  Rather,
	// it is to support cases where the server produces a response
	// before the client is done sending the request (e.g. when
	// the server produces an error response before reading the
	// whole request).

	type request struct {
		req      *http.Request
		tReadReq time.Time
		err      error
	}

	reqCh := make(chan request)
	doneCh := make(chan struct{})
	defer close(doneCh)

	passReq := func(req request) bool {
		select {
		case reqCh <- req:
			return true
		case <-doneCh:
			return false
		}
	}

	// The request handler loop
	go func() {
		reqrd := bufio.NewReader(inbound)
		for {
			// XXX timeout on no request
			req, err := http.ReadRequest(reqrd)
			if err != nil {
				if err == io.EOF {
					close(reqCh)
					return
				}

				passReq(request{err: err})
				return
			}

			if !passReq(request{req: req, tReadReq: time.Now()}) {
				return
			}

			err = req.Write(outbound)
			if err != nil {
				passReq(request{err: err})
				return
			}
		}
	}()

	// The response handler loop
	resprd := bufio.NewReader(outbound)
	for {
		req, ok := <-reqCh
		if !ok {
			return nil
		}

		if req.err != nil {
			return req.err
		}

		resp, err := http.ReadResponse(resprd, req.req)
		tReadResponse := time.Now()
		if err != nil {
			return err
		}

		err = resp.Write(inbound)
		if err != nil {
			return err
		}

		tWroteResponse := time.Now()

		eh.HttpExchange(&events.HttpExchange{
			Inbound:   inboundAddr,
			Outbound:  outboundAddr,
			Request:   req.req,
			Response:  resp,
			RoundTrip: tReadResponse.Sub(req.tReadReq),
			TotalTime: tWroteResponse.Sub(req.tReadReq),
		})
	}
}
<|endoftext|>


<commit_before>package drivers

import (
	"io"

	"github.com/lxc/lxd/lxd/backup"
	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/instancewriter"
)

type mock struct {
	common
}

// load is used to run one-time action per-driver rather than per-pool.
func (d *mock) load() error {
	return nil
}

// Info returns info about the driver and its environment.
func (d *mock) Info() Info {
	return Info{
		Name:                  "mock",
		Version:               "1",
		OptimizedImages:       false,
		PreservesInodes:       false,
		Remote:                d.isRemote(),
		VolumeTypes:           []VolumeType{VolumeTypeCustom, VolumeTypeImage, VolumeTypeContainer, VolumeTypeVM},
		BlockBacking:          false,
		RunningQuotaResize:    true,
		RunningSnapshotFreeze: true,
		DirectIO:              true,
		MountedRoot:           true,
	}
}

func (d *mock) Create() error {
	return nil
}

func (d *mock) Delete(op *operations.Operation) error {
	return nil
}

// Validate checks that all provide keys are supported and that no conflicting or missing configuration is present.
func (d *mock) Validate(config map[string]string) error {
	return d.validatePool(config, nil)
}

// Update applies any driver changes required from a configuration change.
func (d *mock) Update(changedConfig map[string]string) error {
	return nil
}

// Mount mounts the storage pool.
func (d *mock) Mount() (bool, error) {
	return true, nil
}

// Unmount unmounts the storage pool.
func (d *mock) Unmount() (bool, error) {
	return true, nil
}

// GetResources returns the pool resource usage information.
func (d *mock) GetResources() (*api.ResourcesStoragePool, error) {
	return nil, nil
}

// CreateVolume creates an empty volume and can optionally fill it by executing the supplied filler function.
func (d *mock) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Operation) error {
	return nil
}

// CreateVolumeFromBackup restores a backup tarball onto the storage device.
func (d *mock) CreateVolumeFromBackup(vol Volume, srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) (func(vol Volume) error, func(), error) {
	return nil, nil, nil
}

// CreateVolumeFromCopy provides same-pool volume copying functionality.
func (d *mock) CreateVolumeFromCopy(vol Volume, srcVol Volume, copySnapshots bool, op *operations.Operation) error {
	return nil
}

// CreateVolumeFromMigration creates a volume being sent via a migration.
func (d *mock) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, preFiller *VolumeFiller, op *operations.Operation) error {
	return nil
}

// RefreshVolume provides same-pool volume and specific snapshots syncing functionality.
func (d *mock) RefreshVolume(vol Volume, srcVol Volume, srcSnapshots []Volume, op *operations.Operation) error {
	return nil
}

// DeleteVolume deletes a volume of the storage device. If any snapshots of the volume remain then this function
// will return an error.
func (d *mock) DeleteVolume(vol Volume, op *operations.Operation) error {
	return nil
}

// HasVolume indicates whether a specific volume exists on the storage pool.
func (d *mock) HasVolume(vol Volume) bool {
	return true
}

// ValidateVolume validates the supplied volume config. Optionally removes invalid keys from the volume's config.
func (d *mock) ValidateVolume(vol Volume, removeUnknownKeys bool) error {
	return nil
}

// UpdateVolume applies config changes to the volume.
func (d *mock) UpdateVolume(vol Volume, changedConfig map[string]string) error {
	if vol.contentType != ContentTypeFS {
		return ErrNotSupported
	}

	if _, changed := changedConfig["size"]; changed {
		err := d.SetVolumeQuota(vol, changedConfig["size"], nil)
		if err != nil {
			return err
		}
	}

	return nil
}

// GetVolumeUsage returns the disk space used by the volume.
func (d *mock) GetVolumeUsage(vol Volume) (int64, error) {
	return 0, nil
}

// SetVolumeQuota sets the quota on the volume.
func (d *mock) SetVolumeQuota(vol Volume, size string, op *operations.Operation) error {
	return nil
}

// GetVolumeDiskPath returns the location of a disk volume.
func (d *mock) GetVolumeDiskPath(vol Volume) (string, error) {
	return "", nil
}

// MountVolume simulates mounting a volume. As dir driver doesn't have volumes to mount it returns
// false indicating that there is no need to issue an unmount.
func (d *mock) MountVolume(vol Volume, op *operations.Operation) (bool, error) {
	return false, nil
}

// UnmountVolume simulates unmounting a volume. As dir driver doesn't have volumes to unmount it
// returns false indicating the volume was already unmounted.
func (d *mock) UnmountVolume(vol Volume, op *operations.Operation) (bool, error) {
	return false, nil
}

// RenameVolume renames a volume and its snapshots.
func (d *mock) RenameVolume(vol Volume, newVolName string, op *operations.Operation) error {
	return nil
}

// MigrateVolume sends a volume for migration.
func (d *mock) MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

// BackupVolume copies a volume (and optionally its snapshots) to a specified target path.
// This driver does not support optimized backups.
func (d *mock) BackupVolume(vol Volume, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

// CreateVolumeSnapshot creates a snapshot of a volume.
func (d *mock) CreateVolumeSnapshot(snapVol Volume, op *operations.Operation) error {
	return nil
}

// DeleteVolumeSnapshot removes a snapshot from the storage device. The volName and snapshotName
// must be bare names and should not be in the format "volume/snapshot".
func (d *mock) DeleteVolumeSnapshot(snapVol Volume, op *operations.Operation) error {
	return nil
}

// MountVolumeSnapshot sets up a read-only mount on top of the snapshot to avoid accidental modifications.
func (d *mock) MountVolumeSnapshot(snapVol Volume, op *operations.Operation) (bool, error) {
	return true, nil
}

// UnmountVolumeSnapshot removes the read-only mount placed on top of a snapshot.
func (d *mock) UnmountVolumeSnapshot(snapVol Volume, op *operations.Operation) (bool, error) {
	return true, nil
}

// VolumeSnapshots returns a list of snapshots for the volume.
func (d *mock) VolumeSnapshots(vol Volume, op *operations.Operation) ([]string, error) {
	return nil, nil
}

// RestoreVolume restores a volume from a snapshot.
func (d *mock) RestoreVolume(vol Volume, snapshotName string, op *operations.Operation) error {
	return nil
}

// RenameVolumeSnapshot renames a volume snapshot.
func (d *mock) RenameVolumeSnapshot(snapVol Volume, newSnapshotName string, op *operations.Operation) error {
	return nil
}
<commit_msg>lxd/storage/drivers/drivers/mock: Adds keepBlockDev arg to UnmountVolume<commit_after>package drivers

import (
	"io"

	"github.com/lxc/lxd/lxd/backup"
	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/instancewriter"
)

type mock struct {
	common
}

// load is used to run one-time action per-driver rather than per-pool.
func (d *mock) load() error {
	return nil
}

// Info returns info about the driver and its environment.
func (d *mock) Info() Info {
	return Info{
		Name:                  "mock",
		Version:               "1",
		OptimizedImages:       false,
		PreservesInodes:       false,
		Remote:                d.isRemote(),
		VolumeTypes:           []VolumeType{VolumeTypeCustom, VolumeTypeImage, VolumeTypeContainer, VolumeTypeVM},
		BlockBacking:          false,
		RunningQuotaResize:    true,
		RunningSnapshotFreeze: true,
		DirectIO:              true,
		MountedRoot:           true,
	}
}

func (d *mock) Create() error {
	return nil
}

func (d *mock) Delete(op *operations.Operation) error {
	return nil
}

// Validate checks that all provide keys are supported and that no conflicting or missing configuration is present.
func (d *mock) Validate(config map[string]string) error {
	return d.validatePool(config, nil)
}

// Update applies any driver changes required from a configuration change.
func (d *mock) Update(changedConfig map[string]string) error {
	return nil
}

// Mount mounts the storage pool.
func (d *mock) Mount() (bool, error) {
	return true, nil
}

// Unmount unmounts the storage pool.
func (d *mock) Unmount() (bool, error) {
	return true, nil
}

// GetResources returns the pool resource usage information.
func (d *mock) GetResources() (*api.ResourcesStoragePool, error) {
	return nil, nil
}

// CreateVolume creates an empty volume and can optionally fill it by executing the supplied filler function.
func (d *mock) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Operation) error {
	return nil
}

// CreateVolumeFromBackup restores a backup tarball onto the storage device.
func (d *mock) CreateVolumeFromBackup(vol Volume, srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) (func(vol Volume) error, func(), error) {
	return nil, nil, nil
}

// CreateVolumeFromCopy provides same-pool volume copying functionality.
func (d *mock) CreateVolumeFromCopy(vol Volume, srcVol Volume, copySnapshots bool, op *operations.Operation) error {
	return nil
}

// CreateVolumeFromMigration creates a volume being sent via a migration.
func (d *mock) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, preFiller *VolumeFiller, op *operations.Operation) error {
	return nil
}

// RefreshVolume provides same-pool volume and specific snapshots syncing functionality.
func (d *mock) RefreshVolume(vol Volume, srcVol Volume, srcSnapshots []Volume, op *operations.Operation) error {
	return nil
}

// DeleteVolume deletes a volume of the storage device. If any snapshots of the volume remain then this function
// will return an error.
func (d *mock) DeleteVolume(vol Volume, op *operations.Operation) error {
	return nil
}

// HasVolume indicates whether a specific volume exists on the storage pool.
func (d *mock) HasVolume(vol Volume) bool {
	return true
}

// ValidateVolume validates the supplied volume config. Optionally removes invalid keys from the volume's config.
func (d *mock) ValidateVolume(vol Volume, removeUnknownKeys bool) error {
	return nil
}

// UpdateVolume applies config changes to the volume.
func (d *mock) UpdateVolume(vol Volume, changedConfig map[string]string) error {
	if vol.contentType != ContentTypeFS {
		return ErrNotSupported
	}

	if _, changed := changedConfig["size"]; changed {
		err := d.SetVolumeQuota(vol, changedConfig["size"], nil)
		if err != nil {
			return err
		}
	}

	return nil
}

// GetVolumeUsage returns the disk space used by the volume.
func (d *mock) GetVolumeUsage(vol Volume) (int64, error) {
	return 0, nil
}

// SetVolumeQuota sets the quota on the volume.
func (d *mock) SetVolumeQuota(vol Volume, size string, op *operations.Operation) error {
	return nil
}

// GetVolumeDiskPath returns the location of a disk volume.
func (d *mock) GetVolumeDiskPath(vol Volume) (string, error) {
	return "", nil
}

// MountVolume simulates mounting a volume. As dir driver doesn't have volumes to mount it returns
// false indicating that there is no need to issue an unmount.
func (d *mock) MountVolume(vol Volume, op *operations.Operation) (bool, error) {
	return false, nil
}

// UnmountVolume simulates unmounting a volume. As dir driver doesn't have volumes to unmount it
// returns false indicating the volume was already unmounted.
func (d *mock) UnmountVolume(vol Volume, keepBlockDev bool, op *operations.Operation) (bool, error) {
	return false, nil
}

// RenameVolume renames a volume and its snapshots.
func (d *mock) RenameVolume(vol Volume, newVolName string, op *operations.Operation) error {
	return nil
}

// MigrateVolume sends a volume for migration.
func (d *mock) MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

// BackupVolume copies a volume (and optionally its snapshots) to a specified target path.
// This driver does not support optimized backups.
func (d *mock) BackupVolume(vol Volume, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

// CreateVolumeSnapshot creates a snapshot of a volume.
func (d *mock) CreateVolumeSnapshot(snapVol Volume, op *operations.Operation) error {
	return nil
}

// DeleteVolumeSnapshot removes a snapshot from the storage device. The volName and snapshotName
// must be bare names and should not be in the format "volume/snapshot".
func (d *mock) DeleteVolumeSnapshot(snapVol Volume, op *operations.Operation) error {
	return nil
}

// MountVolumeSnapshot sets up a read-only mount on top of the snapshot to avoid accidental modifications.
func (d *mock) MountVolumeSnapshot(snapVol Volume, op *operations.Operation) (bool, error) {
	return true, nil
}

// UnmountVolumeSnapshot removes the read-only mount placed on top of a snapshot.
func (d *mock) UnmountVolumeSnapshot(snapVol Volume, op *operations.Operation) (bool, error) {
	return true, nil
}

// VolumeSnapshots returns a list of snapshots for the volume.
func (d *mock) VolumeSnapshots(vol Volume, op *operations.Operation) ([]string, error) {
	return nil, nil
}

// RestoreVolume restores a volume from a snapshot.
func (d *mock) RestoreVolume(vol Volume, snapshotName string, op *operations.Operation) error {
	return nil
}

// RenameVolumeSnapshot renames a volume snapshot.
func (d *mock) RenameVolumeSnapshot(snapVol Volume, newSnapshotName string, op *operations.Operation) error {
	return nil
}
<|endoftext|>


<commit_before>package awstasks

import (
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/golang/glog"
	"k8s.io/kube-deploy/upup/pkg/fi"
	"k8s.io/kube-deploy/upup/pkg/fi/cloudup/awsup"
	"net/url"
)

type IAMRole struct {
	ID                 *string
	Name               *string
	RolePolicyDocument fi.Resource // "inline" IAM policy
}

var _ fi.CompareWithID = &InternetGateway{}

func (e *IAMRole) CompareWithID() *string {
	return e.Name
}

func (e *IAMRole) String() string {
	return fi.TaskAsString(e)
}

func (e *IAMRole) Find(c *fi.Context) (*IAMRole, error) {
	cloud := c.Cloud.(*awsup.AWSCloud)

	request := &iam.GetRoleInput{RoleName: e.Name}

	response, err := cloud.IAM.GetRole(request)
	if awsErr, ok := err.(awserr.Error); ok {
		if awsErr.Code() == "NoSuchEntity" {
			return nil, nil
		}
	}
	if err != nil {
		return nil, fmt.Errorf("error getting role: %v", err)
	}

	r := response.Role
	actual := &IAMRole{}
	actual.ID = r.RoleId
	actual.Name = r.RoleName
	if r.AssumeRolePolicyDocument != nil {
		// The AssumeRolePolicyDocument is URI encoded (?)
		policy := *r.AssumeRolePolicyDocument
		policy, err = url.QueryUnescape(policy)
		if err != nil {
			return nil, fmt.Errorf("error parsing AssumeRolePolicyDocument for IAMRole %q: %v", e.Name, err)
		}
		actual.RolePolicyDocument = fi.NewStringResource(policy)
	}

	glog.V(2).Infof("found matching IAMRole %q", *actual.ID)
	e.ID = actual.ID

	return actual, nil
}

func (e *IAMRole) Run(c *fi.Context) error {
	return fi.DefaultDeltaRunMethod(e, c)
}

func (s *IAMRole) CheckChanges(a, e, changes *IAMRole) error {
	if a != nil {
		if e.Name == nil {
			return fi.RequiredField("Name")
		}
	} else {
		if changes.Name == nil {
			return fi.CannotChangeField("Name")
		}
	}
	return nil
}

func (_ *IAMRole) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *IAMRole) error {
	policy, err := fi.ResourceAsString(e.RolePolicyDocument)
	if err != nil {
		return fmt.Errorf("error rendering PolicyDocument: %v", err)
	}

	if a == nil {
		glog.V(2).Infof("Creating IAMRole with Name:%q", *e.Name)

		request := &iam.CreateRoleInput{}
		request.AssumeRolePolicyDocument = aws.String(policy)
		request.RoleName = e.Name

		response, err := t.Cloud.IAM.CreateRole(request)
		if err != nil {
			return fmt.Errorf("error creating IAMRole: %v", err)
		}

		e.ID = response.Role.RoleId
	} else {
		if changes.RolePolicyDocument != nil {
			glog.V(2).Infof("Updating IAMRole AssumeRolePolicy  %q", *e.Name)

			request := &iam.UpdateAssumeRolePolicyInput{}
			request.PolicyDocument = aws.String(policy)
			request.RoleName = e.Name

			_, err := t.Cloud.IAM.UpdateAssumeRolePolicy(request)
			if err != nil {
				return fmt.Errorf("error updating IAMRole: %v", err)
			}
		}
	}

	return nil //return output.AddAWSTags(cloud.Tags(), v, "vpc")
}
<commit_msg>upup: Perform JSON comparison on IAMRole PolicyDocuments<commit_after>package awstasks

import (
	"fmt"

	"encoding/json"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/golang/glog"
	"k8s.io/kube-deploy/upup/pkg/fi"
	"k8s.io/kube-deploy/upup/pkg/fi/cloudup/awsup"
	"net/url"
	"reflect"
)

type IAMRole struct {
	ID                 *string
	Name               *string
	RolePolicyDocument fi.Resource // "inline" IAM policy
}

var _ fi.CompareWithID = &InternetGateway{}

func (e *IAMRole) CompareWithID() *string {
	return e.Name
}

func (e *IAMRole) String() string {
	return fi.TaskAsString(e)
}

func (e *IAMRole) Find(c *fi.Context) (*IAMRole, error) {
	cloud := c.Cloud.(*awsup.AWSCloud)

	request := &iam.GetRoleInput{RoleName: e.Name}

	response, err := cloud.IAM.GetRole(request)
	if awsErr, ok := err.(awserr.Error); ok {
		if awsErr.Code() == "NoSuchEntity" {
			return nil, nil
		}
	}
	if err != nil {
		return nil, fmt.Errorf("error getting role: %v", err)
	}

	r := response.Role
	actual := &IAMRole{}
	actual.ID = r.RoleId
	actual.Name = r.RoleName
	if r.AssumeRolePolicyDocument != nil {
		// The AssumeRolePolicyDocument is URI encoded (?)
		actualPolicy := *r.AssumeRolePolicyDocument
		actualPolicy, err = url.QueryUnescape(actualPolicy)
		if err != nil {
			return nil, fmt.Errorf("error parsing AssumeRolePolicyDocument for IAMRole %q: %v", e.Name, err)
		}

		// The RolePolicyDocument is reformatted by AWS
		// We parse both as JSON; if the json forms are equal we pretend the actual value is the expected value
		if e.RolePolicyDocument != nil {
			expectedPolicy, err := fi.ResourceAsString(e.RolePolicyDocument)
			if err != nil {
				return nil, fmt.Errorf("error reading expected RolePolicyDocument for IAMRole %q: %v", e.Name, err)
			}
			expectedJson := make(map[string]interface{})
			err = json.Unmarshal([]byte(expectedPolicy), &expectedJson)
			if err != nil {
				return nil, fmt.Errorf("error parsing expected RolePolicyDocument for IAMRole %q: %v", e.Name, err)
			}
			actualJson := make(map[string]interface{})
			err = json.Unmarshal([]byte(actualPolicy), &actualJson)
			if err != nil {
				return nil, fmt.Errorf("error parsing actual RolePolicyDocument for IAMRole %q: %v", e.Name, err)
			}

			if reflect.DeepEqual(actualJson, expectedJson) {
				glog.V(2).Infof("actual RolePolicyDocument was json-equal to expected; returning expected value")
				actualPolicy = expectedPolicy
			}
		}

		actual.RolePolicyDocument = fi.NewStringResource(actualPolicy)
	}

	glog.V(2).Infof("found matching IAMRole %q", *actual.ID)
	e.ID = actual.ID

	return actual, nil
}

func (e *IAMRole) Run(c *fi.Context) error {
	return fi.DefaultDeltaRunMethod(e, c)
}

func (s *IAMRole) CheckChanges(a, e, changes *IAMRole) error {
	if a != nil {
		if e.Name == nil {
			return fi.RequiredField("Name")
		}
	} else {
		if changes.Name == nil {
			return fi.CannotChangeField("Name")
		}
	}
	return nil
}

func (_ *IAMRole) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *IAMRole) error {
	policy, err := fi.ResourceAsString(e.RolePolicyDocument)
	if err != nil {
		return fmt.Errorf("error rendering PolicyDocument: %v", err)
	}

	if a == nil {
		glog.V(2).Infof("Creating IAMRole with Name:%q", *e.Name)

		request := &iam.CreateRoleInput{}
		request.AssumeRolePolicyDocument = aws.String(policy)
		request.RoleName = e.Name

		response, err := t.Cloud.IAM.CreateRole(request)
		if err != nil {
			return fmt.Errorf("error creating IAMRole: %v", err)
		}

		e.ID = response.Role.RoleId
	} else {
		if changes.RolePolicyDocument != nil {
			glog.V(2).Infof("Updating IAMRole AssumeRolePolicy  %q", *e.Name)

			request := &iam.UpdateAssumeRolePolicyInput{}
			request.PolicyDocument = aws.String(policy)
			request.RoleName = e.Name

			_, err := t.Cloud.IAM.UpdateAssumeRolePolicy(request)
			if err != nil {
				return fmt.Errorf("error updating IAMRole: %v", err)
			}
		}
	}

	return nil //return output.AddAWSTags(cloud.Tags(), v, "vpc")
}
<|endoftext|>


<commit_before>package handlers

import (
	"log"
	"net"
	"io"

	"github.com/seadsystem/Backend/DB/landingzone/constants"
)

// Handle a client's request
func HandleRequest(conn net.Conn) {
	log.Println("Got a connection.")

	var buffer []byte
	tempbuf := make([]byte, 1)

	for {
		log.Println("Reading bytes...")
		n, err := conn.Read(tempbuf)
		log.Printf("Read byte: %s\n", tempbuf[0])
		if err != nil {
			if err != io.EOF {
				log.Println("Read error:", err)
			} else {
				log.Println("Done reading bytes.")
			}
			break
		}
		buffer = append(buffer, tempbuf[:n]...)

	}

	if len(buffer) < 1 {
		log.Println("Error: received empty request")
	} else {
		log.Println("Received data:")
		log.Println(string(buffer))
	}

	conn.Write([]byte("Response"))
	conn.Close()
}
<commit_msg>Commented unused import<commit_after>package handlers

import (
	"log"
	"net"
	"io"

	//"github.com/seadsystem/Backend/DB/landingzone/constants"
)

// Handle a client's request
func HandleRequest(conn net.Conn) {
	log.Println("Got a connection.")

	var buffer []byte
	tempbuf := make([]byte, 1)

	for {
		log.Println("Reading bytes...")
		n, err := conn.Read(tempbuf)
		log.Printf("Read byte: %s\n", tempbuf[0])
		if err != nil {
			if err != io.EOF {
				log.Println("Read error:", err)
			} else {
				log.Println("Done reading bytes.")
			}
			break
		}
		buffer = append(buffer, tempbuf[:n]...)

	}

	if len(buffer) < 1 {
		log.Println("Error: received empty request")
	} else {
		log.Println("Received data:")
		log.Println(string(buffer))
	}

	conn.Write([]byte("Response"))
	conn.Close()
}
<|endoftext|>


<commit_before>package apachelog

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
	"time"
)

// Most commonly used log formats.
const (
	CombinedLogFromat = "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\""
	CommonLogFormat   = "%h %l %u %t \"%r\" %s %b"
)

// Time layout for parsing %t format.
const StandardEnglishFormat = "02/Jan/2006:15:04:05 -0700"

// A stateFn extracts an information contained in "line" and starting from
// "pos". The function is supposed to update the entry with the extracted
// information.
type stateFn func(entry *AccessLogEntry, line string, pos int) error

// makeStateFn constructs a chain of state functions from an expression, which
// corresponds to a list of format strings as defined by the Apache
// mod_log_config module documentation:
//    https://httpd.apache.org/docs/2.2/fr/mod/mod_log_config.html#formats
func makeStateFn(expr []string) (stateFn, error) {
	// End of the recursive call, we return nil.
	if expr == nil || len(expr) == 0 {
		return nil, nil
	}

	formatStr := expr[0]

	// Expressions can be quoted, so we keep a track of it and trim the quotes.
	var quoted bool
	if strings.HasPrefix(formatStr, "\"") {
		quoted = true
		strings.Trim(formatStr, "\"")
	}

	// Recursive call to determine the next state function.
	// XXX(gilliek): errors are reported right to left
	next, err := makeStateFn(expr[1:])
	if err != nil {
		return nil, err
	}

	switch f := LookupFormat(formatStr); f {
	case REMOTE_HOST:
		return parseRemoteHost(quoted, next), nil
	case UNKNOWN:
		fallthrough
	default:
		return nil, fmt.Errorf("%q format is not supported", formatStr)
	}
}

type Parser struct {
	br *bufio.Reader
	fn stateFn
}

// Combined creates a new parser that reads from r and that parses log entries
// using the Apache Combined Log format.
func Combined(r io.Reader) (*Parser, error) {
	return Custom(r, CombinedLogFromat)
}

// Common creates a new parser that reads from r and that parses log entries
// using the Apache Common Log format.
func Common(r io.Reader) (*Parser, error) {
	return Custom(r, CommonLogFormat)
}

// Custom creates a new parser that reads from r and that is capable of parsing
// log entries having the given format.
//
// The format is mostly the same as the one defined by the mod_log_config Apache
// module:
//    https://httpd.apache.org/docs/2.2/fr/mod/mod_log_config.html#formats
//
// However, unlike the Apache format, it does not support modifiers of any
// kind (<, >, !, ...).
func Custom(r io.Reader, format string) (*Parser, error) {
	if r == nil {
		return nil, errors.New("reader is nil")
	}
	fn, err := makeStateFn(strings.Split(format, " "))
	if err != nil {
		return nil, err
	}
	return &Parser{
		br: bufio.NewReader(r),
		fn: fn,
	}, nil
}

func (p *Parser) Parse() (*AccessLogEntry, error) {
	line, err := p.br.ReadString('\n')
	if err != nil {
		return nil, err
	}
	var entry AccessLogEntry
	if err := p.fn(&entry, line, 0); err != nil {
		return nil, err
	}
	return &entry, nil
}

func parseRemoteHost(quoted bool, next stateFn) stateFn {
	return func(entry *AccessLogEntry, line string, pos int) error {
		input := line[pos:] // narrow the input to the current position
		newPos := pos

		// handle quotes
		var (
			data string
			off  int
			err  error
		)
		if quoted {
			data, off, err = readWithQuotes(input)
			off++ // go after the "
		} else {
			data, off, err = readWithoutQuotes(input)
		}
		if err != nil {
			return err
		}
		newPos += off
		entry.RemoteHost = data

		// jump over next space, if any
		if line[newPos] == ' ' {
			newPos++
		}

		// If we reached the final \n character or that there is no further
		// state, we do not call the next function.
		if line[newPos] == '\n' || next == nil {
			return nil
		}

		return next(entry, line, newPos)
	}
}

func parseRemoteLogname(quoted bool, next stateFn) stateFn {
	return func(entry *AccessLogEntry, line string, pos int) error {
		input := line[pos:] // narrow the input to the current position
		newPos := pos

		// handle quotes
		var (
			data string
			off  int
			err  error
		)
		if quoted {
			data, off, err = readWithQuotes(input)
			off++ // go after the "
		} else {
			data, off, err = readWithoutQuotes(input)
		}
		if err != nil {
			return err
		}
		newPos += off
		entry.RemoteLogname = data

		// jump over next space, if any
		if line[newPos] == ' ' {
			newPos++
		}

		// If we reached the final \n character or that there is no further
		// state, we do not call the next function.
		if line[newPos] == '\n' || next == nil {
			return nil
		}

		return next(entry, line, newPos)
	}
}

// readWithQuotes extract the content of a quoted expression along with the
// ending quote position.
//
// s is expected to be a non empty string starting with a " (double quote)
// character. The closing double quote does not need to be at end of the string.
func readWithQuotes(s string) (data string, pos int, err error) {
	if s[0] != '"' {
		err = fmt.Errorf("got %q, want quote", s[0])
		return
	}
	pos++
	if idx := strings.Index(s[pos:], "\""); idx == -1 {
		err = errors.New("missing closing quote")
	} else {
		pos += idx
	}
	data = s[1:pos]
	return
}

func readWithoutQuotes(s string) (data string, pos int, err error) {
	if idx := strings.IndexAny(s, " \n"); idx == -1 {
		// should never happen
		err = errors.New("malformed input string")
	} else {
		pos += idx
	}
	data = s[:pos]
	return
}

func readDateTime(s string) (d time.Time, pos int, err error) {
	if s[0] != '[' {
		err = fmt.Errorf("got %q, want '['", s[0])
		return
	}
	pos++
	if idx := strings.Index(s[pos:], "]"); idx == -1 {
		err = errors.New("missing closing ']'")
	} else {
		pos += idx
		if d, err = time.Parse(StandardEnglishFormat, s[1:pos]); err != nil {
			err = errors.New("failed to parse datetime: " + err.Error())
		}
	}
	return
}

func readInt(s string) (data int64, pos int, err error) {
	if s[0] < '0' || s[0] > '9' {
		err = fmt.Errorf("got %q, want digit between 0 and 9", s[0])
		return
	}
	for pos = 1; pos < len(s); pos++ {
		if s[pos] < '0' || s[pos] > '9' {
			break
		}
	}
	// error should not occur since only digit are kept
	data, err = strconv.ParseInt(s[:pos], 10, 64)
	return
}
<commit_msg>apachelog: add "Parser" suffix to constructors<commit_after>package apachelog

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
	"time"
)

// Most commonly used log formats.
const (
	CombinedLogFromat = "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\""
	CommonLogFormat   = "%h %l %u %t \"%r\" %s %b"
)

// Time layout for parsing %t format.
const StandardEnglishFormat = "02/Jan/2006:15:04:05 -0700"

// A stateFn extracts an information contained in "line" and starting from
// "pos". The function is supposed to update the entry with the extracted
// information.
type stateFn func(entry *AccessLogEntry, line string, pos int) error

// makeStateFn constructs a chain of state functions from an expression, which
// corresponds to a list of format strings as defined by the Apache
// mod_log_config module documentation:
//    https://httpd.apache.org/docs/2.2/fr/mod/mod_log_config.html#formats
func makeStateFn(expr []string) (stateFn, error) {
	// End of the recursive call, we return nil.
	if expr == nil || len(expr) == 0 {
		return nil, nil
	}

	formatStr := expr[0]

	// Expressions can be quoted, so we keep a track of it and trim the quotes.
	var quoted bool
	if strings.HasPrefix(formatStr, "\"") {
		quoted = true
		strings.Trim(formatStr, "\"")
	}

	// Recursive call to determine the next state function.
	// XXX(gilliek): errors are reported right to left
	next, err := makeStateFn(expr[1:])
	if err != nil {
		return nil, err
	}

	switch f := LookupFormat(formatStr); f {
	case REMOTE_HOST:
		return parseRemoteHost(quoted, next), nil
	case UNKNOWN:
		fallthrough
	default:
		return nil, fmt.Errorf("%q format is not supported", formatStr)
	}
}

type Parser struct {
	br *bufio.Reader
	fn stateFn
}

// CombinedParser creates a new parser that reads from r and that parses log
// entries using the Apache Combined Log format.
func CombinedParser(r io.Reader) (*Parser, error) {
	return CustomParser(r, CombinedLogFromat)
}

// CommonParser creates a new parser that reads from r and that parses log entries
// using the Apache Common Log format.
func CommonParser(r io.Reader) (*Parser, error) {
	return CustomParser(r, CommonLogFormat)
}

// CustomParser creates a new parser that reads from r and that is capable of
// parsing log entries having the given format.
//
// The format is mostly the same as the one defined by the mod_log_config Apache
// module:
//    https://httpd.apache.org/docs/2.2/fr/mod/mod_log_config.html#formats
//
// However, unlike the Apache format, it does not support modifiers of any
// kind (<, >, !, ...).
func CustomParser(r io.Reader, format string) (*Parser, error) {
	if r == nil {
		return nil, errors.New("reader is nil")
	}
	fn, err := makeStateFn(strings.Split(format, " "))
	if err != nil {
		return nil, err
	}
	return &Parser{
		br: bufio.NewReader(r),
		fn: fn,
	}, nil
}

func (p *Parser) Parse() (*AccessLogEntry, error) {
	line, err := p.br.ReadString('\n')
	if err != nil {
		return nil, err
	}
	var entry AccessLogEntry
	if err := p.fn(&entry, line, 0); err != nil {
		return nil, err
	}
	return &entry, nil
}

func parseRemoteHost(quoted bool, next stateFn) stateFn {
	return func(entry *AccessLogEntry, line string, pos int) error {
		input := line[pos:] // narrow the input to the current position
		newPos := pos

		// handle quotes
		var (
			data string
			off  int
			err  error
		)
		if quoted {
			data, off, err = readWithQuotes(input)
			off++ // go after the "
		} else {
			data, off, err = readWithoutQuotes(input)
		}
		if err != nil {
			return err
		}
		newPos += off
		entry.RemoteHost = data

		// jump over next space, if any
		if line[newPos] == ' ' {
			newPos++
		}

		// If we reached the final \n character or that there is no further
		// state, we do not call the next function.
		if line[newPos] == '\n' || next == nil {
			return nil
		}

		return next(entry, line, newPos)
	}
}

func parseRemoteLogname(quoted bool, next stateFn) stateFn {
	return func(entry *AccessLogEntry, line string, pos int) error {
		input := line[pos:] // narrow the input to the current position
		newPos := pos

		// handle quotes
		var (
			data string
			off  int
			err  error
		)
		if quoted {
			data, off, err = readWithQuotes(input)
			off++ // go after the "
		} else {
			data, off, err = readWithoutQuotes(input)
		}
		if err != nil {
			return err
		}
		newPos += off
		entry.RemoteLogname = data

		// jump over next space, if any
		if line[newPos] == ' ' {
			newPos++
		}

		// If we reached the final \n character or that there is no further
		// state, we do not call the next function.
		if line[newPos] == '\n' || next == nil {
			return nil
		}

		return next(entry, line, newPos)
	}
}

// readWithQuotes extract the content of a quoted expression along with the
// ending quote position.
//
// s is expected to be a non empty string starting with a " (double quote)
// character. The closing double quote does not need to be at end of the string.
func readWithQuotes(s string) (data string, pos int, err error) {
	if s[0] != '"' {
		err = fmt.Errorf("got %q, want quote", s[0])
		return
	}
	pos++
	if idx := strings.Index(s[pos:], "\""); idx == -1 {
		err = errors.New("missing closing quote")
	} else {
		pos += idx
	}
	data = s[1:pos]
	return
}

func readWithoutQuotes(s string) (data string, pos int, err error) {
	if idx := strings.IndexAny(s, " \n"); idx == -1 {
		// should never happen
		err = errors.New("malformed input string")
	} else {
		pos += idx
	}
	data = s[:pos]
	return
}

func readDateTime(s string) (d time.Time, pos int, err error) {
	if s[0] != '[' {
		err = fmt.Errorf("got %q, want '['", s[0])
		return
	}
	pos++
	if idx := strings.Index(s[pos:], "]"); idx == -1 {
		err = errors.New("missing closing ']'")
	} else {
		pos += idx
		if d, err = time.Parse(StandardEnglishFormat, s[1:pos]); err != nil {
			err = errors.New("failed to parse datetime: " + err.Error())
		}
	}
	return
}

func readInt(s string) (data int64, pos int, err error) {
	if s[0] < '0' || s[0] > '9' {
		err = fmt.Errorf("got %q, want digit between 0 and 9", s[0])
		return
	}
	for pos = 1; pos < len(s); pos++ {
		if s[pos] < '0' || s[pos] > '9' {
			break
		}
	}
	// error should not occur since only digit are kept
	data, err = strconv.ParseInt(s[:pos], 10, 64)
	return
}
<|endoftext|>


<commit_before>package api

import (
	"testing"

	"github.com/NebulousLabs/Sia/build"
)

func TestVersion(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	st, err := createServerTester("TestVersion")
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.Close()
	var dv DaemonVersion
	st.getAPI("/daemon/version", &dv)
	if dv.Version != build.Version {
		t.Fatalf("/daemon/version reporting bad version: expected %v, got %v", build.Version, dv.Version)
	}
}

// TestStop tests the /daemon/stop handler.
func TestStop(t *testing.T) {
	st, err := createServerTester("TestStop")
	if err != nil {
		t.Fatal(err)
	}
	var success struct{ Success bool }
	err = st.getAPI("/daemon/stop", &success)
	if err != nil {
		t.Fatal(err)
	}
	err = st.getAPI("/daemon/stop", &success)
	if err == nil {
		t.Fatal("after /daemon/stop, subsequent calls should fail")
	}
}
<commit_msg>Add sleep to give time for server to close<commit_after>package api

import (
	"testing"
	"time"

	"github.com/NebulousLabs/Sia/build"
)

func TestVersion(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	st, err := createServerTester("TestVersion")
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.Close()
	var dv DaemonVersion
	st.getAPI("/daemon/version", &dv)
	if dv.Version != build.Version {
		t.Fatalf("/daemon/version reporting bad version: expected %v, got %v", build.Version, dv.Version)
	}
}

// TestStop tests the /daemon/stop handler.
func TestStop(t *testing.T) {
	st, err := createServerTester("TestStop")
	if err != nil {
		t.Fatal(err)
	}
	var success struct{ Success bool }
	err = st.getAPI("/daemon/stop", &success)
	if err != nil {
		t.Fatal(err)
	}
	// Sleep to give time for server to close, as /daemon/stop will return success
	// before Server.Close() is called.
	time.Sleep(200 * time.Millisecond)
	err = st.getAPI("/daemon/stop", &success)
	if err == nil {
		t.Fatal("after /daemon/stop, subsequent calls should fail")
	}
}
<|endoftext|>


<commit_before>package cmdutil

import (
	"fmt"
	"os"
	"strings"

	"github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/spf13/cobra"
)

// RunFixedArgs wraps a function in a function
// that checks its exact argument count.
func RunFixedArgs(numArgs int, run func([]string) error) func(*cobra.Command, []string) {
	return func(cmd *cobra.Command, args []string) {
		if len(args) != numArgs {
			fmt.Printf("expected %d arguments, got %d\n\n", numArgs, len(args))
			cmd.Usage()
		} else {
			if err := run(args); err != nil {
				ErrorAndExit("%v", err)
			}
		}
	}
}

// RunBoundedArgs wraps a function in a function
// that checks its argument count is within a range.
func RunBoundedArgs(min int, max int, run func([]string) error) func(*cobra.Command, []string) {
	return func(cmd *cobra.Command, args []string) {
		if len(args) < min || len(args) > max {
			fmt.Printf("expected %d to %d arguments, got %d\n\n", min, max, len(args))
			cmd.Usage()
		} else {
			if err := run(args); err != nil {
				ErrorAndExit("%v", err)
			}
		}
	}
}

// Run makes a new cobra run function that wraps the given function.
func Run(run func(args []string) error) func(*cobra.Command, []string) {
	return func(_ *cobra.Command, args []string) {
		if err := run(args); err != nil {
			ErrorAndExit(err.Error())
		}
	}
}

// ErrorAndExit errors with the given format and args, and then exits.
func ErrorAndExit(format string, args ...interface{}) {
	if errString := strings.TrimSpace(fmt.Sprintf(format, args...)); errString != "" {
		fmt.Fprintf(os.Stderr, "%s\n", errString)
	}
	os.Exit(1)
}

// ParseCommits takes a slice of arguments of the form "repo/commit-id" or
// "repo" (in which case we consider the commit ID to be empty), and returns
// a list of *pfs.Commits
func ParseCommits(args []string) ([]*pfs.Commit, error) {
	var commits []*pfs.Commit
	for _, arg := range args {
		parts := strings.SplitN(arg, "/", 2)
		hasRepo := len(parts) > 0 && parts[0] != ""
		hasCommit := len(parts) == 2 && parts[1] != ""
		if hasCommit && !hasRepo {
			return nil, fmt.Errorf("invalid commit id \"%s\": repo cannot be empty", arg)
		}
		commit := &pfs.Commit{
			Repo: &pfs.Repo{
				Name: parts[0],
			},
		}
		if len(parts) == 2 {
			commit.ID = parts[1]
		} else {
			commit.ID = ""
		}
		commits = append(commits, commit)
	}
	return commits, nil
}

// ParseBranches takes a slice of arguments of the form "repo/branch-name" or
// "repo" (in which case we consider the branch name to be empty), and returns
// a list of *pfs.Branches
func ParseBranches(args []string) ([]*pfs.Branch, error) {
	commits, err := ParseCommits(args)
	if err != nil {
		return nil, err
	}
	var result []*pfs.Branch
	for _, commit := range commits {
		result = append(result, &pfs.Branch{Repo: commit.Repo, Name: commit.ID})
	}
	return result, nil
}

// RepeatedStringArg is an alias for []string
type RepeatedStringArg []string

func (r *RepeatedStringArg) String() string {
	result := "["
	for i, s := range *r {
		if i != 0 {
			result += ", "
		}
		result += s
	}
	return result + "]"
}

// Set adds a string to r
func (r *RepeatedStringArg) Set(s string) error {
	*r = append(*r, s)
	return nil
}

// Type returns the string representation of the type of r
func (r *RepeatedStringArg) Type() string {
	return "[]string"
}

func DocsCommandTemplate() string {
    return `Usage:
  pachctl [command]{{if gt .Aliases 0}}

Aliases:
  {{.NameAndAliases}}
{{end}}{{if .HasExample}}

Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}

Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}

Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}

Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}
`
}
<commit_msg>checkpoint<commit_after>package cmdutil

import (
	"fmt"
	"os"
	"strings"

	"github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/spf13/cobra"
)

// RunFixedArgs wraps a function in a function
// that checks its exact argument count.
func RunFixedArgs(numArgs int, run func([]string) error) func(*cobra.Command, []string) {
	return func(cmd *cobra.Command, args []string) {
		if len(args) != numArgs {
			fmt.Printf("expected %d arguments, got %d\n\n", numArgs, len(args))
			cmd.Usage()
		} else {
			if err := run(args); err != nil {
				ErrorAndExit("%v", err)
			}
		}
	}
}

// RunBoundedArgs wraps a function in a function
// that checks its argument count is within a range.
func RunBoundedArgs(min int, max int, run func([]string) error) func(*cobra.Command, []string) {
	return func(cmd *cobra.Command, args []string) {
		if len(args) < min || len(args) > max {
			fmt.Printf("expected %d to %d arguments, got %d\n\n", min, max, len(args))
			cmd.Usage()
		} else {
			if err := run(args); err != nil {
				ErrorAndExit("%v", err)
			}
		}
	}
}

// Run makes a new cobra run function that wraps the given function.
func Run(run func(args []string) error) func(*cobra.Command, []string) {
	return func(_ *cobra.Command, args []string) {
		if err := run(args); err != nil {
			ErrorAndExit(err.Error())
		}
	}
}

// ErrorAndExit errors with the given format and args, and then exits.
func ErrorAndExit(format string, args ...interface{}) {
	if errString := strings.TrimSpace(fmt.Sprintf(format, args...)); errString != "" {
		fmt.Fprintf(os.Stderr, "%s\n", errString)
	}
	os.Exit(1)
}

// ParseCommits takes a slice of arguments of the form "repo/commit-id" or
// "repo" (in which case we consider the commit ID to be empty), and returns
// a list of *pfs.Commits
func ParseCommits(args []string) ([]*pfs.Commit, error) {
	var commits []*pfs.Commit
	for _, arg := range args {
		parts := strings.SplitN(arg, "/", 2)
		hasRepo := len(parts) > 0 && parts[0] != ""
		hasCommit := len(parts) == 2 && parts[1] != ""
		if hasCommit && !hasRepo {
			return nil, fmt.Errorf("invalid commit id \"%s\": repo cannot be empty", arg)
		}
		commit := &pfs.Commit{
			Repo: &pfs.Repo{
				Name: parts[0],
			},
		}
		if len(parts) == 2 {
			commit.ID = parts[1]
		} else {
			commit.ID = ""
		}
		commits = append(commits, commit)
	}
	return commits, nil
}

// ParseBranches takes a slice of arguments of the form "repo/branch-name" or
// "repo" (in which case we consider the branch name to be empty), and returns
// a list of *pfs.Branches
func ParseBranches(args []string) ([]*pfs.Branch, error) {
	commits, err := ParseCommits(args)
	if err != nil {
		return nil, err
	}
	var result []*pfs.Branch
	for _, commit := range commits {
		result = append(result, &pfs.Branch{Repo: commit.Repo, Name: commit.ID})
	}
	return result, nil
}

// RepeatedStringArg is an alias for []string
type RepeatedStringArg []string

func (r *RepeatedStringArg) String() string {
	result := "["
	for i, s := range *r {
		if i != 0 {
			result += ", "
		}
		result += s
	}
	return result + "]"
}

// Set adds a string to r
func (r *RepeatedStringArg) Set(s string) error {
	*r = append(*r, s)
	return nil
}

// Type returns the string representation of the type of r
func (r *RepeatedStringArg) Type() string {
	return "[]string"
}

// Sets the usage string for a 'docs' command.  Docs commands have no
// functionality except to output some docs and related commands, and
// should not specify a 'Run' attribute.
func SetDocsCommandUsage(command *cobra.Command, subcommands ...*cobra.Command) {
}

func DocsCommandTemplate() string {
    return `Usage:
  pachctl [command]{{if gt .Aliases 0}}

Aliases:
  {{.NameAndAliases}}
{{end}}{{if .HasExample}}

Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}

Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}

Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}

Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}
`
}
<|endoftext|>


<commit_before>package conf

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strconv"
	"strings"

	log "github.com/sirupsen/logrus"

	"github.com/ghodss/yaml"
	"github.com/p4tin/goaws/app"
	"github.com/p4tin/goaws/app/common"
)

var envs map[string]app.Environment

func LoadYamlConfig(filename string, env string) []string {
	ports := []string{"4100"}

	if filename == "" {
		filename, _ = filepath.Abs("./conf/goaws.yaml")
	}
	log.Warnf("Loading config file: %s", filename)
	yamlFile, err := ioutil.ReadFile(filename)
	if err != nil {
		return ports
	}

	err = yaml.Unmarshal(yamlFile, &envs)
	if err != nil {
		log.Errorf("err: %v\n", err)
		return ports
	}
	if env == "" {
		env = "Local"
	}

	if envs[env].Region == "" {
		app.CurrentEnvironment.Region = "local"
	}

	app.CurrentEnvironment = envs[env]

	if envs[env].Port != "" {
		ports = []string{envs[env].Port}
	} else if envs[env].SqsPort != "" && envs[env].SnsPort != "" {
		ports = []string{envs[env].SqsPort, envs[env].SnsPort}
		app.CurrentEnvironment.Port = envs[env].SqsPort
	}

	common.LogMessages = false
	common.LogFile = "./goaws_messages.log"

	if envs[env].LogToFile == true {
		common.LogMessages = true
		if envs[env].LogFile != "" {
			common.LogFile = envs[env].LogFile
		}
	}

	if app.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout == 0 {
		app.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout = 30
	}

	if app.CurrentEnvironment.AccountID == "" {
		app.CurrentEnvironment.AccountID = "queue"
	}

	if app.CurrentEnvironment.Host == "" {
		app.CurrentEnvironment.Host = "localhost"
		app.CurrentEnvironment.Port = "4100"
	}

	app.SyncQueues.Lock()
	app.SyncTopics.Lock()
	for _, queue := range envs[env].Queues {
		queueUrl := "http://" + app.CurrentEnvironment.Host + ":" + app.CurrentEnvironment.Port +
			"/" + app.CurrentEnvironment.AccountID + "/" + queue.Name
		if app.CurrentEnvironment.Region != "" {
			queueUrl = "http://" + app.CurrentEnvironment.Region + "." + app.CurrentEnvironment.Host + ":" +
				app.CurrentEnvironment.Port + "/" + app.CurrentEnvironment.AccountID + "/" + queue.Name
		}
		queueArn := "arn:aws:sqs:" + app.CurrentEnvironment.Region + ":" + app.CurrentEnvironment.AccountID + ":" + queue.Name

		if queue.ReceiveMessageWaitTimeSeconds == 0 {
			queue.ReceiveMessageWaitTimeSeconds = app.CurrentEnvironment.QueueAttributeDefaults.ReceiveMessageWaitTimeSeconds
		}

		app.SyncQueues.Queues[queue.Name] = &app.Queue{
			Name:                queue.Name,
			TimeoutSecs:         app.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout,
			Arn:                 queueArn,
			URL:                 queueUrl,
			ReceiveWaitTimeSecs: queue.ReceiveMessageWaitTimeSeconds,
			IsFIFO:              app.HasFIFOQueueName(queue.Name),
		}
	}

	// loop one more time to create queue's RedrivePolicy and assigned deadletter queues
	for _, queue := range envs[env].Queues {
		q := app.SyncQueues.Queues[queue.Name]
		if queue.RedrivePolicy != "" {
			err := setQueueRedrivePolicy(app.SyncQueues.Queues, q, queue.RedrivePolicy)
			if err != nil {
				log.Errorf("err: %s", err)
				return ports
			}
		}

	}

	for _, topic := range envs[env].Topics {
		topicArn := "arn:aws:sns:" + app.CurrentEnvironment.Region + ":" + app.CurrentEnvironment.AccountID + ":" + topic.Name

		newTopic := &app.Topic{Name: topic.Name, Arn: topicArn}
		newTopic.Subscriptions = make([]*app.Subscription, 0, 0)

		for _, subs := range topic.Subscriptions {
			var newSub *app.Subscription
			if strings.Contains(subs.Protocol, "http") {
				newSub = createHttpSubscription(subs)
			} else {
				//Queue does not exist yet, create it.
				newSub = createSqsSubscription(subs, topicArn)
			}
			if subs.FilterPolicy != "" {
				filterPolicy := &app.FilterPolicy{}
				err = json.Unmarshal([]byte(subs.FilterPolicy), filterPolicy)
				if err != nil {
					log.Errorf("err: %s", err)
					return ports
				}
				newSub.FilterPolicy = filterPolicy
			}

			newTopic.Subscriptions = append(newTopic.Subscriptions, newSub)
		}
		app.SyncTopics.Topics[topic.Name] = newTopic
	}

	app.SyncQueues.Unlock()
	app.SyncTopics.Unlock()

	return ports
}

func createHttpSubscription(configSubscription app.EnvSubsciption) *app.Subscription {
	newSub := &app.Subscription{EndPoint: configSubscription.EndPoint, Protocol: configSubscription.Protocol, TopicArn: configSubscription.TopicArn, Raw: configSubscription.Raw}
	subArn, _ := common.NewUUID()
	subArn = configSubscription.TopicArn + ":" + subArn
	newSub.SubscriptionArn = subArn
	return newSub
}

func createSqsSubscription(configSubscription app.EnvSubsciption, topicArn string) *app.Subscription {
	if _, ok := app.SyncQueues.Queues[configSubscription.QueueName]; !ok {
		queueUrl := "http://" + app.CurrentEnvironment.Host + ":" + app.CurrentEnvironment.Port +
			"/" + app.CurrentEnvironment.AccountID + "/" + configSubscription.QueueName
		if app.CurrentEnvironment.Region != "" {
			queueUrl = "http://" + app.CurrentEnvironment.Region + "." + app.CurrentEnvironment.Host + ":" +
				app.CurrentEnvironment.Port + "/" + app.CurrentEnvironment.AccountID + "/" + configSubscription.QueueName
		}
		queueArn := "arn:aws:sqs:" + app.CurrentEnvironment.Region + ":" + app.CurrentEnvironment.AccountID + ":" + configSubscription.QueueName
		app.SyncQueues.Queues[configSubscription.QueueName] = &app.Queue{
			Name:                configSubscription.QueueName,
			TimeoutSecs:         app.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout,
			Arn:                 queueArn,
			URL:                 queueUrl,
			ReceiveWaitTimeSecs: app.CurrentEnvironment.QueueAttributeDefaults.ReceiveMessageWaitTimeSeconds,
			IsFIFO:              app.HasFIFOQueueName(configSubscription.QueueName),
		}
	}
	qArn := app.SyncQueues.Queues[configSubscription.QueueName].Arn
	newSub := &app.Subscription{EndPoint: qArn, Protocol: "sqs", TopicArn: topicArn, Raw: configSubscription.Raw}
	subArn, _ := common.NewUUID()
	subArn = topicArn + ":" + subArn
	newSub.SubscriptionArn = subArn
	return newSub
}

func setQueueRedrivePolicy(queues map[string]*app.Queue, q *app.Queue, strRedrivePolicy string) error {
	// support both int and string maxReceiveCount (Amazon clients use string)
	redrivePolicy1 := struct {
		MaxReceiveCount     int    `json:"maxReceiveCount"`
		DeadLetterTargetArn string `json:"deadLetterTargetArn"`
	}{}
	redrivePolicy2 := struct {
		MaxReceiveCount     string `json:"maxReceiveCount"`
		DeadLetterTargetArn string `json:"deadLetterTargetArn"`
	}{}
	err1 := json.Unmarshal([]byte(strRedrivePolicy), &redrivePolicy1)
	err2 := json.Unmarshal([]byte(strRedrivePolicy), &redrivePolicy2)
	maxReceiveCount := redrivePolicy1.MaxReceiveCount
	deadLetterQueueArn := redrivePolicy1.DeadLetterTargetArn
	if err1 != nil && err2 != nil {
		return fmt.Errorf("invalid json for queue redrive policy ")
	} else if err1 != nil {
		maxReceiveCount, _ = strconv.Atoi(redrivePolicy2.MaxReceiveCount)
		deadLetterQueueArn = redrivePolicy2.DeadLetterTargetArn
	}

	if (deadLetterQueueArn != "" && maxReceiveCount == 0) ||
		(deadLetterQueueArn == "" && maxReceiveCount != 0) {
		return fmt.Errorf("invalid redrive policy values")
	}
	dlt := strings.Split(deadLetterQueueArn, ":")
	deadLetterQueueName := dlt[len(dlt)-1]
	deadLetterQueue, ok := queues[deadLetterQueueName]
	if !ok {
		return fmt.Errorf("deadletter queue not found")
	}
	q.DeadLetterQueue = deadLetterQueue
	q.MaxReceiveCount = maxReceiveCount

	return nil
}
<commit_msg>sqs: allow redrive-policy to be set from config yaml<commit_after>package conf

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strconv"
	"strings"

	log "github.com/sirupsen/logrus"

	"github.com/ghodss/yaml"
	"github.com/p4tin/goaws/app"
	"github.com/p4tin/goaws/app/common"
)

var envs map[string]app.Environment

func LoadYamlConfig(filename string, env string) []string {
	ports := []string{"4100"}

	if filename == "" {
		filename, _ = filepath.Abs("./conf/goaws.yaml")
	}
	log.Warnf("Loading config file: %s", filename)
	yamlFile, err := ioutil.ReadFile(filename)
	if err != nil {
		return ports
	}

	err = yaml.Unmarshal(yamlFile, &envs)
	if err != nil {
		log.Errorf("err: %v\n", err)
		return ports
	}
	if env == "" {
		env = "Local"
	}

	if envs[env].Region == "" {
		app.CurrentEnvironment.Region = "local"
	}

	app.CurrentEnvironment = envs[env]

	if envs[env].Port != "" {
		ports = []string{envs[env].Port}
	} else if envs[env].SqsPort != "" && envs[env].SnsPort != "" {
		ports = []string{envs[env].SqsPort, envs[env].SnsPort}
		app.CurrentEnvironment.Port = envs[env].SqsPort
	}

	common.LogMessages = false
	common.LogFile = "./goaws_messages.log"

	if envs[env].LogToFile == true {
		common.LogMessages = true
		if envs[env].LogFile != "" {
			common.LogFile = envs[env].LogFile
		}
	}

	if app.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout == 0 {
		app.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout = 30
	}

	if app.CurrentEnvironment.AccountID == "" {
		app.CurrentEnvironment.AccountID = "queue"
	}

	if app.CurrentEnvironment.Host == "" {
		app.CurrentEnvironment.Host = "localhost"
		app.CurrentEnvironment.Port = "4100"
	}

	app.SyncQueues.Lock()
	app.SyncTopics.Lock()
	for _, queue := range envs[env].Queues {
		queueUrl := "http://" + app.CurrentEnvironment.Host + ":" + app.CurrentEnvironment.Port +
			"/" + app.CurrentEnvironment.AccountID + "/" + queue.Name
		if app.CurrentEnvironment.Region != "" {
			queueUrl = "http://" + app.CurrentEnvironment.Region + "." + app.CurrentEnvironment.Host + ":" +
				app.CurrentEnvironment.Port + "/" + app.CurrentEnvironment.AccountID + "/" + queue.Name
		}
		queueArn := "arn:aws:sqs:" + app.CurrentEnvironment.Region + ":" + app.CurrentEnvironment.AccountID + ":" + queue.Name

		if queue.ReceiveMessageWaitTimeSeconds == 0 {
			queue.ReceiveMessageWaitTimeSeconds = app.CurrentEnvironment.QueueAttributeDefaults.ReceiveMessageWaitTimeSeconds
		}

		app.SyncQueues.Queues[queue.Name] = &app.Queue{
			Name:                queue.Name,
			TimeoutSecs:         app.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout,
			Arn:                 queueArn,
			URL:                 queueUrl,
			ReceiveWaitTimeSecs: queue.ReceiveMessageWaitTimeSeconds,
			IsFIFO:              app.HasFIFOQueueName(queue.Name),
		}
	}

	// loop one more time to create queue's RedrivePolicy and assign deadletter queues in case dead letter queue is defined first in the config
	for _, queue := range envs[env].Queues {
		q := app.SyncQueues.Queues[queue.Name]
		if queue.RedrivePolicy != "" {
			err := setQueueRedrivePolicy(app.SyncQueues.Queues, q, queue.RedrivePolicy)
			if err != nil {
				log.Errorf("err: %s", err)
				return ports
			}
		}

	}

	for _, topic := range envs[env].Topics {
		topicArn := "arn:aws:sns:" + app.CurrentEnvironment.Region + ":" + app.CurrentEnvironment.AccountID + ":" + topic.Name

		newTopic := &app.Topic{Name: topic.Name, Arn: topicArn}
		newTopic.Subscriptions = make([]*app.Subscription, 0, 0)

		for _, subs := range topic.Subscriptions {
			var newSub *app.Subscription
			if strings.Contains(subs.Protocol, "http") {
				newSub = createHttpSubscription(subs)
			} else {
				//Queue does not exist yet, create it.
				newSub = createSqsSubscription(subs, topicArn)
			}
			if subs.FilterPolicy != "" {
				filterPolicy := &app.FilterPolicy{}
				err = json.Unmarshal([]byte(subs.FilterPolicy), filterPolicy)
				if err != nil {
					log.Errorf("err: %s", err)
					return ports
				}
				newSub.FilterPolicy = filterPolicy
			}

			newTopic.Subscriptions = append(newTopic.Subscriptions, newSub)
		}
		app.SyncTopics.Topics[topic.Name] = newTopic
	}

	app.SyncQueues.Unlock()
	app.SyncTopics.Unlock()

	return ports
}

func createHttpSubscription(configSubscription app.EnvSubsciption) *app.Subscription {
	newSub := &app.Subscription{EndPoint: configSubscription.EndPoint, Protocol: configSubscription.Protocol, TopicArn: configSubscription.TopicArn, Raw: configSubscription.Raw}
	subArn, _ := common.NewUUID()
	subArn = configSubscription.TopicArn + ":" + subArn
	newSub.SubscriptionArn = subArn
	return newSub
}

func createSqsSubscription(configSubscription app.EnvSubsciption, topicArn string) *app.Subscription {
	if _, ok := app.SyncQueues.Queues[configSubscription.QueueName]; !ok {
		queueUrl := "http://" + app.CurrentEnvironment.Host + ":" + app.CurrentEnvironment.Port +
			"/" + app.CurrentEnvironment.AccountID + "/" + configSubscription.QueueName
		if app.CurrentEnvironment.Region != "" {
			queueUrl = "http://" + app.CurrentEnvironment.Region + "." + app.CurrentEnvironment.Host + ":" +
				app.CurrentEnvironment.Port + "/" + app.CurrentEnvironment.AccountID + "/" + configSubscription.QueueName
		}
		queueArn := "arn:aws:sqs:" + app.CurrentEnvironment.Region + ":" + app.CurrentEnvironment.AccountID + ":" + configSubscription.QueueName
		app.SyncQueues.Queues[configSubscription.QueueName] = &app.Queue{
			Name:                configSubscription.QueueName,
			TimeoutSecs:         app.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout,
			Arn:                 queueArn,
			URL:                 queueUrl,
			ReceiveWaitTimeSecs: app.CurrentEnvironment.QueueAttributeDefaults.ReceiveMessageWaitTimeSeconds,
			IsFIFO:              app.HasFIFOQueueName(configSubscription.QueueName),
		}
	}
	qArn := app.SyncQueues.Queues[configSubscription.QueueName].Arn
	newSub := &app.Subscription{EndPoint: qArn, Protocol: "sqs", TopicArn: topicArn, Raw: configSubscription.Raw}
	subArn, _ := common.NewUUID()
	subArn = topicArn + ":" + subArn
	newSub.SubscriptionArn = subArn
	return newSub
}

func setQueueRedrivePolicy(queues map[string]*app.Queue, q *app.Queue, strRedrivePolicy string) error {
	// support both int and string maxReceiveCount (Amazon clients use string)
	redrivePolicy1 := struct {
		MaxReceiveCount     int    `json:"maxReceiveCount"`
		DeadLetterTargetArn string `json:"deadLetterTargetArn"`
	}{}
	redrivePolicy2 := struct {
		MaxReceiveCount     string `json:"maxReceiveCount"`
		DeadLetterTargetArn string `json:"deadLetterTargetArn"`
	}{}
	err1 := json.Unmarshal([]byte(strRedrivePolicy), &redrivePolicy1)
	err2 := json.Unmarshal([]byte(strRedrivePolicy), &redrivePolicy2)
	maxReceiveCount := redrivePolicy1.MaxReceiveCount
	deadLetterQueueArn := redrivePolicy1.DeadLetterTargetArn
	if err1 != nil && err2 != nil {
		return fmt.Errorf("invalid json for queue redrive policy ")
	} else if err1 != nil {
		maxReceiveCount, _ = strconv.Atoi(redrivePolicy2.MaxReceiveCount)
		deadLetterQueueArn = redrivePolicy2.DeadLetterTargetArn
	}

	if (deadLetterQueueArn != "" && maxReceiveCount == 0) ||
		(deadLetterQueueArn == "" && maxReceiveCount != 0) {
		return fmt.Errorf("invalid redrive policy values")
	}
	dlt := strings.Split(deadLetterQueueArn, ":")
	deadLetterQueueName := dlt[len(dlt)-1]
	deadLetterQueue, ok := queues[deadLetterQueueName]
	if !ok {
		return fmt.Errorf("deadletter queue not found")
	}
	q.DeadLetterQueue = deadLetterQueue
	q.MaxReceiveCount = maxReceiveCount

	return nil
}
<|endoftext|>