class Krane::DaemonSet

def deploy_failed?

def deploy_failed?
  pods.present? && pods.any?(&:deploy_failed?) &&
  observed_generation == current_generation
end

def deploy_succeeded?

def deploy_succeeded?
  return false unless exists?
  current_generation == observed_generation &&
    rollout_data["desiredNumberScheduled"].to_i == rollout_data["updatedNumberScheduled"].to_i &&
    relevant_pods_ready?
end

def fetch_debug_logs

def fetch_debug_logs
  most_useful_pod = pods.find(&:deploy_failed?) || pods.find(&:deploy_timed_out?) || pods.first
  most_useful_pod.fetch_debug_logs
end

def find_nodes(cache)

def find_nodes(cache)
  all_nodes = cache.get_all(Node.kind)
  all_nodes.each_with_object([]) do |node_data, relevant_nodes|
    next if node_data.dig('spec', 'unschedulable').to_s.downcase == 'true'
    cond = node_data.dig('status', 'conditions').find { |c| c['type'].downcase == 'ready' }
    next if (!cond.nil? && cond['status'].downcase != 'true')
    relevant_nodes << Node.new(definition: node_data)
  end
end

def parent_of_pod?(pod_data)

def parent_of_pod?(pod_data)
  return false unless pod_data.dig("metadata", "ownerReferences")
  template_generation = @instance_data.dig("spec", "templateGeneration") ||
    @instance_data.dig("metadata", "annotations", "deprecated.daemonset.template.generation")
  return false unless template_generation.present?
  pod_data["metadata"]["ownerReferences"].any? { |ref| ref["uid"] == @instance_data["metadata"]["uid"] } &&
  pod_data["metadata"]["labels"]["pod-template-generation"].to_i == template_generation.to_i
end

def print_debug_logs?

def print_debug_logs?
  pods.present? # the kubectl command times out if no pods exist
end

def refresh_nodes(cache)

def refresh_nodes(cache)
  new_nodes = find_nodes(cache)
  return new_nodes if @nodes.blank?
  # Remove non-existent nodes
  @nodes.select do |node|
    new_nodes.find { |n| n.name == node.name } != nil
  end
end

def relevant_pods_ready?

def relevant_pods_ready?
  return true if rollout_data["desiredNumberScheduled"].to_i == rollout_data["numberReady"].to_i # all pods ready
  relevant_node_names = @nodes.map(&:name)
  considered_pods = @pods.select { |p| relevant_node_names.include?(p.node_name) && !p.evicted? }
  @logger.debug("DaemonSet is reporting #{rollout_data['numberReady']} pods ready." \
    " Considered #{considered_pods.size} pods out of #{@pods.size} for #{@nodes.size} nodes.")
  considered_pods.present? &&
    considered_pods.all?(&:deploy_succeeded?) &&
    rollout_data["numberReady"].to_i >= considered_pods.length
end

def rollout_data

def rollout_data
  return { "currentNumberScheduled" => 0 } unless exists?
  @instance_data["status"]
    .slice("updatedNumberScheduled", "desiredNumberScheduled", "numberReady")
end

def status

def status
  return super unless exists?
  rollout_data.map { |state_replicas, num| "#{num} #{state_replicas}" }.join(", ")
end

def sync(cache)

def sync(cache)
  super
  @pods = exists? ? find_pods(cache) : []
  @nodes = refresh_nodes(cache)
end