class Gitchefsync::EnvSync

Public Class Methods

new(repo_list) click to toggle source
# File lib/gitchefsync/env_sync.rb, line 90
def initialize(repo_list)
  options = Gitchefsync.options
  config = Gitchefsync.configuration

  FS.knifeReady(config['stage_dir'],options[:knife_config])

  repo_list.each do |repo|
    repo.validate_structure
  end

  @knife = config['knife']
  @stage_filepath = config['stage_dir']
  @force_upload = config['force_upload']
  @repo_list = repo_list
  #this is a bit of a hack to determine if we're writing audit
  @sous = config['sync_local']
  @audit = Audit.new(config['audit_dir'], 'env' )
  @audit_keep_trim = config['audit_keep_trim']
  @audit_keep_trim ||= 20
  @env_file_list = Array.new()
  @db_file_list = Array.new()
  @role_file_list = Array.new()
end

Public Instance Methods

cleanup_json_files() click to toggle source
# File lib/gitchefsync/env_sync.rb, line 211
def cleanup_json_files
  Gitchefsync.logger.info "cleanup_json_files"

  #list env and compare on the server, deleting ones that aren't in git
  knifeUtil = KnifeUtil.new(@knife, @stage_filepath)

  delta_env_list = knifeUtil.listEnv() - @env_file_list
  Gitchefsync.logger.info "event_id=env_diff:delta=#{delta_env_list}"
  # MAND-672
  delta_env_list.each do |env_name|
    # TODO: Audit file may not be correct if someone manually
    #       uploaded an environment file with json 'name' variable different
    #       then actual environment filename.
    a = AuditItem.new(env_name,'',nil)
    a.setAction "DEL"
    FS.cmd "#{@knife} environment delete #{env_name} --yes"
    Gitchefsync.logger.info "event_id=environment_deleted:env_name=#{env_name}"
    @audit.add(a)
  end
 
  delta_db_list = knifeUtil.listDB() - @db_file_list
  Gitchefsync.logger.info "event_id=data_bag_item_diff:delta=#{delta_db_list}"
  delta_db_list.each do |bag, item|
    # TODO: Audit file may not be correct if someone manually
    #       uploaded an data bag with item json 'id' variable different
    #       then actual json filename.
    a = AuditItem.new("BAG: #{bag} ITEM: #{item}",'',nil)
    a.setAction "DEL"
    FS.cmd "#{@knife} data bag delete #{bag} #{item} --yes"
    Gitchefsync.logger.info "event_id=data_bag_item_deleted:bag=#{bag}:item=#{item}"
    @audit.add(a)
    
    items_remaining = knifeUtil.showDBItem(bag)
    if items_remaining.empty?
      a = AuditItem.new("BAG: #{bag}",'',nil)
      a.setAction "DEL"
      FS.cmd "#{@knife} data bag delete #{bag} --yes"
      Gitchefsync.logger.info "event_id=data_bag_deleted:bag=#{bag}"
      @audit.add(a)
    end
  end
 
  delta_role_list = knifeUtil.listRole() - @role_file_list
  Gitchefsync.logger.info "event_id=role_diff:delta=#{delta_role_list}"
  delta_role_list.each do |role_name|
    # TODO: Audit file may not be correct if someone manually
    #       uploaded an role file with json 'name' variable different
    #       then actual role filename.
    a = AuditItem.new(role_name,'',nil)
    a.setAction "DEL"
    FS.cmd "#{@knife} role delete #{role_name} --yes"
    Gitchefsync.logger.info "event_id=role_deleted:role_name=#{role_name}"
    @audit.add(a)
  end

 
  if !@sous
    @audit.write
    #trim the audit file
    @audit.trim(@audit_keep_trim)
  end 
end
data_bag_iden(fullpath) click to toggle source
# File lib/gitchefsync/env_sync.rb, line 159
def data_bag_iden fullpath
  chef_repo, data_bag = false, false
  fullpath.split(File::SEPARATOR).each do |dir|
    return dir if chef_repo && data_bag
    chef_repo = dir.eql? "chef-repo" unless chef_repo
    data_bag = dir.eql? "data_bags" if chef_repo
  end
  raise ValidationError, "event_id=invalid_path_to_data_bag_json:path=#{fullpath}"
end
json_type(file) click to toggle source
# File lib/gitchefsync/env_sync.rb, line 126
def json_type file
  return "env" unless FS.getBasePath(file, "environments").nil?
  return "db" unless FS.getBasePath(file, "data_bags").nil?
  return "role" unless FS.getBasePath(file, "roles").nil?
end
reject_json(content) click to toggle source
# File lib/gitchefsync/env_sync.rb, line 114
def reject_json content
  file_json = nil
  begin
    
    file_json = JSON.parse content
  rescue Exception => e
    Gitchefsync.logger.error "event_id=env_json_parse_error:file=#{file}"
    @audit.addEnv(file,'UPDATE', e )
  end
  file_json
end
update_json_files() click to toggle source
# File lib/gitchefsync/env_sync.rb, line 275
def update_json_files
  Gitchefsync.logger.info "event_id=update_json_files"
  @env_file_list.clear
  @env_file_list << "_default"
  @db_file_list.clear
  @role_file_list.clear

  #latest audit info for delta purposes
  begin
    latest_audit = @audit.latestAuditItems
    latest_audit ||= Array.new
    Gitchefsync.logger.info "event_id=audit_file_found:length=#{latest_audit.length}"
  rescue AuditError => e
    Gitchefsync.logger.warn "event_id=no_audit_file_found"
    latest_audit = Array.new
  end
 
  
  @repo_list.each do |repo|
    env_dir = repo.chef_path + "/**/*json"

    Dir.glob(env_dir).each  do |file|

      file_attr = Hash.new()
      content = File.read(file)
      
      file_attr['json'] = reject_json(content)
      next if file_attr['json'].nil?
      file_attr['type'] = json_type(file)
      file_attr['filename'] = File.basename(file)
      file_attr['basename'] = File.basename(file).chomp(".json")
      file_attr['fullpath'] = file
      file_attr['extra_info'] = Hash.new
      #To do comparison we'll hash current
      file_attr['extra_info']['digest'] = Digest::SHA256.hexdigest content
      #and compare hash to last audit
      item = @audit.itemByName(file,latest_audit)
      delta = true
      if !item.nil?
        Gitchefsync.logger.debug "event_id=audit_item_found:name=#{file}:digest=#{file_attr['extra_info']['digest']}"
        if item.extra_info != nil && file_attr['extra_info']['digest'].eql?(item.extra_info['digest'])
          Gitchefsync.logger.debug "file_digest=#{item.extra_info['digest']}"
          delta = false
        end
      else
        Gitchefsync.logger.warn "event_id=no_audit_item_found:name=#{file}"
      end
      if file_attr['type'].eql? "env"
        upload_env(file_attr, delta)
      elsif file_attr['type'].eql? "db"
        upload_db(file_attr, delta)
      elsif file_attr['type'].eql? "role"
        upload_role(file_attr, delta)
      end
    end
  end

  self.cleanup_json_files
end
upload_db(f, delta) click to toggle source
# File lib/gitchefsync/env_sync.rb, line 169
def upload_db(f, delta)
  Gitchefsync.logger.debug "event_id=upload_data_bag:filepath=#{f['fullpath']}:delta=#{delta}"
  db_iden = data_bag_iden(f['fullpath'])
  begin
    validate_json(f, 'id')
    @db_file_list << [db_iden, f['json']['id']]
    #show_out = FS.cmdNoError "#{@knife} data bag show #{db_iden} #{f['json']['id']}"
    if delta || @force_upload
      FS.cmd "#{@knife} data bag create #{db_iden}"
      FS.cmd "#{@knife} data bag from file #{db_iden} #{f['fullpath']}"
      Gitchefsync.logger.info "event_id=databag_uploaded:file_json_name=#{f['json']['id']}:file=#{f['fullpath']}"
      @audit.addEnv(f['fullpath'],'UPDATE', nil, f['extra_info'] )
    else
      Gitchefsync.logger.debug "event_id=data_bag_not_uploaded:file_json_name=#{f['json']['id']}:file=#{f['fullpath']}"
      @audit.addEnv(f['fullpath'],'EXISTING', nil, f['extra_info'])
    end
  rescue ValidationError => e
    Gitchefsync.logger.error("event_id=validation_error:msg=#{e.message}")
    @audit.addEnv(f['fullpath'],'UPDATE', e , f['extra_info'])
  end
end
upload_env(f, delta) click to toggle source
# File lib/gitchefsync/env_sync.rb, line 139
def upload_env(f, delta)
  Gitchefsync.logger.debug "event_id=upload_env:filepath=#{f['fullpath']}:delta=#{delta}"
  begin
    validate_json(f, 'name')
    @env_file_list << f['json']['name']
    
    if delta || @force_upload
      FS.cmd "#{@knife} environment from file #{f['fullpath']} --yes"
      Gitchefsync.logger.info "event_id=environment_uploaded:file_json_name=#{f['json']['name']}:file=#{f['fullpath']}"
      @audit.addEnv(f['fullpath'],'UPDATE',nil,f['extra_info'] )
    else
      Gitchefsync.logger.debug "event_id=environment_not_uploaded:file_json_name=#{f['json']['name']}:file=#{f['fullpath']}"
      @audit.addEnv(f['fullpath'],'EXISTING',nil,f['extra_info'] )
    end
  rescue ValidationError => e
    Gitchefsync.logger.error("event_id=validation_error:msg=#{e.message}")
    @audit.addEnv(f['fullpath'],'UPDATE', e ,f['extra_info'])
  end
end
upload_role(f, delta) click to toggle source
# File lib/gitchefsync/env_sync.rb, line 191
def upload_role(f, delta)
  Gitchefsync.logger.debug "event_id=upload_role:fullpath=#{f['fullpath']}:delta=#{delta}"
  begin
    validate_json(f, 'name')
    @role_file_list << f['json']['name']
    
    if delta || @force_upload
      FS.cmd "#{@knife} role from file #{f['fullpath']} --yes"
      Gitchefsync.logger.info "event_id=role_uploaded:file_json_name=#{f['json']['name']}:file=#{f['fullpath']}"
      @audit.addEnv(f['fullpath'],'UPDATE',nil, f['extra_info'] )
    else
      Gitchefsync.logger.debug "event_id=role_not_uploaded:file_json_name=#{f['json']['name']}:file=#{f['fullpath']}"
      @audit.addEnv(f['fullpath'],'EXISTING', nil, f['extra_info'] )
    end
  rescue ValidationError => e
    Gitchefsync.logger.error("event_id=validation_error:msg=#{e.message}")
    @audit.addEnv(f['fullpath'],'UPDATE', e , f['extra_info'])
  end
end
validate_json(f, iden) click to toggle source
# File lib/gitchefsync/env_sync.rb, line 132
def validate_json(f, iden)
  if f['basename'] != f['json'][iden]
    raise ValidationError, "The file json's #{iden} attribute does not match basename: #{f['basename']}"
  end
  Gitchefsync.logger.debug "event_id=json_is_valid:iden=#{iden}:basename=#{f['basename']}"
end