Skip to content

Commit

Permalink
Add partial support for import server
Browse files Browse the repository at this point in the history
Running

```
terraform import hpegl_pc_server.test 126fd201-9e6e-5e31-9ffb-a766265b1fd3,697e8cbf-df7e-570c-a3c7-912d4ce8375a
```

will partially update the state file. Some fields are missing

* esx_root_credential_id
* ilo_admin_credential_id
* server_network

these fields are not currently retrievable via the API, so they will be set to
`null` in the state. This will lead to an error if a "terraform apply" is
subsequently run, unless these fields are manually tweaked.

This means that "terraform import" for server resources is only partially
supported.
  • Loading branch information
stuart-mclaren-hpe committed Jan 22, 2025
1 parent 5817bc1 commit c647587
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 25 deletions.
112 changes: 87 additions & 25 deletions internal/resources/server/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"path"
"strings"

"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/async"
"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/client"
Expand Down Expand Up @@ -247,18 +248,6 @@ func doRead(
return
}

// If this doesn't match, something is wrong
if *hypervisorClusterID != (*dataP).HypervisorHost.HypervisorClusterId.ValueString() {
(*diagsP).AddError(
"error reading server",
"'hypervisor cluster id' mismatch "+
(*dataP).HypervisorHost.HypervisorClusterId.ValueString()+
" != "+*hypervisorClusterID,
)

return
}

hypervisorHostIP := server.GetHypervisorHost().GetHypervisorHostIp()
if hypervisorHostIP == nil {
(*diagsP).AddError(
Expand All @@ -269,18 +258,6 @@ func doRead(
return
}

// If this doesn't match, something is wrong
if *hypervisorHostIP != (*dataP).HypervisorHost.HypervisorHostIp.ValueString() {
(*diagsP).AddError(
"error reading server",
"'hypervisor host ip' mismatch "+
(*dataP).HypervisorHost.HypervisorHostIp.ValueString()+
" != "+*hypervisorHostIP,
)

return
}

hypervisorClusterName := server.GetHypervisorHost().GetHypervisorClusterName()
if hypervisorClusterName == nil {
(*diagsP).AddError(
Expand Down Expand Up @@ -330,6 +307,62 @@ func doRead(

(*dataP).HypervisorHost = hypervisorHost

iloNetInfo := server.GetIloNetworkInfo()
if iloNetInfo == nil {
(*diagsP).AddError(
"error reading server",
"'ilo network info' is nil",
)

return
}
iloGateway := server.GetIloNetworkInfo().GetGateway()
if iloGateway == nil {
(*diagsP).AddError(
"error reading server",
"'ilo network info gateway' is nil",
)

return
}

iloIP := server.GetIloNetworkInfo().GetIloIp()
if iloIP == nil {
(*diagsP).AddError(
"error reading server",
"'ilo network info ip address' is nil",
)

return
}

iloSubnetMask := server.GetIloNetworkInfo().GetSubnetMask()
if iloSubnetMask == nil {
(*diagsP).AddError(
"error reading server",
"'ilo network info subnet mask' is nil",
)

return
}

value = map[string]attr.Value{
"gateway": types.StringValue(*iloGateway),
"ilo_ip": types.StringValue(*iloIP),
"subnet_mask": types.StringValue(*iloSubnetMask),
}

iloNetworkInfo, diags := NewIloNetworkInfoValue(
(*dataP).IloNetworkInfo.AttributeTypes(ctx), value,
)

(*diagsP).Append(diags...)
if (*diagsP).HasError() {
return
}

(*dataP).IloNetworkInfo = iloNetworkInfo

if server.GetSerialNumber() == nil {
(*diagsP).AddError(
"error reading server",
Expand Down Expand Up @@ -574,10 +607,39 @@ func (r *Resource) Delete(
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

// Import only grants access to a single "ID" parameter. Therefore, we have to
// combine the "hci_cluster_uuid" and datastore "id" values into the single
// req.ID string
func parseImportID(
id string,
) (systemID string, clusterID string, error error) {
params := strings.Split(id, ",")
if len(params) != 2 || params[0] == "" || params[1] == "" {
return "", "", errors.New("invalid import ID format")
}

return params[0], params[1], nil
}

func (r *Resource) ImportState(
ctx context.Context,
req resource.ImportStateRequest,
resp *resource.ImportStateResponse,
) {
resource.ImportStatePassthroughID(ctx, tfpath.Root("id"), req, resp)
systemID, serverID, err := parseImportID(req.ID)
if err != nil {
resp.Diagnostics.AddError(
"import has invalid server id format",
"Provided import ID \""+req.ID+"\" is invalid. "+
"Format must be \"<system_id>,<server_id>\". For example: "+
"126fd201-9e6e-5e31-9ffb-a766265b1fd3,697e8cbf-df7e-570c-a3c7-912d4ce8375a",
)

return
}

diags := resp.State.SetAttribute(ctx, tfpath.Root("id"), serverID)
resp.Diagnostics.Append(diags...)
diags = resp.State.SetAttribute(ctx, tfpath.Root("system_id"), systemID)
resp.Diagnostics.Append(diags...)
}
67 changes: 67 additions & 0 deletions test/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package acceptance

import (
"fmt"
"regexp"
"testing"

"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/provider"
Expand Down Expand Up @@ -254,6 +255,72 @@ func TestAccServerResource(t *testing.T) {
testAccCheckResourceDestroyed("hpegl_pc_server.test"),
),
},
{
// Import
Check: checkFn,
Config: config,
ImportState: true,
ResourceName: "hpegl_pc_server.test",
ImportStateId: "126fd201-9e6e-5e31-9ffb-a766265b1fd3,697e8cbf-df7e-570c-a3c7-912d4ce8375a",
ImportStatePersist: true,
},
/*
TODO: (API) This test cannot currently pass.
See FF-31582 FF-31587 FF-31581 PC-6095 etc
{
// Check post import state matches the resource config
// e.g. verfies 'name' in state matches 'name' in config
Config: config,
Check: checkFn,
ExpectNonEmptyPlan: false,
},
*/
},
})
}

func TestAccServerImportBadId(t *testing.T) {
config := providerConfig + `
resource "hpegl_pc_server" "test" {
system_id = "126fd201-9e6e-5e31-9ffb-a766265b1fd3"
esx_root_credential_id = "cccfcad1-85b7-4162-b16e-f7cadc2c46b5"
ilo_admin_credential_id = "dddfcad1-85b7-4162-b16e-f7cadc2c46b5"
hypervisor_host = {
hypervisor_cluster_id = "acd4daea-e5e3-5f35-8be3-ce4a4b6d946c"
hypervisor_host_ip = "16.182.105.217"
}
ilo_network_info = {
ilo_ip = "16.182.105.216"
gateway = "16.182.104.1"
subnet_mask = "255.255.248.0"
}
server_network = [
{
esx_ip_address = "10.0.0.88"
data_ip_infos = [
{
ip_address = "16.182.105.217"
}
]
}
]
}
`

expected := `import has invalid server id format(.|\n)*698de955-87b5-5fe6-b683-78c3948beede`
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
// Import
ExpectError: regexp.MustCompile(expected),
Config: config,
ImportState: true,
ResourceName: "hpegl_pc_server.test",
// Invalid id (not "<cluster id>,<datastore id>")
ImportStateId: "698de955-87b5-5fe6-b683-78c3948beede",
ImportStatePersist: true,
},
},
})
}

0 comments on commit c647587

Please sign in to comment.