Skip to content

Commit 1e3299f

Browse files
authored
Merge pull request #18 from ScaleComputing/node_data_source
node data source
2 parents 544b583 + 5edda98 commit 1e3299f

File tree

11 files changed

+393
-124
lines changed

11 files changed

+393
-124
lines changed

docs/data-sources/node.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "hypercore_node Data Source - hypercore"
4+
subcategory: ""
5+
description: |-
6+
7+
---
8+
9+
# hypercore_node (Data Source)
10+
11+
12+
13+
## Example Usage
14+
15+
```terraform
16+
# Copyright (c) HashiCorp, Inc.
17+
# SPDX-License-Identifier: MPL-2.0
18+
19+
# Get all nodes
20+
data "hypercore_node" "all_nodes" {
21+
}
22+
23+
output "hypercore_nodes" {
24+
value = data.hypercore_node.all_nodes.nodes
25+
}
26+
27+
# Get a specific node
28+
data "hypercore_node" "node_1" {
29+
peer_id = 1
30+
}
31+
32+
output "hypercore_node_1_uuid" {
33+
value = data.hypercore_node.node_1.nodes.0.uuid
34+
}
35+
```
36+
37+
<!-- schema generated by tfplugindocs -->
38+
## Schema
39+
40+
### Optional
41+
42+
- `peer_id` (Number)
43+
44+
### Read-Only
45+
46+
- `nodes` (Attributes List) (see [below for nested schema](#nestedatt--nodes))
47+
48+
<a id="nestedatt--nodes"></a>
49+
### Nested Schema for `nodes`
50+
51+
Read-Only:
52+
53+
- `backplane_ip` (String)
54+
- `lan_ip` (String)
55+
- `peer_id` (Number)
56+
- `uuid` (String)

docs/data-sources/vm.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,23 @@ Optional:
4747

4848
Read-Only:
4949

50+
- `affinity_strategy` (Object) VM node affinity. (see [below for nested schema](#nestedatt--vms--affinity_strategy))
5051
- `description` (String)
5152
- `disks` (Attributes List) List of disks (see [below for nested schema](#nestedatt--vms--disks))
5253
- `name` (String)
5354
- `power_state` (String)
5455
- `uuid` (String)
5556

57+
<a id="nestedatt--vms--affinity_strategy"></a>
58+
### Nested Schema for `vms.affinity_strategy`
59+
60+
Read-Only:
61+
62+
- `backup_node_uuid` (String)
63+
- `preferred_node_uuid` (String)
64+
- `strict_affinity` (Boolean)
65+
66+
5667
<a id="nestedatt--vms--disks"></a>
5768
### Nested Schema for `vms.disks`
5869

docs/resources/vm.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ output "vm_uuid" {
5858

5959
### Optional
6060

61+
- `affinity_strategy` (Object) VM node affinity. (see [below for nested schema](#nestedatt--affinity_strategy))
6162
- `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))
6263
- `description` (String) Description of this VM
6364
- `group` (String) Group/tag to create this VM in
@@ -68,6 +69,16 @@ output "vm_uuid" {
6869

6970
- `id` (String) HypercoreVM identifier
7071

72+
<a id="nestedatt--affinity_strategy"></a>
73+
### Nested Schema for `affinity_strategy`
74+
75+
Optional:
76+
77+
- `backup_node_uuid` (String)
78+
- `preferred_node_uuid` (String)
79+
- `strict_affinity` (Boolean)
80+
81+
7182
<a id="nestedatt--clone"></a>
7283
### Nested Schema for `clone`
7384

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright (c) HashiCorp, Inc.
2+
# SPDX-License-Identifier: MPL-2.0
3+
4+
# Get all nodes
5+
data "hypercore_node" "all_nodes" {
6+
}
7+
8+
output "hypercore_nodes" {
9+
value = data.hypercore_node.all_nodes.nodes
10+
}
11+
12+
# Get a specific node
13+
data "hypercore_node" "node_1" {
14+
peer_id = 1
15+
}
16+
17+
output "hypercore_node_1_uuid" {
18+
value = data.hypercore_node.node_1.nodes.0.uuid
19+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
// https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-data-source-read
5+
// https://developer.hashicorp.com/terraform/plugin/framework/migrating
6+
7+
package provider
8+
9+
import (
10+
"context"
11+
"fmt"
12+
13+
"github.com/hashicorp/terraform-plugin-framework/datasource"
14+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
15+
"github.com/hashicorp/terraform-plugin-framework/types"
16+
"github.com/hashicorp/terraform-plugin-log/tflog"
17+
"github.com/hashicorp/terraform-provider-hypercore/internal/utils"
18+
)
19+
20+
// Ensure the implementation satisfies the expected interfaces.
21+
var (
22+
_ datasource.DataSource = &hypercoreNodeDataSource{}
23+
_ datasource.DataSourceWithConfigure = &hypercoreNodeDataSource{}
24+
)
25+
26+
// NewHypercoreNodeDataSource is a helper function to simplify the provider implementation.
27+
func NewHypercoreNodeDataSource() datasource.DataSource {
28+
return &hypercoreNodeDataSource{}
29+
}
30+
31+
// hypercoreNodeDataSource is the data source implementation.
32+
type hypercoreNodeDataSource struct {
33+
client *utils.RestClient
34+
}
35+
36+
// coffeesDataSourceModel maps the data source schema data.
37+
type hypercoreNodesDataSourceModel struct {
38+
FilterPeerID types.Int64 `tfsdk:"peer_id"`
39+
Nodes []hypercoreNodeModel `tfsdk:"nodes"`
40+
}
41+
42+
// hypercoreVMModel maps VM schema data.
43+
type hypercoreNodeModel struct {
44+
UUID types.String `tfsdk:"uuid"`
45+
BackplaneIP types.String `tfsdk:"backplane_ip"`
46+
LanIP types.String `tfsdk:"lan_ip"`
47+
PeerID types.Int64 `tfsdk:"peer_id"`
48+
}
49+
50+
// Metadata returns the data source type name.
51+
func (d *hypercoreNodeDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
52+
resp.TypeName = req.ProviderTypeName + "_node"
53+
}
54+
55+
// Schema defines the schema for the data source.
56+
func (d *hypercoreNodeDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
57+
resp.Schema = schema.Schema{
58+
Attributes: map[string]schema.Attribute{
59+
"peer_id": schema.Int64Attribute{
60+
Optional: true,
61+
},
62+
"nodes": schema.ListNestedAttribute{
63+
Computed: true,
64+
NestedObject: schema.NestedAttributeObject{
65+
Attributes: map[string]schema.Attribute{
66+
"uuid": schema.StringAttribute{
67+
Computed: true,
68+
},
69+
"backplane_ip": schema.StringAttribute{
70+
Computed: true,
71+
},
72+
"lan_ip": schema.StringAttribute{
73+
Computed: true,
74+
},
75+
"peer_id": schema.Int64Attribute{
76+
Computed: true,
77+
},
78+
},
79+
},
80+
},
81+
},
82+
}
83+
}
84+
85+
// Configure adds the provider configured client to the data source.
86+
func (d *hypercoreNodeDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
87+
// Add a nil check when handling ProviderData because Terraform
88+
// sets that data after it calls the ConfigureProvider RPC.
89+
if req.ProviderData == nil {
90+
return
91+
}
92+
93+
restClient, ok := req.ProviderData.(*utils.RestClient)
94+
if !ok {
95+
resp.Diagnostics.AddError(
96+
"Unexpected Data Source Configure Type",
97+
fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
98+
)
99+
return
100+
}
101+
102+
d.client = restClient
103+
}
104+
105+
// Read refreshes the Terraform state with the latest data.
106+
func (d *hypercoreNodeDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
107+
var conf hypercoreNodesDataSourceModel
108+
req.Config.Get(ctx, &conf)
109+
// use float64, because this is the type of loaded json data
110+
filter_peer_id := float64(conf.FilterPeerID.ValueInt64())
111+
112+
query := map[string]any{}
113+
// peerID=0 is reserved value, never returned by HC3
114+
if filter_peer_id != 0.0 {
115+
query = map[string]any{"peerID": filter_peer_id}
116+
}
117+
118+
hc3_nodes := d.client.ListRecords(
119+
"/rest/v1/Node",
120+
query,
121+
-1.0,
122+
)
123+
tflog.Info(ctx, fmt.Sprintf("TTRT: filter_peer_id=%v node_count=%d\n", filter_peer_id, len(hc3_nodes)))
124+
125+
var state hypercoreNodesDataSourceModel
126+
for _, node := range hc3_nodes {
127+
hypercoreNodeState := hypercoreNodeModel{
128+
UUID: types.StringValue(utils.AnyToString(node["uuid"])),
129+
BackplaneIP: types.StringValue(utils.AnyToString(node["backplaneIP"])),
130+
LanIP: types.StringValue(utils.AnyToString(node["lanIP"])),
131+
PeerID: types.Int64Value(utils.AnyToInteger64(node["peerID"])),
132+
}
133+
state.Nodes = append(state.Nodes, hypercoreNodeState)
134+
}
135+
136+
// Set state
137+
diags := resp.State.Set(ctx, &state)
138+
resp.Diagnostics.Append(diags...)
139+
if resp.Diagnostics.HasError() {
140+
return
141+
}
142+
}

internal/provider/hypercore_vm_data_source.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"fmt"
1212
"strings"
1313

14+
"github.com/hashicorp/terraform-plugin-framework/attr"
1415
"github.com/hashicorp/terraform-plugin-framework/datasource"
1516
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
1617
"github.com/hashicorp/terraform-plugin-framework/types"
@@ -51,6 +52,7 @@ type hypercoreVMModel struct {
5152
Tags []types.String `tfsdk:"tags"`
5253
Disks []HypercoreDiskModel `tfsdk:"disks"`
5354
// TODO nics
55+
AffinityStrategy AffinityStrategyModel `tfsdk:"affinity_strategy"`
5456
}
5557

5658
type HypercoreDiskModel struct {
@@ -100,6 +102,15 @@ func (d *hypercoreVMDataSource) Schema(_ context.Context, _ datasource.SchemaReq
100102
ElementType: types.StringType,
101103
Optional: true,
102104
},
105+
"affinity_strategy": schema.ObjectAttribute{
106+
MarkdownDescription: "VM node affinity.",
107+
Computed: true,
108+
AttributeTypes: map[string]attr.Type{
109+
"strict_affinity": types.BoolType,
110+
"preferred_node_uuid": types.StringType,
111+
"backup_node_uuid": types.StringType,
112+
},
113+
},
103114

104115
"disks": schema.ListNestedAttribute{
105116
MarkdownDescription: "List of disks",
@@ -204,18 +215,26 @@ func (d *hypercoreVMDataSource) Read(ctx context.Context, req datasource.ReadReq
204215
}
205216
disks = append(disks, disk)
206217
}
218+
219+
hc3affinityStrategy := utils.AnyToMap(vm["affinityStrategy"])
220+
var affinityStrategy AffinityStrategyModel
221+
affinityStrategy.StrictAffinity = types.BoolValue(utils.AnyToBool(hc3affinityStrategy["strictAffinity"]))
222+
affinityStrategy.PreferredNodeUUID = types.StringValue(utils.AnyToString(hc3affinityStrategy["preferredNodeUUID"]))
223+
affinityStrategy.BackupNodeUUID = types.StringValue(utils.AnyToString(hc3affinityStrategy["backupNodeUUID"]))
224+
207225
// VM
208226
memory_B := utils.AnyToInteger64(vm["mem"])
209227
memory_MiB := memory_B / 1024 / 1024
210228
hypercoreVMState := hypercoreVMModel{
211-
UUID: types.StringValue(utils.AnyToString(vm["uuid"])),
212-
Name: types.StringValue(utils.AnyToString(vm["name"])),
213-
VCPU: types.Int32Value(int32(utils.AnyToInteger64(vm["numVCPU"]))),
214-
Memory: types.Int64Value(memory_MiB),
215-
Description: types.StringValue(utils.AnyToString(vm["description"])),
216-
PowerState: types.StringValue(utils.AnyToString(vm["state"])), // TODO convert (stopped vs SHUTOFF)
217-
Tags: tags_String,
218-
Disks: disks,
229+
UUID: types.StringValue(utils.AnyToString(vm["uuid"])),
230+
Name: types.StringValue(utils.AnyToString(vm["name"])),
231+
VCPU: types.Int32Value(int32(utils.AnyToInteger64(vm["numVCPU"]))),
232+
Memory: types.Int64Value(memory_MiB),
233+
Description: types.StringValue(utils.AnyToString(vm["description"])),
234+
PowerState: types.StringValue(utils.AnyToString(vm["state"])), // TODO convert (stopped vs SHUTOFF)
235+
Tags: tags_String,
236+
AffinityStrategy: affinityStrategy,
237+
Disks: disks,
219238
}
220239
state.Vms = append(state.Vms, hypercoreVMState)
221240
}

0 commit comments

Comments
 (0)