class ChefCLI::PolicyfileServices::CleanPolicies

def http_client

def http_client
  @http_client ||= Chef::ServerAPI.new(chef_config.chef_server_url,
    signing_key_filename: chef_config.client_key,
    client_name: chef_config.node_name)
end

def initialize(config: nil, ui: nil)

def initialize(config: nil, ui: nil)
  @chef_config = config
  @ui = ui
end

def orphaned_policies

def orphaned_policies
  policy_lister.policies_by_name.keys.inject([]) do |orphans, policy_name|
    orphans + policy_lister.orphaned_revisions(policy_name).map do |revision_id|
      Orphan.new(policy_name, revision_id)
    end
  end
rescue => e
  raise PolicyfileCleanError.new("Failed to list policies for cleaning.", e)
end

def policy_lister

def policy_lister
  @policy_lister ||= Policyfile::Lister.new(config: chef_config)
end

def remove_policy(policy)

def remove_policy(policy)
  ui.msg("DELETE #{policy.policy_name} #{policy.revision_id}")
  http_client.delete("/policies/#{policy.policy_name}/revisions/#{policy.revision_id}")
  :ok
rescue => e
  e
end

def run

def run
  revisions_to_remove = orphaned_policies
  if revisions_to_remove.empty?
    ui.err("No policy revisions deleted")
    return true
  end
  results = revisions_to_remove.map do |policy|
    [ remove_policy(policy), policy ]
  end
  failures = results.select { |result, _policy| result.is_a?(Exception) }
  unless failures.empty?
    details = failures.map do |result, policy|
      "- #{policy.policy_name} (#{policy.revision_id}): #{result.class} #{result}"
    end
    message = "Failed to delete some policy revisions:\n" + details.join("\n") + "\n"
    raise PolicyfileCleanError.new(message, MultipleErrors.new("multiple errors"))
  end
  true
end