Skip to content

Commit 2277742

Browse files
jeremylenzclaude
andcommitted
Fixes #38986 - Support runtime evaluation of Procs in plugin metadata
Allow plugins to register metadata as lambdas that are evaluated at runtime instead of at registration time. This enables dynamic state changes without requiring a server restart. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 637f3be commit 2277742

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

app/helpers/application_helper.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,8 @@ def core_app_metadata
423423
end
424424

425425
def app_metadata
426-
core_app_metadata.merge(
427-
::Foreman::Plugin.app_metadata_registry.all_plugin_metadata
428-
)
426+
::Foreman::Plugin::AppMetadataRegistry.resolve_procs(core_app_metadata)
427+
.merge(::Foreman::Plugin.app_metadata_registry.all_plugin_metadata_resolved)
429428
end
430429

431430
def ui_settings

app/registries/foreman/plugin/app_metadata_registry.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ def register(plugin_name, data = {})
1717
def all_plugin_metadata
1818
@plugin_metadata
1919
end
20+
21+
def all_plugin_metadata_resolved
22+
@plugin_metadata.transform_values { |v| self.class.resolve_procs(v) }
23+
end
24+
25+
# Evaluates any Proc values in the given hash, calling them and replacing
26+
# them with their return values. All other values remain unchanged.
27+
# @param hash [Hash] A hash potentially containing Proc values
28+
# @return [Hash] A new hash with Procs evaluated
29+
def self.resolve_procs(hash)
30+
hash.transform_values { |v| v.is_a?(Proc) ? v.call : v }
31+
end
2032
end
2133
end
2234
end

test/helpers/application_helper_test.rb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,69 @@ def test_generate_link_for
133133
assert_equal "/new/hosts/#{@host.id}", result
134134
end
135135
end
136+
137+
describe 'app_metadata and evaluate_metadata_hash' do
138+
test 'app_metadata returns hash with core and plugin metadata' do
139+
result = app_metadata
140+
141+
assert_kind_of Hash, result
142+
assert result.key?(:version)
143+
assert result.key?(:UISettings)
144+
end
145+
146+
test 'app_metadata evaluates lambda values in plugin metadata' do
147+
counter = 0
148+
::Foreman::Plugin.app_metadata_registry.register(:test_plugin, {
149+
dynamic: -> { counter += 1 },
150+
})
151+
152+
metadata = app_metadata
153+
result1 = metadata['test_plugin']['dynamic']
154+
result2 = app_metadata['test_plugin']['dynamic']
155+
156+
assert_equal 1, result1
157+
assert_equal 2, result2
158+
ensure
159+
# Clean up test registration
160+
::Foreman::Plugin.app_metadata_registry.instance_variable_get(:@plugin_metadata).delete(:test_plugin)
161+
end
162+
163+
test 'app_metadata preserves static values' do
164+
::Foreman::Plugin.app_metadata_registry.register(:test_plugin_static, {
165+
static_string: 'test',
166+
static_number: 42,
167+
static_bool: true,
168+
})
169+
170+
result = app_metadata['test_plugin_static']
171+
172+
assert_equal 'test', result['static_string']
173+
assert_equal 42, result['static_number']
174+
assert_equal true, result['static_bool']
175+
ensure
176+
::Foreman::Plugin.app_metadata_registry.instance_variable_get(:@plugin_metadata).delete(:test_plugin_static)
177+
end
178+
179+
test 'app_metadata handles mixed static and lambda values' do
180+
call_count = 0
181+
::Foreman::Plugin.app_metadata_registry.register(:test_plugin_mixed, {
182+
static: 'static_value',
183+
dynamic: lambda {
184+
call_count += 1
185+
"dynamic_#{call_count}"
186+
},
187+
})
188+
189+
result = app_metadata['test_plugin_mixed']
190+
191+
assert_equal 'static_value', result['static']
192+
assert_equal 'dynamic_1', result['dynamic']
193+
194+
# Second call should re-evaluate lambda
195+
result2 = app_metadata['test_plugin_mixed']
196+
assert_equal 'dynamic_2', result2['dynamic']
197+
ensure
198+
::Foreman::Plugin.app_metadata_registry.instance_variable_get(:@plugin_metadata).delete(:test_plugin_mixed)
199+
end
200+
end
136201
end

0 commit comments

Comments
 (0)