Skip to content

Commit

Permalink
Refactor replicaset provider into readable functions
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenpost committed Apr 3, 2024
1 parent 4078d2e commit 372d5ec
Showing 1 changed file with 136 additions and 129 deletions.
265 changes: 136 additions & 129 deletions lib/puppet/provider/mongodb_replset/mongo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,33 @@ def destroy
end

def flush
set_members
if @property_flush[:ensure] == :absent
# TODO: I don't know how to remove a node from a replset; unimplemented
# Puppet.debug "Removing all members from replset #{self.name}"
# @property_hash[:members].collect do |member|
# rs_remove(member, master_host(@property_hash[:members]))
# end
return
end

alive_hosts = if !@property_flush[:members].nil? && !@property_flush[:members].empty?
# Find the alive members so we don't try to add dead members to the replset using new config
get_alive_members(@property_flush[:members])
elsif !resource[:members].nil? && !resource[:members].empty?
# Find the alive members using current 'is' config
get_alive_members(@resource[:members])
else
[]
end

raise Puppet::Error, 'Replica set needs at least one member alive to make changes' if alive_hosts.empty?

if @property_flush[:ensure] == :present && @property_hash[:ensure] != :present && !master_host(alive_hosts)
create_replica_set(alive_hosts)
else
update_members(alive_hosts)
update_settings if !@property_flush[:settings].nil? && !@property_flush[:settings].empty?
end
@property_hash = self.class.replset_properties
end

Expand Down Expand Up @@ -223,158 +249,139 @@ def get_replset_settings_changes(current_settings, new_settings)
current_settings
end

def set_members
if @property_flush[:ensure] == :absent
# TODO: I don't know how to remove a node from a replset; unimplemented
# Puppet.debug "Removing all members from replset #{self.name}"
# @property_hash[:members].collect do |member|
# rs_remove(member, master_host(@property_hash[:members]))
# end
return
end

def get_alive_members(members)
Puppet.debug 'Checking for dead and alive members'
if !@property_flush[:members].nil? && !@property_flush[:members].empty?
# Find the alive members so we don't try to add dead members to the replset using new config
alive_hosts, dead_hosts = get_hosts_status(@property_flush[:members])
Puppet.debug "Alive members: #{alive_hosts.inspect}"
Puppet.debug "Dead members: #{dead_hosts.inspect}" unless dead_hosts.empty?
raise Puppet::Error, "Can't connect to any member of replicaset #{name}." if alive_hosts.empty?
elsif !resource[:members].nil? && !resource[:members].empty?
# Find the alive members using current 'is' config
alive_hosts, dead_hosts = get_hosts_status(@resource[:members])
Puppet.debug "Alive members: #{alive_hosts.inspect}"
Puppet.debug "Dead members: #{dead_hosts.inspect}" unless dead_hosts.empty?
raise Puppet::Error, "Can't connect to any member of replicaset #{name}." if alive_hosts.empty?
else
alive_hosts = []
end
alive_hosts, dead_hosts = get_hosts_status(members)
Puppet.debug "Alive members: #{alive_hosts.inspect}"
Puppet.debug "Dead members: #{dead_hosts.inspect}" unless dead_hosts.empty?
raise Puppet::Error, "Can't connect to any member of replicaset #{name}." if alive_hosts.empty?

Puppet.debug 'Checking for new replset'
if @property_flush[:ensure] == :present && @property_hash[:ensure] != :present && !master_host(alive_hosts)
Puppet.debug "Initializing the replset #{name}"
alive_hosts
end

def create_replica_set(alive_hosts)
Puppet.debug "Initializing the replset #{name}"

# Create a replset configuration
members_conf = alive_hosts.each_with_index.map do |host, id|
member = host
member['_id'] = id
member
end

# Create a replset configuration
members_conf = alive_hosts.each_with_index.map do |host, id|
member = host
member['_id'] = id
member
replset_conf = {
_id: name,
members: members_conf,
settings: (@property_flush[:settings].nil? ? {} : @property_flush[:settings])
}.to_json

Puppet.debug "Starting replset config is #{replset_conf.to_json}"
output = rs_initiate(replset_conf)
raise Puppet::Error, "rs.initiate() failed for replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?

# Check that the replicaset has finished initialization
retry_limit = 10
retry_sleep = 3

retry_limit.times do |n|
if db_ismaster(alive_hosts[0]['host'])['ismaster']
Puppet.debug 'Replica set initialization has successfully ended'
return true
else
Puppet.debug "Waiting for replica initialization. Retry: #{n}"
sleep retry_sleep
next
end
end
raise Puppet::Error, "rs.initiate() failed for replicaset #{name}"
end

replset_conf = {
_id: name,
members: members_conf,
settings: (@property_flush[:settings].nil? ? {} : @property_flush[:settings])
}.to_json
def update_members(alive_hosts)
Puppet.debug "Checking for replset #{name} changes"
master = master_host(alive_hosts)
raise Puppet::Error, "Can't find master host for replicaset #{name}." unless master

Puppet.debug "Starting replset config is #{replset_conf.to_json}"
output = rs_initiate(replset_conf)
raise Puppet::Error, "rs.initiate() failed for replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?
master_rs_config = rs_config(master)
add_members, remove_members, update_members = get_members_changes(master_rs_config['members'], @property_flush[:members])

# Check that the replicaset has finished initialization
Puppet.debug "Members to be Added: #{add_members.inspect}" unless add_members.empty?
add_members.each do |member|
retry_limit = 10
retry_sleep = 3

output = {}
retry_limit.times do |n|
if db_ismaster(alive_hosts[0]['host'])['ismaster']
Puppet.debug 'Replica set initialization has successfully ended'
return true
else
Puppet.debug "Waiting for replica initialization. Retry: #{n}"
output = rs_add(member, master)
if output['ok'].zero?
Puppet.debug "Retry adding host to replicaset. Retry: #{n}"
sleep retry_sleep
next
master = master_host(alive_hosts)
else
Puppet.debug 'Host successfully added to replicaset'
break
end
end
raise Puppet::Error, "rs.initiate() failed for replicaset #{name}: host #{alive_hosts[0]['host']} didn't become master"
raise Puppet::Error, "rs.add() failed to add host to replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?
end

else
Puppet.debug "Checking for replset #{name} changes"
master = master_host(alive_hosts)
raise Puppet::Error, "Can't find master host for replicaset #{name}." unless master

master_rs_config = rs_config(master)
add_members, remove_members, update_members = get_members_changes(master_rs_config['members'], @property_flush[:members])

Puppet.debug "Members to be Added: #{add_members.inspect}" unless add_members.empty?
add_members.each do |member|
retry_limit = 10
retry_sleep = 3

output = {}
retry_limit.times do |n|
output = rs_add(member, master)
if output['ok'].zero?
Puppet.debug "Retry adding host to replicaset. Retry: #{n}"
sleep retry_sleep
master = master_host(alive_hosts)
else
Puppet.debug 'Host successfully added to replicaset'
break
end
end
raise Puppet::Error, "rs.add() failed to add host to replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?
end
Puppet.debug "Members to be Removed: #{remove_members.inspect}" unless remove_members.empty?
remove_members.each do |member|
retry_limit = 10
retry_sleep = 3

Puppet.debug "Members to be Removed: #{remove_members.inspect}" unless remove_members.empty?
remove_members.each do |member|
retry_limit = 10
retry_sleep = 3

output = {}
retry_limit.times do |n|
output = rs_remove(member, master)
if output['ok'].zero?
Puppet.debug "Retry removing host from replicaset. Retry: #{n}"
sleep retry_sleep
master = master_host(alive_hosts)
else
Puppet.debug 'Host successfully removed from replicaset'
break
end
output = {}
retry_limit.times do |n|
output = rs_remove(member, master)
if output['ok'].zero?
Puppet.debug "Retry removing host from replicaset. Retry: #{n}"
sleep retry_sleep
master = master_host(alive_hosts)
else
Puppet.debug 'Host successfully removed from replicaset'
break
end
raise Puppet::Error, "rs.remove() failed to remove host from replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?
end
raise Puppet::Error, "rs.remove() failed to remove host from replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?
end

Puppet.debug "Members to be Updated: #{update_members.inspect}" unless update_members.empty?
update_members.each do |member|
retry_limit = 10
retry_sleep = 3

Puppet.debug "Members to be Updated: #{update_members.inspect}" unless update_members.empty?
update_members.each do |member|
retry_limit = 10
retry_sleep = 3

output = {}
retry_limit.times do |n|
output = rs_reconfig_member(member, master)
if output['ok'].zero?
Puppet.debug "Retry updating host in replicaset. Retry: #{n}"
sleep retry_sleep
master = master_host(alive_hosts)
else
Puppet.debug 'Host successfully updated in replicaset'
break
end
output = {}
retry_limit.times do |n|
output = rs_reconfig_member(member, master)
if output['ok'].zero?
Puppet.debug "Retry updating host in replicaset. Retry: #{n}"
sleep retry_sleep
master = master_host(alive_hosts)
else
Puppet.debug 'Host successfully updated in replicaset'
break
end
raise Puppet::Error, "rs.reconfig() failed to update host in replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?
end
raise Puppet::Error, "rs.reconfig() failed to update host in replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?
end
end

if !@property_flush[:settings].nil? && !@property_flush[:settings].empty?
settings = get_replset_settings_changes(master_rs_config, @property_flush[:settings])
Puppet.warning "Updating settings for replset #{name}"
retry_limit = 10
retry_sleep = 3
output = {}
retry_limit.times do |n|
output = rs_reconfig_settings(settings, master)
if output['ok'].zero?
Puppet.debug "Retry updating settings in replicaset. Retry: #{n}"
sleep retry_sleep
master = master_host(alive_hosts)
else
Puppet.debug 'Settings successfully updated in replicaset'
break
end
end
raise Puppet::Error, "rs.reconfig() failed to update settings in replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?
def update_settings
settings = get_replset_settings_changes(master_rs_config, @property_flush[:settings])
Puppet.warning "Updating settings for replset #{name}"
retry_limit = 10
retry_sleep = 3
output = {}
retry_limit.times do |n|
output = rs_reconfig_settings(settings, master)
if output['ok'].zero?
Puppet.debug "Retry updating settings in replicaset. Retry: #{n}"
sleep retry_sleep
else
Puppet.debug 'Settings successfully updated in replicaset'
break
end
end
raise Puppet::Error, "rs.reconfig() failed to update settings in replicaset #{name}: #{output['errmsg']}" if output['ok'].zero?
end

def mongo_command(command, host, retries = 4)
Expand Down

0 comments on commit 372d5ec

Please sign in to comment.