Skip to content

Commit cca022e

Browse files
authored
Add compatibility to "name" argument (#132)
* Add compatibility to "name" argument The breaking change of making host.name read-only renders a lot of TF configs unusable. This commit adds diff suppression handling to work with name, shortname and fqdn even with older manifests. * Remove deprecation of foreman_host.name attribute; extend README The deprecation was meant to be an improvement but causes breaking changes to many Terraform manifests. We removed the deprecation and extended the README instead.
1 parent 224d19a commit cca022e

File tree

5 files changed

+88
-10
lines changed

5 files changed

+88
-10
lines changed

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22

33
Terraform provider to interact with [Foreman](https://www.theforeman.org/).
44

5+
6+
## Changes in 0.6.x
7+
Starting with `v0.6.0` some (breaking) changes require an update of Terraform manifests.
8+
9+
* The host `build` argument was removed (`0.6.0`) and is replaced by `set_build_flag`. (`0.6.1`)
10+
* The reason behind this change is complex and was thoroughly discussed in https://github.com/terraform-coop/terraform-provider-foreman/discussions/125
11+
* Using the argument does one thing: it tells Foreman to set the `build` flag for a host. It defaults to `false`, setting it to `true` causes the host to be re-installed on next boot (network-based installation).
12+
* The `method` argument is re-introduced as `provision_method`. It can be either `build` (network-based) or `image` (image-based).
13+
* Both options require different additional arguments, e.g the image to be used. See `examples/host/`.
14+
* The host `name` argument was considered for deprecation (`0.6.0`).
15+
* The `name` attribute has issues based on the "append_domain_name" setting in Foreman. It causes "inconsistent plan" errors when you give it a shortname as value, Terraform receives an FQDN back, and the `name` attribute is then used in variables in other places in your Terraform manifests.
16+
* As an alternative, the `shortname` argument can be used instead. It is meant for the hostname without the domain part. If you use `name` as input argument, `shortname` will be filled by the provider automatically.
17+
* To get the host's FQDN from the provider, use the read-only attribute `fqdn`. (`0.6.1`)
18+
* **Use `shortname` and `fqdn` as variables in your manifests**! Example: `other_server = foreman_host.other_server.fqdn`. This will prevent you from running into inconsistent plans.
19+
20+
521
## Migration notice
622

723
The provider has moved from its previous location at https://github.com/terraform-coop/terraform-provider-foreman

docs/resources/foreman_host.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ resource "foreman_host" "example" {
1818

1919
The following arguments are supported:
2020

21+
- `architecture_id` - (Optional) ID of the architecture of this host
2122
- `bmc_success` - (Optional) REMOVED - Tracks the partial state of BMC operations on host creation. If these operations fail, the host will be created in Foreman and this boolean will remain `false`. On the next `terraform apply` will trigger the host update to pick back up with the BMC operations.
2223
- `comment` - (Optional) Add additional information about this host.Note: Changes to this attribute will trigger a host rebuild.
2324
- `compute_attributes` - (Optional) Hypervisor specific VM options. Must be a JSON string, as every compute provider has different attributes schema
@@ -34,21 +35,26 @@ The following arguments are supported:
3435
- `managed` - (Optional) Whether or not this host is managed by Foreman. Create host only, don't set build status or manage power states.
3536
- `medium_id` - (Optional, Force New) ID of the medium mounted on the host.
3637
- `model_id` - (Optional) ID of the hardware model if applicable
38+
- `name` - (Optional, Force New) Name of this host as stored in Foreman. Can be short name or FQDN, depending on your Foreman settings (especially the setting 'append_domain_name_for_hosts').
3739
- `operatingsystem_id` - (Optional, Force New) ID of the operating system to put on the host.
3840
- `owner_id` - (Optional) ID of the user or usergroup that owns the host.
3941
- `owner_type` - (Optional) Owner of the host, must be either User ot Usergroup
4042
- `parameters` - (Optional) A map of parameters that will be saved as host parameters in the machine config.
4143
- `provision_method` - (Optional, Force New) Sets the provision method in Foreman for this host: either network-based ('build') or image-based ('image')
44+
- `ptable_id` - (Optional) ID of the partition table the host should use
4245
- `puppet_class_ids` - (Optional) IDs of the applied puppet classes.
4346
- `retry_count` - (Optional) Number of times to retry on a failed attempt to register or delete a host in foreman.
47+
- `root_password` - (Optional) Default root password
4448
- `set_build_flag` - (Optional) Sets the Foreman-internal 'build' flag on this host - even if it is already built completely.
45-
- `shortname` - (Required, Force New) The short name of this host. Example: when the FQDN is 'host01.example.org', then 'host01' is the short name.
49+
- `shortname` - (Optional, Force New) The short name of this host. Example: when the FQDN is 'host01.example.org', then 'host01' is the short name.
50+
- `subnet_id` - (Optional) ID of the subnet the host should be placed in
4651

4752

4853
## Attributes Reference
4954

5055
The following attributes are exported:
5156

57+
- `architecture_id` - ID of the architecture of this host
5258
- `comment` - Add additional information about this host.Note: Changes to this attribute will trigger a host rebuild.
5359
- `compute_attributes` - Hypervisor specific VM options. Must be a JSON string, as every compute provider has different attributes schema
5460
- `compute_profile_id` -
@@ -72,9 +78,12 @@ The following attributes are exported:
7278
- `owner_type` - Owner of the host, must be either User ot Usergroup
7379
- `parameters` - A map of parameters that will be saved as host parameters in the machine config.
7480
- `provision_method` - Sets the provision method in Foreman for this host: either network-based ('build') or image-based ('image')
81+
- `ptable_id` - ID of the partition table the host should use
7582
- `puppet_class_ids` - IDs of the applied puppet classes.
7683
- `retry_count` - Number of times to retry on a failed attempt to register or delete a host in foreman.
84+
- `root_password` - Default root password
7785
- `set_build_flag` - Sets the Foreman-internal 'build' flag on this host - even if it is already built completely.
7886
- `shortname` - The short name of this host. Example: when the FQDN is 'host01.example.org', then 'host01' is the short name.
87+
- `subnet_id` - ID of the subnet the host should be placed in
7988
- `token` - Build token. Can be used to signal to Foreman that a host build is complete.
8089

foreman/api/host.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type ForemanHost struct {
5151

5252
// Shortname, FQDN without DomainName.
5353
// Not provided by the API, only available in templates with embedded Ruby
54-
Shortname string
54+
Shortname string `json:"-"`
5555

5656
// The "fqdn" field in the Terraform schema exists only in the schema,
5757
// not in this struct. Reason: name is a Foreman-managed field that can either hold

foreman/resource_foreman_host.go

+60-8
Original file line numberDiff line numberDiff line change
@@ -329,19 +329,21 @@ func resourceForemanHost() *schema.Resource {
329329
},
330330

331331
"name": {
332-
Type: schema.TypeString,
333-
Computed: true,
334-
Optional: false,
335-
Required: false,
336-
Deprecated: "[Deprecated. Use 'shortname' instead!]",
337-
Description: "Name of this host as stored in Foreman. Can be short name or FQDN, depending on your Foreman settings (especially the setting 'append_domain_name_for_hosts').",
332+
Type: schema.TypeString,
333+
Computed: true,
334+
Optional: true,
335+
ForceNew: true,
336+
Required: false,
337+
Description: "Name of this host as stored in Foreman. Can be short name or FQDN, depending on your Foreman settings (especially the setting 'append_domain_name_for_hosts').",
338+
DiffSuppressFunc: resourceForemanHostNameDiffSuppressFunc,
338339
},
339340

340341
"shortname": {
341342
Type: schema.TypeString,
342343
ForceNew: true,
343-
Optional: false,
344-
Required: true,
344+
Computed: true,
345+
Optional: true,
346+
Required: false,
345347
Description: "The short name of this host. Example: when the FQDN is 'host01.example.org', then 'host01' is the short name.",
346348
ValidateDiagFunc: func(value interface{}, p cty.Path) diag.Diagnostics {
347349
var diags diag.Diagnostics
@@ -355,6 +357,16 @@ func resourceForemanHost() *schema.Resource {
355357
}
356358
return diags
357359
},
360+
DiffSuppressFunc: func(k, oldValue, newValue string, d *schema.ResourceData) bool {
361+
name := d.Get("name").(string)
362+
363+
// Use case: manifest has no "shortname" defined, but uses "name". Then an apply fetches the shortname,
364+
// but a new apply would think it should be re-set to "".
365+
if name != "" && newValue == "" && strings.HasPrefix(name, oldValue) {
366+
return true
367+
}
368+
return false
369+
},
358370
},
359371

360372
"fqdn": {
@@ -1418,3 +1430,43 @@ func resourceForemanHostCustomizeDiffComputeAttributes(ctx context.Context, d *s
14181430
d.SetNew("compute_attributes", flattenComputeAttributes(oldMap))
14191431
return nil
14201432
}
1433+
1434+
func resourceForemanHostNameDiffSuppressFunc(k, oldValue, newValue string, d *schema.ResourceData) bool {
1435+
domainName := d.Get("domain_name").(string)
1436+
if domainName == "" {
1437+
// If domainName not given, no comparison is possible
1438+
return false
1439+
}
1440+
1441+
beforeOld, afterOld, foundOld := strings.Cut(oldValue, ".")
1442+
beforeNew, afterNew, foundNew := strings.Cut(newValue, ".")
1443+
1444+
if !foundOld && foundNew {
1445+
if oldValue == beforeNew {
1446+
// Shortname was expanded to FQDN
1447+
return true
1448+
}
1449+
1450+
if afterNew == domainName {
1451+
return true
1452+
}
1453+
}
1454+
1455+
if (!foundOld && !foundNew) && (beforeOld != beforeNew) {
1456+
// Neither value has a dot but values differ, so no suppression
1457+
return false
1458+
}
1459+
1460+
if (foundOld && foundNew) && (afterOld != afterNew) {
1461+
// Domains differ
1462+
return false
1463+
}
1464+
1465+
// Use case: We pass in a shortname, Foreman expands it and the next "terraform apply"
1466+
// thinks the shortname is a new value.
1467+
if (foundOld && !foundNew) && strings.HasPrefix(oldValue, newValue) {
1468+
return true
1469+
}
1470+
1471+
return false
1472+
}

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ nav:
4444
- 'foreman_partitiontable': 'data-sources/foreman_partitiontable.md'
4545
- 'foreman_provisioningtemplate': 'data-sources/foreman_provisioningtemplate.md'
4646
- 'foreman_puppetclass': 'data-sources/foreman_puppetclass.md'
47+
- 'foreman_setting': 'data-sources/foreman_setting.md'
4748
- 'foreman_smartclassparameter': 'data-sources/foreman_smartclassparameter.md'
4849
- 'foreman_smartproxy': 'data-sources/foreman_smartproxy.md'
4950
- 'foreman_subnet': 'data-sources/foreman_subnet.md'

0 commit comments

Comments
 (0)