foreman_opentofu 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +107 -55
  3. data/app/assets/javascripts/foreman_opentofu/locale/de_DE/foreman_opentofu.js +136 -0
  4. data/app/assets/javascripts/foreman_opentofu/locale/en/foreman_opentofu.js +80 -2
  5. data/app/controllers/api/v2/tf_states_controller.rb +13 -13
  6. data/app/controllers/concerns/foreman_opentofu/api/v2/hosts_controller_power_override.rb +22 -0
  7. data/app/controllers/concerns/foreman_opentofu/hosts_controller_power_override.rb +14 -0
  8. data/app/lib/foreman_opentofu/concerns/base_template_scope_extensions.rb +50 -15
  9. data/app/models/concerns/foreman_opentofu/vm_command_collection_normalization.rb +68 -1
  10. data/app/models/foreman_opentofu/compute_vm.rb +75 -8
  11. data/app/models/foreman_opentofu/opentofu_vm_commands.rb +8 -5
  12. data/app/models/foreman_opentofu/tf_state.rb +3 -0
  13. data/app/models/foreman_opentofu/tofu.rb +57 -1
  14. data/app/overrides/compute_resources_vms/tofu_remove_new_vm_from_removable_layout.rb +7 -0
  15. data/app/services/foreman_opentofu/app_wrapper.rb +11 -1
  16. data/app/services/foreman_opentofu/authorizer_power_override.rb +15 -0
  17. data/app/services/foreman_opentofu/key_pairs.rb +26 -0
  18. data/app/services/foreman_opentofu/opentofu_executer.rb +79 -8
  19. data/app/services/foreman_opentofu/power_capability.rb +14 -0
  20. data/app/services/foreman_opentofu/provider_type.rb +47 -2
  21. data/app/services/foreman_opentofu/renderer/source/snapshot.rb +25 -0
  22. data/app/services/foreman_opentofu/template_snapshot_service.rb +68 -0
  23. data/app/services/foreman_opentofu/tofu_key_pair.rb +24 -0
  24. data/app/views/api/v2/compute_resources/tofu.json.rabl +1 -0
  25. data/app/views/compute_resources/form/_tofu.html.erb +3 -3
  26. data/app/views/compute_resources_vms/form/tofu/_base.html.erb +11 -10
  27. data/app/views/compute_resources_vms/form/tofu/_network.html.erb +4 -1
  28. data/app/views/compute_resources_vms/form/tofu/_volume.html.erb +4 -2
  29. data/app/views/foreman_opentofu/compute_resources_vms/_indexed_networks_fields.html.erb +3 -4
  30. data/app/views/foreman_opentofu/compute_resources_vms/_indexed_volumes_fields.html.erb +1 -3
  31. data/app/views/foreman_opentofu/compute_resources_vms/form/_removable_layout.html.erb +5 -0
  32. data/app/views/foreman_opentofu/compute_resources_vms/form/tofu/_interfaces_fields.html.erb +3 -1
  33. data/app/views/foreman_opentofu/compute_resources_vms/form/tofu/_volumes_fields.html.erb +18 -4
  34. data/app/views/templates/provisioning/hetzner_provision_host.erb +37 -22
  35. data/lib/foreman_opentofu/engine.rb +13 -2
  36. data/lib/foreman_opentofu/provider_types/hetzner.rb +79 -22
  37. data/lib/foreman_opentofu/provider_types/nutanix.rb +1 -1
  38. data/lib/foreman_opentofu/version.rb +1 -1
  39. data/lib/tasks/snapshots.rake +63 -0
  40. data/locale/de_DE/LC_MESSAGES/foreman_opentofu.mo +0 -0
  41. data/locale/de_DE/foreman_opentofu.po +137 -0
  42. data/locale/en/LC_MESSAGES/foreman_opentofu.mo +0 -0
  43. data/locale/en/foreman_opentofu.po +80 -3
  44. data/locale/foreman_opentofu.pot +149 -11
  45. data/test/controllers/api/v2/tf_states_controller_test.rb +71 -2
  46. data/test/factories/compute_resources.rb +8 -0
  47. data/test/fixtures/renderer/snapshots/ProvisioningTemplate/opentofu_script/Hetzner_provision_default.empty.snap.txt +72 -0
  48. data/test/fixtures/renderer/snapshots/ProvisioningTemplate/opentofu_script/Hetzner_provision_default.hetzner_host.snap.txt +74 -0
  49. data/test/fixtures/renderer/snapshots/ProvisioningTemplate/opentofu_script/Nutanix_provision_default.empty.snap.txt +56 -0
  50. data/test/fixtures/renderer/snapshots/ProvisioningTemplate/opentofu_script/Nutanix_provision_default.nutanix_host.snap.txt +62 -0
  51. data/test/fixtures/renderer/snapshots.yaml +6 -0
  52. data/test/fixtures/snapshots/foreman_opentofu/base_template_scope_extensions_test/resource_block.txt +8 -0
  53. data/test/lib/foreman_opentofu/concerns/base_template_scope_extensions_test.rb +77 -4
  54. data/test/models/foreman_opentofu/compute_vm_test.rb +32 -0
  55. data/test/models/foreman_opentofu/opentofu_vm_commands_test.rb +110 -49
  56. data/test/models/foreman_opentofu/tf_state_test.rb +19 -0
  57. data/test/models/foreman_opentofu/tofu_test.rb +70 -0
  58. data/test/renderer/renderer_test.rb +60 -0
  59. data/test/services/app_wrapper_test.rb +29 -0
  60. data/test/services/foreman_opentofu/provider_type_test.rb +106 -6
  61. data/test/services/key_pairs_test.rb +32 -0
  62. data/test/services/opentofu_executer_test.rb +141 -3
  63. data/test/services/tofu_key_pair_test.rb +34 -0
  64. metadata +42 -6
  65. data/locale/gemspec.rb +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3f7d22aa8036489bd3356eff61fb54608d15c1ced729e2a592257e3383213a5
4
- data.tar.gz: 3a7272bc1b5e4a36974b859362d18209d3cbc36293e00c9722a2c6991bdcd0ee
3
+ metadata.gz: aac98f7ab29438afb053493e3ef572e5374d5140eec49cc67e4f4d9787776a08
4
+ data.tar.gz: 85f7eb01a3b220b06b357c5ef9b0270bbf49fc19ea286f7e421964871f7bf726
5
5
  SHA512:
6
- metadata.gz: 7efbc5b6168046cac8b716864636ac9f16acd32b229e017ff876d93cde3aecf3ff4e94572e09407ecf2e3de6462592efd46e4bcacf49285c765aceba4e32787b
7
- data.tar.gz: f7b2493f8dcca6913ab2167f9cb529610d0e9c91240d43ea324503b24352fa5b0cb774b8ffee4f1cf76791e38ef9440c90ad0bfdbe8390b3b62fa1d4d09d38f5
6
+ metadata.gz: 3a8231fb351a2f809d768880ed32dd0be78b13333453f4d5fbb71fbcc4c801dc963c0b08beeed69ba916c307c669856d17e8513d1cdb4923f25e0c6b49487e73
7
+ data.tar.gz: c221f8852cfedf5d07bb40bb93832c2512b77b59b58c043dd8f23cfdf61ee102321be84825158e61981bcd1255b4bc2b6c18fa589d368c5c0d2df16dc2697994
data/README.md CHANGED
@@ -64,7 +64,7 @@ Provisioning workflow:
64
64
 
65
65
  Provider-specific details (for example Nutanix, Hetzner) are handled entirely through OpenTofu scripts.
66
66
 
67
- ### Create new ProviderType
67
+ ### Add support for a new Tofu-Provider
68
68
 
69
69
  This Plugin empowers you to add support of a new backend VM- or Cloud-Platform yourself.
70
70
  Follow these simple steps to do so:
@@ -80,11 +80,39 @@ You may use the UI-Editor in Hosts -> Templates -> Provisioning Templates to cre
80
80
  Either clone a pre-installed template or create one from scratch.
81
81
  In the latter case be sure to select the correct Template Type: OpenTofu Script template.
82
82
 
83
+
84
+ #### Create Provider Type
85
+
86
+ To let the Foreman OpenTofu Plugin know about your new Provider Type, one additional file has to be created in `/lib/foreman_opentofu/provider_types/`.
87
+
88
+ A very simple ProviderType file to add a new Provider named `nutanix` has to be located in `lib/foreman_opentofu/provider_types/nutanix.rb` and might look like this:
89
+
90
+ ```ruby
91
+ ForemanOpentofu::ProviderTypeManager.register('nutanix') do
92
+ end
93
+ ```
94
+
95
+ Additional informations about the ProviderType can be set within the `register`-block:
96
+
97
+ ##### `default_attributes`
98
+
99
+ Define values that should be set as default for attributes.
100
+ The values do not have to be defined in the config-file.
101
+ If attributes are also defined in the config-file and therefore set during Host creation, the default\_attribute values will be overwritten.
102
+
103
+ ```ruby
104
+ ForemanOpentofu::ProviderTypeManager.register('nutanix') do
105
+ @default_attributes = {
106
+ 'enable_cpu_passthrough' => true,
107
+ 'num_threads_per_core' => 2,
108
+ }
109
+ end
110
+ ```
111
+
83
112
  #### Create Parameter Config
84
113
 
85
- To define which Virtual Machine parameters can be set for a new Host a new config file under `/config` must be added.
86
- Feel free to use either YAML or JSON (be sure to end the filename with `.json` or `.yaml`).
87
- The config file defines an array of dicts, where each dict represents a configuration-parameter.
114
+ To define which Virtual Machine parameters can be set for a new Host the `self.provider_attrs` variable must be defined within the `register`-block.
115
+ The `provider_attrs`-variable defines an Array of Dicts/Hashes, where each Dict/Hash represents a configuration-parameter.
88
116
 
89
117
  A config-parameter has the following values:
90
118
 
@@ -98,54 +126,53 @@ A config-parameter has the following values:
98
126
  * `help`: Tooltip describing what that value does and what values are allowed
99
127
  * `mandatory`: `true`/`false` defines if omitting the value triggers an error
100
128
  * `options`: array of strings representing the possible values
129
+ * `default`: default-value should be specified if parameter is mandatory and options is empty
101
130
  * `group`: define where the value should be configured
102
131
  * `vm`: ones per Host in the 'Virtual Machine' tab,
103
132
  * `disk`: for each defined disk/volume in the 'Virtual Machine' tab
104
133
  * `nic`: for each defined network-interface on the 'Interfaces' tab
105
134
 
106
- A short config file might look like this:
107
-
108
- ```json
109
- [
110
- { "name": "memory_size_mib", "type": "number", "group": "vm", "mandatory": false,
111
- "label": "Memory (MB)" },
112
- { "name": "boot_type", "type": "select", "group": "vm", "mandatory": false,
113
- "label": "Firmware", "options": [ "UEFI", "LEGACY", "SECURE_BOOT" ] },
114
- { "name": "disk_size_mib", "type": "number", "group": "disk", "mandatory": true,
115
- "label": "Size (MB)" },
116
- { "name": "model", "type": "select", "group": "nic", "mandatory": true,
117
- "options": [ "VIRTIO", "E1000" ] }
135
+ A short definition might look like this:
136
+
137
+ ```ruby
138
+ self.provider_attrs = [
139
+ { name: 'memory_size_mib', type: 'number', group: 'vm', mandatory: false,
140
+ label: 'Memory (MB)' },
141
+ { name: 'boot_type', type: 'select', group: 'vm', mandatory: false,
142
+ label: 'Firmware', options: [ 'UEFI', 'LEGACY', 'SECURE_BOOT' ] },
143
+ { name: 'disk_size_mib', type: 'number', group: 'disk', mandatory: true,
144
+ label: 'Size (MB)' },
145
+ { name: 'model', type: 'select', group: 'nic', mandatory: true,
146
+ options: [ 'VIRTIO', 'E1000' ] }
118
147
  ]
119
148
  ```
120
149
 
121
- The name of the file must be the same as the provider-type name we set in the next step (e.g. `/config/nutanix.json`).
122
-
123
150
  ##### Dynamic Config Parameter
124
151
 
125
152
  Sometimes it is necessary to provide a list of possible values that are defined by the backend-service.
126
153
  Curating the 'options'-Array is tedious at best or not possible if multiple instances of the backend service are in use.
127
154
  This can be addressed by specifiying an OpenTofu provider's [DataSource](https://opentofu.org/docs/language/data-sources/) in the following way:
128
155
 
129
- ```json
156
+ ```ruby
130
157
  {
131
- "name": "volume_group", "type": "select", "group": "disk", "mandatory": true, "label": "Volume Group",
132
- "options": {
133
- "data_source": {
134
- "name": "nutanix_volume_groups_v2",
135
- "arguments": {
136
- "filter": "name eq 'volume_group_test'",
137
- "limit": 20
158
+ name: 'volume_group', type: 'select', group: 'disk', mandatory: true, label: 'Volume Group',
159
+ options: {
160
+ data_source: {
161
+ name: 'nutanix_volume_groups_v2',
162
+ arguments: {
163
+ filter: 'name eq 'volume_group_test'',
164
+ limit: 20
138
165
  },
139
- "entity": {
140
- "id": "metadata.uuid"
166
+ entity: {
167
+ id: 'metadata.uuid'
141
168
  }
142
169
  },
143
- "output_path_postfix": "volume_groups"
170
+ output_path_postfix: 'volume_groups'
144
171
  }
145
172
  }
146
173
 
147
174
  ```
148
- The GUI requires a list of objects that at least contain a name and an id for each select-option.
175
+ The GUI requires a list of objects that at least contains a name and an id for each select-option.
149
176
  The `entity` section can be used to define a specific value from an object within the list that the DataSource returns.
150
177
  If the object already has `name` and `id` entries, these will automatically used.
151
178
  In the above example `name` exists in the object and can be used.
@@ -170,49 +197,57 @@ output "resources" {
170
197
 
171
198
  Some config parameter names have special meanings.
172
199
  For instance, Image-based Deployment requires binding images available on the backend-service with Operating Systems configured in Foreman.
200
+
201
+ ###### available\_images
202
+
173
203
  To enable Foreman OpenTofu to display the available images, a `select`-parameter with the name `available_images` must be specified.
174
204
  It is recommended to tie this to a data-source available in the OpenTofu provider.
175
205
 
176
- ```json
206
+ ```ruby
177
207
  {
178
- "name": "available_images", "type": "select",
179
- "options": {
180
- "data_source": {
181
- "name": "hcloud_images",
182
- "arguments": { "with_architecture": ["x86"] }
208
+ name: 'available_images', type: 'select',
209
+ options: {
210
+ data_source: {
211
+ name: 'hcloud_images',
212
+ arguments: { with_architecture: ['x86'] }
183
213
  },
184
- "output_path_postfix": "images"
214
+ output_path_postfix: 'images'
185
215
  }
186
216
  }
187
217
  ```
188
218
 
219
+ ###### available\_ssh\_keys
189
220
 
190
- #### Create Provider Type
191
-
192
- To let the Foreman OpenTofu Plugin know about your new Provider Type, one additional file has to be created in `/lib/foreman_opentofu/provider_types/`.
193
-
194
- A very simple ProviderType file to add a new Provider named `nutanix` has to be located in `lib/foreman_opentofu/provider_types/nutanix.rb` and might look like this:
221
+ Cloud-based Providers usually require an SSH key pair to configure image-based hosts.
222
+ This dynamic data-source should provide a list of SSH keys known to the cloud-provider.
195
223
 
196
224
  ```ruby
197
- ForemanOpentofu::ProviderTypeManager.register('nutanix') do
198
- end
225
+ {
226
+ name: 'available_ssh_keys', type: 'select',
227
+ label: 'SSH-Deployment-Keys', options: {
228
+ data_source: {
229
+ name: 'hcloud_ssh_keys',
230
+ },
231
+ entity: {
232
+ fingerprint: 'fingerprint',
233
+ },
234
+ output_path_postfix: 'ssh_keys',
235
+ }
236
+ }
199
237
  ```
200
238
 
201
- Additional informations about the ProviderType can be set within the `register`-block:
239
+ #### Protection against Accidental Resource Recreation
202
240
 
203
- ##### `default_attributes`
241
+ Depending on the settings that are changed for an existing resource (e.g. a Host), OpenTofu may decide that it has to destroy the existing resource and create a new one.
242
+ This is almost never what we want for a managed Foreman Host.
243
+ After editing a host, this Plugin checks OpenTofu's plan for applying the changes.
244
+ If the plan includes a 'delete'-action, it will raise an exception and will not apply the changes.
204
245
 
205
- Define values that should be set as default for attributes.
206
- The values do not have to be defined in the config-file.
207
- If attributes are also defined in the config-file and therefore set during Host creation, the default\_attribute values will be overwritten.
246
+ In case the recreation of a specific resource type is expected behavior, the resource type can be added to an allow-list within the ProviderType definition file.
247
+ The following example allows OpenTofu to destroy and recreate resources of type `hcloud_volume`:
208
248
 
209
249
  ```ruby
210
- ForemanOpentofu::ProviderTypeManager.register('nutanix') do
211
- @default_attributes = {
212
- 'enable_cpu_passthrough' => true,
213
- 'num_threads_per_core' => 2,
214
- }
215
- end
250
+ self.recreate_type_allow_list = ['hcloud_volume']
216
251
  ```
217
252
 
218
253
 
@@ -302,6 +337,23 @@ bundle exec foreman start
302
337
 
303
338
  See details in [foreman plugin development](https://projects.theforeman.org/projects/foreman/wiki/How_to_Create_a_Plugin)
304
339
 
340
+
341
+ ### Testing
342
+
343
+ #### Template Snapshots
344
+
345
+ The OpenTofu templates are tested against recorded snapshots similar to the Provisioning Templates in Foreman.
346
+ The snapshots are generated by rendering the templates with predefined fixture-data using the following command in the foreman-directory:
347
+
348
+ ```shell
349
+ bundle exec rake foreman_opentofu:snapshots:generate RAILS_ENV=test
350
+ ```
351
+
352
+ At the moment the fixture-data is defined in `app/services/foreman_opentofu/template_snapshot_service.rb`.
353
+
354
+ Templates to test must be added to `test/fixtures/renderer/snapshots.yaml`.
355
+
356
+
305
357
  ## Contributing
306
358
 
307
359
  Fork and send a Pull Request or create Issue. Thank you.
@@ -0,0 +1,136 @@
1
+ locales['foreman_opentofu'] = locales['foreman_opentofu'] || {}; locales['foreman_opentofu']['de_DE'] = {
2
+ "domain": "foreman_opentofu",
3
+ "locale_data": {
4
+ "foreman_opentofu": {
5
+ "": {
6
+ "Project-Id-Version": "foreman_opentofu 0.0.4",
7
+ "Report-Msgid-Bugs-To": "",
8
+ "PO-Revision-Date": "2026-02-16 11:45+0000",
9
+ "Last-Translator": "Markus Bucher <bucher@atix.de>, 2026",
10
+ "Language-Team": "German (Germany) (https://app.transifex.com/foreman/teams/114/de_DE/)",
11
+ "MIME-Version": "1.0",
12
+ "Content-Type": "text/plain; charset=UTF-8",
13
+ "Content-Transfer-Encoding": "8bit",
14
+ "Language": "de_DE",
15
+ "Plural-Forms": "nplurals=2; plural=(n != 1);",
16
+ "lang": "de_DE",
17
+ "domain": "foreman_opentofu",
18
+ "plural_forms": "nplurals=2; plural=(n != 1);"
19
+ },
20
+ "127.0.0.1": [
21
+ "127.0.0.1"
22
+ ],
23
+ "Add Interface": [
24
+ "Interface hinzufügen"
25
+ ],
26
+ "Add Volume": [
27
+ "Volume hinzufügen"
28
+ ],
29
+ "Cache slow calls to OpenTofu Compute resources to speed up page rendering": [
30
+ "Ergebnisse langsamer Abfragen zu OpenTofu zwischenspeichern um das Laden der Seiten zu beschleunigen"
31
+ ],
32
+ "Caching": [
33
+ "Zwischenspeicher"
34
+ ],
35
+ "Common fields": [
36
+ "Allgemeine Werte"
37
+ ],
38
+ "Disabled": [
39
+ "Deaktiviert"
40
+ ],
41
+ "Does this image support user data input (e.g. via cloud-init)?": [
42
+ "Unterstützt dieses Image die Eingabe von Benutzerdaten (z.B. via cloud-init)?"
43
+ ],
44
+ "Enable caching": [
45
+ "Caching aktivieren"
46
+ ],
47
+ "Enabled": [
48
+ "Aktiviert"
49
+ ],
50
+ "ID of the Image on the Hypervisor": [
51
+ "ID des Abbilds auf dem Hypervisor"
52
+ ],
53
+ "Image": [
54
+ "Abbild"
55
+ ],
56
+ "Image \\\"%{image}\\\" needs user data, but \\\"%{os}\\\" is not associated to any provisioning template of the kind user_data. Please associate it with a suitable template or uncheck 'User data' from the image definition.": [
57
+ "Abbild \\\"%{image}\\\" benötigt Benutzerdaten. Jedoch ist \\\"%{os}\\\" keine Bereitstellungsvorlage der Art user_data zugeordnet. Bitte weisen Sie eine geeignete Vorlage zu, oder deaktivieren sie \\\"Benutzerdaten\\\" in der Abbilddefinition."
58
+ ],
59
+ "Image ID": [
60
+ "Abbild ID"
61
+ ],
62
+ "Network interfaces": [
63
+ "Netzwerkinterface"
64
+ ],
65
+ "No networks found.": [
66
+ "Keine Netzwerke gefunden."
67
+ ],
68
+ "Number of Bits for the SSH-Key required to provision hosts on image-based providers.": [
69
+ "Bitanzahl des SSH-Schlüssels der für die abbildbasierte Bereitstellung von Hosts benötigt wird."
70
+ ],
71
+ "Number of seconds a run of OpenTofu command is allowed to report TfState back to the plugin.": [
72
+ "Anzahl der Sekunden in denen ein OpenTofu Befehl einen TfState an das Plugin zurücksenden darf."
73
+ ],
74
+ "OpenTofu": [
75
+ "OpenTofu"
76
+ ],
77
+ "OpenTofu Provider": [
78
+ "OpenTofu Provider"
79
+ ],
80
+ "OpenTofu Script template": [
81
+ "OpenTofu Script Vorlage"
82
+ ],
83
+ "OpenTofu Template": [
84
+ "OpenTofu Vorlage"
85
+ ],
86
+ "Password to authenticate with - used for SSH finish step.": [
87
+ "Passwort mit dem sich authentifiziert wird - benötigt, um den letzten Schritt mit SSH abzuschließen."
88
+ ],
89
+ "Please select an image": [
90
+ "Bitte Abbild auswählen"
91
+ ],
92
+ "Power change operations are not enabled on this host.": [
93
+ "Power-Operationen werden auf diesem Host nicht unterstützt"
94
+ ],
95
+ "SSH-Key Length": [
96
+ "SSH-Schlüssellänge"
97
+ ],
98
+ "TODO: Description of ForemanPluginTemplate.": [
99
+ ""
100
+ ],
101
+ "TfState Token Timeout": [
102
+ "TfState Token Timeout"
103
+ ],
104
+ "The user that is used to ssh into the instance, normally cloud-user, ec2-user, ubuntu, root etc": [
105
+ "Der Benutzer für die SSH-Verbindung zur Instanz. Normalerweise cloud-user, ec2-user, ubuntu, root, etc."
106
+ ],
107
+ "URL": [
108
+ "URL"
109
+ ],
110
+ "Unable to find template specified by %s setting": [
111
+ "Konnte Vorlage mit der %s-Einstellung nicht finden"
112
+ ],
113
+ "Unable to render provisioning template": [
114
+ "Bereitstellungsvorlage konnte nicht verarbeitet werden"
115
+ ],
116
+ "VM Config": [
117
+ "VM Konfiguration"
118
+ ],
119
+ "add new network interface": [
120
+ "neues Netzwerkinterface hinzufügen"
121
+ ],
122
+ "add new storage volume": [
123
+ "neues Speichervolume hinzufügen"
124
+ ],
125
+ "e.g. admin": [
126
+ "z.B. admin"
127
+ ],
128
+ "remove network interface": [
129
+ "Netzwerkinterface entfernen"
130
+ ],
131
+ "remove storage volume": [
132
+ "entferne Speichervolume"
133
+ ]
134
+ }
135
+ }
136
+ };
@@ -3,7 +3,7 @@
3
3
  "locale_data": {
4
4
  "foreman_opentofu": {
5
5
  "": {
6
- "Project-Id-Version": "foreman_opentofu 1.0.0",
6
+ "Project-Id-Version": "foreman_opentofu 0.0.4",
7
7
  "Report-Msgid-Bugs-To": "",
8
8
  "PO-Revision-Date": "2026-02-16 18:46+0000",
9
9
  "Last-Translator": "FULL NAME <EMAIL@ADDRESS>",
@@ -20,9 +20,60 @@
20
20
  "127.0.0.1": [
21
21
  ""
22
22
  ],
23
+ "Add Interface": [
24
+ ""
25
+ ],
26
+ "Add Volume": [
27
+ ""
28
+ ],
29
+ "Cache slow calls to OpenTofu Compute resources to speed up page rendering": [
30
+ ""
31
+ ],
32
+ "Caching": [
33
+ ""
34
+ ],
23
35
  "Common fields": [
24
36
  ""
25
37
  ],
38
+ "Disabled": [
39
+ ""
40
+ ],
41
+ "Does this image support user data input (e.g. via cloud-init)?": [
42
+ ""
43
+ ],
44
+ "Enable caching": [
45
+ ""
46
+ ],
47
+ "Enabled": [
48
+ ""
49
+ ],
50
+ "ID of the Image on the Hypervisor": [
51
+ ""
52
+ ],
53
+ "Image": [
54
+ ""
55
+ ],
56
+ "Image \\\"%{image}\\\" needs user data, but \\\"%{os}\\\" is not associated to any provisioning template of the kind user_data. Please associate it with a suitable template or uncheck 'User data' from the image definition.": [
57
+ ""
58
+ ],
59
+ "Image ID": [
60
+ ""
61
+ ],
62
+ "Network interfaces": [
63
+ ""
64
+ ],
65
+ "No networks found.": [
66
+ ""
67
+ ],
68
+ "Number of Bits for the SSH-Key required to provision hosts on image-based providers.": [
69
+ ""
70
+ ],
71
+ "Number of seconds a run of OpenTofu command is allowed to report TfState back to the plugin.": [
72
+ ""
73
+ ],
74
+ "OpenTofu": [
75
+ ""
76
+ ],
26
77
  "OpenTofu Provider": [
27
78
  ""
28
79
  ],
@@ -32,12 +83,27 @@
32
83
  "OpenTofu Template": [
33
84
  ""
34
85
  ],
35
- "Storage": [
86
+ "Password to authenticate with - used for SSH finish step.": [
87
+ ""
88
+ ],
89
+ "Please select an image": [
90
+ ""
91
+ ],
92
+ "Power change operations are not enabled on this host.": [
93
+ ""
94
+ ],
95
+ "SSH-Key Length": [
36
96
  ""
37
97
  ],
38
98
  "TODO: Description of ForemanPluginTemplate.": [
39
99
  ""
40
100
  ],
101
+ "TfState Token Timeout": [
102
+ ""
103
+ ],
104
+ "The user that is used to ssh into the instance, normally cloud-user, ec2-user, ubuntu, root etc": [
105
+ ""
106
+ ],
41
107
  "URL": [
42
108
  ""
43
109
  ],
@@ -50,8 +116,20 @@
50
116
  "VM Config": [
51
117
  ""
52
118
  ],
119
+ "add new network interface": [
120
+ ""
121
+ ],
122
+ "add new storage volume": [
123
+ ""
124
+ ],
53
125
  "e.g. admin": [
54
126
  ""
127
+ ],
128
+ "remove network interface": [
129
+ ""
130
+ ],
131
+ "remove storage volume": [
132
+ ""
55
133
  ]
56
134
  }
57
135
  }
@@ -2,10 +2,8 @@ module Api
2
2
  module V2
3
3
  class TfStatesController < ::Api::V2::BaseController
4
4
  include ::Api::Version2
5
+ include ::Foreman::Controller::FilterParameters
5
6
 
6
- # TODO: verify this
7
- # We don't require any of these methods for provisioning
8
- # skip_before_action :require_login, :check_user_enabled, :session_expiry, :update_activity_time, :set_taxonomy, :authorize, unless: -> { preview? }
9
7
  skip_before_action :set_taxonomy
10
8
 
11
9
  # Allow HTTP POST methods without CSRF
@@ -14,6 +12,11 @@ module Api
14
12
  # overwrite authorize with the local token-based authorization
15
13
  before_action :authorize, except: [:destroy]
16
14
 
15
+ # Don't log tfstate response in logs as it can have sensitive information
16
+ skip_after_action :log_response_body
17
+
18
+ filter_parameters :version, :terraform_version, :serial, :lineage, :outputs, :resources, :tf_state, :check_results
19
+
17
20
  resource_description do
18
21
  api_version 'v2'
19
22
  api_base_url '/foreman_opentofu/api'
@@ -22,15 +25,13 @@ module Api
22
25
  def show
23
26
  state = ForemanOpentofu::TfState.find_by(name: params[:name])
24
27
 
25
- if state
26
- render plain: state.state, content_type: 'application/json'
27
- else
28
- render plain: '', status: :not_found
29
- end
28
+ return head :not_found unless state
29
+
30
+ render plain: state.state, content_type: 'application/json'
30
31
  end
31
32
 
32
33
  def create
33
- raw_state = request.body.read
34
+ raw_state = request.raw_post
34
35
  if raw_state.blank?
35
36
  render plain: 'Missing state body', status: :unprocessable_entity
36
37
  return
@@ -41,10 +42,9 @@ module Api
41
42
  state = ForemanOpentofu::TfState.find_or_initialize_by(name: params[:name])
42
43
  state.state = raw_state
43
44
  state.save!
44
- render plain: '', status: :ok
45
- rescue JSON::ParserError => e
46
- Rails.logger.error("Invalid state JSON: #{e.message}")
47
- render plain: 'Invalid state format', status: :unprocessable_entity
45
+ head :ok
46
+ rescue JSON::ParserError
47
+ render plain: 'Invalid state format', status: :bad_request
48
48
  end
49
49
  end
50
50
 
@@ -0,0 +1,22 @@
1
+ module ForemanOpentofu
2
+ module Api
3
+ module V2
4
+ module HostsControllerPowerOverride
5
+ def power
6
+ if ForemanOpentofu::PowerCapability.power_change_disabled_for_host?(@host)
7
+ return render_error :custom_error, status: :unprocessable_entity, locals: { message: _('Power change operations are not enabled on this host.') }
8
+ end
9
+
10
+ super
11
+ end
12
+
13
+ def power_status
14
+ result = PowerManager::PowerStatus.safe_power_state(@host, timeout: params[:timeout])
15
+ result[:statusText] = _('Power change operations are not enabled on this host.') if ForemanOpentofu::PowerCapability.power_change_disabled_for_host?(@host)
16
+
17
+ render json: result
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module ForemanOpentofu
2
+ module HostsControllerPowerOverride
3
+ def power
4
+ if ForemanOpentofu::PowerCapability.power_change_disabled_for_host?(@host)
5
+ return process_error(
6
+ redirect: :back,
7
+ error_msg: _('Power change operations are not enabled on this host.')
8
+ )
9
+ end
10
+
11
+ super
12
+ end
13
+ end
14
+ end