Skip to content

Commit 01ea011

Browse files
authored
Merge branch 'main' into dependabot/go_modules/github.com/hashicorp/go-retryablehttp-0.7.8
2 parents e3db367 + 330991b commit 01ea011

File tree

8 files changed

+515
-17
lines changed

8 files changed

+515
-17
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## 1.5.0 (August 11, 2025)
2+
Bump the allowed number of rules in a Tracking Plan to 2000 items depending on workspace limits.
3+
4+
## 1.4.1 (July 21, 2025)
5+
Bump the Go language version to `v1.24.2` to fix the following security vulnerabilities:
6+
7+
- [CVE-2025-22871](https://nvd.nist.gov/vuln/detail/CVE-2025-22871)
8+
- [CVE-2024-45337](https://github.com/advisories/GHSA-v778-237x-gjrc)
9+
110
## 1.4.0 (April 7, 2025)
211
Adds graceful handling of 404 errors when getting resources. The resource is now removed from the state file and regenerated on the next plan/apply.
312

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ The Segment provider allows [Terraform](https://www.terraform.io/) to manage [Se
55
## Requirements
66

77
- [Terraform](https://www.terraform.io/downloads.html) >= 1.0
8-
- [Go](https://golang.org/doc/install) >= 1.21
8+
- [Go](https://golang.org/doc/install) >= 1.24.2
99

1010
## Building The Provider
1111

go.mod

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
module github.com/segmentio/terraform-provider-segment
22

3-
go 1.23.0
4-
5-
toolchain go1.24.1
3+
go 1.24.2
64

75
require (
86
github.com/avast/retry-go/v4 v4.6.1
@@ -39,7 +37,7 @@ require (
3937
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
4038
github.com/armon/go-radix v1.0.0 // indirect
4139
github.com/bgentry/speakeasy v0.1.0 // indirect
42-
github.com/cloudflare/circl v1.3.7 // indirect
40+
github.com/cloudflare/circl v1.6.1 // indirect
4341
github.com/dnephin/pflag v1.0.7 // indirect
4442
github.com/fatih/color v1.17.0 // indirect
4543
github.com/fsnotify/fsnotify v1.8.0 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR
3131
github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
3232
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
3333
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
34-
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
35-
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
34+
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
35+
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
3636
github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
3737
github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
3838
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=

internal/provider/function_resource.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,19 @@ import (
66
"net/http"
77
"regexp"
88

9-
"github.com/segmentio/terraform-provider-segment/internal/provider/docs"
10-
"github.com/segmentio/terraform-provider-segment/internal/provider/models"
11-
129
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
1310
"github.com/hashicorp/terraform-plugin-framework/path"
1411
"github.com/hashicorp/terraform-plugin-framework/resource"
1512
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
1613
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
1714
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
1815
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
16+
tftypes "github.com/hashicorp/terraform-plugin-framework/types"
1917

2018
"github.com/segmentio/public-api-sdk-go/api"
19+
20+
"github.com/segmentio/terraform-provider-segment/internal/provider/docs"
21+
"github.com/segmentio/terraform-provider-segment/internal/provider/models"
2122
)
2223

2324
var (
@@ -35,6 +36,10 @@ type functionResource struct {
3536
authContext context.Context
3637
}
3738

39+
func hasValue(v tftypes.String) bool {
40+
return !(v.IsNull() || v.IsUnknown())
41+
}
42+
3843
func (r *functionResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
3944
resp.TypeName = req.ProviderTypeName + "_function"
4045
}
@@ -163,7 +168,7 @@ func (r *functionResource) Create(ctx context.Context, req resource.CreateReques
163168
state.Fill(function)
164169

165170
// Destination functions append workspace name to display name causing inconsistency
166-
if state.ResourceType.ValueString() == "DESTINATION" || state.ResourceType.ValueString() == "INSERT_DESTINATION" {
171+
if state.ResourceType.ValueString() == "DESTINATION" || state.ResourceType.ValueString() == "INSERT_DESTINATION" || state.ResourceType.ValueString() == "INSERT_SOURCE" {
167172
state.DisplayName = plan.DisplayName
168173
}
169174

@@ -210,7 +215,7 @@ func (r *functionResource) Read(ctx context.Context, req resource.ReadRequest, r
210215
state.Fill(function)
211216

212217
// Destination functions append workspace name to display name causing inconsistency
213-
if state.ResourceType.ValueString() == "DESTINATION" || state.ResourceType.ValueString() == "INSERT_DESTINATION" {
218+
if state.ResourceType.ValueString() == "DESTINATION" || state.ResourceType.ValueString() == "INSERT_DESTINATION" || state.ResourceType.ValueString() == "INSERT_SOURCE" && hasValue(previousState.DisplayName) {
214219
state.DisplayName = previousState.DisplayName
215220
}
216221

@@ -266,7 +271,7 @@ func (r *functionResource) Update(ctx context.Context, req resource.UpdateReques
266271
state.Fill(function)
267272

268273
// Destination functions append workspace name to display name causing inconsistency
269-
if state.ResourceType.ValueString() == "DESTINATION" || state.ResourceType.ValueString() == "INSERT_DESTINATION" {
274+
if state.ResourceType.ValueString() == "DESTINATION" || state.ResourceType.ValueString() == "INSERT_DESTINATION" || state.ResourceType.ValueString() == "INSERT_SOURCE" {
270275
state.DisplayName = plan.DisplayName
271276
}
272277

internal/provider/function_resource_test.go

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,219 @@ func TestAccFunctionResource(t *testing.T) {
269269
},
270270
})
271271
}
272+
273+
func TestAccFunctionResource_InsertSource(t *testing.T) {
274+
t.Parallel()
275+
276+
// keeps track of whether we’ve already updated the Function
277+
updated := 0
278+
279+
// ────────────────────────── Fake Segment API ──────────────────────────
280+
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
281+
w.Header().Set("content-type", "application/json")
282+
283+
switch {
284+
// ── CREATE ─────────────────────────────────────────────────────────
285+
case req.URL.Path == "/functions" && req.Method == http.MethodPost:
286+
_, _ = w.Write([]byte(`
287+
{
288+
"data": {
289+
"function": {
290+
"id": "my-function-id",
291+
"workspaceId": "my-workspace-id",
292+
"displayName": "My test function",
293+
"description": "My function description",
294+
"logoUrl": "https://segment.com/cool-logo.png",
295+
"code": "// My test code!",
296+
"createdAt": "2023-10-11T18:52:07.087Z",
297+
"createdBy": "my-user-id",
298+
"previewWebhookUrl": "",
299+
"settings": [{
300+
"name": "mySettingName",
301+
"label": "My setting label",
302+
"description": "My setting description",
303+
"type": "STRING",
304+
"required": false,
305+
"sensitive": false
306+
}],
307+
"buildpack": "boreal",
308+
"catalogId": "my-catalog-id",
309+
"batchMaxCount": 0,
310+
"resourceType": "INSERT_SOURCE"
311+
}
312+
}
313+
}`))
314+
// ── UPDATE ─────────────────────────────────────────────────────────
315+
case req.URL.Path == "/functions/my-function-id" && req.Method == http.MethodPatch:
316+
updated++
317+
_, _ = w.Write([]byte(`
318+
{
319+
"data": {
320+
"function": {
321+
"id": "my-function-id",
322+
"workspaceId": "my-workspace-id",
323+
"displayName": "My new test function",
324+
"description": "My new function description",
325+
"logoUrl": "https://segment.com/cool-other-logo.png",
326+
"code": "// My new test code!",
327+
"createdAt": "2023-10-11T18:52:07.087Z",
328+
"createdBy": "my-user-id",
329+
"previewWebhookUrl": "",
330+
"settings": [{
331+
"name": "myNewSettingName",
332+
"label": "My new setting label",
333+
"description": "My new setting description",
334+
"type": "STRING",
335+
"required": true,
336+
"sensitive": true
337+
}],
338+
"buildpack": "boreal",
339+
"catalogId": "my-catalog-id",
340+
"batchMaxCount": 0,
341+
"resourceType": "INSERT_SOURCE"
342+
}
343+
}
344+
}`))
345+
346+
case req.URL.Path == "/functions/my-function-id" && req.Method == http.MethodGet:
347+
if updated == 0 {
348+
_, _ = w.Write([]byte(`
349+
{
350+
"data": {
351+
"function": {
352+
"id": "my-function-id",
353+
"workspaceId": "my-workspace-id",
354+
"displayName": "My test function",
355+
"description": "My function description",
356+
"logoUrl": "https://segment.com/cool-logo.png",
357+
"code": "// My test code!",
358+
"createdAt": "2023-10-11T18:52:07.087Z",
359+
"createdBy": "my-user-id",
360+
"previewWebhookUrl": "",
361+
"settings": [{
362+
"name": "mySettingName",
363+
"label": "My setting label",
364+
"description": "My setting description",
365+
"type": "STRING",
366+
"required": false,
367+
"sensitive": false
368+
}],
369+
"buildpack": "boreal",
370+
"catalogId": "my-catalog-id",
371+
"batchMaxCount": 0,
372+
"resourceType": "INSERT_SOURCE"
373+
}
374+
}
375+
}`))
376+
} else {
377+
_, _ = w.Write([]byte(`
378+
{
379+
"data": {
380+
"function": {
381+
"id": "my-function-id",
382+
"workspaceId": "my-workspace-id",
383+
"displayName": "My new test function",
384+
"description": "My new function description",
385+
"logoUrl": "https://segment.com/cool-other-logo.png",
386+
"code": "// My new test code!",
387+
"createdAt": "2023-10-11T18:52:07.087Z",
388+
"createdBy": "my-user-id",
389+
"previewWebhookUrl": "",
390+
"settings": [{
391+
"name": "myNewSettingName",
392+
"label": "My new setting label",
393+
"description": "My new setting description",
394+
"type": "STRING",
395+
"required": true,
396+
"sensitive": true
397+
}],
398+
"buildpack": "boreal",
399+
"catalogId": "my-catalog-id",
400+
"batchMaxCount": 0,
401+
"resourceType": "INSERT_SOURCE"
402+
}
403+
}
404+
}`))
405+
}
406+
}
407+
}))
408+
defer fakeServer.Close()
409+
410+
providerConfig := `
411+
provider "segment" {
412+
url = "` + fakeServer.URL + `"
413+
token = "abc123"
414+
}
415+
`
416+
417+
resource.Test(t, resource.TestCase{
418+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
419+
Steps: []resource.TestStep{
420+
{
421+
Config: providerConfig + `
422+
resource "segment_function" "test" {
423+
code = "// My test code!"
424+
display_name = "My test function"
425+
logo_url = "https://segment.com/cool-logo.png"
426+
resource_type = "INSERT_SOURCE"
427+
description = "My function description"
428+
settings = [{
429+
name = "mySettingName"
430+
label = "My setting label"
431+
type = "STRING"
432+
description = "My setting description"
433+
required = false
434+
sensitive = false
435+
}]
436+
}
437+
`,
438+
Check: resource.ComposeAggregateTestCheckFunc(
439+
resource.TestCheckResourceAttr("segment_function.test", "id", "my-function-id"),
440+
resource.TestCheckResourceAttr("segment_function.test", "resource_type", "INSERT_SOURCE"),
441+
resource.TestCheckResourceAttr("segment_function.test", "display_name", "My test function"),
442+
resource.TestCheckResourceAttr("segment_function.test", "logo_url", "https://segment.com/cool-logo.png"),
443+
resource.TestCheckResourceAttr("segment_function.test", "description", "My function description"),
444+
resource.TestCheckResourceAttr("segment_function.test", "settings.#", "1"),
445+
resource.TestCheckResourceAttr("segment_function.test", "settings.0.name", "mySettingName"),
446+
resource.TestCheckResourceAttr("segment_function.test", "settings.0.required", "false"),
447+
resource.TestCheckResourceAttr("segment_function.test", "settings.0.sensitive", "false"),
448+
),
449+
},
450+
451+
{
452+
ResourceName: "segment_function.test",
453+
ImportState: true,
454+
ImportStateVerify: true,
455+
},
456+
457+
{
458+
Config: providerConfig + `
459+
resource "segment_function" "test" {
460+
code = "// My new test code!"
461+
display_name = "My new test function"
462+
logo_url = "https://segment.com/cool-other-logo.png"
463+
resource_type = "INSERT_SOURCE"
464+
description = "My new function description"
465+
settings = [{
466+
name = "myNewSettingName"
467+
label = "My new setting label"
468+
type = "STRING"
469+
description = "My new setting description"
470+
required = true
471+
sensitive = true
472+
}]
473+
}
474+
`,
475+
Check: resource.ComposeAggregateTestCheckFunc(
476+
resource.TestCheckResourceAttr("segment_function.test", "resource_type", "INSERT_SOURCE"),
477+
resource.TestCheckResourceAttr("segment_function.test", "display_name", "My new test function"),
478+
resource.TestCheckResourceAttr("segment_function.test", "logo_url", "https://segment.com/cool-other-logo.png"),
479+
resource.TestCheckResourceAttr("segment_function.test", "description", "My new function description"),
480+
resource.TestCheckResourceAttr("segment_function.test", "settings.0.name", "myNewSettingName"),
481+
resource.TestCheckResourceAttr("segment_function.test", "settings.0.required", "true"),
482+
resource.TestCheckResourceAttr("segment_function.test", "settings.0.sensitive", "true"),
483+
),
484+
},
485+
},
486+
})
487+
}

0 commit comments

Comments
 (0)