Skip to content

Commit

Permalink
Add initial 'server' resource code
Browse files Browse the repository at this point in the history
Future changes will add API support for creating and deleting
servers. Once that support is available we can have full support
in the provider for managing servers. For now, we add what we
can, mainly reading.
  • Loading branch information
stuart-mclaren-hpe committed Aug 26, 2024
1 parent 9c3b44d commit aebd8ef
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 0 deletions.
2 changes: 2 additions & 0 deletions internal/provider/experimental_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package provider
import (
"context"
"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/resources/datastore"
"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/resources/server"
"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/resources/hypervisorcluster"
"github.com/hashicorp/terraform-plugin-framework/resource"
)
Expand All @@ -18,5 +19,6 @@ func (p *PCBeProvider) Resources(
return []func() resource.Resource{
datastore.NewResource,
hypervisorcluster.NewResource,
server.NewResource,
}
}
207 changes: 207 additions & 0 deletions internal/resources/server/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package server

import (
"context"

"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/client"
"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/sdk/systems/privatecloudbusiness"
"github.com/hashicorp/terraform-plugin-framework/diag"
tfpath "github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
)

// Ensure provider defined types fully satisfy framework interfaces.
var (
_ resource.Resource = &Resource{}
_ resource.ResourceWithImportState = &Resource{}
)

func NewResource() resource.Resource {
return &Resource{}
}

// Resource defines the resource implementation.
type Resource struct {
client *client.PCBeClient
}

func (r *Resource) Metadata(
ctx context.Context,
req resource.MetadataRequest,
resp *resource.MetadataResponse,
) {
resp.TypeName = req.ProviderTypeName + "_server"
}

func (r *Resource) Schema(
ctx context.Context,
req resource.SchemaRequest,
resp *resource.SchemaResponse,
) {
resp.Schema = ServerResourceSchema(ctx)
}

func (r *Resource) Configure(
ctx context.Context,
req resource.ConfigureRequest,
resp *resource.ConfigureResponse,
) {
if req.ProviderData == nil {
return
}

r.client = req.ProviderData.(*client.PCBeClient)
}

func doRead(
ctx context.Context,
client client.PCBeClient,
dataP *ServerModel,
diagsP *diag.Diagnostics,
) {
serverID := (*dataP).Id.ValueString()
systemID := (*dataP).SystemId.ValueString()

sysClient, _, err := client.NewSysClient(ctx)
if err != nil {
(*diagsP).AddError(
"error reading server",
"unexpected error: "+err.Error(),
)

return
}

grc := &privatecloudbusiness.
V1beta1SystemsItemServersWithServerItemRequestBuilderGetRequestConfiguration{}
server, err := sysClient.PrivateCloudBusiness().
V1beta1().
Systems().
ById(systemID).
Servers().
ByServerId(serverID).
GetAsWithServerGetResponse(ctx, grc)
if err != nil {
(*diagsP).AddError(
"error reading server",
"get server by ID failed: "+err.Error(),
)

return
}

if server.GetId() == nil {
(*diagsP).AddError(
"error reading server",
"'id' is nil",
)

return
}

if server.GetName() == nil {
(*diagsP).AddError(
"error reading server",
"'name' is nil",
)

return
}

(*dataP).Name = types.StringValue(*(server.GetName()))
}

func doCreate(
_ context.Context,
_ client.PCBeClient,
dataP *ServerModel,
_ *diag.Diagnostics,
) {
// For now, just set the ID to a known value
(*dataP).Id = types.StringValue("697e8cbf-df7e-570c-a3c7-912d4ce8375a")
}

// TODO: (API) Implement create when server create API is implemented
func (r *Resource) Create(
ctx context.Context,
req resource.CreateRequest,
resp *resource.CreateResponse,
) {
var data ServerModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

doCreate(ctx, *r.client, &data, &resp.Diagnostics)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

doRead(ctx, *r.client, &data, &resp.Diagnostics)
if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *Resource) Read(
ctx context.Context,
req resource.ReadRequest,
resp *resource.ReadResponse,
) {
var data ServerModel

resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

doRead(ctx, *r.client, &data, &resp.Diagnostics)

if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *Resource) Update(
ctx context.Context,
req resource.UpdateRequest,
resp *resource.UpdateResponse,
) {
tflog.Error(ctx, "update server is not implemented")
}

// TODO: (API) Implement delete when server delete API is implemented
func (r *Resource) Delete(
ctx context.Context,
req resource.DeleteRequest,
resp *resource.DeleteResponse,
) {
var data ServerModel

// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// For now, just delete the state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *Resource) ImportState(
ctx context.Context,
req resource.ImportStateRequest,
resp *resource.ImportStateResponse,
) {
resource.ImportStatePassthroughID(ctx, tfpath.Root("id"), req, resp)
}

0 comments on commit aebd8ef

Please sign in to comment.