diff --git a/.changelog/20615.txt b/.changelog/20615.txt new file mode 100644 index 00000000000..3e3a1e98804 --- /dev/null +++ b/.changelog/20615.txt @@ -0,0 +1,3 @@ +```release-note:new-data-source +aws_msk_broker_nodes +``` \ No newline at end of file diff --git a/aws/data_source_aws_msk_broker_nodes.go b/aws/data_source_aws_msk_broker_nodes.go new file mode 100644 index 00000000000..ed63cffb4bf --- /dev/null +++ b/aws/data_source_aws_msk_broker_nodes.go @@ -0,0 +1,113 @@ +package aws + +import ( + "fmt" + "sort" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/kafka" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceAwsMskBrokerNodes() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsMskBrokerNodesRead, + + Schema: map[string]*schema.Schema{ + "cluster_arn": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateArn, + }, + + "node_info_list": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "attached_eni_id": { + Type: schema.TypeString, + Computed: true, + }, + "broker_id": { + Type: schema.TypeFloat, + Computed: true, + }, + "client_subnet": { + Type: schema.TypeString, + Computed: true, + }, + "client_vpc_ip_address": { + Type: schema.TypeString, + Computed: true, + }, + "endpoints": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "node_arn": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceAwsMskBrokerNodesRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).kafkaconn + + clusterARN := d.Get("cluster_arn").(string) + input := &kafka.ListNodesInput{ + ClusterArn: aws.String(clusterARN), + } + var nodeInfos []*kafka.NodeInfo + + err := conn.ListNodesPages(input, func(page *kafka.ListNodesOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + nodeInfos = append(nodeInfos, page.NodeInfoList...) + + return !lastPage + }) + + if err != nil { + return fmt.Errorf("error listing MSK Cluster (%s) Broker Nodes: %w", clusterARN, err) + } + + // node list is returned unsorted sort on broker id + sort.Slice(nodeInfos, func(i, j int) bool { + iBrokerId := aws.Float64Value(nodeInfos[i].BrokerNodeInfo.BrokerId) + jBrokerId := aws.Float64Value(nodeInfos[j].BrokerNodeInfo.BrokerId) + return iBrokerId < jBrokerId + }) + + tfList := make([]interface{}, len(nodeInfos)) + + for i, apiObject := range nodeInfos { + brokerNodeInfo := apiObject.BrokerNodeInfo + tfMap := map[string]interface{}{ + "attached_eni_id": aws.StringValue(brokerNodeInfo.AttachedENIId), + "broker_id": aws.Float64Value(brokerNodeInfo.BrokerId), + "client_subnet": aws.StringValue(brokerNodeInfo.ClientSubnet), + "client_vpc_ip_address": aws.StringValue(brokerNodeInfo.ClientVpcIpAddress), + "endpoints": aws.StringValueSlice(brokerNodeInfo.Endpoints), + "node_arn": aws.StringValue(apiObject.NodeARN), + } + + tfList[i] = tfMap + } + + d.SetId(clusterARN) + + if err := d.Set("node_info_list", tfList); err != nil { + return fmt.Errorf("error setting node_info_list: %w", err) + } + + return nil +} diff --git a/aws/data_source_aws_msk_broker_nodes_test.go b/aws/data_source_aws_msk_broker_nodes_test.go new file mode 100644 index 00000000000..ed529018d06 --- /dev/null +++ b/aws/data_source_aws_msk_broker_nodes_test.go @@ -0,0 +1,59 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/kafka" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccAWSMskBrokerNodesDataSource_basic(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.aws_msk_broker_nodes.test" + resourceName := "aws_msk_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSMsk(t) }, + ErrorCheck: testAccErrorCheck(t, kafka.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckMskClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccMskBrokerNodesDataSourceConfig(rName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, "cluster_arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "node_info_list.#", resourceName, "number_of_broker_nodes"), + resource.TestCheckResourceAttr(dataSourceName, "node_info_list.0.broker_id", "1"), + resource.TestCheckResourceAttr(dataSourceName, "node_info_list.1.broker_id", "2"), + resource.TestCheckResourceAttr(dataSourceName, "node_info_list.2.broker_id", "3"), + ), + }, + }, + }) +} +func testAccMskBrokerNodesDataSourceConfig(rName string) string { + return composeConfig(testAccMskClusterBaseConfig(rName), fmt.Sprintf(` +resource "aws_msk_cluster" "test" { + cluster_name = %[1]q + kafka_version = "2.2.1" + number_of_broker_nodes = 3 + + broker_node_group_info { + client_subnets = [aws_subnet.example_subnet_az1.id, aws_subnet.example_subnet_az2.id, aws_subnet.example_subnet_az3.id] + ebs_volume_size = 10 + instance_type = "kafka.t3.small" + security_groups = [aws_security_group.example_sg.id] + } + + tags = { + foo = "bar" + } +} + +data "aws_msk_broker_nodes" "test" { + cluster_arn = aws_msk_cluster.test.arn +} +`, rName)) +} diff --git a/aws/data_source_aws_msk_cluster_test.go b/aws/data_source_aws_msk_cluster_test.go index 594f721bc17..9f62d0e05f3 100644 --- a/aws/data_source_aws_msk_cluster_test.go +++ b/aws/data_source_aws_msk_cluster_test.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) -func TestAccAWSMskClusterDataSource_Name(t *testing.T) { +func TestAccAWSMskClusterDataSource_basic(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") dataSourceName := "data.aws_msk_cluster.test" resourceName := "aws_msk_cluster.test" @@ -21,7 +21,7 @@ func TestAccAWSMskClusterDataSource_Name(t *testing.T) { CheckDestroy: testAccCheckMskClusterDestroy, Steps: []resource.TestStep{ { - Config: testAccMskClusterDataSourceConfigName(rName), + Config: testAccMskClusterDataSourceConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"), resource.TestCheckResourceAttrPair(dataSourceName, "bootstrap_brokers", resourceName, "bootstrap_brokers"), @@ -38,7 +38,7 @@ func TestAccAWSMskClusterDataSource_Name(t *testing.T) { }) } -func testAccMskClusterDataSourceConfigName(rName string) string { +func testAccMskClusterDataSourceConfig(rName string) string { return composeConfig(testAccMskClusterBaseConfig(rName), fmt.Sprintf(` resource "aws_msk_cluster" "test" { cluster_name = %[1]q diff --git a/aws/provider.go b/aws/provider.go index 24376297ed1..b9fb77d2cd5 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -351,6 +351,7 @@ func Provider() *schema.Provider { "aws_lex_intent": dataSourceAwsLexIntent(), "aws_lex_slot_type": dataSourceAwsLexSlotType(), "aws_mq_broker": dataSourceAwsMqBroker(), + "aws_msk_broker_nodes": dataSourceAwsMskBrokerNodes(), "aws_msk_cluster": dataSourceAwsMskCluster(), "aws_msk_configuration": dataSourceAwsMskConfiguration(), "aws_nat_gateway": dataSourceAwsNatGateway(), diff --git a/website/docs/d/msk_broker_nodes.html.markdown b/website/docs/d/msk_broker_nodes.html.markdown new file mode 100644 index 00000000000..43993892601 --- /dev/null +++ b/website/docs/d/msk_broker_nodes.html.markdown @@ -0,0 +1,40 @@ +--- +subcategory: "Managed Streaming for Kafka (MSK)" +layout: "aws" +page_title: "AWS: aws_msk_broker_nodes" +description: |- + Get information on an Amazon MSK Broker Nodes +--- + +# Data Source: aws_msk_broker_nodes + +Get information on an Amazon MSK Broker Nodes. + +## Example Usage + +```terraform +data "aws_msk_broker_nodes" "example" { + cluster_arn = aws_msk_cluster.example.arn +} +``` + +## Argument Reference + +The following arguments are supported: + +* `cluster_arn` - (Required) The ARN of the cluster the nodes belong to. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* [`node_info_list`](#Nodes) - List of MSK Broker Nodes, sorted by broker ID in ascending order. + +### Nodes + +* `attached_eni_id` - The attached elastic network interface of the broker +* `broker_id` - The ID of the broker +* `client_subnet` - The client subnet to which this broker node belongs +* `client_vpc_ip_address` - The client virtual private cloud (VPC) IP address +* `endpoints` - Set of endpoints for accessing the broker. This does not include ports +* `node_arn` - The Amazon Resource Name (ARN) of the node \ No newline at end of file