<commit_before>package filesystem_test

import (
	"flag"
	"io/ioutil"
	"log"
	"net"
	"os"
	"testing"

	"google.golang.org/grpc"

	"github.com/apoydence/eachers/testhelpers"
	"github.com/apoydence/loggrebutterfly/master/internal/filesystem"
	"github.com/apoydence/onpar"
	"github.com/apoydence/talaria/pb"

	. "github.com/apoydence/onpar/expect"
	. "github.com/apoydence/onpar/matchers"
)

func TestMain(m *testing.M) {
	flag.Parse()

	if !testing.Verbose() {
		log.SetOutput(ioutil.Discard)
	}

	os.Exit(m.Run())
}

type TF struct {
	*testing.T

	fs                  *filesystem.FileSystem
	mockSchedulerServer *mockSchedulerServer
}

func TestFileSystemCreate(t *testing.T) {
	t.Parallel()
	o := onpar.New()
	defer o.Run(t)

	setup(o)

	o.Group("when scheduler does not return an error", func() {
		o.BeforeEach(func(t TF) TF {
			testhelpers.AlwaysReturn(t.mockSchedulerServer.CreateOutput.Ret0, new(pb.CreateResponse))
			close(t.mockSchedulerServer.CreateOutput.Ret1)
			return t
		})

		o.Spec("it instructs the scheduler to create a buffer", func(t TF) {
			err := t.fs.Create("some-file")
			Expect(t, err == nil).To(BeTrue())

			Expect(t, t.mockSchedulerServer.CreateInput.Arg1).To(
				Chain(Receive(), Equal(&pb.CreateInfo{
					Name: "some-file",
				})),
			)
		})
	})
}

func TestFileSystemReadOnly(t *testing.T) {
	t.Parallel()
	o := onpar.New()
	defer o.Run(t)

	setup(o)

	o.Group("when scheduler does not return an error", func() {
		o.BeforeEach(func(t TF) TF {
			testhelpers.AlwaysReturn(t.mockSchedulerServer.ReadOnlyOutput.Ret0, new(pb.ReadOnlyResponse))
			close(t.mockSchedulerServer.ReadOnlyOutput.Ret1)
			return t
		})

		o.Spec("it instructs the scheduler to set the buffer to ReadOnly", func(t TF) {
			err := t.fs.ReadOnly("some-file")
			Expect(t, err == nil).To(BeTrue())

			Expect(t, t.mockSchedulerServer.ReadOnlyInput.Arg1).To(
				Chain(Receive(), Equal(&pb.ReadOnlyInfo{
					Name: "some-file",
				})),
			)
		})
	})
}

func TestFileSystemList(t *testing.T) {
	t.Parallel()
	o := onpar.New()
	defer o.Run(t)

	setup(o)

	o.Group("when scheduler does not return an error", func() {
		o.BeforeEach(func(t TF) TF {
			testhelpers.AlwaysReturn(t.mockSchedulerServer.ListClusterInfoOutput.Ret0, &pb.ListResponse{
				Info: []*pb.ClusterInfo{
					{Name: "a"},
					{Name: "b"},
					{Name: "c"},
				},
			})
			close(t.mockSchedulerServer.ListClusterInfoOutput.Ret1)
			return t
		})

		o.Spec("it lists the buffers from the scheduler and converts to data node addrs", func(t TF) {
			files, err := t.fs.List()
			Expect(t, err == nil).To(BeTrue())

			Expect(t, files).To(Contain("A", "B", "C"))
		})
	})
}

func TestFileSystemRoutes(t *testing.T) {
	t.Parallel()
	o := onpar.New()
	defer o.Run(t)

	setup(o)

	o.Group("when scheduler does not return an error", func() {
		o.BeforeEach(func(t TF) TF {
			testhelpers.AlwaysReturn(t.mockSchedulerServer.ListClusterInfoOutput.Ret0, &pb.ListResponse{
				Info: []*pb.ClusterInfo{
					{Name: "a", Leader: "l"},
					{Name: "b", Leader: "l"},
					{Name: "c", Leader: "l"},
				},
			})
			close(t.mockSchedulerServer.ListClusterInfoOutput.Ret1)
			return t
		})

		o.Spec("it lists the buffers from the scheduler", func(t TF) {
			routes, err := t.fs.Routes()
			Expect(t, err == nil).To(BeTrue())
			Expect(t, routes).To(Chain(HaveKey("a"), Equal("l")))
			Expect(t, routes).To(Chain(HaveKey("b"), Equal("l")))
			Expect(t, routes).To(Chain(HaveKey("c"), Equal("l")))
		})
	})
}

func setup(o *onpar.Onpar) {
	o.BeforeEach(func(t *testing.T) TF {
		addr, mockSchedulerServer := startMockSched()
		m := map[string]string{
			"a": "A",
			"b": "B",
			"c": "C",
		}

		return TF{
			T:                   t,
			mockSchedulerServer: mockSchedulerServer,
			fs:                  filesystem.New(addr, m),
		}
	})
}

func startMockSched() (string, *mockSchedulerServer) {
	mockSchedulerServer := newMockSchedulerServer()

	lis, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterSchedulerServer(s, mockSchedulerServer)
	go func() {
		if err := s.Serve(lis); err != nil {
			panic(err)
		}
	}()

	return lis.Addr().String(), mockSchedulerServer
}
<commit_msg>Fix test<commit_after>package filesystem_test

import (
	"flag"
	"io/ioutil"
	"log"
	"net"
	"os"
	"testing"

	"google.golang.org/grpc"

	"github.com/apoydence/eachers/testhelpers"
	"github.com/apoydence/loggrebutterfly/master/internal/filesystem"
	"github.com/apoydence/onpar"
	"github.com/apoydence/talaria/pb"

	. "github.com/apoydence/onpar/expect"
	. "github.com/apoydence/onpar/matchers"
)

func TestMain(m *testing.M) {
	flag.Parse()

	if !testing.Verbose() {
		log.SetOutput(ioutil.Discard)
	}

	os.Exit(m.Run())
}

type TF struct {
	*testing.T

	fs                  *filesystem.FileSystem
	mockSchedulerServer *mockSchedulerServer
}

func TestFileSystemCreate(t *testing.T) {
	t.Parallel()
	o := onpar.New()
	defer o.Run(t)

	setup(o)

	o.Group("when scheduler does not return an error", func() {
		o.BeforeEach(func(t TF) TF {
			testhelpers.AlwaysReturn(t.mockSchedulerServer.CreateOutput.Ret0, new(pb.CreateResponse))
			close(t.mockSchedulerServer.CreateOutput.Ret1)
			return t
		})

		o.Spec("it instructs the scheduler to create a buffer", func(t TF) {
			err := t.fs.Create("some-file")
			Expect(t, err == nil).To(BeTrue())

			Expect(t, t.mockSchedulerServer.CreateInput.Arg1).To(
				Chain(Receive(), Equal(&pb.CreateInfo{
					Name: "some-file",
				})),
			)
		})
	})
}

func TestFileSystemReadOnly(t *testing.T) {
	t.Parallel()
	o := onpar.New()
	defer o.Run(t)

	setup(o)

	o.Group("when scheduler does not return an error", func() {
		o.BeforeEach(func(t TF) TF {
			testhelpers.AlwaysReturn(t.mockSchedulerServer.ReadOnlyOutput.Ret0, new(pb.ReadOnlyResponse))
			close(t.mockSchedulerServer.ReadOnlyOutput.Ret1)
			return t
		})

		o.Spec("it instructs the scheduler to set the buffer to ReadOnly", func(t TF) {
			err := t.fs.ReadOnly("some-file")
			Expect(t, err == nil).To(BeTrue())

			Expect(t, t.mockSchedulerServer.ReadOnlyInput.Arg1).To(
				Chain(Receive(), Equal(&pb.ReadOnlyInfo{
					Name: "some-file",
				})),
			)
		})
	})
}

func TestFileSystemList(t *testing.T) {
	t.Parallel()
	o := onpar.New()
	defer o.Run(t)

	setup(o)

	o.Group("when scheduler does not return an error", func() {
		o.BeforeEach(func(t TF) TF {
			testhelpers.AlwaysReturn(t.mockSchedulerServer.ListClusterInfoOutput.Ret0, &pb.ListResponse{
				Info: []*pb.ClusterInfo{
					{Name: "a", Leader: "a"},
					{Name: "b", Leader: "b"},
					{Name: "c", Leader: "c"},
				},
			})
			close(t.mockSchedulerServer.ListClusterInfoOutput.Ret1)
			return t
		})

		o.Spec("it lists the buffers from the scheduler and converts to data node addrs", func(t TF) {
			files, err := t.fs.List()
			Expect(t, err == nil).To(BeTrue())

			Expect(t, files).To(Contain("A", "B", "C"))
		})
	})
}

func TestFileSystemRoutes(t *testing.T) {
	t.Parallel()
	o := onpar.New()
	defer o.Run(t)

	setup(o)

	o.Group("when scheduler does not return an error", func() {
		o.BeforeEach(func(t TF) TF {
			testhelpers.AlwaysReturn(t.mockSchedulerServer.ListClusterInfoOutput.Ret0, &pb.ListResponse{
				Info: []*pb.ClusterInfo{
					{Name: "a", Leader: "a"},
					{Name: "b", Leader: "b"},
					{Name: "c", Leader: "c"},
				},
			})
			close(t.mockSchedulerServer.ListClusterInfoOutput.Ret1)
			return t
		})

		o.Spec("it lists the buffers from the scheduler", func(t TF) {
			routes, err := t.fs.Routes()
			Expect(t, err == nil).To(BeTrue())
			Expect(t, routes).To(Chain(HaveKey("a"), Equal("A")))
			Expect(t, routes).To(Chain(HaveKey("b"), Equal("B")))
			Expect(t, routes).To(Chain(HaveKey("c"), Equal("C")))
		})
	})
}

func setup(o *onpar.Onpar) {
	o.BeforeEach(func(t *testing.T) TF {
		addr, mockSchedulerServer := startMockSched()
		m := map[string]string{
			"a": "A",
			"b": "B",
			"c": "C",
		}

		return TF{
			T:                   t,
			mockSchedulerServer: mockSchedulerServer,
			fs:                  filesystem.New(addr, m),
		}
	})
}

func startMockSched() (string, *mockSchedulerServer) {
	mockSchedulerServer := newMockSchedulerServer()

	lis, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterSchedulerServer(s, mockSchedulerServer)
	go func() {
		if err := s.Serve(lis); err != nil {
			panic(err)
		}
	}()

	return lis.Addr().String(), mockSchedulerServer
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"regexp"
	"testing"

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

func TestAccAWSNeptuneParameterGroup_basic(t *testing.T) {
	var v neptune.DBParameterGroup
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_neptune_parameter_group.test"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSNeptuneParameterGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Required(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					testAccCheckAWSNeptuneParameterGroupAttributes(&v, rName),
					resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile(fmt.Sprintf("^arn:[^:]+:rds:[^:]+:\\d{12}:pg:%s", rName))),
					resource.TestCheckResourceAttr(resourceName, "description", "Managed by Terraform"),
					resource.TestCheckResourceAttr(resourceName, "family", "neptune1"),
					resource.TestCheckResourceAttr(resourceName, "name", rName),
					resource.TestCheckResourceAttr(resourceName, "parameter.#", "0"),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSNeptuneParameterGroup_Description(t *testing.T) {
	var v neptune.DBParameterGroup
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_neptune_parameter_group.test"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSNeptuneParameterGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Description(rName, "description1"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					testAccCheckAWSNeptuneParameterGroupAttributes(&v, rName),
					resource.TestCheckResourceAttr(resourceName, "description", "description1"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSNeptuneParameterGroup_Parameter(t *testing.T) {
	var v neptune.DBParameterGroup
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_neptune_parameter_group.test"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSNeptuneParameterGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Parameter(rName, "neptune_query_timeout", "25", "pending-reboot"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					testAccCheckAWSNeptuneParameterGroupAttributes(&v, rName),
					resource.TestCheckResourceAttr(resourceName, "parameter.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "parameter.2423897584.apply_method", "pending-reboot"),
					resource.TestCheckResourceAttr(resourceName, "parameter.2423897584.name", "neptune_query_timeout"),
					resource.TestCheckResourceAttr(resourceName, "parameter.2423897584.value", "25"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
			// This test should be updated with a dynamic parameter when available
			{
				Config:      testAccAWSNeptuneParameterGroupConfig_Parameter(rName, "neptune_query_timeout", "25", "immediate"),
				ExpectError: regexp.MustCompile(`cannot use immediate apply method for static parameter`),
			},
			// Test removing the configuration
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Required(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					testAccCheckAWSNeptuneParameterGroupAttributes(&v, rName),
					resource.TestCheckResourceAttr(resourceName, "parameter.#", "0"),
				),
			},
		},
	})
}

func TestAccAWSNeptuneParameterGroup_Tags(t *testing.T) {
	var v neptune.DBParameterGroup

	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_neptune_parameter_group.test"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSNeptuneParameterGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Tags_SingleTag(rName, "key1", "value1"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Tags_SingleTag(rName, "key1", "value2"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "tags.key1", "value2"),
				),
			},
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Tags_MultipleTags(rName, "key2", "value2", "key3", "value3"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
					resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
					resource.TestCheckResourceAttr(resourceName, "tags.key3", "value3"),
				),
			},
		},
	})
}

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

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_neptune_parameter_group" {
			continue
		}

		// Try to find the Group
		resp, err := conn.DescribeDBParameterGroups(
			&neptune.DescribeDBParameterGroupsInput{
				DBParameterGroupName: aws.String(rs.Primary.ID),
			})

		if err != nil {
			if isAWSErr(err, neptune.ErrCodeDBParameterGroupNotFoundFault, "") {
				return nil
			}
			return err
		}

		if len(resp.DBParameterGroups) != 0 && aws.StringValue(resp.DBParameterGroups[0].DBParameterGroupName) == rs.Primary.ID {
			return fmt.Errorf("DB Parameter Group still exists")
		}
	}

	return nil
}

func testAccCheckAWSNeptuneParameterGroupAttributes(v *neptune.DBParameterGroup, rName string) resource.TestCheckFunc {
	return func(s *terraform.State) error {

		if *v.DBParameterGroupName != rName {
			return fmt.Errorf("bad name: %#v", v.DBParameterGroupName)
		}

		if *v.DBParameterGroupFamily != "neptune1" {
			return fmt.Errorf("bad family: %#v", v.DBParameterGroupFamily)
		}

		return nil
	}
}

func testAccCheckAWSNeptuneParameterGroupExists(n string, v *neptune.DBParameterGroup) 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 Neptune Parameter Group ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).neptuneconn

		opts := neptune.DescribeDBParameterGroupsInput{
			DBParameterGroupName: aws.String(rs.Primary.ID),
		}

		resp, err := conn.DescribeDBParameterGroups(&opts)

		if err != nil {
			return err
		}

		if len(resp.DBParameterGroups) != 1 ||
			*resp.DBParameterGroups[0].DBParameterGroupName != rs.Primary.ID {
			return fmt.Errorf("Neptune Parameter Group not found")
		}

		*v = *resp.DBParameterGroups[0]

		return nil
	}
}

func testAccAWSNeptuneParameterGroupConfig_Parameter(rName, pName, pValue, pApplyMethod string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  family = "neptune1"
  name   = "%s"

  parameter {
    apply_method = "%s"
    name         = "%s"
    value        = "%s"
  }
}`, rName, pApplyMethod, pName, pValue)
}

func testAccAWSNeptuneParameterGroupConfig_Description(rName, description string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  description = "%s"
  family      = "neptune1"
  name        = "%s"
}`, description, rName)
}

func testAccAWSNeptuneParameterGroupConfig_Required(rName string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  family = "neptune1"
  name   = "%s"
}`, rName)
}

func testAccAWSNeptuneParameterGroupConfig_Tags_SingleTag(name, tKey, tValue string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  family = "neptune1"
  name   = "%s"

  tags {
    %s = "%s"
  }
}
`, name, tKey, tValue)
}

func testAccAWSNeptuneParameterGroupConfig_Tags_MultipleTags(name, tKey1, tValue1, tKey2, tValue2 string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  family = "neptune1"
  name   = "%s"

  tags {
    %s = "%s"
    %s = "%s"
  }
}
`, name, tKey1, tValue1, tKey2, tValue2)
}
<commit_msg>tests/resource/aws_neptune_parameter_group: Use %q instead of "%s" in fmt.Sprintf()<commit_after>package aws

import (
	"fmt"
	"regexp"
	"testing"

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

func TestAccAWSNeptuneParameterGroup_basic(t *testing.T) {
	var v neptune.DBParameterGroup
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_neptune_parameter_group.test"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSNeptuneParameterGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Required(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					testAccCheckAWSNeptuneParameterGroupAttributes(&v, rName),
					resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile(fmt.Sprintf("^arn:[^:]+:rds:[^:]+:\\d{12}:pg:%s", rName))),
					resource.TestCheckResourceAttr(resourceName, "description", "Managed by Terraform"),
					resource.TestCheckResourceAttr(resourceName, "family", "neptune1"),
					resource.TestCheckResourceAttr(resourceName, "name", rName),
					resource.TestCheckResourceAttr(resourceName, "parameter.#", "0"),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSNeptuneParameterGroup_Description(t *testing.T) {
	var v neptune.DBParameterGroup
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_neptune_parameter_group.test"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSNeptuneParameterGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Description(rName, "description1"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					testAccCheckAWSNeptuneParameterGroupAttributes(&v, rName),
					resource.TestCheckResourceAttr(resourceName, "description", "description1"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSNeptuneParameterGroup_Parameter(t *testing.T) {
	var v neptune.DBParameterGroup
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_neptune_parameter_group.test"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSNeptuneParameterGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Parameter(rName, "neptune_query_timeout", "25", "pending-reboot"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					testAccCheckAWSNeptuneParameterGroupAttributes(&v, rName),
					resource.TestCheckResourceAttr(resourceName, "parameter.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "parameter.2423897584.apply_method", "pending-reboot"),
					resource.TestCheckResourceAttr(resourceName, "parameter.2423897584.name", "neptune_query_timeout"),
					resource.TestCheckResourceAttr(resourceName, "parameter.2423897584.value", "25"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
			// This test should be updated with a dynamic parameter when available
			{
				Config:      testAccAWSNeptuneParameterGroupConfig_Parameter(rName, "neptune_query_timeout", "25", "immediate"),
				ExpectError: regexp.MustCompile(`cannot use immediate apply method for static parameter`),
			},
			// Test removing the configuration
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Required(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					testAccCheckAWSNeptuneParameterGroupAttributes(&v, rName),
					resource.TestCheckResourceAttr(resourceName, "parameter.#", "0"),
				),
			},
		},
	})
}

func TestAccAWSNeptuneParameterGroup_Tags(t *testing.T) {
	var v neptune.DBParameterGroup

	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_neptune_parameter_group.test"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSNeptuneParameterGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Tags_SingleTag(rName, "key1", "value1"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Tags_SingleTag(rName, "key1", "value2"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "tags.key1", "value2"),
				),
			},
			{
				Config: testAccAWSNeptuneParameterGroupConfig_Tags_MultipleTags(rName, "key2", "value2", "key3", "value3"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSNeptuneParameterGroupExists(resourceName, &v),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
					resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
					resource.TestCheckResourceAttr(resourceName, "tags.key3", "value3"),
				),
			},
		},
	})
}

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

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_neptune_parameter_group" {
			continue
		}

		// Try to find the Group
		resp, err := conn.DescribeDBParameterGroups(
			&neptune.DescribeDBParameterGroupsInput{
				DBParameterGroupName: aws.String(rs.Primary.ID),
			})

		if err != nil {
			if isAWSErr(err, neptune.ErrCodeDBParameterGroupNotFoundFault, "") {
				return nil
			}
			return err
		}

		if len(resp.DBParameterGroups) != 0 && aws.StringValue(resp.DBParameterGroups[0].DBParameterGroupName) == rs.Primary.ID {
			return fmt.Errorf("DB Parameter Group still exists")
		}
	}

	return nil
}

func testAccCheckAWSNeptuneParameterGroupAttributes(v *neptune.DBParameterGroup, rName string) resource.TestCheckFunc {
	return func(s *terraform.State) error {

		if *v.DBParameterGroupName != rName {
			return fmt.Errorf("bad name: %#v", v.DBParameterGroupName)
		}

		if *v.DBParameterGroupFamily != "neptune1" {
			return fmt.Errorf("bad family: %#v", v.DBParameterGroupFamily)
		}

		return nil
	}
}

func testAccCheckAWSNeptuneParameterGroupExists(n string, v *neptune.DBParameterGroup) 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 Neptune Parameter Group ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).neptuneconn

		opts := neptune.DescribeDBParameterGroupsInput{
			DBParameterGroupName: aws.String(rs.Primary.ID),
		}

		resp, err := conn.DescribeDBParameterGroups(&opts)

		if err != nil {
			return err
		}

		if len(resp.DBParameterGroups) != 1 ||
			*resp.DBParameterGroups[0].DBParameterGroupName != rs.Primary.ID {
			return fmt.Errorf("Neptune Parameter Group not found")
		}

		*v = *resp.DBParameterGroups[0]

		return nil
	}
}

func testAccAWSNeptuneParameterGroupConfig_Parameter(rName, pName, pValue, pApplyMethod string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  family = "neptune1"
  name   = %q

  parameter {
    apply_method = %q
    name         = %q
    value        = %q
  }
}`, rName, pApplyMethod, pName, pValue)
}

func testAccAWSNeptuneParameterGroupConfig_Description(rName, description string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  description = %q
  family      = "neptune1"
  name        = %q
}`, description, rName)
}

func testAccAWSNeptuneParameterGroupConfig_Required(rName string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  family = "neptune1"
  name   = %q
}`, rName)
}

func testAccAWSNeptuneParameterGroupConfig_Tags_SingleTag(name, tKey, tValue string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  family = "neptune1"
  name   = %q

  tags {
    %s = %q
  }
}
`, name, tKey, tValue)
}

func testAccAWSNeptuneParameterGroupConfig_Tags_MultipleTags(name, tKey1, tValue1, tKey2, tValue2 string) string {
	return fmt.Sprintf(`
resource "aws_neptune_parameter_group" "test" {
  family = "neptune1"
  name   = %q

  tags {
    %s = %q
    %s = %q
  }
}
`, name, tKey1, tValue1, tKey2, tValue2)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Jetstack cert-manager contributors.

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 cainjector

import (
	"context"
	"fmt"
	"strings"

	"github.com/go-logr/logr"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"

	certmanager "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
	logf "github.com/jetstack/cert-manager/pkg/logs"
)

// dropNotFound ignores the given error if it's a not-found error,
// but otherwise just returns the argument.
func dropNotFound(err error) error {
	if apierrors.IsNotFound(err) {
		return nil
	}
	return err
}

// OwningCertForSecret gets the name of the owning certificate for a
// given secret, returning nil if no such object exists.
// Right now, this actually uses a label instead of owner refs,
// since certmanager doesn't set owner refs on secrets.
func OwningCertForSecret(secret *corev1.Secret) *types.NamespacedName {
	lblVal, hasLbl := secret.Annotations[certmanager.CertificateNameKey]
	if !hasLbl {
		return nil
	}
	return &types.NamespacedName{
		Name:      lblVal,
		Namespace: secret.Namespace,
	}
}

// InjectTarget is a Kubernetes API object that has one or more references to Kubernetes
// Services with corresponding fields for CA bundles.
type InjectTarget interface {
	// AsObject returns this injectable as an object.
	// It should be a pointer suitable for mutation.
	AsObject() runtime.Object

	// SetCA sets the CA of this target to the given certificate data (in the standard
	// PEM format used across Kubernetes).  In cases where multiple CA fields exist per
	// target (like admission webhook configs), all CAs are set to the given value.
	SetCA(data []byte)
}

// Injectable is a point in a Kubernetes API object that represents a Kubernetes Service
// reference with a corresponding spot for a CA bundle.
type Injectable interface {
}

// CertInjector knows how to create an instance of an InjectTarget for some particular type
// of inject target.  For instance, an implementation might create a InjectTarget
// containing an empty MutatingWebhookConfiguration.  The underlying API object can
// be populated (via AsObject) using client.Client#Get, and then CAs can be injected with
// Injectables (representing the various individual webhooks in the config) retrieved with
// Services.
type CertInjector interface {
	// NewTarget creates a new InjectTarget containing an empty underlying object.
	NewTarget() InjectTarget
	// IsAlpha tells the client to disregard "no matching kind" type of errors
	IsAlpha() bool
}

// genericInjectReconciler is a reconciler that knows how to check if a given object is
// marked as requiring a CA, chase down the corresponding Service, Certificate, Secret, and
// inject that into the object.
type genericInjectReconciler struct {
	// injector is responsible for the logic of actually setting a CA -- it's the component
	// that contains type-specific logic.
	injector CertInjector
	// sources is a list of available 'data sources' that can be used to extract
	// caBundles from various source.
	// This is defined as a variable to allow an instance of the secret-based
	// cainjector to run even when Certificate resources cannot we watched due to
	// the conversion webhook not being available.
	sources []caDataSource

	log logr.Logger
	client.Client

	resourceName string // just used for logging
}

// splitNamespacedName turns the string form of a namespaced name
// (<namespace>/<name>) back into a types.NamespacedName.
func splitNamespacedName(nameStr string) types.NamespacedName {
	splitPoint := strings.IndexRune(nameStr, types.Separator)
	if splitPoint == -1 {
		return types.NamespacedName{Name: nameStr}
	}
	return types.NamespacedName{Namespace: nameStr[:splitPoint], Name: nameStr[splitPoint+1:]}
}

// Reconcile attempts to ensure that a particular object has all the CAs injected that
// it has requested.
func (r *genericInjectReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
	ctx := context.Background()
	log := r.log.WithValues(r.resourceName, req.NamespacedName)

	// fetch the target object
	target := r.injector.NewTarget()
	if err := r.Client.Get(ctx, req.NamespacedName, target.AsObject()); err != nil {
		if dropNotFound(err) == nil {
			// don't requeue on deletions, which yield a non-found object
			log.V(logf.TraceLevel).Info("not found", "err", err)
			return ctrl.Result{}, nil
		}
		log.Error(err, "unable to fetch target object to inject into")
		return ctrl.Result{}, err
	}

	// ensure that it wants injection
	metaObj, err := meta.Accessor(target.AsObject())
	if err != nil {
		log.Error(err, "unable to get metadata for object")
		return ctrl.Result{}, err
	}
	log = logf.WithResource(r.log, metaObj)

	if !metaObj.GetDeletionTimestamp().IsZero() {
		log.V(logf.TraceLevel).Info("ignoring", "reason", "object has a non-zero deletion timestamp")
		return ctrl.Result{}, nil
	}

	dataSource, err := r.caDataSourceFor(log, metaObj)
	if err != nil {
		log.V(logf.DebugLevel).Info("failed to determine ca data source for injectable")
		return ctrl.Result{}, nil
	}

	caData, err := dataSource.ReadCA(ctx, log, metaObj)
	if err != nil {
		log.Error(err, "failed to read CA from data source")
		return ctrl.Result{}, err
	}
	if caData == nil {
		log.V(logf.InfoLevel).Info("could not find any ca data in data source for target")
		return ctrl.Result{}, nil
	}

	// actually do the injection
	target.SetCA(caData)

	// actually update with injected CA data
	if err := r.Client.Update(ctx, target.AsObject()); err != nil {
		log.Error(err, "unable to update target object with new CA data")
		return ctrl.Result{}, err
	}
	log.V(logf.InfoLevel).Info("updated object")

	return ctrl.Result{}, nil
}

func (r *genericInjectReconciler) caDataSourceFor(log logr.Logger, metaObj metav1.Object) (caDataSource, error) {
	for _, s := range r.sources {
		if s.Configured(log, metaObj) {
			return s, nil
		}
	}
	return nil, fmt.Errorf("could not determine ca data source for resource")
}
<commit_msg>Explain why we ignore objects with a deletionTimestamp<commit_after>/*
Copyright 2019 The Jetstack cert-manager contributors.

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 cainjector

import (
	"context"
	"fmt"
	"strings"

	"github.com/go-logr/logr"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"

	certmanager "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
	logf "github.com/jetstack/cert-manager/pkg/logs"
)

// dropNotFound ignores the given error if it's a not-found error,
// but otherwise just returns the argument.
func dropNotFound(err error) error {
	if apierrors.IsNotFound(err) {
		return nil
	}
	return err
}

// OwningCertForSecret gets the name of the owning certificate for a
// given secret, returning nil if no such object exists.
// Right now, this actually uses a label instead of owner refs,
// since certmanager doesn't set owner refs on secrets.
func OwningCertForSecret(secret *corev1.Secret) *types.NamespacedName {
	lblVal, hasLbl := secret.Annotations[certmanager.CertificateNameKey]
	if !hasLbl {
		return nil
	}
	return &types.NamespacedName{
		Name:      lblVal,
		Namespace: secret.Namespace,
	}
}

// InjectTarget is a Kubernetes API object that has one or more references to Kubernetes
// Services with corresponding fields for CA bundles.
type InjectTarget interface {
	// AsObject returns this injectable as an object.
	// It should be a pointer suitable for mutation.
	AsObject() runtime.Object

	// SetCA sets the CA of this target to the given certificate data (in the standard
	// PEM format used across Kubernetes).  In cases where multiple CA fields exist per
	// target (like admission webhook configs), all CAs are set to the given value.
	SetCA(data []byte)
}

// Injectable is a point in a Kubernetes API object that represents a Kubernetes Service
// reference with a corresponding spot for a CA bundle.
type Injectable interface {
}

// CertInjector knows how to create an instance of an InjectTarget for some particular type
// of inject target.  For instance, an implementation might create a InjectTarget
// containing an empty MutatingWebhookConfiguration.  The underlying API object can
// be populated (via AsObject) using client.Client#Get, and then CAs can be injected with
// Injectables (representing the various individual webhooks in the config) retrieved with
// Services.
type CertInjector interface {
	// NewTarget creates a new InjectTarget containing an empty underlying object.
	NewTarget() InjectTarget
	// IsAlpha tells the client to disregard "no matching kind" type of errors
	IsAlpha() bool
}

// genericInjectReconciler is a reconciler that knows how to check if a given object is
// marked as requiring a CA, chase down the corresponding Service, Certificate, Secret, and
// inject that into the object.
type genericInjectReconciler struct {
	// injector is responsible for the logic of actually setting a CA -- it's the component
	// that contains type-specific logic.
	injector CertInjector
	// sources is a list of available 'data sources' that can be used to extract
	// caBundles from various source.
	// This is defined as a variable to allow an instance of the secret-based
	// cainjector to run even when Certificate resources cannot we watched due to
	// the conversion webhook not being available.
	sources []caDataSource

	log logr.Logger
	client.Client

	resourceName string // just used for logging
}

// splitNamespacedName turns the string form of a namespaced name
// (<namespace>/<name>) back into a types.NamespacedName.
func splitNamespacedName(nameStr string) types.NamespacedName {
	splitPoint := strings.IndexRune(nameStr, types.Separator)
	if splitPoint == -1 {
		return types.NamespacedName{Name: nameStr}
	}
	return types.NamespacedName{Namespace: nameStr[:splitPoint], Name: nameStr[splitPoint+1:]}
}

// Reconcile attempts to ensure that a particular object has all the CAs injected that
// it has requested.
func (r *genericInjectReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
	ctx := context.Background()
	log := r.log.WithValues(r.resourceName, req.NamespacedName)

	// fetch the target object
	target := r.injector.NewTarget()
	if err := r.Client.Get(ctx, req.NamespacedName, target.AsObject()); err != nil {
		if dropNotFound(err) == nil {
			// don't requeue on deletions, which yield a non-found object
			log.V(logf.DebugLevel).Info("ignoring", "reason", "not found", "err", err)
			return ctrl.Result{}, nil
		}
		log.Error(err, "unable to fetch target object to inject into")
		return ctrl.Result{}, err
	}

	metaObj, err := meta.Accessor(target.AsObject())
	if err != nil {
		log.Error(err, "unable to get metadata for object")
		return ctrl.Result{}, err
	}
	log = logf.WithResource(r.log, metaObj)

	// ignore resources that are being deleted
	if !metaObj.GetDeletionTimestamp().IsZero() {
		log.V(logf.DebugLevel).Info("ignoring", "reason", "object has a non-zero deletion timestamp")
		return ctrl.Result{}, nil
	}

	// ensure that it wants injection
	dataSource, err := r.caDataSourceFor(log, metaObj)
	if err != nil {
		log.V(logf.DebugLevel).Info("failed to determine ca data source for injectable")
		return ctrl.Result{}, nil
	}

	caData, err := dataSource.ReadCA(ctx, log, metaObj)
	if err != nil {
		log.Error(err, "failed to read CA from data source")
		return ctrl.Result{}, err
	}
	if caData == nil {
		log.V(logf.InfoLevel).Info("could not find any ca data in data source for target")
		return ctrl.Result{}, nil
	}

	// actually do the injection
	target.SetCA(caData)

	// actually update with injected CA data
	if err := r.Client.Update(ctx, target.AsObject()); err != nil {
		log.Error(err, "unable to update target object with new CA data")
		return ctrl.Result{}, err
	}
	log.V(logf.InfoLevel).Info("updated object")

	return ctrl.Result{}, nil
}

func (r *genericInjectReconciler) caDataSourceFor(log logr.Logger, metaObj metav1.Object) (caDataSource, error) {
	for _, s := range r.sources {
		if s.Configured(log, metaObj) {
			return s, nil
		}
	}
	return nil, fmt.Errorf("could not determine ca data source for resource")
}
<|endoftext|>


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

package jpeg

import (
	"bytes"
	"image"
	"image/png"
	"io/ioutil"
	"rand"
	"os"
	"testing"
)

var testCase = []struct {
	filename  string
	quality   int
	tolerance int64
}{
	{"../testdata/video-001.png", 1, 24 << 8},
	{"../testdata/video-001.png", 20, 12 << 8},
	{"../testdata/video-001.png", 60, 8 << 8},
	{"../testdata/video-001.png", 80, 6 << 8},
	{"../testdata/video-001.png", 90, 4 << 8},
	{"../testdata/video-001.png", 100, 2 << 8},
}

func delta(u0, u1 uint32) int64 {
	d := int64(u0) - int64(u1)
	if d < 0 {
		return -d
	}
	return d
}

func readPng(filename string) (image.Image, os.Error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return png.Decode(f)
}

func TestWriter(t *testing.T) {
	for _, tc := range testCase {
		// Read the image.
		m0, err := readPng(tc.filename)
		if err != nil {
			t.Error(tc.filename, err)
			continue
		}
		// Encode that image as JPEG.
		buf := bytes.NewBuffer(nil)
		err = Encode(buf, m0, &Options{Quality: tc.quality})
		if err != nil {
			t.Error(tc.filename, err)
			continue
		}
		// Decode that JPEG.
		m1, err := Decode(buf)
		if err != nil {
			t.Error(tc.filename, err)
			continue
		}
		// Compute the average delta in RGB space.
		b := m0.Bounds()
		var sum, n int64
		for y := b.Min.Y; y < b.Max.Y; y++ {
			for x := b.Min.X; x < b.Max.X; x++ {
				c0 := m0.At(x, y)
				c1 := m1.At(x, y)
				r0, g0, b0, _ := c0.RGBA()
				r1, g1, b1, _ := c1.RGBA()
				sum += delta(r0, r1)
				sum += delta(g0, g1)
				sum += delta(b0, b1)
				n += 3
			}
		}
		// Compare the average delta to the tolerance level.
		if sum/n > tc.tolerance {
			t.Errorf("%s, quality=%d: average delta is too high", tc.filename, tc.quality)
			continue
		}
	}
}

func BenchmarkEncodeRGBOpaque(b *testing.B) {
	b.StopTimer()
	img := image.NewRGBA(640, 480)
	// Set all pixels to 0xFF alpha to force opaque mode.
	bo := img.Bounds()
	rnd := rand.New(rand.NewSource(123))
	for y := bo.Min.Y; y < bo.Max.Y; y++ {
		for x := bo.Min.X; x < bo.Max.X; x++ {
			img.Set(x, y, image.RGBAColor{
				uint8(rnd.Intn(256)),
				uint8(rnd.Intn(256)),
				uint8(rnd.Intn(256)),
				255})
		}
	}
	if !img.Opaque() {
		panic("expected image to be opaque")
	}
	b.SetBytes(640 * 480 * 4)
	b.StartTimer()
	options := &Options{Quality: 90}
	for i := 0; i < b.N; i++ {
		Encode(ioutil.Discard, img, options)
	}
}
<commit_msg>image/jpeg: fix build<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package jpeg

import (
	"bytes"
	"image"
	"image/png"
	"io/ioutil"
	"rand"
	"os"
	"testing"
)

var testCase = []struct {
	filename  string
	quality   int
	tolerance int64
}{
	{"../testdata/video-001.png", 1, 24 << 8},
	{"../testdata/video-001.png", 20, 12 << 8},
	{"../testdata/video-001.png", 60, 8 << 8},
	{"../testdata/video-001.png", 80, 6 << 8},
	{"../testdata/video-001.png", 90, 4 << 8},
	{"../testdata/video-001.png", 100, 2 << 8},
}

func delta(u0, u1 uint32) int64 {
	d := int64(u0) - int64(u1)
	if d < 0 {
		return -d
	}
	return d
}

func readPng(filename string) (image.Image, os.Error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return png.Decode(f)
}

func TestWriter(t *testing.T) {
	for _, tc := range testCase {
		// Read the image.
		m0, err := readPng(tc.filename)
		if err != nil {
			t.Error(tc.filename, err)
			continue
		}
		// Encode that image as JPEG.
		buf := bytes.NewBuffer(nil)
		err = Encode(buf, m0, &Options{Quality: tc.quality})
		if err != nil {
			t.Error(tc.filename, err)
			continue
		}
		// Decode that JPEG.
		m1, err := Decode(buf)
		if err != nil {
			t.Error(tc.filename, err)
			continue
		}
		// Compute the average delta in RGB space.
		b := m0.Bounds()
		var sum, n int64
		for y := b.Min.Y; y < b.Max.Y; y++ {
			for x := b.Min.X; x < b.Max.X; x++ {
				c0 := m0.At(x, y)
				c1 := m1.At(x, y)
				r0, g0, b0, _ := c0.RGBA()
				r1, g1, b1, _ := c1.RGBA()
				sum += delta(r0, r1)
				sum += delta(g0, g1)
				sum += delta(b0, b1)
				n += 3
			}
		}
		// Compare the average delta to the tolerance level.
		if sum/n > tc.tolerance {
			t.Errorf("%s, quality=%d: average delta is too high", tc.filename, tc.quality)
			continue
		}
	}
}

func BenchmarkEncodeRGBOpaque(b *testing.B) {
	b.StopTimer()
	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
	// Set all pixels to 0xFF alpha to force opaque mode.
	bo := img.Bounds()
	rnd := rand.New(rand.NewSource(123))
	for y := bo.Min.Y; y < bo.Max.Y; y++ {
		for x := bo.Min.X; x < bo.Max.X; x++ {
			img.Set(x, y, image.RGBAColor{
				uint8(rnd.Intn(256)),
				uint8(rnd.Intn(256)),
				uint8(rnd.Intn(256)),
				255})
		}
	}
	if !img.Opaque() {
		panic("expected image to be opaque")
	}
	b.SetBytes(640 * 480 * 4)
	b.StartTimer()
	options := &Options{Quality: 90}
	for i := 0; i < b.N; i++ {
		Encode(ioutil.Discard, img, options)
	}
}
<|endoftext|>


<commit_before>package vsock

import (
	"errors"
	"fmt"
	"net"
	"os"
	"syscall"
)

/* No way to teach net or syscall about vsock sockaddr, so go right to C */

/*
#include <sys/socket.h>
#include "include/uapi/linux/vm_sockets.h"
int bind_sockaddr_vm(int fd, const struct sockaddr_vm *sa_vm) {
    return bind(fd, (const struct sockaddr*)sa_vm, sizeof(*sa_vm));
}
int connect_sockaddr_vm(int fd, const struct sockaddr_vm *sa_vm) {
    return connect(fd, (const struct sockaddr*)sa_vm, sizeof(*sa_vm));
}
int accept_vm(int fd, struct sockaddr_vm *sa_vm, socklen_t *sa_vm_len) {
    return accept4(fd, (struct sockaddr *)sa_vm, sa_vm_len, 0);
}
*/
import "C"

const (
	AF_VSOCK            = 40
	VSOCK_CID_ANY       = 4294967295 /* 2^32-1 */
)

// Listen returns a net.Listener which can accept connections on the given
// vhan port.
func Listen(port uint) (net.Listener, error) {
	accept_fd, err := syscall.Socket(AF_VSOCK, syscall.SOCK_STREAM, 0)
	if err != nil {
		return nil, err
	}

	sa := C.struct_sockaddr_vm{}
	sa.svm_family = AF_VSOCK
	sa.svm_port = C.uint(port)
	sa.svm_cid = VSOCK_CID_ANY

	if ret := C.bind_sockaddr_vm(C.int(accept_fd), &sa); ret != 0 {
		return nil, errors.New(fmt.Sprintf("failed bind vsock connection to %08x.%08x, returned %d", sa.svm_cid, sa.svm_port, ret))
	}

	err = syscall.Listen(accept_fd, syscall.SOMAXCONN)
	if err != nil {
		return nil, err
	}
	return &vsockListener{accept_fd, port}, nil
}

type vsockListener struct {
	accept_fd int
	port      uint
}

func (v *vsockListener) Accept() (net.Conn, error) {
	var accept_sa C.struct_sockaddr_vm
	var accept_sa_len C.socklen_t

	accept_sa_len = C.sizeof_struct_sockaddr_vm
	fd, err := C.accept_vm(C.int(v.accept_fd), &accept_sa, &accept_sa_len)
	if err != nil {
		return nil, err
	}
	vsock := os.NewFile(uintptr(fd), fmt.Sprintf("vsock:%d", fd))
	conn, err := net.FileConn(vsock)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func (v *vsockListener) Close() error {
	return syscall.Close(v.accept_fd)
}

type vsockAddr struct {
	network string
	addr    string
}

func (a *vsockAddr) Network() string {
	return a.network
}

func (a *vsockAddr) String() string {
	return a.addr
}

func (v *vsockListener) Addr() net.Addr {
	return &vsockAddr{
		network: "vsock",
		addr:    fmt.Sprintf("%08x", v.port),
	}
}
<commit_msg>proxy: vsock connections support CloseRead and CloseWrite<commit_after>package vsock

import (
	"errors"
	"fmt"
	"net"
	"os"
	"syscall"
)

/* No way to teach net or syscall about vsock sockaddr, so go right to C */

/*
#include <sys/socket.h>
#include "include/uapi/linux/vm_sockets.h"
int bind_sockaddr_vm(int fd, const struct sockaddr_vm *sa_vm) {
    return bind(fd, (const struct sockaddr*)sa_vm, sizeof(*sa_vm));
}
int connect_sockaddr_vm(int fd, const struct sockaddr_vm *sa_vm) {
    return connect(fd, (const struct sockaddr*)sa_vm, sizeof(*sa_vm));
}
int accept_vm(int fd, struct sockaddr_vm *sa_vm, socklen_t *sa_vm_len) {
    return accept4(fd, (struct sockaddr *)sa_vm, sa_vm_len, 0);
}
*/
import "C"

const (
	AF_VSOCK      = 40
	VSOCK_CID_ANY = 4294967295 /* 2^32-1 */
)

// Listen returns a net.Listener which can accept connections on the given
// vhan port.
func Listen(port uint) (net.Listener, error) {
	accept_fd, err := syscall.Socket(AF_VSOCK, syscall.SOCK_STREAM, 0)
	if err != nil {
		return nil, err
	}

	sa := C.struct_sockaddr_vm{}
	sa.svm_family = AF_VSOCK
	sa.svm_port = C.uint(port)
	sa.svm_cid = VSOCK_CID_ANY

	if ret := C.bind_sockaddr_vm(C.int(accept_fd), &sa); ret != 0 {
		return nil, errors.New(fmt.Sprintf("failed bind vsock connection to %08x.%08x, returned %d", sa.svm_cid, sa.svm_port, ret))
	}

	err = syscall.Listen(accept_fd, syscall.SOMAXCONN)
	if err != nil {
		return nil, err
	}
	return &vsockListener{accept_fd, port}, nil
}

// Conn is a vsock connection which support half-close.
type Conn interface {
	net.Conn
	CloseRead() error
	CloseWrite() error
}

type vsockListener struct {
	accept_fd int
	port      uint
}

func (v *vsockListener) Accept() (net.Conn, error) {
	var accept_sa C.struct_sockaddr_vm
	var accept_sa_len C.socklen_t

	accept_sa_len = C.sizeof_struct_sockaddr_vm
	fd, err := C.accept_vm(C.int(v.accept_fd), &accept_sa, &accept_sa_len)
	if err != nil {
		return nil, err
	}
	return newVsockConn(uintptr(fd), v.port)
}

func (v *vsockListener) Close() error {
	return syscall.Close(v.accept_fd)
}

type VsockAddr struct {
	Port uint
}

func (a VsockAddr) Network() string {
	return "vsock"
}

func (a VsockAddr) String() string {
	return fmt.Sprintf("%08x", a.Port)
}

func (v *vsockListener) Addr() net.Addr {
	return VsockAddr{Port: v.port}
}

// a wrapper around FileConn which supports CloseRead and CloseWrite
type vsockConn struct {
	net.Conn
	fd     uintptr
	local  VsockAddr
	remote VsockAddr
}

type VsockConn struct {
	vsockConn
}

func newVsockConn(fd uintptr, localPort uint) (*VsockConn, error) {
	vsock := os.NewFile(fd, fmt.Sprintf("vsock:%d", fd))
	conn, err := net.FileConn(vsock)
	if err != nil {
		return nil, err
	}
	local := VsockAddr{Port: localPort}
	remote := VsockAddr{Port: uint(0)} // FIXME
	return &VsockConn{vsockConn{Conn: conn, fd: fd, local: local, remote: remote}}, nil
}

func (v *VsockConn) LocalAddr() net.Addr {
	return v.local
}

func (v *VsockConn) RemoteAddr() net.Addr {
	return v.remote
}

func (v *VsockConn) CloseRead() error {
	return syscall.Shutdown(int(v.fd), syscall.SHUT_RD)
}

func (v *VsockConn) CloseWrite() error {
	return syscall.Shutdown(int(v.fd), syscall.SHUT_WR)
}
<|endoftext|>


<commit_before>/*
Copyright 2011 Google Inc.

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

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

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

package main

import (
	"bytes"
	"encoding/base64"
	"encoding/gob"
	"io"
	"log"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

// LaunchRequest is a subset of exec.Cmd plus the addition of Uid/Gid.
// This structure is gob'd and base64'd and sent to the child process
// in the environment variable _RUNSIT_LAUNCH_INFO.  The child then
// drops root and execs itself to be the requested process.
type LaunchRequest struct {
	Uid      int   // or 0 to not change
	Gid      int   // or 0 to not change
	Gids     []int // supplemental
	Path     string
	Env      []string
	Argv     []string // must include Path as argv[0]
	Dir      string
	NumFiles int // new nfile fd rlimit, or 0 to not change
}

func (lr *LaunchRequest) start(extraFiles []*os.File) (cmd *exec.Cmd, outPipe, errPipe io.ReadCloser, err error) {
	var buf bytes.Buffer
	b64enc := base64.NewEncoder(base64.StdEncoding, &buf)
	err = gob.NewEncoder(b64enc).Encode(lr)
	b64enc.Close()
	if err != nil {
		return
	}

	defer func() {
		if err != nil {
			for _, p := range []io.ReadCloser{outPipe, errPipe} {
				if p != nil {
					p.Close()
				}
			}
		}
	}()

	cmd = exec.Command(os.Args[0])
	cmd.Env = append(cmd.Env, "_RUNSIT_LAUNCH_INFO="+buf.String())
	cmd.ExtraFiles = extraFiles
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Setpgid: true,
	}

	outPipe, err = cmd.StdoutPipe()
	if err != nil {
		return
	}
	errPipe, err = cmd.StderrPipe()
	if err != nil {
		return
	}

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

	return cmd, outPipe, errPipe, nil
}

func MaybeBecomeChildProcess() {
	lrs := os.Getenv("_RUNSIT_LAUNCH_INFO")
	if lrs == "" {
		return
	}
	defer os.Exit(2) // should never make it this far, though

	lr := new(LaunchRequest)
	d := gob.NewDecoder(base64.NewDecoder(base64.StdEncoding, strings.NewReader(lrs)))
	err := d.Decode(lr)
	if err != nil {
		log.Fatalf("Failed to decode LaunchRequest in child: %v", err)
	}

	if lr.Gid != 0 {
		if err := syscall.Setgid(lr.Gid); err != nil {
			log.Fatalf("failed to Setgid(%d): %v", lr.Gid, err)
		}
	}
	if len(lr.Gids) != 0 {
		if err := syscall.Setgroups(lr.Gids); err != nil {
			log.Printf("setgroups: %v", err)
		}
	}
	if lr.Uid != 0 {
		if err := syscall.Setuid(lr.Uid); err != nil {
			log.Fatalf("failed to Setuid(%d): %v", lr.Uid, err)
		}
	}
	if lr.Path != "" {
		err = os.Chdir(lr.Dir)
		if err != nil {
			log.Fatalf("failed to chdir to %q: %v", lr.Dir, err)
		}
	}
	if lr.NumFiles != 0 {
		var lim syscall.Rlimit
		if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
			log.Fatalf("failed to get NOFILE rlimit: %v", err)
		}
		noFile := uint64(lr.NumFiles)
		lim.Cur = noFile
		lim.Max = noFile
		if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
			log.Fatalf("failed to set NOFILE rlimit: %v", err)
		}
	}
	err = syscall.Exec(lr.Path, lr.Argv, lr.Env)
	log.Fatalf("failed to exec %q: %v", lr.Path, err)
}
<commit_msg>set rlimit before dropping root, duh<commit_after>/*
Copyright 2011 Google Inc.

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

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

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

package main

import (
	"bytes"
	"encoding/base64"
	"encoding/gob"
	"io"
	"log"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

// LaunchRequest is a subset of exec.Cmd plus the addition of Uid/Gid.
// This structure is gob'd and base64'd and sent to the child process
// in the environment variable _RUNSIT_LAUNCH_INFO.  The child then
// drops root and execs itself to be the requested process.
type LaunchRequest struct {
	Uid      int   // or 0 to not change
	Gid      int   // or 0 to not change
	Gids     []int // supplemental
	Path     string
	Env      []string
	Argv     []string // must include Path as argv[0]
	Dir      string
	NumFiles int // new nfile fd rlimit, or 0 to not change
}

func (lr *LaunchRequest) start(extraFiles []*os.File) (cmd *exec.Cmd, outPipe, errPipe io.ReadCloser, err error) {
	var buf bytes.Buffer
	b64enc := base64.NewEncoder(base64.StdEncoding, &buf)
	err = gob.NewEncoder(b64enc).Encode(lr)
	b64enc.Close()
	if err != nil {
		return
	}

	defer func() {
		if err != nil {
			for _, p := range []io.ReadCloser{outPipe, errPipe} {
				if p != nil {
					p.Close()
				}
			}
		}
	}()

	cmd = exec.Command(os.Args[0])
	cmd.Env = append(cmd.Env, "_RUNSIT_LAUNCH_INFO="+buf.String())
	cmd.ExtraFiles = extraFiles
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Setpgid: true,
	}

	outPipe, err = cmd.StdoutPipe()
	if err != nil {
		return
	}
	errPipe, err = cmd.StderrPipe()
	if err != nil {
		return
	}

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

	return cmd, outPipe, errPipe, nil
}

func MaybeBecomeChildProcess() {
	lrs := os.Getenv("_RUNSIT_LAUNCH_INFO")
	if lrs == "" {
		return
	}
	defer os.Exit(2) // should never make it this far, though

	lr := new(LaunchRequest)
	d := gob.NewDecoder(base64.NewDecoder(base64.StdEncoding, strings.NewReader(lrs)))
	err := d.Decode(lr)
	if err != nil {
		log.Fatalf("Failed to decode LaunchRequest in child: %v", err)
	}
	if lr.NumFiles != 0 {
		var lim syscall.Rlimit
		if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
			log.Fatalf("failed to get NOFILE rlimit: %v", err)
		}
		noFile := uint64(lr.NumFiles)
		lim.Cur = noFile
		lim.Max = noFile
		if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
			log.Fatalf("failed to set NOFILE rlimit: %v", err)
		}
	}
	if lr.Gid != 0 {
		if err := syscall.Setgid(lr.Gid); err != nil {
			log.Fatalf("failed to Setgid(%d): %v", lr.Gid, err)
		}
	}
	if len(lr.Gids) != 0 {
		if err := syscall.Setgroups(lr.Gids); err != nil {
			log.Printf("setgroups: %v", err)
		}
	}
	if lr.Uid != 0 {
		if err := syscall.Setuid(lr.Uid); err != nil {
			log.Fatalf("failed to Setuid(%d): %v", lr.Uid, err)
		}
	}
	if lr.Path != "" {
		err = os.Chdir(lr.Dir)
		if err != nil {
			log.Fatalf("failed to chdir to %q: %v", lr.Dir, err)
		}
	}
	err = syscall.Exec(lr.Path, lr.Argv, lr.Env)
	log.Fatalf("failed to exec %q: %v", lr.Path, err)
}
<|endoftext|>


<commit_before>package coreutils

import (
	"os"
	"os/exec"
	"os/user"
	"strconv"
	"syscall"
)

// ExecCommand executes a command with args and returning the stringified output
func ExecCommand(command string, args []string, redirect bool) string {
	if ExecutableExists(command) { // If the executable exists
		currentUser, _ := user.Current()

		var output []byte
		runner := exec.Command(command, args...)

		uidInt, _ := strconv.Atoi(currentUser.Uid)
		gidInt, _ := strconv.Atoi(currentUser.Gid)

		runner.SysProcAttr = &syscall.SysProcAttr{}
		runner.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uidInt), Gid: uint32(gidInt) }

		if redirect { // If we should redirect output to var
			output, _ = runner.CombinedOutput() // Combine the output of stderr and stdout
		} else {
			runner.Stdout = os.Stdout
			runner.Stderr = os.Stderr
			runner.Start()
		}

		return string(output[:])
	} else { // If the executable doesn't exist
		return command + " is not an executable."
	}
}

// ExecutableExists checks if an executable exists
func ExecutableExists(executableName string) bool {
	_, existsErr := exec.LookPath(executableName)
	return (existsErr == nil)
}
<commit_msg>Revert "Ensure we set the Uid and Gid to run the command at."<commit_after>package coreutils

import (
	"os"
	"os/exec"
)

// ExecCommand executes a command with args and returning the stringified output
func ExecCommand(command string, args []string, redirect bool) string {
	if ExecutableExists(command) { // If the executable exists
		var output []byte
		runner := exec.Command(command, args...)

		if redirect { // If we should redirect output to var
			output, _ = runner.CombinedOutput() // Combine the output of stderr and stdout
		} else {
			runner.Stdout = os.Stdout
			runner.Stderr = os.Stderr
			runner.Start()
		}

		return string(output[:])
	} else { // If the executable doesn't exist
		return command + " is not an executable."
	}
}

// ExecutableExists checks if an executable exists
func ExecutableExists(executableName string) bool {
	_, existsErr := exec.LookPath(executableName)
	return (existsErr == nil)
}
<|endoftext|>


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

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	vc "github.com/containers/virtcontainers"
	"github.com/containers/virtcontainers/pkg/oci"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

type execParams struct {
	ociProcess   specs.Process
	cID          string
	pidFile      string
	console      string
	detach       bool
	processLabel string
	noSubreaper  bool
}

var execCommand = cli.Command{
	Name:  "exec",
	Usage: "Execute new process inside the container",
	ArgsUsage: `<container-id> <command> [command options]  || -p process.json <container-id>

   <container-id> is the name for the instance of the container and <command>
   is the command to be executed in the container. <command> can't be empty
   unless a "-p" flag provided.

EXAMPLE:
   If the container is configured to run the linux ps command the following
   will output a list of processes running in the container:

       # ` + name + ` <container-id> ps`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "console",
			Usage: "path to a pseudo terminal",
		},
		cli.StringFlag{
			Name:  "cwd",
			Usage: "current working directory in the container",
		},
		cli.StringSliceFlag{
			Name:  "env, e",
			Usage: "set environment variables",
		},
		cli.BoolFlag{
			Name:  "tty, t",
			Usage: "allocate a pseudo-TTY",
		},
		cli.StringFlag{
			Name:  "user, u",
			Usage: "UID (format: <uid>[:<gid>])",
		},
		cli.StringFlag{
			Name:  "process, p",
			Usage: "path to the process.json",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.StringFlag{
			Name:  "process-label",
			Usage: "set the asm process label for the process commonly used with selinux",
		},
		cli.StringFlag{
			Name:  "apparmor",
			Usage: "set the apparmor profile for the process",
		},
		cli.BoolFlag{
			Name:  "no-new-privs",
			Usage: "set the no new privileges value for the process",
		},
		cli.StringSliceFlag{
			Name:  "cap, c",
			Value: &cli.StringSlice{},
			Usage: "add a capability to the bounding set for the process",
		},
		cli.BoolFlag{
			Name:   "no-subreaper",
			Usage:  "disable the use of the subreaper used to reap reparented processes",
			Hidden: true,
		},
	},
	Action: func(context *cli.Context) error {
		params, err := generateExecParams(context)
		if err != nil {
			return err
		}

		return execute(params)
	},
}

func generateExecParams(context *cli.Context) (execParams, error) {
	ctxArgs := context.Args()

	params := execParams{
		cID:          ctxArgs.First(),
		pidFile:      context.String("pid-file"),
		console:      context.String("console"),
		detach:       context.Bool("detach"),
		processLabel: context.String("process-label"),
		noSubreaper:  context.Bool("no-subreaper"),
	}

	if context.IsSet("process") == true {
		var ociProcess specs.Process

		fileContent, err := ioutil.ReadFile(context.String("process"))
		if err != nil {
			return execParams{}, err
		}

		if err := json.Unmarshal(fileContent, &ociProcess); err != nil {
			return execParams{}, err
		}

		params.ociProcess = ociProcess
	} else {
		params.ociProcess = specs.Process{
			Terminal: context.Bool("tty"),
			User: specs.User{
				Username: context.String("user"),
			},
			Args:            ctxArgs.Tail(),
			Env:             context.StringSlice("env"),
			Cwd:             context.String("cwd"),
			NoNewPrivileges: context.Bool("no-new-privs"),
			ApparmorProfile: context.String("apparmor"),
		}
	}

	return params, nil
}

func execute(params execParams) error {
	fullID, err := expandContainerID(params.cID)
	if err != nil {
		return err
	}

	params.cID = fullID

	podStatus, err := vc.StatusPod(params.cID)
	if err != nil {
		return err
	}

	if len(podStatus.ContainersStatus) != 1 {
		return fmt.Errorf("BUG: ContainerStatus list from PodStatus %s is wrong, expecting only one ContainerStatus: %v", params.cID, podStatus.ContainersStatus)
	}

	// container MUST be running
	if podStatus.ContainersStatus[0].State.State != vc.StateRunning {
		return fmt.Errorf("Container %s is not running", params.cID)
	}

	// Check status of process running inside the container
	running, err := processRunning(podStatus.ContainersStatus[0].PID)
	if err != nil {
		return err
	}
	if running == false {
		if err := stopContainer(podStatus); err != nil {
			return err
		}

		return fmt.Errorf("Process not running inside container %s", params.cID)
	}

	envVars, err := oci.EnvVars(params.ociProcess.Env)
	if err != nil {
		return err
	}

	cmd := vc.Cmd{
		Args:        params.ociProcess.Args,
		Envs:        envVars,
		WorkDir:     params.ociProcess.Cwd,
		User:        params.ociProcess.User.Username,
		Interactive: params.ociProcess.Terminal,
		Console:     params.console,
	}

	_, _, process, err := vc.EnterContainer(params.cID, podStatus.ContainersStatus[0].ID, cmd)
	if err != nil {
		return err
	}

	// Creation of PID file has to be the last thing done in the exec
	// because containerd considers the exec to have finished starting
	// after this file is created.
	if err := createPIDFile(params.pidFile, process.Pid); err != nil {
		return err
	}

	return nil
}
<commit_msg>exec: Rely on oci.CompatOCIProcess instead of specs.Process<commit_after>// Copyright (c) 2014,2015,2016 Docker, Inc.
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	vc "github.com/containers/virtcontainers"
	"github.com/containers/virtcontainers/pkg/oci"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

type execParams struct {
	ociProcess   oci.CompatOCIProcess
	cID          string
	pidFile      string
	console      string
	detach       bool
	processLabel string
	noSubreaper  bool
}

var execCommand = cli.Command{
	Name:  "exec",
	Usage: "Execute new process inside the container",
	ArgsUsage: `<container-id> <command> [command options]  || -p process.json <container-id>

   <container-id> is the name for the instance of the container and <command>
   is the command to be executed in the container. <command> can't be empty
   unless a "-p" flag provided.

EXAMPLE:
   If the container is configured to run the linux ps command the following
   will output a list of processes running in the container:

       # ` + name + ` <container-id> ps`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "console",
			Usage: "path to a pseudo terminal",
		},
		cli.StringFlag{
			Name:  "cwd",
			Usage: "current working directory in the container",
		},
		cli.StringSliceFlag{
			Name:  "env, e",
			Usage: "set environment variables",
		},
		cli.BoolFlag{
			Name:  "tty, t",
			Usage: "allocate a pseudo-TTY",
		},
		cli.StringFlag{
			Name:  "user, u",
			Usage: "UID (format: <uid>[:<gid>])",
		},
		cli.StringFlag{
			Name:  "process, p",
			Usage: "path to the process.json",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.StringFlag{
			Name:  "process-label",
			Usage: "set the asm process label for the process commonly used with selinux",
		},
		cli.StringFlag{
			Name:  "apparmor",
			Usage: "set the apparmor profile for the process",
		},
		cli.BoolFlag{
			Name:  "no-new-privs",
			Usage: "set the no new privileges value for the process",
		},
		cli.StringSliceFlag{
			Name:  "cap, c",
			Value: &cli.StringSlice{},
			Usage: "add a capability to the bounding set for the process",
		},
		cli.BoolFlag{
			Name:   "no-subreaper",
			Usage:  "disable the use of the subreaper used to reap reparented processes",
			Hidden: true,
		},
	},
	Action: func(context *cli.Context) error {
		params, err := generateExecParams(context)
		if err != nil {
			return err
		}

		return execute(params)
	},
}

func generateExecParams(context *cli.Context) (execParams, error) {
	ctxArgs := context.Args()

	params := execParams{
		cID:          ctxArgs.First(),
		pidFile:      context.String("pid-file"),
		console:      context.String("console"),
		detach:       context.Bool("detach"),
		processLabel: context.String("process-label"),
		noSubreaper:  context.Bool("no-subreaper"),
	}

	if context.IsSet("process") == true {
		var ociProcess oci.CompatOCIProcess

		fileContent, err := ioutil.ReadFile(context.String("process"))
		if err != nil {
			return execParams{}, err
		}

		if err := json.Unmarshal(fileContent, &ociProcess); err != nil {
			return execParams{}, err
		}

		params.ociProcess = ociProcess
	} else {
		params.ociProcess = oci.CompatOCIProcess{}
		params.ociProcess.Terminal = context.Bool("tty")
		params.ociProcess.User = specs.User{
			Username: context.String("user"),
		}
		params.ociProcess.Args = ctxArgs.Tail()
		params.ociProcess.Env = context.StringSlice("env")
		params.ociProcess.Cwd = context.String("cwd")
		params.ociProcess.NoNewPrivileges = context.Bool("no-new-privs")
		params.ociProcess.ApparmorProfile = context.String("apparmor")
	}

	return params, nil
}

func execute(params execParams) error {
	fullID, err := expandContainerID(params.cID)
	if err != nil {
		return err
	}

	params.cID = fullID

	podStatus, err := vc.StatusPod(params.cID)
	if err != nil {
		return err
	}

	if len(podStatus.ContainersStatus) != 1 {
		return fmt.Errorf("BUG: ContainerStatus list from PodStatus %s is wrong, expecting only one ContainerStatus: %v", params.cID, podStatus.ContainersStatus)
	}

	// container MUST be running
	if podStatus.ContainersStatus[0].State.State != vc.StateRunning {
		return fmt.Errorf("Container %s is not running", params.cID)
	}

	// Check status of process running inside the container
	running, err := processRunning(podStatus.ContainersStatus[0].PID)
	if err != nil {
		return err
	}
	if running == false {
		if err := stopContainer(podStatus); err != nil {
			return err
		}

		return fmt.Errorf("Process not running inside container %s", params.cID)
	}

	envVars, err := oci.EnvVars(params.ociProcess.Env)
	if err != nil {
		return err
	}

	cmd := vc.Cmd{
		Args:        params.ociProcess.Args,
		Envs:        envVars,
		WorkDir:     params.ociProcess.Cwd,
		User:        params.ociProcess.User.Username,
		Interactive: params.ociProcess.Terminal,
		Console:     params.console,
	}

	_, _, process, err := vc.EnterContainer(params.cID, podStatus.ContainersStatus[0].ID, cmd)
	if err != nil {
		return err
	}

	// Creation of PID file has to be the last thing done in the exec
	// because containerd considers the exec to have finished starting
	// after this file is created.
	if err := createPIDFile(params.pidFile, process.Pid); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


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

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	vc "github.com/containers/virtcontainers"
	"github.com/containers/virtcontainers/pkg/oci"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

type execParams struct {
	ociProcess   specs.Process
	cID          string
	pidFile      string
	console      string
	detach       bool
	processLabel string
	noSubreaper  bool
}

var execCommand = cli.Command{
	Name:  "exec",
	Usage: "Execute new process inside the container",
	ArgsUsage: `<container-id> <command> [command options]  || -p process.json <container-id>

   <container-id> is the name for the instance of the container and <command>
   is the command to be executed in the container. <command> can't be empty
   unless a "-p" flag provided.

EXAMPLE:
   If the container is configured to run the linux ps command the following
   will output a list of processes running in the container:

       # runc exec <container-id> ps`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "console",
			Usage: "path to a pseudo terminal",
		},
		cli.StringFlag{
			Name:  "cwd",
			Usage: "current working directory in the container",
		},
		cli.StringSliceFlag{
			Name:  "env, e",
			Usage: "set environment variables",
		},
		cli.BoolFlag{
			Name:  "tty, t",
			Usage: "allocate a pseudo-TTY",
		},
		cli.StringFlag{
			Name:  "user, u",
			Usage: "UID (format: <uid>[:<gid>])",
		},
		cli.StringFlag{
			Name:  "process, p",
			Usage: "path to the process.json",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.StringFlag{
			Name:  "process-label",
			Usage: "set the asm process label for the process commonly used with selinux",
		},
		cli.StringFlag{
			Name:  "apparmor",
			Usage: "set the apparmor profile for the process",
		},
		cli.BoolFlag{
			Name:  "no-new-privs",
			Usage: "set the no new privileges value for the process",
		},
		cli.StringSliceFlag{
			Name:  "cap, c",
			Value: &cli.StringSlice{},
			Usage: "add a capability to the bounding set for the process",
		},
		cli.BoolFlag{
			Name:   "no-subreaper",
			Usage:  "disable the use of the subreaper used to reap reparented processes",
			Hidden: true,
		},
	},
	Action: func(context *cli.Context) error {
		params, err := generateExecParams(context)
		if err != nil {
			return err
		}

		return execute(params)
	},
}

func generateExecParams(context *cli.Context) (execParams, error) {
	ctxArgs := context.Args()

	params := execParams{
		cID:          ctxArgs.First(),
		pidFile:      context.String("pid-file"),
		console:      context.String("console"),
		detach:       context.Bool("detach"),
		processLabel: context.String("process-label"),
		noSubreaper:  context.Bool("no-subreaper"),
	}

	if context.IsSet("process") == true {
		var ociProcess specs.Process

		fileContent, err := ioutil.ReadFile(context.String("process"))
		if err != nil {
			return execParams{}, err
		}

		if err := json.Unmarshal(fileContent, ociProcess); err != nil {
			return execParams{}, err
		}

		params.ociProcess = ociProcess
	} else {
		params.ociProcess = specs.Process{
			Terminal: context.Bool("tty"),
			User: specs.User{
				Username: context.String("user"),
			},
			Args:            ctxArgs.Tail(),
			Env:             context.StringSlice("env"),
			Cwd:             context.String("cwd"),
			NoNewPrivileges: context.Bool("no-new-privs"),
			ApparmorProfile: context.String("apparmor"),
		}
	}

	return params, nil
}

func execute(params execParams) error {
	if err := validContainer(params.cID); err != nil {
		return err
	}

	podStatus, err := vc.StatusPod(params.cID)
	if err != nil {
		return err
	}

	if len(podStatus.ContainersStatus) != 1 {
		return fmt.Errorf("BUG: ContainerStatus list from PodStatus %s is wrong, expecting only one ContainerStatus: %v", params.cID, podStatus.ContainersStatus)
	}

	// container MUST be running
	if podStatus.ContainersStatus[0].State.State != vc.StateRunning {
		return fmt.Errorf("Container %s is not running", params.cID)
	}

	// Check status of process running inside the container
	running, err := processRunning(podStatus.ContainersStatus[0].PID)
	if err != nil {
		return err
	}
	if running == false {
		if err := stopContainer(podStatus); err != nil {
			return err
		}

		return fmt.Errorf("Process not running inside container %s", params.cID)
	}

	envVars, err := oci.EnvVars(params.ociProcess.Env)
	if err != nil {
		return err
	}

	cmd := vc.Cmd{
		Args:    params.ociProcess.Args,
		Envs:    envVars,
		WorkDir: params.ociProcess.Cwd,
		User:    params.ociProcess.User.Username,
	}

	if _, err := loadConfiguration(""); err != nil {
		return err
	}

	_, _, process, err := vc.EnterContainer(params.cID, podStatus.ContainersStatus[0].ID, cmd)
	if err != nil {
		return err
	}

	// Creation of PID file has to be the last thing done in the exec
	// because containerd considers the exec to have finished starting
	// after this file is created.
	if err := createPIDFile(params.pidFile, process.Pid); err != nil {
		return err
	}

	return nil
}
<commit_msg>exec: Pass the terminal down to virtcontainers<commit_after>// Copyright (c) 2014,2015,2016 Docker, Inc.
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	vc "github.com/containers/virtcontainers"
	"github.com/containers/virtcontainers/pkg/oci"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

type execParams struct {
	ociProcess   specs.Process
	cID          string
	pidFile      string
	console      string
	detach       bool
	processLabel string
	noSubreaper  bool
}

var execCommand = cli.Command{
	Name:  "exec",
	Usage: "Execute new process inside the container",
	ArgsUsage: `<container-id> <command> [command options]  || -p process.json <container-id>

   <container-id> is the name for the instance of the container and <command>
   is the command to be executed in the container. <command> can't be empty
   unless a "-p" flag provided.

EXAMPLE:
   If the container is configured to run the linux ps command the following
   will output a list of processes running in the container:

       # runc exec <container-id> ps`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "console",
			Usage: "path to a pseudo terminal",
		},
		cli.StringFlag{
			Name:  "cwd",
			Usage: "current working directory in the container",
		},
		cli.StringSliceFlag{
			Name:  "env, e",
			Usage: "set environment variables",
		},
		cli.BoolFlag{
			Name:  "tty, t",
			Usage: "allocate a pseudo-TTY",
		},
		cli.StringFlag{
			Name:  "user, u",
			Usage: "UID (format: <uid>[:<gid>])",
		},
		cli.StringFlag{
			Name:  "process, p",
			Usage: "path to the process.json",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.StringFlag{
			Name:  "process-label",
			Usage: "set the asm process label for the process commonly used with selinux",
		},
		cli.StringFlag{
			Name:  "apparmor",
			Usage: "set the apparmor profile for the process",
		},
		cli.BoolFlag{
			Name:  "no-new-privs",
			Usage: "set the no new privileges value for the process",
		},
		cli.StringSliceFlag{
			Name:  "cap, c",
			Value: &cli.StringSlice{},
			Usage: "add a capability to the bounding set for the process",
		},
		cli.BoolFlag{
			Name:   "no-subreaper",
			Usage:  "disable the use of the subreaper used to reap reparented processes",
			Hidden: true,
		},
	},
	Action: func(context *cli.Context) error {
		params, err := generateExecParams(context)
		if err != nil {
			return err
		}

		return execute(params)
	},
}

func generateExecParams(context *cli.Context) (execParams, error) {
	ctxArgs := context.Args()

	params := execParams{
		cID:          ctxArgs.First(),
		pidFile:      context.String("pid-file"),
		console:      context.String("console"),
		detach:       context.Bool("detach"),
		processLabel: context.String("process-label"),
		noSubreaper:  context.Bool("no-subreaper"),
	}

	if context.IsSet("process") == true {
		var ociProcess specs.Process

		fileContent, err := ioutil.ReadFile(context.String("process"))
		if err != nil {
			return execParams{}, err
		}

		if err := json.Unmarshal(fileContent, ociProcess); err != nil {
			return execParams{}, err
		}

		params.ociProcess = ociProcess
	} else {
		params.ociProcess = specs.Process{
			Terminal: context.Bool("tty"),
			User: specs.User{
				Username: context.String("user"),
			},
			Args:            ctxArgs.Tail(),
			Env:             context.StringSlice("env"),
			Cwd:             context.String("cwd"),
			NoNewPrivileges: context.Bool("no-new-privs"),
			ApparmorProfile: context.String("apparmor"),
		}
	}

	return params, nil
}

func execute(params execParams) error {
	if err := validContainer(params.cID); err != nil {
		return err
	}

	podStatus, err := vc.StatusPod(params.cID)
	if err != nil {
		return err
	}

	if len(podStatus.ContainersStatus) != 1 {
		return fmt.Errorf("BUG: ContainerStatus list from PodStatus %s is wrong, expecting only one ContainerStatus: %v", params.cID, podStatus.ContainersStatus)
	}

	// container MUST be running
	if podStatus.ContainersStatus[0].State.State != vc.StateRunning {
		return fmt.Errorf("Container %s is not running", params.cID)
	}

	// Check status of process running inside the container
	running, err := processRunning(podStatus.ContainersStatus[0].PID)
	if err != nil {
		return err
	}
	if running == false {
		if err := stopContainer(podStatus); err != nil {
			return err
		}

		return fmt.Errorf("Process not running inside container %s", params.cID)
	}

	envVars, err := oci.EnvVars(params.ociProcess.Env)
	if err != nil {
		return err
	}

	cmd := vc.Cmd{
		Args:        params.ociProcess.Args,
		Envs:        envVars,
		WorkDir:     params.ociProcess.Cwd,
		User:        params.ociProcess.User.Username,
		Interactive: params.ociProcess.Terminal,
		Console:     params.console,
	}

	if _, err := loadConfiguration(""); err != nil {
		return err
	}

	_, _, process, err := vc.EnterContainer(params.cID, podStatus.ContainersStatus[0].ID, cmd)
	if err != nil {
		return err
	}

	// Creation of PID file has to be the last thing done in the exec
	// because containerd considers the exec to have finished starting
	// after this file is created.
	if err := createPIDFile(params.pidFile, process.Pid); err != nil {
		return err
	}

	return nil
}
<|endoftext|>