-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SUMO-245309 Add the terraform support for Azure metric sources #710
base: master
Are you sure you want to change the base?
Changes from all commits
5397700
6c1b4a0
5d6282b
d747310
df9b4b0
9d5d99d
c0deeeb
6ad5431
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,209 @@ | ||||||||||||||||||||
package sumologic | ||||||||||||||||||||
|
||||||||||||||||||||
import ( | ||||||||||||||||||||
"fmt" | ||||||||||||||||||||
"os" | ||||||||||||||||||||
"strconv" | ||||||||||||||||||||
"testing" | ||||||||||||||||||||
|
||||||||||||||||||||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||||||||||||||||||||
"github.com/hashicorp/terraform-plugin-sdk/terraform" | ||||||||||||||||||||
) | ||||||||||||||||||||
|
||||||||||||||||||||
func TestAccSumologicAzureMetricsSource_create(t *testing.T) { | ||||||||||||||||||||
var azureMetricsSource PollingSource | ||||||||||||||||||||
var collector Collector | ||||||||||||||||||||
cName, cDescription, cCategory := getRandomizedParams() | ||||||||||||||||||||
sName, sDescription, sCategory := getRandomizedParams() | ||||||||||||||||||||
azureMetricsResourceName := "sumologic_azure_metrics_source.azure" | ||||||||||||||||||||
testTenantId := os.Getenv("SUMOLOGIC_TEST_AZURE_TENANT_ID") | ||||||||||||||||||||
testClientId := os.Getenv("SUMOLOGIC_TEST_AZURE_CLIENT_ID") | ||||||||||||||||||||
testClientSecret := os.Getenv("SUMOLOGIC_TEST_AZURE_CLIENT_SECRET") | ||||||||||||||||||||
|
||||||||||||||||||||
resource.Test(t, resource.TestCase{ | ||||||||||||||||||||
PreCheck: func() { testAccPreCheck(t) }, | ||||||||||||||||||||
Providers: testAccProviders, | ||||||||||||||||||||
CheckDestroy: testAccCheckAzureMetricsSourceDestroy, | ||||||||||||||||||||
Steps: []resource.TestStep{ | ||||||||||||||||||||
{ | ||||||||||||||||||||
Config: testAccSumologicAzureMetricsSourceConfig(cName, cDescription, cCategory, sName, sDescription, sCategory, testTenantId, testClientId, testClientSecret), | ||||||||||||||||||||
Check: resource.ComposeTestCheckFunc( | ||||||||||||||||||||
testAccCheckAzureMetricsSourceExists(azureMetricsResourceName, &azureMetricsSource), | ||||||||||||||||||||
testAccCheckAzureMetricsSourceValues(&azureMetricsSource, sName, sDescription, sCategory), | ||||||||||||||||||||
testAccCheckCollectorExists("sumologic_collector.test", &collector), | ||||||||||||||||||||
testAccCheckCollectorValues(&collector, cName, cDescription, cCategory, "Etc/UTC", ""), | ||||||||||||||||||||
resource.TestCheckResourceAttrSet(azureMetricsResourceName, "id"), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "name", sName), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "description", sDescription), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "category", sCategory), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "content_type", "AzureMetrics"), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "path.0.type", "AzureMetricsPath"), | ||||||||||||||||||||
), | ||||||||||||||||||||
ExpectNonEmptyPlan: true, | ||||||||||||||||||||
}, | ||||||||||||||||||||
}, | ||||||||||||||||||||
}) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
func TestAccSumologicAzureMetricsSource_update(t *testing.T) { | ||||||||||||||||||||
var azureMetricsSource PollingSource | ||||||||||||||||||||
cName, cDescription, cCategory := getRandomizedParams() | ||||||||||||||||||||
sName, sDescription, sCategory := getRandomizedParams() | ||||||||||||||||||||
sNameUpdated, sDescriptionUpdated, sCategoryUpdated := getRandomizedParams() | ||||||||||||||||||||
azureMetricsResourceName := "sumologic_azure_metrics_source.azure" | ||||||||||||||||||||
testTenantId := os.Getenv("SUMOLOGIC_TEST_AZURE_TENANT_ID") | ||||||||||||||||||||
testClientId := os.Getenv("SUMOLOGIC_TEST_AZURE_CLIENT_ID") | ||||||||||||||||||||
testClientSecret := os.Getenv("SUMOLOGIC_TEST_AZURE_CLIENT_SECRET") | ||||||||||||||||||||
|
||||||||||||||||||||
resource.Test(t, resource.TestCase{ | ||||||||||||||||||||
PreCheck: func() { testAccPreCheck(t) }, | ||||||||||||||||||||
Providers: testAccProviders, | ||||||||||||||||||||
CheckDestroy: testAccCheckAzureMetricsSourceDestroy, | ||||||||||||||||||||
Steps: []resource.TestStep{ | ||||||||||||||||||||
{ | ||||||||||||||||||||
Config: testAccSumologicAzureMetricsSourceConfig(cName, cDescription, cCategory, sName, sDescription, sCategory, testTenantId, testClientId, testClientSecret), | ||||||||||||||||||||
Check: resource.ComposeTestCheckFunc( | ||||||||||||||||||||
testAccCheckAzureMetricsSourceExists(azureMetricsResourceName, &azureMetricsSource), | ||||||||||||||||||||
testAccCheckAzureMetricsSourceValues(&azureMetricsSource, sName, sDescription, sCategory), | ||||||||||||||||||||
resource.TestCheckResourceAttrSet(azureMetricsResourceName, "id"), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "name", sName), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "description", sDescription), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "category", sCategory), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "content_type", "AzureMetrics"), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "path.0.type", "AzureMetricsPath"), | ||||||||||||||||||||
), | ||||||||||||||||||||
ExpectNonEmptyPlan: true, | ||||||||||||||||||||
}, | ||||||||||||||||||||
{ | ||||||||||||||||||||
Config: testAccSumologicAzureMetricsSourceConfig(cName, cDescription, cCategory, sNameUpdated, sDescriptionUpdated, sCategoryUpdated, testTenantId, testClientId, testClientSecret), | ||||||||||||||||||||
Check: resource.ComposeTestCheckFunc( | ||||||||||||||||||||
testAccCheckAzureMetricsSourceExists(azureMetricsResourceName, &azureMetricsSource), | ||||||||||||||||||||
testAccCheckAzureMetricsSourceValues(&azureMetricsSource, sNameUpdated, sDescriptionUpdated, sCategoryUpdated), | ||||||||||||||||||||
resource.TestCheckResourceAttrSet(azureMetricsResourceName, "id"), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "name", sNameUpdated), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "description", sDescriptionUpdated), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "category", sCategoryUpdated), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "content_type", "AzureMetrics"), | ||||||||||||||||||||
resource.TestCheckResourceAttr(azureMetricsResourceName, "path.0.type", "AzureMetricsPath"), | ||||||||||||||||||||
), | ||||||||||||||||||||
ExpectNonEmptyPlan: true, | ||||||||||||||||||||
}, | ||||||||||||||||||||
}, | ||||||||||||||||||||
}) | ||||||||||||||||||||
|
||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
func testAccCheckAzureMetricsSourceDestroy(s *terraform.State) error { | ||||||||||||||||||||
client := testAccProvider.Meta().(*Client) | ||||||||||||||||||||
for _, rs := range s.RootModule().Resources { | ||||||||||||||||||||
if rs.Type != "sumologic_azure_metrics_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 testAccCheckAzureMetricsSourceExists(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 testAccCheckAzureMetricsSourceValues(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 testAccSumologicAzureMetricsSourceConfig(cName, cDescription, cCategory, sName, sDescription, sCategory, testTenantId, testClientId, testClientSecret string) string { | ||||||||||||||||||||
return fmt.Sprintf(` | ||||||||||||||||||||
resource "sumologic_collector" "test" { | ||||||||||||||||||||
name = "%s" | ||||||||||||||||||||
description = "%s" | ||||||||||||||||||||
category = "%s" | ||||||||||||||||||||
} | ||||||||||||||||||||
resource "sumologic_azure_metrics_source" "azure" { | ||||||||||||||||||||
name = "%s" | ||||||||||||||||||||
description = "%s" | ||||||||||||||||||||
category = "%s" | ||||||||||||||||||||
content_type = "AzureMetrics" | ||||||||||||||||||||
collector_id = "${sumologic_collector.test.id}" | ||||||||||||||||||||
|
||||||||||||||||||||
authentication { | ||||||||||||||||||||
type = "AzureClientSecretAuthentication" | ||||||||||||||||||||
tenant_id = "%s" | ||||||||||||||||||||
client_id = "%s" | ||||||||||||||||||||
client_secret = "%s" | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
path { | ||||||||||||||||||||
type = "AzureMetricsPath" | ||||||||||||||||||||
environment = "Azure" | ||||||||||||||||||||
limit_to_namespaces = ["Microsoft.ClassicStorage/storageAccounts"] | ||||||||||||||||||||
azure_tag_filters { | ||||||||||||||||||||
type = "AzureTagFilters" | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we require this type inside There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We require user to specify When |
||||||||||||||||||||
namespace = "Microsoft.ClassicStorage/storageAccounts" | ||||||||||||||||||||
tags { | ||||||||||||||||||||
name = "test-name-1" | ||||||||||||||||||||
values = ["value1"] | ||||||||||||||||||||
} | ||||||||||||||||||||
tags { | ||||||||||||||||||||
name = "test-name-2" | ||||||||||||||||||||
values = ["value2"] | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the array representation here looks very different that the API layer, in the API layer if I want to specify tags for two different namespaces where each namespace there are two tag names, it would look like this
but it seems based on your example here, the above API config translated to TF config would look like this:
also if we keep this, then the naming needs to change, basically these two fields should both change from plural to singular because each represents a single array element. In the normal array representation like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the cloudwatch There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I followed the way kinesis metric source defined the
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I'm currently suspecting if these two forms are equivalent in terraform world. I can do some experiments around this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After testing, the only accepted form for a list of objects, this duplicate terraform-provider-sumologic/sumologic/resource_sumologic_cloudwatch_source_test.go Lines 178 to 186 in 69d8e42
The reason why documentation page shows that way is that it defines a local variable that is similar to the format of what we see in API
It does some extra step using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm. any idea why |
||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
lifecycle { | ||||||||||||||||||||
ignore_changes = [authentication.0.client_secret] | ||||||||||||||||||||
} | ||||||||||||||||||||
}`, cName, cDescription, cCategory, sName, sDescription, sCategory, testTenantId, testClientId, testClientSecret) | ||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this bullet point was accidentally deleted