<commit_before>package aws

import (
	"fmt"
	"log"
	"regexp"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dax"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func init() {
	resource.AddTestSweepers("aws_dax_cluster", &resource.Sweeper{
		Name: "aws_dax_cluster",
		F:    testSweepDAXClusters,
	})
}

func testSweepDAXClusters(region string) error {
	client, err := sharedClientForRegion(region)
	if err != nil {
		return fmt.Errorf("Error getting client: %s", err)
	}
	conn := client.(*AWSClient).daxconn

	resp, err := conn.DescribeClusters(&dax.DescribeClustersInput{})
	if err != nil {
		// GovCloud (with no DAX support) has an endpoint that responds with:
		// InvalidParameterValueException: Access Denied to API Version: DAX_V3
		if testSweepSkipSweepError(err) || isAWSErr(err, "InvalidParameterValueException", "Access Denied to API Version: DAX_V3") {
			log.Printf("[WARN] Skipping DAX Cluster sweep for %s: %s", region, err)
			return nil
		}
		return fmt.Errorf("Error retrieving DAX clusters: %s", err)
	}

	if len(resp.Clusters) == 0 {
		log.Print("[DEBUG] No DAX clusters to sweep")
		return nil
	}

	log.Printf("[INFO] Found %d DAX clusters", len(resp.Clusters))

	for _, cluster := range resp.Clusters {
		log.Printf("[INFO] Deleting DAX cluster %s", *cluster.ClusterName)
		_, err := conn.DeleteCluster(&dax.DeleteClusterInput{
			ClusterName: cluster.ClusterName,
		})
		if err != nil {
			return fmt.Errorf("Error deleting DAX cluster %s: %s", *cluster.ClusterName, err)
		}
	}

	return nil
}

func TestAccAWSDAXCluster_importBasic(t *testing.T) {
	resourceName := "aws_dax_cluster.test"
	rString := acctest.RandString(10)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfig(rString),
			},

			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSDAXCluster_basic(t *testing.T) {
	var dc dax.Cluster
	rString := acctest.RandString(10)
	iamRoleResourceName := "aws_iam_role.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfig(rString),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					testAccMatchResourceAttrRegionalARN("aws_dax_cluster.test", "arn", "dax", regexp.MustCompile("cache/.+")),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "cluster_name", regexp.MustCompile(`^tf-\w+$`)),
					resource.TestCheckResourceAttrPair("aws_dax_cluster.test", "iam_role_arn", iamRoleResourceName, "arn"),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "node_type", "dax.t2.small"),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "replication_factor", "1"),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "description", "test cluster"),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "parameter_group_name", regexp.MustCompile(`^default.dax`)),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "maintenance_window", regexp.MustCompile(`^\w{3}:\d{2}:\d{2}-\w{3}:\d{2}:\d{2}$`)),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "subnet_group_name", "default"),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "nodes.0.id", regexp.MustCompile(`^tf-[\w-]+$`)),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "configuration_endpoint", regexp.MustCompile(`:\d+$`)),
					resource.TestCheckResourceAttrSet(
						"aws_dax_cluster.test", "cluster_address"),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "port", regexp.MustCompile(`^\d+$`)),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "server_side_encryption.#", "1"),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "server_side_encryption.0.enabled", "false"),
				),
			},
		},
	})
}

func TestAccAWSDAXCluster_resize(t *testing.T) {
	var dc dax.Cluster
	rString := acctest.RandString(10)
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfigResize_singleNode(rString),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "replication_factor", "1"),
				),
			},
			{
				Config: testAccAWSDAXClusterConfigResize_multiNode(rString),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "replication_factor", "2"),
				),
			},
			{
				Config: testAccAWSDAXClusterConfigResize_singleNode(rString),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "replication_factor", "1"),
				),
			},
		},
	})
}

func TestAccAWSDAXCluster_encryption_disabled(t *testing.T) {
	var dc dax.Cluster
	rString := acctest.RandString(10)
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfigWithEncryption(rString, false),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr("aws_dax_cluster.test", "server_side_encryption.#", "1"),
					resource.TestCheckResourceAttr("aws_dax_cluster.test", "server_side_encryption.0.enabled", "false"),
				),
			},
			// Ensure it shows no difference when removing server_side_encryption configuration
			{
				Config:             testAccAWSDAXClusterConfig(rString),
				PlanOnly:           true,
				ExpectNonEmptyPlan: false,
			},
		},
	})
}

func TestAccAWSDAXCluster_encryption_enabled(t *testing.T) {
	var dc dax.Cluster
	rString := acctest.RandString(10)
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfigWithEncryption(rString, true),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr("aws_dax_cluster.test", "server_side_encryption.#", "1"),
					resource.TestCheckResourceAttr("aws_dax_cluster.test", "server_side_encryption.0.enabled", "true"),
				),
			},
			// Ensure it shows a difference when removing server_side_encryption configuration
			{
				Config:             testAccAWSDAXClusterConfig(rString),
				PlanOnly:           true,
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSDAXClusterDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).daxconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_dax_cluster" {
			continue
		}
		res, err := conn.DescribeClusters(&dax.DescribeClustersInput{
			ClusterNames: []*string{aws.String(rs.Primary.ID)},
		})
		if err != nil {
			// Verify the error is what we want
			if isAWSErr(err, dax.ErrCodeClusterNotFoundFault, "") {
				continue
			}
			return err
		}
		if len(res.Clusters) > 0 {
			return fmt.Errorf("still exist.")
		}
	}
	return nil
}

func testAccCheckAWSDAXClusterExists(n string, v *dax.Cluster) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No DAX cluster ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).daxconn
		resp, err := conn.DescribeClusters(&dax.DescribeClustersInput{
			ClusterNames: []*string{aws.String(rs.Primary.ID)},
		})
		if err != nil {
			return fmt.Errorf("DAX error: %v", err)
		}

		for _, c := range resp.Clusters {
			if *c.ClusterName == rs.Primary.ID {
				*v = *c
			}
		}

		return nil
	}
}

func testAccPreCheckAWSDax(t *testing.T) {
	conn := testAccProvider.Meta().(*AWSClient).daxconn

	input := &dax.DescribeClustersInput{}

	_, err := conn.DescribeClusters(input)

	if testAccPreCheckSkipError(err) || isAWSErr(err, "InvalidParameterValueException", "Access Denied to API Version: DAX_V3") {
		t.Skipf("skipping acceptance testing: %s", err)
	}

	if err != nil {
		t.Fatalf("unexpected PreCheck error: %s", err)
	}
}

var baseConfig = `
resource "aws_iam_role" "test" {
  assume_role_policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
       {
            "Effect": "Allow",
            "Principal": {
                "Service": "dax.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
}

resource "aws_iam_role_policy" "test" {
  role = "${aws_iam_role.test.id}"

  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "dynamodb:*",
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
EOF
}
`

func testAccAWSDAXClusterConfig(rString string) string {
	return fmt.Sprintf(`%s
resource "aws_dax_cluster" "test" {
  cluster_name       = "tf-%s"
  iam_role_arn       = "${aws_iam_role.test.arn}"
  node_type          = "dax.t2.small"
  replication_factor = 1
  description        = "test cluster"

  tags = {
    foo = "bar"
  }
}
`, baseConfig, rString)
}

func testAccAWSDAXClusterConfigWithEncryption(rString string, enabled bool) string {
	return fmt.Sprintf(`%s
resource "aws_dax_cluster" "test" {
  cluster_name       = "tf-%s"
  iam_role_arn       = "${aws_iam_role.test.arn}"
  node_type          = "dax.t2.small"
  replication_factor = 1
  description        = "test cluster"

  tags = {
    foo = "bar"
  }

  server_side_encryption {
    enabled = %t
  }
}
`, baseConfig, rString, enabled)
}

func testAccAWSDAXClusterConfigResize_singleNode(rString string) string {
	return fmt.Sprintf(`%s
resource "aws_dax_cluster" "test" {
  cluster_name       = "tf-%s"
  iam_role_arn       = "${aws_iam_role.test.arn}"
  node_type          = "dax.r3.large"
  replication_factor = 1
}
`, baseConfig, rString)
}

func testAccAWSDAXClusterConfigResize_multiNode(rString string) string {
	return fmt.Sprintf(`%s
resource "aws_dax_cluster" "test" {
  cluster_name       = "tf-%s"
  iam_role_arn       = "${aws_iam_role.test.arn}"
  node_type          = "dax.r3.large"
  replication_factor = 2
}
`, baseConfig, rString)
}
<commit_msg>Update aws/resource_aws_dax_cluster_test.go<commit_after>package aws

import (
	"fmt"
	"log"
	"regexp"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dax"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func init() {
	resource.AddTestSweepers("aws_dax_cluster", &resource.Sweeper{
		Name: "aws_dax_cluster",
		F:    testSweepDAXClusters,
	})
}

func testSweepDAXClusters(region string) error {
	client, err := sharedClientForRegion(region)
	if err != nil {
		return fmt.Errorf("Error getting client: %s", err)
	}
	conn := client.(*AWSClient).daxconn

	resp, err := conn.DescribeClusters(&dax.DescribeClustersInput{})
	if err != nil {
		// GovCloud (with no DAX support) has an endpoint that responds with:
		// InvalidParameterValueException: Access Denied to API Version: DAX_V3
		if testSweepSkipSweepError(err) || isAWSErr(err, "InvalidParameterValueException", "Access Denied to API Version: DAX_V3") {
			log.Printf("[WARN] Skipping DAX Cluster sweep for %s: %s", region, err)
			return nil
		}
		return fmt.Errorf("Error retrieving DAX clusters: %s", err)
	}

	if len(resp.Clusters) == 0 {
		log.Print("[DEBUG] No DAX clusters to sweep")
		return nil
	}

	log.Printf("[INFO] Found %d DAX clusters", len(resp.Clusters))

	for _, cluster := range resp.Clusters {
		log.Printf("[INFO] Deleting DAX cluster %s", *cluster.ClusterName)
		_, err := conn.DeleteCluster(&dax.DeleteClusterInput{
			ClusterName: cluster.ClusterName,
		})
		if err != nil {
			return fmt.Errorf("Error deleting DAX cluster %s: %s", *cluster.ClusterName, err)
		}
	}

	return nil
}

func TestAccAWSDAXCluster_importBasic(t *testing.T) {
	resourceName := "aws_dax_cluster.test"
	rString := acctest.RandString(10)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfig(rString),
			},

			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSDAXCluster_basic(t *testing.T) {
	var dc dax.Cluster
	rString := acctest.RandString(10)
	iamRoleResourceName := "aws_iam_role.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfig(rString),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					testAccMatchResourceAttrRegionalARN("aws_dax_cluster.test", "arn", "dax", regexp.MustCompile("cache/.+")),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "cluster_name", regexp.MustCompile(`^tf-\w+$`)),
					resource.TestCheckResourceAttrPair("aws_dax_cluster.test", "iam_role_arn", iamRoleResourceName, "arn"),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "node_type", "dax.t2.small"),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "replication_factor", "1"),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "description", "test cluster"),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "parameter_group_name", regexp.MustCompile(`^default.dax`)),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "maintenance_window", regexp.MustCompile(`^\w{3}:\d{2}:\d{2}-\w{3}:\d{2}:\d{2}$`)),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "subnet_group_name", "default"),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "nodes.0.id", regexp.MustCompile(`^tf-[\w-]+$`)),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "configuration_endpoint", regexp.MustCompile(`:\d+$`)),
					resource.TestCheckResourceAttrSet(
						"aws_dax_cluster.test", "cluster_address"),
					resource.TestMatchResourceAttr(
						"aws_dax_cluster.test", "port", regexp.MustCompile(`^\d+$`)),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "server_side_encryption.#", "1"),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "server_side_encryption.0.enabled", "false"),
				),
			},
		},
	})
}

func TestAccAWSDAXCluster_resize(t *testing.T) {
	var dc dax.Cluster
	rString := acctest.RandString(10)
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfigResize_singleNode(rString),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "replication_factor", "1"),
				),
			},
			{
				Config: testAccAWSDAXClusterConfigResize_multiNode(rString),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "replication_factor", "2"),
				),
			},
			{
				Config: testAccAWSDAXClusterConfigResize_singleNode(rString),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr(
						"aws_dax_cluster.test", "replication_factor", "1"),
				),
			},
		},
	})
}

func TestAccAWSDAXCluster_encryption_disabled(t *testing.T) {
	var dc dax.Cluster
	rString := acctest.RandString(10)
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfigWithEncryption(rString, false),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr("aws_dax_cluster.test", "server_side_encryption.#", "1"),
					resource.TestCheckResourceAttr("aws_dax_cluster.test", "server_side_encryption.0.enabled", "false"),
				),
			},
			// Ensure it shows no difference when removing server_side_encryption configuration
			{
				Config:             testAccAWSDAXClusterConfig(rString),
				PlanOnly:           true,
				ExpectNonEmptyPlan: false,
			},
		},
	})
}

func TestAccAWSDAXCluster_encryption_enabled(t *testing.T) {
	var dc dax.Cluster
	rString := acctest.RandString(10)
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSDax(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSDAXClusterDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSDAXClusterConfigWithEncryption(rString, true),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSDAXClusterExists("aws_dax_cluster.test", &dc),
					resource.TestCheckResourceAttr("aws_dax_cluster.test", "server_side_encryption.#", "1"),
					resource.TestCheckResourceAttr("aws_dax_cluster.test", "server_side_encryption.0.enabled", "true"),
				),
			},
			// Ensure it shows a difference when removing server_side_encryption configuration
			{
				Config:             testAccAWSDAXClusterConfig(rString),
				PlanOnly:           true,
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSDAXClusterDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).daxconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_dax_cluster" {
			continue
		}
		res, err := conn.DescribeClusters(&dax.DescribeClustersInput{
			ClusterNames: []*string{aws.String(rs.Primary.ID)},
		})
		if err != nil {
			// Verify the error is what we want
			if isAWSErr(err, dax.ErrCodeClusterNotFoundFault, "") {
				continue
			}
			return err
		}
		if len(res.Clusters) > 0 {
			return fmt.Errorf("still exist.")
		}
	}
	return nil
}

func testAccCheckAWSDAXClusterExists(n string, v *dax.Cluster) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No DAX cluster ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).daxconn
		resp, err := conn.DescribeClusters(&dax.DescribeClustersInput{
			ClusterNames: []*string{aws.String(rs.Primary.ID)},
		})
		if err != nil {
			return fmt.Errorf("DAX error: %v", err)
		}

		for _, c := range resp.Clusters {
			if *c.ClusterName == rs.Primary.ID {
				*v = *c
			}
		}

		return nil
	}
}

func testAccPreCheckAWSDax(t *testing.T) {
	conn := testAccProvider.Meta().(*AWSClient).daxconn

	input := &dax.DescribeClustersInput{}

	_, err := conn.DescribeClusters(input)

	if testAccPreCheckSkipError(err) || isAWSErr(err, "InvalidParameterValueException", "Access Denied to API Version: DAX_V3") {
		t.Skipf("skipping acceptance testing: %s", err)
	}

	if err != nil {
		t.Fatalf("unexpected PreCheck error: %s", err)
	}
}

const baseConfig = `
resource "aws_iam_role" "test" {
  assume_role_policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
       {
            "Effect": "Allow",
            "Principal": {
                "Service": "dax.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
}

resource "aws_iam_role_policy" "test" {
  role = "${aws_iam_role.test.id}"

  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "dynamodb:*",
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
EOF
}
`

func testAccAWSDAXClusterConfig(rString string) string {
	return fmt.Sprintf(`%s
resource "aws_dax_cluster" "test" {
  cluster_name       = "tf-%s"
  iam_role_arn       = "${aws_iam_role.test.arn}"
  node_type          = "dax.t2.small"
  replication_factor = 1
  description        = "test cluster"

  tags = {
    foo = "bar"
  }
}
`, baseConfig, rString)
}

func testAccAWSDAXClusterConfigWithEncryption(rString string, enabled bool) string {
	return fmt.Sprintf(`%s
resource "aws_dax_cluster" "test" {
  cluster_name       = "tf-%s"
  iam_role_arn       = "${aws_iam_role.test.arn}"
  node_type          = "dax.t2.small"
  replication_factor = 1
  description        = "test cluster"

  tags = {
    foo = "bar"
  }

  server_side_encryption {
    enabled = %t
  }
}
`, baseConfig, rString, enabled)
}

func testAccAWSDAXClusterConfigResize_singleNode(rString string) string {
	return fmt.Sprintf(`%s
resource "aws_dax_cluster" "test" {
  cluster_name       = "tf-%s"
  iam_role_arn       = "${aws_iam_role.test.arn}"
  node_type          = "dax.r3.large"
  replication_factor = 1
}
`, baseConfig, rString)
}

func testAccAWSDAXClusterConfigResize_multiNode(rString string) string {
	return fmt.Sprintf(`%s
resource "aws_dax_cluster" "test" {
  cluster_name       = "tf-%s"
  iam_role_arn       = "${aws_iam_role.test.arn}"
  node_type          = "dax.r3.large"
  replication_factor = 2
}
`, baseConfig, rString)
}
<|endoftext|>


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

package api

import (
	"time"

	"github.com/GoogleCloudPlatform/heapster/sinks/cache"
)

type DecoderV2 interface {
	// Timeseries returns the metrics found in input as a timeseries slice.
	TimeseriesFromPods([]*cache.PodElement) ([]Timeseries, error)
	TimeseriesFromContainers([]*cache.ContainerElement) ([]Timeseries, error)
}

type v2Decoder struct {
	supportedStatMetrics []SupportedStatMetric

	// TODO: Garbage collect data.
	// TODO: Deprecate this once we the core is fixed to never export duplicate stats.
	lastExported map[timeseriesKey]time.Time
}

func (self *v2Decoder) TimeseriesFromPods(pods []*cache.PodElement) ([]Timeseries, error) {
	var result []Timeseries
	// Format metrics and push them.
	for index := range pods {
		result = append(result, self.getPodMetrics(pods[index])...)
	}
	return result, nil
}
func (self *v2Decoder) TimeseriesFromContainers(containers []*cache.ContainerElement) ([]Timeseries, error) {
	labels := make(map[string]string)
	var result []Timeseries
	for index := range containers {
		labels[LabelHostname] = containers[index].Hostname
		result = append(result, self.getContainerMetrics(containers[index], copyLabels(labels))...)
	}
	return result, nil
}

// Generate the labels.
func (self *v2Decoder) getPodLabels(pod *cache.PodElement) map[string]string {
	labels := make(map[string]string)
	labels[LabelPodId] = pod.UID
	labels[LabelPodNamespace] = pod.Namespace
	labels[LabelPodNamespaceUID] = pod.NamespaceUID
	labels[LabelPodName] = pod.Name
	labels[LabelLabels] = LabelsToString(pod.Labels, ",")
	labels[LabelHostname] = pod.Hostname
	labels[LabelHostID] = pod.ExternalID

	return labels
}

func (self *v2Decoder) getPodMetrics(pod *cache.PodElement) []Timeseries {
	// Break the individual metrics from the container statistics.
	result := []Timeseries{}
	if pod == nil || pod.Containers == nil {
		return result
	}
	for index := range pod.Containers {
		timeseries := self.getContainerMetrics(pod.Containers[index], self.getPodLabels(pod))
		result = append(result, timeseries...)
	}

	return result
}

func copyLabels(labels map[string]string) map[string]string {
	c := make(map[string]string, len(labels))
	for key, val := range labels {
		c[key] = val
	}
	return c
}

func (self *v2Decoder) getContainerMetrics(container *cache.ContainerElement, labels map[string]string) []Timeseries {
	if container == nil {
		return nil
	}
	labels[LabelContainerName] = container.Name
	labels[LabelHostID] = container.ExternalID
	// One metric value per data point.
	var result []Timeseries
	labelsAsString := LabelsToString(labels, ",")
	for _, metric := range container.Metrics {
		if metric == nil || metric.Spec == nil || metric.Stats == nil {
			continue
		}
		// Add all supported metrics that have values.
		for index, supported := range self.supportedStatMetrics {
			// Finest allowed granularity is seconds.
			metric.Stats.Timestamp = metric.Stats.Timestamp.Round(time.Second)
			key := timeseriesKey{
				Name:   supported.Name,
				Labels: labelsAsString,
			}
			// TODO: remove this once the heapster source is tested to not provide duplicate metric.Statss.

			if data, ok := self.lastExported[key]; ok && data.After(metric.Stats.Timestamp) {
				continue
			}

			if supported.HasValue(metric.Spec) {
				// Cumulative metric.Statss have container creation time as their start time.
				var startTime time.Time
				if supported.Type == MetricCumulative {
					startTime = metric.Spec.CreationTime
				} else {
					startTime = metric.Stats.Timestamp
				}
				points := supported.GetValue(metric.Spec, metric.Stats)
				for _, point := range points {
					labels := copyLabels(labels)
					for name, value := range point.labels {
						labels[name] = value
					}
					timeseries := Timeseries{
						MetricDescriptor: &self.supportedStatMetrics[index].MetricDescriptor,
						Point: &Point{
							Name:   supported.Name,
							Labels: labels,
							Start:  startTime.Round(time.Second),
							End:    metric.Stats.Timestamp,
							Value:  point.value,
						},
					}
					result = append(result, timeseries)
				}
			}
			self.lastExported[key] = metric.Stats.Timestamp
		}

	}

	return result
}

func NewV2Decoder() DecoderV2 {
	// Get supported metrics.
	return &v2Decoder{
		supportedStatMetrics: statMetrics,
		lastExported:         make(map[timeseriesKey]time.Time),
	}
}
<commit_msg>Fix issue with exporting host_id for pod containers.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
	"time"

	"github.com/GoogleCloudPlatform/heapster/sinks/cache"
)

type DecoderV2 interface {
	// Timeseries returns the metrics found in input as a timeseries slice.
	TimeseriesFromPods([]*cache.PodElement) ([]Timeseries, error)
	TimeseriesFromContainers([]*cache.ContainerElement) ([]Timeseries, error)
}

type v2Decoder struct {
	supportedStatMetrics []SupportedStatMetric

	// TODO: Garbage collect data.
	// TODO: Deprecate this once we the core is fixed to never export duplicate stats.
	lastExported map[timeseriesKey]time.Time
}

func (self *v2Decoder) TimeseriesFromPods(pods []*cache.PodElement) ([]Timeseries, error) {
	var result []Timeseries
	// Format metrics and push them.
	for index := range pods {
		result = append(result, self.getPodMetrics(pods[index])...)
	}
	return result, nil
}
func (self *v2Decoder) TimeseriesFromContainers(containers []*cache.ContainerElement) ([]Timeseries, error) {
	labels := make(map[string]string)
	var result []Timeseries
	for index := range containers {
		labels[LabelHostname] = containers[index].Hostname
		result = append(result, self.getContainerMetrics(containers[index], copyLabels(labels))...)
	}
	return result, nil
}

// Generate the labels.
func (self *v2Decoder) getPodLabels(pod *cache.PodElement) map[string]string {
	labels := make(map[string]string)
	labels[LabelPodId] = pod.UID
	labels[LabelPodNamespace] = pod.Namespace
	labels[LabelPodNamespaceUID] = pod.NamespaceUID
	labels[LabelPodName] = pod.Name
	labels[LabelLabels] = LabelsToString(pod.Labels, ",")
	labels[LabelHostname] = pod.Hostname
	labels[LabelHostID] = pod.ExternalID

	return labels
}

func (self *v2Decoder) getPodMetrics(pod *cache.PodElement) []Timeseries {
	// Break the individual metrics from the container statistics.
	result := []Timeseries{}
	if pod == nil || pod.Containers == nil {
		return result
	}
	for index := range pod.Containers {
		timeseries := self.getContainerMetrics(pod.Containers[index], self.getPodLabels(pod))
		result = append(result, timeseries...)
	}

	return result
}

func copyLabels(labels map[string]string) map[string]string {
	c := make(map[string]string, len(labels))
	for key, val := range labels {
		c[key] = val
	}
	return c
}

func (self *v2Decoder) getContainerMetrics(container *cache.ContainerElement, labels map[string]string) []Timeseries {
	if container == nil {
		return nil
	}
	labels[LabelContainerName] = container.Name
	// One metric value per data point.
	var result []Timeseries
	labelsAsString := LabelsToString(labels, ",")
	for _, metric := range container.Metrics {
		if metric == nil || metric.Spec == nil || metric.Stats == nil {
			continue
		}
		// Add all supported metrics that have values.
		for index, supported := range self.supportedStatMetrics {
			// Finest allowed granularity is seconds.
			metric.Stats.Timestamp = metric.Stats.Timestamp.Round(time.Second)
			key := timeseriesKey{
				Name:   supported.Name,
				Labels: labelsAsString,
			}
			// TODO: remove this once the heapster source is tested to not provide duplicate metric.Statss.

			if data, ok := self.lastExported[key]; ok && data.After(metric.Stats.Timestamp) {
				continue
			}

			if supported.HasValue(metric.Spec) {
				// Cumulative metric.Statss have container creation time as their start time.
				var startTime time.Time
				if supported.Type == MetricCumulative {
					startTime = metric.Spec.CreationTime
				} else {
					startTime = metric.Stats.Timestamp
				}
				points := supported.GetValue(metric.Spec, metric.Stats)
				for _, point := range points {
					labels := copyLabels(labels)
					for name, value := range point.labels {
						labels[name] = value
					}
					timeseries := Timeseries{
						MetricDescriptor: &self.supportedStatMetrics[index].MetricDescriptor,
						Point: &Point{
							Name:   supported.Name,
							Labels: labels,
							Start:  startTime.Round(time.Second),
							End:    metric.Stats.Timestamp,
							Value:  point.value,
						},
					}
					result = append(result, timeseries)
				}
			}
			self.lastExported[key] = metric.Stats.Timestamp
		}

	}

	return result
}

func NewV2Decoder() DecoderV2 {
	// Get supported metrics.
	return &v2Decoder{
		supportedStatMetrics: statMetrics,
		lastExported:         make(map[timeseriesKey]time.Time),
	}
}
<|endoftext|>


<commit_before>package protobufcrpc

import (
	"encoding/binary"
	"errors"
	"net"
	"reflect"

	"github.com/golang/protobuf/proto"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

var (
	errTooLong   = errors.New("Too long input")
	errBadN      = errors.New("Read or Write returned unexpected n")
	errBadMethod = errors.New("Bad method")
)

type Method func(input []byte) ([]byte, error)

type Server struct {
	methods []Method
}

func New(desc *grpc.ServiceDesc, service interface{}) (*Server, error) {
	s := &Server{}
	for _, method := range desc.Methods {
		m := reflect.ValueOf(service).MethodByName(method.MethodName)
		reqType := m.Type().In(1).Elem()
		handler := func(input []byte) ([]byte, error) {
			req := reflect.New(reqType)
			pb := req.Interface().(proto.Message)
			if err := proto.Unmarshal(input, pb); err != nil {
				return nil, err
			}
			ctx := reflect.ValueOf(context.Background())
			results := m.Call([]reflect.Value{ctx, req})
			if results[1].Interface() != nil {
				if err := results[1].Interface().(error); err != nil {
					return nil, err
				}
			}
			pb = results[0].Interface().(proto.Message)
			return proto.Marshal(pb)
		}
		s.methods = append(s.methods, handler)
	}
	return s, nil
}

func (s *Server) Serve(conn net.Conn) error {
	// Read.
	var methodIndex, messageLength, requestID int32
	if err := binary.Read(conn, binary.LittleEndian, &methodIndex); err != nil {
		return err
	}
	if err := binary.Read(conn, binary.LittleEndian, &messageLength); err != nil {
		return err
	}
	if err := binary.Read(conn, binary.LittleEndian, &requestID); err != nil {
		return err
	}
	if messageLength > 4096 {
		return errTooLong
	}
	input := make([]byte, messageLength)
	n, err := conn.Read(input)
	if err != nil {
		return err
	}
	if n != int(messageLength) {
		return errBadN
	}
	if methodIndex < 0 || int(methodIndex) > len(s.methods) {
		return errBadMethod
	}
	// Run.
	output, err := s.methods[methodIndex](input)
	if err != nil {
		return err
	}
	// Write.
	success := int32(0)
	if err := binary.Write(conn, binary.LittleEndian, success); err != nil {
		return err
	}
	if err := binary.Write(conn, binary.LittleEndian, methodIndex); err != nil {
		return err
	}
	if err := binary.Write(conn, binary.LittleEndian, int32(len(output))); err != nil {
		return err
	}
	if err := binary.Write(conn, binary.LittleEndian, requestID); err != nil {
		return err
	}
	n, err = conn.Write(output)
	if err != nil {
		return err
	}
	if n != len(output) {
		return errBadN
	}
	return nil
}
<commit_msg>implement errors in protobufcrpc<commit_after>package protobufcrpc

import (
	"encoding/binary"
	"errors"
	"log"
	"net"
	"reflect"

	"github.com/golang/protobuf/proto"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

var (
	errTooLong   = errors.New("Too long input")
	errBadN      = errors.New("Read or Write returned unexpected n")
	errBadMethod = errors.New("Bad method")
)

type Method func(input []byte) ([]byte, error)

type Server struct {
	methods      []Method
	methodsNames []string
}

func New(desc *grpc.ServiceDesc, service interface{}) (*Server, error) {
	s := &Server{}
	for _, method := range desc.Methods {
		m := reflect.ValueOf(service).MethodByName(method.MethodName)
		reqType := m.Type().In(1).Elem()
		handler := func(input []byte) ([]byte, error) {
			req := reflect.New(reqType)
			pb := req.Interface().(proto.Message)
			if err := proto.Unmarshal(input, pb); err != nil {
				return nil, err
			}
			ctx := reflect.ValueOf(context.Background())
			results := m.Call([]reflect.Value{ctx, req})
			if results[1].Interface() != nil {
				if err := results[1].Interface().(error); err != nil {
					return nil, err
				}
			}
			pb = results[0].Interface().(proto.Message)
			return proto.Marshal(pb)
		}
		s.methods = append(s.methods, handler)
		s.methodsNames = append(s.methodsNames, method.MethodName)
	}
	return s, nil
}

func (s *Server) Serve(conn net.Conn) error {
	// Read.
	var methodIndex, messageLength, requestID int32
	if err := binary.Read(conn, binary.LittleEndian, &methodIndex); err != nil {
		return err
	}
	if err := binary.Read(conn, binary.LittleEndian, &messageLength); err != nil {
		return err
	}
	if err := binary.Read(conn, binary.LittleEndian, &requestID); err != nil {
		return err
	}
	if messageLength > 4096 {
		return errTooLong
	}
	input := make([]byte, messageLength)
	n, err := conn.Read(input)
	if err != nil {
		return err
	}
	if n != int(messageLength) {
		return errBadN
	}
	if methodIndex < 0 || int(methodIndex) > len(s.methods) {
		return errBadMethod
	}
	// Run.
	output, err := s.methods[methodIndex](input)
	status := int32(0)
	if err != nil {
		name := s.methodsNames[methodIndex]
		log.Printf("Method %q returned error: %v.", name, err)
		status = 1
		output = nil
	}
	// Write.
	if err := binary.Write(conn, binary.LittleEndian, status); err != nil {
		return err
	}
	if err := binary.Write(conn, binary.LittleEndian, methodIndex); err != nil {
		return err
	}
	if err := binary.Write(conn, binary.LittleEndian, int32(len(output))); err != nil {
		return err
	}
	if err := binary.Write(conn, binary.LittleEndian, requestID); err != nil {
		return err
	}
	n, err = conn.Write(output)
	if err != nil {
		return err
	}
	if n != len(output) {
		return errBadN
	}
	return nil
}
<|endoftext|>


<commit_before>package directory_test

import (
	"testing"

	"github.com/hansrodtang/runcom/backends/directory"
)

const TestDirectory = "./test/"

//
func TestInit(t *testing.T) {
	d := directory.NewBackend(TestDirectory)

}
<commit_msg>Test code coverage reporter.<commit_after>package directory_test

import (
	"testing"

	"github.com/hansrodtang/runcom/backends/directory"
)

const TestDirectory = "./test/"

//
func TestInit(t *testing.T) {
	/*d :=*/ directory.NewBackend(TestDirectory)

}
<|endoftext|>


<commit_before>package services_bbs_test

import (
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	. "github.com/cloudfoundry-incubator/runtime-schema/bbs/services_bbs"
	"github.com/cloudfoundry-incubator/runtime-schema/bbs/shared"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	steno "github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/storeadapter"
	"github.com/cloudfoundry/storeadapter/test_helpers"
)

var _ = Describe("Fetching all Reps", func() {
	var (
		bbs               *ServicesBBS
		interval          time.Duration
		status            <-chan bool
		err               error
		firstPresence     Presence
		secondPresence    Presence
		firstRepPresence  models.RepPresence
		secondRepPresence models.RepPresence
	)

	BeforeEach(func() {
		logSink := steno.NewTestingSink()

		steno.Init(&steno.Config{
			Sinks: []steno.Sink{logSink},
		})

		logger := steno.NewLogger("the-logger")
		steno.EnterTestMode()

		bbs = New(etcdClient, logger)

		firstRepPresence = models.RepPresence{
			RepID: "first-rep",
			Stack: "lucid64",
		}

		secondRepPresence = models.RepPresence{
			RepID: "second-rep",
			Stack: ".Net",
		}
	})

	Describe("GetAllReps", func() {
		Context("when there are available Reps", func() {
			BeforeEach(func() {
				interval = 1 * time.Second

				firstPresence, status, err = bbs.MaintainRepPresence(interval, firstRepPresence)
				Ω(err).ShouldNot(HaveOccurred())
				Eventually(test_helpers.NewStatusReporter(status).Locked).Should(BeTrue())

				secondPresence, status, err = bbs.MaintainRepPresence(interval, secondRepPresence)
				Ω(err).ShouldNot(HaveOccurred())
				Eventually(test_helpers.NewStatusReporter(status).Locked).Should(BeTrue())
			})

			AfterEach(func() {
				firstPresence.Remove()
				secondPresence.Remove()
			})

			It("should get from /v1/rep/", func() {
				repPresences, err := bbs.GetAllReps()
				Ω(err).ShouldNot(HaveOccurred())
				Ω(repPresences).Should(HaveLen(2))
				Ω(repPresences[0]).Should(Equal(firstRepPresence))
				Ω(repPresences[1]).Should(Equal(secondRepPresence))
			})

			Context("when there is unparsable JSON in there...", func() {
				BeforeEach(func() {
					etcdClient.Create(storeadapter.StoreNode{
						Key:   shared.RepSchemaPath("blah"),
						Value: []byte("ß"),
					})
				})

				It("should ignore the unparsable JSON and move on", func() {
					repPresences, err := bbs.GetAllReps()
					Ω(err).ShouldNot(HaveOccurred())
					Ω(repPresences).Should(HaveLen(2))
					Ω(repPresences).Should(ContainElement(firstRepPresence))
					Ω(repPresences).Should(ContainElement(secondRepPresence))
				})
			})
		})

		Context("when there are none", func() {
			It("should return empty", func() {
				reps, err := bbs.GetAllReps()
				Ω(err).ShouldNot(HaveOccurred())
				Ω(reps).Should(BeEmpty())
			})
		})
	})
})
<commit_msg>fix flaky tests 2: more flaky<commit_after>package services_bbs_test

import (
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	. "github.com/cloudfoundry-incubator/runtime-schema/bbs/services_bbs"
	"github.com/cloudfoundry-incubator/runtime-schema/bbs/shared"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	steno "github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/storeadapter"
	"github.com/cloudfoundry/storeadapter/test_helpers"
)

var _ = Describe("Fetching all Reps", func() {
	var (
		bbs               *ServicesBBS
		interval          time.Duration
		status            <-chan bool
		err               error
		firstPresence     Presence
		secondPresence    Presence
		firstRepPresence  models.RepPresence
		secondRepPresence models.RepPresence
	)

	BeforeEach(func() {
		logSink := steno.NewTestingSink()

		steno.Init(&steno.Config{
			Sinks: []steno.Sink{logSink},
		})

		logger := steno.NewLogger("the-logger")
		steno.EnterTestMode()

		bbs = New(etcdClient, logger)

		firstRepPresence = models.RepPresence{
			RepID: "first-rep",
			Stack: "lucid64",
		}

		secondRepPresence = models.RepPresence{
			RepID: "second-rep",
			Stack: ".Net",
		}
	})

	Describe("GetAllReps", func() {
		Context("when there are available Reps", func() {
			BeforeEach(func() {
				interval = 1 * time.Second

				firstPresence, status, err = bbs.MaintainRepPresence(interval, firstRepPresence)
				Ω(err).ShouldNot(HaveOccurred())
				Eventually(test_helpers.NewStatusReporter(status).Locked).Should(BeTrue())

				secondPresence, status, err = bbs.MaintainRepPresence(interval, secondRepPresence)
				Ω(err).ShouldNot(HaveOccurred())
				Eventually(test_helpers.NewStatusReporter(status).Locked).Should(BeTrue())
			})

			AfterEach(func() {
				firstPresence.Remove()
				secondPresence.Remove()
			})

			It("should get from /v1/rep/", func() {
				repPresences, err := bbs.GetAllReps()
				Ω(err).ShouldNot(HaveOccurred())
				Ω(repPresences).Should(HaveLen(2))
				Ω(repPresences).Should(ContainElement(firstRepPresence))
				Ω(repPresences).Should(ContainElement(secondRepPresence))
			})

			Context("when there is unparsable JSON in there...", func() {
				BeforeEach(func() {
					etcdClient.Create(storeadapter.StoreNode{
						Key:   shared.RepSchemaPath("blah"),
						Value: []byte("ß"),
					})
				})

				It("should ignore the unparsable JSON and move on", func() {
					repPresences, err := bbs.GetAllReps()
					Ω(err).ShouldNot(HaveOccurred())
					Ω(repPresences).Should(HaveLen(2))
					Ω(repPresences).Should(ContainElement(firstRepPresence))
					Ω(repPresences).Should(ContainElement(secondRepPresence))
				})
			})
		})

		Context("when there are none", func() {
			It("should return empty", func() {
				reps, err := bbs.GetAllReps()
				Ω(err).ShouldNot(HaveOccurred())
				Ω(reps).Should(BeEmpty())
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/justincarter/docker-workbench/cmd"
	"github.com/urfave/cli"
)

const version = "1.4"

func main() {

	if err := cmd.FlightCheck(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	cli.AppHelpTemplate = templateAppHelp
	cli.CommandHelpTemplate = templateCommandHelp
	cli.VersionPrinter = cmd.Version

	app := cli.NewApp()
	app.Name = "docker-workbench"
	app.Version = version
	app.Usage = "Provision a Docker Workbench for use with docker-machine and docker-compose"

	app.CommandNotFound = cmd.NotFound
	app.Commands = cmd.Commands

	if err := app.Run(os.Args); err != nil {
		fmt.Println(err)
	}
}
<commit_msg>bump version to 1.4.1<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/justincarter/docker-workbench/cmd"
	"github.com/urfave/cli"
)

const version = "1.4.1"

func main() {

	if err := cmd.FlightCheck(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	cli.AppHelpTemplate = templateAppHelp
	cli.CommandHelpTemplate = templateCommandHelp
	cli.VersionPrinter = cmd.Version

	app := cli.NewApp()
	app.Name = "docker-workbench"
	app.Version = version
	app.Usage = "Provision a Docker Workbench for use with docker-machine and docker-compose"

	app.CommandNotFound = cmd.NotFound
	app.Commands = cmd.Commands

	if err := app.Run(os.Args); err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


<commit_before>package goinsta

import (
	"encoding/json"
	"fmt"
)

// Comments allows user to interact with media (item) comments.
// You can Add or Delete by index or by user name.
type Comments struct {
	item     *Item
	endpoint string
	err      error

	Items                          []Comment `json:"comments"`
	CommentCount                   int       `json:"comment_count"`
	Caption                        Caption   `json:"caption"`
	CaptionIsEdited                bool      `json:"caption_is_edited"`
	HasMoreComments                bool      `json:"has_more_comments"`
	HasMoreHeadloadComments        bool      `json:"has_more_headload_comments"`
	MediaHeaderDisplay             string    `json:"media_header_display"`
	DisplayRealtimeTypingIndicator bool      `json:"display_realtime_typing_indicator"`
	NextID                         string    `json:"next_max_id"`
	LastID                         string    `json:"next_min_id"`
	Status                         string    `json:"status"`

	//PreviewComments                []Comment   `json:"preview_comments"`
}

func newComments(item *Item) *Comments {
	c := &Comments{
		item: item,
	}
	return c
}

func (comments Comments) Error() error {
	return comments.err
}

// Disable disables comments in FeedMedia.
//
// See example: examples/media/commentDisable.go
func (comments *Comments) Disable() error {
	switch comments.item.media.(type) {
	case *StoryMedia:
		return fmt.Errorf("Incompatible type. Cannot use Disable() with StoryMedia type")
	default:
	}

	insta := comments.item.media.instagram()
	data, err := insta.prepareData(
		map[string]interface{}{
			"media_id": comments.item.ID,
		},
	)
	if err != nil {
		return err
	}

	_, err = insta.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlCommentDisable, comments.item.ID),
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	return err
}

// Enable enables comments in FeedMedia
//
// See example: examples/media/commentEnable.go
func (comments *Comments) Enable() error {
	switch comments.item.media.(type) {
	case *StoryMedia:
		return fmt.Errorf("Incompatible type. Cannot use Enable() with StoryMedia type")
	default:
	}

	insta := comments.item.media.instagram()
	data, err := insta.prepareData(
		map[string]interface{}{
			"media_id": comments.item.ID,
		},
	)
	if err != nil {
		return err
	}

	_, err = insta.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlCommentEnable, comments.item.ID),
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	return err
}

// Next allows comment pagination.
//
// This function support concurrency methods to get comments using Last and Next ID
//
// New comments are stored in Comments.Items
func (comments *Comments) Next() bool {
	if comments.err != nil {
		return false
	}

	item := comments.item
	insta := comments.item.media.instagram()
	data, err := insta.prepareData(
		map[string]interface{}{
			"can_support_threading": true,
			"max_id":                comments.NextID,
			"min_id":                comments.LastID,
		},
	)
	if err != nil {
		comments.err = err
		return false
	}

	endpoint := comments.endpoint

	body, err := insta.sendRequest(
		&reqOptions{
			Endpoint: endpoint,
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	if err == nil {
		c := Comments{}
		err = json.Unmarshal(body, &c)
		if err == nil {
			*comments = c
			comments.endpoint = endpoint
			comments.item = item
			if !comments.HasMoreComments || comments.NextID == "" {
				comments.err = ErrNoMore
			}
			return true
		}
	}
	comments.err = err
	return false
}

// Sync prepare Comments to receive comments.
// Use Next to receive comments.
//
// See example: examples/media/commentsSync.go
func (comments *Comments) Sync() {
	endpoint := fmt.Sprintf(urlCommentSync, comments.item.ID)
	comments.endpoint = endpoint
	return
}

// Add push a comment in media.
//
// If parent media is a Story this function will send a private message
// replying the Instagram story.
//
// See example: examples/media/commentsAdd.go
func (comments *Comments) Add(text string) (err error) {
	var url, data string
	item := comments.item
	insta := item.media.instagram()

	switch item.media.(type) {
	case *StoryMedia: // story
		url = urlReplyStory
		data, err = insta.prepareData(
			map[string]interface{}{
				"recipient_users": fmt.Sprintf("[[%d]]", item.User.ID),
				"action":          "send_item",
				"client_context":  insta.dID,
				"media_id":        item.media.ID(),
				"text":            text,
				"entry":           "reel",
				"reel_id":         item.User.ID,
			},
		)
	case *FeedMedia: // normal media
		url = fmt.Sprintf(urlCommentAdd, item.ID)
		data, err = insta.prepareData(
			map[string]interface{}{
				"comment_text": text,
			},
		)
	}
	if err != nil {
		return err
	}

	// ignoring response
	_, err = insta.sendRequest(
		&reqOptions{
			Endpoint: url,
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	return err
}

// Del deletes comment.
func (comments *Comments) Del(comment *Comment) error {
	insta := comments.item.media.instagram()

	data, err := insta.prepareData()
	if err != nil {
		return err
	}
	id := comment.getid()

	_, err = insta.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlCommentDelete, comments.item.ID, id),
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	return err
}

// DelByID removes comment using id.
//
// See example: examples/media/commentsDelByID.go
func (comments *Comments) DelByID(id string) error {
	return comments.Del(&Comment{idstr: id})
}

// DelMine removes all of your comments limited by parsed parameter.
//
// If limit is <= 0 DelMine will delete all your comments.
//
// See example: examples/media/commentsDelMine.go
func (comments *Comments) DelMine(limit int) error {
	i := 0
	if limit <= 0 {
		i = limit - 1
	}
	comments.Sync()

	insta := comments.item.media.instagram()
floop:
	for comments.Next() {
		for _, c := range comments.Items {
			if c.UserID == insta.Account.ID || c.User.ID == insta.Account.ID {
				if i >= limit {
					break floop
				}
				comments.Del(&c)
				i++
			}
		}
	}
	if err := comments.Error(); err != nil && err != ErrNoMore {
		return err
	}
	return nil
}
<commit_msg>Fixed parameter error<commit_after>package goinsta

import (
	"encoding/json"
	"fmt"
)

// Comments allows user to interact with media (item) comments.
// You can Add or Delete by index or by user name.
type Comments struct {
	item     *Item
	endpoint string
	err      error

	Items                          []Comment `json:"comments"`
	CommentCount                   int       `json:"comment_count"`
	Caption                        Caption   `json:"caption"`
	CaptionIsEdited                bool      `json:"caption_is_edited"`
	HasMoreComments                bool      `json:"has_more_comments"`
	HasMoreHeadloadComments        bool      `json:"has_more_headload_comments"`
	MediaHeaderDisplay             string    `json:"media_header_display"`
	DisplayRealtimeTypingIndicator bool      `json:"display_realtime_typing_indicator"`
	NextID                         string    `json:"next_max_id"`
	LastID                         string    `json:"next_min_id"`
	Status                         string    `json:"status"`

	//PreviewComments                []Comment   `json:"preview_comments"`
}

func newComments(item *Item) *Comments {
	c := &Comments{
		item: item,
	}
	return c
}

func (comments Comments) Error() error {
	return comments.err
}

// Disable disables comments in FeedMedia.
//
// See example: examples/media/commentDisable.go
func (comments *Comments) Disable() error {
	switch comments.item.media.(type) {
	case *StoryMedia:
		return fmt.Errorf("Incompatible type. Cannot use Disable() with StoryMedia type")
	default:
	}

	insta := comments.item.media.instagram()
	data, err := insta.prepareData(
		map[string]interface{}{
			"media_id": comments.item.ID,
		},
	)
	if err != nil {
		return err
	}

	_, err = insta.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlCommentDisable, comments.item.ID),
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	return err
}

// Enable enables comments in FeedMedia
//
// See example: examples/media/commentEnable.go
func (comments *Comments) Enable() error {
	switch comments.item.media.(type) {
	case *StoryMedia:
		return fmt.Errorf("Incompatible type. Cannot use Enable() with StoryMedia type")
	default:
	}

	insta := comments.item.media.instagram()
	data, err := insta.prepareData(
		map[string]interface{}{
			"media_id": comments.item.ID,
		},
	)
	if err != nil {
		return err
	}

	_, err = insta.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlCommentEnable, comments.item.ID),
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	return err
}

// Next allows comment pagination.
//
// This function support concurrency methods to get comments using Last and Next ID
//
// New comments are stored in Comments.Items
func (comments *Comments) Next() bool {
	if comments.err != nil {
		return false
	}

	item := comments.item
	insta := comments.item.media.instagram()
	data, err := insta.prepareData(
		map[string]interface{}{
			"can_support_threading": true,
			"max_id":                comments.NextID,
			"min_id":                comments.LastID,
		},
	)
	if err != nil {
		comments.err = err
		return false
	}

	endpoint := comments.endpoint

	body, err := insta.sendRequest(
		&reqOptions{
			Endpoint: endpoint,
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	if err == nil {
		c := Comments{}
		err = json.Unmarshal(body, &c)
		if err == nil {
			*comments = c
			comments.endpoint = endpoint
			comments.item = item
			if !comments.HasMoreComments || comments.NextID == "" {
				comments.err = ErrNoMore
			}
			return true
		}
	}
	comments.err = err
	return false
}

// Sync prepare Comments to receive comments.
// Use Next to receive comments.
//
// See example: examples/media/commentsSync.go
func (comments *Comments) Sync() {
	endpoint := fmt.Sprintf(urlCommentSync, comments.item.ID)
	comments.endpoint = endpoint
	return
}

// Add push a comment in media.
//
// If parent media is a Story this function will send a private message
// replying the Instagram story.
//
// See example: examples/media/commentsAdd.go
func (comments *Comments) Add(text string) (err error) {
	var url, data string
	item := comments.item
	insta := item.media.instagram()

	switch item.media.(type) {
	case *StoryMedia: // story
		url = urlReplyStory
		data, err = insta.prepareData(
			map[string]interface{}{
				"recipient_users": fmt.Sprintf("[[%d]]", item.User.ID),
				"action":          "send_item",
				"client_context":  insta.dID,
				"media_id":        item.ID,
				"text":            text,
				"entry":           "reel",
				"reel_id":         item.User.ID,
			},
		)
	case *FeedMedia: // normal media
		url = fmt.Sprintf(urlCommentAdd, item.ID)
		data, err = insta.prepareData(
			map[string]interface{}{
				"comment_text": text,
			},
		)
	}
	if err != nil {
		return err
	}

	// ignoring response
	_, err = insta.sendRequest(
		&reqOptions{
			Endpoint: url,
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	return err
}

// Del deletes comment.
func (comments *Comments) Del(comment *Comment) error {
	insta := comments.item.media.instagram()

	data, err := insta.prepareData()
	if err != nil {
		return err
	}
	id := comment.getid()

	_, err = insta.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlCommentDelete, comments.item.ID, id),
			Query:    generateSignature(data),
			IsPost:   true,
		},
	)
	return err
}

// DelByID removes comment using id.
//
// See example: examples/media/commentsDelByID.go
func (comments *Comments) DelByID(id string) error {
	return comments.Del(&Comment{idstr: id})
}

// DelMine removes all of your comments limited by parsed parameter.
//
// If limit is <= 0 DelMine will delete all your comments.
//
// See example: examples/media/commentsDelMine.go
func (comments *Comments) DelMine(limit int) error {
	i := 0
	if limit <= 0 {
		i = limit - 1
	}
	comments.Sync()

	insta := comments.item.media.instagram()
floop:
	for comments.Next() {
		for _, c := range comments.Items {
			if c.UserID == insta.Account.ID || c.User.ID == insta.Account.ID {
				if i >= limit {
					break floop
				}
				comments.Del(&c)
				i++
			}
		}
	}
	if err := comments.Error(); err != nil && err != ErrNoMore {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

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

import (
	"github.com/gocql/gocql"
)

type Comment struct {
	AbsId gocql.UUID `json:"abstract_id"`
	Id    gocql.UUID `json:"id"`
	Email Email      `json:"email"`
	Body  string     `json:"body"`
}

type Comments []Comment

func ListComments(cass *gocql.Session, absId gocql.UUID) (Comments, error) {
	clist := make(Comments, 0)

	query := `SELECT abstract_id, id, email, body FROM comments WHERE abstract_id=?`
	iq := cass.Query(query, absId).Iter()
	for {
		c := Comment{}
		ok := iq.Scan(&c.AbsId, &c.Id, &c.Email, &c.Body)
		if ok {
			clist = append(clist, c)
		} else {
			break
		}
	}
	if err := iq.Close(); err != nil {
		return nil, err
	}

	return clist, nil
}

func (c *Comment) Save(cass *gocql.Session) error {
	query := `INSERT INTO comments (abstract_id, id, email, body) VALUES (?, ?, ?, ?)`
	return cass.Query(query, c.AbsId, c.Id, c.Email, c.Body).Exec()
}
<commit_msg>Add created field to comment struct.<commit_after>package main

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

import (
	"github.com/gocql/gocql"
	"time"
)

type Comment struct {
	AbsId   gocql.UUID `json:"abstract_id"`
	Id      gocql.UUID `json:"id"`
	Created time.Time  `json:"created"`
	Email   Email      `json:"email"`
	Body    string     `json:"body"`
}

type Comments []Comment

func ListComments(cass *gocql.Session, absId gocql.UUID) (Comments, error) {
	clist := make(Comments, 0)

	query := `SELECT abstract_id, id, email, body FROM comments WHERE abstract_id=?`
	iq := cass.Query(query, absId).Iter()
	for {
		c := Comment{}
		ok := iq.Scan(&c.AbsId, &c.Id, &c.Email, &c.Body)
		if ok {
			c.Created = c.Id.Time()
			clist = append(clist, c)
		} else {
			break
		}
	}
	if err := iq.Close(); err != nil {
		return nil, err
	}

	return clist, nil
}

func (c *Comment) Save(cass *gocql.Session) error {
	query := `INSERT INTO comments (abstract_id, id, email, body) VALUES (?, ?, ?, ?)`
	return cass.Query(query, c.AbsId, c.Id, c.Email, c.Body).Exec()
}
<|endoftext|>


<commit_before>// Copyright 2022 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.

// ---
// @Author Lion <chenxin619315@gmail.com>
// @Date   2022/06/16

package xdb

import (
	"fmt"
	"os"
	"strconv"
	"strings"
)

var shiftIndex = []int{24, 16, 8, 0}

func CheckIP(ip string) (uint32, error) {
	var ps = strings.Split(ip, ".")
	if len(ps) != 4 {
		return 0, fmt.Errorf("invalid ip address `%s`", ip)
	}

	var val = uint32(0)
	for i, s := range ps {
		d, err := strconv.Atoi(s)
		if err != nil {
			return 0, fmt.Errorf("the %dth part `%s` is not an integer", i, s)
		}

		if d < 0 || d > 255 {
			return 0, fmt.Errorf("the %dth part `%s` should be an integer bettween 0 and 255", i, s)
		}

		val |= uint32(d) << shiftIndex[i]
	}

	// convert the ip to integer
	return val, nil
}

func Long2IP(ip uint32) string {
	return fmt.Sprintf("%d.%d.%d.%d", (ip>>24)&0xFF, (ip>>16)&0xFF, (ip>>8)&0xFF, ip&0xFF)
}

func MidIP(sip uint32, eip uint32) uint32 {
	return uint32((uint64(sip) + uint64(eip)) >> 1)
}

// LoadHeader load the header info from the specified handle
func LoadHeader(handle *os.File) (*Header, error) {
	_, err := handle.Seek(0, 0)
	if err != nil {
		return nil, fmt.Errorf("seek to the header: %w", err)
	}

	var buff = make([]byte, HeaderInfoLength)
	rLen, err := handle.Read(buff)
	if err != nil {
		return nil, err
	}

	if rLen != len(buff) {
		return nil, fmt.Errorf("incomplete read: readed bytes should be %d", len(buff))
	}

	return NewHeader(buff)
}

// LoadHeaderFromFile load header info from the specified db file path
func LoadHeaderFromFile(dbFile string) (*Header, error) {
	handle, err := os.OpenFile(dbFile, os.O_RDONLY, 0600)
	if err != nil {
		return nil, fmt.Errorf("open xdb file `%s`: %w", dbFile, err)
	}

	return LoadHeader(handle)
}

// LoadHeaderFromBuff wrap the header info from the content buffer
func LoadHeaderFromBuff(cBuff []byte) (*Header, error) {
	return NewHeader(cBuff[0:256])
}

// LoadVectorIndex util function to load the vector index from the specified file handle
func LoadVectorIndex(handle *os.File) ([]byte, error) {
	// load all the vector index block
	_, err := handle.Seek(HeaderInfoLength, 0)
	if err != nil {
		return nil, fmt.Errorf("seek to vector index: %w", err)
	}

	var buff = make([]byte, VectorIndexRows*VectorIndexCols*VectorIndexSize)
	rLen, err := handle.Read(buff)
	if err != nil {
		return nil, err
	}

	if rLen != len(buff) {
		return nil, fmt.Errorf("incomplete read: readed bytes should be %d", len(buff))
	}

	return buff, nil
}

// LoadVectorIndexFromFile load vector index from a specified file path
func LoadVectorIndexFromFile(dbFile string) ([]byte, error) {
	handle, err := os.OpenFile(dbFile, os.O_RDONLY, 0600)
	if err != nil {
		return nil, fmt.Errorf("open xdb file `%s`: %w", dbFile, err)
	}

	return LoadVectorIndex(handle)
}

// LoadContent load the whole xdb content from the specified file handle
func LoadContent(handle *os.File) ([]byte, error) {
	// get file size
	fi, err := handle.Stat()
	if err != nil {
		return nil, fmt.Errorf("stat: %w", err)
	}

	size := fi.Size()

	// seek to the head of the file
	_, err = handle.Seek(0, 0)
	if err != nil {
		return nil, fmt.Errorf("seek to get xdb file length: %w", err)
	}

	var buff = make([]byte, size)
	rLen, err := handle.Read(buff)
	if err != nil {
		return nil, err
	}

	if rLen != len(buff) {
		return nil, fmt.Errorf("incomplete read: readed bytes should be %d", len(buff))
	}

	return buff, nil
}

// LoadContentFromFile load the whole xdb content from the specified db file path
func LoadContentFromFile(dbFile string) ([]byte, error) {
	handle, err := os.OpenFile(dbFile, os.O_RDONLY, 0600)
	if err != nil {
		return nil, fmt.Errorf("open xdb file `%s`: %w", dbFile, err)
	}

	return LoadContent(handle)
}
<commit_msg>auto close the handle after buffer loaded<commit_after>// Copyright 2022 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.

// ---
// @Author Lion <chenxin619315@gmail.com>
// @Date   2022/06/16

package xdb

import (
	"fmt"
	"os"
	"strconv"
	"strings"
)

var shiftIndex = []int{24, 16, 8, 0}

func CheckIP(ip string) (uint32, error) {
	var ps = strings.Split(ip, ".")
	if len(ps) != 4 {
		return 0, fmt.Errorf("invalid ip address `%s`", ip)
	}

	var val = uint32(0)
	for i, s := range ps {
		d, err := strconv.Atoi(s)
		if err != nil {
			return 0, fmt.Errorf("the %dth part `%s` is not an integer", i, s)
		}

		if d < 0 || d > 255 {
			return 0, fmt.Errorf("the %dth part `%s` should be an integer bettween 0 and 255", i, s)
		}

		val |= uint32(d) << shiftIndex[i]
	}

	// convert the ip to integer
	return val, nil
}

func Long2IP(ip uint32) string {
	return fmt.Sprintf("%d.%d.%d.%d", (ip>>24)&0xFF, (ip>>16)&0xFF, (ip>>8)&0xFF, ip&0xFF)
}

func MidIP(sip uint32, eip uint32) uint32 {
	return uint32((uint64(sip) + uint64(eip)) >> 1)
}

// LoadHeader load the header info from the specified handle
func LoadHeader(handle *os.File) (*Header, error) {
	_, err := handle.Seek(0, 0)
	if err != nil {
		return nil, fmt.Errorf("seek to the header: %w", err)
	}

	var buff = make([]byte, HeaderInfoLength)
	rLen, err := handle.Read(buff)
	if err != nil {
		return nil, err
	}

	if rLen != len(buff) {
		return nil, fmt.Errorf("incomplete read: readed bytes should be %d", len(buff))
	}

	return NewHeader(buff)
}

// LoadHeaderFromFile load header info from the specified db file path
func LoadHeaderFromFile(dbFile string) (*Header, error) {
	handle, err := os.OpenFile(dbFile, os.O_RDONLY, 0600)
	if err != nil {
		return nil, fmt.Errorf("open xdb file `%s`: %w", dbFile, err)
	}

	header, err := LoadHeader(handle)
	if err != nil {
		return nil, err
	}

	_ = handle.Close()
	return header, nil
}

// LoadHeaderFromBuff wrap the header info from the content buffer
func LoadHeaderFromBuff(cBuff []byte) (*Header, error) {
	return NewHeader(cBuff[0:256])
}

// LoadVectorIndex util function to load the vector index from the specified file handle
func LoadVectorIndex(handle *os.File) ([]byte, error) {
	// load all the vector index block
	_, err := handle.Seek(HeaderInfoLength, 0)
	if err != nil {
		return nil, fmt.Errorf("seek to vector index: %w", err)
	}

	var buff = make([]byte, VectorIndexRows*VectorIndexCols*VectorIndexSize)
	rLen, err := handle.Read(buff)
	if err != nil {
		return nil, err
	}

	if rLen != len(buff) {
		return nil, fmt.Errorf("incomplete read: readed bytes should be %d", len(buff))
	}

	return buff, nil
}

// LoadVectorIndexFromFile load vector index from a specified file path
func LoadVectorIndexFromFile(dbFile string) ([]byte, error) {
	handle, err := os.OpenFile(dbFile, os.O_RDONLY, 0600)
	if err != nil {
		return nil, fmt.Errorf("open xdb file `%s`: %w", dbFile, err)
	}

	vIndex, err := LoadVectorIndex(handle)
	if err != nil {
		return nil, err
	}

	_ = handle.Close()
	return vIndex, nil
}

// LoadContent load the whole xdb content from the specified file handle
func LoadContent(handle *os.File) ([]byte, error) {
	// get file size
	fi, err := handle.Stat()
	if err != nil {
		return nil, fmt.Errorf("stat: %w", err)
	}

	size := fi.Size()

	// seek to the head of the file
	_, err = handle.Seek(0, 0)
	if err != nil {
		return nil, fmt.Errorf("seek to get xdb file length: %w", err)
	}

	var buff = make([]byte, size)
	rLen, err := handle.Read(buff)
	if err != nil {
		return nil, err
	}

	if rLen != len(buff) {
		return nil, fmt.Errorf("incomplete read: readed bytes should be %d", len(buff))
	}

	return buff, nil
}

// LoadContentFromFile load the whole xdb content from the specified db file path
func LoadContentFromFile(dbFile string) ([]byte, error) {
	handle, err := os.OpenFile(dbFile, os.O_RDONLY, 0600)
	if err != nil {
		return nil, fmt.Errorf("open xdb file `%s`: %w", dbFile, err)
	}

	cBuff, err := LoadContent(handle)
	if err != nil {
		return nil, err
	}

	_ = handle.Close()
	return cBuff, nil
}
<|endoftext|>


<commit_before>package functional

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"
	"time"
)

var fleetctlBinPath string

func init() {
	fleetctlBinPath = os.Getenv("FLEETCTL_BIN")
	if fleetctlBinPath == "" {
		fmt.Println("FLEETCTL_BIN environment variable must be set")
		os.Exit(1)
	} else if _, err := os.Stat(fleetctlBinPath); err != nil {
		fmt.Printf("%v\n", err)
		os.Exit(1)
	}

	if os.Getenv("SSH_AUTH_SOCK") == "" {
		fmt.Println("SSH_AUTH_SOCK environment variable must be set")
		os.Exit(1)
	}
}

func fleetctl(args ...string) (string, string, error) {
	log.Printf("%s %s", fleetctlBinPath, strings.Join(args, " "))
	var stdoutBytes, stderrBytes bytes.Buffer
	cmd := exec.Command(fleetctlBinPath, args...)
	cmd.Stdout = &stdoutBytes
	cmd.Stderr = &stderrBytes
	err := cmd.Run()
	return stdoutBytes.String(), stderrBytes.String(), err
}

func fleetctlWithInput(input string, args ...string) (string, string, error) {
	log.Printf("%s %s", fleetctlBinPath, strings.Join(args, " "))
	var stdoutBytes, stderrBytes bytes.Buffer
	cmd := exec.Command(fleetctlBinPath, args...)
	cmd.Stdout = &stdoutBytes
	cmd.Stderr = &stderrBytes
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return "", "", err
	}

	if err = cmd.Start(); err != nil {
		return "", "", err
	}

	stdin.Write([]byte(input))
	stdin.Close()
	err = cmd.Wait()

	return stdoutBytes.String(), stderrBytes.String(), err
}

// Wait up to 10s to find the specified number of machines, retrying periodically.
func waitForNMachines(count int) ([]string, error) {
	var machines []string

	timeout := 10 * time.Second
	alarm := time.After(timeout)

	ticker := time.Tick(time.Second)
loop:
	for {
		select {
		case <-alarm:
			return machines, fmt.Errorf("Failed to find %d machines within %v", count, timeout)
		case <-ticker:
			stdout, _, err := fleetctl("list-machines", "--no-legend", "-l")
			stdout = strings.TrimSpace(stdout)
			if err != nil {
				continue
			}

			found := 0
			if stdout != "" {
				machines = strings.Split(stdout, "\n")
				found = len(machines)
			}

			if found != count {
				continue
			}

			for k, v := range machines {
				machines[k] = strings.SplitN(v, "\t", 2)[0]
			}

			break loop
		}
	}

	return machines, nil
}

// waitForNActiveUnits polls fleet for up to 10s, exiting when N units are
// found to be in an active state. It returns a map of active units to
// their target machines.
func waitForNActiveUnits(count int) (map[string]UnitState, error) {
	states := make(map[string]UnitState)

	timeout := 10 * time.Second
	alarm := time.After(timeout)

	ticker := time.Tick(time.Second)
loop:
	for {
		select {
		case <-alarm:
			return nil, fmt.Errorf("Failed to find %d active units within %v", count, timeout)
		case <-ticker:
			stdout, _, err := fleetctl("list-units", "--no-legend", "-l")
			stdout = strings.TrimSpace(stdout)
			if stdout == "" || err != nil {
				continue
			}

			lines := strings.Split(stdout, "\n")
			allStates := parseUnitStates(lines)
			active := filterActiveUnits(allStates)
			if len(active) != count {
				continue
			}

			for _, state := range active {
				states[state.Name] = state
			}
			break loop
		}
	}

	return states, nil
}

type UnitState struct {
	Name        string
	ActiveState string
	Machine     string
}

func parseUnitStates(units []string) map[string]UnitState {
	states := make(map[string]UnitState)
	for _, unit := range units {
		cols := strings.SplitN(unit, "\t", 6)
		if len(cols) == 6 {
			machine := strings.SplitN(cols[5], "/", 2)[0]
			states[cols[0]] = UnitState{cols[0], cols[2], machine}
		}
	}
	return states
}

func filterActiveUnits(states map[string]UnitState) map[string]UnitState {
	filtered := make(map[string]UnitState)
	for unit, state := range states {
		if state.ActiveState == "active" {
			filtered[unit] = state
		}
	}
	return filtered
}

// tempUnit creates a local unit file with the given contents, returning
// the name of the file
func tempUnit(contents string) (string, error) {
	tmp, err := ioutil.TempFile(os.TempDir(), "fleet-test-unit-")
	if err != nil {
		return "", err
	}

	tmp.Write([]byte(contents))
	tmp.Close()

	svc := fmt.Sprintf("%s.service", tmp.Name())
	err = os.Rename(tmp.Name(), svc)
	if err != nil {
		os.Remove(tmp.Name())
		return "", err
	}

	return svc, nil
}
<commit_msg>refactor(functional): Use full flag names in functional tests<commit_after>package functional

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"
	"time"
)

var fleetctlBinPath string

func init() {
	fleetctlBinPath = os.Getenv("FLEETCTL_BIN")
	if fleetctlBinPath == "" {
		fmt.Println("FLEETCTL_BIN environment variable must be set")
		os.Exit(1)
	} else if _, err := os.Stat(fleetctlBinPath); err != nil {
		fmt.Printf("%v\n", err)
		os.Exit(1)
	}

	if os.Getenv("SSH_AUTH_SOCK") == "" {
		fmt.Println("SSH_AUTH_SOCK environment variable must be set")
		os.Exit(1)
	}
}

func fleetctl(args ...string) (string, string, error) {
	log.Printf("%s %s", fleetctlBinPath, strings.Join(args, " "))
	var stdoutBytes, stderrBytes bytes.Buffer
	cmd := exec.Command(fleetctlBinPath, args...)
	cmd.Stdout = &stdoutBytes
	cmd.Stderr = &stderrBytes
	err := cmd.Run()
	return stdoutBytes.String(), stderrBytes.String(), err
}

func fleetctlWithInput(input string, args ...string) (string, string, error) {
	log.Printf("%s %s", fleetctlBinPath, strings.Join(args, " "))
	var stdoutBytes, stderrBytes bytes.Buffer
	cmd := exec.Command(fleetctlBinPath, args...)
	cmd.Stdout = &stdoutBytes
	cmd.Stderr = &stderrBytes
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return "", "", err
	}

	if err = cmd.Start(); err != nil {
		return "", "", err
	}

	stdin.Write([]byte(input))
	stdin.Close()
	err = cmd.Wait()

	return stdoutBytes.String(), stderrBytes.String(), err
}

// Wait up to 10s to find the specified number of machines, retrying periodically.
func waitForNMachines(count int) ([]string, error) {
	var machines []string

	timeout := 10 * time.Second
	alarm := time.After(timeout)

	ticker := time.Tick(time.Second)
loop:
	for {
		select {
		case <-alarm:
			return machines, fmt.Errorf("Failed to find %d machines within %v", count, timeout)
		case <-ticker:
			stdout, _, err := fleetctl("list-machines", "--no-legend", "--full")
			stdout = strings.TrimSpace(stdout)
			if err != nil {
				continue
			}

			found := 0
			if stdout != "" {
				machines = strings.Split(stdout, "\n")
				found = len(machines)
			}

			if found != count {
				continue
			}

			for k, v := range machines {
				machines[k] = strings.SplitN(v, "\t", 2)[0]
			}

			break loop
		}
	}

	return machines, nil
}

// waitForNActiveUnits polls fleet for up to 10s, exiting when N units are
// found to be in an active state. It returns a map of active units to
// their target machines.
func waitForNActiveUnits(count int) (map[string]UnitState, error) {
	states := make(map[string]UnitState)

	timeout := 10 * time.Second
	alarm := time.After(timeout)

	ticker := time.Tick(time.Second)
loop:
	for {
		select {
		case <-alarm:
			return nil, fmt.Errorf("Failed to find %d active units within %v", count, timeout)
		case <-ticker:
			stdout, _, err := fleetctl("list-units", "--no-legend", "--full")
			stdout = strings.TrimSpace(stdout)
			if stdout == "" || err != nil {
				continue
			}

			lines := strings.Split(stdout, "\n")
			allStates := parseUnitStates(lines)
			active := filterActiveUnits(allStates)
			if len(active) != count {
				continue
			}

			for _, state := range active {
				states[state.Name] = state
			}
			break loop
		}
	}

	return states, nil
}

type UnitState struct {
	Name        string
	ActiveState string
	Machine     string
}

func parseUnitStates(units []string) map[string]UnitState {
	states := make(map[string]UnitState)
	for _, unit := range units {
		cols := strings.SplitN(unit, "\t", 6)
		if len(cols) == 6 {
			machine := strings.SplitN(cols[5], "/", 2)[0]
			states[cols[0]] = UnitState{cols[0], cols[2], machine}
		}
	}
	return states
}

func filterActiveUnits(states map[string]UnitState) map[string]UnitState {
	filtered := make(map[string]UnitState)
	for unit, state := range states {
		if state.ActiveState == "active" {
			filtered[unit] = state
		}
	}
	return filtered
}

// tempUnit creates a local unit file with the given contents, returning
// the name of the file
func tempUnit(contents string) (string, error) {
	tmp, err := ioutil.TempFile(os.TempDir(), "fleet-test-unit-")
	if err != nil {
		return "", err
	}

	tmp.Write([]byte(contents))
	tmp.Close()

	svc := fmt.Sprintf("%s.service", tmp.Name())
	err = os.Rename(tmp.Name(), svc)
	if err != nil {
		os.Remove(tmp.Name())
		return "", err
	}

	return svc, nil
}
<|endoftext|>


<commit_before>// The jsonhttp package provides general functions for returning
// JSON responses to HTTP requests. It is agnostic about
// the specific form of any returned errors.
package jsonhttp

import (
	"encoding/json"
	"net/http"

	"gopkg.in/errgo.v1"
)

// ErrorToResponse represents a function that can convert a Go error
// into a form that can be returned as a JSON body from an HTTP request.
// The httpStatus value reports the desired HTTP status.
type ErrorToResponse func(err error) (httpStatus int, errorBody interface{})

// ErrorHandler is like http.Handler except it returns an error
// which may be returned as the error body of the response.
// An ErrorHandler function should not itself write to the ResponseWriter
// if it returns an error.
type ErrorHandler func(http.ResponseWriter, *http.Request) error

// HandleErrors returns a function that can be used to convert an ErrorHandler
// into an http.Handler. The given errToResp parameter is used to convert
// any non-nil error returned by handle to the response in the HTTP body.
func HandleErrors(errToResp ErrorToResponse) func(handle ErrorHandler) http.Handler {
	writeError := WriteError(errToResp)
	return func(handle ErrorHandler) http.Handler {
		f := func(w http.ResponseWriter, req *http.Request) {
			w1 := responseWriter{
				ResponseWriter: w,
			}
			if err := handle(&w1, req); err != nil {
				// We write the error only if the header hasn't
				// already been written, because if it has, then
				// we will not be able to set the appropriate error
				// response code, and there's a danger that we
				// may be corrupting output by appending
				// a JSON error message to it.
				if !w1.headerWritten {
					writeError(w, err)
				}
				// TODO log the error?
			}
		}
		return http.HandlerFunc(f)
	}
}

// responseWriter wraps http.ResponseWriter but allows us
// to find out whether any body has already been written.
type responseWriter struct {
	headerWritten bool
	http.ResponseWriter
}

func (w *responseWriter) Write(data []byte) (int, error) {
	w.headerWritten = true
	return w.ResponseWriter.Write(data)
}

func (w *responseWriter) WriteHeader(code int) {
	w.headerWritten = true
	w.ResponseWriter.WriteHeader(code)
}

// Flush implements http.Flusher.Flush.
func (w *responseWriter) Flush() {
	w.headerWritten = true
	if f, ok := w.ResponseWriter.(http.Flusher); ok {
		f.Flush()
	}
}

// Ensure statically that responseWriter does implement http.Flusher.
var _ http.Flusher = (*responseWriter)(nil)

// WriteError returns a function that can be used to write an error to a ResponseWriter
// and set the HTTP status code. The errToResp parameter is used to determine
// the actual error value and status to write.
func WriteError(errToResp ErrorToResponse) func(w http.ResponseWriter, err error) {
	return func(w http.ResponseWriter, err error) {
		status, resp := errToResp(err)
		WriteJSON(w, status, resp)
	}
}

// WriteJSON writes the given value to the ResponseWriter
// and sets the HTTP status to the given code.
func WriteJSON(w http.ResponseWriter, code int, val interface{}) error {
	// TODO consider marshalling directly to w using json.NewEncoder.
	// pro: this will not require a full buffer allocation.
	// con: if there's an error after the first write, it will be lost.
	data, err := json.Marshal(val)
	if err != nil {
		// TODO(rog) log an error if this fails and lose the
		// error return, because most callers will need
		// to do that anyway.
		return errgo.Mask(err)
	}
	w.Header().Set("content-type", "application/json")
	w.WriteHeader(code)
	w.Write(data)
	return nil
}

// JSONHandler is like http.Handler except that it returns a
// body (to be converted to JSON) and an error.
// The Header parameter can be used to set
// custom header on the response.
type JSONHandler func(http.Header, *http.Request) (interface{}, error)

// HandleJSON returns a function that can be used to convert an JSONHandler
// into an http.Handler. The given errToResp parameter is used to convert
// any non-nil error returned by handle to the response in the HTTP body
// If it returns a nil value, the original error is returned as a JSON string.
func HandleJSON(errToResp ErrorToResponse) func(handle JSONHandler) http.Handler {
	handleErrors := HandleErrors(errToResp)
	return func(handle JSONHandler) http.Handler {
		f := func(w http.ResponseWriter, req *http.Request) error {
			val, err := handle(w.Header(), req)
			if err != nil {
				return errgo.Mask(err, errgo.Any)
			}
			return WriteJSON(w, http.StatusOK, val)
		}
		return handleErrors(f)
	}
}
<commit_msg>Added missing copyright.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
// The jsonhttp package provides general functions for returning
// JSON responses to HTTP requests. It is agnostic about
// the specific form of any returned errors.
package jsonhttp

import (
	"encoding/json"
	"net/http"

	"gopkg.in/errgo.v1"
)

// ErrorToResponse represents a function that can convert a Go error
// into a form that can be returned as a JSON body from an HTTP request.
// The httpStatus value reports the desired HTTP status.
type ErrorToResponse func(err error) (httpStatus int, errorBody interface{})

// ErrorHandler is like http.Handler except it returns an error
// which may be returned as the error body of the response.
// An ErrorHandler function should not itself write to the ResponseWriter
// if it returns an error.
type ErrorHandler func(http.ResponseWriter, *http.Request) error

// HandleErrors returns a function that can be used to convert an ErrorHandler
// into an http.Handler. The given errToResp parameter is used to convert
// any non-nil error returned by handle to the response in the HTTP body.
func HandleErrors(errToResp ErrorToResponse) func(handle ErrorHandler) http.Handler {
	writeError := WriteError(errToResp)
	return func(handle ErrorHandler) http.Handler {
		f := func(w http.ResponseWriter, req *http.Request) {
			w1 := responseWriter{
				ResponseWriter: w,
			}
			if err := handle(&w1, req); err != nil {
				// We write the error only if the header hasn't
				// already been written, because if it has, then
				// we will not be able to set the appropriate error
				// response code, and there's a danger that we
				// may be corrupting output by appending
				// a JSON error message to it.
				if !w1.headerWritten {
					writeError(w, err)
				}
				// TODO log the error?
			}
		}
		return http.HandlerFunc(f)
	}
}

// responseWriter wraps http.ResponseWriter but allows us
// to find out whether any body has already been written.
type responseWriter struct {
	headerWritten bool
	http.ResponseWriter
}

func (w *responseWriter) Write(data []byte) (int, error) {
	w.headerWritten = true
	return w.ResponseWriter.Write(data)
}

func (w *responseWriter) WriteHeader(code int) {
	w.headerWritten = true
	w.ResponseWriter.WriteHeader(code)
}

// Flush implements http.Flusher.Flush.
func (w *responseWriter) Flush() {
	w.headerWritten = true
	if f, ok := w.ResponseWriter.(http.Flusher); ok {
		f.Flush()
	}
}

// Ensure statically that responseWriter does implement http.Flusher.
var _ http.Flusher = (*responseWriter)(nil)

// WriteError returns a function that can be used to write an error to a ResponseWriter
// and set the HTTP status code. The errToResp parameter is used to determine
// the actual error value and status to write.
func WriteError(errToResp ErrorToResponse) func(w http.ResponseWriter, err error) {
	return func(w http.ResponseWriter, err error) {
		status, resp := errToResp(err)
		WriteJSON(w, status, resp)
	}
}

// WriteJSON writes the given value to the ResponseWriter
// and sets the HTTP status to the given code.
func WriteJSON(w http.ResponseWriter, code int, val interface{}) error {
	// TODO consider marshalling directly to w using json.NewEncoder.
	// pro: this will not require a full buffer allocation.
	// con: if there's an error after the first write, it will be lost.
	data, err := json.Marshal(val)
	if err != nil {
		// TODO(rog) log an error if this fails and lose the
		// error return, because most callers will need
		// to do that anyway.
		return errgo.Mask(err)
	}
	w.Header().Set("content-type", "application/json")
	w.WriteHeader(code)
	w.Write(data)
	return nil
}

// JSONHandler is like http.Handler except that it returns a
// body (to be converted to JSON) and an error.
// The Header parameter can be used to set
// custom header on the response.
type JSONHandler func(http.Header, *http.Request) (interface{}, error)

// HandleJSON returns a function that can be used to convert an JSONHandler
// into an http.Handler. The given errToResp parameter is used to convert
// any non-nil error returned by handle to the response in the HTTP body
// If it returns a nil value, the original error is returned as a JSON string.
func HandleJSON(errToResp ErrorToResponse) func(handle JSONHandler) http.Handler {
	handleErrors := HandleErrors(errToResp)
	return func(handle JSONHandler) http.Handler {
		f := func(w http.ResponseWriter, req *http.Request) error {
			val, err := handle(w.Header(), req)
			if err != nil {
				return errgo.Mask(err, errgo.Any)
			}
			return WriteJSON(w, http.StatusOK, val)
		}
		return handleErrors(f)
	}
}
<|endoftext|>


<commit_before>package kite

import (
	"errors"
	"koding/newKite/kd/util"
	"path/filepath"
	"syscall"
)

type Run struct{}

func NewRun() *Run {
	return &Run{}
}

func (*Run) Definition() string {
	return "Run a kite"
}

func (*Run) Exec(args []string) error {
	// Parse kite name
	if len(args) != 1 {
		return errors.New("You should give a kite name")
	}

	// Guess full kite name if short name is given
	var kiteFullName string
	suppliedName := args[0]
	_, _, err := splitVersion(kiteFullName, true)
	if err != nil {
		allKites, err := getInstalledKites(suppliedName)
		if err != nil {
			return err
		}

		if len(allKites) == 1 {
			kiteFullName = allKites[0]
		} else {
			return errors.New("More than one version is installed. Please give a full kite name.")
		}
	} else {
		kiteFullName = suppliedName
	}

	binPath, err := getBinPath(kiteFullName + ".kite")
	if err != nil {
		return err
	}

	binPath = filepath.Join(util.GetKdPath(), "kites", binPath)
	return syscall.Exec(binPath, []string{"hello", "world"}, []string{})
}
<commit_msg>fix kd kite run command<commit_after>package kite

import (
	"errors"
	"koding/newKite/kd/util"
	"path/filepath"
	"syscall"
)

type Run struct{}

func NewRun() *Run {
	return &Run{}
}

func (*Run) Definition() string {
	return "Run a kite"
}

func (*Run) Exec(args []string) error {
	// Parse kite name
	if len(args) != 1 {
		return errors.New("You should give a kite name")
	}

	// Guess full kite name if short name is given
	var kiteFullName string

	// User is allowed to enter kite name in these forms: "fs", "fs-0.0.1"
	suppliedName := args[0]

	_, _, err := splitVersion(suppliedName, false)
	if err != nil {
		allKites, err := getInstalledKites(suppliedName)
		if err != nil {
			return err
		}

		if len(allKites) == 0 {
			return errors.New("Kite not found")
		}

		if len(allKites) > 1 {
			return errors.New("More than one version is installed. Please give a full kite name.")
		}

		kiteFullName = allKites[0]
	} else {
		kiteFullName = suppliedName
	}

	binPath, err := getBinPath(kiteFullName + ".kite")
	if err != nil {
		return err
	}

	binPath = filepath.Join(util.GetKdPath(), "kites", binPath)
	return syscall.Exec(binPath, []string{"hello", "world"}, []string{})
}
<|endoftext|>