From 10e6319492ed4a263d6456eec6b28dca267d10db Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Wed, 22 May 2019 13:33:47 -0400 Subject: [PATCH 1/2] New Resource: aws_msk_configuration Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/8736 Output from acceptance testing: ``` --- PASS: TestAccAWSMskConfiguration_KafkaVersions (14.14s) --- PASS: TestAccAWSMskConfiguration_Description (19.35s) --- PASS: TestAccAWSMskConfiguration_basic (27.64s) --- PASS: TestAccAWSMskConfiguration_ServerProperties (29.51s) ``` --- aws/provider.go | 1 + aws/resource_aws_msk_configuration.go | 137 +++++++++++ aws/resource_aws_msk_configuration_test.go | 213 ++++++++++++++++++ website/aws.erb | 4 + .../docs/r/msk_configuration.html.markdown | 52 +++++ 5 files changed, 407 insertions(+) create mode 100644 aws/resource_aws_msk_configuration.go create mode 100644 aws/resource_aws_msk_configuration_test.go create mode 100644 website/docs/r/msk_configuration.html.markdown diff --git a/aws/provider.go b/aws/provider.go index 13d74089d06..128b87498d1 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -563,6 +563,7 @@ func Provider() terraform.ResourceProvider { "aws_media_store_container": resourceAwsMediaStoreContainer(), "aws_media_store_container_policy": resourceAwsMediaStoreContainerPolicy(), "aws_msk_cluster": resourceAwsMskCluster(), + "aws_msk_configuration": resourceAwsMskConfiguration(), "aws_nat_gateway": resourceAwsNatGateway(), "aws_network_acl": resourceAwsNetworkAcl(), "aws_default_network_acl": resourceAwsDefaultNetworkAcl(), diff --git a/aws/resource_aws_msk_configuration.go b/aws/resource_aws_msk_configuration.go new file mode 100644 index 00000000000..374f55e1873 --- /dev/null +++ b/aws/resource_aws_msk_configuration.go @@ -0,0 +1,137 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/kafka" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsMskConfiguration() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsMskConfigurationCreate, + Read: resourceAwsMskConfigurationRead, + Delete: schema.Noop, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "kafka_versions": { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "latest_revision": { + Type: schema.TypeInt, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "server_properties": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + } +} + +func resourceAwsMskConfigurationCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).kafkaconn + + input := &kafka.CreateConfigurationInput{ + KafkaVersions: expandStringSet(d.Get("kafka_versions").(*schema.Set)), + Name: aws.String(d.Get("name").(string)), + ServerProperties: []byte(d.Get("server_properties").(string)), + } + + if v, ok := d.GetOk("description"); ok { + input.Description = aws.String(v.(string)) + } + + output, err := conn.CreateConfiguration(input) + + if err != nil { + return fmt.Errorf("error creating MSK Configuration: %s", err) + } + + d.SetId(aws.StringValue(output.Arn)) + + return resourceAwsMskConfigurationRead(d, meta) +} + +func resourceAwsMskConfigurationRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).kafkaconn + + configurationInput := &kafka.DescribeConfigurationInput{ + Arn: aws.String(d.Id()), + } + + configurationOutput, err := conn.DescribeConfiguration(configurationInput) + + if isAWSErr(err, kafka.ErrCodeNotFoundException, "") { + log.Printf("[WARN] MSK Configuration (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return fmt.Errorf("error describing MSK Configuration (%s): %s", d.Id(), err) + } + + if configurationOutput == nil { + return fmt.Errorf("error describing MSK Configuration (%s): missing result", d.Id()) + } + + if configurationOutput.LatestRevision == nil { + return fmt.Errorf("error describing MSK Configuration (%s): missing latest revision", d.Id()) + } + + revision := configurationOutput.LatestRevision.Revision + revisionInput := &kafka.DescribeConfigurationRevisionInput{ + Arn: aws.String(d.Id()), + Revision: revision, + } + + revisionOutput, err := conn.DescribeConfigurationRevision(revisionInput) + + if err != nil { + return fmt.Errorf("error describing MSK Configuration (%s) Revision (%d): %s", d.Id(), aws.Int64Value(revision), err) + } + + if revisionOutput == nil { + return fmt.Errorf("error describing MSK Configuration (%s) Revision (%d): missing result", d.Id(), aws.Int64Value(revision)) + } + + d.Set("arn", aws.StringValue(configurationOutput.Arn)) + d.Set("description", aws.StringValue(configurationOutput.Description)) + + if err := d.Set("kafka_versions", aws.StringValueSlice(configurationOutput.KafkaVersions)); err != nil { + return fmt.Errorf("error setting kafka_versions: %s", err) + } + + d.Set("latest_revision", aws.Int64Value(revision)) + d.Set("name", aws.StringValue(configurationOutput.Name)) + d.Set("server_properties", string(revisionOutput.ServerProperties)) + + return nil +} diff --git a/aws/resource_aws_msk_configuration_test.go b/aws/resource_aws_msk_configuration_test.go new file mode 100644 index 00000000000..f024fd19df4 --- /dev/null +++ b/aws/resource_aws_msk_configuration_test.go @@ -0,0 +1,213 @@ +package aws + +import ( + "fmt" + "regexp" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/kafka" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSMskConfiguration_basic(t *testing.T) { + var configuration1 kafka.DescribeConfigurationOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_msk_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckMskConfigurationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccMskConfigurationConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckMskConfigurationExists(resourceName, &configuration1), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "kafka", regexp.MustCompile(`configuration/.+`)), + resource.TestCheckResourceAttr(resourceName, "description", ""), + resource.TestCheckResourceAttr(resourceName, "kafka_versions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "latest_revision", "1"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestMatchResourceAttr(resourceName, "server_properties", regexp.MustCompile(`auto.create.topics.enable = true`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSMskConfiguration_Description(t *testing.T) { + var configuration1 kafka.DescribeConfigurationOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_msk_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckMskConfigurationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccMskConfigurationConfigDescription(rName, "description1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMskConfigurationExists(resourceName, &configuration1), + resource.TestCheckResourceAttr(resourceName, "description", "description1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSMskConfiguration_KafkaVersions(t *testing.T) { + var configuration1 kafka.DescribeConfigurationOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_msk_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckMskConfigurationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccMskConfigurationConfigKafkaVersions(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckMskConfigurationExists(resourceName, &configuration1), + resource.TestCheckResourceAttr(resourceName, "kafka_versions.#", "2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSMskConfiguration_ServerProperties(t *testing.T) { + var configuration1 kafka.DescribeConfigurationOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_msk_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckMskConfigurationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccMskConfigurationConfigServerProperties(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckMskConfigurationExists(resourceName, &configuration1), + resource.TestMatchResourceAttr(resourceName, "server_properties", regexp.MustCompile(`auto.create.topics.enable = false`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckMskConfigurationDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_msk_configuration" { + continue + } + + // The API does not support deletions at this time + } + + return nil +} + +func testAccCheckMskConfigurationExists(resourceName string, configuration *kafka.DescribeConfigurationOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("Resource ID not set: %s", resourceName) + } + + conn := testAccProvider.Meta().(*AWSClient).kafkaconn + + input := &kafka.DescribeConfigurationInput{ + Arn: aws.String(rs.Primary.ID), + } + + output, err := conn.DescribeConfiguration(input) + + if err != nil { + return fmt.Errorf("error describing MSK Cluster (%s): %s", rs.Primary.ID, err) + } + + *configuration = *output + + return nil + } +} + +func testAccMskConfigurationConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_msk_configuration" "test" { + kafka_versions = ["2.1.0"] + name = %[1]q + server_properties = < aws_msk_cluster + +
  • + aws_msk_configuration +
  • diff --git a/website/docs/r/msk_configuration.html.markdown b/website/docs/r/msk_configuration.html.markdown new file mode 100644 index 00000000000..f4988e29d0d --- /dev/null +++ b/website/docs/r/msk_configuration.html.markdown @@ -0,0 +1,52 @@ +--- +layout: "aws" +page_title: "AWS: aws_msk_configuration" +sidebar_current: "docs-aws-resource-msk-configuration" +description: |- + Terraform resource for managing an Amazon Managed Streaming for Kafka configuration +--- + +# Resource: aws_msk_configuration + +Manages an Amazon Managed Streaming for Kafka configuration. More information can be found on the [MSK Developer Guide](https://docs.aws.amazon.com/msk/latest/developerguide/msk-configuration.html). + +~> **NOTE:** The API does not support deleting MSK configurations. Removing this Terraform resource will only remove the Terraform state for it. + +~> **NOTE:** This AWS service is in Preview and may change before General Availability release. Backwards compatibility is not guaranteed between Terraform AWS Provider releases. + +## Example Usage + +```hcl +resource "aws_msk_configuration" "example" { + kafka_versions = ["2.1.0"] + name = "example" + server_properties = < Date: Thu, 23 May 2019 06:21:25 -0400 Subject: [PATCH 2/2] Update website/docs/r/msk_configuration.html.markdown Co-Authored-By: Wilken Rivera --- website/docs/r/msk_configuration.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/msk_configuration.html.markdown b/website/docs/r/msk_configuration.html.markdown index f4988e29d0d..eeeb903bf67 100644 --- a/website/docs/r/msk_configuration.html.markdown +++ b/website/docs/r/msk_configuration.html.markdown @@ -32,7 +32,7 @@ PROPERTIES The following arguments are supported: * `server_properties` - (Required) Contents of the server.properties file. Supported properties are documented in the [MSK Developer Guide](https://docs.aws.amazon.com/msk/latest/developerguide/msk-configuration-properties.html). -* `kafka_version` - (Required) List of Apache Kafka versions which can use this configuration. +* `kafka_versions` - (Required) List of Apache Kafka versions which can use this configuration. * `name` - (Required) Name of the configuration. * `description` - (Optional) Description of the configuration.