Skip to content

Commit 004a9a7

Browse files
committed
(FM-8092) Fix caching scope of transport schemas
When running in puppetserver for the [environment_transports](https://github.com/puppetlabs/puppetserver/blob/master/documentation/puppet-api/v3/environment_transports.markdown) API, the Resource API would cache registered transport schemas forever. This meant that deploying a new module version and running the usual environment cache cleaning scripts would not update the transport schema. With this change, we push the transport cache into an ObjectIdCacheAdapter around the environment, which will be cleaned up by the internal utilities.
1 parent 7e89026 commit 004a9a7

File tree

2 files changed

+38
-66
lines changed

2 files changed

+38
-66
lines changed

lib/puppet/resource_api/transport.rb

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def register(schema)
1212
unless transports[schema[:name]].nil?
1313
raise Puppet::DevError, 'Transport `%{name}` is already registered for `%{environment}`' % {
1414
name: schema[:name],
15-
environment: current_environment,
15+
environment: current_environment_name,
1616
}
1717
end
1818
transports[schema[:name]] = Puppet::ResourceApi::TransportSchemaDef.new(schema)
@@ -27,7 +27,7 @@ def list
2727
module_function :list # rubocop:disable Style/AccessModifierDeclarations
2828

2929
# retrieve a Hash of transport schemas, keyed by their name.
30-
# This uses the Puppet autoloader, provide a environment name as `force_environment`
30+
# This uses the Puppet autoloader, provide an environment name as `force_environment`
3131
# to choose where to load from.
3232
# @api private
3333
def list_all_transports(force_environment)
@@ -45,7 +45,7 @@ def self.load_all_schemas
4545
require 'puppet/settings'
4646
require 'puppet/util/autoload'
4747
@autoloader ||= Puppet::Util::Autoload.new(self, 'puppet/transport/schema')
48-
@autoloader.loadall(Puppet.lookup(:current_environment))
48+
@autoloader.loadall(current_environment)
4949
end
5050
private_class_method :load_all_schemas
5151

@@ -74,7 +74,7 @@ def self.validate(name, connection_info)
7474
if transport_schema.nil?
7575
raise Puppet::DevError, 'Transport for `%{target}` not registered with `%{environment}`' % {
7676
target: name,
77-
environment: current_environment,
77+
environment: current_environment_name,
7878
}
7979
end
8080

@@ -108,21 +108,26 @@ def self.wrap_sensitive(name, connection_info)
108108
private_class_method :wrap_sensitive
109109

110110
def self.transports
111-
@transports ||= {}
112-
@transports[current_environment] ||= {}
111+
env = current_environment
112+
if env
113+
ObjectIdCacheAdapter.adapt(env).retrieve(:rsapi_transport_cache)
114+
else
115+
@transports_default ||= {}
116+
end
113117
end
114118
private_class_method :transports
115119

116120
def self.current_environment
117-
if Puppet.respond_to? :lookup
118-
env = Puppet.lookup(:current_environment)
119-
env.nil? ? :transports_default : env.name
120-
else
121-
:transports_default
122-
end
121+
Puppet.lookup(:current_environment) if Puppet.respond_to? :lookup
123122
end
124123
private_class_method :current_environment
125124

125+
def self.current_environment_name
126+
env = current_environment
127+
env.nil? ? :transports_default : env.name
128+
end
129+
private_class_method :current_environment_name
130+
126131
def self.clean_bolt_attributes(transport_schema, connection_info)
127132
context = get_context(transport_schema.name)
128133

@@ -154,4 +159,19 @@ def self.clean_bolt_attributes(transport_schema, connection_info)
154159
nil
155160
end
156161
private_class_method :clean_bolt_attributes
162+
163+
# copy from https://github.com/puppetlabs/puppet/blob/8cae8a17dbac08d2db0238d5bce2f1e4d1898d65/lib/puppet/pops/adapters.rb#L6-L17
164+
# to keep backwards compatibility with puppet4 and 5, which don't have this yet.
165+
class ObjectIdCacheAdapter < Puppet::Pops::Adaptable::Adapter
166+
attr_accessor :cache
167+
168+
def initialize
169+
@cache = {}
170+
end
171+
172+
# Retrieves a mutable hash with all stored values
173+
def retrieve(o)
174+
@cache[o.__id__] ||= {}
175+
end
176+
end
157177
end

spec/puppet/resource_api/transport_spec.rb

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ def change_environment(name = nil)
55
environment = class_double(Puppet::Node::Environment)
66

77
if name.nil?
8-
allow(Puppet).to receive(:respond_to?).and_return(false)
8+
allow(Puppet).to receive(:respond_to?).with(:lookup).and_return(false)
99
else
10-
allow(Puppet).to receive(:respond_to?).and_return(true)
10+
allow(Puppet).to receive(:respond_to?).with(:lookup).and_return(true)
1111
end
1212

1313
allow(Puppet).to receive(:lookup).with(:current_environment).and_return(environment)
@@ -73,64 +73,16 @@ def change_environment(name = nil)
7373
},
7474
}
7575
end
76-
let(:schema2) do
77-
{
78-
name: 'schema2',
79-
desc: 'basic transport',
80-
connection_info: {
81-
host: {
82-
type: 'String',
83-
desc: 'the host ip address or hostname',
84-
},
85-
},
86-
}
87-
end
88-
let(:schema3) do
89-
{
90-
name: 'schema3',
91-
desc: 'basic transport',
92-
connection_info: {
93-
user: {
94-
type: 'String',
95-
desc: 'the user to connect as',
96-
},
97-
password: {
98-
type: 'String',
99-
sensitive: true,
100-
desc: 'the password to make the connection',
101-
},
102-
},
103-
}
104-
end
10576

10677
it 'adds to the transports register' do
10778
expect { described_class.register(schema) }.not_to raise_error
10879
end
10980

110-
context 'when a transports are added to multiple environments' do
111-
let(:transports) { described_class.instance_variable_get(:@transports) }
81+
context 'when no environment is available' do
82+
before(:each) { change_environment(nil) }
11283

113-
it 'will record the schemas in the correct structure' do
114-
change_environment(nil)
115-
described_class.register(schema)
116-
expect(transports).to have_key(:transports_default)
117-
expect(transports[:transports_default][schema[:name]]).to be_a_kind_of(Puppet::ResourceApi::TransportSchemaDef)
118-
expect(transports[:transports_default][schema[:name]].definition).to eq(schema)
119-
120-
change_environment('foo')
121-
described_class.register(schema)
122-
described_class.register(schema2)
123-
expect(transports).to have_key('foo')
124-
expect(transports['foo'][schema[:name]]).to be_a_kind_of(Puppet::ResourceApi::TransportSchemaDef)
125-
expect(transports['foo'][schema[:name]].definition).to eq(schema)
126-
expect(transports['foo'][schema2[:name]]).to be_a_kind_of(Puppet::ResourceApi::TransportSchemaDef)
127-
expect(transports['foo'][schema2[:name]].definition).to eq(schema2)
128-
129-
change_environment(:bar)
130-
described_class.register(schema3)
131-
expect(transports).to have_key(:bar)
132-
expect(transports[:bar][schema3[:name]]).to be_a_kind_of(Puppet::ResourceApi::TransportSchemaDef)
133-
expect(transports[:bar][schema3[:name]].definition).to eq(schema3)
84+
it 'adds to the transports register' do
85+
expect { described_class.register(schema) }.not_to raise_error
13486
end
13587
end
13688
end

0 commit comments

Comments
 (0)