Skip to content

Commit 61909e0

Browse files
authored
feat(monitor-cloud-account): Add new monitor cloud account resource (#244)
* [SMPROD-10685] starting new resource implementation for monitor_cloud_account_provider [SMPROD-10685] add tests and documentation * update codeowners * Update monitor_cloud_account_provider.md * Update monitor_cloud_account_provider.md * [SMPROD-10685] update reource name and schema * [SMPROD-10685] update client and model naming * Update monitor_cloud_account.md
1 parent c7a2380 commit 61909e0

File tree

8 files changed

+380
-0
lines changed

8 files changed

+380
-0
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# monitor
88
*monitor*alert* @arturodilecce @dbonf
99
*monitor*dashboard* @brokenpip3
10+
*monitor*providers* @jwsarna1
1011

1112
# policies/rules
1213
*secure*policy* @jacklongsd @kmvachhani @ben-m-lucas

sysdig/internal/client/monitor/client.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ type SysdigMonitorClient interface {
5656
CreateDashboard(context.Context, *model.Dashboard) (*model.Dashboard, error)
5757
UpdateDashboard(context.Context, *model.Dashboard) (*model.Dashboard, error)
5858
DeleteDashboard(context.Context, int) error
59+
60+
GetCloudAccountById(context.Context, int) (*CloudAccount, error)
61+
CreateCloudAccount(context.Context, *CloudAccount) (*CloudAccount, error)
62+
UpdateCloudAccount(context.Context, int, *CloudAccount) (*CloudAccount, error)
63+
DeleteCloudAccountById(context.Context, int) error
5964
}
6065

6166
func WithExtraHeaders(client SysdigMonitorClient, extraHeaders map[string]string) SysdigMonitorClient {
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package monitor
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
)
9+
10+
func (client *sysdigMonitorClient) GetCloudAccountById(ctx context.Context, id int) (*CloudAccount, error) {
11+
response, err := client.doSysdigMonitorRequest(ctx, http.MethodGet, client.getProviderUrl(id), nil)
12+
if err != nil {
13+
return nil, err
14+
}
15+
defer response.Body.Close()
16+
17+
if response.StatusCode != http.StatusOK {
18+
return nil, errorFromResponse(response)
19+
}
20+
21+
body, err := io.ReadAll(response.Body)
22+
if err != nil {
23+
return nil, err
24+
}
25+
return CloudAccountFromJSON(body), nil
26+
}
27+
28+
func (client *sysdigMonitorClient) CreateCloudAccount(ctx context.Context, provider *CloudAccount) (*CloudAccount, error) {
29+
response, err := client.doSysdigMonitorRequest(ctx, http.MethodPost, client.getProvidersUrl(), CloudAccountToJSON(provider))
30+
if err != nil {
31+
return nil, err
32+
}
33+
defer response.Body.Close()
34+
35+
if response.StatusCode != http.StatusCreated {
36+
return nil, errorFromResponse(response)
37+
}
38+
39+
body, err := io.ReadAll(response.Body)
40+
if err != nil {
41+
return nil, err
42+
}
43+
return CloudAccountFromJSON(body), nil
44+
}
45+
46+
func (client *sysdigMonitorClient) UpdateCloudAccount(ctx context.Context, id int, provider *CloudAccount) (*CloudAccount, error) {
47+
response, err := client.doSysdigMonitorRequest(ctx, http.MethodPut, client.getProviderUrl(id), CloudAccountToJSON(provider))
48+
if err != nil {
49+
return nil, err
50+
}
51+
defer response.Body.Close()
52+
53+
if response.StatusCode != http.StatusOK {
54+
return nil, errorFromResponse(response)
55+
}
56+
57+
body, err := io.ReadAll(response.Body)
58+
if err != nil {
59+
return nil, err
60+
}
61+
return CloudAccountFromJSON(body), nil
62+
}
63+
64+
func (client *sysdigMonitorClient) DeleteCloudAccountById(ctx context.Context, id int) error {
65+
response, err := client.doSysdigMonitorRequest(ctx, http.MethodDelete, client.getProviderUrl(id), nil)
66+
if err != nil {
67+
return err
68+
}
69+
defer response.Body.Close()
70+
71+
if response.StatusCode != http.StatusOK {
72+
return errorFromResponse(response)
73+
}
74+
75+
return nil
76+
}
77+
78+
func (client *sysdigMonitorClient) getProviderUrl(id int) string {
79+
return fmt.Sprintf("%v/%v", client.getProvidersUrl(), id)
80+
}
81+
82+
func (client *sysdigMonitorClient) getProvidersUrl() string {
83+
return fmt.Sprintf("%v/api/v2/providers", client.URL)
84+
}

sysdig/internal/client/monitor/models.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,34 @@ type CustomNotification struct {
1414
AppendText string `json:"appendText,omitempty"`
1515
}
1616

17+
type CloudAccountCredentials struct {
18+
AccountId string `json:"accountId"`
19+
}
20+
21+
type CloudAccount struct {
22+
Id int `json:"id"`
23+
Platform string `json:"platform"`
24+
IntegrationType string `json:"integrationType"`
25+
Credentials CloudAccountCredentials `json:"credentials"`
26+
AdditionalOptions string `json:"additionalOptions"`
27+
}
28+
29+
type cloudAccountWrapper struct {
30+
CloudAccount CloudAccount `json:"provider"`
31+
}
32+
33+
func CloudAccountFromJSON(body []byte) *CloudAccount {
34+
var result cloudAccountWrapper
35+
_ = json.Unmarshal(body, &result)
36+
37+
return &result.CloudAccount
38+
}
39+
40+
func CloudAccountToJSON(providerInfo *CloudAccount) io.Reader {
41+
payload, _ := json.Marshal(*providerInfo)
42+
return bytes.NewBuffer(payload)
43+
}
44+
1745
type SysdigCapture struct {
1846
Name string `json:"name"`
1947
Filters string `json:"filters,omitempty"`

sysdig/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ func Provider() *schema.Provider {
9292
"sysdig_monitor_notification_channel_victorops": resourceSysdigMonitorNotificationChannelVictorOps(),
9393
"sysdig_monitor_notification_channel_webhook": resourceSysdigMonitorNotificationChannelWebhook(),
9494
"sysdig_monitor_team": resourceSysdigMonitorTeam(),
95+
"sysdig_monitor_cloud_account": resourceSysdigMonitorCloudAccount(),
9596
},
9697
DataSourcesMap: map[string]*schema.Resource{
9798
"sysdig_secure_trusted_cloud_identity": dataSourceSysdigSecureTrustedCloudIdentity(),
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package sysdig
2+
3+
import (
4+
"context"
5+
"github.com/draios/terraform-provider-sysdig/sysdig/internal/client/monitor"
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
"strconv"
9+
"time"
10+
)
11+
12+
func resourceSysdigMonitorCloudAccount() *schema.Resource {
13+
timeout := 5 * time.Minute
14+
15+
return &schema.Resource{
16+
CreateContext: resourceSysdigMonitorCloudAccountCreate,
17+
DeleteContext: resourceSysdigMonitorCloudAccountDelete,
18+
ReadContext: resourceSysdigMonitorCloudAccountRead,
19+
UpdateContext: resourceSysdigMonitorCloudAccountUpdate,
20+
Importer: &schema.ResourceImporter{
21+
StateContext: schema.ImportStatePassthroughContext,
22+
},
23+
Timeouts: &schema.ResourceTimeout{
24+
Create: schema.DefaultTimeout(timeout),
25+
Update: schema.DefaultTimeout(timeout),
26+
Read: schema.DefaultTimeout(timeout),
27+
Delete: schema.DefaultTimeout(timeout),
28+
},
29+
Schema: map[string]*schema.Schema{
30+
"cloud_provider": {
31+
Type: schema.TypeString,
32+
Required: true,
33+
},
34+
"integration_type": {
35+
Type: schema.TypeString,
36+
Required: true,
37+
},
38+
"account_id": {
39+
Type: schema.TypeString,
40+
Required: true,
41+
},
42+
"additional_options": {
43+
Type: schema.TypeString,
44+
Optional: true,
45+
},
46+
},
47+
}
48+
}
49+
50+
func resourceSysdigMonitorCloudAccountCreate(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
51+
client, err := i.(SysdigClients).sysdigMonitorClient()
52+
if err != nil {
53+
return diag.FromErr(err)
54+
}
55+
56+
cloudAccount := monitorCloudAccountFromResourceData(data)
57+
58+
cloudAccountCreated, err := client.CreateCloudAccount(ctx, &cloudAccount)
59+
if err != nil {
60+
return diag.FromErr(err)
61+
}
62+
63+
data.SetId(strconv.Itoa(cloudAccountCreated.Id))
64+
65+
return nil
66+
}
67+
68+
func resourceSysdigMonitorCloudAccountDelete(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
69+
client, err := i.(SysdigClients).sysdigMonitorClient()
70+
if err != nil {
71+
return diag.FromErr(err)
72+
}
73+
74+
id, err := strconv.Atoi(data.Id())
75+
if err != nil {
76+
return diag.FromErr(err)
77+
}
78+
79+
err = client.DeleteCloudAccountById(ctx, id)
80+
if err != nil {
81+
return diag.FromErr(err)
82+
}
83+
84+
return nil
85+
}
86+
87+
func resourceSysdigMonitorCloudAccountRead(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
88+
client, err := i.(SysdigClients).sysdigMonitorClient()
89+
if err != nil {
90+
return diag.FromErr(err)
91+
}
92+
93+
id, err := strconv.Atoi(data.Id())
94+
if err != nil {
95+
return diag.FromErr(err)
96+
}
97+
98+
cloudAccount, err := client.GetCloudAccountById(ctx, id)
99+
if err != nil {
100+
return diag.FromErr(err)
101+
}
102+
103+
err = monitorCloudAccountToResourceData(data, cloudAccount)
104+
if err != nil {
105+
return diag.FromErr(err)
106+
}
107+
108+
return nil
109+
}
110+
111+
func resourceSysdigMonitorCloudAccountUpdate(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
112+
client, err := i.(SysdigClients).sysdigMonitorClient()
113+
if err != nil {
114+
return diag.FromErr(err)
115+
}
116+
117+
cloudAccount := monitorCloudAccountFromResourceData(data)
118+
119+
id, err := strconv.Atoi(data.Id())
120+
if err != nil {
121+
return diag.FromErr(err)
122+
}
123+
124+
_, err = client.UpdateCloudAccount(ctx, id, &cloudAccount)
125+
if err != nil {
126+
return diag.FromErr(err)
127+
}
128+
129+
return nil
130+
}
131+
132+
func monitorCloudAccountFromResourceData(data *schema.ResourceData) monitor.CloudAccount {
133+
return monitor.CloudAccount{
134+
Platform: data.Get("cloud_provider").(string),
135+
IntegrationType: data.Get("integration_type").(string),
136+
AdditionalOptions: data.Get("additional_options").(string),
137+
Credentials: monitor.CloudAccountCredentials{
138+
AccountId: data.Get("account_id").(string),
139+
},
140+
}
141+
}
142+
143+
func monitorCloudAccountToResourceData(data *schema.ResourceData, cloudAccount *monitor.CloudAccount) error {
144+
err := data.Set("cloud_provider", cloudAccount.Platform)
145+
if err != nil {
146+
return err
147+
}
148+
149+
err = data.Set("integration_type", cloudAccount.IntegrationType)
150+
if err != nil {
151+
return err
152+
}
153+
154+
err = data.Set("additional_options", cloudAccount.AdditionalOptions)
155+
if err != nil {
156+
return err
157+
}
158+
159+
err = data.Set("account_id", cloudAccount.Credentials.AccountId)
160+
if err != nil {
161+
return err
162+
}
163+
164+
return nil
165+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package sysdig_test
2+
3+
import (
4+
"fmt"
5+
"github.com/draios/terraform-provider-sysdig/sysdig"
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"os"
10+
"testing"
11+
)
12+
13+
func TestCustomerProviderKeys(t *testing.T) {
14+
rText := func() string { return acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) }
15+
accountId := rText()
16+
resource.ParallelTest(t, resource.TestCase{
17+
PreCheck: func() {
18+
if v := os.Getenv("SYSDIG_MONITOR_API_TOKEN"); v == "" {
19+
t.Fatal("SYSDIG_MONITOR_API_TOKEN must be set for acceptance tests")
20+
}
21+
},
22+
ProviderFactories: map[string]func() (*schema.Provider, error){
23+
"sysdig": func() (*schema.Provider, error) {
24+
return sysdig.Provider(), nil
25+
},
26+
},
27+
Steps: []resource.TestStep{
28+
{
29+
Config: monitorCustomerProviderKey(accountId),
30+
},
31+
{
32+
Config: monitorCustomerProviderKeyAdditionalOptions(accountId, rText()),
33+
},
34+
{
35+
ResourceName: "sysdig_monitor_cloud_account.provider",
36+
ImportState: true,
37+
ImportStateVerify: true,
38+
},
39+
},
40+
})
41+
}
42+
43+
func monitorCustomerProviderKey(rText string) string {
44+
return fmt.Sprintf(`
45+
resource "sysdig_monitor_cloud_account" "provider" {
46+
cloud_provider = "GCP"
47+
integration_type = "API"
48+
account_id = "sample-%s"
49+
}
50+
`, rText)
51+
}
52+
53+
func monitorCustomerProviderKeyAdditionalOptions(accountId string, rText string) string {
54+
return fmt.Sprintf(`
55+
resource "sysdig_monitor_cloud_account" "provider" {
56+
cloud_provider = "Azure"
57+
integration_type = "Metrics Streams"
58+
account_id = "sample-%s"
59+
additional_options = "%s"
60+
}
61+
`, accountId, rText)
62+
}

0 commit comments

Comments
 (0)