Skip to content

Commit

Permalink
Fix for ImageId and Repository empty in Container Inventory (#1339)
Browse files Browse the repository at this point in the history
Fix for ImageId and Repository empty issue
  • Loading branch information
suyadav1 authored Jan 15, 2025
1 parent 37acc68 commit fbc48b6
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 76 deletions.
96 changes: 65 additions & 31 deletions source/plugins/go/input/lib/kubernetescontainerinventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,15 @@ func GetContainerInventoryRecords(podItem map[string]interface{}, batchTime stri
if imageIDValue, ok := containerStatusMap["imageID"].(string); ok && imageIDValue != "" {
if atLocation := strings.Index(imageIDValue, "@"); atLocation != -1 {
containerInventoryRecord["ImageId"] = imageIDValue[atLocation+1:]
} else {
containerInventoryRecord["ImageId"] = imageIDValue
}
}

if imageValue, ok := containerStatusMap["image"].(string); ok && imageValue != "" {
addImageInfoToContainerInventoryRecord(containerInventoryRecord, imageValue)
}

containerInventoryRecord["ExitCode"] = 0
isContainerTerminated := false
isContainerWaiting := false
Expand Down Expand Up @@ -116,36 +122,12 @@ func GetContainerInventoryRecords(podItem map[string]interface{}, batchTime stri

if containerInfoMap, ok := containersInfoMap[containerName]; ok {
if imageValue, ok := containerInfoMap["image"]; ok && imageValue != "" {
atLocation := strings.Index(imageValue, "@")
isDigestSpecified := false
if atLocation != -1 {
imageValue = imageValue[:atLocation]
if containerInventoryRecord["ImageId"] == nil || containerInventoryRecord["ImageId"] == "" {
containerInventoryRecord["ImageId"] = imageValue[atLocation+1:]
}
isDigestSpecified = true
}
slashLocation := strings.Index(imageValue, "/")
colonLocation := strings.Index(imageValue, ":")
if colonLocation != -1 {
if slashLocation == -1 {
containerInventoryRecord["Image"] = imageValue[:colonLocation]
} else {
containerInventoryRecord["Repository"] = imageValue[:slashLocation]
containerInventoryRecord["Image"] = imageValue[slashLocation+1 : colonLocation]
}
containerInventoryRecord["ImageTag"] = imageValue[colonLocation+1:]
} else {
if slashLocation == -1 {
containerInventoryRecord["Image"] = imageValue
} else {
containerInventoryRecord["Repository"] = imageValue[:slashLocation]
containerInventoryRecord["Image"] = imageValue[slashLocation+1:]
}
if !isDigestSpecified {
containerInventoryRecord["ImageTag"] = "latest"
}
}
addImageInfoToContainerInventoryRecord(containerInventoryRecord, imageValue)
}

// if the repository is still not populated, set a default value as docker.io
if containerInventoryRecord["Repository"] == nil || containerInventoryRecord["Repository"] == "" {
containerInventoryRecord["Repository"] = "docker.io"
}

podName := containerInfoMap["PodName"]
Expand Down Expand Up @@ -182,6 +164,58 @@ func GetContainerInventoryRecords(podItem map[string]interface{}, batchTime stri
return containerInventoryRecords
}

func addImageInfoToContainerInventoryRecord(containerInventoryRecord map[string]interface{}, imageValue string) {
// image can be in any one of below formats:
// repository/image[:imagetag | @digest], repository/image:imagetag@digest, repo/image, image:imagetag, image@digest, image
if imageValue == "" {
return
}
atLocation := strings.Index(imageValue, "@")
isDigestSpecified := false
if atLocation != -1 {
if containerInventoryRecord["ImageId"] == nil || containerInventoryRecord["ImageId"] == "" {
containerInventoryRecord["ImageId"] = imageValue[atLocation+1:]
}
imageValue = imageValue[:atLocation]
isDigestSpecified = true
}
slashLocation := strings.Index(imageValue, "/")
colonLocation := strings.Index(imageValue, ":")
if colonLocation != -1 {
if slashLocation == -1 {
if containerInventoryRecord["Image"] == nil || containerInventoryRecord["Image"] == "" {
containerInventoryRecord["Image"] = imageValue[:colonLocation]
}
} else {
if containerInventoryRecord["Repository"] == nil || containerInventoryRecord["Repository"] == "" {
containerInventoryRecord["Repository"] = imageValue[:slashLocation]
}
if containerInventoryRecord["Image"] == nil || containerInventoryRecord["Image"] == "" {
containerInventoryRecord["Image"] = imageValue[slashLocation+1 : colonLocation]
}
}
if containerInventoryRecord["ImageTag"] == nil || containerInventoryRecord["ImageTag"] == "" {
containerInventoryRecord["ImageTag"] = imageValue[colonLocation+1:]
}
} else {
if slashLocation == -1 {
if containerInventoryRecord["Image"] == nil || containerInventoryRecord["Image"] == "" {
containerInventoryRecord["Image"] = imageValue
}
} else {
if containerInventoryRecord["Repository"] == nil || containerInventoryRecord["Repository"] == "" {
containerInventoryRecord["Repository"] = imageValue[:slashLocation]
}
if containerInventoryRecord["Image"] == nil || containerInventoryRecord["Image"] == "" {
containerInventoryRecord["Image"] = imageValue[slashLocation+1:]
}
}
if !isDigestSpecified && (containerInventoryRecord["ImageTag"] == nil || containerInventoryRecord["ImageTag"] == "") {
containerInventoryRecord["ImageTag"] = "latest"
}
}
}

func getContainersInfoMap(podItem map[string]interface{}, isWindows bool) map[string]map[string]string {
containersInfoMap := make(map[string]map[string]string)

Expand Down Expand Up @@ -562,7 +596,7 @@ func GetContainerInventory(namespaceFilteringMode string, namespaces []string, b
return GetContainerInventoryHelper(podList, namespaceFilteringMode, namespaces, batchTime)
}

func GetContainerInventoryHelper(podList map[string]interface{}, namespaceFilteringMode string, namespaces []string, batchTime string) ([]string, []map[string]interface{}){
func GetContainerInventoryHelper(podList map[string]interface{}, namespaceFilteringMode string, namespaces []string, batchTime string) ([]string, []map[string]interface{}) {
containerIds := []string{}
containerInventory := []map[string]interface{}{}
clusterCollectEnvironmentVar := os.Getenv("AZMON_CLUSTER_COLLECT_ENV_VAR")
Expand Down
125 changes: 80 additions & 45 deletions source/plugins/ruby/kubernetes_container_inventory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,19 @@ def getContainerInventoryRecords(podItem, batchTime, clusterCollectEnvironmentVa
# for containers that have image issues (like invalid image/tag etc..) this will be empty. do not make it all 0
containerInventoryRecord["InstanceID"] = containerId
end
# imagedId is of the format - repo@sha256:imageid
# imagedId is either of the the format - repo@sha256:imageid or sha256:imageid
imageIdValue = containerStatus["imageID"]
if !imageIdValue.nil? && !imageIdValue.empty?
atLocation = imageIdValue.index("@")
if !atLocation.nil?
containerInventoryRecord["ImageId"] = imageIdValue[(atLocation + 1)..-1]
else
containerInventoryRecord["ImageId"] = imageIdValue
end
end

addImageInfoToContainerInventoryRecord(containerInventoryRecord, containerStatus["image"])

containerInventoryRecord["ExitCode"] = 0
isContainerTerminated = false
isContainerWaiting = false
Expand Down Expand Up @@ -84,49 +89,12 @@ def getContainerInventoryRecords(podItem, batchTime, clusterCollectEnvironmentVa
end

containerInfoMap = containersInfoMap[containerName]
# image can be in any one of below format in spec
# repository/image[:imagetag | @digest], repository/image:imagetag@digest, repo/image, image:imagetag, image@digest, image
imageValue = containerInfoMap["image"]
if !imageValue.nil? && !imageValue.empty?
# Find delimiters in image format
atLocation = imageValue.index("@")
isDigestSpecified = false
if !atLocation.nil?
# repository/image@digest or repository/image:imagetag@digest, image@digest
imageValue = imageValue[0..(atLocation - 1)]
# Use Digest from the spec's image in case when the status doesnt get populated i.e. container in pending or image pull back etc.
if containerInventoryRecord["ImageId"].nil? || containerInventoryRecord["ImageId"].empty?
containerInventoryRecord["ImageId"] = imageValue[(atLocation + 1)..-1]
end
isDigestSpecified = true
end
slashLocation = imageValue.index("/")
colonLocation = imageValue.index(":")
if !colonLocation.nil?
if slashLocation.nil?
# image:imagetag
containerInventoryRecord["Image"] = imageValue[0..(colonLocation - 1)]
else
# repository/image:imagetag
containerInventoryRecord["Repository"] = imageValue[0..(slashLocation - 1)]
containerInventoryRecord["Image"] = imageValue[(slashLocation + 1)..(colonLocation - 1)]
end
containerInventoryRecord["ImageTag"] = imageValue[(colonLocation + 1)..-1]
else
if slashLocation.nil?
# image
containerInventoryRecord["Image"] = imageValue
else
# repo/image
containerInventoryRecord["Repository"] = imageValue[0..(slashLocation - 1)]
containerInventoryRecord["Image"] = imageValue[(slashLocation + 1)..-1]
end
# if no tag specified, k8s assumes latest as imagetag and this is same behavior from docker API and from status.
# Ref - https://kubernetes.io/docs/concepts/containers/images/#image-names
if isDigestSpecified == false
containerInventoryRecord["ImageTag"] = "latest"
end
end
# Populate the fields related to the image if not already populated
addImageInfoToContainerInventoryRecord(containerInventoryRecord, containerInfoMap["image"])

# if the repository is still not populated, set a default value as docker.io
if containerInventoryRecord["Repository"].nil? || containerInventoryRecord["Repository"].empty?
containerInventoryRecord["Repository"] = "docker.io"
end

podName = containerInfoMap["PodName"]
Expand Down Expand Up @@ -169,6 +137,73 @@ def getContainerInventoryRecords(podItem, batchTime, clusterCollectEnvironmentVa
return containerInventoryRecords
end

def addImageInfoToContainerInventoryRecord(containerInventoryRecord, imageValue)
begin
if imageValue.nil? || imageValue.empty?
return
end
# image can be in any one of below formats:
# repository/image[:imagetag | @digest], repository/image:imagetag@digest, repo/image, image:imagetag, image@digest, image
# Find delimiters in image format
atLocation = imageValue.index("@")
isDigestSpecified = false
if !atLocation.nil?
# Use Digest from the spec's image in case when the status doesnt get populated i.e. container in pending or image pull back etc.
if containerInventoryRecord["ImageId"].nil? || containerInventoryRecord["ImageId"].empty?
containerInventoryRecord["ImageId"] = imageValue[(atLocation + 1)..-1]
end
# repository/image@digest or repository/image:imagetag@digest, image@digest
imageValue = imageValue[0..(atLocation - 1)]
isDigestSpecified = true
end
slashLocation = imageValue.index("/")
colonLocation = imageValue.index(":")
if !colonLocation.nil?
if slashLocation.nil?
# image:imagetag
if containerInventoryRecord["Image"].nil? || containerInventoryRecord["Image"].empty?
containerInventoryRecord["Image"] = imageValue[0..(colonLocation - 1)]
end
else
# repository/image:imagetag
if containerInventoryRecord["Repository"].nil? || containerInventoryRecord["Repository"].empty?
containerInventoryRecord["Repository"] = imageValue[0..(slashLocation - 1)]
end
if containerInventoryRecord["Image"].nil? || containerInventoryRecord["Image"].empty?
containerInventoryRecord["Image"] = imageValue[(slashLocation + 1)..(colonLocation - 1)]
end
end
if containerInventoryRecord["ImageTag"].nil? || containerInventoryRecord["ImageTag"].empty?
containerInventoryRecord["ImageTag"] = imageValue[(colonLocation + 1)..-1]
end
else
if slashLocation.nil?
# image
if containerInventoryRecord["Image"].nil? || containerInventoryRecord["Image"].empty?
containerInventoryRecord["Image"] = imageValue
end
else
# repo/image
if containerInventoryRecord["Repository"].nil? || containerInventoryRecord["Repository"].empty?
containerInventoryRecord["Repository"] = imageValue[0..(slashLocation - 1)]
end
if containerInventoryRecord["Image"].nil? || containerInventoryRecord["Image"].empty?
containerInventoryRecord["Image"] = imageValue[(slashLocation + 1)..-1]
end
end
# if no tag specified, k8s assumes latest as imagetag and this is same behavior from docker API and from status.
# Ref - https://kubernetes.io/docs/concepts/containers/images/#image-names
if isDigestSpecified == false && (containerInventoryRecord["ImageTag"].nil? || containerInventoryRecord["ImageTag"].empty?)
containerInventoryRecord["ImageTag"] = "latest"
end
end
rescue => error
$log.warn("KubernetesContainerInventory::addImageInfoToContainerInventoryRecord : Add Image Info to Container Inventory Records failed: #{error}")
$log.debug_backtrace(error.backtrace)
ApplicationInsightsUtility.sendExceptionTelemetry(error)
end
end

def getContainersInfoMap(podItem, isWindows)
containersInfoMap = {}
begin
Expand Down Expand Up @@ -405,4 +440,4 @@ def isSandboxingPod(podItem)
return isKataRuntimePod
end
end
end
end

0 comments on commit fbc48b6

Please sign in to comment.