New command: automatic generate app description

This commit is contained in:
Mikhail Klementev 2019-12-30 10:47:36 +00:00
parent 197a78f595
commit f18d55bd27
No known key found for this signature in database
GPG key ID: BE44DA8C062D87DC
3 changed files with 101 additions and 14 deletions

View file

@ -7,8 +7,6 @@ Simple application VMs (hypervisor-based sandbox) based on Nix package manager.
Uses one **read-only** /nix directory for all appvms. So creating a new appvm (but not first) is just about one minute. Uses one **read-only** /nix directory for all appvms. So creating a new appvm (but not first) is just about one minute.
Currently optimized for full screen usage (but remote-viewer has ability to resize window dynamically without change resolution).
![appvm screenshot](screenshots/2018-07-05.png) ![appvm screenshot](screenshots/2018-07-05.png)
## Dependencies ## Dependencies
@ -82,18 +80,8 @@ to crontab like that:
<nix/base.nix> <nix/base.nix>
]; ];
environment.systemPackages = [ pkgs.chromium ]; services.xserver.displayManager.sessionCommands =
services.xserver.displayManager.sessionCommands = "while [ 1 ]; do ${pkgs.chromium}/bin/chromium; done &"; "while [ 1 ]; do ${pkgs.chromium}/bin/chromium; done &";
} }
For create new app you should add package name (search at https://nixos.org/nixos/packages.html) and path to binary (typically same as package name). For create new app you should add package name (search at https://nixos.org/nixos/packages.html) and path to binary (typically same as package name).
## Defined applications (pull requests are welcome!)
* chromium
* thunderbird
* tdesktop
* evince
* libreoffice
* wire
* torbrowser

View file

@ -390,9 +390,15 @@ func main() {
stopName := kingpin.Command("stop", "Stop application").Arg("name", "Application name").Required().String() stopName := kingpin.Command("stop", "Stop application").Arg("name", "Application name").Required().String()
dropName := kingpin.Command("drop", "Remove application data").Arg("name", "Application name").Required().String() dropName := kingpin.Command("drop", "Remove application data").Arg("name", "Application name").Required().String()
generateCommand := kingpin.Command("generate", "Generate appvm definition")
generateName := generateCommand.Arg("name", "Nix package name").Required().String()
generateBin := generateCommand.Arg("bin", "Binary").Default("").String()
switch kingpin.Parse() { switch kingpin.Parse() {
case "list": case "list":
list(l) list(l)
case "generate":
generate(l, *generateName, *generateBin)
case "start": case "start":
start(l, *startName, *startVerbose) start(l, *startName, *startVerbose)
case "stop": case "stop":

93
generate.go Normal file
View file

@ -0,0 +1,93 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"strings"
"github.com/digitalocean/go-libvirt"
)
var template = `
{pkgs, ...}:
{
imports = [
<nixpkgs/nixos/modules/virtualisation/qemu-vm.nix>
<nix/base.nix>
];
services.xserver.displayManager.sessionCommands =
"while [ 1 ]; do ${pkgs.%s}/bin/%s; done &";
}
`
func isPackageExists(name string) bool {
cmd := exec.Command("nix-env", "-iA", name)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
return err == nil
}
func nixPath(name string) (path string, err error) {
command := exec.Command("nix", "path-info", name)
bytes, err := command.Output()
if err != nil {
return
}
path = string(bytes)
return
}
func generate(l *libvirt.Libvirt, name, bin string) {
if !isPackageExists(name) {
log.Println("Package pkgs."+name, "does not exists")
return
}
path, err := nixPath(name)
if err != nil {
log.Println("Cannot find nix path")
return
}
path = strings.TrimSpace(path)
files, err := ioutil.ReadDir(path + "/bin/")
if err != nil {
log.Println(err)
return
}
if bin == "" && len(files) != 1 {
fmt.Println("There's more than one binary in */bin, " +
"you should specify one of them explicitly")
fmt.Println("Files in", path+"/bin/:")
for _, f := range files {
fmt.Println("\t", f.Name())
}
return
}
if bin != "" {
var found bool = false
for _, f := range files {
if bin == f.Name() {
found = true
}
}
if !found {
log.Println("There's no such file in */bin")
return
}
} else {
bin = files[0].Name()
}
realName := strings.Split(name, ".")[1]
fmt.Printf(template, realName, bin)
}