0.1.8 745953a

initconfig.go RawHistoryFolder

1package common
2
3import (
4	"errors"
5	"fmt"
6	"io/fs"
7	"os"
8	"path/filepath"
9	"runtime"
10	"strings"
11
12	"github.com/bnema/gordon/pkg/docker"
13	"github.com/bnema/gordon/pkg/parser"
14)
15
16type Config struct {
17	General         GeneralConfig         `yaml:"General"`
18	Http            HttpConfig            `yaml:"Http"`
19	Admin           AdminConfig           `yaml:"Admin"`
20	ContainerEngine ContainerEngineConfig `yaml:"ContainerEngine"`
21	Traefik         TraefikConfig         `yaml:"Traefik"`
22	Build           BuildConfig           `yaml:"-"`
23}
24
25type BuildConfig struct {
26	RunEnv       string `yaml:"-"` // come from env
27	BuildVersion string `yaml:"-"` // come from build ldflags
28	BuildCommit  string `yaml:"-"` // come from build ldflags
29	BuildDate    string `yaml:"-"` // come from build ldflags
30	ProxyURL     string `yaml:"-"`
31}
32
33type AdminConfig struct {
34	Path string `yaml:"path"`
35}
36
37type GeneralConfig struct {
38	StorageDir string `yaml:"storageDir"`
39	Token      string `yaml:"token"`
40}
41type HttpConfig struct {
42	Port       string `yaml:"port"`
43	Domain     string `yaml:"domain"`
44	SubDomain  string `yaml:"subDomain"`
45	BackendURL string `yaml:"backendURL"`
46	Https      bool   `yaml:"https"`
47}
48
49type ContainerEngineConfig struct {
50	Sock       string `yaml:"dockersock"`
51	PodmanSock string `yaml:"podmansock"`
52	Podman     bool   `yaml:"podman"`
53	Network    string `yaml:"network"`
54}
55
56type TraefikConfig struct {
57	EntryPoint       string `yaml:"entryPoint"`
58	SecureEntryPoint string `yaml:"secureEntryPoint"`
59	Resolver         string `yaml:"resolver"`
60}
61
62// Default values
63var (
64	sock             = "/var/run/docker.sock"
65	podmansock       = "/run/user/1000/podman/podman.sock"
66	entryPoint       = "web"
67	entryPointSecure = "websecure"
68	resolver         = "myresolver"
69)
70
71func getConfigDir() (string, error) {
72	var configDir string
73
74	if isWSL() {
75		// Use XDG_CONFIG_HOME for WSL
76		if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" {
77			configDir = filepath.Join(xdgConfigHome, "Gordon")
78		} else {
79			// If XDG_CONFIG_HOME is not set, fall back to default locations
80			homeDir, err := os.UserHomeDir()
81			if err != nil {
82				// If we can't get the home directory, use a fallback
83				homeDir = os.TempDir() // Use the system's temp directory as a fallback
84				fmt.Printf("Warning: Unable to determine home directory. Using temp directory: %s\n", homeDir)
85			}
86
87			configDir = filepath.Join(homeDir, ".config", "Gordon")
88
89		}
90
91		return configDir, nil
92	}
93
94	if docker.IsRunningInContainer() {
95		return "/.", nil
96	}
97
98	// Check for XDG_CONFIG_HOME first
99	if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" {
100		configDir = filepath.Join(xdgConfigHome, "Gordon")
101	} else {
102		// If XDG_CONFIG_HOME is not set, fall back to default locations
103		homeDir, err := os.UserHomeDir()
104		if err != nil {
105			// If we can't get the home directory, use a fallback
106			homeDir = os.TempDir() // Use the system's temp directory as a fallback
107			fmt.Printf("Warning: Unable to determine home directory. Using temp directory: %s\n", homeDir)
108		}
109
110		// Select the configuration directory based on the OS
111		if runtime.GOOS == "windows" {
112			configDir = filepath.Join(homeDir, "AppData", "Roaming", "Gordon")
113		} else {
114			configDir = filepath.Join(homeDir, ".config", "Gordon")
115		}
116	}
117
118	return configDir, nil
119}
120
121func readAndUnmarshalConfig(fs fs.FS, filePath string, config *Config) error {
122	err := parser.ParseYAMLFile(fs, filePath, config)
123	if err != nil {
124		return fmt.Errorf("error reading and unmarshaling configuration file: %w", err)
125	}
126	return nil
127}
128
129func (config *Config) LoadConfig() (*Config, error) {
130	configDir, err := getConfigDir()
131	if err != nil {
132		return nil, fmt.Errorf("error getting configuration directory: %w", err)
133	}
134
135	configFilePath := filepath.Join(configDir, "config.yml")
136
137	_, err = os.Stat(configFilePath)
138	if errors.Is(err, fs.ErrNotExist) {
139		fmt.Printf("Config file not found, creating it at %s\n", configFilePath)
140
141		// Create config dir if it doesn't exist
142		err = os.MkdirAll(configDir, 0755)
143		if err != nil {
144			return nil, fmt.Errorf("error creating configuration directory: %w", err)
145		}
146
147		// Create config file with the default values of ContainerEngineConfig
148		config = &Config{
149			ContainerEngine: ContainerEngineConfig{
150				Sock:       sock,
151				PodmanSock: podmansock,
152				Podman:     ReadUserInput("Are you using podman ? (y/n)") == "y",
153			},
154			Traefik: TraefikConfig{
155				EntryPoint:       entryPoint,
156				SecureEntryPoint: entryPointSecure,
157				Resolver:         resolver,
158			},
159		}
160
161		err = config.SaveConfig()
162		if err != nil {
163			return nil, fmt.Errorf("error saving new configuration: %w", err)
164		}
165		return config, nil
166	}
167
168	if err != nil {
169		return nil, fmt.Errorf("error checking configuration file: %w", err)
170	}
171
172	err = readAndUnmarshalConfig(os.DirFS(configDir), "config.yml", config)
173	if err != nil {
174		return nil, err
175	}
176
177	// Load run env
178	config.Build.RunEnv = os.Getenv("RUN_ENV")
179
180	if config.Build.RunEnv == "" {
181		config.Build.RunEnv = "prod"
182	}
183
184	return config, nil
185}
186
187func (config *Config) SaveConfig() error {
188	configDir, err := getConfigDir()
189	if err != nil {
190		return fmt.Errorf("error getting configuration directory: %w", err)
191	}
192	configFilePath := filepath.Join(configDir, "config.yml")
193
194	err = parser.WriteYAMLFile(configFilePath, config)
195	if err != nil {
196		return fmt.Errorf("error writing configuration file: %w", err)
197	}
198
199	return nil
200}
201
202func (config *Config) GetToken() (string, error) {
203	token := config.General.Token
204	if token == "" {
205		return "", fmt.Errorf("no token found in config.yml")
206	}
207
208	return token, nil
209
210}
211
212// GetRunEnv returns the run environment
213func (config *BuildConfig) GetRunEnv() string {
214	return config.RunEnv
215}
216
217// GetVersion returns the version
218func (config *Config) GetVersion() string {
219	return config.Build.BuildVersion
220}
221
222// get storage dir
223func (config *Config) GetStorageDir() string {
224	return config.General.StorageDir
225}
226
227func (c *Config) GetBackendURL() string {
228	return c.Http.BackendURL
229}
230
231func (c *Config) SetToken(token string) {
232	c.General.Token = token
233}
234
235func isWSL() bool {
236	// Check for /proc/version file
237	if _, err := os.Stat("/proc/version"); err == nil {
238		content, err := os.ReadFile("/proc/version")
239		if err == nil && strings.Contains(strings.ToLower(string(content)), "microsoft") {
240			return true
241		}
242	}
243
244	// Check for WSL-specific environment variable
245	if os.Getenv("WSL_DISTRO_NAME") != "" {
246		return true
247	}
248
249	return false
250}
251
252func (c *HttpConfig) Protocol() string {
253	if c.Https {
254		return "https"
255	}
256	return "http"
257}
258
259func (c *HttpConfig) FullDomain() string {
260	if c.SubDomain != "" {
261		return fmt.Sprintf("%s.%s", c.SubDomain, c.Domain)
262	}
263	return c.Domain
264}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close