From c869f7a8a75794a5c9b6be5b669ff5ba6fdb22c1 Mon Sep 17 00:00:00 2001 From: Alexey Mikhailov Date: Fri, 10 Aug 2018 13:40:03 +0700 Subject: [PATCH 01/10] support lightsail open ports resource --- aws/provider.go | 1 + aws/resource_aws_lightsail_public_ports.go | 121 +++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 aws/resource_aws_lightsail_public_ports.go diff --git a/aws/provider.go b/aws/provider.go index 5e652ec39ba0..ead0d4858d70 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -821,6 +821,7 @@ func Provider() *schema.Provider { "aws_lightsail_key_pair": resourceAwsLightsailKeyPair(), "aws_lightsail_static_ip": resourceAwsLightsailStaticIp(), "aws_lightsail_static_ip_attachment": resourceAwsLightsailStaticIpAttachment(), + "aws_lightsail_public_ports": resourceAwsLightsailPublicPorts(), "aws_lb_cookie_stickiness_policy": resourceAwsLBCookieStickinessPolicy(), "aws_load_balancer_policy": resourceAwsLoadBalancerPolicy(), "aws_load_balancer_backend_server_policy": resourceAwsLoadBalancerBackendServerPolicies(), diff --git a/aws/resource_aws_lightsail_public_ports.go b/aws/resource_aws_lightsail_public_ports.go new file mode 100644 index 000000000000..752eff78ec95 --- /dev/null +++ b/aws/resource_aws_lightsail_public_ports.go @@ -0,0 +1,121 @@ +package aws + +import ( + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/lightsail" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" +) + +func resourceAwsLightsailPublicPorts() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsLightsailPublicPortsCreate, + Read: resourceAwsLightsailPublicPortsRead, + Delete: resourceAwsLightsailPublicPortsDelete, + + Schema: map[string]*schema.Schema{ + "instance_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "port_infos": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "from_port": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(0, 65535), + }, + "to_port": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(0, 65535), + }, + "protocol": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + lightsail.NetworkProtocolUdp, + lightsail.NetworkProtocolTcp, + }, false), + }, + }, + }, + }, + }, + } +} + +func buildAwsLightsailPortInfos(info []interface{}) []*lightsail.PortInfo { + if len(info) == 0 { + return nil + } + + var portInfos []*lightsail.PortInfo + + for _, v := range info { + m := v.(map[string]interface{}) + portInfos = append(portInfos, &lightsail.PortInfo{ + FromPort: aws.Int64((int64)(m["from_port"].(int))), + ToPort: aws.Int64((int64)(m["to_port"].(int))), + Protocol: aws.String(m["protocol"].(string)), + }) + } + return portInfos +} + +func resourceAwsLightsailPublicPortsCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).lightsailconn + _, err := conn.PutInstancePublicPorts(&lightsail.PutInstancePublicPortsInput{ + InstanceName: aws.String(d.Get("instance_name").(string)), + PortInfos: buildAwsLightsailPortInfos(d.Get("port_infos").([]interface{})), + }) + + if err != nil { + return err + } + + return resourceAwsLightsailPublicPortsRead(d, meta) +} + +func resourceAwsLightsailPublicPortsRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).lightsailconn + _, err := conn.GetInstancePortStates(&lightsail.GetInstancePortStatesInput{ + InstanceName: aws.String(d.Get("instance_name").(string)), + }) + + if err != nil { + if awsErr, ok := err.(awserr.Error); ok { + if awsErr.Code() == "NotFoundException" { + log.Printf("[WARN] Lightsail Instance (%s) not found, removing from state", d.Get("instance_name")) + return nil + } + return err + } + return err + } + + return nil +} + +func resourceAwsLightsailPublicPortsDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).lightsailconn + _, err := conn.PutInstancePublicPorts(&lightsail.PutInstancePublicPortsInput{ + InstanceName: aws.String(d.Get("instance_name").(string)), + }) + + if err != nil { + return err + } + return nil +} From 69e2d3c5f96fbddcfcf7a349efa15fae93cfe765 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 24 Mar 2021 17:53:19 -0400 Subject: [PATCH 02/10] r/lightsail_instance_public_ports: Add changelog --- .changelog/8611.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/8611.txt diff --git a/.changelog/8611.txt b/.changelog/8611.txt new file mode 100644 index 000000000000..350021e3c1b3 --- /dev/null +++ b/.changelog/8611.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_lightsail_instance_public_ports +``` \ No newline at end of file From 4fc9faa56e816ea852e79741c7a227135dbe3b31 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 24 Mar 2021 17:53:43 -0400 Subject: [PATCH 03/10] r/lightsail_instance_public_ports: New resource --- aws/provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/provider.go b/aws/provider.go index ead0d4858d70..27bf36d6f018 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -818,10 +818,10 @@ func Provider() *schema.Provider { "aws_licensemanager_license_configuration": resourceAwsLicenseManagerLicenseConfiguration(), "aws_lightsail_domain": resourceAwsLightsailDomain(), "aws_lightsail_instance": resourceAwsLightsailInstance(), + "aws_lightsail_instance_public_ports": resourceAwsLightsailInstancePublicPorts(), "aws_lightsail_key_pair": resourceAwsLightsailKeyPair(), "aws_lightsail_static_ip": resourceAwsLightsailStaticIp(), "aws_lightsail_static_ip_attachment": resourceAwsLightsailStaticIpAttachment(), - "aws_lightsail_public_ports": resourceAwsLightsailPublicPorts(), "aws_lb_cookie_stickiness_policy": resourceAwsLBCookieStickinessPolicy(), "aws_load_balancer_policy": resourceAwsLoadBalancerPolicy(), "aws_load_balancer_backend_server_policy": resourceAwsLoadBalancerBackendServerPolicies(), From 78e067c87986372e64582216dbde709199ed846a Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 24 Mar 2021 17:54:28 -0400 Subject: [PATCH 04/10] docs/lightsail_instance_public_ports: Add docs for new resource --- ...htsail_instance_public_ports.html.markdown | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 website/docs/r/lightsail_instance_public_ports.html.markdown diff --git a/website/docs/r/lightsail_instance_public_ports.html.markdown b/website/docs/r/lightsail_instance_public_ports.html.markdown new file mode 100644 index 000000000000..7c8666859bb8 --- /dev/null +++ b/website/docs/r/lightsail_instance_public_ports.html.markdown @@ -0,0 +1,55 @@ +--- +subcategory: "Lightsail" +layout: "aws" +page_title: "AWS: aws_lightsail_instance_public_ports" +description: |- + Provides an Lightsail Instance +--- + +# Resource: aws_lightsail_instance_public_ports + +Opens ports for a specific Amazon Lightsail instance, and specifies the IP addresses allowed to connect to the instance through the ports, and the protocol. + +-> See [What is Amazon Lightsail?](https://lightsail.aws.amazon.com/ls/docs/getting-started/article/what-is-amazon-lightsail) for more information. + +~> **Note:** Lightsail is currently only supported in a limited number of AWS Regions, please see ["Regions and Availability Zones in Amazon Lightsail"](https://lightsail.aws.amazon.com/ls/docs/overview/article/understanding-regions-and-availability-zones-in-amazon-lightsail) for more details. + +## Example Usage + +```terraform +resource "aws_lightsail_instance" "test" { + name = "yak_sail" + availability_zone = data.aws_availability_zones.available.names[0] + blueprint_id = "amazon_linux" + bundle_id = "nano_1_0" +} + +resource "aws_lightsail_instance_public_ports" "test" { + instance_name = aws_lightsail_instance.test.name + + port_info { + protocol = "tcp" + from_port = 80 + to_port = 80 + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `instance_name` - (Required) Name of the Lightsail Instance. +* `port_info` - (Required) Configuration block with port information. AWS closes all currently open ports that are not included in the `port_info`. Detailed below. + +### port_info + +* `from_port` - (Required) First port in a range of open ports on an instance. +* `protocol` - (Required) IP protocol name. Valid values are `tcp`, `all`, `udp`, and `icmp`. +* `to_port` - (Required) Last port in a range of open ports on an instance. + +## Attributes Reference + +In addition to all arguments above, the following attribute is exported: + +* `id` - ID of the resource. From cbd183f58916f0fa2d172a8a433f439128ae1808 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 24 Mar 2021 17:55:10 -0400 Subject: [PATCH 05/10] r/lightsail_instance_public_ports: Clean up new resource --- ...rce_aws_lightsail_instance_public_ports.go | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 aws/resource_aws_lightsail_instance_public_ports.go diff --git a/aws/resource_aws_lightsail_instance_public_ports.go b/aws/resource_aws_lightsail_instance_public_ports.go new file mode 100644 index 000000000000..5116ce73b222 --- /dev/null +++ b/aws/resource_aws_lightsail_instance_public_ports.go @@ -0,0 +1,214 @@ +package aws + +import ( + "bytes" + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/lightsail" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + multierror "github.com/hashicorp/go-multierror" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/hashcode" +) + +func resourceAwsLightsailInstancePublicPorts() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsLightsailInstancePublicPortsCreate, + Read: resourceAwsLightsailInstancePublicPortsRead, + Delete: resourceAwsLightsailInstancePublicPortsDelete, + + Schema: map[string]*schema.Schema{ + "instance_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "port_info": { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "from_port": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(0, 65535), + }, + "protocol": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(lightsail.NetworkProtocol_Values(), false), + }, + "to_port": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(0, 65535), + }, + }, + }, + }, + }, + } +} + +func resourceAwsLightsailInstancePublicPortsCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).lightsailconn + + var portInfos []*lightsail.PortInfo + if v, ok := d.GetOk("port_info"); ok && v.(*schema.Set).Len() > 0 { + portInfos = expandLightsailPortInfos(v.(*schema.Set).List()) + } + + input := &lightsail.PutInstancePublicPortsInput{ + InstanceName: aws.String(d.Get("instance_name").(string)), + PortInfos: portInfos, + } + + _, err := conn.PutInstancePublicPorts(input) + + if err != nil { + return fmt.Errorf("unable to create public ports for instance %s: %w", d.Get("instance_name").(string), err) + } + + var buffer bytes.Buffer + for _, portInfo := range portInfos { + buffer.WriteString(fmt.Sprintf("%s-%d-%d\n", aws.StringValue(portInfo.Protocol), aws.Int64Value(portInfo.FromPort), aws.Int64Value(portInfo.ToPort))) + } + + d.SetId(fmt.Sprintf("%s-%d", d.Get("instance_name").(string), hashcode.String(buffer.String()))) + + return resourceAwsLightsailInstancePublicPortsRead(d, meta) +} + +func resourceAwsLightsailInstancePublicPortsRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).lightsailconn + + input := &lightsail.GetInstancePortStatesInput{ + InstanceName: aws.String(d.Get("instance_name").(string)), + } + + output, err := conn.GetInstancePortStates(input) + + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, "NotFoundException") { + log.Printf("[WARN] Lightsail instance public ports (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return fmt.Errorf("error reading Lightsail instance public ports (%s): %w", d.Id(), err) + } + + if err := d.Set("port_info", flattenLightsailInstancePortStates(output.PortStates)); err != nil { + return fmt.Errorf("error setting port_info: %w", err) + } + + return nil +} + +func resourceAwsLightsailInstancePublicPortsDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).lightsailconn + + var err *multierror.Error + + var portInfos []*lightsail.PortInfo + if v, ok := d.GetOk("port_info"); ok && v.(*schema.Set).Len() > 0 { + portInfos = expandLightsailPortInfos(v.(*schema.Set).List()) + } + + for _, portInfo := range portInfos { + _, portError := conn.CloseInstancePublicPorts(&lightsail.CloseInstancePublicPortsInput{ + InstanceName: aws.String(d.Get("instance_name").(string)), + PortInfo: portInfo, + }) + + if portError != nil { + err = multierror.Append(err, portError) + } + } + + if err != nil { + return fmt.Errorf("unable to close public ports for instance %s: %w", d.Get("instance_name").(string), err) + } + + return nil +} + +func expandLightsailPortInfo(tfMap map[string]interface{}) *lightsail.PortInfo { + if tfMap == nil { + return nil + } + + apiObject := &lightsail.PortInfo{ + FromPort: aws.Int64((int64)(tfMap["from_port"].(int))), + ToPort: aws.Int64((int64)(tfMap["to_port"].(int))), + Protocol: aws.String(tfMap["protocol"].(string)), + } + + return apiObject +} + +func expandLightsailPortInfos(tfList []interface{}) []*lightsail.PortInfo { + if len(tfList) == 0 { + return nil + } + + var apiObjects []*lightsail.PortInfo + + for _, tfMapRaw := range tfList { + tfMap, ok := tfMapRaw.(map[string]interface{}) + + if !ok { + continue + } + + apiObject := expandLightsailPortInfo(tfMap) + + if apiObject == nil { + continue + } + + apiObjects = append(apiObjects, apiObject) + } + + return apiObjects +} + +func flattenLightsailInstancePortState(apiObject *lightsail.InstancePortState) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + tfMap["from_port"] = aws.Int64Value(apiObject.FromPort) + tfMap["to_port"] = aws.Int64Value(apiObject.ToPort) + tfMap["protocol"] = aws.StringValue(apiObject.Protocol) + + return tfMap +} + +func flattenLightsailInstancePortStates(apiObjects []*lightsail.InstancePortState) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var tfList []interface{} + + for _, apiObject := range apiObjects { + if apiObject == nil { + continue + } + + tfList = append(tfList, flattenLightsailInstancePortState(apiObject)) + } + + return tfList +} From 126bea022eb5d98cf06fe61c2818b85d197b039d Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 24 Mar 2021 17:55:28 -0400 Subject: [PATCH 06/10] tests/r/lightsail_instance_public_ports: Add tests --- ...ws_lightsail_instance_public_ports_test.go | 191 ++++++++++++++++++ aws/resource_aws_lightsail_public_ports.go | 121 ----------- 2 files changed, 191 insertions(+), 121 deletions(-) create mode 100644 aws/resource_aws_lightsail_instance_public_ports_test.go delete mode 100644 aws/resource_aws_lightsail_public_ports.go diff --git a/aws/resource_aws_lightsail_instance_public_ports_test.go b/aws/resource_aws_lightsail_instance_public_ports_test.go new file mode 100644 index 000000000000..da484f594405 --- /dev/null +++ b/aws/resource_aws_lightsail_instance_public_ports_test.go @@ -0,0 +1,191 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/lightsail" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccAWSLightsailInstancePublicPorts_basic(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_lightsail_instance_public_ports.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPartitionHasServicePreCheck(lightsail.EndpointsID, t) + testAccPreCheckAWSLightsail(t) + }, + ErrorCheck: testAccErrorCheck(t, lightsail.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLightsailInstancePublicPortsDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLightsailInstancePublicPortsConfig_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSLightsailInstancePublicPortsExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "port_info.#", "1"), + resource.TestCheckResourceAttr(resourceName, "port_info.0.protocol", "tcp"), + resource.TestCheckResourceAttr(resourceName, "port_info.0.from_port", "80"), + resource.TestCheckResourceAttr(resourceName, "port_info.0.to_port", "80"), + ), + }, + }, + }) +} + +func TestAccAWSLightsailInstancePublicPorts_multiple(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_lightsail_instance_public_ports.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPartitionHasServicePreCheck(lightsail.EndpointsID, t) + testAccPreCheckAWSLightsail(t) + }, + ErrorCheck: testAccErrorCheck(t, lightsail.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLightsailInstancePublicPortsDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLightsailInstancePublicPortsConfig_multiple(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSLightsailInstancePublicPortsExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "port_info.#", "2"), + resource.TestCheckResourceAttr(resourceName, "port_info.1.protocol", "tcp"), + resource.TestCheckResourceAttr(resourceName, "port_info.1.from_port", "80"), + resource.TestCheckResourceAttr(resourceName, "port_info.1.to_port", "80"), + resource.TestCheckResourceAttr(resourceName, "port_info.0.protocol", "tcp"), + resource.TestCheckResourceAttr(resourceName, "port_info.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "port_info.0.to_port", "443"), + ), + }, + }, + }) +} + +func testAccCheckAWSLightsailInstancePublicPortsExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("resource not found: %s", resourceName) + } + + conn := testAccProvider.Meta().(*AWSClient).lightsailconn + + input := &lightsail.GetInstancePortStatesInput{ + InstanceName: aws.String(rs.Primary.Attributes["instance_name"]), + } + + _, err := conn.GetInstancePortStates(input) + + if err != nil { + return fmt.Errorf("error getting Lightsail Instance Public Ports (%s): %w", rs.Primary.ID, err) + } + + return nil + } +} + +func testAccCheckAWSLightsailInstancePublicPortsDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).lightsailconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_lightsail_instance_public_ports" { + continue + } + + input := &lightsail.GetInstancePortStatesInput{ + InstanceName: aws.String(rs.Primary.Attributes["instance_name"]), + } + + output, err := conn.GetInstancePortStates(input) + + if tfawserr.ErrCodeEquals(err, lightsail.ErrCodeNotFoundException) { + continue + } + + if err != nil { + return fmt.Errorf("error getting Lightsail Instance Public Ports (%s): %w", rs.Primary.ID, err) + } + + if output != nil { + return fmt.Errorf("Lightsail Instance Public Ports (%s) still exists", rs.Primary.ID) + } + } + + return nil +} + +func testAccAWSLightsailInstancePublicPortsConfig_basic(rName string) string { + return fmt.Sprintf(` +data "aws_availability_zones" "available" { + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_lightsail_instance" "test" { + name = %[1]q + availability_zone = data.aws_availability_zones.available.names[0] + blueprint_id = "amazon_linux" + bundle_id = "nano_1_0" +} + +resource "aws_lightsail_instance_public_ports" "test" { + instance_name = aws_lightsail_instance.test.name + + port_info { + protocol = "tcp" + from_port = 80 + to_port = 80 + } +} +`, rName) +} + +func testAccAWSLightsailInstancePublicPortsConfig_multiple(rName string) string { + return fmt.Sprintf(` +data "aws_availability_zones" "available" { + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_lightsail_instance" "test" { + name = %[1]q + availability_zone = data.aws_availability_zones.available.names[0] + blueprint_id = "amazon_linux" + bundle_id = "nano_1_0" +} + +resource "aws_lightsail_instance_public_ports" "test" { + instance_name = aws_lightsail_instance.test.name + + port_info { + protocol = "tcp" + from_port = 80 + to_port = 80 + } + + port_info { + protocol = "tcp" + from_port = 443 + to_port = 443 + } +} +`, rName) +} diff --git a/aws/resource_aws_lightsail_public_ports.go b/aws/resource_aws_lightsail_public_ports.go deleted file mode 100644 index 752eff78ec95..000000000000 --- a/aws/resource_aws_lightsail_public_ports.go +++ /dev/null @@ -1,121 +0,0 @@ -package aws - -import ( - "log" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/lightsail" - "github.com/hashicorp/terraform/helper/schema" - "github.com/hashicorp/terraform/helper/validation" -) - -func resourceAwsLightsailPublicPorts() *schema.Resource { - return &schema.Resource{ - Create: resourceAwsLightsailPublicPortsCreate, - Read: resourceAwsLightsailPublicPortsRead, - Delete: resourceAwsLightsailPublicPortsDelete, - - Schema: map[string]*schema.Schema{ - "instance_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "port_infos": { - Type: schema.TypeList, - Required: true, - ForceNew: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "from_port": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - ValidateFunc: validation.IntBetween(0, 65535), - }, - "to_port": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - ValidateFunc: validation.IntBetween(0, 65535), - }, - "protocol": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - lightsail.NetworkProtocolUdp, - lightsail.NetworkProtocolTcp, - }, false), - }, - }, - }, - }, - }, - } -} - -func buildAwsLightsailPortInfos(info []interface{}) []*lightsail.PortInfo { - if len(info) == 0 { - return nil - } - - var portInfos []*lightsail.PortInfo - - for _, v := range info { - m := v.(map[string]interface{}) - portInfos = append(portInfos, &lightsail.PortInfo{ - FromPort: aws.Int64((int64)(m["from_port"].(int))), - ToPort: aws.Int64((int64)(m["to_port"].(int))), - Protocol: aws.String(m["protocol"].(string)), - }) - } - return portInfos -} - -func resourceAwsLightsailPublicPortsCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).lightsailconn - _, err := conn.PutInstancePublicPorts(&lightsail.PutInstancePublicPortsInput{ - InstanceName: aws.String(d.Get("instance_name").(string)), - PortInfos: buildAwsLightsailPortInfos(d.Get("port_infos").([]interface{})), - }) - - if err != nil { - return err - } - - return resourceAwsLightsailPublicPortsRead(d, meta) -} - -func resourceAwsLightsailPublicPortsRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).lightsailconn - _, err := conn.GetInstancePortStates(&lightsail.GetInstancePortStatesInput{ - InstanceName: aws.String(d.Get("instance_name").(string)), - }) - - if err != nil { - if awsErr, ok := err.(awserr.Error); ok { - if awsErr.Code() == "NotFoundException" { - log.Printf("[WARN] Lightsail Instance (%s) not found, removing from state", d.Get("instance_name")) - return nil - } - return err - } - return err - } - - return nil -} - -func resourceAwsLightsailPublicPortsDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).lightsailconn - _, err := conn.PutInstancePublicPorts(&lightsail.PutInstancePublicPortsInput{ - InstanceName: aws.String(d.Get("instance_name").(string)), - }) - - if err != nil { - return err - } - return nil -} From 6024828961e1d0b784f0de7f0f2bfc6fa55fddfe Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 24 Mar 2021 17:59:04 -0400 Subject: [PATCH 07/10] tests/lightsail_instance_public_ports: Lint --- aws/resource_aws_lightsail_instance_public_ports_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aws/resource_aws_lightsail_instance_public_ports_test.go b/aws/resource_aws_lightsail_instance_public_ports_test.go index da484f594405..d22363706e16 100644 --- a/aws/resource_aws_lightsail_instance_public_ports_test.go +++ b/aws/resource_aws_lightsail_instance_public_ports_test.go @@ -146,9 +146,9 @@ resource "aws_lightsail_instance_public_ports" "test" { instance_name = aws_lightsail_instance.test.name port_info { - protocol = "tcp" - from_port = 80 - to_port = 80 + protocol = "tcp" + from_port = 80 + to_port = 80 } } `, rName) From f25719dc948d118ba6e260b23cf62e8a4ab2679d Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 24 Mar 2021 17:59:56 -0400 Subject: [PATCH 08/10] docs/r/lightsail_instance_public_ports: Lint --- website/docs/r/lightsail_instance_public_ports.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/lightsail_instance_public_ports.html.markdown b/website/docs/r/lightsail_instance_public_ports.html.markdown index 7c8666859bb8..6178af0e69f3 100644 --- a/website/docs/r/lightsail_instance_public_ports.html.markdown +++ b/website/docs/r/lightsail_instance_public_ports.html.markdown @@ -40,7 +40,7 @@ resource "aws_lightsail_instance_public_ports" "test" { The following arguments are required: * `instance_name` - (Required) Name of the Lightsail Instance. -* `port_info` - (Required) Configuration block with port information. AWS closes all currently open ports that are not included in the `port_info`. Detailed below. +* `port_info` - (Required) Configuration block with port information. AWS closes all currently open ports that are not included in the `port_info`. Detailed below. ### port_info From c963d533fa7bea684221ac2da3d425cd4ef08dff Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 24 Mar 2021 18:01:59 -0400 Subject: [PATCH 09/10] docs/r/lightsail_instance_public_ports: Lint --- .../docs/r/lightsail_instance_public_ports.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/r/lightsail_instance_public_ports.html.markdown b/website/docs/r/lightsail_instance_public_ports.html.markdown index 6178af0e69f3..a87df42c307b 100644 --- a/website/docs/r/lightsail_instance_public_ports.html.markdown +++ b/website/docs/r/lightsail_instance_public_ports.html.markdown @@ -28,9 +28,9 @@ resource "aws_lightsail_instance_public_ports" "test" { instance_name = aws_lightsail_instance.test.name port_info { - protocol = "tcp" - from_port = 80 - to_port = 80 + protocol = "tcp" + from_port = 80 + to_port = 80 } } ``` From 80fc255c4d40ea8ef6ec8b7caf5c51a826661108 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 24 Mar 2021 18:06:40 -0400 Subject: [PATCH 10/10] docs/r/lightsail_instance_public_ports: Lint --- website/docs/r/lightsail_instance_public_ports.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/lightsail_instance_public_ports.html.markdown b/website/docs/r/lightsail_instance_public_ports.html.markdown index a87df42c307b..320f7d51957b 100644 --- a/website/docs/r/lightsail_instance_public_ports.html.markdown +++ b/website/docs/r/lightsail_instance_public_ports.html.markdown @@ -50,6 +50,6 @@ The following arguments are required: ## Attributes Reference -In addition to all arguments above, the following attribute is exported: +In addition to all arguments above, the following attributes are exported: * `id` - ID of the resource.