Skip to content

Commit fbc48b6

Browse files
authored
Fix for ImageId and Repository empty in Container Inventory (#1339)
Fix for ImageId and Repository empty issue
1 parent 37acc68 commit fbc48b6

File tree

2 files changed

+145
-76
lines changed

2 files changed

+145
-76
lines changed

source/plugins/go/input/lib/kubernetescontainerinventory.go

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,15 @@ func GetContainerInventoryRecords(podItem map[string]interface{}, batchTime stri
7979
if imageIDValue, ok := containerStatusMap["imageID"].(string); ok && imageIDValue != "" {
8080
if atLocation := strings.Index(imageIDValue, "@"); atLocation != -1 {
8181
containerInventoryRecord["ImageId"] = imageIDValue[atLocation+1:]
82+
} else {
83+
containerInventoryRecord["ImageId"] = imageIDValue
8284
}
8385
}
8486

87+
if imageValue, ok := containerStatusMap["image"].(string); ok && imageValue != "" {
88+
addImageInfoToContainerInventoryRecord(containerInventoryRecord, imageValue)
89+
}
90+
8591
containerInventoryRecord["ExitCode"] = 0
8692
isContainerTerminated := false
8793
isContainerWaiting := false
@@ -116,36 +122,12 @@ func GetContainerInventoryRecords(podItem map[string]interface{}, batchTime stri
116122

117123
if containerInfoMap, ok := containersInfoMap[containerName]; ok {
118124
if imageValue, ok := containerInfoMap["image"]; ok && imageValue != "" {
119-
atLocation := strings.Index(imageValue, "@")
120-
isDigestSpecified := false
121-
if atLocation != -1 {
122-
imageValue = imageValue[:atLocation]
123-
if containerInventoryRecord["ImageId"] == nil || containerInventoryRecord["ImageId"] == "" {
124-
containerInventoryRecord["ImageId"] = imageValue[atLocation+1:]
125-
}
126-
isDigestSpecified = true
127-
}
128-
slashLocation := strings.Index(imageValue, "/")
129-
colonLocation := strings.Index(imageValue, ":")
130-
if colonLocation != -1 {
131-
if slashLocation == -1 {
132-
containerInventoryRecord["Image"] = imageValue[:colonLocation]
133-
} else {
134-
containerInventoryRecord["Repository"] = imageValue[:slashLocation]
135-
containerInventoryRecord["Image"] = imageValue[slashLocation+1 : colonLocation]
136-
}
137-
containerInventoryRecord["ImageTag"] = imageValue[colonLocation+1:]
138-
} else {
139-
if slashLocation == -1 {
140-
containerInventoryRecord["Image"] = imageValue
141-
} else {
142-
containerInventoryRecord["Repository"] = imageValue[:slashLocation]
143-
containerInventoryRecord["Image"] = imageValue[slashLocation+1:]
144-
}
145-
if !isDigestSpecified {
146-
containerInventoryRecord["ImageTag"] = "latest"
147-
}
148-
}
125+
addImageInfoToContainerInventoryRecord(containerInventoryRecord, imageValue)
126+
}
127+
128+
// if the repository is still not populated, set a default value as docker.io
129+
if containerInventoryRecord["Repository"] == nil || containerInventoryRecord["Repository"] == "" {
130+
containerInventoryRecord["Repository"] = "docker.io"
149131
}
150132

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

167+
func addImageInfoToContainerInventoryRecord(containerInventoryRecord map[string]interface{}, imageValue string) {
168+
// image can be in any one of below formats:
169+
// repository/image[:imagetag | @digest], repository/image:imagetag@digest, repo/image, image:imagetag, image@digest, image
170+
if imageValue == "" {
171+
return
172+
}
173+
atLocation := strings.Index(imageValue, "@")
174+
isDigestSpecified := false
175+
if atLocation != -1 {
176+
if containerInventoryRecord["ImageId"] == nil || containerInventoryRecord["ImageId"] == "" {
177+
containerInventoryRecord["ImageId"] = imageValue[atLocation+1:]
178+
}
179+
imageValue = imageValue[:atLocation]
180+
isDigestSpecified = true
181+
}
182+
slashLocation := strings.Index(imageValue, "/")
183+
colonLocation := strings.Index(imageValue, ":")
184+
if colonLocation != -1 {
185+
if slashLocation == -1 {
186+
if containerInventoryRecord["Image"] == nil || containerInventoryRecord["Image"] == "" {
187+
containerInventoryRecord["Image"] = imageValue[:colonLocation]
188+
}
189+
} else {
190+
if containerInventoryRecord["Repository"] == nil || containerInventoryRecord["Repository"] == "" {
191+
containerInventoryRecord["Repository"] = imageValue[:slashLocation]
192+
}
193+
if containerInventoryRecord["Image"] == nil || containerInventoryRecord["Image"] == "" {
194+
containerInventoryRecord["Image"] = imageValue[slashLocation+1 : colonLocation]
195+
}
196+
}
197+
if containerInventoryRecord["ImageTag"] == nil || containerInventoryRecord["ImageTag"] == "" {
198+
containerInventoryRecord["ImageTag"] = imageValue[colonLocation+1:]
199+
}
200+
} else {
201+
if slashLocation == -1 {
202+
if containerInventoryRecord["Image"] == nil || containerInventoryRecord["Image"] == "" {
203+
containerInventoryRecord["Image"] = imageValue
204+
}
205+
} else {
206+
if containerInventoryRecord["Repository"] == nil || containerInventoryRecord["Repository"] == "" {
207+
containerInventoryRecord["Repository"] = imageValue[:slashLocation]
208+
}
209+
if containerInventoryRecord["Image"] == nil || containerInventoryRecord["Image"] == "" {
210+
containerInventoryRecord["Image"] = imageValue[slashLocation+1:]
211+
}
212+
}
213+
if !isDigestSpecified && (containerInventoryRecord["ImageTag"] == nil || containerInventoryRecord["ImageTag"] == "") {
214+
containerInventoryRecord["ImageTag"] = "latest"
215+
}
216+
}
217+
}
218+
185219
func getContainersInfoMap(podItem map[string]interface{}, isWindows bool) map[string]map[string]string {
186220
containersInfoMap := make(map[string]map[string]string)
187221

@@ -562,7 +596,7 @@ func GetContainerInventory(namespaceFilteringMode string, namespaces []string, b
562596
return GetContainerInventoryHelper(podList, namespaceFilteringMode, namespaces, batchTime)
563597
}
564598

565-
func GetContainerInventoryHelper(podList map[string]interface{}, namespaceFilteringMode string, namespaces []string, batchTime string) ([]string, []map[string]interface{}){
599+
func GetContainerInventoryHelper(podList map[string]interface{}, namespaceFilteringMode string, namespaces []string, batchTime string) ([]string, []map[string]interface{}) {
566600
containerIds := []string{}
567601
containerInventory := []map[string]interface{}{}
568602
clusterCollectEnvironmentVar := os.Getenv("AZMON_CLUSTER_COLLECT_ENV_VAR")

source/plugins/ruby/kubernetes_container_inventory.rb

Lines changed: 80 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,19 @@ def getContainerInventoryRecords(podItem, batchTime, clusterCollectEnvironmentVa
4343
# for containers that have image issues (like invalid image/tag etc..) this will be empty. do not make it all 0
4444
containerInventoryRecord["InstanceID"] = containerId
4545
end
46-
# imagedId is of the format - repo@sha256:imageid
46+
# imagedId is either of the the format - repo@sha256:imageid or sha256:imageid
4747
imageIdValue = containerStatus["imageID"]
4848
if !imageIdValue.nil? && !imageIdValue.empty?
4949
atLocation = imageIdValue.index("@")
5050
if !atLocation.nil?
5151
containerInventoryRecord["ImageId"] = imageIdValue[(atLocation + 1)..-1]
52+
else
53+
containerInventoryRecord["ImageId"] = imageIdValue
5254
end
5355
end
56+
57+
addImageInfoToContainerInventoryRecord(containerInventoryRecord, containerStatus["image"])
58+
5459
containerInventoryRecord["ExitCode"] = 0
5560
isContainerTerminated = false
5661
isContainerWaiting = false
@@ -84,49 +89,12 @@ def getContainerInventoryRecords(podItem, batchTime, clusterCollectEnvironmentVa
8489
end
8590

8691
containerInfoMap = containersInfoMap[containerName]
87-
# image can be in any one of below format in spec
88-
# repository/image[:imagetag | @digest], repository/image:imagetag@digest, repo/image, image:imagetag, image@digest, image
89-
imageValue = containerInfoMap["image"]
90-
if !imageValue.nil? && !imageValue.empty?
91-
# Find delimiters in image format
92-
atLocation = imageValue.index("@")
93-
isDigestSpecified = false
94-
if !atLocation.nil?
95-
# repository/image@digest or repository/image:imagetag@digest, image@digest
96-
imageValue = imageValue[0..(atLocation - 1)]
97-
# 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.
98-
if containerInventoryRecord["ImageId"].nil? || containerInventoryRecord["ImageId"].empty?
99-
containerInventoryRecord["ImageId"] = imageValue[(atLocation + 1)..-1]
100-
end
101-
isDigestSpecified = true
102-
end
103-
slashLocation = imageValue.index("/")
104-
colonLocation = imageValue.index(":")
105-
if !colonLocation.nil?
106-
if slashLocation.nil?
107-
# image:imagetag
108-
containerInventoryRecord["Image"] = imageValue[0..(colonLocation - 1)]
109-
else
110-
# repository/image:imagetag
111-
containerInventoryRecord["Repository"] = imageValue[0..(slashLocation - 1)]
112-
containerInventoryRecord["Image"] = imageValue[(slashLocation + 1)..(colonLocation - 1)]
113-
end
114-
containerInventoryRecord["ImageTag"] = imageValue[(colonLocation + 1)..-1]
115-
else
116-
if slashLocation.nil?
117-
# image
118-
containerInventoryRecord["Image"] = imageValue
119-
else
120-
# repo/image
121-
containerInventoryRecord["Repository"] = imageValue[0..(slashLocation - 1)]
122-
containerInventoryRecord["Image"] = imageValue[(slashLocation + 1)..-1]
123-
end
124-
# if no tag specified, k8s assumes latest as imagetag and this is same behavior from docker API and from status.
125-
# Ref - https://kubernetes.io/docs/concepts/containers/images/#image-names
126-
if isDigestSpecified == false
127-
containerInventoryRecord["ImageTag"] = "latest"
128-
end
129-
end
92+
# Populate the fields related to the image if not already populated
93+
addImageInfoToContainerInventoryRecord(containerInventoryRecord, containerInfoMap["image"])
94+
95+
# if the repository is still not populated, set a default value as docker.io
96+
if containerInventoryRecord["Repository"].nil? || containerInventoryRecord["Repository"].empty?
97+
containerInventoryRecord["Repository"] = "docker.io"
13098
end
13199

132100
podName = containerInfoMap["PodName"]
@@ -169,6 +137,73 @@ def getContainerInventoryRecords(podItem, batchTime, clusterCollectEnvironmentVa
169137
return containerInventoryRecords
170138
end
171139

140+
def addImageInfoToContainerInventoryRecord(containerInventoryRecord, imageValue)
141+
begin
142+
if imageValue.nil? || imageValue.empty?
143+
return
144+
end
145+
# image can be in any one of below formats:
146+
# repository/image[:imagetag | @digest], repository/image:imagetag@digest, repo/image, image:imagetag, image@digest, image
147+
# Find delimiters in image format
148+
atLocation = imageValue.index("@")
149+
isDigestSpecified = false
150+
if !atLocation.nil?
151+
# 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.
152+
if containerInventoryRecord["ImageId"].nil? || containerInventoryRecord["ImageId"].empty?
153+
containerInventoryRecord["ImageId"] = imageValue[(atLocation + 1)..-1]
154+
end
155+
# repository/image@digest or repository/image:imagetag@digest, image@digest
156+
imageValue = imageValue[0..(atLocation - 1)]
157+
isDigestSpecified = true
158+
end
159+
slashLocation = imageValue.index("/")
160+
colonLocation = imageValue.index(":")
161+
if !colonLocation.nil?
162+
if slashLocation.nil?
163+
# image:imagetag
164+
if containerInventoryRecord["Image"].nil? || containerInventoryRecord["Image"].empty?
165+
containerInventoryRecord["Image"] = imageValue[0..(colonLocation - 1)]
166+
end
167+
else
168+
# repository/image:imagetag
169+
if containerInventoryRecord["Repository"].nil? || containerInventoryRecord["Repository"].empty?
170+
containerInventoryRecord["Repository"] = imageValue[0..(slashLocation - 1)]
171+
end
172+
if containerInventoryRecord["Image"].nil? || containerInventoryRecord["Image"].empty?
173+
containerInventoryRecord["Image"] = imageValue[(slashLocation + 1)..(colonLocation - 1)]
174+
end
175+
end
176+
if containerInventoryRecord["ImageTag"].nil? || containerInventoryRecord["ImageTag"].empty?
177+
containerInventoryRecord["ImageTag"] = imageValue[(colonLocation + 1)..-1]
178+
end
179+
else
180+
if slashLocation.nil?
181+
# image
182+
if containerInventoryRecord["Image"].nil? || containerInventoryRecord["Image"].empty?
183+
containerInventoryRecord["Image"] = imageValue
184+
end
185+
else
186+
# repo/image
187+
if containerInventoryRecord["Repository"].nil? || containerInventoryRecord["Repository"].empty?
188+
containerInventoryRecord["Repository"] = imageValue[0..(slashLocation - 1)]
189+
end
190+
if containerInventoryRecord["Image"].nil? || containerInventoryRecord["Image"].empty?
191+
containerInventoryRecord["Image"] = imageValue[(slashLocation + 1)..-1]
192+
end
193+
end
194+
# if no tag specified, k8s assumes latest as imagetag and this is same behavior from docker API and from status.
195+
# Ref - https://kubernetes.io/docs/concepts/containers/images/#image-names
196+
if isDigestSpecified == false && (containerInventoryRecord["ImageTag"].nil? || containerInventoryRecord["ImageTag"].empty?)
197+
containerInventoryRecord["ImageTag"] = "latest"
198+
end
199+
end
200+
rescue => error
201+
$log.warn("KubernetesContainerInventory::addImageInfoToContainerInventoryRecord : Add Image Info to Container Inventory Records failed: #{error}")
202+
$log.debug_backtrace(error.backtrace)
203+
ApplicationInsightsUtility.sendExceptionTelemetry(error)
204+
end
205+
end
206+
172207
def getContainersInfoMap(podItem, isWindows)
173208
containersInfoMap = {}
174209
begin
@@ -405,4 +440,4 @@ def isSandboxingPod(podItem)
405440
return isKataRuntimePod
406441
end
407442
end
408-
end
443+
end

0 commit comments

Comments
 (0)