]> review.fuel-infra Code Review - puppet-modules/puppetlabs-apt.git/commitdiff
Add basic create/delete handling
authorDavid Schmitt <david.schmitt@puppet.com>
Thu, 21 Sep 2017 10:24:55 +0000 (11:24 +0100)
committerDavid Schmitt <david.schmitt@puppet.com>
Thu, 21 Sep 2017 10:24:55 +0000 (11:24 +0100)
This still requires more work to match up to the original implementation,
but suffices for basic acceptance testing.

lib/puppet/provider/apt_key2/apt_key2.rb
spec/unit/puppet/provider/apt_key2/apt_key2_spec.rb

index 3b6cd911fd2e5cf51bdac19dd920858ae60816a3..c4cf9dee3105d4dfa6306bd7cf5049f357723fd5 100644 (file)
@@ -89,42 +89,55 @@ class Puppet::Provider::AptKey2::AptKey2
     }
   end
 
-  def set(current_state, target_state, noop = false)
-    target_state.each do |title, resource|
-      logger.warning(title, 'The id should be a full fingerprint (40 characters) to avoid collision attacks, see the README for details.') if title.length < 40
-      if resource[:source] && resource[:content]
-        logger.fail(title, 'The properties content and source are mutually exclusive')
-        next
-      end
-
-      current = current_state[title]
-      if current && resource[:ensure].to_s == 'absent'
-        logger.deleting(title) do
-          begin
-            apt_key('del', resource[:short], noop: noop)
-            r = execute(["#{command(:apt_key)} list | grep '/#{resource[:short]}\s'"], failonfail: false)
-          end while r.exitstatus.zero?
-        end
-      elsif current && resource[:ensure].to_s == 'present'
-        logger.warning(title, 'No updating implemented')
-        # update(key, noop: noop)
-      elsif !current && resource[:ensure].to_s == 'present'
-        create(title, resource, noop: noop)
+  def set(context, changes)
+    changes.each do |name, change|
+      is = change.key?(:is) ? change[:is] : get_single(name)
+      should = change[:should]
+      context.warning(name, 'The id should be a full fingerprint (40 characters) to avoid collision attacks, see the README for details.') if name.length < 40
+
+      is = { id: name, ensure: 'absent' } if is.nil?
+      should = { id: name, ensure: 'absent' } if should.nil?
+
+      if is[:ensure].to_s == 'absent' && should[:ensure].to_s == 'present'
+        create(context, name, should)
+      elsif is[:ensure].to_s == 'present' && should[:ensure].to_s == 'absent'
+        delete(context, name)
       end
     end
+    # target_state.each do |title, resource|
+    #   if resource[:source] && resource[:content]
+    #     logger.fail(title, 'The properties content and source are mutually exclusive')
+    #     next
+    #   end
+
+    #   current = current_state[title]
+    #   if current && resource[:ensure].to_s == 'absent'
+    #     logger.deleting(title) do
+    #       begin
+    #         apt_key('del', resource[:short], noop: noop)
+    #         r = execute(["#{command(:apt_key)} list | grep '/#{resource[:short]}\s'"], failonfail: false)
+    #       end while r.exitstatus.zero?
+    #     end
+    #   elsif current && resource[:ensure].to_s == 'present'
+    #     logger.warning(title, 'No updating implemented')
+    #     # update(key, noop: noop)
+    #   elsif !current && resource[:ensure].to_s == 'present'
+    #     create(title, resource, noop: noop)
+    #   end
+    # end
   end
 
-  def create(title, resource, noop = false)
-    logger.creating(title) do |logger|
+  def create(global_context, title, resource, noop = false)
+    global_context.creating(title) do |context|
       if resource[:source].nil? && resource[:content].nil?
         # Breaking up the command like this is needed because it blows up
         # if --recv-keys isn't the last argument.
-        args = ['adv', '--keyserver', resource[:server]]
+        args = ['adv', '--keyserver', resource[:server].to_s]
         if resource[:options]
           args.push('--keyserver-options', resource[:options])
         end
         args.push('--recv-keys', resource[:id])
-        apt_key(*args, noop: noop)
+        @apt_key_cmd.run(context, *args, noop: noop)
       elsif resource[:content]
         temp_key_file(resource[:content], logger) do |key_file|
           apt_key('add', key_file, noop: noop)
@@ -134,11 +147,17 @@ class Puppet::Provider::AptKey2::AptKey2
         apt_key('add', key_file.path, noop: noop)
         # In case we really screwed up, better safe than sorry.
       else
-        logger.fail("an unexpected condition occurred while trying to add the key: #{title} (content: #{resource[:content].inspect}, source: #{resource[:source].inspect})")
+        context.fail("an unexpected condition occurred while trying to add the key: #{title} (content: #{resource[:content].inspect}, source: #{resource[:source].inspect})")
       end
     end
   end
 
+  def delete(global_context, title, noop = false)
+    global_context.deleting(title) do |context|
+      @apt_key_cmd.run(context, 'del', title, noop: noop)
+    end
+  end
+
   # This method writes out the specified contents to a temporary file and
   # confirms that the fingerprint from the file, matches the long key that is in the manifest
   def temp_key_file(resource, logger)
index f98e03148dfe949f1d93138ddffc57ed896b21e6..9b1c744e52d39277a82929ef79c775aabfb53892 100644 (file)
@@ -108,4 +108,88 @@ EOS
       ]
     end
   end
+
+  describe '#set(context, changes)' do
+    let(:apt_key_cmd) { instance_double('Puppet::ResourceApi::Command') }
+    let(:process) { instance_double('ChildProcess::AbstractProcess') }
+    let(:io) { instance_double('ChildProcess::AbstractIO') }
+    let(:id) { 'A' * 40 }
+
+    before(:each) do
+      allow(Puppet::ResourceApi::Command).to receive(:new).and_return(apt_key_cmd)
+    end
+
+    context 'when passing in empty changes' do
+      it 'does nothing' do
+        expect { provider.set(context, {}) }.not_to raise_error
+      end
+    end
+
+    context 'when managing a up-to-date key' do
+      it 'does nothing' do
+        expect {
+          provider.set(context, id => {
+                         is: {
+                           id: id, ensure: :present
+                         },
+                         should: {
+                           id: id, ensure: :present
+                         },
+                       })
+        }.not_to raise_error
+      end
+    end
+
+    context 'when managing an absent key' do
+      it 'does nothing' do
+        provider.set(context, id =>
+        {
+          is: nil,
+          should: {
+            id: id,
+            ensure: :absent,
+          },
+        })
+      end
+    end
+
+    context 'when fetching a key from the keyserver' do
+      let(:creating_ctx) { instance_double('Puppet::ResourceApi::BaseContext', 'creating_ctx') }
+
+      it 'updates the system' do
+        expect(context).to receive(:creating).with(id).and_yield(creating_ctx)
+        expect(apt_key_cmd).to receive(:run).with(creating_ctx, 'adv', '--keyserver', 'keyserver.example.com', '--recv-keys', id, noop: false).and_return 0
+        provider.set(context, id =>
+        {
+          is: nil,
+          should: {
+            id: id,
+            ensure: :present,
+            server: :'keyserver.example.com',
+          },
+        })
+      end
+    end
+
+    context 'when deleting a key' do
+      let(:deleting_ctx) { instance_double('Puppet::ResourceApi::BaseContext', 'deleting_ctx') }
+
+      it 'updates the system' do
+        expect(context).to receive(:deleting).with(id).and_yield(deleting_ctx)
+        expect(apt_key_cmd).to receive(:run).with(deleting_ctx, 'del', id, noop: false).and_return 0
+        provider.set(context, id =>
+        {
+          is: {
+            id: id,
+            ensure: :present,
+            server: :'keyserver.ubuntu.com',
+          },
+          should: {
+            id: id,
+            ensure: :absent,
+          },
+        })
+      end
+    end
+  end
 end