Skip to content

Commit b54a3af

Browse files
committed
feat(zones): support v2 expression syntax for sysdig_secure_zone
1 parent 97535da commit b54a3af

18 files changed

Lines changed: 2790 additions & 228 deletions

go.mod

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@ require (
77
github.com/aws/aws-sdk-go v1.55.7
88
github.com/hashicorp/go-cty v1.5.0
99
github.com/hashicorp/go-retryablehttp v0.7.8
10-
github.com/hashicorp/terraform-plugin-log v0.9.0
11-
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0
10+
github.com/hashicorp/terraform-plugin-log v0.10.0
11+
github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1
12+
github.com/hashicorp/terraform-plugin-testing v1.14.0
1213
github.com/jmespath/go-jmespath v0.4.0
1314
github.com/rs/zerolog v1.34.0
1415
github.com/spf13/cast v1.9.2
1516
github.com/stretchr/testify v1.10.0
1617
github.com/sysdiglabs/agent-kilt v1.0.0
17-
google.golang.org/protobuf v1.36.6
18+
google.golang.org/protobuf v1.36.9
1819
)
1920

2021
require (
@@ -23,7 +24,7 @@ require (
2324
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
2425
github.com/cloudflare/circl v1.6.1 // indirect
2526
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
26-
github.com/davecgh/go-spew v1.1.1 // indirect
27+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
2728
github.com/docker/cli v28.3.2+incompatible // indirect
2829
github.com/docker/distribution v2.8.3+incompatible // indirect
2930
github.com/docker/docker-credential-helpers v0.9.3 // indirect
@@ -37,16 +38,16 @@ require (
3738
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
3839
github.com/hashicorp/go-hclog v1.6.3 // indirect
3940
github.com/hashicorp/go-multierror v1.1.1 // indirect
40-
github.com/hashicorp/go-plugin v1.6.3 // indirect
41+
github.com/hashicorp/go-plugin v1.7.0 // indirect
4142
github.com/hashicorp/go-uuid v1.0.3 // indirect
4243
github.com/hashicorp/go-version v1.7.0 // indirect
4344
github.com/hashicorp/hc-install v0.9.2 // indirect
4445
github.com/hashicorp/hcl/v2 v2.24.0 // indirect
4546
github.com/hashicorp/logutils v1.0.0 // indirect
46-
github.com/hashicorp/terraform-exec v0.23.0 // indirect
47-
github.com/hashicorp/terraform-json v0.25.0 // indirect
48-
github.com/hashicorp/terraform-plugin-go v0.28.0 // indirect
49-
github.com/hashicorp/terraform-registry-address v0.3.0 // indirect
47+
github.com/hashicorp/terraform-exec v0.24.0 // indirect
48+
github.com/hashicorp/terraform-json v0.27.2 // indirect
49+
github.com/hashicorp/terraform-plugin-go v0.29.0 // indirect
50+
github.com/hashicorp/terraform-registry-address v0.4.0 // indirect
5051
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
5152
github.com/hashicorp/yamux v0.1.2 // indirect
5253
github.com/klauspost/compress v1.18.0 // indirect
@@ -62,22 +63,22 @@ require (
6263
github.com/opencontainers/go-digest v1.0.0 // indirect
6364
github.com/opencontainers/image-spec v1.1.1 // indirect
6465
github.com/pkg/errors v0.9.1 // indirect
65-
github.com/pmezard/go-difflib v1.0.0 // indirect
66+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
6667
github.com/sirupsen/logrus v1.9.3 // indirect
6768
github.com/vbatts/tar-split v0.12.1 // indirect
6869
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
6970
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
7071
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
71-
github.com/zclconf/go-cty v1.16.3 // indirect
72-
golang.org/x/crypto v0.39.0 // indirect
73-
golang.org/x/mod v0.25.0 // indirect
74-
golang.org/x/net v0.41.0 // indirect
75-
golang.org/x/sync v0.16.0 // indirect
76-
golang.org/x/sys v0.34.0 // indirect
77-
golang.org/x/text v0.26.0 // indirect
78-
golang.org/x/tools v0.34.0 // indirect
72+
github.com/zclconf/go-cty v1.17.0 // indirect
73+
golang.org/x/crypto v0.45.0 // indirect
74+
golang.org/x/mod v0.29.0 // indirect
75+
golang.org/x/net v0.47.0 // indirect
76+
golang.org/x/sync v0.18.0 // indirect
77+
golang.org/x/sys v0.38.0 // indirect
78+
golang.org/x/text v0.31.0 // indirect
79+
golang.org/x/tools v0.38.0 // indirect
7980
google.golang.org/appengine v1.6.8 // indirect
8081
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
81-
google.golang.org/grpc v1.73.0 // indirect
82+
google.golang.org/grpc v1.75.1 // indirect
8283
gopkg.in/yaml.v3 v3.0.1 // indirect
8384
)

go.sum

Lines changed: 62 additions & 55 deletions
Large diffs are not rendered by default.

sysdig/common.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ const (
5252
SchemaScopeKey = "scope"
5353
SchemaScopesKey = "scopes"
5454
SchemaTargetTypeKey = "target_type"
55+
SchemaResourceTypeKey = "resource_type"
56+
SchemaExpressionKey = "expression"
57+
SchemaFieldKey = "field"
58+
SchemaOperatorKey = "operator"
59+
SchemaValueKey = "value"
60+
SchemaValuesKey = "values"
5561
SchemaRoleKey = "role"
5662
SchemaSystemRoleKey = "system_role"
5763
SchemaRulesKey = "rules"

sysdig/data_source_sysdig_secure_zone.go

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,34 @@ func dataSourceSysdigSecureZone() *schema.Resource {
5050
Type: schema.TypeString,
5151
Computed: true,
5252
},
53+
// Not marked Deprecated: rules with v2-compatible syntax are fully supported.
54+
// Only v1 syntax (labels, labelValues, agentTags) is deprecated, but since
55+
// this is a Computed field, SDK v2 has no mechanism for conditional deprecation.
56+
// The resource-side ValidateDiagFunc handles the v1-only warning.
5357
SchemaRulesKey: {
5458
Type: schema.TypeString,
5559
Computed: true,
5660
},
61+
SchemaExpressionKey: {
62+
Type: schema.TypeList,
63+
Computed: true,
64+
Elem: &schema.Resource{
65+
Schema: map[string]*schema.Schema{
66+
SchemaFieldKey: {Type: schema.TypeString, Computed: true},
67+
SchemaOperatorKey: {Type: schema.TypeString, Computed: true},
68+
SchemaValueKey: {Type: schema.TypeString, Computed: true},
69+
SchemaValuesKey: {
70+
Type: schema.TypeList,
71+
Computed: true,
72+
Elem: &schema.Schema{Type: schema.TypeString},
73+
},
74+
},
75+
},
76+
},
5777
},
5878
},
5979
},
80+
6081
"id": {
6182
Type: schema.TypeString,
6283
Optional: true,
@@ -78,8 +99,12 @@ func dataSourceSysdigSecureZoneRead(ctx context.Context, d *schema.ResourceData,
7899
if err != nil {
79100
return diag.FromErr(err)
80101
}
81-
102+
clientv2, err := getZoneV2Client(m.(SysdigClients))
103+
if err != nil {
104+
return diag.FromErr(err)
105+
}
82106
var zone *v2.Zone
107+
var zoneV2 *v2.ZoneV2
83108
zoneIDRaw, hasZoneID := d.GetOk("id")
84109
if hasZoneID {
85110
zoneID, err := strconv.Atoi(zoneIDRaw.(string))
@@ -90,6 +115,10 @@ func dataSourceSysdigSecureZoneRead(ctx context.Context, d *schema.ResourceData,
90115
if err != nil {
91116
return diag.FromErr(fmt.Errorf("error fetching zone by ID: %s", err))
92117
}
118+
zoneV2, err = clientv2.GetZoneV2(ctx, zoneID)
119+
if err != nil {
120+
return diag.FromErr(fmt.Errorf("error fetching zone v2 by ID: %s", err))
121+
}
93122
} else if nameRaw, hasName := d.GetOk("name"); hasName {
94123
name := nameRaw.(string)
95124
zones, err := client.GetZones(ctx, name)
@@ -105,6 +134,10 @@ func dataSourceSysdigSecureZoneRead(ctx context.Context, d *schema.ResourceData,
105134
if zone == nil {
106135
return diag.FromErr(fmt.Errorf("zone with name '%s' not found", name))
107136
}
137+
zoneV2, err = clientv2.GetZoneV2(ctx, zone.ID)
138+
if err != nil {
139+
return diag.FromErr(fmt.Errorf("error fetching zones: %s", err))
140+
}
108141
} else {
109142
return diag.FromErr(fmt.Errorf("either id or name must be specified"))
110143
}
@@ -117,9 +150,44 @@ func dataSourceSysdigSecureZoneRead(ctx context.Context, d *schema.ResourceData,
117150
_ = d.Set(SchemaLastModifiedBy, zone.LastModifiedBy)
118151
_ = d.Set(SchemaLastUpdated, time.UnixMilli(zone.LastUpdated).Format(time.RFC3339))
119152

120-
if err := d.Set(SchemaScopeKey, fromZoneScopesResponse(zone.Scopes)); err != nil {
153+
if err := d.Set(SchemaScopeKey, getZoneScopes(zone.Scopes, zoneV2)); err != nil {
121154
return diag.FromErr(fmt.Errorf("error setting scope: %s", err))
122155
}
123156

124157
return nil
125158
}
159+
160+
func getZoneScopes(legacyScopes []v2.ZoneScope, zoneV2 *v2.ZoneV2) []any {
161+
// Build expression lookup by filter ID from the v2 response.
162+
exprByID := make(map[int][]any)
163+
if zoneV2 != nil {
164+
for _, s := range zoneV2.Scopes {
165+
for _, f := range s.Filters {
166+
if f.ID != 0 && len(f.Expressions) > 0 {
167+
var exprs []any
168+
for _, e := range f.Expressions {
169+
exprs = append(exprs, flattenExpressionV21(e))
170+
}
171+
exprByID[f.ID] = exprs
172+
}
173+
}
174+
}
175+
}
176+
177+
// Merge: v1 scope ← v2 expressions by ID.
178+
// If a scope's ID has no v2 match (rollout not complete, or filter has no
179+
// expressions), the scope gets rules only — graceful degradation.
180+
out := make([]any, 0, len(legacyScopes))
181+
for _, scope := range legacyScopes {
182+
m := map[string]any{
183+
SchemaIDKey: scope.ID,
184+
SchemaTargetTypeKey: scope.TargetType,
185+
SchemaRulesKey: scope.Rules,
186+
}
187+
if exprs, ok := exprByID[scope.ID]; ok {
188+
m[SchemaExpressionKey] = exprs
189+
}
190+
out = append(out, m)
191+
}
192+
return out
193+
}

sysdig/data_source_sysdig_secure_zone_test.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package sysdig_test
44

55
import (
6+
"fmt"
67
"testing"
78

89
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
@@ -43,6 +44,144 @@ func TestAccDataSourceSysdigSecureZone(t *testing.T) {
4344
})
4445
}
4546

47+
func TestAccDataSourceSysdigSecureZone_ByName(t *testing.T) {
48+
zoneName := "Zone_DS_" + randomText(5)
49+
50+
resource.ParallelTest(t, resource.TestCase{
51+
PreCheck: preCheckAnyEnv(t, SysdigSecureApiTokenEnv, SysdigIBMSecureAPIKeyEnv),
52+
ProviderFactories: map[string]func() (*schema.Provider, error){
53+
"sysdig": func() (*schema.Provider, error) {
54+
return sysdig.Provider(), nil
55+
},
56+
},
57+
Steps: []resource.TestStep{
58+
{
59+
Config: testAccDataSourceSecureZoneByName(zoneName),
60+
Check: resource.ComposeTestCheckFunc(
61+
resource.TestCheckResourceAttr(
62+
"data.sysdig_secure_zone.test",
63+
"name",
64+
zoneName,
65+
),
66+
resource.TestCheckResourceAttr(
67+
"data.sysdig_secure_zone.test",
68+
"scope.0.target_type",
69+
"aws",
70+
),
71+
72+
// v2 expressions
73+
resource.TestCheckResourceAttr(
74+
"data.sysdig_secure_zone.test",
75+
"scope.0.expression.#",
76+
"1",
77+
),
78+
resource.TestCheckResourceAttr(
79+
"data.sysdig_secure_zone.test",
80+
"scope.0.expression.0.field",
81+
"organization",
82+
),
83+
),
84+
},
85+
},
86+
})
87+
}
88+
89+
func TestAccDataSourceSysdigSecureZone_ByID(t *testing.T) {
90+
zoneName := "Zone_DS_ID_" + randomText(5)
91+
92+
resource.ParallelTest(t, resource.TestCase{
93+
PreCheck: preCheckAnyEnv(t, SysdigSecureApiTokenEnv, SysdigIBMSecureAPIKeyEnv),
94+
ProviderFactories: map[string]func() (*schema.Provider, error){
95+
"sysdig": func() (*schema.Provider, error) {
96+
return sysdig.Provider(), nil
97+
},
98+
},
99+
Steps: []resource.TestStep{
100+
{
101+
Config: testAccDataSourceSecureZoneByID(zoneName),
102+
Check: resource.ComposeTestCheckFunc(
103+
resource.TestCheckResourceAttrSet(
104+
"data.sysdig_secure_zone.test",
105+
"id",
106+
),
107+
resource.TestCheckResourceAttr(
108+
"data.sysdig_secure_zone.test",
109+
"scope.0.expression.#",
110+
"1",
111+
),
112+
),
113+
},
114+
},
115+
})
116+
}
117+
118+
func testAccSecureZoneWithExpression(name string) string {
119+
return fmt.Sprintf(`
120+
resource "sysdig_secure_zone" "test" {
121+
name = "%s"
122+
description = "ds acceptance test"
123+
124+
scope {
125+
target_type = "aws"
126+
127+
expression {
128+
field = "organization"
129+
operator = "in"
130+
values = ["o1", "o2"]
131+
}
132+
}
133+
}
134+
`, name)
135+
}
136+
137+
func testAccDataSourceSecureZoneByName(name string) string {
138+
return fmt.Sprintf(`
139+
resource "sysdig_secure_zone" "test" {
140+
name = "%s"
141+
description = "ds acceptance test"
142+
143+
scope {
144+
target_type = "aws"
145+
146+
expression {
147+
field = "organization"
148+
operator = "in"
149+
values = ["o1", "o2"]
150+
}
151+
}
152+
}
153+
154+
data "sysdig_secure_zone" "test" {
155+
depends_on = [sysdig_secure_zone.test]
156+
name = "%s"
157+
}
158+
`, name, name)
159+
}
160+
161+
func testAccDataSourceSecureZoneByID(name string) string {
162+
return fmt.Sprintf(`
163+
resource "sysdig_secure_zone" "test" {
164+
name = "%s"
165+
description = "ds acceptance test"
166+
167+
scope {
168+
target_type = "aws"
169+
170+
expression {
171+
field = "organization"
172+
operator = "in"
173+
values = ["o1", "o2"]
174+
}
175+
}
176+
}
177+
178+
data "sysdig_secure_zone" "test" {
179+
depends_on = [sysdig_secure_zone.test]
180+
id = sysdig_secure_zone.test.id
181+
}
182+
`, name)
183+
}
184+
46185
func testAccDataSourceSysdigSecureZoneConfig() string {
47186
return `
48187
resource "sysdig_secure_zone" "sample" {

0 commit comments

Comments
 (0)