1package common
2
3import (
4 "errors"
5 "fmt"
6 "io/fs"
7 "os"
8 "path/filepath"
9 "runtime"
10
11 "github.com/bnema/gordon/pkg/docker"
12 "github.com/bnema/gordon/pkg/parser"
13)
14
15type Config struct {
16 General GeneralConfig `yaml:"General"`
17 Http HttpConfig `yaml:"Http"`
18 Admin AdminConfig `yaml:"Admin"`
19 ContainerEngine ContainerEngineConfig `yaml:"ContainerEngine"`
20 Traefik TraefikConfig `yaml:"Traefik"`
21 Build BuildConfig `yaml:"-"`
22}
23
24type BuildConfig struct {
25 RunEnv string `yaml:"-"` // come from env
26 BuildVersion string `yaml:"-"` // come from build ldflags
27 BuildCommit string `yaml:"-"` // come from build ldflags
28 BuildDate string `yaml:"-"` // come from build ldflags
29 ProxyURL string `yaml:"-"`
30}
31
32type AdminConfig struct {
33 Path string `yaml:"path"`
34}
35
36type GeneralConfig struct {
37 StorageDir string `yaml:"storageDir"`
38 Token string `yaml:"token"`
39}
40type HttpConfig struct {
41 Port string `yaml:"port"`
42 Domain string `yaml:"domain"`
43 SubDomain string `yaml:"subDomain"`
44 BackendURL string `yaml:"backendURL"`
45 Https bool `yaml:"https"`
46}
47
48type ContainerEngineConfig struct {
49 Sock string `yaml:"dockersock"`
50 PodmanSock string `yaml:"podmansock"`
51 Podman bool `yaml:"podman"`
52 Network string `yaml:"network"`
53}
54
55type TraefikConfig struct {
56 EntryPoint string `yaml:"entryPoint"`
57 SecureEntryPoint string `yaml:"secureEntryPoint"`
58 Resolver string `yaml:"resolver"`
59}
60
61// Default values
62var (
63 sock = "/var/run/docker.sock"
64 podmansock = "/run/user/1000/podman/podman.sock"
65 entryPoint = "web"
66 entryPointSecure = "websecure"
67 resolver = "myresolver"
68)
69
70func getConfigDir() (string, error) {
71
72 if docker.IsRunningInContainer() {
73 return "/.", nil
74 }
75
76 // Get the user's home directory for non-container environments
77 homeDir, err := os.UserHomeDir()
78 if err != nil {
79 return "", fmt.Errorf("error getting user's home directory: %w", err)
80 }
81
82 // Select the configuration directory based on the OS
83 configDir := filepath.Join(homeDir, ".config", "Gordon")
84 if runtime.GOOS == "windows" {
85 configDir = filepath.Join(homeDir, "AppData", "Roaming", "Gordon")
86 }
87
88 return configDir, nil
89}
90
91func readAndUnmarshalConfig(fs fs.FS, filePath string, config *Config) error {
92 err := parser.ParseYAMLFile(fs, filePath, config)
93 if err != nil {
94 return fmt.Errorf("error reading and unmarshaling configuration file: %w", err)
95 }
96 return nil
97}
98
99func (config *Config) LoadConfig() (*Config, error) {
100 configDir, err := getConfigDir()
101 if err != nil {
102 return nil, fmt.Errorf("error getting configuration directory: %w", err)
103 }
104
105 configFilePath := filepath.Join(configDir, "config.yml")
106
107 _, err = os.Stat(configFilePath)
108 if errors.Is(err, fs.ErrNotExist) {
109 fmt.Printf("Config file not found, creating it at %s\n", configFilePath)
110
111 // Create config dir if it doesn't exist
112 err = os.MkdirAll(configDir, 0755)
113 if err != nil {
114 return nil, fmt.Errorf("error creating configuration directory: %w", err)
115 }
116
117 // Create config file with the default values of ContainerEngineConfig
118 config = &Config{
119 ContainerEngine: ContainerEngineConfig{
120 Sock: sock,
121 PodmanSock: podmansock,
122 Podman: ReadUserInput("Are you using podman ? (y/n)") == "y",
123 },
124 Traefik: TraefikConfig{
125 EntryPoint: entryPoint,
126 SecureEntryPoint: entryPointSecure,
127 Resolver: resolver,
128 },
129 }
130
131 err = config.SaveConfig()
132 if err != nil {
133 return nil, fmt.Errorf("error saving new configuration: %w", err)
134 }
135 return config, nil
136 }
137
138 if err != nil {
139 return nil, fmt.Errorf("error checking configuration file: %w", err)
140 }
141
142 err = readAndUnmarshalConfig(os.DirFS(configDir), "config.yml", config)
143 if err != nil {
144 return nil, err
145 }
146
147 // Load run env
148 config.Build.RunEnv = os.Getenv("RUN_ENV")
149
150 if config.Build.RunEnv == "" {
151 config.Build.RunEnv = "prod"
152 }
153
154 return config, nil
155}
156
157func (config *Config) SaveConfig() error {
158 configDir, err := getConfigDir()
159 if err != nil {
160 return fmt.Errorf("error getting configuration directory: %w", err)
161 }
162 configFilePath := filepath.Join(configDir, "config.yml")
163
164 err = parser.WriteYAMLFile(configFilePath, config)
165 if err != nil {
166 return fmt.Errorf("error writing configuration file: %w", err)
167 }
168
169 fmt.Printf("Configuration saved to %s\n", configFilePath)
170 return nil
171}
172
173func (config *Config) GetToken() (string, error) {
174 token := config.General.Token
175 if token == "" {
176 return "", fmt.Errorf("no token found in config.yml")
177 }
178
179 return token, nil
180
181}
182
183// GetRunEnv returns the run environment
184func (config *BuildConfig) GetRunEnv() string {
185 return config.RunEnv
186}
187
188// GetVersion returns the version
189func (config *Config) GetVersion() string {
190 return config.Build.BuildVersion
191}
192
193// get storage dir
194func (config *Config) GetStorageDir() string {
195 return config.General.StorageDir
196}
197
198func (c *Config) GetBackendURL() string {
199 return c.Http.BackendURL
200}
201
202func (c *Config) SetToken(token string) {
203 c.General.Token = token
204}