Skip to content

Commit

Permalink
feat: add diagnose command
Browse files Browse the repository at this point in the history
Verify installation for Java, Blade and Docker and display warnings and
tips. Also verify bundles total size cached in home directory and docker images total size (both dxp and portal).
  • Loading branch information
lgdd committed May 27, 2023
1 parent 1b1afdf commit 4b015ef
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.16

require (
github.com/blang/semver v3.5.1+incompatible
github.com/dustin/go-humanize v1.0.1
github.com/ettle/strcase v0.1.1
github.com/fatih/color v1.13.0
github.com/fsnotify/fsnotify v1.6.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down
217 changes: 217 additions & 0 deletions lfr/pkg/cmd/diagnose/diagnose.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
package diagnose

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"math"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"

"github.com/dustin/go-humanize"
"github.com/lgdd/liferay-cli/lfr/pkg/util/fileutil"
"github.com/lgdd/liferay-cli/lfr/pkg/util/printutil"
"github.com/spf13/cobra"
)

var (
Cmd = &cobra.Command{
Use: "diagnose",
Aliases: []string{"diag"},
Run: diagnose,
Short: `Run a diagnosis to verify your environment for Liferay development.`,
}
)

func diagnose(cmd *cobra.Command, args []string) {
verifyJava()
verifyBlade()
dockerInstalled := verifyDocker()
fmt.Print("\n")
verifyBundles()
if dockerInstalled {
verifyDockerImages()
}
fmt.Println("\nMore information about compatibilities: https://www.liferay.com/compatibility-matrix")
}

func verifyJava() bool {
var javaVersionCmdOut, javaVersionCmdErr bytes.Buffer
javaVersionCmd := exec.Command("java", "-version")
javaVersionCmd.Stdout = &javaVersionCmdOut
javaVersionCmd.Stderr = &javaVersionCmdErr

err := javaVersionCmd.Run()

if err != nil {
printutil.Danger("[✗] ")
fmt.Printf("Liferay requires Java 8 or 11.\n")
return false
}

javaVersionResult := javaVersionCmdErr.String()

if strings.Contains(javaVersionResult, "build 1.8") ||
strings.Contains(javaVersionResult, "build 11.") {
printutil.Success("[✓] ")
fmt.Printf("Java intalled (%s)\n", strings.Split(javaVersionResult, "\n")[0])
printlnBulletPoint("Make sure that your Java edition is a Java Technical Compatibility Kit (TCK) compliant build.")
printlnBulletPoint("JDK compatibility is for runtime and project compile time. DXP source compile is compatible with JDK 8 only.")
} else {
printutil.Warning("[!] ")
fmt.Printf("Java (%s)\n", strings.Split(javaVersionResult, "\n")[0])
printlnBulletPointWarning("Liferay supports Java 8 and 11 only.")
}
return true
}

func verifyBlade() bool {
var bladeVersionCmdOut, bladeVersionCmdErr bytes.Buffer
bladeVersionCmd := exec.Command("blade", "version")
bladeVersionCmd.Stdout = &bladeVersionCmdOut
bladeVersionCmd.Stderr = &bladeVersionCmdErr

err := bladeVersionCmd.Run()

if err != nil {
printutil.Danger("[✗] ")
fmt.Printf("Blade is not installed.\n")
printlnBulletPoint("You might like this tool, but Blade is still the offical one with useful features.")
printlnBulletPoint("Blade is supported by Liferay and used by Liferay IDE behind the scenes.")
printlnBulletPoint("Checkout the documentation: https://learn.liferay.com/w/dxp/building-applications/tooling/blade-cli")
return false
}

bladeVersionResult := bladeVersionCmdOut.String()
printutil.Success("[✓] ")
fmt.Printf("Blade installed (%s)\n", strings.Split(bladeVersionResult, "\n")[0])
return true
}

func verifyDocker() bool {
var dockerVersionCmdOut, dockerVersionCmdErr bytes.Buffer
dockerVersionCmd := exec.Command("docker", "version", "--format", "json")
dockerVersionCmd.Stdout = &dockerVersionCmdOut
dockerVersionCmd.Stderr = &dockerVersionCmdErr

err := dockerVersionCmd.Run()

if err != nil {
printutil.Warning("[!] ")
fmt.Printf("Docker is not installed.\n")
printlnBulletPoint("Docker is not required, but it's a easy way to get started and try Liferay DXP.")
printlnBulletPoint("Checkout official images: https://hub.docker.com/u/liferay")
return false
}

var dockerVersion DockerVersion
dockerVersionResult := dockerVersionCmdOut.String()
json.Unmarshal([]byte(dockerVersionResult), &dockerVersion)
printutil.Success("[✓] ")
fmt.Printf("Docker installed (%s)\n", strings.Split(dockerVersion.Server.Platform.Name, "\n")[0])
return true
}

func verifyBundles() {
homeDir, err := os.UserHomeDir()

if err != nil {
panic(err)
}

liferayHomeDir := filepath.Join(homeDir, ".liferay")
liferayHomeBundlesDir := filepath.Join(liferayHomeDir, "bundles")

bundlesDirSize, err := fileutil.DirSize(liferayHomeBundlesDir)

if err == nil && bundlesDirSize > 0 {
printutil.Info("[i] ")
fmt.Printf("Downloaded bundles are using ~%s.\n", humanize.Bytes(uint64(bundlesDirSize)))
printlnBulletPoint("They are stored under " + liferayHomeBundlesDir)
}
}

func verifyDockerImages() {
dxpImagesTotalSize := getDockerImagesSize("liferay/dxp")
portalImagesTotalSize := getDockerImagesSize("liferay/portal")
dockerImagesTotalSize := dxpImagesTotalSize + portalImagesTotalSize

if dockerImagesTotalSize > 0 {
printutil.Info("[i] ")
fmt.Printf("Official Liferay Docker images are using ~%s.\n", humanize.Bytes(dockerImagesTotalSize))
printlnBulletPoint("Run 'docker images liferay/dxp' to list DXP Images (EE)")
printlnBulletPoint("Run 'docker images liferay/portal' to list Portal Images (CE)")
}
}

func getDockerImagesSize(tag string) uint64 {
var dockerImagesTotalSize uint64
var dockerImagesCmdOut, dockerImagesCmdErr bytes.Buffer
dockerImagesCmd := exec.Command("docker", "images", tag, "--format", "{{.Size}}")
dockerImagesCmd.Stdout = &dockerImagesCmdOut
dockerImagesCmd.Stderr = &dockerImagesCmdErr

err := dockerImagesCmd.Run()

if err == nil {
dockerImagesResult := dockerImagesCmdOut.String()
dockerImagesSizes := strings.Split(dockerImagesResult, "\n")

for _, dockerImageSize := range dockerImagesSizes {
if len(dockerImageSize) > 0 {
currentDockerImageSize, err := parseBytesFromString(dockerImageSize)
if err == nil {
dockerImagesTotalSize = dockerImagesTotalSize + currentDockerImageSize
}
}
}

}
return dockerImagesTotalSize
}

func parseBytesFromString(size string) (uint64, error) {
sizeSplit0 := strings.Split(size, "B")[0]
unit := sizeSplit0[len(sizeSplit0)-1:] + "B"
sizeParsed, err := strconv.ParseFloat(strings.Split(size, unit)[0], 64)

if err != nil {
return 0, err
}

switch unit {
case "MB":
return uint64(sizeParsed * math.Pow(1000, 2)), nil
case "GB":
return uint64(sizeParsed * math.Pow(1000, 3)), nil
default:
return 0, errors.New("Unexpected unit for a Liferay docker image")
}
}

type DockerVersion struct {
Server struct {
Platform struct {
Name string `json:"Name"`
} `json:"Platform"`
} `json:"Server"`
}

func printlnBulletPoint(msg string) {
printutil.Bold(" • ")
printutil.Bold(msg + "\n")
}

func printlnBulletPointWarning(msg string) {
printutil.Bold(" ! ")
printutil.Bold(msg + "\n")
}

func printlnBulletPointDanger(msg string) {
printutil.Danger(" ✗ ")
printutil.Bold(msg + "\n")
}
2 changes: 2 additions & 0 deletions lfr/pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/lgdd/liferay-cli/lfr/pkg/cmd/completion"
"github.com/lgdd/liferay-cli/lfr/pkg/cmd/create"
"github.com/lgdd/liferay-cli/lfr/pkg/cmd/deploy"
"github.com/lgdd/liferay-cli/lfr/pkg/cmd/diagnose"
"github.com/lgdd/liferay-cli/lfr/pkg/cmd/exec"
"github.com/lgdd/liferay-cli/lfr/pkg/cmd/initb"
"github.com/lgdd/liferay-cli/lfr/pkg/cmd/logs"
Expand Down Expand Up @@ -41,6 +42,7 @@ func init() {
root.AddCommand(shell.Cmd)
root.AddCommand(version.Cmd)
root.AddCommand(update.Cmd)
root.AddCommand(diagnose.Cmd)
root.PersistentFlags().BoolVar(&printutil.NoColor, "no-color", false, "disable colors for output messages")
}

Expand Down
14 changes: 14 additions & 0 deletions lfr/pkg/util/fileutil/fileutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,17 @@ func Tail(logFile string, follow bool) {
fmt.Println(line.Text)
}
}

func DirSize(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
size += info.Size()
}
return err
})
return size, err
}

0 comments on commit 4b015ef

Please sign in to comment.