- Notifications
You must be signed in to change notification settings - Fork178
Fix CLI credentials config file loading issue (closes #261)#685
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Draft
ljluestc wants to merge1 commit intokubero-dev:mainChoose a base branch fromljluestc:fix/cli-credentials-issue-261
base:main
Could not load branches
Branch not found:{{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline, and old review comments may become outdated.
Uh oh!
There was an error while loading.Please reload this page.
Draft
Changes fromall commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
99 changes: 99 additions & 0 deletionscmd/dns-addon/main.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| package main | ||
| import ( | ||
| "flag" | ||
| "fmt" | ||
| "os" | ||
| "github.com/kubero-dev/kubero/pkg/dns" | ||
| "github.com/kubero-dev/kubero/pkg/dns/providers" | ||
| ) | ||
| func main() { | ||
| var ( | ||
| provider string | ||
| domain string | ||
| action string | ||
| appName string | ||
| namespace string | ||
| ipAddress string | ||
| ttl int | ||
| cfAPIToken string | ||
| cfZoneID string | ||
| ) | ||
| // Parse command-line flags | ||
| flag.StringVar(&provider, "provider", "cloudflare", "DNS provider (cloudflare, aws, gcp, azure)") | ||
| flag.StringVar(&domain, "domain", "", "Base domain for DNS entries") | ||
| flag.StringVar(&action, "action", "", "Action to perform (create, update, delete)") | ||
| flag.StringVar(&appName, "app", "", "Application name") | ||
| flag.StringVar(&namespace, "namespace", "default", "Kubernetes namespace") | ||
| flag.StringVar(&ipAddress, "ip", "", "IP address for the DNS record") | ||
| flag.IntVar(&ttl, "ttl", 300, "TTL for DNS records in seconds") | ||
| flag.StringVar(&cfAPIToken, "cf-token", "", "Cloudflare API token") | ||
| flag.StringVar(&cfZoneID, "cf-zone", "", "Cloudflare Zone ID") | ||
| flag.Parse() | ||
| // Validate required flags | ||
| if domain == "" { | ||
| fmt.Println("Error: domain is required") | ||
| flag.Usage() | ||
| os.Exit(1) | ||
| } | ||
| if action == "" { | ||
| fmt.Println("Error: action is required") | ||
| flag.Usage() | ||
| os.Exit(1) | ||
| } | ||
| if appName == "" { | ||
| fmt.Println("Error: app name is required") | ||
| flag.Usage() | ||
| os.Exit(1) | ||
| } | ||
| // Create DNS configuration | ||
| providerType := dns.ProviderType(provider) | ||
| config := dns.DNSConfig{ | ||
| Provider: providerType, | ||
| Domain: domain, | ||
| TTL: ttl, | ||
| } | ||
| // Create DNS operator | ||
| operator := dns.NewOperator(config) | ||
| // Perform requested action | ||
| var err error | ||
| switch action { | ||
| case "create": | ||
| if ipAddress == "" { | ||
| fmt.Println("Error: IP address is required for create action") | ||
| flag.Usage() | ||
| os.Exit(1) | ||
| } | ||
| err = operator.CreateDNSEntry(appName, namespace, ipAddress) | ||
| case "update": | ||
| if ipAddress == "" { | ||
| fmt.Println("Error: IP address is required for update action") | ||
| flag.Usage() | ||
| os.Exit(1) | ||
| } | ||
| err = operator.UpdateDNSEntry(appName, namespace, ipAddress) | ||
| case "delete": | ||
| err = operator.DeleteDNSEntry(appName, namespace) | ||
| default: | ||
| fmt.Printf("Error: unknown action %s\n", action) | ||
| flag.Usage() | ||
| os.Exit(1) | ||
| } | ||
| if err != nil { | ||
| fmt.Printf("Error: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
| fmt.Println("DNS operation completed successfully") | ||
| } |
122 changes: 122 additions & 0 deletionscmd/kubero/login.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| package main | ||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "path/filepath" | ||
| "github.com/spf13/cobra" | ||
| "gopkg.in/yaml.v3" | ||
| "sigs.k8s.io/controller-runtime/pkg/log" | ||
| ) | ||
| type InstanceConfig struct { | ||
| Instances map[string]struct { | ||
| APIURL string `yaml:"api_url"` | ||
| Token string `yaml:"token"` | ||
| } `yaml:"instances"` | ||
| } | ||
| func init() { | ||
| rootCmd.AddCommand(loginCmd) | ||
| } | ||
| var loginCmd = &cobra.Command{ | ||
| Use: "login", | ||
| Short: "Login to a Kubero instance", | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| logger := log.FromContext(cmd.Context()) | ||
| configDir, err := getConfigDir() | ||
| if err != nil { | ||
| return fmt.Errorf("failed to determine config directory: %v", err) | ||
| } | ||
| // Ensure config directory exists | ||
| if err := os.MkdirAll(configDir, 0755); err != nil { | ||
| logger.Error(err, "Failed to create config directory", "path", configDir) | ||
| return fmt.Errorf("failed to create config directory %s: %v", configDir, err) | ||
| } | ||
| // Prompt for instance details | ||
| instanceName := promptString("Enter the name of the instance", "julep") | ||
| apiURL := promptString("Enter the API URL of the instance", "http://kubero.julep.ai") | ||
| token := promptString("Kubero Token", "") | ||
| // Validate API URL | ||
| if apiURL == "" || !isValidURL(apiURL) { | ||
| return fmt.Errorf("invalid API URL: %s", apiURL) | ||
| } | ||
| // Create or update credentials file | ||
| configPath := filepath.Join(configDir, "credentials") | ||
| config := InstanceConfig{Instances: make(map[string]struct { | ||
| APIURL string | ||
| Token string | ||
| })} | ||
| if _, err := os.Stat(configPath); err == nil { | ||
| // Load existing config | ||
| data, err := os.ReadFile(configPath) | ||
| if err != nil { | ||
| logger.Error(err, "Failed to read existing credentials file", "path", configPath) | ||
| return fmt.Errorf("failed to read credentials file: %v", err) | ||
| } | ||
| if err := yaml.Unmarshal(data, &config); err != nil { | ||
| logger.Error(err, "Failed to parse existing credentials file", "path", configPath) | ||
| return fmt.Errorf("failed to parse credentials file: %v", err) | ||
| } | ||
| } | ||
| // Update config with new instance | ||
| config.Instances[instanceName] = struct { | ||
| APIURL string | ||
| Token string | ||
| }{APIURL: apiURL, Token: token} | ||
| // Write config to file | ||
| data, err := yaml.Marshal(&config) | ||
| if err != nil { | ||
| logger.Error(err, "Failed to marshal config") | ||
| return fmt.Errorf("failed to marshal config: %v", err) | ||
| } | ||
| if err := os.WriteFile(configPath, data, 0600); err != nil { | ||
| logger.Error(err, "Failed to write credentials file", "path", configPath) | ||
| return fmt.Errorf("failed to write credentials file %s: %v", configPath, err) | ||
| } | ||
| fmt.Printf("Successfully logged in to instance %s\n", instanceName) | ||
| return nil | ||
| }, | ||
| } | ||
| // Helper function to determine config directory | ||
| func getConfigDir() (string, error) { | ||
| // Try ~/.kubero first | ||
| homeDir, err := os.UserHomeDir() | ||
| if err == nil { | ||
| configDir := filepath.Join(homeDir, ".kubero") | ||
| if _, err := os.Stat(configDir); err == nil || os.IsNotExist(err) { | ||
| return configDir, nil | ||
| } | ||
| } | ||
| // Fallback to /etc/kubero | ||
| if _, err := os.Stat("/etc/kubero"); err == nil || os.IsNotExist(err) { | ||
| return "/etc/kubero", nil | ||
| } | ||
| return "", fmt.Errorf("no writable config directory found in [/etc/kubero, ~/.kubero]") | ||
| } | ||
| // Helper function to validate URL (simplified; add more validation if needed) | ||
| func isValidURL(url string) bool { | ||
| return len(url) > 7 && (url[:7] == "http://" || url[:8] == "https://") | ||
| } | ||
| // Helper function for prompting (replace with actual prompt logic, e.g., survey) | ||
| func promptString(prompt, defaultValue string) string { | ||
| fmt.Printf("%s [%s]: ", prompt, defaultValue) | ||
| var input string | ||
| fmt.Scanln(&input) | ||
| if input == "" { | ||
| return defaultValue | ||
| } | ||
| return input | ||
| } |
104 changes: 104 additions & 0 deletionscmd/kubero/main.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| package main | ||
| package main | ||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "path/filepath" | ||
| "github.com/spf13/cobra" | ||
| "gopkg.in/yaml.v3" | ||
| "sigs.k8s.io/controller-runtime/pkg/log" | ||
| ) | ||
| var rootCmd = &cobra.Command{ | ||
| Use: "kubero", | ||
| Short: "Kubero CLI for managing Kubero instances", | ||
| PersistentPreRunE: func(cmd *cobra.Command, args []string) error { | ||
| // Skip config validation for login command | ||
| if cmd.Name() == "login" { | ||
| return nil | ||
| } | ||
| logger := log.FromContext(cmd.Context()) | ||
| configDir, err := getConfigDir() | ||
| if err != nil { | ||
| return fmt.Errorf("failed to determine config directory: %v", err) | ||
| } | ||
| configPath := filepath.Join(configDir, "credentials") | ||
| if _, err := os.Stat(configPath); os.IsNotExist(err) { | ||
| logger.Error(err, "Credentials file not found", "path", configPath) | ||
| return fmt.Errorf("credentials file not found in %s; please run 'kubero login'", configPath) | ||
| } | ||
| data, err := os.ReadFile(configPath) | ||
| if err != nil { | ||
| logger.Error(err, "Failed to read credentials file", "path", configPath) | ||
| return fmt.Errorf("failed to read credentials file: %v", err) | ||
| } | ||
| var config InstanceConfig | ||
| if err := yaml.Unmarshal(data, &config); err != nil { | ||
| logger.Error(err, "Failed to parse credentials file", "path", configPath) | ||
| return fmt.Errorf("failed to parse credentials file: %v", err) | ||
| } | ||
| // Validate at least one instance exists | ||
| if len(config.Instances) == 0 { | ||
| return fmt.Errorf("no instances configured; please run 'kubero login'") | ||
| } | ||
| return nil | ||
| }, | ||
| } | ||
| // Execute executes the root command | ||
| func Execute() error { | ||
| return rootCmd.Execute() | ||
| } | ||
| func main() { | ||
| if err := Execute(); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
| } | ||
| // Add dashboard command as an example | ||
| var dashboardCmd = &cobra.Command{ | ||
| Use: "dashboard", | ||
| Short: "Open the Kubero dashboard in your browser", | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| fmt.Println("Opening Kubero dashboard...") | ||
| // Implementation goes here | ||
| return nil | ||
| }, | ||
| } | ||
| // Add list command as an example | ||
| var listCmd = &cobra.Command{ | ||
| Use: "list", | ||
| Short: "List all applications in the Kubero instance", | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| fmt.Println("Listing applications...") | ||
| // Implementation goes here | ||
| return nil | ||
| }, | ||
| } | ||
| func init() { | ||
| // Add commands | ||
| rootCmd.AddCommand(dashboardCmd) | ||
| rootCmd.AddCommand(listCmd) | ||
| } | ||
| import ( | ||
| "fmt" | ||
| "github.com/kubero-dev/kubero/pkg/core" | ||
| ) | ||
| func main() { | ||
| fmt.Println("Starting Kubero...") | ||
| app := core.NewApp() | ||
| app.Run() | ||
| } |
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.