class ElasticAPM::Metadata::SystemInfo::ContainerInfo

@api private

Constants

CGROUP_PATH
CONTAINER_ID_REGEX
KUBEPODS_REGEX
SYSTEMD_SCOPE_SUFFIX

Attributes

cgroup_path[R]
container_id[RW]
kubernetes_namespace[RW]
kubernetes_node_name[RW]
kubernetes_pod_name[RW]
kubernetes_pod_uid[RW]

Public Class Methods

new(cgroup_path: CGROUP_PATH) click to toggle source
# File lib/elastic_apm/metadata/system_info/container_info.rb, line 12
def initialize(cgroup_path: CGROUP_PATH)
  @cgroup_path = cgroup_path
end
read!() click to toggle source
# File lib/elastic_apm/metadata/system_info/container_info.rb, line 24
def self.read!
  new.read!
end

Public Instance Methods

container() click to toggle source
# File lib/elastic_apm/metadata/system_info/container_info.rb, line 28
def container
  @container ||=
    begin
      return unless container_id
      { id: container_id }
    end
end
kubernetes() click to toggle source

rubocop:disable Metrics/MethodLength

# File lib/elastic_apm/metadata/system_info/container_info.rb, line 37
def kubernetes
  @kubernetes =
    begin
      kubernetes = {
        namespace: kubernetes_namespace,
        node: { name: kubernetes_node_name },
        pod: {
          name: kubernetes_pod_name,
          uid: kubernetes_pod_uid
        }
      }
      return nil if kubernetes.values.all?(&:nil?)

      kubernetes
    end
end
read!() click to toggle source
# File lib/elastic_apm/metadata/system_info/container_info.rb, line 18
def read!
  read_from_cgroup!
  read_from_env!
  self
end

Private Instance Methods

read_from_cgroup!() click to toggle source

rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize

# File lib/elastic_apm/metadata/system_info/container_info.rb, line 74
def read_from_cgroup!
  return unless File.exist?(cgroup_path)
  IO.readlines(cgroup_path).each do |line|
    parts = line.strip.split(':')
    next if parts.length != 3

    cgroup_path = parts[2]

    # Depending on the filesystem driver used for cgroup
    # management, the paths in /proc/pid/cgroup will have
    # one of the following formats in a Docker container:
    #
    #   systemd: /system.slice/docker-<container-ID>.scope
    #   cgroupfs: /docker/<container-ID>
    #
    # In a Kubernetes pod, the cgroup path will look like:
    #
    #   systemd:
    #      /kubepods.slice/kubepods-<QoS-class>.slice/kubepods-\
    #        <QoS-class>-pod<pod-UID>.slice/<container-iD>.scope
    #   cgroupfs:
    #      /kubepods/<QoS-class>/pod<pod-UID>/<container-iD>
    directory, container_id = File.split(cgroup_path)

    if container_id.end_with?(SYSTEMD_SCOPE_SUFFIX)
      container_id = container_id[0...-SYSTEMD_SCOPE_SUFFIX.length]
      if container_id.include?('-')
        container_id = container_id.split('-', 2)[1]
      end
    end

    if (kubepods_match = KUBEPODS_REGEX.match(directory))
      pod_id = kubepods_match[1] || kubepods_match[2]

      self.container_id = container_id
      self.kubernetes_pod_uid = pod_id
    elsif CONTAINER_ID_REGEX.match(container_id)
      self.container_id = container_id
    end
  end
end
read_from_env!() click to toggle source

rubocop:enable Metrics/MethodLength

# File lib/elastic_apm/metadata/system_info/container_info.rb, line 57
def read_from_env!
  self.kubernetes_namespace =
    ENV.fetch('KUBERNETES_NAMESPACE', kubernetes_namespace)
  self.kubernetes_node_name =
    ENV.fetch('KUBERNETES_NODE_NAME', kubernetes_node_name)
  self.kubernetes_pod_name =
    ENV.fetch('KUBERNETES_POD_NAME', kubernetes_pod_name)
  self.kubernetes_pod_uid =
    ENV.fetch('KUBERNETES_POD_UID', kubernetes_pod_uid)
end