|
@@ -0,0 +1,126 @@
|
|
|
+package apt
|
|
|
+
|
|
|
+
|
|
|
+import (
|
|
|
+ "os/exec"
|
|
|
+ "runtime"
|
|
|
+ "net/http"
|
|
|
+ "errors"
|
|
|
+ "encoding/json"
|
|
|
+ "strings"
|
|
|
+ "log"
|
|
|
+ "os"
|
|
|
+)
|
|
|
+
|
|
|
+/*
|
|
|
+ Pacakge management tool for Linux OS with APT
|
|
|
+
|
|
|
+ ONLY USABLE under Linux environment
|
|
|
+*/
|
|
|
+
|
|
|
+type AptPackageManager struct{
|
|
|
+ AllowAutoInstall bool
|
|
|
+}
|
|
|
+
|
|
|
+func NewPackageManager(autoInstall bool) *AptPackageManager{
|
|
|
+ return &AptPackageManager{
|
|
|
+ AllowAutoInstall: autoInstall,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//Install the given package if not exists. Set mustComply to true for "panic on failed to install"
|
|
|
+func (a *AptPackageManager)InstallIfNotExists(pkgname string, mustComply bool) error{
|
|
|
+ //Clear the pkgname
|
|
|
+ pkgname = strings.ReplaceAll(pkgname, "&","")
|
|
|
+ pkgname = strings.ReplaceAll(pkgname, "|","")
|
|
|
+
|
|
|
+ if runtime.GOOS == "windows" {
|
|
|
+ //Check if the command already exists in windows path paramters.
|
|
|
+ cmd := exec.Command("where", pkgname, "2>", "nul")
|
|
|
+ _, err := cmd.CombinedOutput()
|
|
|
+ if err != nil{
|
|
|
+ return errors.New("Package " + pkgname + " not found in Windows %PATH%.")
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ if (a.AllowAutoInstall == false){
|
|
|
+ return errors.New("Package auto install is disabled")
|
|
|
+ }
|
|
|
+
|
|
|
+ cmd := exec.Command("whereis", pkgname)
|
|
|
+ out, err := cmd.CombinedOutput()
|
|
|
+ if err != nil{
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ packageInfo := strings.Split(strings.TrimSpace(string(out)), ":")
|
|
|
+ //log.Println(packageInfo)
|
|
|
+ if (len(packageInfo) > 1 && packageInfo[1] != ""){
|
|
|
+ return nil
|
|
|
+ }else{
|
|
|
+ //Package not installed. Install if now if running in sudo mode
|
|
|
+ log.Println("Installing package " + pkgname + "...")
|
|
|
+ cmd := exec.Command("apt-get", "install", "-y", pkgname)
|
|
|
+ cmd.Stdout = os.Stdout
|
|
|
+ cmd.Stderr = os.Stderr
|
|
|
+ err := cmd.Run()
|
|
|
+ if err != nil{
|
|
|
+ if (mustComply){
|
|
|
+ //Panic and terminate server process
|
|
|
+ log.Println("Installation failed on package: " + pkgname, string(out))
|
|
|
+ os.Exit(0)
|
|
|
+ }else{
|
|
|
+ log.Println("Installation failed on package: " + pkgname)
|
|
|
+ log.Println(string(out))
|
|
|
+ }
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func HandlePackageListRequest(w http.ResponseWriter, r *http.Request){
|
|
|
+ if runtime.GOOS == "windows" {
|
|
|
+ w.Header().Set("Content-Type", "application/json")
|
|
|
+ w.Write([]byte("{\"error\":\"" + "Function disabled on Windows" + "\"}"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ cmd := exec.Command("apt", "list", "--installed")
|
|
|
+ out, err := cmd.CombinedOutput()
|
|
|
+ if err != nil{
|
|
|
+ w.Header().Set("Content-Type", "application/json")
|
|
|
+ w.Write([]byte("{\"error\":\"" + err.Error() + "\"}"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ results := [][]string{}
|
|
|
+ //Parse the output string
|
|
|
+ installedPackages := strings.Split(string(out), "\n")
|
|
|
+ for _, thisPackage := range installedPackages{
|
|
|
+ if len(thisPackage) > 0{
|
|
|
+ packageInfo := strings.Split(thisPackage, "/")
|
|
|
+ packageName := packageInfo[0]
|
|
|
+ if len(packageInfo) >= 2{
|
|
|
+ packageVersion := strings.Split(packageInfo[1], ",")[1]
|
|
|
+ if (packageVersion[:3] == "now"){
|
|
|
+ packageVersion = packageVersion[4:]
|
|
|
+ }
|
|
|
+ if (strings.Contains(packageVersion, "[installed") && packageVersion[len(packageVersion) - 1:] != "]"){
|
|
|
+ packageVersion = packageVersion + ",automatic]"
|
|
|
+ }
|
|
|
+
|
|
|
+ results = append(results, []string{packageName, packageVersion})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ jsonString, _ := json.Marshal(results);
|
|
|
+ w.Header().Set("Content-Type", "application/json")
|
|
|
+ w.Write(jsonString)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|