Skip to content

Commit

Permalink
SUMO-227092: Support terraform for azure event hub log source
Browse files Browse the repository at this point in the history
  • Loading branch information
yyyttthan99 committed Nov 8, 2023
1 parent b5a6461 commit 77d105e
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
## 2.27.1 (Unreleased)
FEATURES:
* **New Resource:** sumologic_azure_event_hub_log_source (GH-57X)

## 2.27.0 (September 28, 2023)
FEATURES:
Expand Down
1 change: 1 addition & 0 deletions sumologic/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ func Provider() terraform.ResourceProvider {
"sumologic_log_search": resourceSumologicLogSearch(),
"sumologic_metrics_search": resourceSumologicMetricsSearch(),
"sumologic_rum_source": resourceSumologicRumSource(),
"sumologic_azure_event_hub_log_source": resourceSumologicGenericPollingSource(),
},
DataSourcesMap: map[string]*schema.Resource{
"sumologic_cse_log_mapping_vendor_product": dataSourceCSELogMappingVendorAndProduct(),
Expand Down
188 changes: 188 additions & 0 deletions sumologic/resource_sumologic_azure_event_hub_log_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
package sumologic

import (
"fmt"
"os"
"strconv"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
)

func TestAccSumologicAzureEventHubLogSource_create(t *testing.T) {
var azureEventHubLogSource PollingSource
var collector Collector
cName, cDescription, cCategory := getRandomizedParams()
sName, sDescription, sCategory := getRandomizedParams()
azureEventHubLogResourceName := "sumologic_azure_event_hub_log_source.azure"
testNamespace := os.Getenv("SUMOLOGIC_TEST_NAMESPACE")
testEventHub := os.Getenv("SUMOLOGIC_TEST_EVENT_HUB")
testConsumerGroup := os.Getenv("SUMOLOGIC_TEST_CONSUMER_GROUP")
testRegion := os.Getenv("SUMOLOGIC_TEST_REGION")
testSASKeyName := os.Getenv("SUMOLOGIC_TEST_SAS_KEY_NAME")
testSASKey := os.Getenv("SUMOLOGIC_TEST_SAS_KEY")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAzureEventHubLogSourceDestroy,
Steps: []resource.TestStep{
{
Config: testAccSumologicAzureEventHubLogSourceConfig(cName, cDescription, cCategory, sName, sDescription, sCategory, testSASKeyName, testSASKey, testNamespace, testEventHub, testConsumerGroup, testRegion),
Check: resource.ComposeTestCheckFunc(
testAccCheckAzureEventHubLogSourceExists(azureEventHubLogResourceName, &azureEventHubLogSource),
testAccCheckAzureEventHubLogSourceValues(&azureEventHubLogSource, sName, sDescription, sCategory),
testAccCheckCollectorExists("sumologic_collector.test", &collector),
testAccCheckCollectorValues(&collector, cName, cDescription, cCategory, "Etc/UTC", ""),
resource.TestCheckResourceAttrSet(azureEventHubLogResourceName, "id"),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "name", sName),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "description", sDescription),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "category", sCategory),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "content_type", "AzureEventHubLog"),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "path.0.type", "AzureEventHubPath"),
),
},
},
})
}
func TestAccSumologicAzureEventHubLogSource_update(t *testing.T) {
var azureEventHubLogSource PollingSource
cName, cDescription, cCategory := getRandomizedParams()
sName, sDescription, sCategory := getRandomizedParams()
sNameUpdated, sDescriptionUpdated, sCategoryUpdated := getRandomizedParams()
azureEventHubLogResourceName := "sumologic_azure_event_hub_log_source.azure"
testNamespace := os.Getenv("SUMOLOGIC_TEST_NAMESPACE")
testEventHub := os.Getenv("SUMOLOGIC_TEST_EVENT_HUB")
testConsumerGroup := os.Getenv("SUMOLOGIC_TEST_CONSUMER_GROUP")
testRegion := os.Getenv("SUMOLOGIC_TEST_REGION")
testSASKeyName := os.Getenv("SUMOLOGIC_TEST_SAS_KEY_NAME")
testSASKey := os.Getenv("SUMOLOGIC_TEST_SAS_KEY")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAzureEventHubLogSourceDestroy,
Steps: []resource.TestStep{
{
Config: testAccSumologicAzureEventHubLogSourceConfig(cName, cDescription, cCategory, sName, sDescription, sCategory, testSASKeyName, testSASKey, testNamespace, testEventHub, testConsumerGroup, testRegion),
Check: resource.ComposeTestCheckFunc(
testAccCheckAzureEventHubLogSourceExists(azureEventHubLogResourceName, &azureEventHubLogSource),
testAccCheckAzureEventHubLogSourceValues(&azureEventHubLogSource, sName, sDescription, sCategory),
resource.TestCheckResourceAttrSet(azureEventHubLogResourceName, "id"),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "name", sName),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "description", sDescription),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "category", sCategory),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "content_type", "AzureEventHubLog"),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "path.0.type", "AzureEventHubPath"),
),
},
{
Config: testAccSumologicAzureEventHubLogSourceConfig(cName, cDescription, cCategory, sNameUpdated, sDescriptionUpdated, sCategoryUpdated, testSASKeyName, testSASKey, testNamespace, testEventHub, testConsumerGroup, testRegion),
Check: resource.ComposeTestCheckFunc(
testAccCheckAzureEventHubLogSourceExists(azureEventHubLogResourceName, &azureEventHubLogSource),
testAccCheckAzureEventHubLogSourceValues(&azureEventHubLogSource, sNameUpdated, sDescriptionUpdated, sCategoryUpdated),
resource.TestCheckResourceAttrSet(azureEventHubLogResourceName, "id"),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "name", sNameUpdated),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "description", sDescriptionUpdated),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "category", sCategoryUpdated),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "content_type", "AzureEventHubLog"),
resource.TestCheckResourceAttr(azureEventHubLogResourceName, "path.0.type", "AzureEventHubPath"),
),
},
},
})
}
func testAccCheckAzureEventHubLogSourceDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*Client)
for _, rs := range s.RootModule().Resources {
if rs.Type != "sumologic_azure_event_hub_log_source" {
continue
}
if rs.Primary.ID == "" {
return fmt.Errorf("Azure Event Hub Log Source destruction check: Azure Event Hub Log Source ID is not set")
}
id, err := strconv.Atoi(rs.Primary.ID)
if err != nil {
return fmt.Errorf("Encountered an error: " + err.Error())
}
collectorID, err := strconv.Atoi(rs.Primary.Attributes["collector_id"])
if err != nil {
return fmt.Errorf("Encountered an error: " + err.Error())
}
s, err := client.GetPollingSource(collectorID, id)
if err != nil {
return fmt.Errorf("Encountered an error: " + err.Error())
}
if s != nil {
return fmt.Errorf("Polling Source still exists")
}
}
return nil
}
func testAccCheckAzureEventHubLogSourceExists(n string, pollingSource *PollingSource) 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("Polling Source ID is not set")
}
id, err := strconv.Atoi(rs.Primary.ID)
if err != nil {
return fmt.Errorf("Polling Source id should be int; got %s", rs.Primary.ID)
}
collectorID, err := strconv.Atoi(rs.Primary.Attributes["collector_id"])
if err != nil {
return fmt.Errorf("Encountered an error: " + err.Error())
}
c := testAccProvider.Meta().(*Client)
pollingSourceResp, err := c.GetPollingSource(collectorID, id)
if err != nil {
return err
}
*pollingSource = *pollingSourceResp
return nil
}
}
func testAccCheckAzureEventHubLogSourceValues(pollingSource *PollingSource, name, description, category string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if pollingSource.Name != name {
return fmt.Errorf("bad name, expected \"%s\", got: %#v", name, pollingSource.Name)
}
if pollingSource.Description != description {
return fmt.Errorf("bad description, expected \"%s\", got: %#v", description, pollingSource.Description)
}
if pollingSource.Category != category {
return fmt.Errorf("bad category, expected \"%s\", got: %#v", category, pollingSource.Category)
}
return nil
}
}
func testAccSumologicAzureEventHubLogSourceConfig(cName, cDescription, cCategory, sName, sDescription, sCategory, testSASKeyName, testSASKey, testNamespace, testEventHub, testConsumerGroup, testRegion string) string {
return fmt.Sprintf(`
resource "sumologic_collector" "test" {
name = "%s"
description = "%s"
category = "%s"
}
resource "sumologic_azure_event_hub_log_source" "azure" {
name = "%s"
description = "%s"
category = "%s"
content_type = "AzureEventHubLog"
collector_id = "${sumologic_collector.test.id}"
authentication {
type = "AzureEventHubAuthentication"
shared_access_policy_name = "%s"
shared_access_policy_key = "%s"
}
path {
type = "AzureEventHubPath"
namespace = "%s"
event_hub_name = "%s"
consumer_group = "%s"
region = "%s"
}
}`, cName, cDescription, cCategory, sName, sDescription, sCategory, testSASKeyName, testSASKey, testNamespace, testEventHub, testConsumerGroup, testRegion)
}
58 changes: 53 additions & 5 deletions sumologic/resource_sumologic_generic_polling_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,19 @@ func resourceSumologicGenericPollingSource() *schema.Resource {
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{"AwsS3Bucket", "AwsElbBucket", "AwsCloudFrontBucket",
"AwsCloudTrailBucket", "AwsS3AuditBucket", "AwsCloudWatch", "AwsInventory", "AwsXRay", "GcpMetrics", "AwsS3ArchiveBucket"}, false),
"AwsCloudTrailBucket", "AwsS3AuditBucket", "AwsCloudWatch", "AwsInventory", "AwsXRay", "GcpMetrics", "AwsS3ArchiveBucket", "AzureEventHubLog"}, false),
}
pollingSource.Schema["scan_interval"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Optional: true,
}
pollingSource.Schema["paused"] = &schema.Schema{
Type: schema.TypeBool,
Required: true,
Optional: true,
}
pollingSource.Schema["url"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
}
pollingSource.Schema["authentication"] = &schema.Schema{
Expand All @@ -50,7 +51,7 @@ func resourceSumologicGenericPollingSource() *schema.Resource {
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"S3BucketAuthentication", "AWSRoleBasedAuthentication", "service_account"}, false),
ValidateFunc: validation.StringInSlice([]string{"S3BucketAuthentication", "AWSRoleBasedAuthentication", "service_account", "AzureEventHubAuthentication"}, false),
},
"access_key": {
Type: schema.TypeString,
Expand Down Expand Up @@ -104,6 +105,14 @@ func resourceSumologicGenericPollingSource() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"shared_access_policy_name": {
Type: schema.TypeString,
Optional: true,
},
"shared_access_policy_key": {
Type: schema.TypeString,
Optional: true,
},
},
},
}
Expand All @@ -119,7 +128,7 @@ func resourceSumologicGenericPollingSource() *schema.Resource {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"S3BucketPathExpression", "CloudWatchPath",
"AwsInventoryPath", "AwsXRayPath", "GcpMetricsPath"}, false),
"AwsInventoryPath", "AwsXRayPath", "GcpMetricsPath", "AzureEventHubPath"}, false),
},
"bucket_name": {
Type: schema.TypeString,
Expand Down Expand Up @@ -220,6 +229,22 @@ func resourceSumologicGenericPollingSource() *schema.Resource {
},
},
},
"namespace": {
Type: schema.TypeString,
Optional: true,
},
"event_hub_name": {
Type: schema.TypeString,
Optional: true,
},
"consumer_group": {
Type: schema.TypeString,
Optional: true,
},
"region": {
Type: schema.TypeString,
Optional: true,
},
},
},
}
Expand Down Expand Up @@ -315,6 +340,11 @@ func resourceToGenericPollingSource(d *schema.ResourceData) (PollingSource, erro
URL: d.Get("url").(string),
}

if source.ContentType == "AzureEventHubLog" {
pollingSource.Paused = false
pollingSource.ScanInterval = 300000
}

authSettings, errAuthSettings := getPollingAuthentication(d)
if errAuthSettings != nil {
return pollingSource, errAuthSettings
Expand Down Expand Up @@ -352,6 +382,10 @@ func getPollingThirdPartyPathAttributes(pollingResource []PollingResource) []map
"custom_services": flattenCustomServices(t.Path.CustomServices),
"tag_filters": flattenPollingTagFilters(t.Path.TagFilters),
"sns_topic_or_subscription_arn": flattenPollingSnsTopicOrSubscriptionArn(t.Path.SnsTopicOrSubscriptionArn),
"namespace": t.Path.Namespace,
"event_hub_name": t.Path.EventHubName,
"consumer_group": t.Path.ConsumerGroup,
"region": t.Path.Region,
}
s = append(s, mapping)
}
Expand All @@ -378,6 +412,8 @@ func getPollingThirdPartyAuthenticationAttributes(pollingResource []PollingResou
"token_uri": t.Authentication.TokenUrl,
"auth_provider_x509_cert_url": t.Authentication.AuthProviderX509CertUrl,
"client_x509_cert_url": t.Authentication.ClientX509CertUrl,
"shared_access_policy_name": t.Authentication.SharedAccessPolicyName,
"shared_access_policy_key": t.Authentication.SharedAccessPolicyKey,
}
s = append(s, mapping)
}
Expand Down Expand Up @@ -539,6 +575,10 @@ func getPollingAuthentication(d *schema.ResourceData) (PollingAuthentication, er
if err != nil {
return authSettings, err
}
case "AzureEventHubAuthentication":
authSettings.Type = "AzureEventHubAuthentication"
authSettings.SharedAccessPolicyName = auth["shared_access_policy_name"].(string)
authSettings.SharedAccessPolicyKey = auth["shared_access_policy_key"].(string)

default:
errorMessage := fmt.Sprintf("[ERROR] Unknown authType: %v", authType)
Expand Down Expand Up @@ -625,6 +665,14 @@ func getPollingPathSettings(d *schema.ResourceData) (PollingPath, error) {
case "GcpMetricsPath":
pathSettings.Type = pathType
addGcpMetricsPathSettings(&pathSettings, path)
case "AzureEventHubPath":
pathSettings.Type = "AzureEventHubPath"
pathSettings.Namespace = path["namespace"].(string)
pathSettings.EventHubName = path["event_hub_name"].(string)
pathSettings.ConsumerGroup = path["consumer_group"].(string)
if path["region"] != nil {
pathSettings.Region = path["region"].(string)
}
default:
errorMessage := fmt.Sprintf("[ERROR] Unknown resourceType in path: %v", pathType)
log.Print(errorMessage)
Expand Down
6 changes: 6 additions & 0 deletions sumologic/sumologic_polling_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type PollingAuthentication struct {
TokenUrl string `json:"token_uri"`
AuthProviderX509CertUrl string `json:"auth_provider_x509_cert_url"`
ClientX509CertUrl string `json:"client_x509_cert_url"`
SharedAccessPolicyName string `json:"sharedAccessPolicyName"`
SharedAccessPolicyKey string `json:"sharedAccessPolicyKey"`
}

type PollingPath struct {
Expand All @@ -52,6 +54,10 @@ type PollingPath struct {
TagFilters []TagFilter `json:"tagFilters,omitempty"`
SnsTopicOrSubscriptionArn PollingSnsTopicOrSubscriptionArn `json:"snsTopicOrSubscriptionArn,omitempty"`
UseVersionedApi *bool `json:"useVersionedApi,omitempty"`
Namespace string `json:"namespace,omitempty"`
EventHubName string `json:"eventHubName,omitempty"`
ConsumerGroup string `json:"consumerGroup,omitempty"`
Region string `json:"region,omitempty"`
}

type TagFilter struct {
Expand Down
Loading

0 comments on commit 77d105e

Please sign in to comment.