Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
devel:kubic
kubectl-images
kubectl-images-0.6.3.obscpio
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File kubectl-images-0.6.3.obscpio of Package kubectl-images
07070100000000000041ED0000000000000000000000026489DE6B00000000000000000000000000000000000000000000001D00000000kubectl-images-0.6.3/.github07070100000001000041ED0000000000000000000000026489DE6B00000000000000000000000000000000000000000000002700000000kubectl-images-0.6.3/.github/workflows07070100000002000081A40000000000000000000000016489DE6B00000242000000000000000000000000000000000000003300000000kubectl-images-0.6.3/.github/workflows/release.ymlname: release on: push: tags: - 'v*.*.*' jobs: goreleaser: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@master - name: Setup Go uses: actions/setup-go@v1 with: go-version: 1.16 - name: GoReleaser uses: goreleaser/goreleaser-action@v1 with: version: latest args: release --rm-dist env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update new version in krew-index uses: rajatjindal/krew-release-bot@v0.0.39 07070100000003000081A40000000000000000000000016489DE6B000000EC000000000000000000000000000000000000002000000000kubectl-images-0.6.3/.gitignore# Binaries for programs and plugins *.exe *.exe~ *.dll *.so *.dylib # Test binary, built with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out # IDE .idea/ .vscode/ .DS_Store releases/ 07070100000004000081A40000000000000000000000016489DE6B00000216000000000000000000000000000000000000002500000000kubectl-images-0.6.3/.goreleaser.ymlbuilds: - id: kubectl-images main: ./cmd binary: kubectl-images env: - CGO_ENABLED=0 goos: - darwin - linux - windows goarch: - amd64 - arm64 - arm ignore: - goos: windows goarch: arm - goos: windows goarch: arm64 - goos: darwin goarch: arm archives: - builds: - kubectl-images name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" wrap_in_directory: false format: tar.gz files: - LICENSE 07070100000005000081A40000000000000000000000016489DE6B0000099E000000000000000000000000000000000000002000000000kubectl-images-0.6.3/.krew.yamlapiVersion: krew.googlecontainertools.github.com/v1alpha2 kind: Plugin metadata: name: images spec: version: {{ .TagName }} homepage: https://github.com/chenjiandongx/kubectl-images shortDescription: Show container images used in the cluster. description: | This plugin shows container images used in the Kubernetes cluster in a table view. You can show all images or show images used in a specified namespace. platforms: - selector: matchLabels: os: darwin arch: amd64 files: - from: kubectl-images to: . - from: LICENSE to: . {{ addURIAndSha "https://github.com/chenjiandongx/kubectl-images/releases/download/{{ .TagName }}/kubectl-images_darwin_amd64.tar.gz" .TagName }} bin: kubectl-images - selector: matchLabels: os: darwin arch: arm64 files: - from: kubectl-images to: . - from: LICENSE to: . {{ addURIAndSha "https://github.com/chenjiandongx/kubectl-images/releases/download/{{ .TagName }}/kubectl-images_darwin_arm64.tar.gz" .TagName }} bin: kubectl-images - selector: matchLabels: os: linux arch: amd64 files: - from: kubectl-images to: . - from: LICENSE to: . {{ addURIAndSha "https://github.com/chenjiandongx/kubectl-images/releases/download/{{ .TagName }}/kubectl-images_linux_amd64.tar.gz" .TagName }} bin: kubectl-images - selector: matchLabels: os: linux arch: arm64 files: - from: kubectl-images to: . - from: LICENSE to: . {{ addURIAndSha "https://github.com/chenjiandongx/kubectl-images/releases/download/{{ .TagName }}/kubectl-images_linux_arm64.tar.gz" .TagName }} bin: kubectl-images - selector: matchLabels: os: linux arch: arm files: - from: kubectl-images to: . - from: LICENSE to: . {{ addURIAndSha "https://github.com/chenjiandongx/kubectl-images/releases/download/{{ .TagName }}/kubectl-images_linux_arm.tar.gz" .TagName }} bin: kubectl-images - selector: matchLabels: os: windows arch: amd64 files: - from: kubectl-images.exe to: . - from: LICENSE to: . {{ addURIAndSha "https://github.com/chenjiandongx/kubectl-images/releases/download/{{ .TagName }}/kubectl-images_windows_amd64.tar.gz" .TagName }} bin: kubectl-images.exe 07070100000006000081A40000000000000000000000016489DE6B00000432000000000000000000000000000000000000001D00000000kubectl-images-0.6.3/LICENSEMIT License Copyright (c) 2020~now chenjiandongx Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 07070100000007000081A40000000000000000000000016489DE6B00001FC4000000000000000000000000000000000000001F00000000kubectl-images-0.6.3/README.md<h1 align="center">kubectl-images</h1> <p align="center"> <em>๐ธ Show container images used in the cluster.</em> </p> kubectl-images makes use of the `kubectl` command. It first calls `kubectl get pods` to retrieve pods details and filters out the container image information of each pod, then prints out the final result in a table/json/yaml view. ### ๐ฐ Installation Krew ```shell $ kubectl krew install images Updated the local copy of plugin index. Installing plugin: images Installed plugin: images \ | Use this plugin: | kubectl images | Documentation: | https://github.com/chenjiandongx/kubectl-images / ``` Build from source code ```shell $ git clone https://github.com/chenjiandongx/kubectl-images.git $ cd kubectl-images && go build -ldflags="-s -w" -o kubectl-images . && mv ./kubectl-images /usr/local/bin $ kubectl images --help ``` Download the binary ```shell # Refer to the link: https://github.com/chenjiandongx/kubectl-images/releases # Download the binary and then... $ chmod +x kubectl-images && mv kubectl-images /usr/local/bin/ $ kubectl images --help ``` ### ๐ Usage ```shell ~ ๐ถ kubectl images --help Show container images used in the cluster. Usage: kubectl-images [podname-regex] [flags] Examples: # display a table of all images in current namespace using podName/containerName/containerImage as columns. kubectl images # display images info in yaml format kubectl images -oy # display a table of images that match 'nginx' podname regex in 'dev' namespace using podName/containerImage as columns. kubectl images -n dev nginx -c 1,2 Flags: -A, --all-namespaces if present, list images in all namespaces. -c, --columns string specify the columns to display, separated by comma. [0:Namespace, 1:PodName, 2:ContainerName, 3:ContainerImage, 4:ImagePullPolicy, 5:ImageSize] (default "1,2,3") -C, --context string The name of the kubeconfig context to use. -h, --help help for kubectl-images -k, --kubeconfig string path to the kubeconfig file to use for CLI requests. -n, --namespace string if present, list images in the specified namespace only. Use current namespace as fallback. -o, --output-format string output format. [json(j)|table(t)|yaml(y)] (default "table") -u, --unique Unique images group by namespace/container/images/pullPolicy. --version version for kubectl-images ``` ### ๐ Glances ```shell ~ ๐ถ kubectl images -n kube-system -oy dns - pod: coredns-78fcd69978-9pbjh container: coredns image: k8s.gcr.io/coredns/coredns:v1.8.4 - pod: coredns-78fcd69978-jh7m2 container: coredns image: k8s.gcr.io/coredns/coredns:v1.8.4 ~ ๐ถ kubectl images -A -c 0,1,3 [Summary]: 2 namespaces, 11 pods, 11 containers and 9 different images +-------------+----------------------------------------+--------------------------------------------+ | Namespace | Pod | Image | +-------------+----------------------------------------+--------------------------------------------+ | kube-system | coredns-78fcd69978-9pbjh | k8s.gcr.io/coredns/coredns:v1.8.4 | + +----------------------------------------+ + | | coredns-78fcd69978-jh7m2 | | + +----------------------------------------+--------------------------------------------+ | | etcd-docker-desktop | k8s.gcr.io/etcd:3.5.0-0 | + +----------------------------------------+--------------------------------------------+ | | kube-apiserver-docker-desktop | k8s.gcr.io/kube-apiserver:v1.22.5 | + +----------------------------------------+--------------------------------------------+ | | kube-controller-manager-docker-desktop | k8s.gcr.io/kube-controller-manager:v1.22.5 | + +----------------------------------------+--------------------------------------------+ | | kube-proxy-vc7fv | k8s.gcr.io/kube-proxy:v1.22.5 | + +----------------------------------------+--------------------------------------------+ | | kube-scheduler-docker-desktop | k8s.gcr.io/kube-scheduler:v1.22.5 | + +----------------------------------------+--------------------------------------------+ | | storage-provisioner | docker/desktop-storage-provisioner:v2.0 | + +----------------------------------------+--------------------------------------------+ | | vpnkit-controller | docker/desktop-vpnkit-controller:v2.0 | +-------------+----------------------------------------+--------------------------------------------+ | nginx | nginx-deployment-66b6c48dd5-s9wv5 | nginx:1.14.2 | + +----------------------------------------+ + | | nginx-deployment-66b6c48dd5-wmn9x | | +-------------+----------------------------------------+--------------------------------------------+ ~ ๐ถ kubectl images -A -c 0,1,3 -u [Summary]: 2 namespaces, 11 pods, 11 containers and 9 different images +-------------+----------------------------------------+--------------------------------------------+ | Namespace | Pod | Image | +-------------+----------------------------------------+--------------------------------------------+ | kube-system | coredns-78fcd69978-9pbjh | k8s.gcr.io/coredns/coredns:v1.8.4 | + + +----------------------------------------+--------------------------------------------+ | | etcd-docker-desktop | k8s.gcr.io/etcd:3.5.0-0 | + +----------------------------------------+--------------------------------------------+ | | kube-apiserver-docker-desktop | k8s.gcr.io/kube-apiserver:v1.22.5 | + +----------------------------------------+--------------------------------------------+ | | kube-controller-manager-docker-desktop | k8s.gcr.io/kube-controller-manager:v1.22.5 | + +----------------------------------------+--------------------------------------------+ | | kube-proxy-vc7fv | k8s.gcr.io/kube-proxy:v1.22.5 | + +----------------------------------------+--------------------------------------------+ | | kube-scheduler-docker-desktop | k8s.gcr.io/kube-scheduler:v1.22.5 | + +----------------------------------------+--------------------------------------------+ | | storage-provisioner | docker/desktop-storage-provisioner:v2.0 | + +----------------------------------------+--------------------------------------------+ | | vpnkit-controller | docker/desktop-vpnkit-controller:v2.0 | +-------------+----------------------------------------+--------------------------------------------+ | nginx | nginx-deployment-66b6c48dd5-s9wv5 | nginx:1.14.2 | +-------------+----------------------------------------+--------------------------------------------+ ~ ๐ถ kubectl images -c 0,1,2,3,4 -n nginx -oj [ { "namespace": "nginx", "pod": "nginx-deployment-66b6c48dd5-s9wv5", "container": "nginx", "image": "nginx:latest", "imagePullPolicy": "IfNotPresent" }, { "namespace": "nginx", "pod": "nginx-deployment-66b6c48dd5-wmn9x", "container": "nginx", "image": "nginx:latest", "imagePullPolicy": "IfNotPresent" } ] ``` ### ๐ License MIT [ยฉchenjiandongx](https://github.com/chenjiandongx) 07070100000008000041ED0000000000000000000000026489DE6B00000000000000000000000000000000000000000000001900000000kubectl-images-0.6.3/cmd07070100000009000081A40000000000000000000000016489DE6B00000A2D000000000000000000000000000000000000002100000000kubectl-images-0.6.3/cmd/main.gopackage main import ( "fmt" "os" "regexp" kubeimages "github.com/chenjiandongx/kubectl-images" "github.com/spf13/cobra" ) const version = "0.6.3" var rootCmd *cobra.Command func init() { rootCmd = &cobra.Command{ Use: "kubectl-images [podname-regex]", Short: "Show container images used in the cluster.", Example: ` # display a table of all images in current namespace using podName/containerName/containerImage as columns. kubectl images # display images info in yaml format kubectl images -oy # display a table of images that match 'nginx' podname regex in 'dev' namespace using podName/containerImage as columns. kubectl images -n dev nginx -c 1,2`, Version: version, Run: func(cmd *cobra.Command, args []string) { var regx *regexp.Regexp var err error if len(args) > 0 { if regx, err = regexp.Compile(args[0]); err != nil { fmt.Fprintf(os.Stderr, "[Oh...] Invalid regex pattern (%q)", args[0]) return } } namespace, _ := cmd.Flags().GetString("namespace") columns, _ := cmd.Flags().GetString("columns") format, _ := cmd.Flags().GetString("output-format") allNamespace, _ := cmd.Flags().GetBool("all-namespaces") kubeConfig, _ := cmd.Flags().GetString("kubeConfig") context, _ := cmd.Flags().GetString("context") unique, _ := cmd.Flags().GetBool("unique") kubeImage := kubeimages.NewKubeImage(regx, kubeimages.Parameters{ AllNamespace: allNamespace, Namespace: namespace, Columns: columns, KubeConfig: kubeConfig, Context: context, Unique: unique, }) kubeImage.Render(format) }, } rootCmd.Flags().BoolP("all-namespaces", "A", false, "if present, list images in all namespaces.") rootCmd.Flags().StringP("namespace", "n", "", "if present, list images in the specified namespace only. Use current namespace as fallback.") rootCmd.Flags().StringP("columns", "c", "1,2,3", "specify the columns to display, separated by comma. [0:Namespace, 1:PodName, 2:ContainerName, 3:ContainerImage, 4:ImagePullPolicy, 5:ImageSize]") rootCmd.Flags().StringP("kubeconfig", "k", "", "path to the kubeconfig file to use for CLI requests.") rootCmd.Flags().StringP("output-format", "o", "table", "output format. [json(j)|table(t)|yaml(y)]") rootCmd.Flags().StringP("context", "C", "", "The name of the kubeconfig context to use.") rootCmd.Flags().BoolP("unique", "u", false, "Unique images group by namespace/container/images/pullPolicy.") } func main() { if err := rootCmd.Execute(); err != nil { fmt.Fprintf(os.Stderr, "[Oh...] Failed to exec command: %v", err) } } 0707010000000A000081A40000000000000000000000016489DE6B00000170000000000000000000000000000000000000001C00000000kubectl-images-0.6.3/go.modmodule github.com/chenjiandongx/kubectl-images go 1.18 require ( github.com/dustin/go-humanize v1.0.1 github.com/olekukonko/tablewriter v0.0.4 github.com/spf13/cobra v0.0.5 gopkg.in/yaml.v2 v2.2.8 ) require ( github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/mattn/go-runewidth v0.0.7 // indirect github.com/spf13/pflag v1.0.3 // indirect ) 0707010000000B000081A40000000000000000000000016489DE6B00000F36000000000000000000000000000000000000001C00000000kubectl-images-0.6.3/go.sumgithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 0707010000000C000081A40000000000000000000000016489DE6B000028F7000000000000000000000000000000000000002700000000kubectl-images-0.6.3/kubectl_images.gopackage kubeimage import ( "encoding/json" "fmt" "os" "os/exec" "path" "regexp" "strconv" "strings" "github.com/dustin/go-humanize" "github.com/olekukonko/tablewriter" "gopkg.in/yaml.v2" ) const ( podTemplate = `go-template={{range .items}} {{.metadata.namespace}} {{","}} {{.metadata.name}} {{","}} {{range .spec.containers}} {{.name}} {{","}} {{.image}} {{","}} {{.imagePullPolicy}} {{"\n"}} {{end}} {{range .spec.initContainers}} {{"(init)"}} {{.name}} {{","}} {{.image}} {{","}} {{.imagePullPolicy}} {{"\n"}} {{end}} {{end}}` nodeTemplate = `go-template={{range .items}} {{range .status.images}} {{range .names}} {{.}} {{","}} {{end}} {{.sizeBytes}} {{"\n"}} {{end}} {{end}}` labelNamespace = "Namespace" labelPod = "Pod" labelContainer = "Container" labelImage = "Image" labelImagePullPolicy = "ImagePullPolicy" labelImageSize = "ImageSize" ) type Parameters struct { AllNamespace bool Namespace string Columns string KubeConfig string Context string Unique bool } // KubeImage is the representation of a container image used in the cluster. type KubeImage struct { entities []*ImageEntity columns []string regx *regexp.Regexp params Parameters imageSize map[string]int needNodeInfo bool } // NewKubeImage creates a new KubeImage instance. func NewKubeImage(regx *regexp.Regexp, params Parameters) *KubeImage { var needNodeInfo bool names := make([]string, 0) for _, c := range stringSplit(params.Columns, ",") { switch c { case "0": names = append(names, labelNamespace) case "1": names = append(names, labelPod) case "2": names = append(names, labelContainer) case "3": names = append(names, labelImage) case "4": names = append(names, labelImagePullPolicy) case "5": names = append(names, labelImageSize) needNodeInfo = true } } return &KubeImage{ columns: names, params: params, regx: regx, imageSize: make(map[string]int), needNodeInfo: needNodeInfo, } } // ImageEntity is the representation of an entity to be displayed. type ImageEntity struct { Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` Pod string `json:"pod,omitempty" yaml:"pod,omitempty"` Container string `json:"container,omitempty" yaml:"container,omitempty"` Image string `json:"image,omitempty" yaml:"image,omitempty"` ImagePullPolicy string `json:"imagePullPolicy,omitempty" yaml:"imagePullPolicy,omitempty"` ImageSize string `json:"imageSize,omitempty" yaml:"imageSize,omitempty"` } func (ie *ImageEntity) selectBy(columns []string) []string { result := make([]string, 0) for _, c := range columns { switch c { case labelNamespace: result = append(result, ie.Namespace) case labelPod: result = append(result, ie.Pod) case labelContainer: result = append(result, ie.Container) case labelImage: result = append(result, ie.Image) case labelImagePullPolicy: result = append(result, ie.ImagePullPolicy) case labelImageSize: result = append(result, ie.ImageSize) } } return result } func (ie *ImageEntity) filterBy(columns []string) ImageEntity { var entity ImageEntity for _, c := range columns { switch c { case labelNamespace: entity.Namespace = ie.Namespace case labelPod: entity.Pod = ie.Pod case labelContainer: entity.Container = ie.Container case labelImage: entity.Image = ie.Image case labelImagePullPolicy: entity.ImagePullPolicy = ie.ImagePullPolicy case labelImageSize: entity.ImageSize = ie.ImageSize } } return entity } // Counter is a simple counter. type Counter struct { cnt int items map[string]bool } // NewCounter creates a new Counter instance. func NewCounter() *Counter { return &Counter{items: make(map[string]bool)} } func (c *Counter) add(obj string) { if !c.items[obj] { c.cnt += 1 c.items[obj] = true } } // Count returns current counter reading. func (c *Counter) Count() int { return c.cnt } func stringSplit(in, sep string) []string { out := make([]string, 0) for _, s := range strings.Split(in, sep) { out = append(out, strings.TrimSpace(s)) } return out } // podCommands builds the command to be executed based on user input. func (ki *KubeImage) podCommands() []string { kubecfg := make([]string, 0) if ki.params.KubeConfig != "" { kubecfg = append(kubecfg, "--kubeconfig", ki.params.KubeConfig) } if ki.params.Context != "" { kubecfg = append(kubecfg, "--context", ki.params.Context) } if ki.params.AllNamespace { return append([]string{"get", "pods", "--all-namespaces", "-o", podTemplate}, kubecfg...) } else if ki.params.Namespace != "" { return append([]string{"get", "pods", "-n", ki.params.Namespace, "-o", podTemplate}, kubecfg...) } return append([]string{"get", "pods", "-o", podTemplate}, kubecfg...) } func (ki *KubeImage) nodeCommands() []string { kubecfg := make([]string, 0) if ki.params.KubeConfig != "" { kubecfg = append(kubecfg, "--kubeconfig", ki.params.KubeConfig) } if ki.params.Context != "" { kubecfg = append(kubecfg, "--context", ki.params.Context) } return append([]string{"get", "nodes", "-o", nodeTemplate}, kubecfg...) } func (ki *KubeImage) recordImageSize(image string, size int) { ki.imageSize[image] = size ki.imageSize[path.Base(image)] = size } func (ki *KubeImage) execNodeCommand() { process := exec.Command("kubectl", ki.nodeCommands()...) bs, err := process.CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "[Oh...] Execute nodes command error: %v, %s", err, string(bs)) os.Exit(1) } for _, line := range stringSplit(string(bs), "\n") { items := stringSplit(line, ",") switch len(items) { case 2: size, err := strconv.Atoi(items[1]) if err != nil { continue } ki.recordImageSize(items[0], size) parts := strings.Split(items[0], ":") if len(parts) == 2 && parts[1] == "latest" { ki.recordImageSize(parts[0], size) } case 3: size, err := strconv.Atoi(items[2]) if err != nil { continue } ki.recordImageSize(items[0], size) ki.recordImageSize(items[1], size) parts := strings.Split(items[1], ":") if len(parts) == 2 && parts[1] == "latest" { ki.recordImageSize(parts[0], size) } } } for _, entity := range ki.entities { size, ok := ki.imageSize[entity.Image] if ok { entity.ImageSize = humanize.IBytes(uint64(size)) } } } func (ki *KubeImage) execPodCommand() { process := exec.Command("kubectl", ki.podCommands()...) bs, err := process.CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "[Oh...] Execute pods command error: %v, %s", err, string(bs)) os.Exit(1) } entities := make([]*ImageEntity, 0) for _, line := range stringSplit(string(bs), "\n") { items := stringSplit(line, ",") entity := &ImageEntity{} switch len(items) { case 1: continue case 3: entity.Container = items[0] entity.Image = items[1] entity.ImagePullPolicy = items[2] case 5: entity.Namespace = items[0] entity.Pod = items[1] entity.Container = items[2] entity.Image = items[3] entity.ImagePullPolicy = items[4] } entities = append(entities, entity) } for i := 0; i < len(entities); i++ { if entities[i].Pod == "" && i > 0 { entities[i].Namespace = entities[i-1].Namespace entities[i].Pod = entities[i-1].Pod } } for i := 0; i < len(entities); i++ { if ki.regx == nil { ki.entities = append(ki.entities, entities[i]) continue } if ki.regx.Match([]byte(entities[i].Pod)) { ki.entities = append(ki.entities, entities[i]) } } } func (ki *KubeImage) groupBy() []*ImageEntity { if !ki.params.Unique { return ki.entities } set := make(map[string]struct{}) entities := make([]*ImageEntity, 0) for i, entity := range ki.entities { k := fmt.Sprintf("%s/%s/%s/%s", entity.Namespace, entity.Container, entity.Image, entity.ImagePullPolicy) if _, ok := set[k]; ok { continue } set[k] = struct{}{} entities = append(entities, ki.entities[i]) } return entities } func (ki *KubeImage) summary() { namespaceCnt := NewCounter() podCnt := NewCounter() imageCnt := NewCounter() containerCnt := 0 for i := 0; i < len(ki.entities); i++ { namespaceCnt.add(ki.entities[i].Namespace) podCnt.add(ki.entities[i].Pod) imageCnt.add(ki.entities[i].Image) containerCnt += 1 } fmt.Fprintf(os.Stdout, "[Summary]: %d namespaces, %d pods, %d containers and %d different images\n", namespaceCnt.Count(), podCnt.Count(), containerCnt, imageCnt.Count(), ) } func (ki *KubeImage) tableRender() { table := tablewriter.NewWriter(os.Stdout) table.SetHeader(ki.columns) table.SetAutoFormatHeaders(false) table.SetAutoMergeCells(true) table.SetRowLine(true) entities := ki.getGroupByEntities() for _, entity := range entities { table.Append(entity) } table.Render() } func (ki *KubeImage) getGroupByEntities() [][]string { set := make(map[string]struct{}) dst := make([][]string, 0) for _, entity := range ki.groupBy() { line := strings.Join(entity.selectBy(ki.columns), "||") _, ok := set[line] if !ok { set[line] = struct{}{} dst = append(dst, strings.Split(line, "||")) } } return dst } func (ki *KubeImage) jsonRender() { entities := ki.groupBy() records := make([]ImageEntity, 0, len(entities)) for _, entity := range entities { records = append(records, entity.filterBy(ki.columns)) } output, err := json.MarshalIndent(records, "", " ") if err != nil { fmt.Fprintf(os.Stderr, "[Oh...] Failed to marshal JSON data, error: %v", err) os.Exit(1) } fmt.Fprintln(os.Stdout, string(output)) } func (ki *KubeImage) yamlRender() { entities := ki.groupBy() records := make([]ImageEntity, 0, len(entities)) for _, entity := range entities { records = append(records, entity.filterBy(ki.columns)) } output, err := yaml.Marshal(records) if err != nil { fmt.Fprintf(os.Stderr, "[Oh...] Failed to marshal YAML data, error: %v", err) os.Exit(1) } fmt.Fprintln(os.Stdout, string(output)) } // Render renders and displays the table output. func (ki *KubeImage) Render(format string) { ki.execPodCommand() if ki.needNodeInfo { ki.execNodeCommand() } if len(ki.entities) == 0 { fmt.Fprintln(os.Stdout, "[Oh...] No images matched!") return } switch format { case "json", "j": ki.jsonRender() case "yaml", "y": ki.yamlRender() default: // table ki.summary() ki.tableRender() } } 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!64 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor