I am trying to collect IP addresses of the pods which has 3 network interfaces attached to. From the output of kubectl get pod .. -o yaml
, I would like to collect the IPs of 2nd and 3rd interfaces including pod-name.
kubectl describe pod
data:
apiVersion: v1
items:
- apiVersion: v1
kind: Pod
metadata:
annotations:
k8s.v1.cni.cncf.io/network-status: |-
[{
"name": "default-cni-network",
"ips": [
"10.244.160.191"
],
"default": true,
"dns": {}
},{
"name": "minio-tenant/minio-sriov1",
"interface": "net1",
"ips": [
"10.56.217.100"
],
"mac": "6a:58:82:8a:93:7b",
"dns": {},
"device-info": {
"type": "pci",
"version": "1.0.0",
"pci": {
"pci-address": "0000:b1:02.7"
}
}
},{
"name": "minio-tenant/minio-sriov2",
"interface": "net2",
"ips": [
"10.56.218.100"
],
"mac": "66:a2:70:eb:5e:04",
"dns": {},
"device-info": {
"type": "pci",
"version": "1.0.0",
"pci": {
"pci-address": "0000:b1:14.0"
}
}
}]
k8s.v1.cni.cncf.io/networks: minio-sriov1,minio-sriov2
k8s.v1.cni.cncf.io/networks-status: |-
[{
"name": "default-cni-network",
"ips": [
"10.244.160.191"
],
"default": true,
"dns": {}
},{
"name": "minio-tenant/minio-sriov1",
"interface": "net1",
"ips": [
"10.56.217.100"
],
"mac": "6a:58:82:8a:93:7b",
"dns": {},
"device-info": {
"type": "pci",
"version": "1.0.0",
"pci": {
"pci-address": "0000:b1:02.7"
}
}
},{
"name": "minio-tenant/minio-sriov2",
"interface": "net2",
"ips": [
"10.56.218.100"
],
"mac": "66:a2:70:eb:5e:04",
"dns": {},
"device-info": {
"type": "pci",
"version": "1.0.0",
"pci": {
"pci-address": "0000:b1:14.0"
}
}
}]
kubernetes.io/psp: node-exporter
meta.helm.sh/release-name: minio-tenant
meta.helm.sh/release-namespace: minio-tenant
min.io/revision: "0"
creationTimestamp: "2022-04-27T08:09:45Z"
generateName: minio-tenant-ss-0-
labels:
app: minio
app.kubernetes.io/managed-by: Helm
controller-revision-hash: minio-tenant-ss-0-7976bbfbc6
statefulset.kubernetes.io/pod-name: minio-tenant-ss-0-0
spec:
affinity:
containers:
- args:
- :9090
env:
- name: MINIO_UPDATE
Using this regular expression:
networks-status:[\s\S]*?
(?:")(name)(?:":\s*")([\S]*)(?:",[\s]*)
(?:")(interface)(?:":\s*")([\S]*)(?:",[\s\S]*?)
(?:")(ips)(?:":\s*\[\s*")([\S]*)(?:")
[\s\S]*?(pod-name)(?::\s)([\S]*)
I would like to get the following output:
name
minio-tenant/minio-sriov1
interface
net1
ips
10.56.217.100
name
minio-tenant/minio-sriov2
interface
net2
ips
10.56.218.100
pod-name
minio-tenant-ss-0-0
It gets me:
name
minio-tenant/minio-sriov1
interface
net1
ips
10.56.217.100
pod-name
minio-tenant-ss-0-0
There is missing portion of IP:
name
minio-tenant/minio-sriov2
interface
net2
ips
10.56.218.100
If I use *
or
to repeat on the data section, I am getting unexpected result.
networks-status:[\s\S]*?
(
(?:")(name)(?:":\s*")([\S]*)(?:",[\s]*)
(?:")(interface)(?:":\s*")([\S]*)(?:",[\s\S]*?)
(?:")(ips)(?:":\s*\[\s*")([\S]*)(?:")
)*
[\s\S]*?(pod-name)(?::\s)([\S]*)
Can you give some hints how I can get the expected results?
CodePudding user response:
As I said in the comments, jq
is the tool of your choise here.
$ kubectl get pod <name> -o json | jq -r '.items[].metadata.annotations."k8s.v1.cni.cncf.io/network-status" | fromjson | del(.[0]) | .[] | .name "\t" .interface "\t" .ips[]'
First we get the value of the annotation by .items[].metadata.annotations."k8s.v1.cni.cncf.io/network-status"
which returns a string with json in it. So we use fromjson
to convert it from json and get an array. We delete the first entry del(.[0])
, because you wrote you only want the 2nd and 3rd and in the end print the name, the interface and the ip separated with a tab for each element .[] | .name "\t" .interface "\t" .ips[]
.
This will output
minio-tenant/minio-sriov1 net1 10.56.217.100
minio-tenant/minio-sriov2 net2 10.56.218.100
CodePudding user response:
Don't use regular expression for this, it is a little bit like trying to use them to parse HTML, it is a non sense, especially because Ansible is very JSON capable. Your issue here lies in the fact that those JSON snippets are in string in your YAML dictionary, but you can use the from_json
filter in order to query them.
Here, I am using a json_query
and JMESPath to retrieve the objects as you where expecting them:
- debug:
var: >-
{
'networks': _metadata.annotations['k8s.v1.cni.cncf.io/network-status']
| from_json
| json_query('[?default != `true`].{
name: name,
interface: interface,
ips: ips
}'),
'pod-name': _metadata.labels['statefulset.kubernetes.io/pod-name']
}
vars:
_metadata: "{{ k8s.stdout['items'].0.metadata }}"
This would yield:
networks:
- interface: net1
ips:
- 10.56.217.100
name: minio-tenant/minio-sriov1
- interface: net2
ips:
- 10.56.218.100
name: minio-tenant/minio-sriov2
pod-name: minio-tenant-ss-0-0
CodePudding user response:
There should be an easier way to do it:
check the kubectl cheat sheet with many example for jsonpath or jq.