Skip to content

Commit

Permalink
Adding provider::semvers::pick function
Browse files Browse the repository at this point in the history
The `pick` function takes a list of semver strings, and a constraint as
a string (according to [docs][1]), and returns a list of matched semver
strings. An empty list is returned if no matches found.

[1]: https://github.com/Masterminds/semver/tree/master?tab=readme-ov-file#checking-version-constraints
  • Loading branch information
anapsix committed Sep 12, 2024
1 parent d480843 commit 60d1a29
Show file tree
Hide file tree
Showing 15 changed files with 286 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
**/.DS_Store
**/.terraform.lock.hcl
**/.terraform
**/.vscode
**/terraform.tfplan
**/terraform.tfstate
**/terraform.tfstate.backup
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 0.4.0

### Added:
- The `provider::semvers::pick` function which takes list of semver strings,
and semver constraint, and returns a list of filtered semver strings, sorted and deduped,
matching the constraint. See [Masterminds/semver](https://github.com/Masterminds/semver/tree/master?tab=readme-ov-file#checking-version-constraints) for constraint syntax.

## 0.3.1

### Fixed
Expand All @@ -12,7 +19,6 @@
- The `provider::semvers::sort` function which takes list of semver strings,
and returns a list of semver strings, sorted and deduped


## 0.2.1

### Added:
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/list.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "semvers_list Data Source - terraform-provider-semvers"
page_title: "semvers_list Data Source - semvers"
subcategory: ""
description: |-
Parses and sorts a list of semver strings.
Expand Down
26 changes: 26 additions & 0 deletions docs/functions/pick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "pick function - semvers"
subcategory: ""
description: |-
Returns semver from list of semvers according to contraint
---

# function: pick

Returns semver from list of semvers according to contraint



## Signature

<!-- signature generated by tfplugindocs -->
```text
pick(versions list of string, constraint string) list of string
```

## Arguments

<!-- arguments generated by tfplugindocs -->
1. `versions` (List of String) List of semver strigs
1. `constraint` (String) Semver constraint
2 changes: 1 addition & 1 deletion docs/functions/sort.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "sort function - terraform-provider-semvers"
page_title: "sort function - semvers"
subcategory: ""
description: |-
Returns sorted list of semver strings
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ require (
github.com/yuin/goldmark-meta v1.1.0 // indirect
github.com/zclconf/go-cty v1.15.0 // indirect
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
golang.org/x/mod v0.19.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/grpc v1.66.0 // indirect
google.golang.org/grpc v1.66.2 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
Expand All @@ -223,6 +225,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down Expand Up @@ -268,6 +272,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
Expand Down
33 changes: 32 additions & 1 deletion internal/helpers/shelper.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package shelper

import (
"github.com/Masterminds/semver/v3"
"sort"

"github.com/Masterminds/semver/v3"
)

// RemoveDups removes duplicate versions from a list of semver.Version pointers
Expand Down Expand Up @@ -54,3 +55,33 @@ func StringsToStrings(list []string) ([]string, error) {
}
return SemversToStrings(semvers), nil
}

func PickFromSemverStrings(list []string, contraint string) ([]string, error) {
var semvers_filtered []string
semvers_list, err := StringsToSemvers(list)
if err != nil {
return nil, err
}
semver_compare, err := semver.NewConstraint(contraint)
if err != nil {
return nil, err
}

for _, v := range semvers_list {
match := semver_compare.Check(v)
// match, msgs := semver_compare.Validate(v)
// for _, m := range msgs {
// fmt.Println(m)
// }
if match {
semvers_filtered = append(semvers_filtered, v.String())
}
}

if len(semvers_filtered) == 0 {
var empty_results []string
return empty_results, nil
}

return semvers_filtered, nil
}
76 changes: 76 additions & 0 deletions internal/provider/function_pick.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) HashiCorp, Inc.
// Copyright (c) Anastas Dancha
// SPDX-License-Identifier: MPL-2.0

package provider

import (
"context"

shelper "github.com/anapsix/terraform-provider-semvers/internal/helpers"
"github.com/hashicorp/terraform-plugin-framework/function"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
)

var (
_ function.Function = SemversPickFunction{}
)

func NewSemversPickFunction() function.Function {
return SemversPickFunction{}
}

type SemversPickFunction struct{}

func (r SemversPickFunction) Metadata(_ context.Context, req function.MetadataRequest, resp *function.MetadataResponse) {
resp.Name = "pick"
}

func (r SemversPickFunction) Definition(_ context.Context, _ function.DefinitionRequest, resp *function.DefinitionResponse) {
resp.Definition = function.Definition{
Summary: "Returns semver from list of semvers according to contraint",
MarkdownDescription: "Returns semver from list of semvers according to contraint",
Parameters: []function.Parameter{
function.ListParameter{
AllowNullValue: false,
AllowUnknownValues: false,
ElementType: types.StringType,
Name: "versions",
MarkdownDescription: "List of semver strigs",
},
function.StringParameter{
AllowNullValue: false,
AllowUnknownValues: false,
Name: "constraint",
MarkdownDescription: "Semver constraint",
},
},
Return: function.ListReturn{
ElementType: types.StringType,
},
}
}

func (r SemversPickFunction) Run(ctx context.Context, req function.RunRequest, resp *function.RunResponse) {
var versions []string
var constraint string

resp.Error = function.ConcatFuncErrors(req.Arguments.Get(ctx, &versions, &constraint))
if resp.Error != nil {
return
}

filtered_semvers, err := shelper.PickFromSemverStrings(versions, constraint)

if err != nil {
tflog.Error(ctx, "Error in shelper.PickFromSemverStrings()")
}

if len(filtered_semvers) == 0 {
empty_list := make([]string, 0)
resp.Error = function.ConcatFuncErrors(resp.Result.Set(ctx, empty_list))
} else {
resp.Error = function.ConcatFuncErrors(resp.Result.Set(ctx, filtered_semvers))
}
}
124 changes: 124 additions & 0 deletions internal/provider/function_pick_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright (c) HashiCorp, Inc.
// Copyright (c) Anastas Dancha
// SPDX-License-Identifier: MPL-2.0

package provider

import (
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfversion"
)

func TestSemversPickFunction_Known(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_8_0),
},
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: `
output "semvers_filtered" {
value = provider::semvers::pick(
["0.1.1-rc1+a231f59", "0.1.1", "0.1.10", "0.1.2-rc1", "0.2.1"],
"~> 0.2"
)
}
`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownOutputValue(
"semvers_filtered",
knownvalue.ListExact([]knownvalue.Check{
knownvalue.StringExact("0.2.1"),
}),
),
},
},
{
Config: `
output "semvers_filtered" {
value = provider::semvers::pick(
["0.1.0", "0.1.1-rc1+a231f59", "0.1.1", "0.1.10", "0.1.2-rc1", "0.2.1"],
">= 0.1.1"
)
}
`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownOutputValue(
"semvers_filtered",
knownvalue.ListExact([]knownvalue.Check{
knownvalue.StringExact("0.1.1"),
knownvalue.StringExact("0.1.10"),
knownvalue.StringExact("0.2.1"),
}),
),
},
},
{
Config: `
output "semvers_filtered" {
value = provider::semvers::pick(
["0.1.0", "0.1.1-rc1+a231f59", "0.1.1", "0.1.10", "0.1.2-rc1", "0.2.1"],
">= 3.0"
)
}
`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownOutputValue(
"semvers_filtered",
knownvalue.ListSizeExact(0),
),
},
},
},
})
}

// func TPick_Null(t *testing.T) {
// resource.UnitTest(t, resource.TestCase{
// TerraformVersionChecks: []tfversion.TerraformVersionCheck{
// tfversion.SkipBelow(tfversion.Version1_8_0),
// },
// ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
// Steps: []resource.TestStep{
// {
// Config: `
// output "test" {
// value = provider::semvers::sort_semvers(null)
// }
// `,
// // The parameter does not enable AllowNullValue
// ExpectError: regexp.MustCompile(`argument must not be null`),
// },
// },
// })
// }

// func TPick_Unknown(t *testing.T) {
// resource.UnitTest(t, resource.TestCase{
// TerraformVersionChecks: []tfversion.TerraformVersionCheck{
// tfversion.SkipBelow(tfversion.Version1_8_0),
// },
// ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
// Steps: []resource.TestStep{
// {
// Config: `
// resource "terraform_data" "test" {
// input = "testvalue"
// }

// output "test" {
// value = provider::semvers::sort_semvers(terraform_data.test.output)
// }
// `,
// Check: resource.ComposeAggregateTestCheckFunc(
// resource.TestCheckOutput("test", "testvalue"),
// ),
// },
// },
// })
// }
2 changes: 1 addition & 1 deletion internal/provider/function_sort.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package provider
import (
"context"

"github.com/anapsix/terraform-provider-semvers/internal/helpers"
shelper "github.com/anapsix/terraform-provider-semvers/internal/helpers"
"github.com/hashicorp/terraform-plugin-framework/function"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
Expand Down
1 change: 1 addition & 0 deletions internal/provider/function_sort_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) HashiCorp, Inc.
// Copyright (c) Anastas Dancha
// SPDX-License-Identifier: MPL-2.0

package provider
Expand Down
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@ func (p *semversProvider) Configure(ctx context.Context, req provider.ConfigureR
func (p *semversProvider) Functions(_ context.Context) []func() function.Function {
return []func() function.Function{
NewSemversSortFunction,
NewSemversPickFunction,
}
}
2 changes: 1 addition & 1 deletion internal/provider/semvers_list_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"

"github.com/anapsix/terraform-provider-semvers/internal/helpers"
shelper "github.com/anapsix/terraform-provider-semvers/internal/helpers"
)

// Data Source definition
Expand Down
Loading

0 comments on commit 60d1a29

Please sign in to comment.