Skip to content

Commit 7cb0dbd

Browse files
committed
CSRE-183: adding data forwarding resource
1 parent 73ab427 commit 7cb0dbd

File tree

4 files changed

+364
-1
lines changed

4 files changed

+364
-1
lines changed

sumologic/provider.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,11 @@ func Provider() terraform.ResourceProvider {
8888
"sumologic_role": resourceSumologicRole(),
8989
"sumologic_user": resourceSumologicUser(),
9090
"sumologic_ingest_budget": resourceSumologicIngestBudget(),
91-
"sumologic_collector_ingest_budget_assignment": resourceSumologicCollectorIngestBudgetAssignment(),
91+
"sumologic_collector_ingestcf_budget_assignment": resourceSumologicCollectorIngestBudgetAssignment(),
9292
"sumologic_folder": resourceSumologicFolder(),
9393
"sumologic_content": resourceSumologicContent(),
9494
"sumologic_scheduled_view": resourceSumologicScheduledView(),
95+
"sumologic_data_forwarding": resourceSumologicDataForwarding(),
9596
"sumologic_partition": resourceSumologicPartition(),
9697
"sumologic_field_extraction_rule": resourceSumologicFieldExtractionRule(),
9798
"sumologic_connection": resourceSumologicConnection(),
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package sumologic
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
5+
"log"
6+
)
7+
8+
func resourceSumologicDataForwarding() *schema.Resource {
9+
return &schema.Resource{
10+
11+
Create: resourceSumologicDataForwardingCreate,
12+
Read: resourceSumologicDataForwardingRead,
13+
Update: resourceSumologicDataForwardingUpdate,
14+
Delete: resourceSumologicDataForwardingDelete,
15+
16+
Schema: map[string]*schema.Schema{
17+
18+
"destination_name": {
19+
Type: schema.TypeString,
20+
Required: true,
21+
//What validation func do we need for this fields?
22+
},
23+
"description": {
24+
Type: schema.TypeString,
25+
Optional: true,
26+
},
27+
"destination_type": {
28+
Type: schema.TypeString,
29+
Optional: true,
30+
},
31+
"bucket_name": {
32+
Type: schema.TypeString,
33+
Required: true,
34+
ForceNew: true,
35+
},
36+
"status": {
37+
Type: schema.TypeString,
38+
Optional: true,
39+
},
40+
"authentication": {
41+
Type: schema.TypeList,
42+
Required: true,
43+
MaxItems: 1,
44+
Elem: &schema.Resource{
45+
Schema: map[string]*schema.Schema{
46+
"type": {
47+
Type: schema.TypeString,
48+
Required: true,
49+
},
50+
"role_arn": {
51+
Type: schema.TypeString,
52+
Optional: true,
53+
},
54+
"access_key": {
55+
Type: schema.TypeString,
56+
Optional: true,
57+
},
58+
"secret_key": {
59+
Type: schema.TypeString,
60+
Optional: true,
61+
},
62+
},
63+
},
64+
},
65+
"s3_region": {
66+
Type: schema.TypeString,
67+
Optional: true,
68+
},
69+
"s3_server_side_encryption": {
70+
Type: schema.TypeBool, //bool
71+
Optional: true,
72+
},
73+
},
74+
}
75+
76+
}
77+
78+
func resourceSumologicDataForwardingCreate(d *schema.ResourceData, meta interface{}) error {
79+
c := meta.(*Client)
80+
81+
if d.Id() == "" {
82+
dataForwarding := resourceToDataForwarding(d)
83+
createdDataForwarding, err := c.CreateDataForwarding(dataForwarding)
84+
85+
if err != nil {
86+
return err
87+
}
88+
89+
d.SetId(createdDataForwarding.ID)
90+
91+
}
92+
93+
return resourceSumologicDataForwardingUpdate(d, meta)
94+
}
95+
96+
func resourceSumologicDataForwardingUpdate(d *schema.ResourceData, meta interface{}) error {
97+
98+
dataForwarding := resourceToDataForwarding(d)
99+
100+
c := meta.(*Client)
101+
err := c.UpdateDataForwarding(dataForwarding)
102+
103+
if err != nil {
104+
return err
105+
}
106+
107+
return resourceSumologicDataForwardingRead(d, meta)
108+
}
109+
110+
func resourceSumologicDataForwardingRead(d *schema.ResourceData, meta interface{}) error {
111+
c := meta.(*Client)
112+
113+
id := d.Id()
114+
dataForwarding, err := c.getDataForwarding(id)
115+
116+
if err != nil {
117+
return err
118+
}
119+
120+
if dataForwarding == nil {
121+
log.Printf("[WARN] Data Forwarding not found, removing from state: %v - %v", id, err)
122+
d.SetId("")
123+
124+
return nil
125+
}
126+
127+
d.Set("destination_name", dataForwarding.DestinationName)
128+
d.Set("description", dataForwarding.Description)
129+
d.Set("destination_type", dataForwarding.DestinationType)
130+
d.Set("bucket_name", dataForwarding.BucketName)
131+
d.Set("status", dataForwarding.Status)
132+
d.Set("S3_region", dataForwarding.S3Region)
133+
d.Set("S3_server_side_encryption", dataForwarding.S3ServerSideEncryption)
134+
135+
return nil
136+
}
137+
138+
func resourceSumologicDataForwardingDelete(d *schema.ResourceData, meta interface{}) error {
139+
c := meta.(*Client)
140+
id := d.Id()
141+
142+
return c.DeleteDataForwarding(id)
143+
}
144+
145+
func resourceToDataForwarding(d *schema.ResourceData) DataForwarding {
146+
147+
authentication := extractAuthenticationDetails(d.Get("authentication").([]interface{}))
148+
149+
return DataForwarding{
150+
ID: d.Id(),
151+
DestinationName: d.Get("destination_name").(string),
152+
Description: d.Get("description").(string),
153+
DestinationType: d.Get("destination_type").(string),
154+
BucketName: d.Get("bucket_name").(string),
155+
Status: d.Get("status").(string),
156+
AccessMethod: authentication["type"].(string),
157+
AccessKey: authentication["access_key"].(string),
158+
SecretKey: authentication["secret_key"].(string),
159+
RoleArn: authentication["role_arn"].(string),
160+
S3Region: d.Get("s3_region").(string),
161+
S3ServerSideEncryption: d.Get("s3_server_side_encryption").(bool),
162+
}
163+
}
164+
165+
func extractAuthenticationDetails(authenticationList []interface{}) map[string]interface{} {
166+
if len(authenticationList) > 0 {
167+
authMap := authenticationList[0].(map[string]interface{})
168+
return authMap
169+
}
170+
// Default values if authentication block is not provided
171+
return map[string]interface{}{
172+
"type": "",
173+
"role_arn": "",
174+
"access_key": "",
175+
"secret_key": "",
176+
}
177+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package sumologic
2+
3+
import (
4+
"fmt"
5+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
6+
"github.com/hashicorp/terraform-plugin-sdk/terraform"
7+
"testing"
8+
)
9+
10+
//func getRandomizedParams() (string, string, string) {
11+
// name := acctest.RandomWithPrefix("tf-acc-test")
12+
// description := acctest.RandomWithPrefix("tf-acc-test")
13+
// category := acctest.RandomWithPrefix("tf-acc-test")
14+
// return name, description, category }
15+
16+
func TestAccSumologicDataForwarding_create(t *testing.T) {
17+
//var dataForwarding DataForwarding
18+
testAwsAccessKey := ""
19+
testAwsSecretKey := ""
20+
21+
resource.Test(t, resource.TestCase{
22+
PreCheck: func() { testAccPreCheck(t) },
23+
Providers: testAccProviders,
24+
Steps: []resource.TestStep{
25+
{
26+
Config: testAccSumologicDataForwardingConfig(testAwsAccessKey, testAwsSecretKey),
27+
Check: resource.ComposeTestCheckFunc(
28+
testAccCheckDataForwardingExists(),
29+
resource.TestCheckResourceAttr("sumologic_data_forwarding.test", "destination_name", "abc")),
30+
},
31+
},
32+
})
33+
34+
}
35+
36+
func testAccCheckDataForwardingExists() resource.TestCheckFunc {
37+
return func(s *terraform.State) error {
38+
client := testAccProvider.Meta().(*Client)
39+
for _, r := range s.RootModule().Resources {
40+
id := r.Primary.ID
41+
if _, err := client.GetPartition(id); err != nil {
42+
return fmt.Errorf("Received an error retrieving data forwarding %s", err)
43+
}
44+
}
45+
return nil
46+
}
47+
}
48+
49+
func testAccSumologicDataForwardingConfig(testAwsAccessKey string, testAwsSecretKey string) string {
50+
return fmt.Sprintf(`
51+
resource "aws_s3_bucket" "test_bucket" {
52+
bucket = "S3-tests-data-forwarding"
53+
}
54+
55+
resource "aws_iam_role" "sumo_role" {
56+
name = "SumoRole"
57+
assume_role_policy = jsonencode({
58+
"Version": "2012-10-17",
59+
"Statement": [
60+
{
61+
"Effect": "Allow",
62+
"Principal": {
63+
"AWS": "arn:aws:iam::246946804217:root"
64+
},
65+
"Action": "sts:AssumeRole",
66+
"Condition": {
67+
"StringEquals": {
68+
"sts:ExternalId": "long:0000000000000005"
69+
}
70+
}
71+
}
72+
]
73+
})
74+
path = "/"
75+
}
76+
77+
resource "aws_iam_policy" "sumo_policy" {
78+
name = "SumoPolicy"
79+
policy = jsonencode({
80+
"Version": "2012-10-17",
81+
"Statement": [
82+
{
83+
"Effect": "Allow",
84+
"Action": ["s3:PutObject"],
85+
"Resource": ["arn:aws:s3:::${aws_s3_bucket.test_bucket.bucket}/*"]
86+
}
87+
]
88+
})
89+
}
90+
91+
resource "aws_iam_role_policy_attachment" "sumo_policy_attach" {
92+
role = aws_iam_role.sumo_role.name
93+
policy_arn = aws_iam_policy.sumo_policy.arn
94+
}
95+
96+
output "sumo_role_arn" {
97+
description = "ARN of the created role. Copy this ARN back to Sumo to complete the data forwarding destination creation process."
98+
value = aws_iam_role.sumo_role.arn
99+
}
100+
101+
resource "sumologic_data_forwarding" "test" {
102+
destination_name = "abc"
103+
bucket_name = "${aws_s3_bucket.test_bucket.bucket}"
104+
authentication {
105+
type = "RoleBased"
106+
role_arn = "${aws_iam_role_policy_attachment.sumo_policy_attach.policy_arn}"
107+
}
108+
destination_type = "temp"
109+
}
110+
`)
111+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package sumologic
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
)
7+
8+
func (s *Client) getDataForwarding(id string) (*DataForwarding, error) {
9+
10+
data, _, err := s.Get(fmt.Sprintf("v1/logsDataForwarding/destinations/%s", id))
11+
if err != nil {
12+
return nil, err
13+
}
14+
if data == nil {
15+
return nil, nil
16+
}
17+
18+
var dataForwarding DataForwarding
19+
err = json.Unmarshal(data, &dataForwarding)
20+
21+
if err != nil {
22+
return nil, err
23+
}
24+
25+
return &dataForwarding, nil
26+
27+
}
28+
func (s *Client) CreateDataForwarding(dataForwarding DataForwarding) (*DataForwarding, error) {
29+
var createdDataForwarding DataForwarding
30+
31+
responseBody, err := s.Post("v1/logsDataForwarding/destinations", dataForwarding)
32+
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
err = json.Unmarshal(responseBody, &createdDataForwarding)
38+
39+
if err != nil {
40+
return nil, err
41+
}
42+
43+
return &createdDataForwarding, nil
44+
}
45+
46+
func (s *Client) UpdateDataForwarding(dataForwarding DataForwarding) error {
47+
48+
url := fmt.Sprintf("v1/logsDataForwarding/destinations/%s", dataForwarding.ID)
49+
_, err := s.Put(url, dataForwarding)
50+
51+
return err
52+
}
53+
func (s *Client) DeleteDataForwarding(id string) error {
54+
url := fmt.Sprintf("v1/logsDataForwarding/destinations/%s", id)
55+
56+
_, err := s.Delete(url)
57+
58+
return err
59+
}
60+
61+
type DataForwarding struct {
62+
ID string `json:"id,omitempty"`
63+
DestinationName string `json:"destinationName"`
64+
Description string `json:"description"`
65+
DestinationType string `json:"destinationType"`
66+
BucketName string `json:"bucketName"`
67+
Status string `json:"status"`
68+
AccessMethod string `json:"authenticationMode"`
69+
AccessKey string `json:"accessKeyId"`
70+
SecretKey string `json:"secretAccessKey"`
71+
RoleArn string `json:"roleArn"`
72+
S3Region string `json:"region"`
73+
S3ServerSideEncryption bool `json:"encrypted"`
74+
}

0 commit comments

Comments
 (0)