| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | package configui | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"embed" | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"html/template" | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2021-11-12 09:25:44 +00:00
										 |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2021-11-09 03:27:58 +00:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-11-05 03:10:13 +00:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2021-11-03 10:08:37 +00:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 	"kumoly.io/lib/klog" | 
					
						
							| 
									
										
										
										
											2021-11-04 05:55:45 +00:00
										 |  |  | 	"kumoly.io/lib/ksrv/engine" | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	"kumoly.io/tools/configui/public" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | const UNIX_SHELL = "/usr/bin/sh" | 
					
						
							|  |  |  | const WIN_SHELL = "C:\\Windows\\System32\\cmd" | 
					
						
							|  |  |  | const DARWIN_SHELL = "/bin/bash" | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 07:08:34 +00:00
										 |  |  | const version = "v0.1.12" | 
					
						
							| 
									
										
										
										
											2021-10-23 16:49:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | //go:embed templates
 | 
					
						
							|  |  |  | var tmplFS embed.FS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Ext2Mode map[string]string = map[string]string{ | 
					
						
							|  |  |  | 	"go":   "golang", | 
					
						
							|  |  |  | 	"log":  "sh", | 
					
						
							|  |  |  | 	"txt":  "text", | 
					
						
							|  |  |  | 	"yml":  "yaml", | 
					
						
							|  |  |  | 	"conf": "ini", | 
					
						
							| 
									
										
										
										
											2021-10-24 06:32:55 +00:00
										 |  |  | 	"md":   "markdown", | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 03:27:58 +00:00
										 |  |  | type Action struct { | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | 	Name string `json:"name"` | 
					
						
							|  |  |  | 	Cmd  string `json:"cmd"` | 
					
						
							|  |  |  | 	Dir  string `json:"dir"` | 
					
						
							| 
									
										
										
										
											2021-11-12 09:25:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	run chan struct{} `json:"-"` | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | 	pid int | 
					
						
							| 
									
										
										
										
											2021-11-09 03:27:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Integration struct { | 
					
						
							|  |  |  | 	Name        string                 `json:"name"` | 
					
						
							|  |  |  | 	Description string                 `json:"description"` | 
					
						
							|  |  |  | 	Cmd         func() (string, error) `json:"-"` | 
					
						
							| 
									
										
										
										
											2021-11-11 01:58:36 +00:00
										 |  |  | 	run         chan struct{}          `json:"-"` | 
					
						
							| 
									
										
										
										
											2021-11-09 03:27:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | type ConfigUI struct { | 
					
						
							|  |  |  | 	AppName    string `json:"app_name"` | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 	Prod       bool   `json:"production"` | 
					
						
							| 
									
										
										
										
											2021-10-24 07:06:02 +00:00
										 |  |  | 	BaseUrl    string `json:"base_url"` | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	ConfigPath string `json:"config_path"` | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | 	SHELL      string `json:"shell"` | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	NoReconfig bool   `json:"no_reconfig"` | 
					
						
							|  |  |  | 	AllowIP    string `json:"allow_ip"` | 
					
						
							| 
									
										
										
										
											2021-11-03 10:08:37 +00:00
										 |  |  | 	CmdTimeout string `json:"timeout"` | 
					
						
							|  |  |  | 	cmdTimeout time.Duration | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 03:27:58 +00:00
										 |  |  | 	Files        []*File `json:"files"` | 
					
						
							|  |  |  | 	fileIndex    map[string]int | 
					
						
							|  |  |  | 	Actions      []Action       `json:"actions"` | 
					
						
							| 
									
										
										
										
											2021-11-09 03:41:41 +00:00
										 |  |  | 	Integrations []*Integration `json:"integrations,omitempty"` | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ResultBellow bool `json:"result_bellow"` | 
					
						
							|  |  |  | 	HideConfig   bool `json:"hide_config"` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Should be in main app
 | 
					
						
							| 
									
										
										
										
											2021-11-05 16:09:51 +00:00
										 |  |  | 	LogPath  string      `json:"log_path"` | 
					
						
							|  |  |  | 	LogLevel klog.Llevel `json:"log_level"` | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 09:25:44 +00:00
										 |  |  | 	// Running commands
 | 
					
						
							| 
									
										
										
										
											2021-11-13 04:59:08 +00:00
										 |  |  | 	Onitachi map[string]*Oni `json:"onitachi"` | 
					
						
							| 
									
										
										
										
											2021-11-12 09:25:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 03:10:13 +00:00
										 |  |  | 	TmplFS     embed.FS `json:"-"` | 
					
						
							|  |  |  | 	tmpl       *engine.Engine | 
					
						
							| 
									
										
										
										
											2021-11-09 03:27:58 +00:00
										 |  |  | 	PublicFS   embed.FS `json:"-"` | 
					
						
							|  |  |  | 	log        *klog.Logger | 
					
						
							|  |  |  | 	ksrv_log   *klog.Logger | 
					
						
							|  |  |  | 	f          *os.File | 
					
						
							|  |  |  | 	configLock sync.Mutex | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func New() *ConfigUI { | 
					
						
							| 
									
										
										
										
											2021-11-04 05:55:45 +00:00
										 |  |  | 	tmpl := engine.Must(engine.New("").Funcs(template.FuncMap{ | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 		"step": func(from, to, step uint) []uint { | 
					
						
							|  |  |  | 			items := []uint{} | 
					
						
							|  |  |  | 			for i := from; i <= to; i += step { | 
					
						
							|  |  |  | 				items = append(items, i) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return items | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2021-11-09 03:27:58 +00:00
										 |  |  | 		"normal": func(name string) string { | 
					
						
							|  |  |  | 			return strings.ReplaceAll(name, " ", "-") | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | 		"state_class": func(state State) string { | 
					
						
							|  |  |  | 			switch state { | 
					
						
							|  |  |  | 			case STARTED: | 
					
						
							|  |  |  | 				return "is-success" | 
					
						
							|  |  |  | 			case ERROR: | 
					
						
							|  |  |  | 				return "is-danger" | 
					
						
							|  |  |  | 			case ENDED: | 
					
						
							|  |  |  | 				return "has-background-grey-light" | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				return "" | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		"state_icon": func(state State) string { | 
					
						
							|  |  |  | 			switch state { | 
					
						
							|  |  |  | 			case STARTED: | 
					
						
							|  |  |  | 				return "play_arrow" | 
					
						
							|  |  |  | 			case ERROR: | 
					
						
							|  |  |  | 				return "error" | 
					
						
							|  |  |  | 			case ENDED: | 
					
						
							|  |  |  | 				return "stop" | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				return "pending" | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	}).ParseFS(tmplFS, "templates/*.tmpl", "templates/**/*.tmpl")) | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | 	sh := "" | 
					
						
							|  |  |  | 	switch runtime.GOOS { | 
					
						
							|  |  |  | 	case "darwin": | 
					
						
							|  |  |  | 		sh = DARWIN_SHELL | 
					
						
							|  |  |  | 	case "windows": | 
					
						
							|  |  |  | 		sh = WIN_SHELL | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		sh = UNIX_SHELL | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	return &ConfigUI{ | 
					
						
							| 
									
										
										
										
											2021-11-03 10:08:37 +00:00
										 |  |  | 		fileIndex:  map[string]int{}, | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | 		SHELL:      sh, | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 		Prod:       true, | 
					
						
							| 
									
										
										
										
											2021-11-03 10:08:37 +00:00
										 |  |  | 		AppName:    "ConfigUI", | 
					
						
							|  |  |  | 		BaseUrl:    "/", | 
					
						
							| 
									
										
										
										
											2021-11-09 03:27:58 +00:00
										 |  |  | 		Actions:    []Action{{Name: "User", Cmd: "whoami"}}, | 
					
						
							| 
									
										
										
										
											2021-11-03 10:08:37 +00:00
										 |  |  | 		PublicFS:   public.FS, | 
					
						
							|  |  |  | 		TmplFS:     tmplFS, | 
					
						
							|  |  |  | 		tmpl:       tmpl, | 
					
						
							|  |  |  | 		CmdTimeout: "10s", | 
					
						
							|  |  |  | 		cmdTimeout: time.Second * 10, | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 		LogLevel:   klog.Lerror | klog.Linfo, | 
					
						
							|  |  |  | 		log:        klog.Sub("ConfigUI"), | 
					
						
							| 
									
										
										
										
											2021-11-13 04:59:08 +00:00
										 |  |  | 		Onitachi:   make(map[string]*Oni), | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (cui *ConfigUI) File(file_name string) (*File, error) { | 
					
						
							|  |  |  | 	if file_name == cui.AppName { | 
					
						
							|  |  |  | 		return &File{ | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 			Path:  cui.ConfigPath, | 
					
						
							|  |  |  | 			Name:  cui.AppName, | 
					
						
							|  |  |  | 			Lang:  "json", | 
					
						
							|  |  |  | 			owner: cui, | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 		}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	index, ok := cui.fileIndex[file_name] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return nil, errors.New("no file found") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return cui.Files[index], nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (cui *ConfigUI) LoadConfig(confstr string) error { | 
					
						
							| 
									
										
										
										
											2021-11-13 04:59:08 +00:00
										 |  |  | 	cui.configLock.Lock() | 
					
						
							|  |  |  | 	defer cui.configLock.Unlock() | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	tmpConf := &ConfigUI{} | 
					
						
							|  |  |  | 	err := json.Unmarshal([]byte(confstr), tmpConf) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// construct fileIndex
 | 
					
						
							|  |  |  | 	tmpIndex := map[string]int{} | 
					
						
							|  |  |  | 	for i, f := range tmpConf.Files { | 
					
						
							|  |  |  | 		if f.Name == "" { | 
					
						
							|  |  |  | 			f.Name = f.Path | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 		f.owner = cui | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 		tmpIndex[f.Name] = i | 
					
						
							| 
									
										
										
										
											2021-11-11 02:21:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// deprecated fix
 | 
					
						
							|  |  |  | 		if f.Cmd == "" && f.Action != "" { | 
					
						
							|  |  |  | 			f.Cmd = f.Action | 
					
						
							|  |  |  | 			f.Action = "" | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-13 04:59:08 +00:00
										 |  |  | 	// del oni dry run
 | 
					
						
							|  |  |  | 	for k, v := range cui.Onitachi { | 
					
						
							|  |  |  | 		_, ok := tmpConf.Onitachi[k] | 
					
						
							|  |  |  | 		if !ok && v.State == STARTED { | 
					
						
							|  |  |  | 			return ErrorNoDeleteRunning.New(k) | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	// copy
 | 
					
						
							|  |  |  | 	cui.fileIndex = tmpIndex | 
					
						
							|  |  |  | 	cui.Files = tmpConf.Files | 
					
						
							|  |  |  | 	cui.AllowIP = tmpConf.AllowIP | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 	cui.Prod = tmpConf.Prod | 
					
						
							| 
									
										
										
										
											2021-11-03 19:45:06 +00:00
										 |  |  | 	klog.PROD = cui.Prod | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	cui.ConfigPath = tmpConf.ConfigPath | 
					
						
							|  |  |  | 	cui.HideConfig = tmpConf.HideConfig | 
					
						
							|  |  |  | 	cui.NoReconfig = tmpConf.NoReconfig | 
					
						
							| 
									
										
										
										
											2021-11-05 03:10:13 +00:00
										 |  |  | 	cui.ResultBellow = tmpConf.ResultBellow | 
					
						
							| 
									
										
										
										
											2021-11-12 15:09:32 +00:00
										 |  |  | 	cui.SHELL = tmpConf.SHELL | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-13 04:59:08 +00:00
										 |  |  | 	cui.log = klog.Sub(cui.AppName) | 
					
						
							|  |  |  | 	cui.LogLevel = tmpConf.LogLevel | 
					
						
							|  |  |  | 	if cui.LogLevel == 0 { | 
					
						
							|  |  |  | 		cui.LogLevel = klog.Lerror | klog.Linfo | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	klog.LEVEL = cui.LogLevel | 
					
						
							|  |  |  | 	cui.LogPath = tmpConf.LogPath | 
					
						
							|  |  |  | 	cui.setLog() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// construct oni - update existing, del
 | 
					
						
							|  |  |  | 	for k, v := range cui.Onitachi { | 
					
						
							|  |  |  | 		n, ok := tmpConf.Onitachi[k] | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			delete(cui.Onitachi, k) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			v.Name = k | 
					
						
							|  |  |  | 			v.Cmd = n.Cmd | 
					
						
							|  |  |  | 			v.Args = n.Args | 
					
						
							|  |  |  | 			v.Envs = n.Envs | 
					
						
							|  |  |  | 			v.Dir = n.Dir | 
					
						
							|  |  |  | 			v.Policy = n.Policy | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// construct oni - append new
 | 
					
						
							|  |  |  | 	for k, v := range tmpConf.Onitachi { | 
					
						
							|  |  |  | 		_, ok := cui.Onitachi[k] | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			v.Name = k | 
					
						
							|  |  |  | 			v.Init(cui) | 
					
						
							|  |  |  | 			cui.Onitachi[k] = v | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 03:27:58 +00:00
										 |  |  | 	cui.Actions = tmpConf.Actions | 
					
						
							|  |  |  | 	for i := range cui.Actions { | 
					
						
							|  |  |  | 		if cui.Actions[i].Name == "" { | 
					
						
							|  |  |  | 			cui.Actions[i].Name = cui.Actions[i].Cmd | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	cui.AppName = tmpConf.AppName | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 	if cui.AppName == "" { | 
					
						
							|  |  |  | 		cui.AppName = "ConfigUI" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 07:06:02 +00:00
										 |  |  | 	cui.BaseUrl = tmpConf.BaseUrl | 
					
						
							| 
									
										
										
										
											2021-10-24 07:15:21 +00:00
										 |  |  | 	if cui.BaseUrl == "" { | 
					
						
							|  |  |  | 		cui.BaseUrl = "/" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-03 10:08:37 +00:00
										 |  |  | 	ct, err := time.ParseDuration(tmpConf.CmdTimeout) | 
					
						
							|  |  |  | 	if err != nil || cui.CmdTimeout == "" { | 
					
						
							|  |  |  | 		cui.CmdTimeout = "10s" | 
					
						
							|  |  |  | 		cui.cmdTimeout = time.Second * 10 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		cui.CmdTimeout = tmpConf.CmdTimeout | 
					
						
							|  |  |  | 		cui.cmdTimeout = ct | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// fmt.Printf("%+v", cui)
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | func (cui *ConfigUI) setLog() { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	if cui.f != nil { | 
					
						
							|  |  |  | 		cui.f.Close() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if cui.LogPath != "" { | 
					
						
							| 
									
										
										
										
											2021-11-12 09:25:44 +00:00
										 |  |  | 		mkdir(filepath.Dir(cui.LogPath)) | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 		cui.f, err = os.OpenFile(cui.LogPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			cui.log.Error(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cui.log.SetErrOutput(cui.f) | 
					
						
							|  |  |  | 		cui.log.SetOutput(cui.f) | 
					
						
							|  |  |  | 		if cui.ksrv_log != nil { | 
					
						
							|  |  |  | 			cui.ksrv_log.SetErrOutput(cui.f) | 
					
						
							|  |  |  | 			cui.ksrv_log.SetOutput(cui.f) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		cui.log.SetErrOutput(os.Stderr) | 
					
						
							|  |  |  | 		cui.log.SetOutput(os.Stderr) | 
					
						
							|  |  |  | 		if cui.ksrv_log != nil { | 
					
						
							|  |  |  | 			cui.ksrv_log.SetErrOutput(os.Stderr) | 
					
						
							|  |  |  | 			cui.ksrv_log.SetOutput(os.Stderr) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | func (cui *ConfigUI) Config() ([]byte, error) { | 
					
						
							|  |  |  | 	return json.MarshalIndent(cui, "", "  ") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (cui *ConfigUI) AppendFile(file *File) error { | 
					
						
							|  |  |  | 	if file.Name == "" { | 
					
						
							|  |  |  | 		file.Name = file.Path | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-03 19:35:51 +00:00
										 |  |  | 	file.owner = cui | 
					
						
							| 
									
										
										
										
											2021-10-23 04:56:24 +00:00
										 |  |  | 	i, ok := cui.fileIndex[file.Name] | 
					
						
							|  |  |  | 	if ok { | 
					
						
							|  |  |  | 		return fmt.Errorf("%v already exists at %d", file.Name, i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cui.fileIndex[file.Name] = len(cui.Files) | 
					
						
							|  |  |  | 	cui.Files = append(cui.Files, file) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |