diff --git a/docs/data-sources/dhcp_fixed_addresses.md b/docs/data-sources/dhcp_fixed_addresses.md
new file mode 100644
index 00000000..092216f6
--- /dev/null
+++ b/docs/data-sources/dhcp_fixed_addresses.md
@@ -0,0 +1,195 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "bloxone_dhcp_fixed_addresses Data Source - terraform-provider-bloxone"
+subcategory: ""
+description: |-
+
+---
+
+# bloxone_dhcp_fixed_addresses (Data Source)
+
+
+
+## Example Usage
+
+```terraform
+# Get DHCP fixed address filtered by an attribute
+data "bloxone_dhcp_fixed_addresses" "example_by_attribute" {
+ filters = {
+ name = "example_fixed_address"
+ }
+}
+
+# Get DHCP fixed address by tag
+data "bloxone_dhcp_fixed_addresses" "example_by_tag" {
+ tag_filters = {
+ location = "site1"
+ }
+}
+
+# Get all fixed address
+data "bloxone_dhcp_fixed_addresses" "example_all" {}
+```
+
+
+## Schema
+
+### Optional
+
+- `filters` (Map of String) Filter are used to return a more specific list of results. Filters can be used to match resources by specific attributes, e.g. name. If you specify multiple filters, the results returned will have only resources that match all the specified filters.
+- `tag_filters` (Map of String) Tag Filters are used to return a more specific list of results filtered by tags. If you specify multiple filters, the results returned will have only resources that match all the specified filters.
+
+### Read-Only
+
+- `results` (Attributes List) (see [below for nested schema](#nestedatt--results))
+
+
+### Nested Schema for `results`
+
+Required:
+
+- `address` (String) The reserved address.
+- `match_type` (String) Indicates how to match the client: * _mac_: match the client MAC address for both IPv4 and IPv6, * _client_text_ or _client_hex_: match the client identifier for IPv4 only, * _relay_text_ or _relay_hex_: match the circuit ID or remote ID in the DHCP relay agent option (82) for IPv4 only, * _duid_: match the DHCP unique identifier, currently match only for IPv6 protocol.
+- `match_value` (String) The value to match.
+
+Optional:
+
+- `comment` (String) The description for the fixed address. May contain 0 to 1024 characters. Can include UTF-8.
+- `dhcp_options` (Attributes List) The list of DHCP options. May be either a specific option or a group of options. (see [below for nested schema](#nestedatt--results--dhcp_options))
+- `disable_dhcp` (Boolean) Optional. _true_ to disable object. The fixed address is converted to an exclusion when generating configuration. Defaults to _false_.
+- `header_option_filename` (String) The configuration for header option filename field.
+- `header_option_server_address` (String) The configuration for header option server address field.
+- `header_option_server_name` (String) The configuration for header option server name field.
+- `hostname` (String) The DHCP host name associated with this fixed address. It is of FQDN type and it defaults to empty.
+- `inheritance_parent` (String) The resource identifier.
+- `inheritance_sources` (Attributes) (see [below for nested schema](#nestedatt--results--inheritance_sources))
+- `ip_space` (String) The resource identifier.
+- `name` (String) The name of the fixed address. May contain 1 to 256 characters. Can include UTF-8.
+- `tags` (Map of String) The tags for the fixed address in JSON format.
+
+Read-Only:
+
+- `created_at` (String) Time when the object has been created.
+- `id` (String) The resource identifier.
+- `inheritance_assigned_hosts` (Attributes List) The list of the inheritance assigned hosts of the object. (see [below for nested schema](#nestedatt--results--inheritance_assigned_hosts))
+- `parent` (String) The resource identifier.
+- `updated_at` (String) Time when the object has been updated. Equals to _created_at_ if not updated after creation.
+
+
+### Nested Schema for `results.dhcp_options`
+
+Optional:
+
+- `group` (String) The resource identifier.
+- `option_code` (String) The resource identifier.
+- `option_value` (String) The option value.
+- `type` (String) The type of item. Valid values are: * _group_ * _option_
+
+
+
+### Nested Schema for `results.inheritance_sources`
+
+Optional:
+
+- `dhcp_options` (Attributes) (see [below for nested schema](#nestedatt--results--inheritance_sources--dhcp_options))
+- `header_option_filename` (Attributes) (see [below for nested schema](#nestedatt--results--inheritance_sources--header_option_filename))
+- `header_option_server_address` (Attributes) (see [below for nested schema](#nestedatt--results--inheritance_sources--header_option_server_address))
+- `header_option_server_name` (Attributes) (see [below for nested schema](#nestedatt--results--inheritance_sources--header_option_server_name))
+
+
+### Nested Schema for `results.inheritance_sources.dhcp_options`
+
+Optional:
+
+- `action` (String) The inheritance setting. Valid values are: * _inherit_: Use the inherited value. * _block_: Don't use the inherited value. Defaults to _inherit_.
+- `value` (Attributes List) The inherited DHCP option values. (see [below for nested schema](#nestedatt--results--inheritance_sources--dhcp_options--value))
+
+
+### Nested Schema for `results.inheritance_sources.dhcp_options.value`
+
+Optional:
+
+- `action` (String) The inheritance setting. Valid values are: * _inherit_: Use the inherited value. * _block_: Don't use the inherited value. Defaults to _inherit_.
+- `source` (String) The resource identifier.
+- `value` (Attributes) (see [below for nested schema](#nestedatt--results--inheritance_sources--dhcp_options--value--value))
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the object referred to by _source_.
+
+
+### Nested Schema for `results.inheritance_sources.dhcp_options.value.value`
+
+Optional:
+
+- `option` (Attributes) (see [below for nested schema](#nestedatt--results--inheritance_sources--dhcp_options--value--value--option))
+- `overriding_group` (String) The resource identifier.
+
+
+### Nested Schema for `results.inheritance_sources.dhcp_options.value.value.overriding_group`
+
+Optional:
+
+- `group` (String) The resource identifier.
+- `option_code` (String) The resource identifier.
+- `option_value` (String) The option value.
+- `type` (String) The type of item. Valid values are: * _group_ * _option_
+
+
+
+
+
+
+### Nested Schema for `results.inheritance_sources.header_option_filename`
+
+Optional:
+
+- `action` (String) The inheritance setting for a field. Valid values are: * _inherit_: Use the inherited value. * _override_: Use the value set in the object. Defaults to _inherit_.
+- `source` (String) The resource identifier.
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the object referred to by _source_.
+- `value` (String) The inherited value.
+
+
+
+### Nested Schema for `results.inheritance_sources.header_option_server_address`
+
+Optional:
+
+- `action` (String) The inheritance setting for a field. Valid values are: * _inherit_: Use the inherited value. * _override_: Use the value set in the object. Defaults to _inherit_.
+- `source` (String) The resource identifier.
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the object referred to by _source_.
+- `value` (String) The inherited value.
+
+
+
+### Nested Schema for `results.inheritance_sources.header_option_server_name`
+
+Optional:
+
+- `action` (String) The inheritance setting for a field. Valid values are: * _inherit_: Use the inherited value. * _override_: Use the value set in the object. Defaults to _inherit_.
+- `source` (String) The resource identifier.
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the object referred to by _source_.
+- `value` (String) The inherited value.
+
+
+
+
+### Nested Schema for `results.inheritance_assigned_hosts`
+
+Optional:
+
+- `host` (String) The resource identifier.
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the host referred to by _ophid_.
+- `ophid` (String) The on-prem host ID.
diff --git a/docs/data-sources/dhcp_hosts.md b/docs/data-sources/dhcp_hosts.md
new file mode 100644
index 00000000..c249c696
--- /dev/null
+++ b/docs/data-sources/dhcp_hosts.md
@@ -0,0 +1,74 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "bloxone_dhcp_hosts Data Source - terraform-provider-bloxone"
+subcategory: ""
+description: |-
+
+---
+
+# bloxone_dhcp_hosts (Data Source)
+
+
+
+## Example Usage
+
+```terraform
+# Get DHCP Host filtered by an attribute
+data "bloxone_dhcp_hosts" "example_by_name" {
+ filters = {
+ name = "example-host"
+ }
+}
+
+# Get DHCP Host by tag
+data "bloxone_dhcp_hosts" "example_by_tag" {
+ tag_filters = {
+ location = "site1"
+ }
+}
+
+# Get all DHCP hosts
+data "bloxone_dhcp_hosts" "example_all" {}
+```
+
+
+## Schema
+
+### Optional
+
+- `filters` (Map of String) Filter are used to return a more specific list of results. Filters can be used to match resources by specific attributes, e.g. name. If you specify multiple filters, the results returned will have only resources that match all the specified filters.
+- `tag_filters` (Map of String) Tag Filters are used to return a more specific list of results filtered by tags. If you specify multiple filters, the results returned will have only resources that match all the specified filters.
+
+### Read-Only
+
+- `results` (Attributes List) (see [below for nested schema](#nestedatt--results))
+
+
+### Nested Schema for `results`
+
+Optional:
+
+- `associated_server` (Attributes) The DHCP Config Profile for the on-prem host. (see [below for nested schema](#nestedatt--results--associated_server))
+- `ip_space` (String) The resource identifier.
+- `server` (String) The resource identifier.
+- `tags` (Map of String) The tags of the on-prem host in JSON format.
+
+Read-Only:
+
+- `address` (String) The primary IP address of the on-prem host.
+- `anycast_addresses` (List of String) Anycast address configured to the host. Order is not significant.
+- `comment` (String) The description for the on-prem host.
+- `current_version` (String) Current dhcp application version of the host.
+- `id` (String) The resource identifier.
+- `name` (String) The display name of the on-prem host.
+- `ophid` (String) The on-prem host ID.
+- `provider_id` (String) External provider identifier.
+- `type` (String) Defines the type of host. Allowed values: * _bloxone_ddi_: host type is BloxOne DDI, * _microsoft_azure_: host type is Microsoft Azure, * _amazon_web_service_: host type is Amazon Web Services. * _microsoft_active_directory_: host type is Microsoft Active Directory.
+
+
+### Nested Schema for `results.associated_server`
+
+Read-Only:
+
+- `id` (String) The resource identifier.
+- `name` (String) The DHCP Config Profile name.
diff --git a/docs/resources/dhcp_fixed_address.md b/docs/resources/dhcp_fixed_address.md
new file mode 100644
index 00000000..f64d638b
--- /dev/null
+++ b/docs/resources/dhcp_fixed_address.md
@@ -0,0 +1,208 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "bloxone_dhcp_fixed_address Resource - terraform-provider-bloxone"
+subcategory: ""
+description: |-
+
+---
+
+# bloxone_dhcp_fixed_address (Resource)
+
+
+
+## Example Usage
+
+```terraform
+resource "bloxone_ipam_ip_space" "example" {
+ name = "example"
+ comment = "Example IP space created by the terraform provider"
+ tags = {
+ location = "site1"
+ }
+}
+
+resource "bloxone_ipam_address_block" "example" {
+ address = "192.160.0.0"
+ cidr = 16
+ space = bloxone_ipam_ip_space.example.id
+ comment = "Example Address Block created by the terraform provider"
+ tags = {
+ location = "site1"
+ }
+}
+
+resource "bloxone_ipam_subnet" "example" {
+ name = "example"
+ space = bloxone_ipam_ip_space.example.id
+ address = "192.168.1.0"
+ cidr = 24
+ comment = "Example Subnet created by the terraform provider"
+ tags = {
+ location = "site1"
+ }
+}
+
+resource "bloxone_dhcp_fixed_address" "example_fixed_address" {
+ name = "example_fixed_address"
+ address = "192.168.1.1"
+ ip_space = bloxone_ipam_ip_space.example.id
+ match_type = "mac"
+ match_value = "00:00:00:00:00:00"
+ comment = "Example Fixed Address created by the terraform provider"
+ tags = {
+ location : "site1"
+ }
+ depends_on = [bloxone_ipam_subnet.example]
+}
+```
+
+
+## Schema
+
+### Required
+
+- `address` (String) The reserved address.
+- `match_type` (String) Indicates how to match the client: * _mac_: match the client MAC address for both IPv4 and IPv6, * _client_text_ or _client_hex_: match the client identifier for IPv4 only, * _relay_text_ or _relay_hex_: match the circuit ID or remote ID in the DHCP relay agent option (82) for IPv4 only, * _duid_: match the DHCP unique identifier, currently match only for IPv6 protocol.
+- `match_value` (String) The value to match.
+
+### Optional
+
+- `comment` (String) The description for the fixed address. May contain 0 to 1024 characters. Can include UTF-8.
+- `dhcp_options` (Attributes List) The list of DHCP options. May be either a specific option or a group of options. (see [below for nested schema](#nestedatt--dhcp_options))
+- `disable_dhcp` (Boolean) Optional. _true_ to disable object. The fixed address is converted to an exclusion when generating configuration. Defaults to _false_.
+- `header_option_filename` (String) The configuration for header option filename field.
+- `header_option_server_address` (String) The configuration for header option server address field.
+- `header_option_server_name` (String) The configuration for header option server name field.
+- `hostname` (String) The DHCP host name associated with this fixed address. It is of FQDN type and it defaults to empty.
+- `inheritance_parent` (String) The resource identifier.
+- `inheritance_sources` (Attributes) (see [below for nested schema](#nestedatt--inheritance_sources))
+- `ip_space` (String) The resource identifier.
+- `name` (String) The name of the fixed address. May contain 1 to 256 characters. Can include UTF-8.
+- `tags` (Map of String) The tags for the fixed address in JSON format.
+
+### Read-Only
+
+- `created_at` (String) Time when the object has been created.
+- `id` (String) The resource identifier.
+- `inheritance_assigned_hosts` (Attributes List) The list of the inheritance assigned hosts of the object. (see [below for nested schema](#nestedatt--inheritance_assigned_hosts))
+- `parent` (String) The resource identifier.
+- `updated_at` (String) Time when the object has been updated. Equals to _created_at_ if not updated after creation.
+
+
+### Nested Schema for `dhcp_options`
+
+Optional:
+
+- `group` (String) The resource identifier.
+- `option_code` (String) The resource identifier.
+- `option_value` (String) The option value.
+- `type` (String) The type of item. Valid values are: * _group_ * _option_
+
+
+
+### Nested Schema for `inheritance_sources`
+
+Optional:
+
+- `dhcp_options` (Attributes) (see [below for nested schema](#nestedatt--inheritance_sources--dhcp_options))
+- `header_option_filename` (Attributes) (see [below for nested schema](#nestedatt--inheritance_sources--header_option_filename))
+- `header_option_server_address` (Attributes) (see [below for nested schema](#nestedatt--inheritance_sources--header_option_server_address))
+- `header_option_server_name` (Attributes) (see [below for nested schema](#nestedatt--inheritance_sources--header_option_server_name))
+
+
+### Nested Schema for `inheritance_sources.dhcp_options`
+
+Optional:
+
+- `action` (String) The inheritance setting. Valid values are: * _inherit_: Use the inherited value. * _block_: Don't use the inherited value. Defaults to _inherit_.
+- `value` (Attributes List) The inherited DHCP option values. (see [below for nested schema](#nestedatt--inheritance_sources--dhcp_options--value))
+
+
+### Nested Schema for `inheritance_sources.dhcp_options.value`
+
+Optional:
+
+- `action` (String) The inheritance setting. Valid values are: * _inherit_: Use the inherited value. * _block_: Don't use the inherited value. Defaults to _inherit_.
+- `source` (String) The resource identifier.
+- `value` (Attributes) (see [below for nested schema](#nestedatt--inheritance_sources--dhcp_options--value--value))
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the object referred to by _source_.
+
+
+### Nested Schema for `inheritance_sources.dhcp_options.value.display_name`
+
+Optional:
+
+- `option` (Attributes) (see [below for nested schema](#nestedatt--inheritance_sources--dhcp_options--value--display_name--option))
+- `overriding_group` (String) The resource identifier.
+
+
+### Nested Schema for `inheritance_sources.dhcp_options.value.display_name.option`
+
+Optional:
+
+- `group` (String) The resource identifier.
+- `option_code` (String) The resource identifier.
+- `option_value` (String) The option value.
+- `type` (String) The type of item. Valid values are: * _group_ * _option_
+
+
+
+
+
+
+### Nested Schema for `inheritance_sources.header_option_filename`
+
+Optional:
+
+- `action` (String) The inheritance setting for a field. Valid values are: * _inherit_: Use the inherited value. * _override_: Use the value set in the object. Defaults to _inherit_.
+- `source` (String) The resource identifier.
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the object referred to by _source_.
+- `value` (String) The inherited value.
+
+
+
+### Nested Schema for `inheritance_sources.header_option_server_address`
+
+Optional:
+
+- `action` (String) The inheritance setting for a field. Valid values are: * _inherit_: Use the inherited value. * _override_: Use the value set in the object. Defaults to _inherit_.
+- `source` (String) The resource identifier.
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the object referred to by _source_.
+- `value` (String) The inherited value.
+
+
+
+### Nested Schema for `inheritance_sources.header_option_server_name`
+
+Optional:
+
+- `action` (String) The inheritance setting for a field. Valid values are: * _inherit_: Use the inherited value. * _override_: Use the value set in the object. Defaults to _inherit_.
+- `source` (String) The resource identifier.
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the object referred to by _source_.
+- `value` (String) The inherited value.
+
+
+
+
+### Nested Schema for `inheritance_assigned_hosts`
+
+Optional:
+
+- `host` (String) The resource identifier.
+
+Read-Only:
+
+- `display_name` (String) The human-readable display name for the host referred to by _ophid_.
+- `ophid` (String) The on-prem host ID.
diff --git a/examples/data-sources/bloxone_dhcp_fixed_addresses/data-source.tf b/examples/data-sources/bloxone_dhcp_fixed_addresses/data-source.tf
new file mode 100644
index 00000000..44e7d586
--- /dev/null
+++ b/examples/data-sources/bloxone_dhcp_fixed_addresses/data-source.tf
@@ -0,0 +1,16 @@
+# Get DHCP fixed address filtered by an attribute
+data "bloxone_dhcp_fixed_addresses" "example_by_attribute" {
+ filters = {
+ name = "example_fixed_address"
+ }
+}
+
+# Get DHCP fixed address by tag
+data "bloxone_dhcp_fixed_addresses" "example_by_tag" {
+ tag_filters = {
+ location = "site1"
+ }
+}
+
+# Get all fixed address
+data "bloxone_dhcp_fixed_addresses" "example_all" {}
diff --git a/examples/data-sources/bloxone_dhcp_hosts/data-source.tf b/examples/data-sources/bloxone_dhcp_hosts/data-source.tf
new file mode 100644
index 00000000..0c0108d7
--- /dev/null
+++ b/examples/data-sources/bloxone_dhcp_hosts/data-source.tf
@@ -0,0 +1,16 @@
+# Get DHCP Host filtered by an attribute
+data "bloxone_dhcp_hosts" "example_by_name" {
+ filters = {
+ name = "example-host"
+ }
+}
+
+# Get DHCP Host by tag
+data "bloxone_dhcp_hosts" "example_by_tag" {
+ tag_filters = {
+ location = "site1"
+ }
+}
+
+# Get all DHCP hosts
+data "bloxone_dhcp_hosts" "example_all" {}
diff --git a/examples/resources/bloxone_dhcp_fixed_address/resource.tf b/examples/resources/bloxone_dhcp_fixed_address/resource.tf
new file mode 100644
index 00000000..96baf7a0
--- /dev/null
+++ b/examples/resources/bloxone_dhcp_fixed_address/resource.tf
@@ -0,0 +1,41 @@
+resource "bloxone_ipam_ip_space" "example" {
+ name = "example"
+ comment = "Example IP space created by the terraform provider"
+ tags = {
+ location = "site1"
+ }
+}
+
+resource "bloxone_ipam_address_block" "example" {
+ address = "192.160.0.0"
+ cidr = 16
+ space = bloxone_ipam_ip_space.example.id
+ comment = "Example Address Block created by the terraform provider"
+ tags = {
+ location = "site1"
+ }
+}
+
+resource "bloxone_ipam_subnet" "example" {
+ name = "example"
+ space = bloxone_ipam_ip_space.example.id
+ address = "192.168.1.0"
+ cidr = 24
+ comment = "Example Subnet created by the terraform provider"
+ tags = {
+ location = "site1"
+ }
+}
+
+resource "bloxone_dhcp_fixed_address" "example_fixed_address" {
+ name = "example_fixed_address"
+ address = "192.168.1.1"
+ ip_space = bloxone_ipam_ip_space.example.id
+ match_type = "mac"
+ match_value = "00:00:00:00:00:00"
+ comment = "Example Fixed Address created by the terraform provider"
+ tags = {
+ location : "site1"
+ }
+ depends_on = [bloxone_ipam_subnet.example]
+}
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index cbcbf843..2ed12bfb 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -86,6 +86,7 @@ func (p *BloxOneProvider) Resources(ctx context.Context) []func() resource.Resou
ipam.NewAddressBlockResource,
ipam.NewAddressResource,
ipam.NewRangeResource,
+ ipam.NewFixedAddressResource,
dns_config.NewViewResource,
dns_config.NewAuthNsgResource,
@@ -104,12 +105,14 @@ func (p *BloxOneProvider) Resources(ctx context.Context) []func() resource.Resou
func (p *BloxOneProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{
+ ipam.NewDhcpHostDataSource,
ipam.NewIpamHostDataSource,
ipam.NewIpSpaceDataSource,
ipam.NewSubnetDataSource,
ipam.NewAddressBlockDataSource,
ipam.NewAddressDataSource,
ipam.NewRangeDataSource,
+ ipam.NewFixedAddressDataSource,
dns_config.NewViewDataSource,
dns_config.NewAuthNsgDataSource,
diff --git a/internal/service/ipam/api_dhcp_host_data_source.go b/internal/service/ipam/api_dhcp_host_data_source.go
new file mode 100644
index 00000000..0c31b533
--- /dev/null
+++ b/internal/service/ipam/api_dhcp_host_data_source.go
@@ -0,0 +1,116 @@
+package ipam
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+
+ bloxoneclient "github.com/infobloxopen/bloxone-go-client/client"
+ "github.com/infobloxopen/bloxone-go-client/ipam"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/flex"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/utils"
+)
+
+// Ensure provider defined types fully satisfy framework interfaces.
+var _ datasource.DataSource = &DhcpHostDataSource{}
+
+func NewDhcpHostDataSource() datasource.DataSource {
+ return &DhcpHostDataSource{}
+}
+
+// DhcpHostDataSource defines the data source implementation.
+type DhcpHostDataSource struct {
+ client *bloxoneclient.APIClient
+}
+
+func (d *DhcpHostDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_" + "dhcp_hosts"
+}
+
+type IpamsvcHostModelWithFilter struct {
+ Filters types.Map `tfsdk:"filters"`
+ TagFilters types.Map `tfsdk:"tag_filters"`
+ Results types.List `tfsdk:"results"`
+}
+
+func (m *IpamsvcHostModelWithFilter) FlattenResults(ctx context.Context, from []ipam.IpamsvcHost, diags *diag.Diagnostics) {
+ if len(from) == 0 {
+ return
+ }
+ m.Results = flex.FlattenFrameworkListNestedBlock(ctx, from, IpamsvcHostAttrTypes, diags, FlattenIpamsvcHost)
+}
+
+func (d *DhcpHostDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ MarkdownDescription: "",
+ Attributes: map[string]schema.Attribute{
+ "filters": schema.MapAttribute{
+ Description: "Filter are used to return a more specific list of results. Filters can be used to match resources by specific attributes, e.g. name. If you specify multiple filters, the results returned will have only resources that match all the specified filters.",
+ ElementType: types.StringType,
+ Optional: true,
+ },
+ "tag_filters": schema.MapAttribute{
+ Description: "Tag Filters are used to return a more specific list of results filtered by tags. If you specify multiple filters, the results returned will have only resources that match all the specified filters.",
+ ElementType: types.StringType,
+ Optional: true,
+ },
+ "results": schema.ListNestedAttribute{
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: utils.DataSourceAttributeMap(IpamsvcHostResourceSchemaAttributes, &resp.Diagnostics),
+ },
+ Computed: true,
+ },
+ },
+ }
+}
+
+func (d *DhcpHostDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
+ // Prevent panic if the provider has not been configured.
+ if req.ProviderData == nil {
+ return
+ }
+
+ client, ok := req.ProviderData.(*bloxoneclient.APIClient)
+
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected DataSource Configure Type",
+ fmt.Sprintf("Expected *bloxoneclient.APIClient, got: %T. Please report this issue to the provider developers.", req.ProviderData),
+ )
+
+ return
+ }
+
+ d.client = client
+}
+
+func (d *DhcpHostDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var data IpamsvcHostModelWithFilter
+
+ // Read Terraform prior state data into the model
+ resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ apiRes, _, err := d.client.IPAddressManagementAPI.
+ DhcpHostAPI.
+ DhcpHostList(ctx).
+ Filter(flex.ExpandFrameworkMapFilterString(ctx, data.Filters, &resp.Diagnostics)).
+ Tfilter(flex.ExpandFrameworkMapFilterString(ctx, data.TagFilters, &resp.Diagnostics)).
+ Execute()
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read DhcpHost, got error: %s", err))
+ return
+ }
+
+ data.FlattenResults(ctx, apiRes.GetResults(), &resp.Diagnostics)
+
+ // Save updated data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
diff --git a/internal/service/ipam/api_dhcp_host_data_source_test.go b/internal/service/ipam/api_dhcp_host_data_source_test.go
new file mode 100644
index 00000000..0205b568
--- /dev/null
+++ b/internal/service/ipam/api_dhcp_host_data_source_test.go
@@ -0,0 +1,101 @@
+package ipam_test
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+
+ "github.com/infobloxopen/bloxone-go-client/ipam"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/acctest"
+)
+
+func TestAccDhcpHostDataSource_Filters(t *testing.T) {
+ dataSourceName := "data.bloxone_dhcp_hosts.test"
+ var v ipam.IpamsvcHost
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDhcpHostDataSourceConfigFilters("TF_TEST_HOST_01"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckDhcpHostExists(context.Background(), dataSourceName, &v),
+ resource.TestCheckResourceAttr(dataSourceName, "results.#", "1"),
+ resource.TestCheckResourceAttr(dataSourceName, "results.0.name", "TF_TEST_HOST_01"),
+ resource.TestCheckResourceAttrSet(dataSourceName, "results.0.id"),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccDhcpHostDataSource_TagFilters(t *testing.T) {
+ dataSourceName := "data.bloxone_dhcp_hosts.test_tag"
+ var v ipam.IpamsvcHost
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDhcpHostDataSourceConfigTagFilters("Terraform Acceptance Testing"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckDhcpHostExists(context.Background(), dataSourceName, &v),
+ resource.TestCheckResourceAttr(dataSourceName, "results.#", "1"),
+ resource.TestCheckResourceAttr(dataSourceName, "results.0.name", "TF_TEST_HOST_01"),
+ resource.TestCheckResourceAttr(dataSourceName, "results.0.tags.used_for", "Terraform Acceptance Testing"),
+ resource.TestCheckResourceAttrSet(dataSourceName, "results.0.id"),
+ ),
+ },
+ },
+ })
+}
+
+func testAccCheckDhcpHostExists(ctx context.Context, dataSourceName string, v *ipam.IpamsvcHost) resource.TestCheckFunc {
+ // Verify the resource exists in the cloud
+ return func(state *terraform.State) error {
+ rs, ok := state.RootModule().Resources[dataSourceName]
+ if !ok {
+ return fmt.Errorf("not found: %s", dataSourceName)
+ }
+ apiRes, _, err := acctest.BloxOneClient.IPAddressManagementAPI.
+ DhcpHostAPI.
+ DhcpHostRead(ctx, rs.Primary.Attributes["results.0.id"]).
+ Execute()
+ if err != nil {
+ return err
+ }
+ if !apiRes.HasResult() {
+ return fmt.Errorf("expected result to be returned: %s", dataSourceName)
+ }
+ *v = apiRes.GetResult()
+ return nil
+ }
+}
+
+// below all TestAcc functions
+
+func testAccDhcpHostDataSourceConfigFilters(name string) string {
+ return fmt.Sprintf(`
+
+data "bloxone_dhcp_hosts" "test" {
+ filters = {
+ name = %q
+ }
+}
+`, name)
+}
+
+func testAccDhcpHostDataSourceConfigTagFilters(tagValue string) string {
+ return fmt.Sprintf(`
+data "bloxone_dhcp_hosts" "test_tag" {
+ tag_filters = {
+ used_for = %q
+ }
+}
+`, tagValue)
+}
diff --git a/internal/service/ipam/api_fixed_address_data_source.go b/internal/service/ipam/api_fixed_address_data_source.go
new file mode 100644
index 00000000..9276acf3
--- /dev/null
+++ b/internal/service/ipam/api_fixed_address_data_source.go
@@ -0,0 +1,116 @@
+package ipam
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+
+ bloxoneclient "github.com/infobloxopen/bloxone-go-client/client"
+ "github.com/infobloxopen/bloxone-go-client/ipam"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/flex"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/utils"
+)
+
+// Ensure provider defined types fully satisfy framework interfaces.
+var _ datasource.DataSource = &FixedAddressDataSource{}
+
+func NewFixedAddressDataSource() datasource.DataSource {
+ return &FixedAddressDataSource{}
+}
+
+// FixedAddressDataSource defines the data source implementation.
+type FixedAddressDataSource struct {
+ client *bloxoneclient.APIClient
+}
+
+func (d *FixedAddressDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_" + "dhcp_fixed_addresses"
+}
+
+type IpamsvcFixedAddressModelWithFilter struct {
+ Filters types.Map `tfsdk:"filters"`
+ TagFilters types.Map `tfsdk:"tag_filters"`
+ Results types.List `tfsdk:"results"`
+}
+
+func (m *IpamsvcFixedAddressModelWithFilter) FlattenResults(ctx context.Context, from []ipam.IpamsvcFixedAddress, diags *diag.Diagnostics) {
+ if len(from) == 0 {
+ return
+ }
+ m.Results = flex.FlattenFrameworkListNestedBlock(ctx, from, IpamsvcFixedAddressAttrTypes, diags, FlattenIpamsvcFixedAddress)
+}
+
+func (d *FixedAddressDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ MarkdownDescription: "",
+ Attributes: map[string]schema.Attribute{
+ "filters": schema.MapAttribute{
+ Description: "Filter are used to return a more specific list of results. Filters can be used to match resources by specific attributes, e.g. name. If you specify multiple filters, the results returned will have only resources that match all the specified filters.",
+ ElementType: types.StringType,
+ Optional: true,
+ },
+ "tag_filters": schema.MapAttribute{
+ Description: "Tag Filters are used to return a more specific list of results filtered by tags. If you specify multiple filters, the results returned will have only resources that match all the specified filters.",
+ ElementType: types.StringType,
+ Optional: true,
+ },
+ "results": schema.ListNestedAttribute{
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: utils.DataSourceAttributeMap(IpamsvcFixedAddressResourceSchemaAttributes, &resp.Diagnostics),
+ },
+ Computed: true,
+ },
+ },
+ }
+}
+
+func (d *FixedAddressDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
+ // Prevent panic if the provider has not been configured.
+ if req.ProviderData == nil {
+ return
+ }
+
+ client, ok := req.ProviderData.(*bloxoneclient.APIClient)
+
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected DataSource Configure Type",
+ fmt.Sprintf("Expected *bloxoneclient.APIClient, got: %T. Please report this issue to the provider developers.", req.ProviderData),
+ )
+
+ return
+ }
+
+ d.client = client
+}
+
+func (d *FixedAddressDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var data IpamsvcFixedAddressModelWithFilter
+
+ // Read Terraform prior state data into the model
+ resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ apiRes, _, err := d.client.IPAddressManagementAPI.
+ FixedAddressAPI.
+ FixedAddressList(ctx).
+ Filter(flex.ExpandFrameworkMapFilterString(ctx, data.Filters, &resp.Diagnostics)).
+ Tfilter(flex.ExpandFrameworkMapFilterString(ctx, data.TagFilters, &resp.Diagnostics)).
+ Execute()
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read FixedAddress, got error: %s", err))
+ return
+ }
+
+ data.FlattenResults(ctx, apiRes.GetResults(), &resp.Diagnostics)
+
+ // Save updated data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
diff --git a/internal/service/ipam/api_fixed_address_data_source_test.go b/internal/service/ipam/api_fixed_address_data_source_test.go
new file mode 100644
index 00000000..0f96e9f0
--- /dev/null
+++ b/internal/service/ipam/api_fixed_address_data_source_test.go
@@ -0,0 +1,124 @@
+package ipam_test
+
+import (
+ "context"
+ "fmt"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+
+ "github.com/infobloxopen/bloxone-go-client/ipam"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/acctest"
+)
+
+func TestAccFixedAddressDataSource_Filters(t *testing.T) {
+ dataSourceName := "data.bloxone_dhcp_fixed_addresses.test"
+ resourceName := "bloxone_dhcp_fixed_address.test"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ CheckDestroy: testAccCheckFixedAddressDestroy(context.Background(), &v),
+ Steps: []resource.TestStep{
+ {
+ Config: testAccFixedAddressDataSourceConfigFilters("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa"),
+ Check: resource.ComposeTestCheckFunc(
+ append([]resource.TestCheckFunc{
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ }, testAccCheckFixedAddressResourceAttrPair(resourceName, dataSourceName)...)...,
+ ),
+ },
+ },
+ })
+}
+
+func TestAccFixedAddressDataSource_TagFilters(t *testing.T) {
+ dataSourceName := "data.bloxone_dhcp_fixed_addresses.test"
+ resourceName := "bloxone_dhcp_fixed_address.test"
+ var v ipam.IpamsvcFixedAddress
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ CheckDestroy: testAccCheckFixedAddressDestroy(context.Background(), &v),
+ Steps: []resource.TestStep{
+ {
+ Config: testAccFixedAddressDataSourceConfigTagFilters("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "value1"),
+ Check: resource.ComposeTestCheckFunc(
+ append([]resource.TestCheckFunc{
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ }, testAccCheckFixedAddressResourceAttrPair(resourceName, dataSourceName)...)...,
+ ),
+ },
+ },
+ })
+}
+
+// below all TestAcc functions
+
+func testAccCheckFixedAddressResourceAttrPair(resourceName, dataSourceName string) []resource.TestCheckFunc {
+ return []resource.TestCheckFunc{
+ resource.TestCheckResourceAttrPair(resourceName, "address", dataSourceName, "results.0.address"),
+ resource.TestCheckResourceAttrPair(resourceName, "comment", dataSourceName, "results.0.comment"),
+ resource.TestCheckResourceAttrPair(resourceName, "created_at", dataSourceName, "results.0.created_at"),
+ resource.TestCheckResourceAttrPair(resourceName, "dhcp_options", dataSourceName, "results.0.dhcp_options"),
+ resource.TestCheckResourceAttrPair(resourceName, "disable_dhcp", dataSourceName, "results.0.disable_dhcp"),
+ resource.TestCheckResourceAttrPair(resourceName, "header_option_filename", dataSourceName, "results.0.header_option_filename"),
+ resource.TestCheckResourceAttrPair(resourceName, "header_option_server_address", dataSourceName, "results.0.header_option_server_address"),
+ resource.TestCheckResourceAttrPair(resourceName, "header_option_server_name", dataSourceName, "results.0.header_option_server_name"),
+ resource.TestCheckResourceAttrPair(resourceName, "hostname", dataSourceName, "results.0.hostname"),
+ resource.TestCheckResourceAttrPair(resourceName, "id", dataSourceName, "results.0.id"),
+ resource.TestCheckResourceAttrPair(resourceName, "inheritance_assigned_hosts", dataSourceName, "results.0.inheritance_assigned_hosts"),
+ resource.TestCheckResourceAttrPair(resourceName, "inheritance_parent", dataSourceName, "results.0.inheritance_parent"),
+ resource.TestCheckResourceAttrPair(resourceName, "inheritance_sources", dataSourceName, "results.0.inheritance_sources"),
+ resource.TestCheckResourceAttrPair(resourceName, "ip_space", dataSourceName, "results.0.ip_space"),
+ resource.TestCheckResourceAttrPair(resourceName, "match_type", dataSourceName, "results.0.match_type"),
+ resource.TestCheckResourceAttrPair(resourceName, "match_value", dataSourceName, "results.0.match_value"),
+ resource.TestCheckResourceAttrPair(resourceName, "name", dataSourceName, "results.0.name"),
+ resource.TestCheckResourceAttrPair(resourceName, "parent", dataSourceName, "results.0.parent"),
+ resource.TestCheckResourceAttrPair(resourceName, "tags", dataSourceName, "results.0.tags"),
+ resource.TestCheckResourceAttrPair(resourceName, "updated_at", dataSourceName, "results.0.updated_at"),
+ }
+}
+
+func testAccFixedAddressDataSourceConfigFilters(address, matchType, matchValue string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+
+data "bloxone_dhcp_fixed_addresses" "test" {
+ filters = {
+ address = bloxone_dhcp_fixed_address.test.address
+ }
+}
+`, address, matchType, matchValue)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressDataSourceConfigTagFilters(address, matchType, matchValue, tagValue string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ tags = {
+ tag1 = %q
+ }
+ depends_on = [bloxone_ipam_subnet.test]
+}
+
+data "bloxone_dhcp_fixed_addresses" "test" {
+ tag_filters = {
+ tag1 = bloxone_dhcp_fixed_address.test.tags.tag1
+ }
+}
+`, address, matchType, matchValue, tagValue)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
diff --git a/internal/service/ipam/api_fixed_address_resource.go b/internal/service/ipam/api_fixed_address_resource.go
new file mode 100644
index 00000000..f36c437f
--- /dev/null
+++ b/internal/service/ipam/api_fixed_address_resource.go
@@ -0,0 +1,168 @@
+package ipam
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+
+ bloxoneclient "github.com/infobloxopen/bloxone-go-client/client"
+)
+
+// Ensure provider defined types fully satisfy framework interfaces.
+var _ resource.Resource = &FixedAddressResource{}
+var _ resource.ResourceWithImportState = &FixedAddressResource{}
+
+func NewFixedAddressResource() resource.Resource {
+ return &FixedAddressResource{}
+}
+
+// FixedAddressResource defines the resource implementation.
+type FixedAddressResource struct {
+ client *bloxoneclient.APIClient
+}
+
+func (r *FixedAddressResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_" + "dhcp_fixed_address"
+}
+
+func (r *FixedAddressResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ MarkdownDescription: "",
+ Attributes: IpamsvcFixedAddressResourceSchemaAttributes,
+ }
+}
+
+func (r *FixedAddressResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
+ // Prevent panic if the provider has not been configured.
+ if req.ProviderData == nil {
+ return
+ }
+
+ client, ok := req.ProviderData.(*bloxoneclient.APIClient)
+
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected Resource Configure Type",
+ fmt.Sprintf("Expected *bloxoneclient.APIClient, got: %T. Please report this issue to the provider developers.", req.ProviderData),
+ )
+
+ return
+ }
+
+ r.client = client
+}
+
+func (r *FixedAddressResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var data IpamsvcFixedAddressModel
+
+ // Read Terraform plan data into the model
+ resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ apiRes, _, err := r.client.IPAddressManagementAPI.
+ FixedAddressAPI.
+ FixedAddressCreate(ctx).
+ Body(*data.Expand(ctx, &resp.Diagnostics)).
+ Execute()
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create FixedAddress, got error: %s", err))
+ return
+ }
+
+ res := apiRes.GetResult()
+ data.Flatten(ctx, &res, &resp.Diagnostics)
+
+ // Save data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (r *FixedAddressResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var data IpamsvcFixedAddressModel
+
+ // Read Terraform prior state data into the model
+ resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ apiRes, httpRes, err := r.client.IPAddressManagementAPI.
+ FixedAddressAPI.
+ FixedAddressRead(ctx, data.Id.ValueString()).
+ Execute()
+ if err != nil {
+ if httpRes != nil && httpRes.StatusCode == http.StatusNotFound {
+ resp.State.RemoveResource(ctx)
+ return
+ }
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read FixedAddress, got error: %s", err))
+ return
+ }
+
+ res := apiRes.GetResult()
+ data.Flatten(ctx, &res, &resp.Diagnostics)
+
+ // Save updated data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (r *FixedAddressResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var data IpamsvcFixedAddressModel
+
+ // Read Terraform plan data into the model
+ resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ apiRes, _, err := r.client.IPAddressManagementAPI.
+ FixedAddressAPI.
+ FixedAddressUpdate(ctx, data.Id.ValueString()).
+ Body(*data.Expand(ctx, &resp.Diagnostics)).
+ Execute()
+ if err != nil {
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update FixedAddress, got error: %s", err))
+ return
+ }
+
+ res := apiRes.GetResult()
+ data.Flatten(ctx, &res, &resp.Diagnostics)
+
+ // Save updated data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (r *FixedAddressResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var data IpamsvcFixedAddressModel
+
+ // Read Terraform prior state data into the model
+ resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ httpRes, err := r.client.IPAddressManagementAPI.
+ FixedAddressAPI.
+ FixedAddressDelete(ctx, data.Id.ValueString()).
+ Execute()
+ if err != nil {
+ if httpRes != nil && httpRes.StatusCode == http.StatusNotFound {
+ return
+ }
+ resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete FixedAddress, got error: %s", err))
+ return
+ }
+}
+
+func (r *FixedAddressResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
+}
diff --git a/internal/service/ipam/api_fixed_address_resource_test.go b/internal/service/ipam/api_fixed_address_resource_test.go
new file mode 100644
index 00000000..b458084f
--- /dev/null
+++ b/internal/service/ipam/api_fixed_address_resource_test.go
@@ -0,0 +1,675 @@
+package ipam_test
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+
+ "github.com/infobloxopen/bloxone-go-client/ipam"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/acctest"
+)
+
+/*
+TODO:
+// Add unit test for dhcp_options
+// Add unit test for NextAvailableIP
+// Add unit tests for inheritance
+*/
+
+func TestAccFixedAddressResource_basic(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressBasicConfig("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "address", "10.0.0.10"),
+ resource.TestCheckResourceAttr(resourceName, "match_type", "mac"),
+ resource.TestCheckResourceAttr(resourceName, "match_value", "aa:aa:aa:aa:aa:aa"),
+ resource.TestCheckResourceAttrPair(resourceName, "ip_space", "bloxone_ipam_ip_space.test", "id"),
+ // Test Read Only fields
+ resource.TestCheckResourceAttrSet(resourceName, "created_at"),
+ resource.TestCheckResourceAttrSet(resourceName, "id"),
+ resource.TestCheckResourceAttrSet(resourceName, "updated_at"),
+ // Test fields with default value
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_disappears(t *testing.T) {
+ resourceName := "bloxone_dhcp_fixed_address.test"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ CheckDestroy: testAccCheckFixedAddressDestroy(context.Background(), &v),
+ Steps: []resource.TestStep{
+ {
+ Config: testAccFixedAddressBasicConfig("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ testAccCheckFixedAddressDisappears(context.Background(), &v),
+ ),
+ ExpectNonEmptyPlan: true,
+ },
+ },
+ })
+}
+
+func TestAccFixedAddressResource_Address(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_address"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressAddress("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "address", "10.0.0.10"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressAddress("10.0.0.11", "mac", "bb:bb:bb:bb:bb:bb"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "address", "10.0.0.11"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_Comment(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_comment"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressComment("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "this range is created by terraform"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "comment", "this range is created by terraform"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressComment("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "update: this range is created by terraform"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "comment", "update: this range is created by terraform"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_DisableDhcp(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_disable_dhcp"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressDisableDhcp("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "false"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "disable_dhcp", "false"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressDisableDhcp("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "true"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "disable_dhcp", "true"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_HeaderOptionFilename(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_header_option_filename"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressHeaderOptionFilename("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "header_option_filename"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "header_option_filename", "header_option_filename"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressHeaderOptionFilename("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "header_option_filename_update"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "header_option_filename", "header_option_filename_update"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_HeaderOptionServerAddress(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_header_option_server_address"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressHeaderOptionServerAddress("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "10.0.0.12"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "header_option_server_address", "10.0.0.12"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressHeaderOptionServerAddress("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "10.0.0.13"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "header_option_server_address", "10.0.0.13"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_HeaderOptionServerName(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_header_option_server_name"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressHeaderOptionServerName("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "header_option_server_name"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "header_option_server_name", "header_option_server_name"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressHeaderOptionServerName("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "header_option_server_name_update"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "header_option_server_name", "header_option_server_name_update"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_Hostname(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_hostname"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressHostname("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "hostname1"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "hostname", "hostname1"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressHostname("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "hostname2"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "hostname", "hostname2"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_IpSpace(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_ip_space"
+ var v1, v2 ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressIpSpace("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "bloxone_ipam_ip_space.one"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v1),
+ resource.TestCheckResourceAttrPair(resourceName, "ip_space", "bloxone_ipam_ip_space.one", "id"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressIpSpace("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "bloxone_ipam_ip_space.two"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressDestroy(context.Background(), &v1),
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v2),
+ resource.TestCheckResourceAttrPair(resourceName, "ip_space", "bloxone_ipam_ip_space.two", "id"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_MatchType_And_MatchValue(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_match_type"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressMatchTypeAndMactchValue("10.0.0.10", "client_hex", "aa"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "match_type", "client_hex"),
+ resource.TestCheckResourceAttr(resourceName, "match_value", "aa"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressMatchTypeAndMactchValue("10.0.0.10", "client_hex", "bb"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "match_type", "client_hex"),
+ resource.TestCheckResourceAttr(resourceName, "match_value", "bb"),
+ ),
+ },
+ {
+ Config: testAccFixedAddressMatchTypeAndMactchValue("10.0.0.10", "client_text", "clienttext"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "match_type", "client_text"),
+ resource.TestCheckResourceAttr(resourceName, "match_value", "clienttext"),
+ ),
+ },
+ {
+ Config: testAccFixedAddressMatchTypeAndMactchValue("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "match_type", "mac"),
+ resource.TestCheckResourceAttr(resourceName, "match_value", "aa:aa:aa:aa:aa:aa"),
+ ),
+ },
+ {
+ Config: testAccFixedAddressMatchTypeAndMactchValue("10.0.0.10", "relay_hex", "aa"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "match_type", "relay_hex"),
+ resource.TestCheckResourceAttr(resourceName, "match_value", "aa"),
+ ),
+ },
+ {
+ Config: testAccFixedAddressMatchTypeAndMactchValue("10.0.0.10", "relay_text", "relaytext"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "match_type", "relay_text"),
+ resource.TestCheckResourceAttr(resourceName, "match_value", "relaytext"),
+ ),
+ },
+ {
+ Config: testAccFixedAddressMatchTypeAndMactchValue("10.0.0.10", "client_hex", "aa"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "match_type", "client_hex"),
+ resource.TestCheckResourceAttr(resourceName, "match_value", "aa"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_Name(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_name"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressName("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "example_fixed_address"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "name", "example_fixed_address"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressName("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "example_fixed_address_updated"),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "name", "example_fixed_address_updated"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccFixedAddressResource_Tags(t *testing.T) {
+ var resourceName = "bloxone_dhcp_fixed_address.test_tags"
+ var v ipam.IpamsvcFixedAddress
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.PreCheck(t) },
+ ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read
+ {
+ Config: testAccFixedAddressTags("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", map[string]string{
+ "tag1": "value1",
+ "tag2": "value2",
+ }),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "tags.tag1", "value1"),
+ resource.TestCheckResourceAttr(resourceName, "tags.tag2", "value2"),
+ ),
+ },
+ // Update and Read
+ {
+ Config: testAccFixedAddressTags("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", map[string]string{
+ "tag2": "value2changed",
+ "tag3": "value3",
+ }),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckFixedAddressExists(context.Background(), resourceName, &v),
+ resource.TestCheckResourceAttr(resourceName, "tags.tag2", "value2changed"),
+ resource.TestCheckResourceAttr(resourceName, "tags.tag3", "value3"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func testAccCheckFixedAddressExists(ctx context.Context, resourceName string, v *ipam.IpamsvcFixedAddress) resource.TestCheckFunc {
+ // Verify the resource exists in the cloud
+ return func(state *terraform.State) error {
+ rs, ok := state.RootModule().Resources[resourceName]
+ if !ok {
+ return fmt.Errorf("not found: %s", resourceName)
+ }
+ apiRes, _, err := acctest.BloxOneClient.IPAddressManagementAPI.
+ FixedAddressAPI.
+ FixedAddressRead(ctx, rs.Primary.ID).
+ Execute()
+ if err != nil {
+ return err
+ }
+ if !apiRes.HasResult() {
+ return fmt.Errorf("expected result to be returned: %s", resourceName)
+ }
+ *v = apiRes.GetResult()
+ return nil
+ }
+}
+
+func testAccCheckFixedAddressDestroy(ctx context.Context, v *ipam.IpamsvcFixedAddress) resource.TestCheckFunc {
+ // Verify the resource was destroyed
+ return func(state *terraform.State) error {
+ _, httpRes, err := acctest.BloxOneClient.IPAddressManagementAPI.
+ FixedAddressAPI.
+ FixedAddressRead(ctx, *v.Id).
+ Execute()
+ if err != nil {
+ if httpRes != nil && httpRes.StatusCode == http.StatusNotFound {
+ // resource was deleted
+ return nil
+ }
+ return err
+ }
+ return errors.New("expected to be deleted")
+ }
+}
+
+func testAccCheckFixedAddressDisappears(ctx context.Context, v *ipam.IpamsvcFixedAddress) resource.TestCheckFunc {
+ // Delete the resource externally to verify disappears test
+ return func(state *terraform.State) error {
+ _, err := acctest.BloxOneClient.IPAddressManagementAPI.
+ FixedAddressAPI.
+ FixedAddressDelete(ctx, *v.Id).
+ Execute()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+}
+
+func testAccFixedAddressBasicConfig(address, matchType, matchValue string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressAddress(address string, matchType string, matchValue string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_address" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressComment(address string, matchType string, matchValue string, comment string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_comment" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ comment = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue, comment)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressDisableDhcp(address string, matchType string, matchValue string, disableDhcp string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_disable_dhcp" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ disable_dhcp = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue, disableDhcp)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressHeaderOptionFilename(address string, matchType string, matchValue string, headerOptionFilename string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_header_option_filename" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ header_option_filename = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue, headerOptionFilename)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressHeaderOptionServerAddress(address string, matchType string, matchValue string, headerOptionServerAddress string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_header_option_server_address" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ header_option_server_address = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue, headerOptionServerAddress)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressHeaderOptionServerName(address string, matchType string, matchValue string, headerOptionServerName string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_header_option_server_name" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ header_option_server_name = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue, headerOptionServerName)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressHostname(address string, matchType string, matchValue string, hostname string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_hostname" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ hostname = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue, hostname)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressIpSpace(address string, matchType string, matchValue string, ipSpace string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_ipam_subnet" "test" {
+ address = "10.0.0.0"
+ cidr = 24
+ space = %s.id
+}
+
+resource "bloxone_dhcp_fixed_address" "test_ip_space" {
+ address = %q
+ match_type = %q
+ match_value = %q
+ ip_space = %s.id
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, ipSpace, address, matchType, matchValue, ipSpace)
+ return strings.Join([]string{testAccBaseWithTwoIPSpace(), config}, "")
+}
+
+func testAccFixedAddressMatchTypeAndMactchValue(address string, matchType string, matchValue string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_match_type" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressName(address string, matchType string, matchValue string, name string) string {
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_name" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ name = %q
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue, name)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
+
+func testAccFixedAddressTags(address string, matchType string, matchValue string, tags map[string]string) string {
+ tagsStr := "{\n"
+ for k, v := range tags {
+ tagsStr += fmt.Sprintf(`
+ %s = %q
+`, k, v)
+ }
+ tagsStr += "\t}"
+
+ config := fmt.Sprintf(`
+resource "bloxone_dhcp_fixed_address" "test_tags" {
+ ip_space = bloxone_ipam_ip_space.test.id
+ address = %q
+ match_type = %q
+ match_value = %q
+ tags = %s
+ depends_on = [bloxone_ipam_subnet.test]
+}
+`, address, matchType, matchValue, tagsStr)
+ return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "")
+}
diff --git a/internal/service/ipam/model_ipamsvc_fixed_address.go b/internal/service/ipam/model_ipamsvc_fixed_address.go
new file mode 100644
index 00000000..46bc5563
--- /dev/null
+++ b/internal/service/ipam/model_ipamsvc_fixed_address.go
@@ -0,0 +1,242 @@
+package ipam
+
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
+
+ "github.com/infobloxopen/bloxone-go-client/ipam"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/flex"
+)
+
+type IpamsvcFixedAddressModel struct {
+ Address types.String `tfsdk:"address"`
+ Comment types.String `tfsdk:"comment"`
+ CreatedAt timetypes.RFC3339 `tfsdk:"created_at"`
+ DhcpOptions types.List `tfsdk:"dhcp_options"`
+ DisableDhcp types.Bool `tfsdk:"disable_dhcp"`
+ HeaderOptionFilename types.String `tfsdk:"header_option_filename"`
+ HeaderOptionServerAddress types.String `tfsdk:"header_option_server_address"`
+ HeaderOptionServerName types.String `tfsdk:"header_option_server_name"`
+ Hostname types.String `tfsdk:"hostname"`
+ Id types.String `tfsdk:"id"`
+ InheritanceAssignedHosts types.List `tfsdk:"inheritance_assigned_hosts"`
+ InheritanceParent types.String `tfsdk:"inheritance_parent"`
+ InheritanceSources types.Object `tfsdk:"inheritance_sources"`
+ IpSpace types.String `tfsdk:"ip_space"`
+ MatchType types.String `tfsdk:"match_type"`
+ MatchValue types.String `tfsdk:"match_value"`
+ Name types.String `tfsdk:"name"`
+ Parent types.String `tfsdk:"parent"`
+ Tags types.Map `tfsdk:"tags"`
+ UpdatedAt timetypes.RFC3339 `tfsdk:"updated_at"`
+}
+
+var IpamsvcFixedAddressAttrTypes = map[string]attr.Type{
+ "address": types.StringType,
+ "comment": types.StringType,
+ "created_at": timetypes.RFC3339Type{},
+ "dhcp_options": types.ListType{ElemType: types.ObjectType{AttrTypes: IpamsvcOptionItemAttrTypes}},
+ "disable_dhcp": types.BoolType,
+ "header_option_filename": types.StringType,
+ "header_option_server_address": types.StringType,
+ "header_option_server_name": types.StringType,
+ "hostname": types.StringType,
+ "id": types.StringType,
+ "inheritance_assigned_hosts": types.ListType{ElemType: types.ObjectType{AttrTypes: InheritanceAssignedHostAttrTypes}},
+ "inheritance_parent": types.StringType,
+ "inheritance_sources": types.ObjectType{AttrTypes: IpamsvcFixedAddressInheritanceAttrTypes},
+ "ip_space": types.StringType,
+ "match_type": types.StringType,
+ "match_value": types.StringType,
+ "name": types.StringType,
+ "parent": types.StringType,
+ "tags": types.MapType{ElemType: types.StringType},
+ "updated_at": timetypes.RFC3339Type{},
+}
+
+var IpamsvcFixedAddressResourceSchemaAttributes = map[string]schema.Attribute{
+ "address": schema.StringAttribute{
+ Required: true,
+ MarkdownDescription: "The reserved address.",
+ },
+ "comment": schema.StringAttribute{
+ Optional: true,
+ MarkdownDescription: "The description for the fixed address. May contain 0 to 1024 characters. Can include UTF-8.",
+ },
+ "created_at": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Computed: true,
+ MarkdownDescription: "Time when the object has been created.",
+ },
+ "dhcp_options": schema.ListNestedAttribute{
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: IpamsvcOptionItemResourceSchemaAttributes,
+ },
+ Optional: true,
+ MarkdownDescription: "The list of DHCP options. May be either a specific option or a group of options.",
+ },
+ "disable_dhcp": schema.BoolAttribute{
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ MarkdownDescription: "Optional. _true_ to disable object. The fixed address is converted to an exclusion when generating configuration. Defaults to _false_.",
+ },
+ "header_option_filename": schema.StringAttribute{
+ Optional: true,
+ MarkdownDescription: "The configuration for header option filename field.",
+ },
+ "header_option_server_address": schema.StringAttribute{
+ Optional: true,
+ MarkdownDescription: "The configuration for header option server address field.",
+ },
+ "header_option_server_name": schema.StringAttribute{
+ Optional: true,
+ MarkdownDescription: "The configuration for header option server name field.",
+ },
+ "hostname": schema.StringAttribute{
+ Optional: true,
+ MarkdownDescription: "The DHCP host name associated with this fixed address. It is of FQDN type and it defaults to empty.",
+ },
+ "id": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The resource identifier.",
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "inheritance_assigned_hosts": schema.ListNestedAttribute{
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: InheritanceAssignedHostResourceSchemaAttributes,
+ },
+ Computed: true,
+ MarkdownDescription: "The list of the inheritance assigned hosts of the object.",
+ },
+ "inheritance_parent": schema.StringAttribute{
+ Optional: true,
+ Computed: true,
+ MarkdownDescription: "The resource identifier.",
+ },
+ "inheritance_sources": schema.SingleNestedAttribute{
+ Attributes: IpamsvcFixedAddressInheritanceResourceSchemaAttributes,
+ Optional: true,
+ },
+ "ip_space": schema.StringAttribute{
+ Optional: true,
+ MarkdownDescription: "The resource identifier.",
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplaceIfConfigured(),
+ },
+ },
+ "match_type": schema.StringAttribute{
+ Required: true,
+ MarkdownDescription: "Indicates how to match the client: * _mac_: match the client MAC address for both IPv4 and IPv6, * _client_text_ or _client_hex_: match the client identifier for IPv4 only, * _relay_text_ or _relay_hex_: match the circuit ID or remote ID in the DHCP relay agent option (82) for IPv4 only, * _duid_: match the DHCP unique identifier, currently match only for IPv6 protocol.",
+ },
+ "match_value": schema.StringAttribute{
+ Required: true,
+ MarkdownDescription: "The value to match.",
+ },
+ "name": schema.StringAttribute{
+ Optional: true,
+ MarkdownDescription: "The name of the fixed address. May contain 1 to 256 characters. Can include UTF-8.",
+ },
+ "parent": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The resource identifier.",
+ },
+ "tags": schema.MapAttribute{
+ ElementType: types.StringType,
+ Optional: true,
+ MarkdownDescription: "The tags for the fixed address in JSON format.",
+ },
+ "updated_at": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Computed: true,
+ MarkdownDescription: "Time when the object has been updated. Equals to _created_at_ if not updated after creation.",
+ },
+}
+
+func ExpandIpamsvcFixedAddress(ctx context.Context, o types.Object, diags *diag.Diagnostics) *ipam.IpamsvcFixedAddress {
+ if o.IsNull() || o.IsUnknown() {
+ return nil
+ }
+ var m IpamsvcFixedAddressModel
+ diags.Append(o.As(ctx, &m, basetypes.ObjectAsOptions{})...)
+ if diags.HasError() {
+ return nil
+ }
+ return m.Expand(ctx, diags)
+}
+
+func (m *IpamsvcFixedAddressModel) Expand(ctx context.Context, diags *diag.Diagnostics) *ipam.IpamsvcFixedAddress {
+ if m == nil {
+ return nil
+ }
+ to := &ipam.IpamsvcFixedAddress{
+ Address: flex.ExpandString(m.Address),
+ Comment: flex.ExpandStringPointer(m.Comment),
+ DhcpOptions: flex.ExpandFrameworkListNestedBlock(ctx, m.DhcpOptions, diags, ExpandIpamsvcOptionItem),
+ DisableDhcp: flex.ExpandBoolPointer(m.DisableDhcp),
+ HeaderOptionFilename: flex.ExpandStringPointer(m.HeaderOptionFilename),
+ HeaderOptionServerAddress: flex.ExpandStringPointer(m.HeaderOptionServerAddress),
+ HeaderOptionServerName: flex.ExpandStringPointer(m.HeaderOptionServerName),
+ Hostname: flex.ExpandStringPointer(m.Hostname),
+ InheritanceParent: flex.ExpandStringPointer(m.InheritanceParent),
+ InheritanceSources: ExpandIpamsvcFixedAddressInheritance(ctx, m.InheritanceSources, diags),
+ IpSpace: flex.ExpandStringPointer(m.IpSpace),
+ MatchType: flex.ExpandString(m.MatchType),
+ MatchValue: flex.ExpandString(m.MatchValue),
+ Name: flex.ExpandStringPointer(m.Name),
+ Parent: flex.ExpandStringPointer(m.Parent),
+ Tags: flex.ExpandFrameworkMapString(ctx, m.Tags, diags),
+ }
+ return to
+}
+
+func FlattenIpamsvcFixedAddress(ctx context.Context, from *ipam.IpamsvcFixedAddress, diags *diag.Diagnostics) types.Object {
+ if from == nil {
+ return types.ObjectNull(IpamsvcFixedAddressAttrTypes)
+ }
+ m := IpamsvcFixedAddressModel{}
+ m.Flatten(ctx, from, diags)
+ t, d := types.ObjectValueFrom(ctx, IpamsvcFixedAddressAttrTypes, m)
+ diags.Append(d...)
+ return t
+}
+
+func (m *IpamsvcFixedAddressModel) Flatten(ctx context.Context, from *ipam.IpamsvcFixedAddress, diags *diag.Diagnostics) {
+ if from == nil {
+ return
+ }
+ if m == nil {
+ *m = IpamsvcFixedAddressModel{}
+ }
+ m.Address = flex.FlattenString(from.Address)
+ m.Comment = flex.FlattenStringPointer(from.Comment)
+ m.CreatedAt = timetypes.NewRFC3339TimePointerValue(from.CreatedAt)
+ m.DhcpOptions = flex.FlattenFrameworkListNestedBlock(ctx, from.DhcpOptions, IpamsvcOptionItemAttrTypes, diags, FlattenIpamsvcOptionItem)
+ m.DisableDhcp = types.BoolPointerValue(from.DisableDhcp)
+ m.HeaderOptionFilename = flex.FlattenStringPointer(from.HeaderOptionFilename)
+ m.HeaderOptionServerAddress = flex.FlattenStringPointer(from.HeaderOptionServerAddress)
+ m.HeaderOptionServerName = flex.FlattenStringPointer(from.HeaderOptionServerName)
+ m.Hostname = flex.FlattenStringPointer(from.Hostname)
+ m.Id = flex.FlattenStringPointer(from.Id)
+ m.InheritanceAssignedHosts = flex.FlattenFrameworkListNestedBlock(ctx, from.InheritanceAssignedHosts, InheritanceAssignedHostAttrTypes, diags, FlattenInheritanceAssignedHost)
+ m.InheritanceParent = flex.FlattenStringPointer(from.InheritanceParent)
+ m.InheritanceSources = FlattenIpamsvcFixedAddressInheritance(ctx, from.InheritanceSources, diags)
+ m.IpSpace = flex.FlattenStringPointer(from.IpSpace)
+ m.MatchType = flex.FlattenString(from.MatchType)
+ m.MatchValue = flex.FlattenString(from.MatchValue)
+ m.Name = flex.FlattenStringPointer(from.Name)
+ m.Parent = flex.FlattenStringPointer(from.Parent)
+ m.Tags = flex.FlattenFrameworkMapString(ctx, from.Tags, diags)
+ m.UpdatedAt = timetypes.NewRFC3339TimePointerValue(from.UpdatedAt)
+}
diff --git a/internal/service/ipam/model_ipamsvc_fixed_address_inheritance.go b/internal/service/ipam/model_ipamsvc_fixed_address_inheritance.go
new file mode 100644
index 00000000..c5d52793
--- /dev/null
+++ b/internal/service/ipam/model_ipamsvc_fixed_address_inheritance.go
@@ -0,0 +1,95 @@
+package ipam
+
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
+
+ "github.com/infobloxopen/bloxone-go-client/ipam"
+)
+
+type IpamsvcFixedAddressInheritanceModel struct {
+ DhcpOptions types.Object `tfsdk:"dhcp_options"`
+ HeaderOptionFilename types.Object `tfsdk:"header_option_filename"`
+ HeaderOptionServerAddress types.Object `tfsdk:"header_option_server_address"`
+ HeaderOptionServerName types.Object `tfsdk:"header_option_server_name"`
+}
+
+var IpamsvcFixedAddressInheritanceAttrTypes = map[string]attr.Type{
+ "dhcp_options": types.ObjectType{AttrTypes: IpamsvcInheritedDHCPOptionListAttrTypes},
+ "header_option_filename": types.ObjectType{AttrTypes: InheritanceInheritedStringAttrTypes},
+ "header_option_server_address": types.ObjectType{AttrTypes: InheritanceInheritedStringAttrTypes},
+ "header_option_server_name": types.ObjectType{AttrTypes: InheritanceInheritedStringAttrTypes},
+}
+
+var IpamsvcFixedAddressInheritanceResourceSchemaAttributes = map[string]schema.Attribute{
+ "dhcp_options": schema.SingleNestedAttribute{
+ Attributes: IpamsvcInheritedDHCPOptionListResourceSchemaAttributes,
+ Optional: true,
+ },
+ "header_option_filename": schema.SingleNestedAttribute{
+ Attributes: InheritanceInheritedStringResourceSchemaAttributes,
+ Optional: true,
+ },
+ "header_option_server_address": schema.SingleNestedAttribute{
+ Attributes: InheritanceInheritedStringResourceSchemaAttributes,
+ Optional: true,
+ },
+ "header_option_server_name": schema.SingleNestedAttribute{
+ Attributes: InheritanceInheritedStringResourceSchemaAttributes,
+ Optional: true,
+ },
+}
+
+func ExpandIpamsvcFixedAddressInheritance(ctx context.Context, o types.Object, diags *diag.Diagnostics) *ipam.IpamsvcFixedAddressInheritance {
+ if o.IsNull() || o.IsUnknown() {
+ return nil
+ }
+ var m IpamsvcFixedAddressInheritanceModel
+ diags.Append(o.As(ctx, &m, basetypes.ObjectAsOptions{})...)
+ if diags.HasError() {
+ return nil
+ }
+ return m.Expand(ctx, diags)
+}
+
+func (m *IpamsvcFixedAddressInheritanceModel) Expand(ctx context.Context, diags *diag.Diagnostics) *ipam.IpamsvcFixedAddressInheritance {
+ if m == nil {
+ return nil
+ }
+ to := &ipam.IpamsvcFixedAddressInheritance{
+ DhcpOptions: ExpandIpamsvcInheritedDHCPOptionList(ctx, m.DhcpOptions, diags),
+ HeaderOptionFilename: ExpandInheritanceInheritedString(ctx, m.HeaderOptionFilename, diags),
+ HeaderOptionServerAddress: ExpandInheritanceInheritedString(ctx, m.HeaderOptionServerAddress, diags),
+ HeaderOptionServerName: ExpandInheritanceInheritedString(ctx, m.HeaderOptionServerName, diags),
+ }
+ return to
+}
+
+func FlattenIpamsvcFixedAddressInheritance(ctx context.Context, from *ipam.IpamsvcFixedAddressInheritance, diags *diag.Diagnostics) types.Object {
+ if from == nil {
+ return types.ObjectNull(IpamsvcFixedAddressInheritanceAttrTypes)
+ }
+ m := IpamsvcFixedAddressInheritanceModel{}
+ m.Flatten(ctx, from, diags)
+ t, d := types.ObjectValueFrom(ctx, IpamsvcFixedAddressInheritanceAttrTypes, m)
+ diags.Append(d...)
+ return t
+}
+
+func (m *IpamsvcFixedAddressInheritanceModel) Flatten(ctx context.Context, from *ipam.IpamsvcFixedAddressInheritance, diags *diag.Diagnostics) {
+ if from == nil {
+ return
+ }
+ if m == nil {
+ *m = IpamsvcFixedAddressInheritanceModel{}
+ }
+ m.DhcpOptions = FlattenIpamsvcInheritedDHCPOptionList(ctx, from.DhcpOptions, diags)
+ m.HeaderOptionFilename = FlattenInheritanceInheritedString(ctx, from.HeaderOptionFilename, diags)
+ m.HeaderOptionServerAddress = FlattenInheritanceInheritedString(ctx, from.HeaderOptionServerAddress, diags)
+ m.HeaderOptionServerName = FlattenInheritanceInheritedString(ctx, from.HeaderOptionServerName, diags)
+}
diff --git a/internal/service/ipam/model_ipamsvc_host.go b/internal/service/ipam/model_ipamsvc_host.go
new file mode 100644
index 00000000..6ad4fe62
--- /dev/null
+++ b/internal/service/ipam/model_ipamsvc_host.go
@@ -0,0 +1,167 @@
+package ipam
+
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
+
+ "github.com/infobloxopen/bloxone-go-client/ipam"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/flex"
+)
+
+type IpamsvcHostModel struct {
+ Address types.String `tfsdk:"address"`
+ AnycastAddresses types.List `tfsdk:"anycast_addresses"`
+ AssociatedServer types.Object `tfsdk:"associated_server"`
+ Comment types.String `tfsdk:"comment"`
+ CurrentVersion types.String `tfsdk:"current_version"`
+ Id types.String `tfsdk:"id"`
+ IpSpace types.String `tfsdk:"ip_space"`
+ Name types.String `tfsdk:"name"`
+ Ophid types.String `tfsdk:"ophid"`
+ ProviderId types.String `tfsdk:"provider_id"`
+ Server types.String `tfsdk:"server"`
+ Tags types.Map `tfsdk:"tags"`
+ Type types.String `tfsdk:"type"`
+}
+
+var IpamsvcHostAttrTypes = map[string]attr.Type{
+ "address": types.StringType,
+ "anycast_addresses": types.ListType{ElemType: types.StringType},
+ "associated_server": types.ObjectType{AttrTypes: IpamsvcHostAssociatedServerAttrTypes},
+ "comment": types.StringType,
+ "current_version": types.StringType,
+ "id": types.StringType,
+ "ip_space": types.StringType,
+ "name": types.StringType,
+ "ophid": types.StringType,
+ "provider_id": types.StringType,
+ "server": types.StringType,
+ "tags": types.MapType{ElemType: types.StringType},
+ "type": types.StringType,
+}
+
+var IpamsvcHostResourceSchemaAttributes = map[string]schema.Attribute{
+ "address": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The primary IP address of the on-prem host.",
+ },
+ "anycast_addresses": schema.ListAttribute{
+ ElementType: types.StringType,
+ Computed: true,
+ MarkdownDescription: "Anycast address configured to the host. Order is not significant.",
+ },
+ "associated_server": schema.SingleNestedAttribute{
+ Attributes: IpamsvcHostAssociatedServerResourceSchemaAttributes,
+ Optional: true,
+ MarkdownDescription: "The DHCP Config Profile for the on-prem host.",
+ },
+ "comment": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The description for the on-prem host.",
+ },
+ "current_version": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "Current dhcp application version of the host.",
+ },
+ "id": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The resource identifier.",
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "ip_space": schema.StringAttribute{
+ Optional: true,
+ MarkdownDescription: "The resource identifier.",
+ },
+ "name": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The display name of the on-prem host.",
+ },
+ "ophid": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The on-prem host ID.",
+ },
+ "provider_id": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "External provider identifier.",
+ },
+ "server": schema.StringAttribute{
+ Optional: true,
+ MarkdownDescription: "The resource identifier.",
+ },
+ "tags": schema.MapAttribute{
+ ElementType: types.StringType,
+ Optional: true,
+ MarkdownDescription: "The tags of the on-prem host in JSON format.",
+ },
+ "type": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "Defines the type of host. Allowed values: * _bloxone_ddi_: host type is BloxOne DDI, * _microsoft_azure_: host type is Microsoft Azure, * _amazon_web_service_: host type is Amazon Web Services. * _microsoft_active_directory_: host type is Microsoft Active Directory.",
+ },
+}
+
+func ExpandIpamsvcHost(ctx context.Context, o types.Object, diags *diag.Diagnostics) *ipam.IpamsvcHost {
+ if o.IsNull() || o.IsUnknown() {
+ return nil
+ }
+ var m IpamsvcHostModel
+ diags.Append(o.As(ctx, &m, basetypes.ObjectAsOptions{})...)
+ if diags.HasError() {
+ return nil
+ }
+ return m.Expand(ctx, diags)
+}
+
+func (m *IpamsvcHostModel) Expand(ctx context.Context, diags *diag.Diagnostics) *ipam.IpamsvcHost {
+ if m == nil {
+ return nil
+ }
+ to := &ipam.IpamsvcHost{
+ AssociatedServer: ExpandIpamsvcHostAssociatedServer(ctx, m.AssociatedServer, diags),
+ IpSpace: flex.ExpandStringPointer(m.IpSpace),
+ Server: flex.ExpandStringPointer(m.Server),
+ Tags: flex.ExpandFrameworkMapString(ctx, m.Tags, diags),
+ }
+ return to
+}
+
+func FlattenIpamsvcHost(ctx context.Context, from *ipam.IpamsvcHost, diags *diag.Diagnostics) types.Object {
+ if from == nil {
+ return types.ObjectNull(IpamsvcHostAttrTypes)
+ }
+ m := IpamsvcHostModel{}
+ m.Flatten(ctx, from, diags)
+ t, d := types.ObjectValueFrom(ctx, IpamsvcHostAttrTypes, m)
+ diags.Append(d...)
+ return t
+}
+
+func (m *IpamsvcHostModel) Flatten(ctx context.Context, from *ipam.IpamsvcHost, diags *diag.Diagnostics) {
+ if from == nil {
+ return
+ }
+ if m == nil {
+ *m = IpamsvcHostModel{}
+ }
+ m.Address = flex.FlattenStringPointer(from.Address)
+ m.AnycastAddresses = flex.FlattenFrameworkListString(ctx, from.AnycastAddresses, diags)
+ m.AssociatedServer = FlattenIpamsvcHostAssociatedServer(ctx, from.AssociatedServer, diags)
+ m.Comment = flex.FlattenStringPointer(from.Comment)
+ m.CurrentVersion = flex.FlattenStringPointer(from.CurrentVersion)
+ m.Id = flex.FlattenStringPointer(from.Id)
+ m.IpSpace = flex.FlattenStringPointer(from.IpSpace)
+ m.Name = flex.FlattenStringPointer(from.Name)
+ m.Ophid = flex.FlattenStringPointer(from.Ophid)
+ m.ProviderId = flex.FlattenStringPointer(from.ProviderId)
+ m.Server = flex.FlattenStringPointer(from.Server)
+ m.Tags = flex.FlattenFrameworkMapString(ctx, from.Tags, diags)
+ m.Type = flex.FlattenStringPointer(from.Type)
+}
diff --git a/internal/service/ipam/model_ipamsvc_host_associated_server.go b/internal/service/ipam/model_ipamsvc_host_associated_server.go
new file mode 100644
index 00000000..6fe0e28e
--- /dev/null
+++ b/internal/service/ipam/model_ipamsvc_host_associated_server.go
@@ -0,0 +1,77 @@
+package ipam
+
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
+
+ "github.com/infobloxopen/bloxone-go-client/ipam"
+ "github.com/infobloxopen/terraform-provider-bloxone/internal/flex"
+)
+
+type IpamsvcHostAssociatedServerModel struct {
+ Id types.String `tfsdk:"id"`
+ Name types.String `tfsdk:"name"`
+}
+
+var IpamsvcHostAssociatedServerAttrTypes = map[string]attr.Type{
+ "id": types.StringType,
+ "name": types.StringType,
+}
+
+var IpamsvcHostAssociatedServerResourceSchemaAttributes = map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The resource identifier.",
+ },
+ "name": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "The DHCP Config Profile name.",
+ },
+}
+
+func ExpandIpamsvcHostAssociatedServer(ctx context.Context, o types.Object, diags *diag.Diagnostics) *ipam.IpamsvcHostAssociatedServer {
+ if o.IsNull() || o.IsUnknown() {
+ return nil
+ }
+ var m IpamsvcHostAssociatedServerModel
+ diags.Append(o.As(ctx, &m, basetypes.ObjectAsOptions{})...)
+ if diags.HasError() {
+ return nil
+ }
+ return m.Expand(ctx, diags)
+}
+
+func (m *IpamsvcHostAssociatedServerModel) Expand(ctx context.Context, diags *diag.Diagnostics) *ipam.IpamsvcHostAssociatedServer {
+ if m == nil {
+ return nil
+ }
+ to := &ipam.IpamsvcHostAssociatedServer{}
+ return to
+}
+
+func FlattenIpamsvcHostAssociatedServer(ctx context.Context, from *ipam.IpamsvcHostAssociatedServer, diags *diag.Diagnostics) types.Object {
+ if from == nil {
+ return types.ObjectNull(IpamsvcHostAssociatedServerAttrTypes)
+ }
+ m := IpamsvcHostAssociatedServerModel{}
+ m.Flatten(ctx, from, diags)
+ t, d := types.ObjectValueFrom(ctx, IpamsvcHostAssociatedServerAttrTypes, m)
+ diags.Append(d...)
+ return t
+}
+
+func (m *IpamsvcHostAssociatedServerModel) Flatten(ctx context.Context, from *ipam.IpamsvcHostAssociatedServer, diags *diag.Diagnostics) {
+ if from == nil {
+ return
+ }
+ if m == nil {
+ *m = IpamsvcHostAssociatedServerModel{}
+ }
+ m.Id = flex.FlattenStringPointer(from.Id)
+ m.Name = flex.FlattenStringPointer(from.Name)
+}
diff --git a/internal/service/ipam/model_ipamsvc_range.go b/internal/service/ipam/model_ipamsvc_range.go
index 5fa7616a..5e74a47d 100644
--- a/internal/service/ipam/model_ipamsvc_range.go
+++ b/internal/service/ipam/model_ipamsvc_range.go
@@ -84,6 +84,7 @@ var IpamsvcRangeResourceSchemaAttributes = map[string]schema.Attribute{
},
"dhcp_host": schema.StringAttribute{
Optional: true,
+ Computed: true,
MarkdownDescription: "The resource identifier.",
},
"dhcp_options": schema.ListNestedAttribute{