a16253860039b0256fe64baed28c69e4c7149ab1 — Martin Angers 7 months ago 643d0f0
pkg/commands/generate: add table, tests
M pkg/collect/resources.go => pkg/collect/resources.go +0 -3
@@ 217,9 217,6 @@ // +bungee name,view_type
  //
  // The name must exist as a DynamoDB table collected by bungee.
- // Alternatively, a Terraform variable may be specified as table name
- // so that this is added as a stream Lambda handler to a table managed
- // outside of bungee.
  type Stream struct {
  	ID       string
  	Name     string

M pkg/commands/generate/resources.go => pkg/commands/generate/resources.go +167 -0
@@ 272,3 272,170 @@ _, err := io.Copy(w, &buf)
  	return err
  }
+ 
+ type table struct {
+ 	ID                   string
+ 	Name                 string
+ 	BillingMode          string
+ 	HashKey              string
+ 	RangeKey             string
+ 	TTL                  *tableTTL
+ 	Attributes           []*tableAttribute
+ 	LocalSecondaryIndex  *tableLocalSecondaryIndex
+ 	GlobalSecondaryIndex *tableGlobalSecondaryIndex
+ 	StreamEnabled        bool
+ 	StreamViewType       string
+ }
+ 
+ func (t *table) encode(w io.Writer, indent string) error {
+ 	var buf bytes.Buffer
+ 
+ 	fmt.Fprintf(&buf, "%sresource \"aws_dynamodb_table\" %q {\n", indent, t.ID)
+ 	if t.Name != "" {
+ 		fmt.Fprintf(&buf, "%s\tname = %q\n", indent, t.Name)
+ 	}
+ 	if t.BillingMode != "" {
+ 		fmt.Fprintf(&buf, "%s\tbilling_mode = %q\n", indent, t.BillingMode)
+ 	}
+ 	if t.HashKey != "" {
+ 		fmt.Fprintf(&buf, "%s\thash_key = %q\n", indent, t.HashKey)
+ 	}
+ 	if t.RangeKey != "" {
+ 		fmt.Fprintf(&buf, "%s\trange_key = %q\n", indent, t.RangeKey)
+ 	}
+ 	if t.TTL != nil {
+ 		if err := t.TTL.encode(&buf, indent+"\t"); err != nil {
+ 			return err
+ 		}
+ 	}
+ 	for _, attr := range t.Attributes {
+ 		if err := attr.encode(&buf, indent+"\t"); err != nil {
+ 			return err
+ 		}
+ 	}
+ 	if t.LocalSecondaryIndex != nil {
+ 		if err := t.LocalSecondaryIndex.encode(&buf, indent+"\t"); err != nil {
+ 			return err
+ 		}
+ 	}
+ 	if t.GlobalSecondaryIndex != nil {
+ 		if err := t.GlobalSecondaryIndex.encode(&buf, indent+"\t"); err != nil {
+ 			return err
+ 		}
+ 	}
+ 	fmt.Fprintf(&buf, "%s\tstream_enabled = %t\n", indent, t.StreamEnabled)
+ 	if t.StreamViewType != "" {
+ 		fmt.Fprintf(&buf, "%s\tstream_view_type = %q\n", indent, t.StreamViewType)
+ 	}
+ 	fmt.Fprintf(&buf, "%s}\n", indent)
+ 
+ 	_, err := io.Copy(w, &buf)
+ 	return err
+ }
+ 
+ type tableAttribute struct {
+ 	Name string
+ 	Type string
+ }
+ 
+ func (t *tableAttribute) encode(w io.Writer, indent string) error {
+ 	var buf bytes.Buffer
+ 
+ 	fmt.Fprintf(&buf, "%sattribute {\n", indent)
+ 	if t.Name != "" {
+ 		fmt.Fprintf(&buf, "%s\tname = %q\n", indent, t.Name)
+ 	}
+ 	if t.Type != "" {
+ 		fmt.Fprintf(&buf, "%s\ttype = %q\n", indent, t.Type)
+ 	}
+ 	fmt.Fprintf(&buf, "%s}\n", indent)
+ 
+ 	_, err := io.Copy(w, &buf)
+ 	return err
+ }
+ 
+ type tableTTL struct {
+ 	Enabled       bool
+ 	AttributeName string
+ }
+ 
+ func (t *tableTTL) encode(w io.Writer, indent string) error {
+ 	var buf bytes.Buffer
+ 
+ 	fmt.Fprintf(&buf, "%sttl {\n", indent)
+ 	fmt.Fprintf(&buf, "%s\tenabled = %t\n", indent, t.Enabled)
+ 	if t.AttributeName != "" {
+ 		fmt.Fprintf(&buf, "%s\tattribute_name = %q\n", indent, t.AttributeName)
+ 	}
+ 	fmt.Fprintf(&buf, "%s}\n", indent)
+ 
+ 	_, err := io.Copy(w, &buf)
+ 	return err
+ }
+ 
+ type tableSecondaryIndex struct {
+ 	Name             string
+ 	HashKey          string
+ 	RangeKey         string
+ 	ProjectionType   string
+ 	NonKeyAttributes []string
+ }
+ 
+ func (t *tableSecondaryIndex) encode(w io.Writer, indent string) error {
+ 	var buf bytes.Buffer
+ 
+ 	if t.Name != "" {
+ 		fmt.Fprintf(&buf, "%s\tname = %q\n", indent, t.Name)
+ 	}
+ 	if t.HashKey != "" {
+ 		fmt.Fprintf(&buf, "%s\thash_key = %q\n", indent, t.HashKey)
+ 	}
+ 	if t.RangeKey != "" {
+ 		fmt.Fprintf(&buf, "%s\trange_key = %q\n", indent, t.RangeKey)
+ 	}
+ 	if t.ProjectionType != "" {
+ 		fmt.Fprintf(&buf, "%s\tprojection_type = %q\n", indent, t.ProjectionType)
+ 	}
+ 	if len(t.NonKeyAttributes) > 0 {
+ 		fmt.Fprintf(&buf, "%s\tnon_key_attributes = [", indent)
+ 		for i, attr := range t.NonKeyAttributes {
+ 			if i > 0 {
+ 				fmt.Fprint(&buf, ",")
+ 			}
+ 			fmt.Fprintf(&buf, "%q", attr)
+ 		}
+ 		fmt.Fprint(&buf, "]\n")
+ 	}
+ 	_, err := io.Copy(w, &buf)
+ 	return err
+ }
+ 
+ type tableLocalSecondaryIndex struct {
+ 	tableSecondaryIndex
+ }
+ 
+ func (t *tableLocalSecondaryIndex) encode(w io.Writer, indent string) error {
+ 	var buf bytes.Buffer
+ 
+ 	fmt.Fprintf(&buf, "%slocal_secondary_index {\n", indent)
+ 	t.tableSecondaryIndex.encode(&buf, indent)
+ 	fmt.Fprintf(&buf, "%s}\n", indent)
+ 
+ 	_, err := io.Copy(w, &buf)
+ 	return err
+ }
+ 
+ type tableGlobalSecondaryIndex struct {
+ 	tableSecondaryIndex
+ }
+ 
+ func (t *tableGlobalSecondaryIndex) encode(w io.Writer, indent string) error {
+ 	var buf bytes.Buffer
+ 
+ 	fmt.Fprintf(&buf, "%sglobal_secondary_index {\n", indent)
+ 	t.tableSecondaryIndex.encode(&buf, indent)
+ 	fmt.Fprintf(&buf, "%s}\n", indent)
+ 
+ 	_, err := io.Copy(w, &buf)
+ 	return err
+ }

M pkg/commands/generate/resources_test.go => pkg/commands/generate/resources_test.go +15 -0
@@ 74,6 74,21 @@ }
  }
  
+ func TestTable(t *testing.T) {
+ 	cases := []*table{
+ 		{ID: "t1", Name: "t1"},
+ 		{ID: "t2", Name: "t2", BillingMode: "PAY_PER_REQUEST", HashKey: "K", RangeKey: "R", Attributes: []*tableAttribute{{Name: "K", Type: "S"}, {Name: "R", Type: "N"}}},
+ 		{ID: "t3", Name: "t3", BillingMode: "PAY_PER_REQUEST", HashKey: "K", RangeKey: "R", Attributes: []*tableAttribute{{Name: "K", Type: "S"}, {Name: "R", Type: "N"}}, StreamEnabled: true, StreamViewType: "KEYS_ONLY"},
+ 		{ID: "t4", Name: "t4", BillingMode: "PAY_PER_REQUEST", HashKey: "K", RangeKey: "R", Attributes: []*tableAttribute{{Name: "K", Type: "S"}, {Name: "R", Type: "N"}}, LocalSecondaryIndex: &tableLocalSecondaryIndex{tableSecondaryIndex{Name: "l1", RangeKey: "L", ProjectionType: "KEYS_ONLY"}}},
+ 		{ID: "t5", Name: "t5", BillingMode: "PAY_PER_REQUEST", HashKey: "K", RangeKey: "R", Attributes: []*tableAttribute{{Name: "K", Type: "S"}, {Name: "R", Type: "N"}}, GlobalSecondaryIndex: &tableGlobalSecondaryIndex{tableSecondaryIndex{Name: "g1", HashKey: "GG", RangeKey: "G", ProjectionType: "INCLUDE", NonKeyAttributes: []string{"X", "Y", "Z"}}}},
+ 		{ID: "t6", Name: "t6", BillingMode: "PAY_PER_REQUEST", HashKey: "K", RangeKey: "R", Attributes: []*tableAttribute{{Name: "K", Type: "S"}, {Name: "R", Type: "N"}}, TTL: &tableTTL{Enabled: true, AttributeName: "T"}},
+ 	}
+ 
+ 	for _, c := range cases {
+ 		t.Run(c.ID, testResource("table", c.ID, c))
+ 	}
+ }
+ 
  func testResource(resource, id string, enc encoder) func(*testing.T) {
  	return func(t *testing.T) {
  		var buf bytes.Buffer

A pkg/commands/generate/testdata/table/t1.tf => pkg/commands/generate/testdata/table/t1.tf +4 -0
@@ 0,0 1,4 @@
+ resource "aws_dynamodb_table" "t1" {
+ 	name = "t1"
+ 	stream_enabled = false
+ }

A pkg/commands/generate/testdata/table/t2.tf => pkg/commands/generate/testdata/table/t2.tf +15 -0
@@ 0,0 1,15 @@
+ resource "aws_dynamodb_table" "t2" {
+ 	name = "t2"
+ 	billing_mode = "PAY_PER_REQUEST"
+ 	hash_key = "K"
+ 	range_key = "R"
+ 	attribute {
+ 		name = "K"
+ 		type = "S"
+ 	}
+ 	attribute {
+ 		name = "R"
+ 		type = "N"
+ 	}
+ 	stream_enabled = false
+ }

A pkg/commands/generate/testdata/table/t3.tf => pkg/commands/generate/testdata/table/t3.tf +16 -0
@@ 0,0 1,16 @@
+ resource "aws_dynamodb_table" "t3" {
+ 	name = "t3"
+ 	billing_mode = "PAY_PER_REQUEST"
+ 	hash_key = "K"
+ 	range_key = "R"
+ 	attribute {
+ 		name = "K"
+ 		type = "S"
+ 	}
+ 	attribute {
+ 		name = "R"
+ 		type = "N"
+ 	}
+ 	stream_enabled = true
+ 	stream_view_type = "KEYS_ONLY"
+ }

A pkg/commands/generate/testdata/table/t4.tf => pkg/commands/generate/testdata/table/t4.tf +20 -0
@@ 0,0 1,20 @@
+ resource "aws_dynamodb_table" "t4" {
+ 	name = "t4"
+ 	billing_mode = "PAY_PER_REQUEST"
+ 	hash_key = "K"
+ 	range_key = "R"
+ 	attribute {
+ 		name = "K"
+ 		type = "S"
+ 	}
+ 	attribute {
+ 		name = "R"
+ 		type = "N"
+ 	}
+ 	local_secondary_index {
+ 		name = "l1"
+ 		range_key = "L"
+ 		projection_type = "KEYS_ONLY"
+ 	}
+ 	stream_enabled = false
+ }

A pkg/commands/generate/testdata/table/t5.tf => pkg/commands/generate/testdata/table/t5.tf +22 -0
@@ 0,0 1,22 @@
+ resource "aws_dynamodb_table" "t5" {
+ 	name = "t5"
+ 	billing_mode = "PAY_PER_REQUEST"
+ 	hash_key = "K"
+ 	range_key = "R"
+ 	attribute {
+ 		name = "K"
+ 		type = "S"
+ 	}
+ 	attribute {
+ 		name = "R"
+ 		type = "N"
+ 	}
+ 	global_secondary_index {
+ 		name = "g1"
+ 		hash_key = "GG"
+ 		range_key = "G"
+ 		projection_type = "INCLUDE"
+ 		non_key_attributes = ["X","Y","Z"]
+ 	}
+ 	stream_enabled = false
+ }

A pkg/commands/generate/testdata/table/t6.tf => pkg/commands/generate/testdata/table/t6.tf +19 -0
@@ 0,0 1,19 @@
+ resource "aws_dynamodb_table" "t6" {
+ 	name = "t6"
+ 	billing_mode = "PAY_PER_REQUEST"
+ 	hash_key = "K"
+ 	range_key = "R"
+ 	ttl {
+ 		enabled = true
+ 		attribute_name = "T"
+ 	}
+ 	attribute {
+ 		name = "K"
+ 		type = "S"
+ 	}
+ 	attribute {
+ 		name = "R"
+ 		type = "N"
+ 	}
+ 	stream_enabled = false
+ }