From c788610fd10d81fb518675402968902ad0bb914b Mon Sep 17 00:00:00 2001 From: John Keiser Date: Tue, 31 May 2016 12:58:50 -0700 Subject: Fewer levels of indirection in serialization --- lib/chef/data_collector.rb | 38 ++++----- lib/chef/data_collector/serializers.rb | 82 +++++++++++++++++++ lib/chef/data_collector/serializers/base.rb | 90 ++++++++------------- lib/chef/data_collector/serializers/node_update.rb | 93 ++++++++-------------- lib/chef/data_collector/serializers/run_end.rb | 85 -------------------- lib/chef/data_collector/serializers/run_start.rb | 55 ------------- 6 files changed, 169 insertions(+), 274 deletions(-) create mode 100644 lib/chef/data_collector/serializers.rb delete mode 100644 lib/chef/data_collector/serializers/run_end.rb delete mode 100644 lib/chef/data_collector/serializers/run_start.rb diff --git a/lib/chef/data_collector.rb b/lib/chef/data_collector.rb index c4afbfaa34..daceed70e1 100644 --- a/lib/chef/data_collector.rb +++ b/lib/chef/data_collector.rb @@ -19,11 +19,9 @@ # require "uri" -require "chef/event_dispatch/base" -require "chef/data_collector/resource_report" -require "chef/data_collector/serializers/node_update" -require "chef/data_collector/serializers/run_end" -require "chef/data_collector/serializers/run_start" +require_relative "event_dispatch/base" +require_relative "data_collector/resource_report" +require_relative "data_collector/serializers" class Chef class DataCollector @@ -64,7 +62,7 @@ class Chef update_run_status(current_run_status) disable_reporter_on_error do - send_to_data_collector(Serializers::RunStart.new(run_status)) + send_to_data_collector(Serializers.run_start_message(run_status)) end end @@ -188,11 +186,11 @@ class Chef end end - def send_to_data_collector(message) + def send_to_data_collector(message_json) return unless data_collector_accessible? - Chef::Log.debug("data_collector_reporter: POSTing the following message to #{data_collector_server_url}: #{message.to_json}") - http.post(nil, message.to_json, headers) + Chef::Log.debug("data_collector_reporter: POSTing the following message to #{data_collector_server_url}: #{message_json}") + http.post(nil, message_json, headers) end def send_run_completion @@ -201,17 +199,19 @@ class Chef # we have nothing to report. return unless run_status - send_to_data_collector(Serializers::NodeUpdate.new(run_status)) - send_to_data_collector( - Serializers::RunEnd.new( - run_status: run_status, - expanded_run_list: expanded_run_list, - total_resource_count: resource_count, - updated_resources: updated_resources, - status: status, - error_descriptions: error_descriptions + if data_collector_accessible? + send_to_data_collector(Serializers::NodeUpdate.new(run_status).to_json) + send_to_data_collector( + Serializers.run_end_message( + run_status, + expanded_run_list: expanded_run_list, + total_resource_count: resource_count, + updated_resources: updated_resources, + status: status, + error_descriptions: error_descriptions + ) ) - ) + end end def headers(additional_headers = {}) diff --git a/lib/chef/data_collector/serializers.rb b/lib/chef/data_collector/serializers.rb new file mode 100644 index 0000000000..d2dc7ef5e9 --- /dev/null +++ b/lib/chef/data_collector/serializers.rb @@ -0,0 +1,82 @@ +# +# Author:: Adam Leff () +# +# Copyright:: Copyright 2012-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "json" +require "securerandom" +require_relative "serializers/base" + +class Chef + class DataCollector + module Serializers + extend Base + + + def self.run_end_message(run_status, + error_descriptions:, + expanded_run_list:, + status:, + total_resource_count:, + updated_resources:) + + metadata = get_metadata + + { + chef_server_fqdn: chef_server_fqdn, + entity_uuid: metadata["node_uuid"], + message_version: "1.0.0", + node_name: node.name, + organization_name: organization, + source: solo_run? ? "chef_solo" : "chef_client" + expanded_run_list: expanded_run_list, + id: run_status.run_id, + message_type: "run_converge", + resources: updated_resources.map(&:for_json), + run_id: run_status.run_id, + run_list: run_status.node.run_list.for_json, + start_time: run_status.start_time.utc.iso8601, + end_time: run_status.end_time.utc.iso8601, + total_resource_count: total_resource_count, + updated_resource_count: updated_resources.count, + } + + if run_status.exception + message[:error] = { + class: => run_status.exception.class, + message: => run_status.exception.message, + backtrace: => run_status.exception.backtrace, + description: => error_descriptions, + } + end + + message + end + + def self.run_start_message(run_status) + message = serialize_base_message(run_status) + message.merge!( + id: run_status.run_id, + message_type: "run_start", + run_id: run_status.run_id, + start_time: run_status.start_time.utc.iso8601, + } + message + end + end +end diff --git a/lib/chef/data_collector/serializers/base.rb b/lib/chef/data_collector/serializers/base.rb index 139d2f1dd7..4024f0b2ad 100644 --- a/lib/chef/data_collector/serializers/base.rb +++ b/lib/chef/data_collector/serializers/base.rb @@ -20,76 +20,54 @@ require "json" require "securerandom" +require "chef/config" class Chef class DataCollector class Serializers - class Base - def document - raise "#{self.class} does not implement the #document method, which should return a hash of data to send" - end - - def message_type - raise "#{self.class} does not implement the #message_type method, which return a string containing the message type" - end - - def to_json - document.to_json - end - + module Base def chef_server_fqdn - return URI(Chef::Config[:chef_server_url]).host unless Chef::Config[:chef_server_url].nil? - return "localhost" unless defined?(run_status) - - run_status.node["fqdn"] - end - - def organization - solo_run? ? data_collector_organization : chef_server_organization - end - - def data_collector_organization - Chef::Config[:data_collector_organization] || "chef_solo" + if Chef::Config[:chef_server_url] + URI(Chef::Config[:chef_server_url]).host + elsif defined?(node) + node["fqdn"] + else + "localhost" + end end - def chef_server_organization - return nil unless Chef::Config[:chef_server_url] + private - Chef::Config[:chef_server_url].match(%r{/organizations/(\w+)}).nil? ? "unknown_organization" : $1 - end - - def collector_source - solo_run? ? "chef_solo" : "chef_client" + def organization + if solo_run? + Chef::Config[:data_collector_organization] || "chef_solo" + else + if Chef::Config[:chef_server_url] + if Chef::Config[:chef_server_url] =~ %r{/organizations/(\w+)} + $1 + else + "unknown_organization" + end + end + end end def solo_run? Chef::Config[:solo] || Chef::Config[:local_mode] end - def node_uuid - read_node_uuid || generate_node_uuid - end - - def generate_node_uuid - uuid = SecureRandom.uuid - update_metadata("node_uuid", uuid) - - uuid - end - - def read_node_uuid - metadata["node_uuid"] - end - - def metadata - @metadata ||= JSON.load(Chef::FileCache.load(metadata_filename)) - rescue Chef::Exceptions::FileNotFound - @metadata = {} - end - - def update_metadata(key, value) - metadata[key] = value - Chef::FileCache.store(metadata_filename, metadata.to_json, 0644) + def get_metadata + begin + metadata = JSON.load(Chef::FileCache.load(metadata_filename)) + rescue Chef::Exceptions::FileNotFound + metadata = {} + end + # Ensure we have a uuid + unless metadata["uuid_json"] + metadata["uuid_json"] = SecureRandom.uuid + Chef::FileCache.store(metadata_filename, metadata.to_json, 0644) + end + metadata end def metadata_filename diff --git a/lib/chef/data_collector/serializers/node_update.rb b/lib/chef/data_collector/serializers/node_update.rb index 0befb89b15..30806a8452 100644 --- a/lib/chef/data_collector/serializers/node_update.rb +++ b/lib/chef/data_collector/serializers/node_update.rb @@ -1,65 +1,40 @@ -# -# Author:: Adam Leff () -# -# Copyright:: Copyright 2012-2016, Chef Software Inc. -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# +require_relative "base" -require "securerandom" -require "chef/data_collector/serializers/base" +module DataCollector + module Serializer + module NodeUpdate + include Base -class Chef - class DataCollector - class Serializers - class NodeUpdate < Base + def self.serialize(run_status) + metadata = get_metadata - attr_reader :run_status - - def initialize(run_status) - @run_status = run_status - end - - def message_type - "action" - end - - def node - run_status.node - end - - def document - { - "entity_name" => node.name, - "entity_type" => "node", - "entity_uuid" => node_uuid, - "id" => SecureRandom.uuid, - "message_version" => "1.0.0", - "message_type" => message_type, - "organization_name" => organization, - "recorded_at" => Time.now.utc.iso8601, - "remote_hostname" => node["fqdn"], - "requestor_name" => node.name, - "requestor_type" => "client", - "service_hostname" => chef_server_fqdn, - "source" => collector_source, - "task" => "update", - "user_agent" => Chef::HTTP::HTTPRequest::DEFAULT_UA, - "data" => node, - } - end + { + chef_server_fqdn: chef_server_fqdn, + entity_uuid: metadata["node_uuid"], + message_version: "1.0.0", + node_name: node.name, + organization_name: organization, + source: solo_run? ? "chef_solo" : "chef_client", + chef_server_fqdn: chef_server_fqdn, + entity_uuid: metadata["node_uuid"], + message_version: "1.0.0", + node_name: node.name, + organization_name: organization, + source: solo_run? ? "chef_solo" : "chef_client", + entity_name: run_status.node.name, + entity_type: "node", + id: SecureRandom.uuid, + message_version: "1.0.0", + message_type: "action", + recorded_at: Time.now.utc.iso8601, + remote_hostname: run_status.node["fqdn"], + requestor_name: run_status.node.name, + requestor_type: "client", + service_hostname: chef_server_fqdn, + task: "update" + user_agent: Chef::HTTP::HTTPRequest::DEFAULT_UA, + data: run_status.node, + ) end end end diff --git a/lib/chef/data_collector/serializers/run_end.rb b/lib/chef/data_collector/serializers/run_end.rb deleted file mode 100644 index 1d1d586aa7..0000000000 --- a/lib/chef/data_collector/serializers/run_end.rb +++ /dev/null @@ -1,85 +0,0 @@ -# -# Author:: Adam Leff () -# -# Copyright:: Copyright 2012-2016, Chef Software Inc. -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require "securerandom" -require "chef/data_collector/serializers/base" - -class Chef - class DataCollector - class Serializers - class RunEnd < Base - attr_reader :error_descriptions - attr_reader :expanded_run_list - attr_reader :run_status - attr_reader :status - attr_reader :total_resource_count - attr_reader :updated_resources - - def initialize(opts) - @error_descriptions = opts[:error_descriptions] - @expanded_run_list = opts[:expanded_run_list] - @run_status = opts[:run_status] - @total_resource_count = opts[:total_resource_count] - @updated_resources = opts[:updated_resources] - @status = opts[:status] - end - - def message_type - "run_converge" - end - - def document - document = { - "chef_server_fqdn" => chef_server_fqdn, - "entity_uuid" => node_uuid, - "expanded_run_list" => expanded_run_list, - "id" => run_status.run_id, - "message_version" => "1.0.0", - "message_type" => message_type, - "node_name" => run_status.node.name, - "organization_name" => organization, - "resources" => updated_resources.map(&:for_json), - "run_id" => run_status.run_id, - "run_list" => run_status.node.run_list.for_json, - "start_time" => run_status.start_time.utc.iso8601, - "end_time" => run_status.end_time.utc.iso8601, - "source" => collector_source, - "status" => status, - "total_resource_count" => total_resource_count, - "updated_resource_count" => updated_resources.count, - } - - document["error"] = formatted_exception if run_status.exception - - document - end - - def formatted_exception - { - "class" => run_status.exception.class, - "message" => run_status.exception.message, - "backtrace" => run_status.exception.backtrace, - "description" => error_descriptions, - } - end - end - end - end -end diff --git a/lib/chef/data_collector/serializers/run_start.rb b/lib/chef/data_collector/serializers/run_start.rb deleted file mode 100644 index 5c202b37e2..0000000000 --- a/lib/chef/data_collector/serializers/run_start.rb +++ /dev/null @@ -1,55 +0,0 @@ -# -# Author:: Adam Leff () -# -# Copyright:: Copyright 2012-2016, Chef Software Inc. -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require "chef/data_collector/serializers/base" - -class Chef - class DataCollector - class Serializers - class RunStart < Base - - attr_reader :run_status - - def initialize(run_status) - @run_status = run_status - end - - def message_type - "run_start" - end - - def document - { - "chef_server_fqdn" => chef_server_fqdn, - "entity_uuid" => node_uuid, - "id" => run_status.run_id, - "message_version" => "1.0.0", - "message_type" => message_type, - "node_name" => run_status.node.name, - "organization_name" => organization, - "run_id" => run_status.run_id, - "source" => collector_source, - "start_time" => run_status.start_time.utc.iso8601, - } - end - end - end - end -end -- cgit v1.2.1