Commit 3e8ad4d6 authored by Ryan Senior's avatar Ryan Senior

(PDB-3108) Consolidate producer-timestamps in the terminus

This commit changes the terminus to ensure producer timestamps are
created from a single place. Prior to this patch they were created in
several places, including having the ability to be passed in from
Puppet itself (not possible since producer-timestamp is something PDB
created). This commit also switches to 3 digit accuracy on
timestamps. Prior to this we were using different accuracy for
catalogs/facts vs. reports, both of which were just truncated once it
was received by the PDB backend.
parent 570e9d81
...@@ -22,8 +22,7 @@ class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST ...@@ -22,8 +22,7 @@ class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST
def extract_extra_request_data(request) def extract_extra_request_data(request)
{ {
:transaction_uuid => request.options[:transaction_uuid], :transaction_uuid => request.options[:transaction_uuid],
:environment => request.environment.to_s, :environment => request.environment.to_s
:producer_timestamp => request.options[:producer_timestamp] || Time.now.iso8601(5),
} }
end end
...@@ -100,7 +99,7 @@ class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST ...@@ -100,7 +99,7 @@ class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST
# @return [Hash] returns original hash augmented with producer_timestamp # @return [Hash] returns original hash augmented with producer_timestamp
# @api private # @api private
def add_producer_timestamp(hash, producer_timestamp) def add_producer_timestamp(hash, producer_timestamp)
hash['producer_timestamp'] = producer_timestamp hash['producer_timestamp'] = Puppet::Util::Puppetdb.to_wire_time(Time.now)
hash hash
end end
......
...@@ -30,7 +30,7 @@ class Puppet::Node::Facts::Puppetdb < Puppet::Indirector::REST ...@@ -30,7 +30,7 @@ class Puppet::Node::Facts::Puppetdb < Puppet::Indirector::REST
# when we attempt to use ActiveSupport 2.3.16 on RHEL 5 with # when we attempt to use ActiveSupport 2.3.16 on RHEL 5 with
# legacy storeconfigs. # legacy storeconfigs.
"environment" => request.options[:environment] || request.environment.to_s, "environment" => request.options[:environment] || request.environment.to_s,
"producer_timestamp" => request.options[:producer_timestamp] || Time.now.iso8601(5), "producer_timestamp" => Puppet::Util::Puppetdb.to_wire_time(Time.now),
"producer" => Puppet[:node_name_value] "producer" => Puppet[:node_name_value]
} }
end end
......
...@@ -13,7 +13,7 @@ class Puppet::Node::Puppetdb < Puppet::Indirector::REST ...@@ -13,7 +13,7 @@ class Puppet::Node::Puppetdb < Puppet::Indirector::REST
def destroy(request) def destroy(request)
payload = { :certname => request.key, payload = { :certname => request.key,
:producer_timestamp => request.options[:producer_timestamp] || Time.now.iso8601(5) } :producer_timestamp => Puppet::Util::Puppetdb.to_wire_time(Time.now) }
submit_command(request.key, payload, CommandDeactivateNode, 3) submit_command(request.key, payload, CommandDeactivateNode, 3)
end end
end end
...@@ -30,12 +30,10 @@ module Puppet::Util::Puppetdb ...@@ -30,12 +30,10 @@ module Puppet::Util::Puppetdb
end end
# Given an instance of ruby's Time class, this method converts it to a String # Given an instance of ruby's Time class, this method converts it to a String
# that conforms to PuppetDB's wire format for representing a date/time. # that conforms to PuppetDB's wire format for representing a date/time. All PuppetDB
# timestamps are stored at millisecond accurace (i.e. 10^-3)
def self.to_wire_time(time) def self.to_wire_time(time)
# The current implementation simply calls iso8601, but having this method time.iso8601(3)
# allows us to change that in the future if needed w/o being forced to
# update all of the date objects elsewhere in the code.
time.iso8601(9)
end end
# Convert a value (usually a string) to a boolean # Convert a value (usually a string) to a boolean
......
...@@ -20,6 +20,10 @@ def create_environmentdir(environment) ...@@ -20,6 +20,10 @@ def create_environmentdir(environment)
end end
end end
def extract_producer_timestamp(command)
DateTime.parse(command["producer_timestamp"]).to_time.to_i
end
RSpec.configure do |config| RSpec.configure do |config|
config.before :each do config.before :each do
......
...@@ -8,6 +8,8 @@ require 'puppet/util/puppetdb/command_names' ...@@ -8,6 +8,8 @@ require 'puppet/util/puppetdb/command_names'
require 'json' require 'json'
require 'puppet/resource/catalog' require 'puppet/resource/catalog'
require 'puppet/version' require 'puppet/version'
require 'date'
require 'time'
describe Puppet::Resource::Catalog::Puppetdb do describe Puppet::Resource::Catalog::Puppetdb do
before :each do before :each do
...@@ -25,8 +27,7 @@ describe Puppet::Resource::Catalog::Puppetdb do ...@@ -25,8 +27,7 @@ describe Puppet::Resource::Catalog::Puppetdb do
end end
let(:options) {{ let(:options) {{
:transaction_uuid => 'abcdefg', :transaction_uuid => 'abcdefg',
:environment => 'my_environment', :environment => 'my_environment'
:producer_timestamp => "a test",
}} }}
before :each do before :each do
...@@ -39,10 +40,15 @@ describe Puppet::Resource::Catalog::Puppetdb do ...@@ -39,10 +40,15 @@ describe Puppet::Resource::Catalog::Puppetdb do
end end
it "should POST the catalog command as a JSON string" do it "should POST the catalog command as a JSON string" do
command_payload = subject.munge_catalog(catalog, options).to_json before_test_time = Time.now
command_payload = subject.munge_catalog(catalog, options)
http.expects(:post).with do |uri, body, headers| http.expects(:post).with do |uri, body, headers|
expect(body).to eq(command_payload) req = JSON.parse(body)
actual_producer_timestamp = extract_producer_timestamp(req)
req.delete("producer_timestamp")
command_payload.delete("producer_timestamp")
req == command_payload &&
actual_producer_timestamp <= Time.now.to_i
end.returns response end.returns response
save save
......
...@@ -6,7 +6,8 @@ require 'puppet/indirector/facts/puppetdb' ...@@ -6,7 +6,8 @@ require 'puppet/indirector/facts/puppetdb'
require 'puppet/util/puppetdb' require 'puppet/util/puppetdb'
require 'puppet/util/puppetdb/command_names' require 'puppet/util/puppetdb/command_names'
require 'json' require 'json'
require 'date'
require 'time'
describe Puppet::Node::Facts::Puppetdb do describe Puppet::Node::Facts::Puppetdb do
...@@ -26,7 +27,6 @@ describe Puppet::Node::Facts::Puppetdb do ...@@ -26,7 +27,6 @@ describe Puppet::Node::Facts::Puppetdb do
let(:facts) { Puppet::Node::Facts.new('foo') } let(:facts) { Puppet::Node::Facts.new('foo') }
let(:options) {{ let(:options) {{
:producer_timestamp => 'a test',
:environment => "my_environment", :environment => "my_environment",
}} }}
...@@ -48,12 +48,17 @@ describe Puppet::Node::Facts::Puppetdb do ...@@ -48,12 +48,17 @@ describe Puppet::Node::Facts::Puppetdb do
"certname" => facts.name, "certname" => facts.name,
"values" => facts.values.merge({"trusted" => trusted_data}), "values" => facts.values.merge({"trusted" => trusted_data}),
"environment" => "my_environment", "environment" => "my_environment",
"producer_timestamp" => "a test",
"producer" => "mom" "producer" => "mom"
}.to_pson }
http.expects(:post).with do |uri, body, headers| http.expects(:post).with do |uri, body, headers|
expect(body).to eq(payload)
req = JSON.parse(body)
actual_producer_timestamp = extract_producer_timestamp(req)
req.delete("producer_timestamp")
req == payload &&
actual_producer_timestamp <= Time.now.to_i
end.returns response end.returns response
save save
......
...@@ -5,6 +5,8 @@ require 'spec_helper' ...@@ -5,6 +5,8 @@ require 'spec_helper'
require 'puppet/indirector/node/puppetdb' require 'puppet/indirector/node/puppetdb'
require 'puppet/util/puppetdb/command_names' require 'puppet/util/puppetdb/command_names'
require 'json' require 'json'
require 'date'
require 'time'
describe Puppet::Node::Puppetdb do describe Puppet::Node::Puppetdb do
...@@ -15,10 +17,10 @@ describe Puppet::Node::Puppetdb do ...@@ -15,10 +17,10 @@ describe Puppet::Node::Puppetdb do
end end
let(:node) { "something.example.com" } let(:node) { "something.example.com" }
let(:producer_timestamp) { Time.now.iso8601(5) } let(:producer_timestamp) { Puppet::Util::Puppetdb.to_wire_time(Time.now) }
def destroy def destroy
Puppet::Node.indirection.destroy(node, {:producer_timestamp => producer_timestamp}) Puppet::Node.indirection.destroy(node)
end end
describe "#destroy" do describe "#destroy" do
...@@ -30,12 +32,10 @@ describe Puppet::Node::Puppetdb do ...@@ -30,12 +32,10 @@ describe Puppet::Node::Puppetdb do
it "should POST a '#{CommandDeactivateNode}' command" do it "should POST a '#{CommandDeactivateNode}' command" do
response.stubs(:body).returns '{"uuid": "a UUID"}' response.stubs(:body).returns '{"uuid": "a UUID"}'
payload = { :certname => node,
:producer_timestamp => producer_timestamp }.to_json
http.expects(:post).with do |uri,body,headers| http.expects(:post).with do |uri,body,headers|
expect(body).to eq(payload) req = JSON.parse(body)
req["certname"] == node &&
extract_producer_timestamp(req) <= Time.now.to_i
end.returns response end.returns response
destroy destroy
......
...@@ -9,7 +9,7 @@ describe Puppet::Util::Puppetdb::Command do ...@@ -9,7 +9,7 @@ describe Puppet::Util::Puppetdb::Command do
let(:payload) { {'resistance' => 'futile', 'opinion' => 'irrelevant'} } let(:payload) { {'resistance' => 'futile', 'opinion' => 'irrelevant'} }
let(:subject) { described_class.new("OPEN SESAME", 1, let(:subject) { described_class.new("OPEN SESAME", 1,
'foo.localdomain', producer-time-ms, payload) } 'foo.localdomain', payload) }
describe "#submit" do describe "#submit" do
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment