Skip to content

Commit 1f11570

Browse files
nkraemer-sysdigiru
andauthored
Add Benchmark Task resource (#117)
* Add Benchmark Task resource * mark fields as ForceNew, correct id type * Add schema validation, fix enabled type, add multiregion test * missing comma * use distinct resource names in test * fix(test) Co-authored-by: iru <[email protected]>
1 parent c53fba1 commit 1f11570

File tree

9 files changed

+343
-1
lines changed

9 files changed

+343
-1
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package secure
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io/ioutil"
7+
"net/http"
8+
)
9+
10+
func (client *sysdigSecureClient) createBenchmarkTaskURL() string {
11+
return fmt.Sprintf("%s/api/benchmarks/v2/tasks", client.URL)
12+
}
13+
14+
func (client *sysdigSecureClient) benchmarkTaskByIdURL(id string) string {
15+
return fmt.Sprintf("%s/api/benchmarks/v2/tasks/%s", client.URL, id)
16+
}
17+
18+
func (client *sysdigSecureClient) CreateBenchmarkTask(ctx context.Context, task *BenchmarkTask) (*BenchmarkTask, error) {
19+
response, err := client.doSysdigSecureRequest(ctx, http.MethodPost, client.createBenchmarkTaskURL(), task.ToJSON())
20+
if err != nil {
21+
return nil, err
22+
}
23+
defer response.Body.Close()
24+
25+
if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated {
26+
err = errorFromResponse(response)
27+
return nil, err
28+
}
29+
30+
bodyBytes, _ := ioutil.ReadAll(response.Body)
31+
return BenchmarkTaskFromJSON(bodyBytes), nil
32+
}
33+
34+
func (client *sysdigSecureClient) GetBenchmarkTask(ctx context.Context, id string) (*BenchmarkTask, error) {
35+
response, err := client.doSysdigSecureRequest(ctx, http.MethodGet, client.benchmarkTaskByIdURL(id), nil)
36+
if err != nil {
37+
return nil, err
38+
}
39+
defer response.Body.Close()
40+
41+
if response.StatusCode != http.StatusOK {
42+
return nil, errorFromResponse(response)
43+
}
44+
45+
bodyBytes, err := ioutil.ReadAll(response.Body)
46+
if err != nil {
47+
return nil, err
48+
}
49+
50+
return BenchmarkTaskFromJSON(bodyBytes), nil
51+
}
52+
53+
func (client *sysdigSecureClient) DeleteBenchmarkTask(ctx context.Context, id string) error {
54+
response, err := client.doSysdigSecureRequest(ctx, http.MethodDelete, client.benchmarkTaskByIdURL(id), nil)
55+
if err != nil {
56+
return err
57+
}
58+
defer response.Body.Close()
59+
60+
if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK {
61+
return errorFromResponse(response)
62+
}
63+
return nil
64+
}

sysdig/internal/client/secure/client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ type SysdigSecureClient interface {
5858
DeleteCloudAccount(context.Context, string) error
5959
UpdateCloudAccount(context.Context, string, *CloudAccount) (*CloudAccount, error)
6060
GetTrustedCloudIdentity(context.Context, string) (string, error)
61+
62+
CreateBenchmarkTask(context.Context, *BenchmarkTask) (*BenchmarkTask, error)
63+
GetBenchmarkTask(context.Context, string) (*BenchmarkTask, error)
64+
DeleteBenchmarkTask(context.Context, string) error
6165
}
6266

6367
func WithExtraHeaders(client SysdigSecureClient, extraHeaders map[string]string) SysdigSecureClient {

sysdig/internal/client/secure/models.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,3 +382,31 @@ func CloudAccountFromJSON(body []byte) *CloudAccount {
382382

383383
return &result
384384
}
385+
386+
// -------- BenchmarkTask --------
387+
388+
var SupportedBenchmarkTaskSchemas = []string{
389+
"aws_foundations_bench-1.3.0",
390+
"gcp_foundations_bench-1.2.0",
391+
}
392+
393+
type BenchmarkTask struct {
394+
ID int `json:"id,omitempty"`
395+
Name string `json:"name"`
396+
Schema string `json:"schema"`
397+
Scope string `json:"scope"`
398+
Schedule string `json:"schedule"`
399+
Enabled bool `json:"enabled"`
400+
}
401+
402+
func (t *BenchmarkTask) ToJSON() io.Reader {
403+
payload, _ := json.Marshal(*t)
404+
return bytes.NewBuffer(payload)
405+
}
406+
407+
func BenchmarkTaskFromJSON(body []byte) *BenchmarkTask {
408+
var result BenchmarkTask
409+
json.Unmarshal(body, &result)
410+
411+
return &result
412+
}

sysdig/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func Provider() *schema.Provider {
7171
"sysdig_secure_vulnerability_exception": resourceSysdigSecureVulnerabilityException(),
7272
"sysdig_secure_vulnerability_exception_list": resourceSysdigSecureVulnerabilityExceptionList(),
7373
"sysdig_secure_cloud_account": resourceSysdigSecureCloudAccount(),
74+
"sysdig_secure_benchmark_task": resourceSysdigSecureBenchmarkTask(),
7475

7576
"sysdig_monitor_alert_downtime": resourceSysdigMonitorAlertDowntime(),
7677
"sysdig_monitor_alert_metric": resourceSysdigMonitorAlertMetric(),
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package sysdig
2+
3+
import (
4+
"context"
5+
"strconv"
6+
"time"
7+
8+
"github.com/draios/terraform-provider-sysdig/sysdig/internal/client/secure"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
12+
)
13+
14+
func resourceSysdigSecureBenchmarkTask() *schema.Resource {
15+
timeout := 5 * time.Minute
16+
17+
return &schema.Resource{
18+
CreateContext: resourceSysdigSecureBenchmarkTaskCreate,
19+
ReadContext: resourceSysdigSecureBenchmarkTaskRead,
20+
DeleteContext: resourceSysdigSecureBenchmarkTaskDelete,
21+
Importer: &schema.ResourceImporter{
22+
StateContext: schema.ImportStatePassthroughContext,
23+
},
24+
25+
Timeouts: &schema.ResourceTimeout{
26+
Create: schema.DefaultTimeout(timeout),
27+
Read: schema.DefaultTimeout(timeout),
28+
Delete: schema.DefaultTimeout(timeout),
29+
},
30+
Schema: map[string]*schema.Schema{
31+
"id": {
32+
Type: schema.TypeString,
33+
Computed: true,
34+
},
35+
"name": {
36+
Type: schema.TypeString,
37+
Required: true,
38+
ForceNew: true,
39+
},
40+
"schema": {
41+
Type: schema.TypeString,
42+
Required: true,
43+
ForceNew: true,
44+
ValidateFunc: validation.StringInSlice(secure.SupportedBenchmarkTaskSchemas, false),
45+
},
46+
"scope": {
47+
Type: schema.TypeString,
48+
Required: true,
49+
ForceNew: true,
50+
},
51+
"schedule": {
52+
Type: schema.TypeString,
53+
Required: true,
54+
ForceNew: true,
55+
},
56+
"enabled": {
57+
Type: schema.TypeBool,
58+
Optional: true,
59+
Default: true,
60+
ForceNew: true,
61+
},
62+
},
63+
}
64+
}
65+
66+
func resourceSysdigSecureBenchmarkTaskCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
67+
client, err := meta.(SysdigClients).sysdigSecureClient()
68+
if err != nil {
69+
return diag.FromErr(err)
70+
}
71+
72+
benchmarkTask, err := client.CreateBenchmarkTask(ctx, benchmarkTaskFromResourceData(d))
73+
if err != nil {
74+
return diag.FromErr(err)
75+
}
76+
77+
d.SetId(strconv.Itoa(benchmarkTask.ID))
78+
d.Set("name", benchmarkTask.Name)
79+
d.Set("schema", benchmarkTask.Schema)
80+
d.Set("scope", benchmarkTask.Scope)
81+
d.Set("schedule", benchmarkTask.Schedule)
82+
d.Set("enabled", benchmarkTask.Enabled)
83+
84+
return nil
85+
}
86+
87+
func resourceSysdigSecureBenchmarkTaskRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
88+
client, err := meta.(SysdigClients).sysdigSecureClient()
89+
if err != nil {
90+
d.SetId("")
91+
return diag.FromErr(err)
92+
}
93+
94+
benchmarkTask, err := client.GetBenchmarkTask(ctx, d.Id())
95+
if err != nil {
96+
d.SetId("")
97+
return diag.FromErr(err)
98+
}
99+
100+
d.SetId(strconv.Itoa(benchmarkTask.ID))
101+
d.Set("name", benchmarkTask.Name)
102+
d.Set("schema", benchmarkTask.Schema)
103+
d.Set("scope", benchmarkTask.Scope)
104+
d.Set("schedule", benchmarkTask.Schedule)
105+
d.Set("enabled", benchmarkTask.Enabled)
106+
107+
return nil
108+
}
109+
110+
func resourceSysdigSecureBenchmarkTaskDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
111+
client, err := meta.(SysdigClients).sysdigSecureClient()
112+
if err != nil {
113+
return diag.FromErr(err)
114+
}
115+
116+
err = client.DeleteBenchmarkTask(ctx, d.Id())
117+
if err != nil {
118+
return diag.FromErr(err)
119+
}
120+
return nil
121+
}
122+
123+
func benchmarkTaskFromResourceData(d *schema.ResourceData) *secure.BenchmarkTask {
124+
return &secure.BenchmarkTask{
125+
Name: d.Get("name").(string),
126+
Schema: d.Get("schema").(string),
127+
Scope: d.Get("scope").(string),
128+
Schedule: d.Get("schedule").(string),
129+
Enabled: d.Get("enabled").(bool),
130+
}
131+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package sysdig_test
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
12+
"github.com/draios/terraform-provider-sysdig/sysdig"
13+
)
14+
15+
func TestAccSecureBenchmarkTask(t *testing.T) {
16+
rText := func() string { return acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) }
17+
resource.ParallelTest(t, resource.TestCase{
18+
PreCheck: func() {
19+
if v := os.Getenv("SYSDIG_SECURE_API_TOKEN"); v == "" {
20+
t.Fatal("SYSDIG_SECURE_API_TOKEN must be set for acceptance tests")
21+
}
22+
},
23+
ProviderFactories: map[string]func() (*schema.Provider, error){
24+
"sysdig": func() (*schema.Provider, error) {
25+
return sysdig.Provider(), nil
26+
},
27+
},
28+
Steps: []resource.TestStep{
29+
{
30+
Config: secureBenchmarkTaskWithName(rText()),
31+
},
32+
{
33+
Config: multiRegionSecureBenchmarkTaskWithName(rText()),
34+
},
35+
{
36+
ResourceName: "sysdig_secure_benchmark_task.sample",
37+
ImportState: true,
38+
ImportStateVerify: true,
39+
},
40+
},
41+
})
42+
}
43+
44+
func secureBenchmarkTaskWithName(name string) string {
45+
return fmt.Sprintf(`
46+
resource "sysdig_secure_benchmark_task" "sample" {
47+
name = "%s"
48+
schedule = "0 6 * * *"
49+
schema = "aws_foundations_bench-1.3.0"
50+
scope = "aws.accountId = \"123456789012\" and aws.region = \"us-west-2\""
51+
enabled = true
52+
}
53+
`, name)
54+
}
55+
56+
func multiRegionSecureBenchmarkTaskWithName(name string) string {
57+
return fmt.Sprintf(`
58+
resource "sysdig_secure_benchmark_task" "sample" {
59+
name = "%s"
60+
schedule = "0 6 * * *"
61+
schema = "aws_foundations_bench-1.3.0"
62+
scope = "aws.accountId = \"123456789012\" and aws.region in (\"us-east-1\", \"us-west-2\", \"eu-central-1\")"
63+
enabled = true
64+
}
65+
`, name)
66+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
layout: "sysdig"
3+
page_title: "Sysdig: sysdig_secure_benchmark_task"
4+
sidebar_current: "docs-sysdig_secure_benchmark_task"
5+
description: |-
6+
Creates a Sysdig Secure Benchmark Task.
7+
---
8+
9+
# sysdig\_secure\_benchmark_task
10+
11+
Creates a Sysdig Secure Benchmark Task.
12+
13+
`~> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository.`
14+
15+
## Example usage
16+
17+
```hcl
18+
resource "sysdig_secure_benchmark_task" "sample" {
19+
name = "My Benchmark Task"
20+
schedule = "0 6 * * *"
21+
schema = "aws_foundations_bench-1.3.0"
22+
scope = "aws.accountId = \"123456789012\" and aws.region = \"us-west-2\""
23+
enabled = "true"
24+
}
25+
```
26+
27+
## Argument Reference
28+
29+
* `name` - (Required) The unique identifier of the cloud account. e.g. for AWS: `123456789012`,
30+
31+
* `schedule` - (Required) The schedule (as a cron expression: [Minute Hour Day DayOfWeek DayOfMonth]) on which this task should be run. The schedule may not be more frequent than once per day.
32+
33+
* `schema` - (Required) The identifier of the benchmark schema of which to run. Possible values are: `aws_foundations_bench-1.3.0`, `gcp_foundations_bench-1.2.0`.
34+
35+
* `scope` - (Required) The Sysdig scope expression on which to run this benchmark: e.g. `aws.accountId = \"123456789012\" and aws.region = \"us-west-2\"`. The labels available are `aws.accountId`, `aws.region`, `gcp.projectId` and `gcp.region`. Only the `=` and `and` operators are supported.
36+
37+
* `enabled` - (Optional) Whether or not this task should be enabled. Default: `true`.
38+
39+
## Import
40+
41+
Secure Benchmark Tasks can be imported using the `id`, e.g.
42+
43+
```
44+
$ terraform import sysdig_secure_benchmark_task.sample 1
45+
```

website/docs/r/sysdig_secure_cloud_account.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ resource "sysdig_secure_cloud_account" "sample" {
3535

3636
## Import
3737

38-
Secure Teams can be imported using the `account_id`, e.g.
38+
Secure Cloud Accounts can be imported using the `account_id`, e.g.
3939

4040
```
4141
$ terraform import sysdig_secure_cloud_account.sample 123456789012

website/sysdig.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
<li<%= sidebar_current("docs-sysdig-secure-resources") %>>
2626
<a href="#">Resources</a>
2727
<ul class="nav nav-auto-expand">
28+
<li<%= sidebar_current("docs-sysdig-secure-benchmark-task") %>>
29+
<a href="/docs/providers/sysdig/r/sysdig_secure_benchmark_task.html">sysdig_secure_benchmark_task</a>
30+
</li>
2831
<li<%= sidebar_current("docs-sysdig-secure-cloud-account") %>>
2932
<a href="/docs/providers/sysdig/r/sysdig_secure_cloud_account.html">sysdig_secure_cloud_account</a>
3033
</li>

0 commit comments

Comments
 (0)