diff --git a/docs/data-sources/server.md b/docs/data-sources/server.md
new file mode 100644
index 0000000..0b62b81
--- /dev/null
+++ b/docs/data-sources/server.md
@@ -0,0 +1,76 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "virtfusion_server Data Source - terraform-provider-virtfusion"
+subcategory: ""
+description: |-
+ The Virtfusion Server data source allows access to the details of a server. This data source can be used to read information about an existing server.
+---
+
+# virtfusion_server (Data Source)
+
+The Virtfusion Server data source allows access to the details of a server. This data source can be used to read information about an existing server.
+
+
+
+
+## Schema
+
+### Required
+
+- `id` (Number) Server ID
+
+### Read-Only
+
+- `build_failed` (Boolean) Build failed
+- `built` (String) Built
+- `commission_status` (Number) Commission status
+- `config_level` (Number) Config level
+- `created` (String) Created
+- `delete_level` (Number) Delete level
+- `hostname` (String) Server hostname
+- `hypervisor_id` (Number) Hypervisor ID
+- `migrate_level` (Number) Migrate level
+- `name` (String) Server name
+- `network` (Attributes) Network interfaces (see [below for nested schema](#nestedatt--network))
+- `owner_id` (Number) Owner ID
+- `primary_network_dhcp4` (Boolean) Primary network DHCP4
+- `primary_network_dhcp6` (Boolean) Primary network DHCP6
+- `protected` (Boolean) Protected
+- `rebuild` (Boolean) Rebuild
+- `state` (String) Server state
+- `suspended` (Boolean) Suspended
+- `updated` (String) Updated
+- `uuid` (String) Server UUID
+
+
+### Nested Schema for `network`
+
+Read-Only:
+
+- `interfaces` (Attributes) Network interfaces (see [below for nested schema](#nestedatt--network--interfaces))
+
+
+### Nested Schema for `network.interfaces`
+
+Read-Only:
+
+- `enabled` (Boolean) Enabled
+- `ipv4` (Attributes) IPv4 (see [below for nested schema](#nestedatt--network--interfaces--ipv4))
+- `mac` (String) MAC
+- `name` (String) Name
+- `type` (String) Type
+
+
+### Nested Schema for `network.interfaces.ipv4`
+
+Read-Only:
+
+- `address` (String) Address
+- `enabled` (Boolean) Enabled
+- `gateway` (String) Gateway
+- `id` (Number) ID
+- `mac` (String) MAC
+- `netmask` (String) Netmask
+- `rdns` (String) RDNS
+- `resolver_one` (String) Resolver one
+- `resolver_two` (String) Resolver two
diff --git a/docs/resources/ssh.md b/docs/resources/ssh.md
index 530acf9..03ba82d 100644
--- a/docs/resources/ssh.md
+++ b/docs/resources/ssh.md
@@ -36,4 +36,3 @@ resource "virtfusion_ssh" "dummy_key" {
### Read-Only
- `id` (Number) SSH Key ID
-- `public_key_hash` (String) Public Key Hash
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 7ff2a2d..6c65512 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -27,8 +27,8 @@ type VirtfusionProvider struct {
version string
}
-// ScaffoldingProviderModel describes the provider data model.
-type ScaffoldingProviderModel struct {
+// VirtfusionProviderModel describes the provider data model.
+type VirtfusionProviderModel struct {
Endpoint types.String `tfsdk:"endpoint"`
ApiToken types.String `tfsdk:"api_token"`
}
@@ -58,7 +58,7 @@ func (p *VirtfusionProvider) Configure(ctx context.Context, req provider.Configu
apiToken := os.Getenv("VIRTFUSION_API_TOKEN")
endpoint := os.Getenv("VIRTFUSION_ENDPOINT")
- var data ScaffoldingProviderModel
+ var data VirtfusionProviderModel
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
@@ -121,7 +121,9 @@ func (p *VirtfusionProvider) Resources(ctx context.Context) []func() resource.Re
}
func (p *VirtfusionProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
- return []func() datasource.DataSource{}
+ return []func() datasource.DataSource{
+ NewVirtfusionServerDataSource,
+ }
}
type CustomTransport struct {
diff --git a/internal/provider/virtfusion_server_data_source.go b/internal/provider/virtfusion_server_data_source.go
new file mode 100644
index 0000000..92fc86b
--- /dev/null
+++ b/internal/provider/virtfusion_server_data_source.go
@@ -0,0 +1,433 @@
+package provider
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+// Ensure provider defined types fully satisfy framework interfaces.
+var _ datasource.DataSource = &VirtfusionServerDataSource{}
+
+func NewVirtfusionServerDataSource() datasource.DataSource {
+ return &VirtfusionServerDataSource{}
+}
+
+// VirtfusionServerDataSource defines the data source implementation.
+type VirtfusionServerDataSource struct {
+ client *http.Client
+}
+
+// VirtfusionServerDataSourceModel describes the data source data model.
+type VirtfusionServerDataSourceModel struct {
+ Id types.Int64 `tfsdk:"id" json:"id"`
+ OwnerId types.Int64 `tfsdk:"owner_id" json:"ownerId"`
+ HypervisorId types.Int64 `tfsdk:"hypervisor_id" json:"hypervisorId"`
+ Name types.String `tfsdk:"name" json:"name"`
+ Hostname types.String `tfsdk:"hostname" json:"hostname"`
+ CommissionStatus types.Int64 `tfsdk:"commission_status" json:"commissionStatus"`
+ Uuid types.String `tfsdk:"uuid" json:"uuid"`
+ State types.String `tfsdk:"state" json:"state"`
+ MigrateLevel types.Int64 `tfsdk:"migrate_level" json:"migrateLevel"`
+ DeleteLevel types.Int64 `tfsdk:"delete_level" json:"deleteLevel"`
+ ConfigLevel types.Int64 `tfsdk:"config_level" json:"configLevel"`
+ Rebuild types.Bool `tfsdk:"rebuild" json:"rebuild"`
+ Suspended types.Bool `tfsdk:"suspended" json:"suspended"`
+ Protected types.Bool `tfsdk:"protected" json:"protected"`
+ BuildFailed types.Bool `tfsdk:"build_failed" json:"buildFailed"`
+ PrimaryNetworkDhcp4 types.Bool `tfsdk:"primary_network_dhcp4" json:"primaryNetworkDhcp4"`
+ PrimaryNetworkDhcp6 types.Bool `tfsdk:"primary_network_dhcp6" json:"primaryNetworkDhcp6"`
+ Built types.String `tfsdk:"built" json:"built"`
+ Created types.String `tfsdk:"created" json:"created"`
+ Updated types.String `tfsdk:"updated" json:"updated"`
+ //Settings struct {
+ // OsTemplateInstall types.Bool `tfsdk:"os_template_install" json:"osTemplateInstall"`
+ // OsTemplateInstallId types.Int64 `tfsdk:"os_template_install_id" json:"osTemplateInstallId"`
+ // EncryptedPassword types.String `tfsdk:"encrypted_password" json:"encryptedPassword"`
+ // BackupPlan types.Int64 `tfsdk:"backup_plan" json:"backupPlan"`
+ // Uefi types.Bool `tfsdk:"uefi" json:"uefi"`
+ // CloudInit types.Bool `tfsdk:"cloud_init" json:"cloudInit"`
+ // CloudInitType types.Int64 `tfsdk:"cloud_init_type" json:"cloudInitType"`
+ // Resources struct {
+ // Memory types.Int64 `tfsdk:"memory" json:"memory"`
+ // Cores types.Int64 `tfsdk:"cores" json:"cpuCores"`
+ // Storage types.Int64 `tfsdk:"storage" json:"storage"`
+ // Traffic types.Int64 `tfsdk:"traffic" json:"traffic"`
+ // } `tfsdk:"resources" json:"resources"`
+ //} `tfsdk:"settings" json:"settings"`
+ Network struct {
+ Interfaces []struct {
+ Enabled types.Bool `tfsdk:"enabled" json:"enabled"`
+ Name types.String `tfsdk:"name" json:"name"`
+ Type types.String `tfsdk:"type" json:"type"`
+ Mac types.String `tfsdk:"mac" json:"mac"`
+ Ipv4 []struct {
+ Id types.Int64 `tfsdk:"id" json:"id"`
+ Enabled types.Bool `tfsdk:"enabled" json:"enabled"`
+ Address types.String `tfsdk:"address" json:"address"`
+ Netmask types.String `tfsdk:"netmask" json:"netmask"`
+ Gateway types.String `tfsdk:"gateway" json:"gateway"`
+ ResolverOne types.String `tfsdk:"resolver_one" json:"resolverOne"`
+ ResolverTwo types.String `tfsdk:"resolver_two" json:"resolverTwo"`
+ Rdns types.String `tfsdk:"rdns" json:"rdns"`
+ Mac types.String `tfsdk:"mac" json:"mac"`
+ } `tfsdk:"ipv4" json:"ipv4"`
+ Ipv6 []struct {
+ } `tfsdk:"ipv6" json:"ipv6"`
+ } `tfsdk:"interfaces" json:"interfaces"`
+ } `tfsdk:"network" json:"network"`
+ //Owner struct {
+ // Id types.Int64 `tfsdk:"id" json:"id"`
+ // Name types.String `tfsdk:"name" json:"name"`
+ // Email types.String `tfsdk:"email" json:"email"`
+ // ExtId types.Int64 `tfsdk:"ext_id" json:"extRelationId"`
+ // Timezone types.String `tfsdk:"timezone" json:"timezone"`
+ // Suspended types.Bool `tfsdk:"suspended" json:"suspended"`
+ // Created types.String `tfsdk:"created" json:"created"`
+ // Updated types.String `tfsdk:"updated" json:"updated"`
+ // TwoFactorAuth types.Bool `tfsdk:"two_factor_auth" json:"twoFactorAuth"`
+ //} `tfsdk:"owner" json:"owner"`
+}
+
+func (d *VirtfusionServerDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_server"
+}
+
+func (d *VirtfusionServerDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ MarkdownDescription: "The Virtfusion Server data source allows access to the details of a server." +
+ " This data source can be used to read information about an existing server.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.Int64Attribute{
+ MarkdownDescription: "Server ID",
+ Required: true,
+ },
+ "owner_id": schema.Int64Attribute{
+ MarkdownDescription: "Owner ID",
+ Computed: true,
+ },
+ "hypervisor_id": schema.Int64Attribute{
+ MarkdownDescription: "Hypervisor ID",
+ Computed: true,
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: "Server name",
+ Computed: true,
+ },
+ "hostname": schema.StringAttribute{
+ MarkdownDescription: "Server hostname",
+ Computed: true,
+ },
+ "commission_status": schema.Int64Attribute{
+ MarkdownDescription: "Commission status",
+ Computed: true,
+ },
+ "uuid": schema.StringAttribute{
+ MarkdownDescription: "Server UUID",
+ Computed: true,
+ },
+ "state": schema.StringAttribute{
+ MarkdownDescription: "Server state",
+ Computed: true,
+ },
+ "migrate_level": schema.Int64Attribute{
+ MarkdownDescription: "Migrate level",
+ Computed: true,
+ },
+ "delete_level": schema.Int64Attribute{
+ MarkdownDescription: "Delete level",
+ Computed: true,
+ },
+ "config_level": schema.Int64Attribute{
+ MarkdownDescription: "Config level",
+ Computed: true,
+ },
+ "rebuild": schema.BoolAttribute{
+ MarkdownDescription: "Rebuild",
+ Computed: true,
+ },
+ "suspended": schema.BoolAttribute{
+ MarkdownDescription: "Suspended",
+ Computed: true,
+ },
+ "protected": schema.BoolAttribute{
+ MarkdownDescription: "Protected",
+ Computed: true,
+ },
+ "build_failed": schema.BoolAttribute{
+ MarkdownDescription: "Build failed",
+ Computed: true,
+ },
+ "primary_network_dhcp4": schema.BoolAttribute{
+ MarkdownDescription: "Primary network DHCP4",
+ Computed: true,
+ },
+ "primary_network_dhcp6": schema.BoolAttribute{
+ MarkdownDescription: "Primary network DHCP6",
+ Computed: true,
+ },
+ "built": schema.StringAttribute{
+ MarkdownDescription: "Built",
+ Computed: true,
+ },
+ "created": schema.StringAttribute{
+ MarkdownDescription: "Created",
+ Computed: true,
+ },
+ "updated": schema.StringAttribute{
+ MarkdownDescription: "Updated",
+ Computed: true,
+ },
+ "network": schema.SingleNestedAttribute{
+ MarkdownDescription: "Network interfaces",
+ Computed: true,
+ Attributes: map[string]schema.Attribute{
+ "interfaces": schema.SingleNestedAttribute{
+ MarkdownDescription: "Network interfaces",
+ Computed: true,
+ Attributes: map[string]schema.Attribute{
+ "enabled": schema.BoolAttribute{
+ MarkdownDescription: "Enabled",
+ Computed: true,
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: "Name",
+ Computed: true,
+ },
+ "type": schema.StringAttribute{
+ MarkdownDescription: "Type",
+ Computed: true,
+ },
+ "mac": schema.StringAttribute{
+ MarkdownDescription: "MAC",
+ Computed: true,
+ },
+ "ipv4": schema.SingleNestedAttribute{
+ MarkdownDescription: "IPv4",
+ Computed: true,
+ Attributes: map[string]schema.Attribute{
+ "id": schema.Int64Attribute{
+ MarkdownDescription: "ID",
+ Computed: true,
+ },
+ "enabled": schema.BoolAttribute{
+ MarkdownDescription: "Enabled",
+ Computed: true,
+ },
+ "address": schema.StringAttribute{
+ MarkdownDescription: "Address",
+ Computed: true,
+ },
+ "netmask": schema.StringAttribute{
+ MarkdownDescription: "Netmask",
+ Computed: true,
+ },
+ "gateway": schema.StringAttribute{
+ MarkdownDescription: "Gateway",
+ Computed: true,
+ },
+ "resolver_one": schema.StringAttribute{
+ MarkdownDescription: "Resolver one",
+ Computed: true,
+ },
+ "resolver_two": schema.StringAttribute{
+ MarkdownDescription: "Resolver two",
+ Computed: true,
+ },
+ "rdns": schema.StringAttribute{
+ MarkdownDescription: "RDNS",
+ Computed: true,
+ },
+ "mac": schema.StringAttribute{
+ MarkdownDescription: "MAC",
+ Computed: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func (d *VirtfusionServerDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
+ // Prevent panic if the provider has not been configured.
+ if req.ProviderData == nil {
+ return
+ }
+
+ client, ok := req.ProviderData.(*http.Client)
+
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected Data Source Configure Type",
+ fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
+ )
+
+ return
+ }
+
+ d.client = client
+}
+
+func (d *VirtfusionServerDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var data VirtfusionServerDataSourceModel
+ var responseData struct {
+ Data struct {
+ Id int64 `json:"id"`
+ OwnerId int64 `json:"owner_id"`
+ HypervisorId int64 `json:"hypervisor_id"`
+ Name string `json:"name"`
+ Hostname string `json:"hostname"`
+ CommissionStatus int64 `json:"commission_status"`
+ Uuid string `json:"uuid"`
+ State string `json:"state"`
+ MigrateLevel int64 `json:"migrate_level"`
+ DeleteLevel int64 `json:"delete_level"`
+ ConfigLevel int64 `json:"config_level"`
+ Rebuild bool `json:"rebuild"`
+ Suspended bool `json:"suspended"`
+ Protected bool `json:"protected"`
+ BuildFailed bool `json:"build_failed"`
+ PrimaryNetworkDhcp4 bool `json:"primary_network_dhcp4"`
+ PrimaryNetworkDhcp6 bool `json:"primary_network_dhcp6"`
+ Built string `json:"built"`
+ Created string `json:"created"`
+ Updated string `json:"updated"`
+ //Settings struct {
+ // OsTemplateInstall types.Bool `json:"os_template_install"`
+ // OsTemplateInstallId types.Int64 `json:"os_template_install_id"`
+ // EncryptedPassword types.String `json:"encrypted_password"`
+ // BackupPlan types.Int64 `json:"backup_plan"`
+ // Uefi types.Bool `json:"uefi"`
+ // CloudInit types.Bool `json:"cloud_init"`
+ // CloudInitType types.Int64 `json:"cloud_init_type"`
+ // Resources struct {
+ // Memory types.Int64 `json:"memory"`
+ // Cores types.Int64 `json:"cpu_cores"`
+ // Storage types.Int64 `json:"storage"`
+ // Traffic types.Int64 `json:"traffic"`
+ // } `json:"resources"`
+ //} `json:"settings"`
+ Network struct {
+ Interfaces []struct {
+ Enabled bool `json:"enabled"`
+ Name string `json:"name"`
+ Type string `json:"type"`
+ Mac string `json:"mac"`
+ Ipv4 []struct {
+ Id int64 `json:"id"`
+ Enabled bool `json:"enabled"`
+ Address string `json:"address"`
+ Netmask string `json:"netmask"`
+ Gateway string `json:"gateway"`
+ ResolverOne string `json:"resolver_one"`
+ ResolverTwo string `json:"resolver_two"`
+ Rdns string `json:"rdns"`
+ Mac string `json:"mac"`
+ } `json:"ipv4"`
+ Ipv6 []struct {
+ } `json:"ipv6"`
+ } `json:"interfaces"`
+ } `json:"network"`
+ //Owner struct {
+ // Id types.Int64 `json:"id"`
+ // Name types.String `json:"name"`
+ // Email types.String `json:"email"`
+ // ExtId types.Int64 `json:"ext_id"`
+ // Timezone types.String `json:"timezone"`
+ // Suspended types.Bool `json:"suspended"`
+ // Created types.String `json:"created"`
+ // Updated types.String `json:"updated"`
+ // TwoFactorAuth types.Bool `json:"two_factor_auth"`
+ //} `json:"owner"`
+ } `json:"data"`
+ }
+
+ // Read Terraform configuration data into the model
+ resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Make an API request using the configured client
+ httpReq, err := http.NewRequest("GET", fmt.Sprintf("/servers/%d", data.Id.ValueInt64()), nil)
+
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Failed to Create Request",
+ fmt.Sprintf("Failed to create a new HTTP request: %s", err.Error()),
+ )
+ return
+ }
+
+ // If the resource returns a 404, then the resource has been deleted. Return an empty state.
+ httpResponse, err := d.client.Do(httpReq)
+ defer func(Body io.ReadCloser) {
+ err := Body.Close()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Failed to close response body",
+ fmt.Sprintf("Failed to close response body: %s", err.Error()),
+ )
+ }
+ }(httpResponse.Body)
+
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Failed to Execute Request",
+ fmt.Sprintf("Failed to execute HTTP request: %s", err.Error()),
+ )
+ return
+ }
+
+ if httpResponse.StatusCode == 404 {
+ resp.State.RemoveResource(ctx)
+ return
+ }
+
+ err = json.NewDecoder(httpResponse.Body).Decode(&responseData)
+
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Failed to decode response body",
+ fmt.Sprintf("Failed to decode response body: %s", err.Error()),
+ )
+ return
+ }
+
+ data.Id = types.Int64Value(responseData.Data.Id)
+ data.OwnerId = types.Int64Value(responseData.Data.OwnerId)
+ data.HypervisorId = types.Int64Value(responseData.Data.HypervisorId)
+ data.Name = types.StringValue(responseData.Data.Name)
+ data.Hostname = types.StringValue(responseData.Data.Hostname)
+ data.CommissionStatus = types.Int64Value(responseData.Data.CommissionStatus)
+ data.Uuid = types.StringValue(responseData.Data.Uuid)
+ data.State = types.StringValue(responseData.Data.State)
+ data.MigrateLevel = types.Int64Value(responseData.Data.MigrateLevel)
+ data.DeleteLevel = types.Int64Value(responseData.Data.DeleteLevel)
+ data.ConfigLevel = types.Int64Value(responseData.Data.ConfigLevel)
+ data.Rebuild = types.BoolValue(responseData.Data.Rebuild)
+ data.Suspended = types.BoolValue(responseData.Data.Suspended)
+ data.Protected = types.BoolValue(responseData.Data.Protected)
+ data.BuildFailed = types.BoolValue(responseData.Data.BuildFailed)
+ data.PrimaryNetworkDhcp4 = types.BoolValue(responseData.Data.PrimaryNetworkDhcp4)
+ data.PrimaryNetworkDhcp6 = types.BoolValue(responseData.Data.PrimaryNetworkDhcp6)
+ data.Built = types.StringValue(responseData.Data.Built)
+ data.Created = types.StringValue(responseData.Data.Created)
+ data.Updated = types.StringValue(responseData.Data.Updated)
+
+ // Save data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}