-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
166 lines (140 loc) · 4.28 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"ovh-terminal/internal/api"
"ovh-terminal/internal/config"
"ovh-terminal/internal/logger"
"ovh-terminal/internal/ui"
tea "github.com/charmbracelet/bubbletea"
)
const (
exitSuccess = 0
exitError = 1
)
// AppConfig holds application configuration and components
type AppConfig struct {
ConfigPath string
Config *config.Config
Logger *logger.Logger
APIClient *api.Client
}
// initLogger initializes the logging system
func initLogger(cfg *config.Config) (*logger.Logger, error) {
log := logger.NewLogger()
// Create logs directory if it doesn't exist
if cfg.General.LogFile != "" && cfg.General.LogFile != "none" {
logDir := filepath.Dir(cfg.General.LogFile)
if err := os.MkdirAll(logDir, 0o755); err != nil {
return nil, fmt.Errorf("failed to create log directory: %w", err)
}
}
if err := log.Configure(cfg.General.LogLevel, cfg.General.LogFile, false); err != nil {
return nil, fmt.Errorf("failed to configure logging: %w", err)
}
return log, nil
}
// initAPIClient initializes the OVH API client
func initAPIClient(cfg *config.AccountConfig, log *logger.Logger) (*api.Client, error) {
client, err := api.NewClient(cfg, log)
if err != nil {
log.Error("Failed to create API client", "error", err)
return nil, err
}
// Verify credentials by attempting to get account info
log.Info("Validating API credentials...")
if _, err := client.GetAccountInfo(); err != nil {
return nil, fmt.Errorf("invalid API credentials:\n%w", err)
}
return client, nil
}
// printError formats and prints an error message
func printError(msg string, details ...string) {
fmt.Fprintf(os.Stderr, "\n❌ %s\n", msg)
if len(details) > 0 {
fmt.Fprintln(os.Stderr, "\nDetails:")
for _, detail := range details {
fmt.Fprintf(os.Stderr, " • %s\n", detail)
}
}
}
// printHelp prints helpful instructions for API setup
func printHelp(configPath string) {
fmt.Fprintln(os.Stderr, "\nTo set up OVH API access:")
fmt.Fprintf(os.Stderr, "1. Get your API credentials from https://api.ovh.com/createToken/\n")
fmt.Fprintf(os.Stderr, "2. Update %s with your credentials\n", configPath)
fmt.Fprintf(os.Stderr, "3. Ensure you have the following API rights:\n")
fmt.Fprintln(os.Stderr, " • GET /me")
fmt.Fprintln(os.Stderr, " • GET /dedicated/server")
fmt.Fprintln(os.Stderr, " • GET /domain")
fmt.Fprintln(os.Stderr, " • GET /cloud/project")
fmt.Fprintln(os.Stderr, " • GET /ip")
}
// setupConfig loads and initializes all application components
func setupConfig() (*AppConfig, error) {
app := &AppConfig{}
// Parse command line flags
flag.StringVar(&app.ConfigPath, "config", "config.toml", "path to config file")
flag.Parse()
// Load configuration
cfg, err := config.LoadConfig(app.ConfigPath)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("configuration file not found: %s", app.ConfigPath)
}
return nil, fmt.Errorf("invalid configuration: %w", err)
}
app.Config = cfg
// Initialize logger
log, err := initLogger(cfg)
if err != nil {
return nil, fmt.Errorf("logging setup failed: %w", err)
}
app.Logger = log
// Initialize API client
account := cfg.Accounts[cfg.General.DefaultAccount]
client, err := initAPIClient(&account, log)
if err != nil {
printError(err.Error(), "API client setup failed")
printHelp(app.ConfigPath)
return nil, err
}
app.APIClient = client
return app, nil
}
func main() {
var exitCode int
defer func() {
os.Exit(exitCode)
}()
// Set up application configuration and components
app, err := setupConfig()
if err != nil {
if os.IsNotExist(err) {
fmt.Fprintf(os.Stderr, "\nTo get started:\n")
fmt.Fprintf(os.Stderr, "1. Copy config-example.toml to %s\n", app.ConfigPath)
fmt.Fprintf(os.Stderr, "2. Edit the file with your API credentials\n")
} else {
printHelp(app.ConfigPath)
printError(err.Error())
}
exitCode = exitError
return
}
app.Logger.Info("Starting OVH Terminal Client")
// Initialize and run UI
p := tea.NewProgram(
ui.Initialize(app.APIClient),
tea.WithAltScreen(),
tea.WithMouseCellMotion(),
)
if _, err := p.Run(); err != nil {
app.Logger.Error("Application crashed", "error", err)
printError("Application crashed", err.Error())
exitCode = exitError
return
}
exitCode = exitSuccess
}