From 28ea1f7a912b8e617a811ebd04bef5b48bc216c2 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 9 Dec 2024 11:49:39 +0000 Subject: [PATCH] add hypervisor server: ilo networking Add ilo networking stanza to server resource: ``` ilo_network_info = { ilo_ip = "16.182.105.216" gateway = "16.182.104.1" subnet_mask = "255.255.248.0" } ``` Note that naming is inconsistent, so we need to map between a list of this format in the POST /add-hypervisor-server http body: ``` "iloMgmtIpInfo": { "ipAddress": "1.2.3.4", "subnetMask": "255.255.255.0", "gateway": "1.2.3.1" } ``` and this (non-list) format in the GET /server http response body: ``` "iloNetworkInfo": { "iloIp": "1.2.3.4", "subnetMask": "255.255.255.0", "gateway": "1.2.3.1" }, ``` --- examples/main.tf | 5 + internal/resources/server/resource.go | 111 +++-- .../resources/server/server_resource_gen.go | 462 ++++++++++++++++++ .../fixtures/servers/create/post.json | 2 +- test/server/server_test.go | 36 ++ 5 files changed, 567 insertions(+), 49 deletions(-) diff --git a/examples/main.tf b/examples/main.tf index be4d599..a657a1f 100644 --- a/examples/main.tf +++ b/examples/main.tf @@ -35,6 +35,11 @@ resource "hpegl_pc_server" "test" { 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 = [ { data_ip_infos = [ diff --git a/internal/resources/server/resource.go b/internal/resources/server/resource.go index a26f8b7..c30e48b 100644 --- a/internal/resources/server/resource.go +++ b/internal/resources/server/resource.go @@ -15,7 +15,6 @@ import ( 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-framework/types/basetypes" "github.com/hashicorp/terraform-plugin-log/tflog" ) @@ -38,7 +37,7 @@ type Resource struct { // input configuration and returns a slice of server network data which can be // used in a POST request to the PCBe API to create a new server // TODO: (API) Issue FF-31496 will prevent this from working currently. -func parseNetworksToPostFormat(serverNetworks basetypes.ListValue) ( +func parseNetworksToPostFormat(dataP *ServerModel) ( []privatecloudbusiness. V1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetworkable, error, @@ -46,44 +45,70 @@ func parseNetworksToPostFormat(serverNetworks basetypes.ListValue) ( var postRequestNetworks []privatecloudbusiness. V1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetworkable + serverNetworks := (*dataP).ServerNetwork + if serverNetworks.IsNull() { + msg := "server network list is null" + + return nil, errors.New(msg) + + } + networks := serverNetworks.Elements() - for _, network := range networks { - serverNetwork, ok := network.(ServerNetworkValue) - if !ok { - msg := "server network element is not a ServerNetworkValue" - - return nil, errors.New(msg) - } - - infos := serverNetwork.DataIpInfos.Elements() - if len(infos) != 1 { - msg := "server network must be an array of length 1" - - return nil, errors.New(msg) - } - - dataIPInfosValue, ok := infos[0].(DataIpInfosValue) - if !ok { - msg := "data ip info element is not a DataIpInfosValue" - - return nil, errors.New(msg) - } - - ip := dataIPInfosValue.IpAddress.ValueString() - net := privatecloudbusiness. - NewV1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetwork() - dataIPInfos := privatecloudbusiness. - NewV1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetwork_dataIpInfos() - dataIPInfos.SetIpAddress(&ip) - dataIps := []privatecloudbusiness. - V1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetwork_dataIpInfosable{ - dataIPInfos, - } - net.SetDataIpInfos(dataIps) - postRequestNetworks = []privatecloudbusiness. - V1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetworkable{net} + if len(networks) != 1 { + msg := "server network list should be of length 1" + + return nil, errors.New(msg) } + serverNetwork, ok := networks[0].(ServerNetworkValue) + if !ok { + msg := "server network element is not a ServerNetworkValue" + + return nil, errors.New(msg) + } + + infos := serverNetwork.DataIpInfos.Elements() + if len(infos) != 1 { + msg := "server network must be an array of length 1" + + return nil, errors.New(msg) + } + + dataIPInfosValue, ok := infos[0].(DataIpInfosValue) + if !ok { + msg := "data ip info element is not a DataIpInfosValue" + + return nil, errors.New(msg) + } + + ip := dataIPInfosValue.IpAddress.ValueString() + dataIPInfos := privatecloudbusiness. + NewV1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetwork_dataIpInfos() + dataIPInfos.SetIpAddress(&ip) + dataIps := []privatecloudbusiness. + V1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetwork_dataIpInfosable{ + dataIPInfos, + } + + iloIPInfos := privatecloudbusiness.NewV1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetwork_iloMgmtIpInfo() + + iloIP := (*dataP).IloNetworkInfo.IloIp.ValueString() + iloIPInfos.SetIpAddress(&iloIP) + + iloSubnetMask := (*dataP).IloNetworkInfo.SubnetMask.ValueString() + iloIPInfos.SetSubnetMask(&iloSubnetMask) + + iloGateway := (*dataP).IloNetworkInfo.Gateway.ValueString() + iloIPInfos.SetGateway(&iloGateway) + + net := privatecloudbusiness. + NewV1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetwork() + net.SetDataIpInfos(dataIps) + net.SetIloMgmtIpInfo(iloIPInfos) + + postRequestNetworks = []privatecloudbusiness. + V1beta1SystemsItemAddHypervisorServersPostRequestBody_serverNetworkable{net} + return postRequestNetworks, nil } @@ -338,16 +363,6 @@ func doCreate( esxRootCredentialID := (*dataP).EsxRootCredentialId.ValueString() systemID := (*dataP).SystemId.ValueString() iloAdminCredentialID := (*dataP).IloAdminCredentialId.ValueString() - serverNetworks := (*dataP).ServerNetwork - if serverNetworks.IsNull() { - (*diagsP).AddError( - "error adding hypervisor server", - "server network list is null", - ) - - return - - } prc := privatecloudbusiness. V1beta1SystemsItemAddHypervisorServersRequestBuilderPostRequestConfiguration{} prb := privatecloudbusiness. @@ -356,7 +371,7 @@ func doCreate( prb.SetIloAdminCredentialId(&iloAdminCredentialID) prb.SetHypervisorClusterId(&hciClusterUUID) - postRequestNetworks, err := parseNetworksToPostFormat(serverNetworks) + postRequestNetworks, err := parseNetworksToPostFormat(dataP) if err != nil { (*diagsP).AddError( "error adding hypervisor server", diff --git a/internal/resources/server/server_resource_gen.go b/internal/resources/server/server_resource_gen.go index 95fa7cc..e1351ea 100644 --- a/internal/resources/server/server_resource_gen.go +++ b/internal/resources/server/server_resource_gen.go @@ -64,6 +64,33 @@ func ServerResourceSchema(ctx context.Context) schema.Schema { Description: "ID corresponding to the ilo admin credential", MarkdownDescription: "ID corresponding to the ilo admin credential", }, + "ilo_network_info": schema.SingleNestedAttribute{ + Attributes: map[string]schema.Attribute{ + "gateway": schema.StringAttribute{ + Required: true, + Description: "IP address of ilo gateway", + MarkdownDescription: "IP address of ilo gateway", + }, + "ilo_ip": schema.StringAttribute{ + Required: true, + Description: "IP address of ilo", + MarkdownDescription: "IP address of ilo", + }, + "subnet_mask": schema.StringAttribute{ + Required: true, + Description: "subnet of ilo gateway, eg 255.255.255.0", + MarkdownDescription: "subnet of ilo gateway, eg 255.255.255.0", + }, + }, + CustomType: IloNetworkInfoType{ + ObjectType: types.ObjectType{ + AttrTypes: IloNetworkInfoValue{}.AttributeTypes(ctx), + }, + }, + Required: true, + Description: "ilo network information", + MarkdownDescription: "ilo network information", + }, "name": schema.StringAttribute{ Computed: true, Description: "A system specified name for the resource.", @@ -121,6 +148,7 @@ type ServerModel struct { HypervisorHost HypervisorHostValue `tfsdk:"hypervisor_host"` Id types.String `tfsdk:"id"` IloAdminCredentialId types.String `tfsdk:"ilo_admin_credential_id"` + IloNetworkInfo IloNetworkInfoValue `tfsdk:"ilo_network_info"` Name types.String `tfsdk:"name"` SerialNumber types.String `tfsdk:"serial_number"` ServerNetwork types.List `tfsdk:"server_network"` @@ -671,6 +699,440 @@ func (v HypervisorHostValue) AttributeTypes(ctx context.Context) map[string]attr } } +var _ basetypes.ObjectTypable = IloNetworkInfoType{} + +type IloNetworkInfoType struct { + basetypes.ObjectType +} + +func (t IloNetworkInfoType) Equal(o attr.Type) bool { + other, ok := o.(IloNetworkInfoType) + + if !ok { + return false + } + + return t.ObjectType.Equal(other.ObjectType) +} + +func (t IloNetworkInfoType) String() string { + return "IloNetworkInfoType" +} + +func (t IloNetworkInfoType) ValueFromObject(ctx context.Context, in basetypes.ObjectValue) (basetypes.ObjectValuable, diag.Diagnostics) { + var diags diag.Diagnostics + + attributes := in.Attributes() + + gatewayAttribute, ok := attributes["gateway"] + + if !ok { + diags.AddError( + "Attribute Missing", + `gateway is missing from object`) + + return nil, diags + } + + gatewayVal, ok := gatewayAttribute.(basetypes.StringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`gateway expected to be basetypes.StringValue, was: %T`, gatewayAttribute)) + } + + iloIpAttribute, ok := attributes["ilo_ip"] + + if !ok { + diags.AddError( + "Attribute Missing", + `ilo_ip is missing from object`) + + return nil, diags + } + + iloIpVal, ok := iloIpAttribute.(basetypes.StringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`ilo_ip expected to be basetypes.StringValue, was: %T`, iloIpAttribute)) + } + + subnetMaskAttribute, ok := attributes["subnet_mask"] + + if !ok { + diags.AddError( + "Attribute Missing", + `subnet_mask is missing from object`) + + return nil, diags + } + + subnetMaskVal, ok := subnetMaskAttribute.(basetypes.StringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`subnet_mask expected to be basetypes.StringValue, was: %T`, subnetMaskAttribute)) + } + + if diags.HasError() { + return nil, diags + } + + return IloNetworkInfoValue{ + Gateway: gatewayVal, + IloIp: iloIpVal, + SubnetMask: subnetMaskVal, + state: attr.ValueStateKnown, + }, diags +} + +func NewIloNetworkInfoValueNull() IloNetworkInfoValue { + return IloNetworkInfoValue{ + state: attr.ValueStateNull, + } +} + +func NewIloNetworkInfoValueUnknown() IloNetworkInfoValue { + return IloNetworkInfoValue{ + state: attr.ValueStateUnknown, + } +} + +func NewIloNetworkInfoValue(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) (IloNetworkInfoValue, diag.Diagnostics) { + var diags diag.Diagnostics + + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/521 + ctx := context.Background() + + for name, attributeType := range attributeTypes { + attribute, ok := attributes[name] + + if !ok { + diags.AddError( + "Missing IloNetworkInfoValue Attribute Value", + "While creating a IloNetworkInfoValue value, a missing attribute value was detected. "+ + "A IloNetworkInfoValue must contain values for all attributes, even if null or unknown. "+ + "This is always an issue with the provider and should be reported to the provider developers.\n\n"+ + fmt.Sprintf("IloNetworkInfoValue Attribute Name (%s) Expected Type: %s", name, attributeType.String()), + ) + + continue + } + + if !attributeType.Equal(attribute.Type(ctx)) { + diags.AddError( + "Invalid IloNetworkInfoValue Attribute Type", + "While creating a IloNetworkInfoValue value, an invalid attribute value was detected. "+ + "A IloNetworkInfoValue must use a matching attribute type for the value. "+ + "This is always an issue with the provider and should be reported to the provider developers.\n\n"+ + fmt.Sprintf("IloNetworkInfoValue Attribute Name (%s) Expected Type: %s\n", name, attributeType.String())+ + fmt.Sprintf("IloNetworkInfoValue Attribute Name (%s) Given Type: %s", name, attribute.Type(ctx)), + ) + } + } + + for name := range attributes { + _, ok := attributeTypes[name] + + if !ok { + diags.AddError( + "Extra IloNetworkInfoValue Attribute Value", + "While creating a IloNetworkInfoValue value, an extra attribute value was detected. "+ + "A IloNetworkInfoValue must not contain values beyond the expected attribute types. "+ + "This is always an issue with the provider and should be reported to the provider developers.\n\n"+ + fmt.Sprintf("Extra IloNetworkInfoValue Attribute Name: %s", name), + ) + } + } + + if diags.HasError() { + return NewIloNetworkInfoValueUnknown(), diags + } + + gatewayAttribute, ok := attributes["gateway"] + + if !ok { + diags.AddError( + "Attribute Missing", + `gateway is missing from object`) + + return NewIloNetworkInfoValueUnknown(), diags + } + + gatewayVal, ok := gatewayAttribute.(basetypes.StringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`gateway expected to be basetypes.StringValue, was: %T`, gatewayAttribute)) + } + + iloIpAttribute, ok := attributes["ilo_ip"] + + if !ok { + diags.AddError( + "Attribute Missing", + `ilo_ip is missing from object`) + + return NewIloNetworkInfoValueUnknown(), diags + } + + iloIpVal, ok := iloIpAttribute.(basetypes.StringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`ilo_ip expected to be basetypes.StringValue, was: %T`, iloIpAttribute)) + } + + subnetMaskAttribute, ok := attributes["subnet_mask"] + + if !ok { + diags.AddError( + "Attribute Missing", + `subnet_mask is missing from object`) + + return NewIloNetworkInfoValueUnknown(), diags + } + + subnetMaskVal, ok := subnetMaskAttribute.(basetypes.StringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`subnet_mask expected to be basetypes.StringValue, was: %T`, subnetMaskAttribute)) + } + + if diags.HasError() { + return NewIloNetworkInfoValueUnknown(), diags + } + + return IloNetworkInfoValue{ + Gateway: gatewayVal, + IloIp: iloIpVal, + SubnetMask: subnetMaskVal, + state: attr.ValueStateKnown, + }, diags +} + +func NewIloNetworkInfoValueMust(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) IloNetworkInfoValue { + object, diags := NewIloNetworkInfoValue(attributeTypes, attributes) + + if diags.HasError() { + // This could potentially be added to the diag package. + diagsStrings := make([]string, 0, len(diags)) + + for _, diagnostic := range diags { + diagsStrings = append(diagsStrings, fmt.Sprintf( + "%s | %s | %s", + diagnostic.Severity(), + diagnostic.Summary(), + diagnostic.Detail())) + } + + panic("NewIloNetworkInfoValueMust received error(s): " + strings.Join(diagsStrings, "\n")) + } + + return object +} + +func (t IloNetworkInfoType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) { + if in.Type() == nil { + return NewIloNetworkInfoValueNull(), nil + } + + if !in.Type().Equal(t.TerraformType(ctx)) { + return nil, fmt.Errorf("expected %s, got %s", t.TerraformType(ctx), in.Type()) + } + + if !in.IsKnown() { + return NewIloNetworkInfoValueUnknown(), nil + } + + if in.IsNull() { + return NewIloNetworkInfoValueNull(), nil + } + + attributes := map[string]attr.Value{} + + val := map[string]tftypes.Value{} + + err := in.As(&val) + + if err != nil { + return nil, err + } + + for k, v := range val { + a, err := t.AttrTypes[k].ValueFromTerraform(ctx, v) + + if err != nil { + return nil, err + } + + attributes[k] = a + } + + return NewIloNetworkInfoValueMust(IloNetworkInfoValue{}.AttributeTypes(ctx), attributes), nil +} + +func (t IloNetworkInfoType) ValueType(ctx context.Context) attr.Value { + return IloNetworkInfoValue{} +} + +var _ basetypes.ObjectValuable = IloNetworkInfoValue{} + +type IloNetworkInfoValue struct { + Gateway basetypes.StringValue `tfsdk:"gateway"` + IloIp basetypes.StringValue `tfsdk:"ilo_ip"` + SubnetMask basetypes.StringValue `tfsdk:"subnet_mask"` + state attr.ValueState +} + +func (v IloNetworkInfoValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) { + attrTypes := make(map[string]tftypes.Type, 3) + + var val tftypes.Value + var err error + + attrTypes["gateway"] = basetypes.StringType{}.TerraformType(ctx) + attrTypes["ilo_ip"] = basetypes.StringType{}.TerraformType(ctx) + attrTypes["subnet_mask"] = basetypes.StringType{}.TerraformType(ctx) + + objectType := tftypes.Object{AttributeTypes: attrTypes} + + switch v.state { + case attr.ValueStateKnown: + vals := make(map[string]tftypes.Value, 3) + + val, err = v.Gateway.ToTerraformValue(ctx) + + if err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + vals["gateway"] = val + + val, err = v.IloIp.ToTerraformValue(ctx) + + if err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + vals["ilo_ip"] = val + + val, err = v.SubnetMask.ToTerraformValue(ctx) + + if err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + vals["subnet_mask"] = val + + if err := tftypes.ValidateValue(objectType, vals); err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + return tftypes.NewValue(objectType, vals), nil + case attr.ValueStateNull: + return tftypes.NewValue(objectType, nil), nil + case attr.ValueStateUnknown: + return tftypes.NewValue(objectType, tftypes.UnknownValue), nil + default: + panic(fmt.Sprintf("unhandled Object state in ToTerraformValue: %s", v.state)) + } +} + +func (v IloNetworkInfoValue) IsNull() bool { + return v.state == attr.ValueStateNull +} + +func (v IloNetworkInfoValue) IsUnknown() bool { + return v.state == attr.ValueStateUnknown +} + +func (v IloNetworkInfoValue) String() string { + return "IloNetworkInfoValue" +} + +func (v IloNetworkInfoValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { + var diags diag.Diagnostics + + attributeTypes := map[string]attr.Type{ + "gateway": basetypes.StringType{}, + "ilo_ip": basetypes.StringType{}, + "subnet_mask": basetypes.StringType{}, + } + + if v.IsNull() { + return types.ObjectNull(attributeTypes), diags + } + + if v.IsUnknown() { + return types.ObjectUnknown(attributeTypes), diags + } + + objVal, diags := types.ObjectValue( + attributeTypes, + map[string]attr.Value{ + "gateway": v.Gateway, + "ilo_ip": v.IloIp, + "subnet_mask": v.SubnetMask, + }) + + return objVal, diags +} + +func (v IloNetworkInfoValue) Equal(o attr.Value) bool { + other, ok := o.(IloNetworkInfoValue) + + if !ok { + return false + } + + if v.state != other.state { + return false + } + + if v.state != attr.ValueStateKnown { + return true + } + + if !v.Gateway.Equal(other.Gateway) { + return false + } + + if !v.IloIp.Equal(other.IloIp) { + return false + } + + if !v.SubnetMask.Equal(other.SubnetMask) { + return false + } + + return true +} + +func (v IloNetworkInfoValue) Type(ctx context.Context) attr.Type { + return IloNetworkInfoType{ + basetypes.ObjectType{ + AttrTypes: v.AttributeTypes(ctx), + }, + } +} + +func (v IloNetworkInfoValue) AttributeTypes(ctx context.Context) map[string]attr.Type { + return map[string]attr.Type{ + "gateway": basetypes.StringType{}, + "ilo_ip": basetypes.StringType{}, + "subnet_mask": basetypes.StringType{}, + } +} + var _ basetypes.ObjectTypable = ServerNetworkType{} type ServerNetworkType struct { diff --git a/internal/simulator/fixtures/servers/create/post.json b/internal/simulator/fixtures/servers/create/post.json index a391dec..75252b9 100644 --- a/internal/simulator/fixtures/servers/create/post.json +++ b/internal/simulator/fixtures/servers/create/post.json @@ -1 +1 @@ -{"esxRootCredentialId":"cccfcad1-85b7-4162-b16e-f7cadc2c46b5","hypervisorClusterId":"acd4daea-e5e3-5f35-8be3-ce4a4b6d946c","iloAdminCredentialId":"dddfcad1-85b7-4162-b16e-f7cadc2c46b5","serverNetwork":[{"dataIpInfos":[{"ipAddress":"16.182.105.217"}]}]} + {"esxRootCredentialId":"cccfcad1-85b7-4162-b16e-f7cadc2c46b5","hypervisorClusterId":"acd4daea-e5e3-5f35-8be3-ce4a4b6d946c","iloAdminCredentialId":"dddfcad1-85b7-4162-b16e-f7cadc2c46b5","serverNetwork":[{"dataIpInfos":[{"ipAddress":"16.182.105.217"}],"iloMgmtIpInfo":{"gateway":"16.182.104.1","ipAddress":"16.182.105.216","subnetMask":"255.255.248.0"}}]} diff --git a/test/server/server_test.go b/test/server/server_test.go index 8b73107..63a3b81 100644 --- a/test/server/server_test.go +++ b/test/server/server_test.go @@ -83,6 +83,11 @@ func TestAccServerResource(t *testing.T) { 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 = [ { data_ip_infos = [ @@ -117,6 +122,22 @@ func TestAccServerResource(t *testing.T) { "hpegl_pc_server.test", "hypervisor_host.hypervisor_host_ip", ), + resource.TestCheckResourceAttrSet( + "hpegl_pc_server.test", + "ilo_network_info.ilo_ip", + ), + resource.TestCheckResourceAttrSet( + "hpegl_pc_server.test", + "ilo_network_info.gateway", + ), + resource.TestCheckResourceAttrSet( + "hpegl_pc_server.test", + "ilo_network_info.subnet_mask", + ), + resource.TestCheckResourceAttrSet( + "hpegl_pc_server.test", + "hypervisor_host.hypervisor_host_ip", + ), checkUUIDAttr("hpegl_pc_server.test", "id"), checkUUIDAttr("hpegl_pc_server.test", "system_id"), checkUUIDAttr("hpegl_pc_server.test", "esx_root_credential_id"), @@ -172,6 +193,21 @@ func TestAccServerResource(t *testing.T) { "hypervisor_host.id", "530b1894-9bd0-5627-9362-565aff1e5cbd", ), + resource.TestCheckResourceAttr( + "hpegl_pc_server.test", + "ilo_network_info.ilo_ip", + "16.182.105.216", + ), + resource.TestCheckResourceAttr( + "hpegl_pc_server.test", + "ilo_network_info.gateway", + "16.182.104.1", + ), + resource.TestCheckResourceAttr( + "hpegl_pc_server.test", + "ilo_network_info.subnet_mask", + "255.255.248.0", + ), resource.TestCheckResourceAttr( "hpegl_pc_server.test", "hypervisor_host.hypervisor_host_ip",