-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
provider: Implement
definednet_host
resource
The resource provides a mechanism for managing hosts on Defined.net control plane.
- Loading branch information
1 parent
6ecc942
commit a2b7cdd
Showing
13 changed files
with
692 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
variable "definednet_token" { | ||
description = "Defined.net HTTP API token" | ||
sensitive = true | ||
} | ||
|
||
provider "definednet" { | ||
token = var.definednet_token | ||
} | ||
|
||
resource "definednet_host" "example" { | ||
name = "example.defined.test" | ||
network_id = "network-7P81MCS2TVAY9XJWQTNJ3PWYPD" | ||
role_id = "role-WSG78880Z655TQJVQFL5CZ405B" | ||
tags = ["service:app"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
`definednet_host` enables managing Nebula overlay network hosts on Defined.net. | ||
|
||
The Defined.net API token must be configured with the following scope: | ||
|
||
- `hosts:create` | ||
- `hosts:delete` | ||
- `hosts:enroll` | ||
- `hosts:list` | ||
- `hosts:read` | ||
- `hosts:update` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,255 @@ | ||
package host | ||
|
||
import ( | ||
"context" | ||
_ "embed" | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
"github.com/sendsmaily/terraform-provider-definednet/internal/definednet" | ||
) | ||
|
||
// NewResource creates a Defined.net Nebula host resource. | ||
func NewResource() resource.Resource { | ||
return &Resource{} | ||
} | ||
|
||
// Resource is Defined.net Nebula host resource. | ||
type Resource struct { | ||
client definednet.Client | ||
} | ||
|
||
var _ resource.Resource = (*Resource)(nil) | ||
var _ resource.ResourceWithConfigure = (*Resource)(nil) | ||
var _ resource.ResourceWithImportState = (*Resource)(nil) | ||
|
||
// Configure configures the resource. | ||
func (r *Resource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||
if req.ProviderData == nil { | ||
return | ||
} | ||
|
||
client, ok := req.ProviderData.(definednet.Client) | ||
if !ok { | ||
resp.Diagnostics.AddError("Invalid Configuration", "The provider specifies an invalid client type") | ||
return | ||
} | ||
|
||
r.client = client | ||
} | ||
|
||
// Metadata returns the resource's metadata. | ||
func (r *Resource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { | ||
resp.TypeName = fmt.Sprintf("%s_host", req.ProviderTypeName) | ||
} | ||
|
||
// Schema returns the resource's configuration schema. | ||
func (r *Resource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { | ||
resp.Schema = Schema | ||
} | ||
|
||
// Create creates Nebula hosts on Defined.net control plane. | ||
func (r *Resource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
var state State | ||
|
||
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
var tags []string | ||
resp.Diagnostics.Append(state.Tags.ElementsAs(ctx, &tags, false)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
host, err := definednet.CreateHost(ctx, r.client, definednet.CreateHostRequest{ | ||
NetworkID: state.NetworkID.ValueString(), | ||
RoleID: state.RoleID.ValueString(), | ||
Name: state.Name.ValueString(), | ||
StaticAddresses: []string{}, | ||
ListenPort: 0, | ||
IsLighthouse: false, | ||
IsRelay: false, | ||
Tags: tags, | ||
}) | ||
|
||
if err != nil { | ||
resp.Diagnostics.AddError("Request Failure", err.Error()) | ||
return | ||
} | ||
|
||
state.ID = types.StringValue(host.ID) | ||
state.IPAddress = types.StringValue(host.IPAddress) | ||
|
||
tflog.Trace(ctx, "created Defined.net host", map[string]any{ | ||
"id": state.ID.String(), | ||
"network_id": state.NetworkID.String(), | ||
"role_id": state.RoleID.String(), | ||
"name": state.Name.String(), | ||
"tags": state.Tags.String(), | ||
}) | ||
|
||
code, err := definednet.CreateEnrollmentCode(ctx, r.client, definednet.CreateEnrollmentCodeRequest{ | ||
ID: state.ID.ValueString(), | ||
}) | ||
|
||
if err != nil { | ||
resp.Diagnostics.AddError("Request Failure", err.Error()) | ||
return | ||
} | ||
|
||
state.EnrollmentCode = types.StringValue(code.Code) | ||
|
||
tflog.Trace(ctx, "created Defined.net enrollment code", map[string]any{ | ||
"id": state.ID.String(), | ||
}) | ||
|
||
resp.Diagnostics.Append(resp.State.Set(ctx, state)...) | ||
} | ||
|
||
// Delete deletes Nebula hosts from Defined.net control plane. | ||
func (r *Resource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||
var state State | ||
|
||
resp.Diagnostics.Append(req.State.Get(ctx, &state)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
if err := definednet.DeleteHost(ctx, r.client, definednet.DeleteHostRequest{ | ||
ID: state.ID.ValueString(), | ||
}); err != nil { | ||
resp.Diagnostics.AddError("Request Failure", err.Error()) | ||
} | ||
} | ||
|
||
// Read reads Nebula hosts from Defined.net control plane. | ||
func (r *Resource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
var state State | ||
|
||
resp.Diagnostics.Append(req.State.Get(ctx, &state)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
host, err := definednet.GetHost(ctx, r.client, definednet.GetHostRequest{ | ||
ID: state.ID.ValueString(), | ||
}) | ||
|
||
if err != nil { | ||
resp.Diagnostics.AddError("Request Failure", err.Error()) | ||
return | ||
} | ||
|
||
state.Name = types.StringValue(host.Name) | ||
state.NetworkID = types.StringValue(host.NetworkID) | ||
state.RoleID = types.StringValue(host.RoleID) | ||
|
||
tags, diags := types.ListValueFrom(ctx, types.StringType, host.Tags) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
state.Tags = tags | ||
|
||
resp.Diagnostics.Append(resp.State.Set(ctx, state)...) | ||
|
||
tflog.Trace(ctx, "refreshed Defined.net host", map[string]any{ | ||
"id": state.ID.String(), | ||
"network_id": state.NetworkID.String(), | ||
"role_id": state.RoleID.String(), | ||
"name": state.Name.String(), | ||
"tags": state.Tags.String(), | ||
}) | ||
} | ||
|
||
// Update updates Nebula hosts on Defined.net control plane. | ||
func (r *Resource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { | ||
var current, next State | ||
|
||
resp.Diagnostics.Append(req.State.Get(ctx, ¤t)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
resp.Diagnostics.Append(req.Plan.Get(ctx, &next)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
var tags []string | ||
resp.Diagnostics.Append(next.Tags.ElementsAs(ctx, &tags, false)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
host, err := definednet.UpdateHost(ctx, r.client, definednet.UpdateHostRequest{ | ||
ID: current.ID.ValueString(), | ||
RoleID: next.RoleID.ValueString(), | ||
Name: next.Name.ValueString(), | ||
StaticAddresses: []string{}, | ||
ListenPort: 0, | ||
Tags: tags, | ||
}) | ||
|
||
if err != nil { | ||
resp.Diagnostics.AddError("Request Failure", err.Error()) | ||
return | ||
} | ||
|
||
next.ID = types.StringValue(host.ID) | ||
next.IPAddress = types.StringValue(host.IPAddress) | ||
next.EnrollmentCode = current.EnrollmentCode | ||
|
||
resp.Diagnostics.Append(resp.State.Set(ctx, next)...) | ||
|
||
tflog.Trace(ctx, "updated Defined.net host", map[string]any{ | ||
"id": next.ID.String(), | ||
"network_id": next.NetworkID.String(), | ||
"role_id": next.RoleID.String(), | ||
"name": next.Name.String(), | ||
"tags": next.Tags.String(), | ||
}) | ||
} | ||
|
||
// ImportState imports Nebula hosts from Defined.net control plane. | ||
func (r *Resource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { | ||
host, err := definednet.GetHost(ctx, r.client, definednet.GetHostRequest{ | ||
ID: req.ID, | ||
}) | ||
|
||
if err != nil { | ||
resp.Diagnostics.AddError("Request Failure", err.Error()) | ||
return | ||
} | ||
|
||
tags, diags := types.ListValueFrom(ctx, types.StringType, host.Tags) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
state := State{ | ||
ID: types.StringValue(host.ID), | ||
Name: types.StringValue(host.Name), | ||
NetworkID: types.StringValue(host.NetworkID), | ||
RoleID: types.StringValue(host.RoleID), | ||
IPAddress: types.StringValue(host.IPAddress), | ||
EnrollmentCode: types.StringNull(), | ||
Tags: tags, | ||
} | ||
|
||
resp.Diagnostics.Append(resp.State.Set(ctx, state)...) | ||
|
||
tflog.Trace(ctx, "imported Defined.net host", map[string]any{ | ||
"id": state.ID.String(), | ||
"network_id": state.NetworkID.String(), | ||
"role_id": state.RoleID.String(), | ||
"name": state.Name.String(), | ||
"tags": state.Tags.String(), | ||
}) | ||
} |
Oops, something went wrong.