Class: KubernetesDeploy::Pod

Inherits:
KubernetesResource show all
Defined in:
lib/kubernetes-deploy/kubernetes_resource/pod.rb

Defined Under Namespace

Classes: Container

Constant Summary collapse

TIMEOUT =
10.minutes
FAILED_PHASE_NAME =
"Failed"

Constants inherited from KubernetesResource

KubernetesResource::DEBUG_RESOURCE_NOT_FOUND_MESSAGE, KubernetesResource::DISABLED_EVENT_INFO_MESSAGE, KubernetesResource::DISABLED_LOG_INFO_MESSAGE, KubernetesResource::DISABLE_FETCHING_EVENT_INFO, KubernetesResource::DISABLE_FETCHING_LOG_INFO, KubernetesResource::LOG_LINE_COUNT, KubernetesResource::STANDARD_TIMEOUT_MESSAGE, KubernetesResource::TIMEOUT_OVERRIDE_ANNOTATION, KubernetesResource::UNUSUAL_FAILURE_MESSAGE

Instance Attribute Summary

Attributes inherited from KubernetesResource

#context, #deploy_started_at, #name, #namespace, #type

Instance Method Summary collapse

Methods inherited from KubernetesResource

build, #debug_message, #deploy_method, #deploy_started?, #deploy_timed_out?, #fetch_events, #file_path, #id, #kubectl, #pretty_status, #pretty_timeout_type, #report_status_to_statsd, #status, #sync_debug_info, timeout, #timeout, #timeout_override, #validate_definition, #validation_error_msg, #validation_failed?

Constructor Details

#initialize(namespace:, context:, definition:, logger:, parent: nil, deploy_started_at: nil) ⇒ Pod

Returns a new instance of Pod.



8
9
10
11
12
13
14
15
16
17
18
# File 'lib/kubernetes-deploy/kubernetes_resource/pod.rb', line 8

def initialize(namespace:, context:, definition:, logger:, parent: nil, deploy_started_at: nil)
  @parent = parent
  @deploy_started_at = deploy_started_at
  @containers = definition.fetch("spec", {}).fetch("containers", []).map { |c| Container.new(c) }
  unless @containers.present?
    logger.summary.add_paragraph("Rendered template content:\n#{definition.to_yaml}")
    raise FatalDeploymentError, "Template is missing required field spec.containers"
  end
  @containers += definition["spec"].fetch("initContainers", []).map { |c| Container.new(c, init_container: true) }
  super(namespace: namespace, context: context, definition: definition, logger: logger)
end

Instance Method Details

#deploy_failed?Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/kubernetes-deploy/kubernetes_resource/pod.rb', line 50

def deploy_failed?
  failure_message.present?
end

#deploy_succeeded?Boolean

Returns:

  • (Boolean)


42
43
44
45
46
47
48
# File 'lib/kubernetes-deploy/kubernetes_resource/pod.rb', line 42

def deploy_succeeded?
  if unmanaged?
    @phase == "Succeeded"
  else
    @phase == "Running" && @ready
  end
end

#exists?Boolean

Returns:

  • (Boolean)


54
55
56
# File 'lib/kubernetes-deploy/kubernetes_resource/pod.rb', line 54

def exists?
  @found
end

#failure_messageObject



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/kubernetes-deploy/kubernetes_resource/pod.rb', line 65

def failure_message
  if @phase == FAILED_PHASE_NAME
    phase_problem = "Pod status: #{@status}. "
  end

  doomed_containers = @containers.select(&:doomed?)
  if doomed_containers.present?
    container_problems = if unmanaged?
      "The following containers encountered errors:\n"
    else
      "The following containers are in a state that is unlikely to be recoverable:\n"
    end
    doomed_containers.each do |c|
      red_name = ColorizedString.new(c.name).red
      container_problems += "> #{red_name}: #{c.doom_reason}\n"
    end
  end
  "#{phase_problem}#{container_problems}".presence
end

#fetch_logsObject

Returns a hash in the following format:

"app" => ["array of log lines", "received from app container"],
"nginx" => ["array of log lines", "received from nginx container"]



90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/kubernetes-deploy/kubernetes_resource/pod.rb', line 90

def fetch_logs
  return {} unless exists? && @containers.present?
  @containers.each_with_object({}) do |container, container_logs|
    cmd = [
      "logs",
      @name,
      "--container=#{container.name}",
      "--since-time=#{@deploy_started_at.to_datetime.rfc3339}",
    ]
    cmd << "--tail=#{LOG_LINE_COUNT}" unless unmanaged?
    out, _err, _st = kubectl.run(*cmd)
    container_logs[container.name] = out.split("\n")
  end
end

#sync(pod_data = nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/kubernetes-deploy/kubernetes_resource/pod.rb', line 20

def sync(pod_data = nil)
  if pod_data.blank?
    raw_json, _err, st = kubectl.run("get", type, @name, "-a", "--output=json")
    pod_data = JSON.parse(raw_json) if st.success?
    raise_predates_deploy_error if pod_data.present? && unmanaged? && !deploy_started?
  end

  if pod_data.present?
    @found = true
    @phase = @status = pod_data["status"]["phase"]
    @status += " (Reason: #{pod_data['status']['reason']})" if pod_data['status']['reason'].present?
    @ready = ready?(pod_data["status"])
    update_container_statuses(pod_data["status"])
  else # reset
    @found = @ready = false
    @status = @phase = 'Unknown'
    @containers.each(&:reset_status)
  end

  display_logs if unmanaged? && deploy_succeeded?
end

#timeout_messageObject



58
59
60
61
62
63
# File 'lib/kubernetes-deploy/kubernetes_resource/pod.rb', line 58

def timeout_message
  return STANDARD_TIMEOUT_MESSAGE unless readiness_probe_failure?
  probe_failure_msgs = @containers.map(&:readiness_fail_reason).compact
  header = "The following containers have not passed their readiness probes on at least one pod:\n"
  header + probe_failure_msgs.join("\n") + "\n"
end