From c7cea1d197c053e5d8aafc68d813689bf8bb2291 Mon Sep 17 00:00:00 2001 From: Akshay Suryawanshi Date: Tue, 6 Jun 2017 06:40:35 -0400 Subject: [PATCH] refactor jetpants_collins moving collins_get and collins_set to its own class --- plugins/jetpants_collins/jetpants_collins.rb | 104 ++--------------- plugins/jetpants_collins/jetpants_tracker.rb | 114 +++++++++++++++++++ testing/packages/jetpants/jetpants.yaml | 2 + 3 files changed, 123 insertions(+), 97 deletions(-) create mode 100644 plugins/jetpants_collins/jetpants_tracker.rb diff --git a/plugins/jetpants_collins/jetpants_collins.rb b/plugins/jetpants_collins/jetpants_collins.rb index 95ac39a..b1e6142 100644 --- a/plugins/jetpants_collins/jetpants_collins.rb +++ b/plugins/jetpants_collins/jetpants_collins.rb @@ -188,7 +188,6 @@ def service end end - ##### INSTANCE (MIX-IN) METHODS ########################################## # The base class needs to implement this! @@ -196,31 +195,17 @@ def collins_asset raise "Any class including Plugin::JetCollins must also implement collins_asset instance method!" end + def collins + Jetpants::Plugin::JetCollinsAsset::Tracker.new(lambda { collins_asset }, lambda { |msg| output msg }) + end + # Pass in a symbol, or array of symbols, to obtain from Collins for this # asset. For example, :status, :pool, :primary_role, :secondary_role. # If you pass in a single symbol, returns a single value. # If you pass in an array, returns a hash mapping each of these fields to their values. # Hash will also contain an extra field called :asset, storing the Collins::Asset object. def collins_get(*field_names) - asset = collins_asset - - if field_names.count > 1 || field_names[0].is_a?(Array) - field_names.flatten! - want_state = !! field_names.delete(:state) - results = Hash[field_names.map {|field| [field, (asset ? asset.send(field) : '')]}] - results[:state] = asset.state.name if want_state - results[:asset] = asset - results - elsif field_names.count == 1 - return '' unless asset - if field_names[0] == :state - asset.state.name - else - asset.send field_names[0] - end - else - nil - end + collins.get(*field_names) end # Pass in a hash mapping field name symbols to values to set @@ -231,82 +216,7 @@ def collins_get(*field_names) # # Alternatively, pass in 2 strings (field_name, value) to set just a single Collins attribute (or status) def collins_set(*args) - attrs = (args.count == 1 ? args[0] : {args[0] => args[1]}) - asset = attrs[:asset] || collins_asset - - upcase = !attrs[:literal] - attrs.delete(:literal) - - # refuse to set Collins values on machines in remote data center unless - # inter_dc_mode is enabled - if asset && asset.type.downcase == 'server_node' && asset.location && asset.location.upcase != Plugin::JetCollins.datacenter - asset = nil unless Jetpants::Plugin::JetCollins.inter_dc_mode? - end - - attrs.each do |key, val| - val ||= '' - case key - when :asset - next - when :status - unless asset - output "WARNING: unable to set Collins status to #{val}" - next - end - state_val = attrs[:state] - previous_status = asset.status.capitalize - # Allow setting status:state at once via foo.collins_status = 'allocated:running' - if val.include? ':' - raise "Attempting to set state in two places" if state_val - vals = val.split(':', 2) - val = vals.first.capitalize - state_val = vals.last.upcase - end - if state_val - previous_state = asset.state.name.upcase - next unless previous_state != state_val.to_s.upcase || previous_status != val.to_s.capitalize - success = Jetpants::Plugin::JetCollins.set_status!(asset, val, 'changed through jetpants', state_val) - unless success - # If we failed to set to this state, try creating the state as new - Jetpants::Plugin::JetCollins.state_create!(state_val, state_val, state_val, val) - success = Jetpants::Plugin::JetCollins.set_status!(asset, val, 'changed through jetpants', state_val) - end - raise "#{self}: Unable to set Collins state to #{state_val} and Unable to set Collins status to #{val}" unless success - output "Collins status:state changed from #{previous_status}:#{previous_state} to #{val.capitalize}:#{state_val.upcase}" - elsif previous_status != val.to_s.capitalize - success = Jetpants::Plugin::JetCollins.set_status!(asset, val) - raise "#{self}: Unable to set Collins status to #{val}" unless success - output "Collins status changed from #{previous_status} to #{val}" - end - when :state - unless asset && asset.status && attrs[:status] - raise "#{self}: Unable to set state without settings a status" unless attrs[:status] - output "WARNING: unable to set Collins state to #{val}" - next - end - else - unless asset - output "WARNING: unable to set Collins attribute #{key} to #{val}" - next - end - previous_value = asset.send(key) - val = val.to_s - val = val.upcase if upcase - if previous_value != val - success = Jetpants::Plugin::JetCollins.set_attribute!(asset, key.to_s.upcase, val) - raise "#{self}: Unable to set Collins attribute #{key} to #{val}" unless success - if (val == '' || !val) && (previous_value == '' || !previous_value) - false - elsif val == '' - output "Collins attribute #{key.to_s.upcase} removed (was: #{previous_value})" - elsif !previous_value || previous_value == '' - output "Collins attribute #{key.to_s.upcase} set to #{val}" - else - output "Collins attribute #{key.to_s.upcase} changed from #{previous_value} to #{val}" - end - end - end - end + collins.set(*args) end # Returns a single downcased "status:state" string, useful when trying to compare both fields @@ -322,4 +232,4 @@ def collins_status_state # load all the monkeypatches for other Jetpants classes -%w(monkeypatch asset host db pool shard topology shardpool commandsuite).each {|mod| require "jetpants_collins/#{mod}"} +%w(monkeypatch asset host db pool shard topology shardpool commandsuite jetpants_tracker).each {|mod| require "jetpants_collins/#{mod}"} diff --git a/plugins/jetpants_collins/jetpants_tracker.rb b/plugins/jetpants_collins/jetpants_tracker.rb new file mode 100644 index 0000000..b6a6093 --- /dev/null +++ b/plugins/jetpants_collins/jetpants_tracker.rb @@ -0,0 +1,114 @@ +module Jetpants + module Plugin + module JetCollinsAsset + + class Tracker + def initialize(asset, logger) + @asset = asset + @logger = logger + end + + def output msg + @logger.call msg + end + + def get(*field_names) + asset = @asset.call + + if field_names.count > 1 || field_names[0].is_a?(Array) + field_names.flatten! + want_state = !! field_names.delete(:state) + results = Hash[field_names.map {|field| [field, (asset ? asset.send(field) : '')]}] + results[:state] = asset.state.name if want_state + results[:asset] = asset + results + elsif field_names.count == 1 + return '' unless asset + if field_names[0] == :state + asset.state.name + else + asset.send field_names[0] + end + else + nil + end + end + + def set(*args) + attrs = (args.count == 1 ? args[0] : {args[0] => args[1]}) + asset = attrs[:asset] || @asset.call + + upcase = !attrs[:literal] + attrs.delete(:literal) + + if asset && asset.type.downcase == 'server_node' && asset.location && asset.location.upcase != Plugin::JetCollins.datacenter + asset = nil unless Jetpants::Plugin::JetCollins.inter_dc_mode? + end + + attrs.each do |key, val| + val ||= '' + case key + when :asset + next + when :status + unless asset + output "WARNING: unable to set Collins status to #{val}" + next + end + state_val = attrs[:state] + previous_status = asset.status.capitalize + if val.include? ':' + raise "Attempting to set state in two places" if state_val + vals = val.split(':', 2) + val = vals.first.capitalize + state_val = vals.last.upcase + end + if state_val + previous_state = asset.state.name.upcase + next unless previous_state != state_val.to_s.upcase || previous_status != val.to_s.capitalize + success = Jetpants::Plugin::JetCollins.set_status!(asset, val, 'changed through jetpants', state_val) + unless success + Jetpants::Plugin::JetCollins.state_create!(state_val, state_val, state_val, val) + success = Jetpants::Plugin::JetCollins.set_status!(asset, val, 'changed through jetpants', state_val) + end + raise "#{self}: Unable to set Collins state to #{state_val} and Unable to set Collins status to #{val}" unless success + output "Collins status:state changed from #{previous_status}:#{previous_state} to #{val.capitalize}:#{state_val.upcase}" + elsif previous_status != val.to_s.capitalize + success = Jetpants::Plugin::JetCollins.set_status!(asset, val) + raise "#{self}: Unable to set Collins status to #{val}" unless success + output "Collins status changed from #{previous_status} to #{val}" + end + when :state + unless asset && asset.status && attrs[:status] + raise "#{self}: Unable to set state without settings a status" unless attrs[:status] + output "WARNING: unable to set Collins state to #{val}" + next + end + else + unless asset + output "WARNING: unable to set Collins attribute #{key} to #{val}" + next + end + previous_value = asset.send(key) + val = val.to_s + val = val.upcase if upcase + if previous_value != val + success = Jetpants::Plugin::JetCollins.set_attribute!(asset, key.to_s.upcase, val) + raise "#{self}: Unable to set Collins attribute #{key} to #{val}" unless success + if (val == '' || !val) && (previous_value == '' || !previous_value) + false + elsif val == '' + output "Collins attribute #{key.to_s.upcase} removed (was: #{previous_value})" + elsif !previous_value || previous_value == '' + output "Collins attribute #{key.to_s.upcase} set to #{val}" + else + output "Collins attribute #{key.to_s.upcase} changed from #{previous_value} to #{val}" + end + end + end + end + end + end + end # module JetCollinsAsset + end # module Plugin +end # module Jetpants diff --git a/testing/packages/jetpants/jetpants.yaml b/testing/packages/jetpants/jetpants.yaml index c6b9c81..4dbccb8 100755 --- a/testing/packages/jetpants/jetpants.yaml +++ b/testing/packages/jetpants/jetpants.yaml @@ -67,5 +67,7 @@ plugins: - mysql_default_cipher remote_lookup: false inter_dc_mode: false + retries: 23 + max_retry_backoff: 16 online_schema_change: