Skip to content

node data source #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions docs/data-sources/node.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "hypercore_node Data Source - hypercore"
subcategory: ""
description: |-

---

# hypercore_node (Data Source)



## Example Usage

```terraform
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0

# Get all nodes
data "hypercore_node" "all_nodes" {
}

output "hypercore_nodes" {
value = data.hypercore_node.all_nodes.nodes
}

# Get a specific node
data "hypercore_node" "node_1" {
peer_id = 1
}

output "hypercore_node_1_uuid" {
value = data.hypercore_node.node_1.nodes.0.uuid
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- `peer_id` (Number)

### Read-Only

- `nodes` (Attributes List) (see [below for nested schema](#nestedatt--nodes))

<a id="nestedatt--nodes"></a>
### Nested Schema for `nodes`

Read-Only:

- `backplane_ip` (String)
- `lan_ip` (String)
- `peer_id` (Number)
- `uuid` (String)
11 changes: 11 additions & 0 deletions docs/data-sources/vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,23 @@ Optional:

Read-Only:

- `affinity_strategy` (Object) VM node affinity. (see [below for nested schema](#nestedatt--vms--affinity_strategy))
- `description` (String)
- `disks` (Attributes List) List of disks (see [below for nested schema](#nestedatt--vms--disks))
- `name` (String)
- `power_state` (String)
- `uuid` (String)

<a id="nestedatt--vms--affinity_strategy"></a>
### Nested Schema for `vms.affinity_strategy`

Read-Only:

- `backup_node_uuid` (String)
- `preferred_node_uuid` (String)
- `strict_affinity` (Boolean)


<a id="nestedatt--vms--disks"></a>
### Nested Schema for `vms.disks`

Expand Down
11 changes: 11 additions & 0 deletions docs/resources/vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ output "vm_uuid" {

### Optional

- `affinity_strategy` (Object) VM node affinity. (see [below for nested schema](#nestedatt--affinity_strategy))
- `clone` (Object) Clone options if the VM is being created as a clone. The `source_vm_uuid` is the UUID of the VM used for cloning, <br>`user_data` and `meta_data` are used for the cloud init data. (see [below for nested schema](#nestedatt--clone))
- `description` (String) Description of this VM
- `group` (String) Group/tag to create this VM in
Expand All @@ -68,6 +69,16 @@ output "vm_uuid" {

- `id` (String) HypercoreVM identifier

<a id="nestedatt--affinity_strategy"></a>
### Nested Schema for `affinity_strategy`

Optional:

- `backup_node_uuid` (String)
- `preferred_node_uuid` (String)
- `strict_affinity` (Boolean)


<a id="nestedatt--clone"></a>
### Nested Schema for `clone`

Expand Down
19 changes: 19 additions & 0 deletions examples/data-sources/hypercore_node/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0

# Get all nodes
data "hypercore_node" "all_nodes" {
}

output "hypercore_nodes" {
value = data.hypercore_node.all_nodes.nodes
}

# Get a specific node
data "hypercore_node" "node_1" {
peer_id = 1
}

output "hypercore_node_1_uuid" {
value = data.hypercore_node.node_1.nodes.0.uuid
}
142 changes: 142 additions & 0 deletions internal/provider/hypercore_node_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

// https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-data-source-read
// https://developer.hashicorp.com/terraform/plugin/framework/migrating

package provider

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-provider-hypercore/internal/utils"
)

// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &hypercoreNodeDataSource{}
_ datasource.DataSourceWithConfigure = &hypercoreNodeDataSource{}
)

// NewHypercoreNodeDataSource is a helper function to simplify the provider implementation.
func NewHypercoreNodeDataSource() datasource.DataSource {
return &hypercoreNodeDataSource{}
}

// hypercoreNodeDataSource is the data source implementation.
type hypercoreNodeDataSource struct {
client *utils.RestClient
}

// coffeesDataSourceModel maps the data source schema data.
type hypercoreNodesDataSourceModel struct {
FilterPeerID types.Int64 `tfsdk:"peer_id"`
Nodes []hypercoreNodeModel `tfsdk:"nodes"`
}

// hypercoreVMModel maps VM schema data.
type hypercoreNodeModel struct {
UUID types.String `tfsdk:"uuid"`
BackplaneIP types.String `tfsdk:"backplane_ip"`
LanIP types.String `tfsdk:"lan_ip"`
PeerID types.Int64 `tfsdk:"peer_id"`
}

// Metadata returns the data source type name.
func (d *hypercoreNodeDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_node"
}

// Schema defines the schema for the data source.
func (d *hypercoreNodeDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"peer_id": schema.Int64Attribute{
Optional: true,
},
"nodes": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"uuid": schema.StringAttribute{
Computed: true,
},
"backplane_ip": schema.StringAttribute{
Computed: true,
},
"lan_ip": schema.StringAttribute{
Computed: true,
},
"peer_id": schema.Int64Attribute{
Computed: true,
},
},
},
},
},
}
}

// Configure adds the provider configured client to the data source.
func (d *hypercoreNodeDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
// Add a nil check when handling ProviderData because Terraform
// sets that data after it calls the ConfigureProvider RPC.
if req.ProviderData == nil {
return
}

restClient, ok := req.ProviderData.(*utils.RestClient)
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 = restClient
}

// Read refreshes the Terraform state with the latest data.
func (d *hypercoreNodeDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var conf hypercoreNodesDataSourceModel
req.Config.Get(ctx, &conf)
// use float64, because this is the type of loaded json data
filter_peer_id := float64(conf.FilterPeerID.ValueInt64())

query := map[string]any{}
// peerID=0 is reserved value, never returned by HC3
if filter_peer_id != 0.0 {
query = map[string]any{"peerID": filter_peer_id}
}

hc3_nodes := d.client.ListRecords(
"/rest/v1/Node",
query,
-1.0,
)
tflog.Info(ctx, fmt.Sprintf("TTRT: filter_peer_id=%v node_count=%d\n", filter_peer_id, len(hc3_nodes)))

var state hypercoreNodesDataSourceModel
for _, node := range hc3_nodes {
hypercoreNodeState := hypercoreNodeModel{
UUID: types.StringValue(utils.AnyToString(node["uuid"])),
BackplaneIP: types.StringValue(utils.AnyToString(node["backplaneIP"])),
LanIP: types.StringValue(utils.AnyToString(node["lanIP"])),
PeerID: types.Int64Value(utils.AnyToInteger64(node["peerID"])),
}
state.Nodes = append(state.Nodes, hypercoreNodeState)
}

// Set state
diags := resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}
35 changes: 27 additions & 8 deletions internal/provider/hypercore_vm_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-framework/attr"
"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 @@ -51,6 +52,7 @@ type hypercoreVMModel struct {
Tags []types.String `tfsdk:"tags"`
Disks []HypercoreDiskModel `tfsdk:"disks"`
// TODO nics
AffinityStrategy AffinityStrategyModel `tfsdk:"affinity_strategy"`
}

type HypercoreDiskModel struct {
Expand Down Expand Up @@ -100,6 +102,15 @@ func (d *hypercoreVMDataSource) Schema(_ context.Context, _ datasource.SchemaReq
ElementType: types.StringType,
Optional: true,
},
"affinity_strategy": schema.ObjectAttribute{
MarkdownDescription: "VM node affinity.",
Computed: true,
AttributeTypes: map[string]attr.Type{
"strict_affinity": types.BoolType,
"preferred_node_uuid": types.StringType,
"backup_node_uuid": types.StringType,
},
},

"disks": schema.ListNestedAttribute{
MarkdownDescription: "List of disks",
Expand Down Expand Up @@ -204,18 +215,26 @@ func (d *hypercoreVMDataSource) Read(ctx context.Context, req datasource.ReadReq
}
disks = append(disks, disk)
}

hc3affinityStrategy := utils.AnyToMap(vm["affinityStrategy"])
var affinityStrategy AffinityStrategyModel
affinityStrategy.StrictAffinity = types.BoolValue(utils.AnyToBool(hc3affinityStrategy["strictAffinity"]))
affinityStrategy.PreferredNodeUUID = types.StringValue(utils.AnyToString(hc3affinityStrategy["preferredNodeUUID"]))
affinityStrategy.BackupNodeUUID = types.StringValue(utils.AnyToString(hc3affinityStrategy["backupNodeUUID"]))

// VM
memory_B := utils.AnyToInteger64(vm["mem"])
memory_MiB := memory_B / 1024 / 1024
hypercoreVMState := hypercoreVMModel{
UUID: types.StringValue(utils.AnyToString(vm["uuid"])),
Name: types.StringValue(utils.AnyToString(vm["name"])),
VCPU: types.Int32Value(int32(utils.AnyToInteger64(vm["numVCPU"]))),
Memory: types.Int64Value(memory_MiB),
Description: types.StringValue(utils.AnyToString(vm["description"])),
PowerState: types.StringValue(utils.AnyToString(vm["state"])), // TODO convert (stopped vs SHUTOFF)
Tags: tags_String,
Disks: disks,
UUID: types.StringValue(utils.AnyToString(vm["uuid"])),
Name: types.StringValue(utils.AnyToString(vm["name"])),
VCPU: types.Int32Value(int32(utils.AnyToInteger64(vm["numVCPU"]))),
Memory: types.Int64Value(memory_MiB),
Description: types.StringValue(utils.AnyToString(vm["description"])),
PowerState: types.StringValue(utils.AnyToString(vm["state"])), // TODO convert (stopped vs SHUTOFF)
Tags: tags_String,
AffinityStrategy: affinityStrategy,
Disks: disks,
}
state.Vms = append(state.Vms, hypercoreVMState)
}
Expand Down
Loading
Loading