From 4a410d1a58dfdb70eca76b0bbebadd13d2bbc0c6 Mon Sep 17 00:00:00 2001 From: agriffit79 Date: Mon, 30 Jan 2023 10:44:26 +0000 Subject: [PATCH] Puppet fixes (#111) * Add config_group support to hosts and hostgroups * Update documentation --- docs/data-sources/foreman_hostgroup.md | 1 + docs/resources/foreman_host.md | 2 ++ docs/resources/foreman_hostgroup.md | 2 ++ foreman/api/client.go | 7 +++++++ foreman/api/host.go | 8 ++++++++ foreman/api/hostgroup.go | 7 +++++++ foreman/resource_foreman_host.go | 20 ++++++++++++++++++++ foreman/resource_foreman_hostgroup.go | 18 ++++++++++++++++++ 8 files changed, 65 insertions(+) diff --git a/docs/data-sources/foreman_hostgroup.md b/docs/data-sources/foreman_hostgroup.md index 9b29f1b1..51b1436b 100644 --- a/docs/data-sources/foreman_hostgroup.md +++ b/docs/data-sources/foreman_hostgroup.md @@ -28,6 +28,7 @@ The following attributes are exported: - `architecture_id` - ID of the architecture associated with this hostgroup. - `compute_profile_id` - ID of the compute profile associated with this hostgroup. +- `config_group_ids` - IDs of the applied config groups. - `content_source_id` - ID of the content source associated with this hostgroup. - `content_view_id` - ID of the content view associated with this hostgroup. - `domain_id` - ID of the domain associated with this hostgroup. diff --git a/docs/resources/foreman_host.md b/docs/resources/foreman_host.md index 49624cf1..4c610b8c 100644 --- a/docs/resources/foreman_host.md +++ b/docs/resources/foreman_host.md @@ -25,6 +25,7 @@ The following arguments are supported: - `compute_attributes` - (Optional) Hypervisor specific VM options. Must be a JSON string, as every compute provider has different attributes schema - `compute_profile_id` - (Optional) - `compute_resource_id` - (Optional, Force New) +- `config_group_ids` - (Optional) IDs of the applied config groups. - `domain_id` - (Optional, Force New) ID of the domain to assign to the host. - `enable_bmc` - (Optional) Enables PMI/BMC functionality. On create and update calls, having this enabled will force a host to poweroff, set next boot to PXE and power on. Defaults to `false`. - `environment_id` - (Optional) ID of the environment to assign to the host. @@ -55,6 +56,7 @@ The following attributes are exported: - `compute_attributes` - Hypervisor specific VM options. Must be a JSON string, as every compute provider has different attributes schema - `compute_profile_id` - - `compute_resource_id` - +- `config_group_ids` - IDs of the applied config groups. - `domain_id` - ID of the domain to assign to the host. - `domain_name` - The domain name of the host. - `enable_bmc` - Enables PMI/BMC functionality. On create and update calls, having this enabled will force a host to poweroff, set next boot to PXE and power on. Defaults to `false`. diff --git a/docs/resources/foreman_hostgroup.md b/docs/resources/foreman_hostgroup.md index 4689f626..9cf8a97c 100644 --- a/docs/resources/foreman_hostgroup.md +++ b/docs/resources/foreman_hostgroup.md @@ -21,6 +21,7 @@ The following arguments are supported: - `architecture_id` - (Optional) ID of the architecture associated with this hostgroup. - `compute_profile_id` - (Optional) ID of the compute profile associated with this hostgroup. +- `config_group_ids` - (Optional) IDs of the applied config groups. - `content_source_id` - (Optional) ID of the content source associated with this hostgroup. - `content_view_id` - (Optional) ID of the content view associated with this hostgroup. - `domain_id` - (Optional) ID of the domain associated with this hostgroup. @@ -47,6 +48,7 @@ The following attributes are exported: - `architecture_id` - ID of the architecture associated with this hostgroup. - `compute_profile_id` - ID of the compute profile associated with this hostgroup. +- `config_group_ids` - IDs of the applied config groups. - `content_source_id` - ID of the content source associated with this hostgroup. - `content_view_id` - ID of the content view associated with this hostgroup. - `domain_id` - ID of the domain associated with this hostgroup. diff --git a/foreman/api/client.go b/foreman/api/client.go index b8a13885..489e11e0 100644 --- a/foreman/api/client.go +++ b/foreman/api/client.go @@ -101,6 +101,12 @@ type ForemanKVParameter struct { Value string `json:"value"` } +// JSON obect for creating and updating puppetattributes on hosts and hostgroups +type PuppetAttribute struct { + Puppetclass_ids []int `json:"puppetclass_ids"` + ConfigGroup_ids []int `json:"config_group_ids"` +} + func FromKV(kv []ForemanKVParameter) (ret map[string]string) { ret = make(map[string]string) for _, pair := range kv { @@ -421,5 +427,6 @@ func (client *Client) WrapJSONWithTaxonomy(name interface{}, item interface{}) ( wrapped["organization_id"] = client.clientConfig.OrganizationID log.Debugf("client.go#WrapJSONWithTaxonomy: item %+v", wrapped) } + return json.Marshal(wrapped) } diff --git a/foreman/api/host.go b/foreman/api/host.go index 7329a21c..27d77361 100644 --- a/foreman/api/host.go +++ b/foreman/api/host.go @@ -95,6 +95,10 @@ type ForemanHost struct { PuppetClassIds []int `json:"puppet_class_ids,omitempty"` // Build token Token string `json:"token,omitempty"` + // List of config groups to apply to the hostg + ConfigGroupIds []int `json:"config_group_ids"` + // The puppetattributes object is only used for create and update, it's not populated on read, hence the duplication + PuppetAttributes PuppetAttribute `json:"puppet_attributes"` } // ForemanInterfacesAttribute representing a hosts defined network interfaces @@ -138,6 +142,7 @@ type foremanHostDecode struct { ForemanHost InterfacesAttributesDecode []ForemanInterfacesAttribute `json:"interfaces"` PuppetClassesDecode []ForemanObject `json:"puppetclasses"` + ConfigGroupsDecode []ForemanObject `json:"config_groups"` HostParametersDecode []ForemanKVParameter `json:"parameters"` } @@ -276,6 +281,7 @@ func (c *Client) CreateHost(ctx context.Context, h *ForemanHost, retryCount int) createdHost.InterfacesAttributes = createdHost.InterfacesAttributesDecode createdHost.PuppetClassIds = foremanObjectArrayToIdIntArray(createdHost.PuppetClassesDecode) + createdHost.ConfigGroupIds = foremanObjectArrayToIdIntArray(createdHost.ConfigGroupsDecode) createdHost.HostParameters = createdHost.HostParametersDecode computeAttributes, _ := c.readComputeAttributes(ctx, createdHost.Id) @@ -317,6 +323,7 @@ func (c *Client) ReadHost(ctx context.Context, id int) (*ForemanHost, error) { } readHost.InterfacesAttributes = readHost.InterfacesAttributesDecode readHost.PuppetClassIds = foremanObjectArrayToIdIntArray(readHost.PuppetClassesDecode) + readHost.ConfigGroupIds = foremanObjectArrayToIdIntArray(readHost.ConfigGroupsDecode) readHost.HostParameters = readHost.HostParametersDecode return &readHost.ForemanHost, nil @@ -372,6 +379,7 @@ func (c *Client) UpdateHost(ctx context.Context, h *ForemanHost, retryCount int) } updatedHost.InterfacesAttributes = updatedHost.InterfacesAttributesDecode updatedHost.PuppetClassIds = foremanObjectArrayToIdIntArray(updatedHost.PuppetClassesDecode) + updatedHost.ConfigGroupIds = foremanObjectArrayToIdIntArray(updatedHost.ConfigGroupsDecode) updatedHost.HostParameters = updatedHost.HostParametersDecode log.Debugf("updatedHost: [%+v]", updatedHost) diff --git a/foreman/api/hostgroup.go b/foreman/api/hostgroup.go index cf611353..6cc53cfd 100644 --- a/foreman/api/hostgroup.go +++ b/foreman/api/hostgroup.go @@ -41,6 +41,8 @@ type ForemanHostgroup struct { ArchitectureId int `json:"architecture_id,omitempty"` // ID of the compute profile associated with this hostgroup ComputeProfileId int `json:"compute_profile_id,omitempty"` + // List of config groups to apply to the hostgroup + ConfigGroupIds []int `json:"config_group_ids"` // ID of the domain associated with this hostgroup DomainId int `json:"domain_id,omitempty"` // ID of the environment associated with this hostgroup @@ -75,6 +77,8 @@ type ForemanHostgroup struct { ContentSourceId int `json:"content_source_id,omitempty"` // Map of HostGroupParameters HostGroupParameters []ForemanKVParameter `json:"group_parameters_attributes,omitempty"` + // The puppetattributes object is only used for create and update, it's not populated on read, hence the duplication + PuppetAttributes PuppetAttribute `json:"puppet_attributes"` } // ForemanHostgroup struct used for JSON decode. Foreman API returns the ids @@ -83,6 +87,7 @@ type ForemanHostgroup struct { type foremanHostGroupDecode struct { ForemanHostgroup PuppetClassesDecode []ForemanObject `json:"puppetclasses"` + ConfigGroupsDecode []ForemanObject `json:"config_groups"` HostGroupParametersDecode []ForemanKVParameter `json:"parameters,omitempty"` } @@ -151,6 +156,7 @@ func (c *Client) ReadHostgroup(ctx context.Context, id int) (*ForemanHostgroup, } readHostgroup.PuppetClassIds = foremanObjectArrayToIdIntArray(readHostgroup.PuppetClassesDecode) + readHostgroup.ConfigGroupIds = foremanObjectArrayToIdIntArray(readHostgroup.ConfigGroupsDecode) readHostgroup.HostGroupParameters = readHostgroup.HostGroupParametersDecode log.Debugf("readHostgroup: [%+v]", readHostgroup) @@ -191,6 +197,7 @@ func (c *Client) UpdateHostgroup(ctx context.Context, h *ForemanHostgroup) (*For } updatedHostgroup.PuppetClassIds = foremanObjectArrayToIdIntArray(updatedHostgroup.PuppetClassesDecode) + updatedHostgroup.ConfigGroupIds = foremanObjectArrayToIdIntArray(updatedHostgroup.ConfigGroupsDecode) updatedHostgroup.HostGroupParameters = updatedHostgroup.HostGroupParametersDecode log.Debugf("updatedHostgroup: [%+v]", updatedHostgroup) diff --git a/foreman/resource_foreman_host.go b/foreman/resource_foreman_host.go index 566bfdd8..02c7ee9b 100644 --- a/foreman/resource_foreman_host.go +++ b/foreman/resource_foreman_host.go @@ -527,6 +527,15 @@ func resourceForemanHost() *schema.Resource { }, Description: "IDs of the applied puppet classes.", }, + "config_group_ids": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + Description: "IDs of the applied config groups.", + }, "compute_resource_id": { Type: schema.TypeInt, Optional: true, @@ -775,7 +784,15 @@ func buildForemanHost(d *schema.ResourceData) *api.ForemanHost { if attr, ok = d.GetOk("puppet_class_ids"); ok { attrSet := attr.(*schema.Set) host.PuppetClassIds = conv.InterfaceSliceToIntSlice(attrSet.List()) + host.PuppetAttributes.Puppetclass_ids = conv.InterfaceSliceToIntSlice(attrSet.List()) } + + if attr, ok = d.GetOk("config_group_ids"); ok { + attrSet := attr.(*schema.Set) + host.ConfigGroupIds = conv.InterfaceSliceToIntSlice(attrSet.List()) + host.PuppetAttributes.ConfigGroup_ids = conv.InterfaceSliceToIntSlice(attrSet.List()) + } + if attr, ok = d.GetOk("parameters"); ok { host.HostParameters = api.ToKV(attr.(map[string]interface{})) } @@ -951,6 +968,7 @@ func setResourceDataFromForemanHost(d *schema.ResourceData, fh *api.ForemanHost) d.Set("image_id", fh.ImageId) d.Set("model_id", fh.ModelId) d.Set("puppet_class_ids", fh.PuppetClassIds) + d.Set("config_group_ids", fh.ConfigGroupIds) d.Set("token", fh.Token) setResourceDataFromForemanInterfacesAttributes(d, fh) @@ -1175,6 +1193,8 @@ func resourceForemanHostUpdate(ctx context.Context, d *schema.ResourceData, meta d.HasChange("operatingsystem_id") || d.HasChange("interfaces_attributes") || d.HasChange("build") || + d.HasChange("puppet_class_ids") || + d.HasChange("config_group_ids") || d.Get("managed") == false { log.Debugf("host: [%+v]", h) diff --git a/foreman/resource_foreman_hostgroup.go b/foreman/resource_foreman_hostgroup.go index 1a3138b3..9c8eb30b 100644 --- a/foreman/resource_foreman_hostgroup.go +++ b/foreman/resource_foreman_hostgroup.go @@ -109,6 +109,16 @@ func resourceForemanHostgroup() *schema.Resource { Description: "ID of the compute profile associated with this hostgroup.", }, + "config_group_ids": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + Description: "IDs of the applied config groups.", + }, + "content_source_id": { Type: schema.TypeInt, Optional: true, @@ -264,6 +274,12 @@ func buildForemanHostgroup(d *schema.ResourceData) *api.ForemanHostgroup { hostgroup.ComputeProfileId = attr.(int) } + if attr, ok = d.GetOk("config_group_ids"); ok { + attrSet := attr.(*schema.Set) + hostgroup.ConfigGroupIds = conv.InterfaceSliceToIntSlice(attrSet.List()) + hostgroup.PuppetAttributes.ConfigGroup_ids = conv.InterfaceSliceToIntSlice(attrSet.List()) + } + if attr, ok = d.GetOk("content_source_id"); ok { hostgroup.ContentSourceId = attr.(int) } @@ -307,6 +323,7 @@ func buildForemanHostgroup(d *schema.ResourceData) *api.ForemanHostgroup { if attr, ok = d.GetOk("puppet_class_ids"); ok { attrSet := attr.(*schema.Set) hostgroup.PuppetClassIds = conv.InterfaceSliceToIntSlice(attrSet.List()) + hostgroup.PuppetAttributes.Puppetclass_ids = conv.InterfaceSliceToIntSlice(attrSet.List()) } if attr, ok = d.GetOk("puppet_proxy_id"); ok { @@ -339,6 +356,7 @@ func setResourceDataFromForemanHostgroup(d *schema.ResourceData, fh *api.Foreman d.Set("parameters", api.FromKV(fh.HostGroupParameters)) d.Set("architecture_id", fh.ArchitectureId) d.Set("compute_profile_id", fh.ComputeProfileId) + d.Set("config_group_ids", fh.ConfigGroupIds) d.Set("content_source_id", fh.ContentSourceId) d.Set("content_view_id", fh.ContentViewId) d.Set("domain_id", fh.DomainId)