Skip to content

Commit

Permalink
added new read-only fields to twingate_connector resource and datasource
Browse files Browse the repository at this point in the history
  • Loading branch information
vmanilo committed Nov 24, 2024
1 parent f2765be commit adfae73
Show file tree
Hide file tree
Showing 20 changed files with 234 additions and 16 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/smoketests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
name: Smoke Tests
permissions: read-all
on:
# schedule:
# - cron: "0 */3 * * *"
schedule:
- cron: "0 */3 * * *"
workflow_dispatch: {}

jobs:
Expand Down
5 changes: 5 additions & 0 deletions docs/data-sources/connector.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
5 changes: 5 additions & 0 deletions docs/data-sources/connectors.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
5 changes: 5 additions & 0 deletions docs/resources/connector.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions twingate/internal/attr/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ package attr
const (
StatusUpdatesEnabled = "status_updates_enabled"
Connectors = "connectors"
Hostname = "hostname"
Version = "version"
PublicIP = "public_ip"
PrivateIPs = "private_ips"
)
10 changes: 10 additions & 0 deletions twingate/internal/client/query/connector-read.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
}
}
10 changes: 10 additions & 0 deletions twingate/internal/model/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
}
}
32 changes: 32 additions & 0 deletions twingate/internal/provider/datasource/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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) {
Expand Down Expand Up @@ -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.",
},
},
}
}
Expand All @@ -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)...)
Expand Down
22 changes: 22 additions & 0 deletions twingate/internal/provider/datasource/connectors.go
Original file line number Diff line number Diff line change
Expand Up @@ -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).",
Expand Down Expand Up @@ -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.",
},
},
},
},
Expand Down
16 changes: 6 additions & 10 deletions twingate/internal/provider/datasource/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -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),
}
})
}
Expand Down Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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{
Expand Down
32 changes: 32 additions & 0 deletions twingate/internal/provider/resource/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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.",
},
},
}
}
Expand Down Expand Up @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions twingate/internal/test/acctests/datasource/connector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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", ""),
),
},
},
Expand Down Expand Up @@ -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)
}

Expand Down
5 changes: 5 additions & 0 deletions twingate/internal/test/acctests/datasource/connectors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}),
),
},
},
Expand Down
1 change: 1 addition & 0 deletions twingate/internal/test/acctests/resource/connector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
),
},
},
Expand Down
Loading

0 comments on commit adfae73

Please sign in to comment.