forked from bgdnvk/clanker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathroot.go
More file actions
170 lines (142 loc) · 5.5 KB
/
Copy pathroot.go
File metadata and controls
170 lines (142 loc) · 5.5 KB
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
167
168
169
170
package cmd
import (
"fmt"
"os"
"github.com/bgdnvk/clanker/internal/aws"
"github.com/bgdnvk/clanker/internal/azure"
"github.com/bgdnvk/clanker/internal/cloudflare"
"github.com/bgdnvk/clanker/internal/digitalocean"
"github.com/bgdnvk/clanker/internal/flyio"
"github.com/bgdnvk/clanker/internal/gcp"
"github.com/bgdnvk/clanker/internal/hetzner"
"github.com/bgdnvk/clanker/internal/railway"
"github.com/bgdnvk/clanker/internal/tencent"
"github.com/bgdnvk/clanker/internal/vercel"
"github.com/bgdnvk/clanker/internal/verda"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var cfgFile string
// Version is set at build time via ldflags
var Version = "dev"
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "clanker",
Short: "AI-powered terminal for Cloud queries",
Version: Version,
Long: `Clanker is an AI-powered CLI tool that helps you query your cloud infrastructure
using natural language. Ask questions about your systems,
get insights, and perform operations through an intelligent interface.`,
}
// Execute adds all child commands to the root command and sets flags appropriately.
func Execute() error {
return rootCmd.Execute()
}
func init() {
cobra.OnInitialize(initConfig)
// Add version command
rootCmd.AddCommand(&cobra.Command{
Use: "version",
Short: "Print the version number",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("clanker version %s\n", Version)
},
})
// Add --version / -v flags
rootCmd.Flags().BoolP("version", "v", false, "Print version information")
rootCmd.PreRun = func(cmd *cobra.Command, args []string) {
if v, _ := cmd.Flags().GetBool("version"); v {
fmt.Printf("clanker version %s\n", Version)
os.Exit(0)
}
}
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.clanker.yaml)")
rootCmd.PersistentFlags().Bool("debug", false, "enable debug output (shows progress + internal diagnostics)")
rootCmd.PersistentFlags().Bool("local-mode", true, "enable local mode with rate limiting to prevent system overload (default: true)")
rootCmd.PersistentFlags().Int("local-delay", 100, "delay in milliseconds between calls in local mode (default 100ms)")
// Backend integration flags
rootCmd.PersistentFlags().String("api-key", "", "Backend API key (or set CLANKER_BACKEND_API_KEY)")
rootCmd.PersistentFlags().String("backend-env", "", "Backend environment: testing, staging, production (or set CLANKER_BACKEND_ENV)")
rootCmd.PersistentFlags().String("backend-url", "", "Backend API URL, overrides backend-env (or set CLANKER_BACKEND_URL)")
for _, binding := range []struct {
key string
flag string
}{
{"debug", "debug"},
{"local_mode", "local-mode"},
{"local_delay_ms", "local-delay"},
{"backend.api_key", "api-key"},
{"backend.env", "backend-env"},
{"backend.url", "backend-url"},
} {
if err := viper.BindPFlag(binding.key, rootCmd.PersistentFlags().Lookup(binding.flag)); err != nil {
fmt.Fprintf(os.Stderr, "warning: failed to bind flag %s: %v\n", binding.flag, err)
}
}
// Set defaults for local mode
viper.SetDefault("local_mode", true)
viper.SetDefault("local_delay_ms", 100)
// Register AWS static commands
awsCmd := aws.CreateAWSCommands()
rootCmd.AddCommand(awsCmd)
// Register GCP static commands
gcpCmd := gcp.CreateGCPCommands()
rootCmd.AddCommand(gcpCmd)
// Register Azure static commands
azureCmd := azure.CreateAzureCommands()
rootCmd.AddCommand(azureCmd)
// Register Cloudflare static commands, ask command, and deploy commands
cfCmd := cloudflare.CreateCloudflareCommands()
AddCfAskCommand(cfCmd)
AddCfDeployCommands(cfCmd)
rootCmd.AddCommand(cfCmd)
// Register Digital Ocean static commands
doCmd := digitalocean.CreateDigitalOceanCommands()
rootCmd.AddCommand(doCmd)
// Register Hetzner static commands
hetznerCmd := hetzner.CreateHetznerCommands()
rootCmd.AddCommand(hetznerCmd)
// Register Vercel static commands. Natural-language queries go through
// `clanker ask --vercel "..."` — the canonical path that resolves
// credentials, fetches context, and drives the configured AI provider.
vercelCmd := vercel.CreateVercelCommands()
rootCmd.AddCommand(vercelCmd)
// Register Fly.io static commands. Natural-language queries go through
// `clanker ask --flyio "..."`. The top-level command is `fly` with `flyio`
// as an alias so users can type either form.
flyioCmd := flyio.CreateFlyioCommands()
rootCmd.AddCommand(flyioCmd)
// Register Railway static commands. Natural-language queries go through
// `clanker ask --railway "..."`.
railwayCmd := railway.CreateRailwayCommands()
rootCmd.AddCommand(railwayCmd)
// Register Verda Cloud static commands + ask subcommand
verdaCmd := verda.CreateVerdaCommands()
AddVerdaAskCommand(verdaCmd)
rootCmd.AddCommand(verdaCmd)
// Register Tencent Cloud static commands. Natural-language queries
// (`clanker ask --tencent ...`) will land in a later phase.
tencentCmd := tencent.CreateTencentCommands()
rootCmd.AddCommand(tencentCmd)
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, err := os.UserHomeDir()
if err != nil {
fmt.Fprintf(os.Stderr, "Error finding home directory: %v\n", err)
os.Exit(1)
}
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".clanker")
}
viper.AutomaticEnv()
if err := viper.ReadInConfig(); err == nil {
if viper.GetBool("debug") {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
}
}