diff --git a/.github/workflows/docker-push.yml b/.github/workflows/docker-push.yml index e2e995a4..baa0f425 100644 --- a/.github/workflows/docker-push.yml +++ b/.github/workflows/docker-push.yml @@ -19,6 +19,7 @@ permissions: env: IMAGE_NAME: ${{ github.repository }} + LATEST_IMAGE: ol8 jobs: Docker: @@ -82,13 +83,25 @@ jobs: exit 1 fi + dh_tags="${{env.IMAGE_NAME}}:${{matrix.image}}-$version,${{env.IMAGE_NAME}}:${{matrix.image}}" + gh_tags="ghcr.io/${{env.IMAGE_NAME}}:${{matrix.image}}-$version,ghcr.io/${{env.IMAGE_NAME}}:${{matrix.image}}" + + if [[ -n "${{env.LATEST_IMAGE}}" && "${{env.LATEST_IMAGE}}" == "${{matrix.image}}" ]] ; then + dh_tags="$dh_tags,${{env.IMAGE_NAME}}:latest" + gh_tags="$gh_tags,ghcr.io/${{env.IMAGE_NAME}}:latest" + fi + echo "version=$version" >> $GITHUB_OUTPUT echo "dockerfile=$docker_file" >> $GITHUB_OUTPUT echo "baseimage=$base_image" >> $GITHUB_OUTPUT + echo "dh_tags=$dh_tags" >> $GITHUB_OUTPUT + echo "gh_tags=$gh_tags" >> $GITHUB_OUTPUT echo -e "\033[34mVersion:\033[0m $version" echo -e "\033[34mDockerfile:\033[0m $docker_file" echo -e "\033[34mBase image:\033[0m $base_image" + echo -e "\033[34mDH Tags:\033[0m $dh_tags" + echo -e "\033[34mGHCR Tags:\033[0m $gh_tags" - name: Check if build/rebuild is required id: build_check @@ -143,9 +156,7 @@ jobs: file: ${{steps.metadata.outputs.dockerfile}} build-args: | REGISTRY=docker.io - tags: | - ${{env.IMAGE_NAME}}:${{matrix.image}}-${{steps.metadata.outputs.version}} - ${{env.IMAGE_NAME}}:${{matrix.image}} + tags: ${{steps.metadata.outputs.dh_tags}} - name: Build and push Docker images (GHCR) if: ${{ steps.build_check.outputs.build == 'true' }} @@ -156,9 +167,7 @@ jobs: file: ${{steps.metadata.outputs.dockerfile}} build-args: | REGISTRY=ghcr.io - tags: | - ghcr.io/${{env.IMAGE_NAME}}:${{matrix.image}}-${{steps.metadata.outputs.version}} - ghcr.io/${{env.IMAGE_NAME}}:${{matrix.image}} + tags: ${{steps.metadata.outputs.gh_tags}} - name: Show info about built Docker image if: ${{ steps.build_check.outputs.build == 'true' }} diff --git a/cli/cli.go b/cli/cli.go index f081de5e..81a80715 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -38,7 +38,7 @@ import ( // Application info const ( APP = "bibop" - VER = "6.0.3" + VER = "6.1.0" DESC = "Utility for testing command-line tools" ) diff --git a/cli/executor/validators.go b/cli/executor/validators.go index 3e9ec41b..959dcbde 100644 --- a/cli/executor/validators.go +++ b/cli/executor/validators.go @@ -8,11 +8,13 @@ package executor // ////////////////////////////////////////////////////////////////////////////////// // import ( + "errors" "fmt" "os/exec" "regexp" "strings" + "github.com/essentialkaos/ek/v12/env" "github.com/essentialkaos/ek/v12/fsutil" "github.com/essentialkaos/ek/v12/sliceutil" "github.com/essentialkaos/ek/v12/strutil" @@ -125,18 +127,14 @@ func checkPackages(r *recipe.Recipe) []error { return nil } - systemInfo, err := system.GetSystemInfo() - - if err != nil { - return []error{err} - } - - switch systemInfo.Distribution { - case system.LINUX_CENTOS, system.LINUX_RHEL, system.LINUX_FEDORA: + switch { + case env.Which("rpm") != "": return checkRPMPackages(r.Packages) - default: - return nil + case env.Which("dpkg") != "": + return checkDEBPackages(r.Packages) } + + return []error{errors.New("Can't check required packages availability: Unsupported OS")} } // getDynamicVars returns slice with dynamic vars @@ -184,3 +182,23 @@ func checkRPMPackages(pkgs []string) []error { return errs } + +// checkDEBPackages checks if deb packages are installed +func checkDEBPackages(pkgs []string) []error { + cmd := exec.Command("dpkg-query", "-l") + cmd.Env = []string{"LC_ALL=C"} + cmd.Args = append(cmd.Args, pkgs...) + + output, _ := cmd.Output() + + var errs []error + + for _, pkgInfo := range strings.Split(string(output), "\n") { + if strings.Contains(pkgInfo, "no packages found") { + pkgName := strutil.Exclude(pkgInfo, "dpkg-query: no packages found matching ") + errs = append(errs, fmt.Errorf("Package %s is not installed", pkgName)) + } + } + + return errs +} diff --git a/go.mod b/go.mod index 5ec7079a..2afdf575 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/buger/jsonparser v1.1.1 github.com/essentialkaos/check v1.3.0 github.com/essentialkaos/depsy v1.0.0 - github.com/essentialkaos/ek/v12 v12.57.0 + github.com/essentialkaos/ek/v12 v12.57.1 github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 ) @@ -14,6 +14,6 @@ require ( github.com/kr/pretty v0.3.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/rogpeppe/go-internal v1.8.1 // indirect - golang.org/x/crypto v0.3.0 // indirect - golang.org/x/sys v0.2.0 // indirect + golang.org/x/crypto v0.5.0 // indirect + golang.org/x/sys v0.4.0 // indirect ) diff --git a/go.sum b/go.sum index 9da5c57a..affc69bc 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ github.com/essentialkaos/check v1.3.0 h1:ria+8o22RCLdt2D/1SHQsEH5Mmy5S+iWHaGHrrb github.com/essentialkaos/check v1.3.0/go.mod h1:PhxzfJWlf5L/skuyhzBLIvjMB5Xu9TIyDIsqpY5MvB8= github.com/essentialkaos/depsy v1.0.0 h1:FikBtTnNhk+xFO/hFr+CfiKs6QnA3wMD6tGL0XTEUkc= github.com/essentialkaos/depsy v1.0.0/go.mod h1:XVsB2eVUonEzmLKQP3ig2P6v2+WcHVgJ10zm0JLqFMM= -github.com/essentialkaos/ek/v12 v12.57.0 h1:FUl5ZUF7czjZXROYVoJamGTWqEIGuZEHrm1DLfzq43I= -github.com/essentialkaos/ek/v12 v12.57.0/go.mod h1:G8ghiSKh8ToJQCdB2bAhE3CnI6dn9nTJdWH3bQIVr1U= +github.com/essentialkaos/ek/v12 v12.57.1 h1:9dj32HLCVmseBoa43F6HaZz1qbKts5GNBCtFdrpQPno= +github.com/essentialkaos/ek/v12 v12.57.1/go.mod h1:G8ghiSKh8ToJQCdB2bAhE3CnI6dn9nTJdWH3bQIVr1U= github.com/essentialkaos/go-linenoise/v3 v3.4.0/go.mod h1:t1kNLY2bSMQCy1JXOefD2BDLs/TTPMtTv3DFNV5uDSI= github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 h1:CVuJwN34x4xM2aT4sIKhmeib40NeBPhRihNjQmpJsA4= github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4= @@ -25,14 +25,14 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -42,16 +42,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/scripts/bibop-dep b/scripts/bibop-dep index 907e09b0..c6f329c2 100644 --- a/scripts/bibop-dep +++ b/scripts/bibop-dep @@ -356,7 +356,6 @@ fi if [[ $# -eq 0 ]] ; then main - exit $? fi unset opt optn optm optv optt optk diff --git a/scripts/bibop-docker b/scripts/bibop-docker index bf63acc2..085aef4b 100755 --- a/scripts/bibop-docker +++ b/scripts/bibop-docker @@ -170,7 +170,6 @@ showOptWarn() { if [[ $# -eq 0 ]] ; then main - exit $? fi unset opt optn optm optv optt optk diff --git a/scripts/bibop-entrypoint b/scripts/bibop-entrypoint index f77048f0..0eeb7858 100755 --- a/scripts/bibop-entrypoint +++ b/scripts/bibop-entrypoint @@ -79,7 +79,6 @@ showOptWarn() { if [[ $# -eq 0 ]] ; then main - exit $? fi unset opt optn optm optv optt optk diff --git a/support/support.go b/support/support.go index cfb0ffe7..f36aeeb1 100644 --- a/support/support.go +++ b/support/support.go @@ -9,7 +9,6 @@ package support import ( "os" - "os/exec" "runtime" "strings" @@ -23,7 +22,7 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // -// Pkg contains simple package info +// Pkg contains basic package info type Pkg struct { Name string Version string @@ -34,14 +33,14 @@ type Pkg struct { // ShowSupportInfo prints verbose info about application, system, dependencies and // important environment func ShowSupportInfo(app, ver, gitRev string, gomod []byte) { - pkgs := collectPackagesInfo() + pkgs := collectEnvInfo() fmtutil.SeparatorTitleColorTag = "{*}" fmtutil.SeparatorFullscreen = false showApplicationInfo(app, ver, gitRev) showOSInfo() - showEnvironmentInfo(pkgs) + showEnvInfo(pkgs) showDepsInfo(gomod) fmtutil.Separator(false) } @@ -52,20 +51,20 @@ func ShowSupportInfo(app, ver, gitRev string, gomod []byte) { func showApplicationInfo(app, ver, gitRev string) { fmtutil.Separator(false, "APPLICATION INFO") - fmtc.Printf(" {*}%-12s{!} %s\n", "Name:", app) - fmtc.Printf(" {*}%-12s{!} %s\n", "Version:", ver) + fmtc.Printf(" {*}%-10s{!} %s\n", "Name:", app) + fmtc.Printf(" {*}%-10s{!} %s\n", "Version:", ver) fmtc.Printf( - " {*}%-12s{!} %s {s}(%s/%s){!}\n", "Go:", + " {*}%-10s{!} %s {s}(%s/%s){!}\n", "Go:", strings.TrimLeft(runtime.Version(), "go"), runtime.GOOS, runtime.GOARCH, ) if gitRev != "" { if !fmtc.DisableColors && fmtc.IsTrueColorSupported() { - fmtc.Printf(" {*}%-12s{!} %s {#"+strutil.Head(gitRev, 6)+"}●{!}\n", "Git SHA:", gitRev) + fmtc.Printf(" {*}%-10s{!} %s {#"+strutil.Head(gitRev, 6)+"}●{!}\n", "Git SHA:", gitRev) } else { - fmtc.Printf(" {*}%-12s{!} %s\n", "Git SHA:", gitRev) + fmtc.Printf(" {*}%-10s{!} %s\n", "Git SHA:", gitRev) } } @@ -75,22 +74,13 @@ func showApplicationInfo(app, ver, gitRev string) { if binSHA != "" { binSHA = strutil.Head(binSHA, 7) if !fmtc.DisableColors && fmtc.IsTrueColorSupported() { - fmtc.Printf(" {*}%-12s{!} %s {#"+strutil.Head(binSHA, 6)+"}●{!}\n", "Bin SHA:", binSHA) + fmtc.Printf(" {*}%-10s{!} %s {#"+strutil.Head(binSHA, 6)+"}●{!}\n", "Bin SHA:", binSHA) } else { - fmtc.Printf(" {*}%-12s{!} %s\n", "Bin SHA:", binSHA) + fmtc.Printf(" {*}%-10s{!} %s\n", "Bin SHA:", binSHA) } } } -// showEnvironmentInfo shows info about environment -func showEnvironmentInfo(pkgs []Pkg) { - fmtutil.Separator(false, "ENVIRONMENT") - - for _, pkg := range pkgs { - fmtc.Printf(" {*}%-16s{!} %s\n", pkg.Name+":", formatValue(pkg.Version)) - } -} - // showDepsInfo shows information about all dependencies func showDepsInfo(gomod []byte) { deps := depsy.Extract(gomod, false) @@ -110,37 +100,10 @@ func showDepsInfo(gomod []byte) { } } -// ////////////////////////////////////////////////////////////////////////////////// // - -// collectPackagesInfo collects info with packages versions -func collectPackagesInfo() []Pkg { - return []Pkg{ - getPackageInfo("systemd"), - getPackageInfo("systemd-sysv"), - getPackageInfo("initscripts"), - getPackageInfo("glibc"), - getPackageInfo("rpm"), - getPackageInfo("python"), - getPackageInfo("python3"), - } -} - -// getPackageVersion returns package name from rpm database -func getPackageInfo(name string) Pkg { - cmd := exec.Command("rpm", "-q", name) - out, err := cmd.Output() - - if err != nil || len(out) == 0 { - return Pkg{name, ""} - } - - return Pkg{name, strings.TrimRight(string(out), "\n\r")} -} - // formatValue formats value for output func formatValue(v string) string { if v == "" { - return fmtc.Sprintf("{s}unknown{!}") + return fmtc.Sprintf("{s-}—{!}") } return v diff --git a/support/support_darwin.go b/support/support_darwin.go index 91866455..e79f57bf 100644 --- a/support/support_darwin.go +++ b/support/support_darwin.go @@ -25,8 +25,18 @@ func showOSInfo() { fmtutil.Separator(false, "SYSTEM INFO") - fmtc.Printf(" {*}%-16s{!} %s\n", "Name:", formatValue(systemInfo.OS)) - fmtc.Printf(" {*}%-16s{!} %s\n", "Version:", formatValue(systemInfo.Version)) - fmtc.Printf(" {*}%-16s{!} %s\n", "Arch:", formatValue(systemInfo.Arch)) - fmtc.Printf(" {*}%-16s{!} %s\n", "Kernel:", formatValue(systemInfo.Kernel)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Name:", formatValue(systemInfo.OS)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Version:", formatValue(systemInfo.Version)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Arch:", formatValue(systemInfo.Arch)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Kernel:", formatValue(systemInfo.Kernel)) +} + +// collectEnvInfo collects info about environment +func collectEnvInfo() []Pkg { + return nil +} + +// showEnvInfo shows info about environment +func showEnvInfo(pkgs []Pkg) { + return } diff --git a/support/support_linux.go b/support/support_linux.go index 3fca68f4..7374053e 100644 --- a/support/support_linux.go +++ b/support/support_linux.go @@ -8,6 +8,9 @@ package support // ////////////////////////////////////////////////////////////////////////////////// // import ( + "os/exec" + "strings" + "github.com/essentialkaos/ek/v12/fmtc" "github.com/essentialkaos/ek/v12/fmtutil" "github.com/essentialkaos/ek/v12/fsutil" @@ -22,14 +25,14 @@ func showOSInfo() { if err == nil { fmtutil.Separator(false, "OS INFO") - fmtc.Printf(" {*}%-16s{!} %s\n", "Name:", formatValue(osInfo.Name)) - fmtc.Printf(" {*}%-16s{!} %s\n", "Pretty Name:", formatValue(osInfo.PrettyName)) - fmtc.Printf(" {*}%-16s{!} %s\n", "Version:", formatValue(osInfo.VersionID)) - fmtc.Printf(" {*}%-16s{!} %s\n", "ID:", formatValue(osInfo.ID)) - fmtc.Printf(" {*}%-16s{!} %s\n", "ID Like:", formatValue(osInfo.IDLike)) - fmtc.Printf(" {*}%-16s{!} %s\n", "Version ID:", formatValue(osInfo.VersionID)) - fmtc.Printf(" {*}%-16s{!} %s\n", "Version Code:", formatValue(osInfo.VersionCodename)) - fmtc.Printf(" {*}%-16s{!} %s\n", "CPE:", formatValue(osInfo.CPEName)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Name:", formatValue(osInfo.Name)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Pretty Name:", formatValue(osInfo.PrettyName)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Version:", formatValue(osInfo.VersionID)) + fmtc.Printf(" {*}%-15s{!} %s\n", "ID:", formatValue(osInfo.ID)) + fmtc.Printf(" {*}%-15s{!} %s\n", "ID Like:", formatValue(osInfo.IDLike)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Version ID:", formatValue(osInfo.VersionID)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Version Code:", formatValue(osInfo.VersionCodename)) + fmtc.Printf(" {*}%-15s{!} %s\n", "CPE:", formatValue(osInfo.CPEName)) } systemInfo, err := system.GetSystemInfo() @@ -39,13 +42,13 @@ func showOSInfo() { } else { if osInfo == nil { fmtutil.Separator(false, "SYSTEM INFO") - fmtc.Printf(" {*}%-16s{!} %s\n", "Name:", formatValue(systemInfo.OS)) - fmtc.Printf(" {*}%-16s{!} %s\n", "Version:", formatValue(systemInfo.Version)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Name:", formatValue(systemInfo.OS)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Version:", formatValue(systemInfo.Version)) } } - fmtc.Printf(" {*}%-16s{!} %s\n", "Arch:", formatValue(systemInfo.Arch)) - fmtc.Printf(" {*}%-16s{!} %s\n", "Kernel:", formatValue(systemInfo.Kernel)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Arch:", formatValue(systemInfo.Arch)) + fmtc.Printf(" {*}%-15s{!} %s\n", "Kernel:", formatValue(systemInfo.Kernel)) containerEngine := "No" @@ -57,5 +60,89 @@ func showOSInfo() { } fmtc.NewLine() - fmtc.Printf(" {*}%-16s{!} %s\n", "Container:", containerEngine) + fmtc.Printf(" {*}%-15s{!} %s\n", "Container:", containerEngine) +} + +// showEnvInfo shows info about environment +func showEnvInfo(pkgs []Pkg) { + fmtutil.Separator(false, "ENVIRONMENT") + + for _, pkg := range pkgs { + fmtc.Printf(" {*}%-18s{!} %s\n", pkg.Name+":", formatValue(pkg.Version)) + } +} + +// collectEnvInfo collects info about packages +func collectEnvInfo() []Pkg { + if isDEBBased() { + return []Pkg{ + getPackageInfo("ca-certificates"), + getPackageInfo("systemd"), + getPackageInfo("systemd-sysv"), + getPackageInfo("initscripts"), + getPackageInfo("libc-bin"), + getPackageInfo("dpkg"), + getPackageInfo("python"), + getPackageInfo("python3"), + getPackageInfo("binutils"), + } + } + + return []Pkg{ + getPackageInfo("ca-certificates"), + getPackageInfo("systemd"), + getPackageInfo("systemd-sysv"), + getPackageInfo("initscripts"), + getPackageInfo("glibc"), + getPackageInfo("rpm"), + getPackageInfo("python"), + getPackageInfo("python3"), + getPackageInfo("binutils"), + } +} + +// getPackageVersion returns package name from rpm database +func getPackageInfo(name string) Pkg { + switch { + case isDEBBased(): + return getDEBPackageInfo(name) + case isRPMBased(): + return getRPMPackageInfo(name) + } + + return Pkg{name, ""} +} + +// isDEBBased returns true if is DEB-based distro +func isRPMBased() bool { + return fsutil.IsExist("/usr/bin/rpm") +} + +// isDEBBased returns true if is DEB-based distro +func isDEBBased() bool { + return fsutil.IsExist("/usr/bin/dpkg-query") +} + +// getRPMPackageInfo returns info about RPM package +func getRPMPackageInfo(name string) Pkg { + cmd := exec.Command("rpm", "-q", name) + out, err := cmd.Output() + + if err != nil || len(out) == 0 { + return Pkg{name, ""} + } + + return Pkg{name, strings.TrimRight(string(out), "\n\r")} +} + +// getDEBPackageInfo returns info about DEB package +func getDEBPackageInfo(name string) Pkg { + cmd := exec.Command("dpkg-query", "--showformat=${Version}", "--show", name) + out, err := cmd.Output() + + if err != nil || len(out) == 0 { + return Pkg{name, ""} + } + + return Pkg{name, string(out)} }