External Commands
Hasta ahora los comandos que practicamos son comandos nativos del sistema operativo que ya posee instrucciones en Nushell (aquellos 430 comandos) que generan salidas de datos estructurados.
¿Los clis que utilizamos en el día a día generan datos estructurados? Vamos a hacer una prueba con kubectl.
Dentro de Nushell...
~> kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-668d6bf9bc-2trtq 0/1 Running 1 (23s ago) 15d
kube-system coredns-668d6bf9bc-2w7pp 0/1 Running 1 (23s ago) 15d
kube-system etcd-kind-control-plane 1/1 Running 0 19s
kube-system kindnet-qrvhz 1/1 Running 1 (23s ago) 15d
kube-system kube-apiserver-kind-control-plane 1/1 Running 0 19s
kube-system kube-controller-manager-kind-control-plane 1/1 Running 3 (23s ago) 15d
kube-system kube-proxy-hcx2w 1/1 Running 1 (23s ago) 15d
kube-system kube-scheduler-kind-control-plane 1/1 Running 3 (23s ago) 15d
Podemos ver que incluso en Nushell la salida fue un texto puro que es lo esperado por el cli, pero podemos convertir esto canalizando esa salida al detect y ahí sí los datos estarán estructurados.
kubectl get pods --all-namespaces | detect columns
╭────┬────────────────────┬─────────────────────────────────────────────────┬───────┬───────────┬──────────┬─────╮
│ # │ NAMESPACE │ NAME │ READY │ STATUS │ RESTARTS │ AGE │
├────┼────────────────────┼─────────────────────────────────────────────────┼───────┼───────────┼──────────┼─────┤
│ 0 │ kube-system │ coredns-668d6bf9bc-2trtq │ 1/1 │ Running │ 1 │ 15d │
│ 1 │ kube-system │ coredns-668d6bf9bc-2w7pp │ 1/1 │ Running │ 1 │ 15d │
│ 2 │ kube-system │ etcd-kind-control-plane │ 1/1 │ Running │ 0 │ 43s │
│ 3 │ kube-system │ kindnet-qrvhz │ 1/1 │ Running │ 1 │ 15d │
│ 4 │ kube-system │ kube-apiserver-kind-control-plane │ 1/1 │ Running │ 0 │ 43s │
│ 5 │ kube-system │ kube-controller-manager-kind-control-plane │ 1/1 │ Running │ 3 │ 15d │
│ 6 │ kube-system │ kube-proxy-hcx2w │ 1/1 │ Running │ 1 │ 15d │
│ 7 │ kube-system │ kube-scheduler-kind-control-plane │ 1/1 │ Running │ 3 │ 15d │
│ 8 │ kube-system │ node-shell-a1cb3985-2609-4946-bbdd-aae156e50d0a │ 0/1 │ Completed │ 0 │ 15d │
│ 9 │ kube-system │ node-shell-bd1ea152-5ef3-4da0-8f4c-3236ff264f3c │ 0/1 │ Unknown │ 0 │ 13d │
│ 10 │ local-path-storage │ local-path-provisioner-58cc7856b6-j8w6t │ 0/1 │ Error │ 1 │ 15d │
╰────┴────────────────────┴─────────────────────────────────────────────────┴───────┴───────────┴──────────┴─────╯
La instrucción detect columns analizó el texto, descubrió los encabezados y valores de las columnas y usó eso para generar datos Nushell y con eso podemos usar los datos de la misma manera que hicimos antes. Vamos a utilizar esos datos.
~> kubectl get pods --all-namespaces | detect columns | where status == "Completed"
╭───┬─────────────┬─────────────────────────────────────────────────┬───────┬───────────┬──────────┬─────╮
│ # │ NAMESPACE │ NAME │ READY │ STATUS │ RESTARTS │ AGE │
├───┼─────────────┼─────────────────────────────────────────────────┼───────┼───────────┼──────────┼─────┤
│ 0 │ kube-system │ node-shell-a1cb3985-2609-4946-bbdd-aae156e50d0a │ 0/1 │ Completed │ 0 │ 15d │
╰───┴─────────────┴─────────────────────────────────────────────────┴───────┴───────────┴──────────┴─────╯
Vamos a agarrar todos que están corriendo por el nombre...
~> kubectl get pods --all-namespaces | detect columns | where status == "Running" | get name
╭───┬────────────────────────────────────────────╮
│ 0 │ coredns-668d6bf9bc-2trtq │
│ 1 │ coredns-668d6bf9bc-2w7pp │
│ 2 │ etcd-kind-control-plane │
│ 3 │ kindnet-qrvhz │
│ 4 │ kube-apiserver-kind-control-plane │
│ 5 │ kube-controller-manager-kind-control-plane │
│ 6 │ kube-proxy-hcx2w │
│ 7 │ kube-scheduler-kind-control-plane │
│ 8 │ local-path-provisioner-58cc7856b6-j8w6t │
╰───┴────────────────────────────────────────────╯
Ahora vamos a agarrar la salida yaml en texto que el comando kubectl get pods -n kube-system kube-scheduler-kind-control-plane -o yaml y estructurar eso...
~> kubectl get pods -n kube-system kube-scheduler-kind-control-plane -o yaml | from yaml
╭────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ apiVersion │ v1 │
│ kind │ Pod │
│ │ ╭───────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ metadata │ │ │ ╭─────────────────────────────┬──────────────────────────────────╮ │ │
│ │ │ annotations │ │ kubernetes.io/config.hash │ 9c2438caa1b59cbb78b0b03f9f4aaee6 │ │ │
│ │ │ │ │ kubernetes.io/config.mirror │ 9c2438caa1b59cbb78b0b03f9f4aaee6 │ │ │
│ │ │ │ │ kubernetes.io/config.seen │ 2025-01-26T10:47:47.286614565Z │ │ │
│ │ │ │ │ kubernetes.io/config.source │ file │ │ │
│ │ │ │ ╰─────────────────────────────┴──────────────────────────────────╯ │ │
│ │ │ creationTimestamp │ 2025-01-26T10:47:51Z │ │
│ │ │ │ ╭───────────┬────────────────╮ │ │
│ │ │ labels │ │ component │ kube-scheduler │ │ │
│ │ │ │ │ tier │ control-plane │ │ │
│ │ │ │ ╰───────────┴────────────────╯ │ │
│ │ │ name │ kube-scheduler-kind-control-plane │ │
│ │ │ namespace │ kube-system │ │
│ │ │ │ ╭───┬────────────┬────────────┬──────┬────────────────────┬──────────────────────────────────────╮ │ │
│ │ │ ownerReferences │ │ # │ apiVersion │ controller │ kind │ name │ uid │ │ │
│ │ │ │ ├───┼────────────┼────────────┼──────┼────────────────────┼──────────────────────────────────────┤ │ │
│ │ │ │ │ 0 │ v1 │ true │ Node │ kind-control-plane │ 7af4cd53-251f-4de2-b37e-c12e081b4f92 │ │ │
│ │ │ │ ╰───┴────────────┴────────────┴──────┴────────────────────┴──────────────────────────────────────╯ │ │
│ │ │ resourceVersion │ 75695 │ │
│ │ │ uid │ acf18d3c-41bf-4bfe-9707-dbb8b19ed395 │ │
│ │ ╰───────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │ ╭───────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ spec │ │ │ ╭───┬────────────────────────────────────────────────────────────────────┬─────────────────────────────┬─────╮ │ │
│ │ │ containers │ │ # │ command │ env │ ... │ │ │
│ │ │ │ ├───┼────────────────────────────────────────────────────────────────────┼─────────────────────────────┼─────┤ │ │
│ │ │ │ │ 0 │ ╭───┬────────────────────────────────────────────────────────────╮ │ ╭───┬──────────┬──────────╮ │ ... │ │ │
│ │ │ │ │ │ │ 0 │ kube-scheduler │ │ │ # │ name │ value │ │ │ │ │
│ │ │ │ │ │ │ 1 │ --authentication-kubeconfig=/etc/kubernetes/scheduler.conf │ │ ├───┼──────────┼──────────┤ │ │ │ │
│ │ │ │ │ │ │ 2 │ --authorization-kubeconfig=/etc/kubernetes/scheduler.conf │ │ │ 0 │ NO_PROXY │ *.local; │ │ │ │ │
│ │ │ │ │ │ │ 3 │ --bind-address=127.0.0.1 │ │ │ │ │ 169.254/ │ │ │ │ │
│ │ │ │ │ │ │ 4 │ --kubeconfig=/etc/kubernetes/scheduler.conf │ │ │ │ │ 16 │ │ │ │ │
│ │ │ │ │ │ │ 5 │ --leader-elect=true │ │ ╰───┴──────────┴──────────╯ │ │ │ │
│ │ │ │ │ │ ╰───┴────────────────────────────────────────────────────────────╯ │ │ │ │ │
│ │ │ │ ╰───┴────────────────────────────────────────────────────────────────────┴─────────────────────────────┴─────╯ │ │
│ │ │ dnsPolicy │ ClusterFirst │ │
│ │ │ enableServiceLinks │ true │ │
│ │ │ hostNetwork │ true │ │
│ │ │ nodeName │ kind-control-plane │ │
│ │ │ preemptionPolicy │ PreemptLowerPriority │ │
│ │ │ priority │ 2000001000 │ │
│ │ │ priorityClassName │ system-node-critical │ │
│ │ │ restartPolicy │ Always │ │
│ │ │ schedulerName │ default-scheduler │ │
│ │ │ │ ╭────────────────┬───────────────────────────╮ │ │
│ │ │ securityContext │ │ │ ╭──────┬────────────────╮ │ │ │
│ │ │ │ │ seccompProfile │ │ type │ RuntimeDefault │ │ │ │
│ │ │ │ │ │ ╰──────┴────────────────╯ │ │ │
│ │ │ │ ╰────────────────┴───────────────────────────╯ │ │
│ │ │ terminationGracePeriodSeconds │ 30 │ │
│ │ │ │ ╭───┬───────────┬──────────╮ │ │
│ │ │ tolerations │ │ # │ effect │ operator │ │ │
│ │ │ │ ├───┼───────────┼──────────┤ │ │
│ │ │ │ │ 0 │ NoExecute │ Exists │ │ │
│ │ │ │ ╰───┴───────────┴──────────╯ │ │
│ │ │ │ ╭───┬───────────────────────────────────────────┬────────────╮ │ │
│ │ │ volumes │ │ # │ hostPath │ name │ │ │
│ │ │ │ ├───┼───────────────────────────────────────────┼────────────┤ │ │
│ │ │ │ │ 0 │ ╭──────┬────────────────────────────────╮ │ kubeconfig │ │ │
│ │ │ │ │ │ │ path │ /etc/kubernetes/scheduler.conf │ │ │ │ │
│ │ │ │ │ │ │ type │ FileOrCreate │ │ │ │ │
│ │ │ │ │ │ ╰──────┴────────────────────────────────╯ │ │ │ │
│ │ │ │ ╰───┴───────────────────────────────────────────┴────────────╯ │ │
│ │ ╰───────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │ ╭───────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ status │ │ │ ╭───┬───────────────┬──────────────────────┬────────┬───────────────────────────╮ │ │
│ │ │ conditions │ │ # │ lastProbeTime │ lastTransitionTime │ status │ type │ │ │
│ │ │ │ ├───┼───────────────┼──────────────────────┼────────┼───────────────────────────┤ │ │
│ │ │ │ │ 0 │ │ 2025-02-10T19:50:32Z │ True │ PodReadyToStartContainers │ │ │
│ │ │ │ │ 1 │ │ 2025-02-10T19:50:32Z │ True │ Initialized │ │ │
│ │ │ │ │ 2 │ │ 2025-02-10T19:50:45Z │ True │ Ready │ │ │
│ │ │ │ │ 3 │ │ 2025-02-10T19:50:45Z │ True │ ContainersReady │ │ │
│ │ │ │ │ 4 │ │ 2025-02-10T19:50:32Z │ True │ PodScheduled │ │ │
│ │ │ │ ╰───┴───────────────┴──────────────────────┴────────┴───────────────────────────╯ │ │
│ │ │ │ ╭───┬───────────────────────────────────────────────────────────────────────────────┬──────────────────────────────┬─────╮ │ │
│ │ │ containerStatuses │ │ # │ containerID │ image │ ... │ │ │
│ │ │ │ ├───┼───────────────────────────────────────────────────────────────────────────────┼──────────────────────────────┼─────┤ │ │
│ │ │ │ │ 0 │ containerd://ed754765bd1040b8435023f4a3af8c3ace6ebd16ea225e91e019b811fdd8f031 │ registry.k8s.io/kube-schedul │ ... │ │ │
│ │ │ │ │ │ │ er-arm64:v1.32.0 │ │ │ │
│ │ │ │ ╰───┴───────────────────────────────────────────────────────────────────────────────┴──────────────────────────────┴─────╯ │ │
│ │ │ hostIP │ 10.89.0.2 │ │
│ │ │ │ ╭───┬───────────╮ │ │
│ │ │ hostIPs │ │ # │ ip │ │ │
│ │ │ │ ├───┼───────────┤ │ │
│ │ │ │ │ 0 │ 10.89.0.2 │ │ │
│ │ │ │ ╰───┴───────────╯ │ │
│ │ │ phase │ Running │ │
│ │ │ podIP │ 10.89.0.2 │ │
│ │ │ │ ╭───┬───────────╮ │ │
│ │ │ podIPs │ │ # │ ip │ │ │
│ │ │ │ ├───┼───────────┤ │ │
│ │ │ │ │ 0 │ 10.89.0.2 │ │ │
│ │ │ │ ╰───┴───────────╯ │ │
│ │ │ qosClass │ Burstable │ │
│ │ │ startTime │ 2025-02-10T19:50:32Z │ │
│ │ ╰───────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯