diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31258383..1feb8cca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,7 @@ on: - 'README.md' branches: - main + - feature/add-connector-metadata-to-twingate_connector-resource-and-data-structure # Ensures only 1 action runs per PR and previous is canceled on new trigger concurrency: diff --git a/.github/workflows/smoketests.yml b/.github/workflows/smoketests.yml index 3525f2f7..ee4ebfd5 100644 --- a/.github/workflows/smoketests.yml +++ b/.github/workflows/smoketests.yml @@ -4,8 +4,8 @@ name: Smoke Tests permissions: read-all on: -# schedule: -# - cron: "0 */3 * * *" + schedule: + - cron: "0 */3 * * *" workflow_dispatch: {} jobs: diff --git a/docs/data-sources/connector.md b/docs/data-sources/connector.md index 4c4fa0b4..49aa43a2 100644 --- a/docs/data-sources/connector.md +++ b/docs/data-sources/connector.md @@ -27,6 +27,11 @@ data "twingate_connector" "foo" { ### Read-Only +- `hostname` (String) The hostname of the machine hosting the Connector. - `name` (String) The name of the Connector. +- `private_ips` (Set of String) The Connector's private IP addresses. +- `public_ip` (String) The Connector's public IP address. - `remote_network_id` (String) The ID of the Remote Network the Connector is attached to. +- `state` (String) The Connector's state. One of `ALIVE`, `DEAD_NO_HEARTBEAT`, `DEAD_HEARTBEAT_TOO_OLD` or `DEAD_NO_RELAYS`. - `status_updates_enabled` (Boolean) Determines whether status notifications are enabled for the Connector. +- `version` (String) The Connector's version. diff --git a/docs/data-sources/connectors.md b/docs/data-sources/connectors.md index 1c2e4360..4c1df6d2 100644 --- a/docs/data-sources/connectors.md +++ b/docs/data-sources/connectors.md @@ -45,7 +45,12 @@ data "twingate_connectors" "all" { Read-Only: +- `hostname` (String) The hostname of the machine hosting the Connector. - `id` (String) The ID of the Connector. - `name` (String) The Name of the Connector. +- `private_ips` (Set of String) The Connector's private IP addresses. +- `public_ip` (String) The Connector's public IP address. - `remote_network_id` (String) The ID of the Remote Network attached to the Connector. +- `state` (String) The Connector's state. One of `ALIVE`, `DEAD_NO_HEARTBEAT`, `DEAD_HEARTBEAT_TOO_OLD` or `DEAD_NO_RELAYS`. - `status_updates_enabled` (Boolean) Determines whether status notifications are enabled for the Connector. +- `version` (String) The Connector's version. diff --git a/docs/resources/connector.md b/docs/resources/connector.md index fcafcc75..64a3c91d 100644 --- a/docs/resources/connector.md +++ b/docs/resources/connector.md @@ -42,7 +42,12 @@ resource "twingate_connector" "aws_connector" { ### Read-Only +- `hostname` (String) The hostname of the machine hosting the Connector. - `id` (String) Autogenerated ID of the Connector, encoded in base64. +- `private_ips` (Set of String) The Connector's private IP addresses. +- `public_ip` (String) The Connector's public IP address. +- `state` (String) The Connector's state. One of `ALIVE`, `DEAD_NO_HEARTBEAT`, `DEAD_HEARTBEAT_TOO_OLD` or `DEAD_NO_RELAYS`. +- `version` (String) The Connector's version. ## Import diff --git a/twingate/internal/attr/connector.go b/twingate/internal/attr/connector.go index c56fa3af..c66d2dc7 100644 --- a/twingate/internal/attr/connector.go +++ b/twingate/internal/attr/connector.go @@ -3,4 +3,8 @@ package attr const ( StatusUpdatesEnabled = "status_updates_enabled" Connectors = "connectors" + Hostname = "hostname" + Version = "version" + PublicIP = "public_ip" + PrivateIPs = "private_ips" ) diff --git a/twingate/internal/client/query/connector-read.go b/twingate/internal/client/query/connector-read.go index 86a98b4b..c46d9dfc 100644 --- a/twingate/internal/client/query/connector-read.go +++ b/twingate/internal/client/query/connector-read.go @@ -15,6 +15,11 @@ type gqlConnector struct { ID graphql.ID } HasStatusNotificationsEnabled bool + Hostname string + State string + Version string + PublicIP string `graphql:"publicIP"` + PrivateIPs []string `graphql:"privateIPs"` } func (q ReadConnector) IsEmpty() bool { @@ -35,5 +40,10 @@ func (c gqlConnector) ToModel() *model.Connector { Name: c.Name, NetworkID: string(c.RemoteNetwork.ID), StatusUpdatesEnabled: &c.HasStatusNotificationsEnabled, + State: c.State, + Hostname: c.Hostname, + Version: c.Version, + PublicIP: c.PublicIP, + PrivateIPs: c.PrivateIPs, } } diff --git a/twingate/internal/model/connector.go b/twingate/internal/model/connector.go index 9f18c00c..403739c7 100644 --- a/twingate/internal/model/connector.go +++ b/twingate/internal/model/connector.go @@ -7,6 +7,11 @@ type Connector struct { Name string NetworkID string StatusUpdatesEnabled *bool + State string + Version string + Hostname string + PublicIP string + PrivateIPs []string } func (c Connector) GetName() string { @@ -23,5 +28,10 @@ func (c Connector) ToTerraform() interface{} { attr.Name: c.Name, attr.RemoteNetworkID: c.NetworkID, attr.StatusUpdatesEnabled: *c.StatusUpdatesEnabled, + attr.State: c.State, + attr.Version: c.Version, + attr.Hostname: c.Hostname, + attr.PublicIP: c.PublicIP, + attr.PrivateIPs: c.PrivateIPs, } } diff --git a/twingate/internal/provider/datasource/connector.go b/twingate/internal/provider/datasource/connector.go index a4dd68ef..0e2b79ef 100644 --- a/twingate/internal/provider/datasource/connector.go +++ b/twingate/internal/provider/datasource/connector.go @@ -6,6 +6,7 @@ import ( "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/attr" "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/client" + "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/utils" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" @@ -27,6 +28,11 @@ type connectorModel struct { Name types.String `tfsdk:"name"` RemoteNetworkID types.String `tfsdk:"remote_network_id"` StatusUpdatesEnabled types.Bool `tfsdk:"status_updates_enabled"` + State types.String `tfsdk:"state"` + Hostname types.String `tfsdk:"hostname"` + Version types.String `tfsdk:"version"` + PublicIP types.String `tfsdk:"public_ip"` + PrivateIPs types.Set `tfsdk:"private_ips"` } func (d *connector) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { @@ -72,6 +78,27 @@ func (d *connector) Schema(ctx context.Context, req datasource.SchemaRequest, re Computed: true, Description: "Determines whether status notifications are enabled for the Connector.", }, + attr.State: schema.StringAttribute{ + Computed: true, + Description: "The Connector's state. One of `ALIVE`, `DEAD_NO_HEARTBEAT`, `DEAD_HEARTBEAT_TOO_OLD` or `DEAD_NO_RELAYS`.", + }, + attr.Hostname: schema.StringAttribute{ + Computed: true, + Description: "The hostname of the machine hosting the Connector.", + }, + attr.Version: schema.StringAttribute{ + Computed: true, + Description: "The Connector's version.", + }, + attr.PublicIP: schema.StringAttribute{ + Computed: true, + Description: "The Connector's public IP address.", + }, + attr.PrivateIPs: schema.SetAttribute{ + Computed: true, + ElementType: types.StringType, + Description: "The Connector's private IP addresses.", + }, }, } } @@ -96,6 +123,11 @@ func (d *connector) Read(ctx context.Context, req datasource.ReadRequest, resp * data.Name = types.StringValue(connector.Name) data.RemoteNetworkID = types.StringValue(connector.NetworkID) data.StatusUpdatesEnabled = types.BoolPointerValue(connector.StatusUpdatesEnabled) + data.State = types.StringValue(connector.State) + data.Version = types.StringValue(connector.Version) + data.Hostname = types.StringValue(connector.Hostname) + data.PublicIP = types.StringValue(connector.PublicIP) + data.PrivateIPs = utils.MakeStringSet(connector.PrivateIPs) // Save data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) diff --git a/twingate/internal/provider/datasource/connectors.go b/twingate/internal/provider/datasource/connectors.go index cd4b9fc0..cf5784a2 100644 --- a/twingate/internal/provider/datasource/connectors.go +++ b/twingate/internal/provider/datasource/connectors.go @@ -58,6 +58,7 @@ func (d *connectors) Configure(ctx context.Context, req datasource.ConfigureRequ d.client = client } +//nolint:funlen func (d *connectors) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ Description: "Connectors provide connectivity to Remote Networks. For more information, see Twingate's [documentation](https://docs.twingate.com/docs/understanding-access-nodes).", @@ -114,6 +115,27 @@ func (d *connectors) Schema(ctx context.Context, req datasource.SchemaRequest, r Computed: true, Description: "Determines whether status notifications are enabled for the Connector.", }, + attr.State: schema.StringAttribute{ + Computed: true, + Description: "The Connector's state. One of `ALIVE`, `DEAD_NO_HEARTBEAT`, `DEAD_HEARTBEAT_TOO_OLD` or `DEAD_NO_RELAYS`.", + }, + attr.Hostname: schema.StringAttribute{ + Computed: true, + Description: "The hostname of the machine hosting the Connector.", + }, + attr.Version: schema.StringAttribute{ + Computed: true, + Description: "The Connector's version.", + }, + attr.PublicIP: schema.StringAttribute{ + Computed: true, + Description: "The Connector's public IP address.", + }, + attr.PrivateIPs: schema.SetAttribute{ + Computed: true, + ElementType: types.StringType, + Description: "The Connector's private IP addresses.", + }, }, }, }, diff --git a/twingate/internal/provider/datasource/converter.go b/twingate/internal/provider/datasource/converter.go index d43c3652..b72f39be 100644 --- a/twingate/internal/provider/datasource/converter.go +++ b/twingate/internal/provider/datasource/converter.go @@ -3,7 +3,6 @@ package datasource import ( "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/model" "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/utils" - "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/types" ) @@ -13,6 +12,11 @@ func convertConnectorsToTerraform(connectors []*model.Connector) []connectorMode Name: types.StringValue(connector.Name), RemoteNetworkID: types.StringValue(connector.NetworkID), StatusUpdatesEnabled: types.BoolPointerValue(connector.StatusUpdatesEnabled), + State: types.StringValue(connector.State), + Version: types.StringValue(connector.Version), + Hostname: types.StringValue(connector.Hostname), + PublicIP: types.StringValue(connector.PublicIP), + PrivateIPs: utils.MakeStringSet(connector.PrivateIPs), } }) } @@ -86,14 +90,6 @@ func convertRemoteNetworksToTerraform(networks []*model.RemoteNetwork) []remoteN func convertDomainsToTerraform(domains []string) *domainsModel { return &domainsModel{ - Domains: convertStringListToSet(domains), + Domains: utils.MakeStringSet(domains), } } - -func convertStringListToSet(items []string) types.Set { - values := utils.Map(items, func(item string) attr.Value { - return types.StringValue(item) - }) - - return types.SetValueMust(types.StringType, values) -} diff --git a/twingate/internal/provider/datasource/dns-filtering-profile.go b/twingate/internal/provider/datasource/dns-filtering-profile.go index 3c159748..7f2f0143 100644 --- a/twingate/internal/provider/datasource/dns-filtering-profile.go +++ b/twingate/internal/provider/datasource/dns-filtering-profile.go @@ -6,6 +6,7 @@ import ( "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/attr" "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/client" + "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/utils" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" @@ -268,7 +269,7 @@ func (d *dnsFilteringProfile) Read(ctx context.Context, req datasource.ReadReque data.FallbackMethod = types.StringValue(profile.FallbackMethod) data.AllowedDomains = convertDomainsToTerraform(profile.AllowedDomains) data.DeniedDomains = convertDomainsToTerraform(profile.DeniedDomains) - data.Groups = convertStringListToSet(profile.Groups) + data.Groups = utils.MakeStringSet(profile.Groups) if profile.PrivacyCategories != nil { data.PrivacyCategories = &privacyCategoriesModel{ diff --git a/twingate/internal/provider/resource/connector.go b/twingate/internal/provider/resource/connector.go index 7f939e9c..8ce784a8 100644 --- a/twingate/internal/provider/resource/connector.go +++ b/twingate/internal/provider/resource/connector.go @@ -7,6 +7,7 @@ import ( "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/attr" "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/client" "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/model" + "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/utils" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -36,6 +37,11 @@ type connectorModel struct { Name types.String `tfsdk:"name"` RemoteNetworkID types.String `tfsdk:"remote_network_id"` StatusUpdatesEnabled types.Bool `tfsdk:"status_updates_enabled"` + State types.String `tfsdk:"state"` + Hostname types.String `tfsdk:"hostname"` + Version types.String `tfsdk:"version"` + PublicIP types.String `tfsdk:"public_ip"` + PrivateIPs types.Set `tfsdk:"private_ips"` } func (r *connector) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { @@ -101,6 +107,27 @@ func (r *connector) Schema(_ context.Context, _ resource.SchemaRequest, resp *re stringplanmodifier.UseStateForUnknown(), }, }, + attr.State: schema.StringAttribute{ + Computed: true, + Description: "The Connector's state. One of `ALIVE`, `DEAD_NO_HEARTBEAT`, `DEAD_HEARTBEAT_TOO_OLD` or `DEAD_NO_RELAYS`.", + }, + attr.Hostname: schema.StringAttribute{ + Computed: true, + Description: "The hostname of the machine hosting the Connector.", + }, + attr.Version: schema.StringAttribute{ + Computed: true, + Description: "The Connector's version.", + }, + attr.PublicIP: schema.StringAttribute{ + Computed: true, + Description: "The Connector's public IP address.", + }, + attr.PrivateIPs: schema.SetAttribute{ + Computed: true, + ElementType: types.StringType, + Description: "The Connector's private IP addresses.", + }, }, } } @@ -198,6 +225,11 @@ func (r *connector) helper(ctx context.Context, conn *model.Connector, state *co state.Name = types.StringValue(conn.Name) state.RemoteNetworkID = types.StringValue(conn.NetworkID) state.StatusUpdatesEnabled = types.BoolPointerValue(conn.StatusUpdatesEnabled) + state.State = types.StringValue(conn.State) + state.Version = types.StringValue(conn.Version) + state.Hostname = types.StringValue(conn.Hostname) + state.PublicIP = types.StringValue(conn.PublicIP) + state.PrivateIPs = utils.MakeStringSet(conn.PrivateIPs) // Set refreshed state diags := respState.Set(ctx, state) diff --git a/twingate/internal/test/acctests/datasource/connector_test.go b/twingate/internal/test/acctests/datasource/connector_test.go index 95381d35..482f502a 100644 --- a/twingate/internal/test/acctests/datasource/connector_test.go +++ b/twingate/internal/test/acctests/datasource/connector_test.go @@ -28,6 +28,10 @@ func TestAccDatasourceTwingateConnector_basic(t *testing.T) { Check: acctests.ComposeTestCheckFunc( resource.TestCheckOutput("my_connector", connectorName), resource.TestCheckOutput("my_connector_notification_status", "true"), + resource.TestCheckOutput("my_connector_state", "DEAD_NO_HEARTBEAT"), + resource.TestCheckOutput("my_connector_version", ""), + resource.TestCheckOutput("my_connector_hostname", ""), + resource.TestCheckOutput("my_connector_public_ip", ""), ), }, }, @@ -55,6 +59,23 @@ func testDatasourceTwingateConnector(remoteNetworkName, connectorName string) st output "my_connector_notification_status" { value = data.twingate_connector.out_dc1.status_updates_enabled } + + output "my_connector_state" { + value = data.twingate_connector.out_dc1.state + } + + output "my_connector_version" { + value = data.twingate_connector.out_dc1.version + } + + output "my_connector_hostname" { + value = data.twingate_connector.out_dc1.hostname + } + + output "my_connector_public_ip" { + value = data.twingate_connector.out_dc1.public_ip + } + `, remoteNetworkName, connectorName) } diff --git a/twingate/internal/test/acctests/datasource/connectors_test.go b/twingate/internal/test/acctests/datasource/connectors_test.go index 206bf64d..3122dc3c 100644 --- a/twingate/internal/test/acctests/datasource/connectors_test.go +++ b/twingate/internal/test/acctests/datasource/connectors_test.go @@ -36,6 +36,11 @@ func TestAccDatasourceTwingateConnectors_basic(t *testing.T) { testCheckOutputLength("my_connectors", 2), testCheckOutputAttr("my_connectors", 0, attr.Name, connectorName), testCheckOutputAttr("my_connectors", 0, attr.StatusUpdatesEnabled, true), + testCheckOutputAttr("my_connectors", 0, attr.State, "DEAD_NO_HEARTBEAT"), + testCheckOutputAttr("my_connectors", 0, attr.Hostname, ""), + testCheckOutputAttr("my_connectors", 0, attr.Version, ""), + testCheckOutputAttr("my_connectors", 0, attr.PublicIP, ""), + testCheckOutputAttr("my_connectors", 0, attr.PrivateIPs, []any{}), ), }, }, diff --git a/twingate/internal/test/acctests/resource/connector_test.go b/twingate/internal/test/acctests/resource/connector_test.go index 9996c396..0bfb18ad 100644 --- a/twingate/internal/test/acctests/resource/connector_test.go +++ b/twingate/internal/test/acctests/resource/connector_test.go @@ -30,6 +30,7 @@ func TestAccRemoteConnectorCreate(t *testing.T) { Check: acctests.ComposeTestCheckFunc( checkTwingateConnectorSetWithRemoteNetwork(theResource, acctests.TerraformRemoteNetwork(terraformResourceName)), sdk.TestCheckResourceAttrSet(theResource, attr.Name), + sdk.TestCheckResourceAttrSet(theResource, attr.State), ), }, }, diff --git a/twingate/internal/test/client/connector_test.go b/twingate/internal/test/client/connector_test.go index 84371834..12fd40a3 100644 --- a/twingate/internal/test/client/connector_test.go +++ b/twingate/internal/test/client/connector_test.go @@ -23,6 +23,7 @@ func TestClientConnectorCreateOk(t *testing.T) { Name: "test-name", NetworkID: "remote-network-id", StatusUpdatesEnabled: ¬ificationEnabled, + State: "DEAD_NO_HEARTBEAT", } jsonResponse := `{ @@ -31,6 +32,7 @@ func TestClientConnectorCreateOk(t *testing.T) { "entity": { "id": "test-id", "name": "test-name", + "state": "DEAD_NO_HEARTBEAT", "hasStatusNotificationsEnabled": true, "remoteNetwork": { "id": "remote-network-id" @@ -61,6 +63,7 @@ func TestClientConnectorCreateWithNotificationStatusOk(t *testing.T) { Name: "test-name", NetworkID: "remote-network-id", StatusUpdatesEnabled: ¬ificationEnabled, + State: "DEAD_NO_HEARTBEAT", } jsonResponse := `{ @@ -69,6 +72,7 @@ func TestClientConnectorCreateWithNotificationStatusOk(t *testing.T) { "entity": { "id": "test-id", "name": "test-name", + "state": "DEAD_NO_HEARTBEAT", "hasStatusNotificationsEnabled": true, "remoteNetwork": { "id": "remote-network-id" @@ -456,6 +460,11 @@ func TestClientConnectorReadOk(t *testing.T) { ID: "test-id", Name: "test-name", StatusUpdatesEnabled: ¬ificationEnabled, + State: "ALIVE", + Hostname: "test-hostname", + Version: "test-version", + PublicIP: "test-public-ip", + PrivateIPs: []string{"test-private-ip"}, } jsonResponse := `{ @@ -463,7 +472,12 @@ func TestClientConnectorReadOk(t *testing.T) { "connector": { "id": "test-id", "name": "test-name", - "hasStatusNotificationsEnabled": true + "hasStatusNotificationsEnabled": true, + "state": "ALIVE", + "hostname": "test-hostname", + "version": "test-version", + "publicIP": "test-public-ip", + "privateIPs": ["test-private-ip"] } } }` @@ -726,8 +740,6 @@ func TestClientConnectorReadRequestError(t *testing.T) { }) } -// readConnectorsWithRemoteNetwork - func TestClientReadConnectorsWithRemoteNetworkOk(t *testing.T) { t.Run("Test Twingate Resource : Read All Client Connectors with remote network - Ok", func(t *testing.T) { expected := []*model.Connector{ diff --git a/twingate/internal/test/models/connector_test.go b/twingate/internal/test/models/connector_test.go index e7449292..642bd162 100644 --- a/twingate/internal/test/models/connector_test.go +++ b/twingate/internal/test/models/connector_test.go @@ -31,6 +31,11 @@ func TestConnectorModel(t *testing.T) { attr.Name: "", attr.RemoteNetworkID: "", attr.StatusUpdatesEnabled: false, + attr.State: "", + attr.Version: "", + attr.Hostname: "", + attr.PublicIP: "", + attr.PrivateIPs: []string(nil), }, }, { @@ -39,6 +44,11 @@ func TestConnectorModel(t *testing.T) { Name: "name", NetworkID: "network-id", StatusUpdatesEnabled: &boolTrue, + State: "DEAD_NO_HEARTBEAT", + Version: "0.1", + Hostname: "127.0.0.1", + PublicIP: "127.0.0.1", + PrivateIPs: []string{"127.0.0.1"}, }, expectedID: "id", expectedName: "name", @@ -47,6 +57,11 @@ func TestConnectorModel(t *testing.T) { attr.Name: "name", attr.RemoteNetworkID: "network-id", attr.StatusUpdatesEnabled: true, + attr.State: "DEAD_NO_HEARTBEAT", + attr.Version: "0.1", + attr.Hostname: "127.0.0.1", + attr.PublicIP: "127.0.0.1", + attr.PrivateIPs: []string{"127.0.0.1"}, }, }, } diff --git a/twingate/internal/test/utils/utils_test.go b/twingate/internal/test/utils/utils_test.go index 6cab3c30..5f8f4611 100644 --- a/twingate/internal/test/utils/utils_test.go +++ b/twingate/internal/test/utils/utils_test.go @@ -2,6 +2,8 @@ package utils import ( "fmt" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/types" "testing" "github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/utils" @@ -131,3 +133,33 @@ func TestDocList(t *testing.T) { }) } } + +func TestMakeStringSet(t *testing.T) { + type testCase struct { + items []string + expected types.Set + } + + cases := []testCase{ + { + items: []string{}, + expected: types.SetValueMust(types.StringType, []attr.Value{}), + }, + { + items: []string{"1", "2", "3"}, + expected: types.SetValueMust(types.StringType, []attr.Value{ + types.StringValue("1"), + types.StringValue("2"), + types.StringValue("3"), + }), + }, + } + + for n, c := range cases { + t.Run(fmt.Sprintf("case: %d", n), func(t *testing.T) { + actual := utils.MakeStringSet(c.items) + + assert.Equal(t, c.expected, actual) + }) + } +} diff --git a/twingate/internal/utils/utils.go b/twingate/internal/utils/utils.go index 00bfbb1a..87ea8d38 100644 --- a/twingate/internal/utils/utils.go +++ b/twingate/internal/utils/utils.go @@ -3,6 +3,9 @@ package utils import ( "fmt" "strings" + + tfattr "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/types" ) // Map - transform giving slice of items by applying the func. @@ -75,3 +78,9 @@ func DocList(items []string) string { return fmt.Sprintf("%s or %s", strings.Join(items[:n-1], ", "), last) } } + +func MakeStringSet(values []string) types.Set { + return types.SetValueMust(types.StringType, Map(values, func(value string) tfattr.Value { + return types.StringValue(value) + })) +}