Skip to content

Commit

Permalink
Merge pull request #575 from SumoLogic/INVS-1627_Support_cse_tag_schemas
Browse files Browse the repository at this point in the history
INVS-1627: Support cse tag schema
  • Loading branch information
pmontiel-sumo authored Sep 11, 2023
2 parents cae29a9 + bd9aa74 commit 2cc9f53
Show file tree
Hide file tree
Showing 7 changed files with 469 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 2.26.1 (Unreleased)
FEATURES:
* **New Resource:** sumologic_cse_tag_schema (GH-575)
* **New Resource:** sumologic_cse_context_action (GH-573)

## 2.26.0 (September 7, 2023)
Expand Down
1 change: 1 addition & 0 deletions sumologic/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func Provider() terraform.ResourceProvider {
},
},
ResourcesMap: map[string]*schema.Resource{
"sumologic_cse_tag_schema": resourceSumologicCSETagSchema(),
"sumologic_cse_context_action": resourceSumologicCSEContextAction(),
"sumologic_cse_automation": resourceSumologicCSEAutomation(),
"sumologic_cse_entity_normalization_configuration": resourceSumologicCSEEntityNormalizationConfiguration(),
Expand Down
178 changes: 178 additions & 0 deletions sumologic/resource_sumologic_cse_tag_schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package sumologic

import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"log"
)

func resourceSumologicCSETagSchema() *schema.Resource {
return &schema.Resource{
Create: resourceSumologicCSETagSchemaCreate,
Read: resourceSumologicCSETagSchemaRead,
Delete: resourceSumologicCSETagSchemaDelete,
Update: resourceSumologicCSETagSchemaUpdate,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Required: true,
},
"label": {
Type: schema.TypeString,
Required: true,
},
"content_types": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.All(
validation.StringIsNotEmpty,
validation.StringInSlice([]string{"customInsight", "entity", "rule", "threatIntelligence"}, false)),
},
},
"free_form": {
Type: schema.TypeBool,
Required: true,
},
"value_options": getValueOptionsSchema(),
},
}
}

func getValueOptionsSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"value": {
Type: schema.TypeString,
Required: true,
},
"label": {
Type: schema.TypeString,
Optional: true,
},
"link": {
Type: schema.TypeString,
Optional: true,
},
},
},
}
}

func resourceSumologicCSETagSchemaRead(d *schema.ResourceData, meta interface{}) error {
c := meta.(*Client)

var CSETagSchema *CSETagSchema
key := d.Id()

CSETagSchema, err := c.GetCSETagSchema(key)
if err != nil {
log.Printf("[WARN] CSE Tag Schema not found when looking by key: %s, err: %v", key, err)

}

if CSETagSchema == nil {
log.Printf("[WARN] CSE tag Schema not found, removing from state: %v - %v", key, err)
d.SetId("")
return nil
}

d.Set("key", CSETagSchema.Key)
d.Set("label", CSETagSchema.Label)
d.Set("content_types", CSETagSchema.ContentTypes)
d.Set("value_options", valueOptionsArrayToResource(CSETagSchema.ValueOptionObjects))
d.Set("free_form", CSETagSchema.FreeForm)

return nil
}

func valueOptionsArrayToResource(valueOptions []ValueOption) []map[string]interface{} {
result := make([]map[string]interface{}, len(valueOptions))

for i, valueOption := range valueOptions {
result[i] = map[string]interface{}{
"value": valueOption.Value,
"label": valueOption.Label,
"link": valueOption.Link,
}
}

return result
}

func resourceSumologicCSETagSchemaDelete(d *schema.ResourceData, meta interface{}) error {
c := meta.(*Client)

return c.DeleteCSETagSchema(d.Id())

}

func resourceSumologicCSETagSchemaCreate(d *schema.ResourceData, meta interface{}) error {
c := meta.(*Client)

key, err := c.CreateCSETagSchema(CSECreateUpdateTagSchema{
Key: d.Get("key").(string),
Label: d.Get("label").(string),
ContentTypes: resourceFieldsToStringArray(d.Get("content_types").([]interface{})),
ValueOptions: resourceToValueOptionArray(d.Get("value_options").([]interface{})),
FreeForm: d.Get("free_form").(bool),
})

if err != nil {
return err
}

d.SetId(key)

return resourceSumologicCSETagSchemaRead(d, meta)
}

func resourceToValueOptionArray(resouceValueOptions []interface{}) []ValueOption {
result := make([]ValueOption, len(resouceValueOptions))

for i, resourceValueOption := range resouceValueOptions {
result[i] = ValueOption{
Value: resourceValueOption.(map[string]interface{})["value"].(string),
Label: resourceValueOption.(map[string]interface{})["label"].(string),
Link: resourceValueOption.(map[string]interface{})["link"].(string),
}
}

return result
}

func resourceSumologicCSETagSchemaUpdate(d *schema.ResourceData, meta interface{}) error {
CSETagSchema, err := resourceToCSETagSchema(d)
if err != nil {
return err
}
c := meta.(*Client)
if err = c.UpdateCSETagSchema(CSETagSchema); err != nil {
return err
}

return resourceSumologicCSETagSchemaRead(d, meta)
}

func resourceToCSETagSchema(d *schema.ResourceData) (CSECreateUpdateTagSchema, error) {
key := d.Id()
if key == "" {
return CSECreateUpdateTagSchema{}, nil
}

return CSECreateUpdateTagSchema{
Key: key,
Label: d.Get("label").(string),
ContentTypes: resourceFieldsToStringArray(d.Get("content_types").([]interface{})),
ValueOptions: resourceToValueOptionArray(d.Get("value_options").([]interface{})),
FreeForm: d.Get("free_form").(bool),
}, nil
}
142 changes: 142 additions & 0 deletions sumologic/resource_sumologic_cse_tag_schema_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package sumologic

import (
"fmt"
"testing"

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

func TestAccSumologicSCETagSchema_create_update(t *testing.T) {
SkipCseTest(t)

var TagSchema CSETagSchema
nKey := "location"
nLabel := "Label"
nContentTypes := []string{"entity"}
nFreeForm := true
nVOValue := "value"
nVOLabel := "label"
nVOLink := "http://foo.bar.com"
uLabel := "uLabel"
resourceName := "sumologic_cse_tag_schema.tag_schema"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCSETagSchemaDestroy,
Steps: []resource.TestStep{
{
Config: testCreateCSETagSchemaConfig(nKey, nLabel, nContentTypes, nFreeForm, nVOValue, nVOLabel, nVOLink),
Check: resource.ComposeTestCheckFunc(
testCheckCSETagSchemaExists(resourceName, &TagSchema),
testCheckTagSchemaValues(&TagSchema, nKey, nLabel, nContentTypes, nFreeForm, nVOValue, nVOLabel, nVOLink),
resource.TestCheckResourceAttrSet(resourceName, "id"),
),
},
{
Config: testCreateCSETagSchemaConfig(nKey, uLabel, nContentTypes, nFreeForm, nVOValue, nVOLabel, nVOLink),
Check: resource.ComposeTestCheckFunc(
testCheckCSETagSchemaExists(resourceName, &TagSchema),
testCheckTagSchemaValues(&TagSchema, nKey, uLabel, nContentTypes, nFreeForm, nVOValue, nVOLabel, nVOLink),
),
},
},
})
}

func testAccCSETagSchemaDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*Client)

for _, rs := range s.RootModule().Resources {
if rs.Type != "sumologic_cse_tag_schema" {
continue
}

if rs.Primary.ID == "" {
return fmt.Errorf("CSE Tag Schema destruction check: CSE Tag Schema key is not set")
}

s, err := client.GetCSETagSchema(rs.Primary.ID)
if err != nil {
return fmt.Errorf("Encountered an error: " + err.Error())
}
if s != nil {
return fmt.Errorf("Tag Schema still exists")
}
}
return nil
}

func testCreateCSETagSchemaConfig(nKey string, nLabel string, nContentTypes []string, nFreeForm bool, nVOValue string, nVOLabel string, nVOLink string) string {

return fmt.Sprintf(`
resource "sumologic_cse_tag_schema" "tag_schema" {
key = "%s"
label = "%s"
content_types = ["%s"]
free_form = "%t"
value_options {
value = "%s"
label = "%s"
link = "%s"
}
}
`, nKey, nLabel, nContentTypes[0], nFreeForm, nVOValue, nVOLabel, nVOLink)
}

func testCheckCSETagSchemaExists(n string, TagSchema *CSETagSchema) 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("Tag Schema key is not set")
}

c := testAccProvider.Meta().(*Client)
TagSchemaResp, err := c.GetCSETagSchema(rs.Primary.ID)
if err != nil {
return err
}

*TagSchema = *TagSchemaResp

return nil
}
}

func testCheckTagSchemaValues(TagSchema *CSETagSchema, nKey string, nLabel string, nContentTypes []string, nFreeForm bool, nVOValue string, nVOLabel string, nVOLink string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if TagSchema.Key != nKey {
return fmt.Errorf("bad key, expected \"%s\", got: %#v", nKey, TagSchema.Key)
}
if TagSchema.Label != nLabel {
return fmt.Errorf("bad label, expected \"%s\", got: %#v", nLabel, TagSchema.Label)
}
if TagSchema.ContentTypes != nil {
if len(TagSchema.ContentTypes) != len(nContentTypes) {
return fmt.Errorf("bad content_types list lenght, expected \"%d\", got: %d", len(nContentTypes), len(TagSchema.ContentTypes))
}
if TagSchema.ContentTypes[0] != nContentTypes[0] {
return fmt.Errorf("bad content_types in list, expected \"%s\", got: %s", nContentTypes[0], TagSchema.ContentTypes[0])
}
}
if TagSchema.FreeForm != nFreeForm {
return fmt.Errorf("bad free_form field, expected \"%t\", got: %#v", nFreeForm, TagSchema.FreeForm)
}
if TagSchema.ValueOptionObjects[0].Value != nVOValue {
return fmt.Errorf("bad value_option.value field, expected \"%s\", got: %#v", nVOValue, TagSchema.ValueOptionObjects[0].Value)
}
if TagSchema.ValueOptionObjects[0].Label != nVOLabel {
return fmt.Errorf("bad value_option.label field, expected \"%s\", got: %#v", nVOLabel, TagSchema.ValueOptionObjects[0].Label)
}
if TagSchema.ValueOptionObjects[0].Link != nVOLink {
return fmt.Errorf("bad value_option.link field, expected \"%s\", got: %#v", nVOLink, TagSchema.ValueOptionObjects[0].Link)
}

return nil
}
}
Loading

0 comments on commit 2cc9f53

Please sign in to comment.