refactor(logging): replace log.Fatalf with log.Errorf and add error handling paths

This commit is contained in:
Luis Pater
2025-12-09 17:16:30 +08:00
parent 92df0cada9
commit c600519fa4
6 changed files with 85 additions and 52 deletions

View File

@@ -139,7 +139,8 @@ func main() {
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
log.Fatalf("failed to get working directory: %v", err) log.Errorf("failed to get working directory: %v", err)
return
} }
// Load environment variables from .env if present. // Load environment variables from .env if present.
@@ -233,13 +234,15 @@ func main() {
}) })
cancel() cancel()
if err != nil { if err != nil {
log.Fatalf("failed to initialize postgres token store: %v", err) log.Errorf("failed to initialize postgres token store: %v", err)
return
} }
examplePath := filepath.Join(wd, "config.example.yaml") examplePath := filepath.Join(wd, "config.example.yaml")
ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
if errBootstrap := pgStoreInst.Bootstrap(ctx, examplePath); errBootstrap != nil { if errBootstrap := pgStoreInst.Bootstrap(ctx, examplePath); errBootstrap != nil {
cancel() cancel()
log.Fatalf("failed to bootstrap postgres-backed config: %v", errBootstrap) log.Errorf("failed to bootstrap postgres-backed config: %v", errBootstrap)
return
} }
cancel() cancel()
configFilePath = pgStoreInst.ConfigPath() configFilePath = pgStoreInst.ConfigPath()
@@ -262,7 +265,8 @@ func main() {
if strings.Contains(resolvedEndpoint, "://") { if strings.Contains(resolvedEndpoint, "://") {
parsed, errParse := url.Parse(resolvedEndpoint) parsed, errParse := url.Parse(resolvedEndpoint)
if errParse != nil { if errParse != nil {
log.Fatalf("failed to parse object store endpoint %q: %v", objectStoreEndpoint, errParse) log.Errorf("failed to parse object store endpoint %q: %v", objectStoreEndpoint, errParse)
return
} }
switch strings.ToLower(parsed.Scheme) { switch strings.ToLower(parsed.Scheme) {
case "http": case "http":
@@ -270,10 +274,12 @@ func main() {
case "https": case "https":
useSSL = true useSSL = true
default: default:
log.Fatalf("unsupported object store scheme %q (only http and https are allowed)", parsed.Scheme) log.Errorf("unsupported object store scheme %q (only http and https are allowed)", parsed.Scheme)
return
} }
if parsed.Host == "" { if parsed.Host == "" {
log.Fatalf("object store endpoint %q is missing host information", objectStoreEndpoint) log.Errorf("object store endpoint %q is missing host information", objectStoreEndpoint)
return
} }
resolvedEndpoint = parsed.Host resolvedEndpoint = parsed.Host
if parsed.Path != "" && parsed.Path != "/" { if parsed.Path != "" && parsed.Path != "/" {
@@ -292,13 +298,15 @@ func main() {
} }
objectStoreInst, err = store.NewObjectTokenStore(objCfg) objectStoreInst, err = store.NewObjectTokenStore(objCfg)
if err != nil { if err != nil {
log.Fatalf("failed to initialize object token store: %v", err) log.Errorf("failed to initialize object token store: %v", err)
return
} }
examplePath := filepath.Join(wd, "config.example.yaml") examplePath := filepath.Join(wd, "config.example.yaml")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
if errBootstrap := objectStoreInst.Bootstrap(ctx, examplePath); errBootstrap != nil { if errBootstrap := objectStoreInst.Bootstrap(ctx, examplePath); errBootstrap != nil {
cancel() cancel()
log.Fatalf("failed to bootstrap object-backed config: %v", errBootstrap) log.Errorf("failed to bootstrap object-backed config: %v", errBootstrap)
return
} }
cancel() cancel()
configFilePath = objectStoreInst.ConfigPath() configFilePath = objectStoreInst.ConfigPath()
@@ -323,7 +331,8 @@ func main() {
gitStoreInst = store.NewGitTokenStore(gitStoreRemoteURL, gitStoreUser, gitStorePassword) gitStoreInst = store.NewGitTokenStore(gitStoreRemoteURL, gitStoreUser, gitStorePassword)
gitStoreInst.SetBaseDir(authDir) gitStoreInst.SetBaseDir(authDir)
if errRepo := gitStoreInst.EnsureRepository(); errRepo != nil { if errRepo := gitStoreInst.EnsureRepository(); errRepo != nil {
log.Fatalf("failed to prepare git token store: %v", errRepo) log.Errorf("failed to prepare git token store: %v", errRepo)
return
} }
configFilePath = gitStoreInst.ConfigPath() configFilePath = gitStoreInst.ConfigPath()
if configFilePath == "" { if configFilePath == "" {
@@ -332,17 +341,21 @@ func main() {
if _, statErr := os.Stat(configFilePath); errors.Is(statErr, fs.ErrNotExist) { if _, statErr := os.Stat(configFilePath); errors.Is(statErr, fs.ErrNotExist) {
examplePath := filepath.Join(wd, "config.example.yaml") examplePath := filepath.Join(wd, "config.example.yaml")
if _, errExample := os.Stat(examplePath); errExample != nil { if _, errExample := os.Stat(examplePath); errExample != nil {
log.Fatalf("failed to find template config file: %v", errExample) log.Errorf("failed to find template config file: %v", errExample)
return
} }
if errCopy := misc.CopyConfigTemplate(examplePath, configFilePath); errCopy != nil { if errCopy := misc.CopyConfigTemplate(examplePath, configFilePath); errCopy != nil {
log.Fatalf("failed to bootstrap git-backed config: %v", errCopy) log.Errorf("failed to bootstrap git-backed config: %v", errCopy)
return
} }
if errCommit := gitStoreInst.PersistConfig(context.Background()); errCommit != nil { if errCommit := gitStoreInst.PersistConfig(context.Background()); errCommit != nil {
log.Fatalf("failed to commit initial git-backed config: %v", errCommit) log.Errorf("failed to commit initial git-backed config: %v", errCommit)
return
} }
log.Infof("git-backed config initialized from template: %s", configFilePath) log.Infof("git-backed config initialized from template: %s", configFilePath)
} else if statErr != nil { } else if statErr != nil {
log.Fatalf("failed to inspect git-backed config: %v", statErr) log.Errorf("failed to inspect git-backed config: %v", statErr)
return
} }
cfg, err = config.LoadConfigOptional(configFilePath, isCloudDeploy) cfg, err = config.LoadConfigOptional(configFilePath, isCloudDeploy)
if err == nil { if err == nil {
@@ -355,13 +368,15 @@ func main() {
} else { } else {
wd, err = os.Getwd() wd, err = os.Getwd()
if err != nil { if err != nil {
log.Fatalf("failed to get working directory: %v", err) log.Errorf("failed to get working directory: %v", err)
return
} }
configFilePath = filepath.Join(wd, "config.yaml") configFilePath = filepath.Join(wd, "config.yaml")
cfg, err = config.LoadConfigOptional(configFilePath, isCloudDeploy) cfg, err = config.LoadConfigOptional(configFilePath, isCloudDeploy)
} }
if err != nil { if err != nil {
log.Fatalf("failed to load config: %v", err) log.Errorf("failed to load config: %v", err)
return
} }
if cfg == nil { if cfg == nil {
cfg = &config.Config{} cfg = &config.Config{}
@@ -391,7 +406,8 @@ func main() {
coreauth.SetQuotaCooldownDisabled(cfg.DisableCooling) coreauth.SetQuotaCooldownDisabled(cfg.DisableCooling)
if err = logging.ConfigureLogOutput(cfg.LoggingToFile); err != nil { if err = logging.ConfigureLogOutput(cfg.LoggingToFile); err != nil {
log.Fatalf("failed to configure log output: %v", err) log.Errorf("failed to configure log output: %v", err)
return
} }
log.Infof("CLIProxyAPI Version: %s, Commit: %s, BuiltAt: %s", buildinfo.Version, buildinfo.Commit, buildinfo.BuildDate) log.Infof("CLIProxyAPI Version: %s, Commit: %s, BuiltAt: %s", buildinfo.Version, buildinfo.Commit, buildinfo.BuildDate)
@@ -400,7 +416,8 @@ func main() {
util.SetLogLevel(cfg) util.SetLogLevel(cfg)
if resolvedAuthDir, errResolveAuthDir := util.ResolveAuthDir(cfg.AuthDir); errResolveAuthDir != nil { if resolvedAuthDir, errResolveAuthDir := util.ResolveAuthDir(cfg.AuthDir); errResolveAuthDir != nil {
log.Fatalf("failed to resolve auth directory: %v", errResolveAuthDir) log.Errorf("failed to resolve auth directory: %v", errResolveAuthDir)
return
} else { } else {
cfg.AuthDir = resolvedAuthDir cfg.AuthDir = resolvedAuthDir
} }

View File

@@ -713,14 +713,16 @@ func (h *Handler) RequestAnthropicToken(c *gin.Context) {
// Generate PKCE codes // Generate PKCE codes
pkceCodes, err := claude.GeneratePKCECodes() pkceCodes, err := claude.GeneratePKCECodes()
if err != nil { if err != nil {
log.Fatalf("Failed to generate PKCE codes: %v", err) log.Errorf("Failed to generate PKCE codes: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate PKCE codes"})
return return
} }
// Generate random state parameter // Generate random state parameter
state, err := misc.GenerateRandomState() state, err := misc.GenerateRandomState()
if err != nil { if err != nil {
log.Fatalf("Failed to generate state parameter: %v", err) log.Errorf("Failed to generate state parameter: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate state parameter"})
return return
} }
@@ -730,7 +732,8 @@ func (h *Handler) RequestAnthropicToken(c *gin.Context) {
// Generate authorization URL (then override redirect_uri to reuse server port) // Generate authorization URL (then override redirect_uri to reuse server port)
authURL, state, err := anthropicAuth.GenerateAuthURL(state, pkceCodes) authURL, state, err := anthropicAuth.GenerateAuthURL(state, pkceCodes)
if err != nil { if err != nil {
log.Fatalf("Failed to generate authorization URL: %v", err) log.Errorf("Failed to generate authorization URL: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate authorization url"})
return return
} }
@@ -872,7 +875,7 @@ func (h *Handler) RequestAnthropicToken(c *gin.Context) {
} }
savedPath, errSave := h.saveTokenRecord(ctx, record) savedPath, errSave := h.saveTokenRecord(ctx, record)
if errSave != nil { if errSave != nil {
log.Fatalf("Failed to save authentication tokens: %v", errSave) log.Errorf("Failed to save authentication tokens: %v", errSave)
oauthStatus[state] = "Failed to save authentication tokens" oauthStatus[state] = "Failed to save authentication tokens"
return return
} }
@@ -1045,7 +1048,7 @@ func (h *Handler) RequestGeminiCLIToken(c *gin.Context) {
gemAuth := geminiAuth.NewGeminiAuth() gemAuth := geminiAuth.NewGeminiAuth()
gemClient, errGetClient := gemAuth.GetAuthenticatedClient(ctx, &ts, h.cfg, true) gemClient, errGetClient := gemAuth.GetAuthenticatedClient(ctx, &ts, h.cfg, true)
if errGetClient != nil { if errGetClient != nil {
log.Fatalf("failed to get authenticated client: %v", errGetClient) log.Errorf("failed to get authenticated client: %v", errGetClient)
oauthStatus[state] = "Failed to get authenticated client" oauthStatus[state] = "Failed to get authenticated client"
return return
} }
@@ -1110,7 +1113,7 @@ func (h *Handler) RequestGeminiCLIToken(c *gin.Context) {
} }
savedPath, errSave := h.saveTokenRecord(ctx, record) savedPath, errSave := h.saveTokenRecord(ctx, record)
if errSave != nil { if errSave != nil {
log.Fatalf("Failed to save token to file: %v", errSave) log.Errorf("Failed to save token to file: %v", errSave)
oauthStatus[state] = "Failed to save token to file" oauthStatus[state] = "Failed to save token to file"
return return
} }
@@ -1131,14 +1134,16 @@ func (h *Handler) RequestCodexToken(c *gin.Context) {
// Generate PKCE codes // Generate PKCE codes
pkceCodes, err := codex.GeneratePKCECodes() pkceCodes, err := codex.GeneratePKCECodes()
if err != nil { if err != nil {
log.Fatalf("Failed to generate PKCE codes: %v", err) log.Errorf("Failed to generate PKCE codes: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate PKCE codes"})
return return
} }
// Generate random state parameter // Generate random state parameter
state, err := misc.GenerateRandomState() state, err := misc.GenerateRandomState()
if err != nil { if err != nil {
log.Fatalf("Failed to generate state parameter: %v", err) log.Errorf("Failed to generate state parameter: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate state parameter"})
return return
} }
@@ -1148,7 +1153,8 @@ func (h *Handler) RequestCodexToken(c *gin.Context) {
// Generate authorization URL // Generate authorization URL
authURL, err := openaiAuth.GenerateAuthURL(state, pkceCodes) authURL, err := openaiAuth.GenerateAuthURL(state, pkceCodes)
if err != nil { if err != nil {
log.Fatalf("Failed to generate authorization URL: %v", err) log.Errorf("Failed to generate authorization URL: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate authorization url"})
return return
} }
@@ -1283,7 +1289,7 @@ func (h *Handler) RequestCodexToken(c *gin.Context) {
savedPath, errSave := h.saveTokenRecord(ctx, record) savedPath, errSave := h.saveTokenRecord(ctx, record)
if errSave != nil { if errSave != nil {
oauthStatus[state] = "Failed to save authentication tokens" oauthStatus[state] = "Failed to save authentication tokens"
log.Fatalf("Failed to save authentication tokens: %v", errSave) log.Errorf("Failed to save authentication tokens: %v", errSave)
return return
} }
fmt.Printf("Authentication successful! Token saved to %s\n", savedPath) fmt.Printf("Authentication successful! Token saved to %s\n", savedPath)
@@ -1318,7 +1324,8 @@ func (h *Handler) RequestAntigravityToken(c *gin.Context) {
state, errState := misc.GenerateRandomState() state, errState := misc.GenerateRandomState()
if errState != nil { if errState != nil {
log.Fatalf("Failed to generate state parameter: %v", errState) log.Errorf("Failed to generate state parameter: %v", errState)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate state parameter"})
return return
} }
@@ -1514,7 +1521,7 @@ func (h *Handler) RequestAntigravityToken(c *gin.Context) {
} }
savedPath, errSave := h.saveTokenRecord(ctx, record) savedPath, errSave := h.saveTokenRecord(ctx, record)
if errSave != nil { if errSave != nil {
log.Fatalf("Failed to save token to file: %v", errSave) log.Errorf("Failed to save token to file: %v", errSave)
oauthStatus[state] = "Failed to save token to file" oauthStatus[state] = "Failed to save token to file"
return return
} }
@@ -1543,7 +1550,8 @@ func (h *Handler) RequestQwenToken(c *gin.Context) {
// Generate authorization URL // Generate authorization URL
deviceFlow, err := qwenAuth.InitiateDeviceFlow(ctx) deviceFlow, err := qwenAuth.InitiateDeviceFlow(ctx)
if err != nil { if err != nil {
log.Fatalf("Failed to generate authorization URL: %v", err) log.Errorf("Failed to generate authorization URL: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate authorization url"})
return return
} }
authURL := deviceFlow.VerificationURIComplete authURL := deviceFlow.VerificationURIComplete
@@ -1570,7 +1578,7 @@ func (h *Handler) RequestQwenToken(c *gin.Context) {
} }
savedPath, errSave := h.saveTokenRecord(ctx, record) savedPath, errSave := h.saveTokenRecord(ctx, record)
if errSave != nil { if errSave != nil {
log.Fatalf("Failed to save authentication tokens: %v", errSave) log.Errorf("Failed to save authentication tokens: %v", errSave)
oauthStatus[state] = "Failed to save authentication tokens" oauthStatus[state] = "Failed to save authentication tokens"
return return
} }
@@ -1674,7 +1682,7 @@ func (h *Handler) RequestIFlowToken(c *gin.Context) {
savedPath, errSave := h.saveTokenRecord(ctx, record) savedPath, errSave := h.saveTokenRecord(ctx, record)
if errSave != nil { if errSave != nil {
oauthStatus[state] = "Failed to save authentication tokens" oauthStatus[state] = "Failed to save authentication tokens"
log.Fatalf("Failed to save authentication tokens: %v", errSave) log.Errorf("Failed to save authentication tokens: %v", errSave)
return return
} }
@@ -2103,6 +2111,7 @@ func checkCloudAPIIsEnabled(ctx context.Context, httpClient *http.Client, projec
continue continue
} }
} }
_ = resp.Body.Close()
return false, fmt.Errorf("project activation required: %s", errMessage) return false, fmt.Errorf("project activation required: %s", errMessage)
} }
return true, nil return true, nil

View File

@@ -76,7 +76,8 @@ func (g *GeminiAuth) GetAuthenticatedClient(ctx context.Context, ts *GeminiToken
auth := &proxy.Auth{User: username, Password: password} auth := &proxy.Auth{User: username, Password: password}
dialer, errSOCKS5 := proxy.SOCKS5("tcp", proxyURL.Host, auth, proxy.Direct) dialer, errSOCKS5 := proxy.SOCKS5("tcp", proxyURL.Host, auth, proxy.Direct)
if errSOCKS5 != nil { if errSOCKS5 != nil {
log.Fatalf("create SOCKS5 dialer failed: %v", errSOCKS5) log.Errorf("create SOCKS5 dialer failed: %v", errSOCKS5)
return nil, fmt.Errorf("create SOCKS5 dialer failed: %w", errSOCKS5)
} }
transport = &http.Transport{ transport = &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
@@ -238,7 +239,11 @@ func (g *GeminiAuth) getTokenFromWeb(ctx context.Context, config *oauth2.Config,
// Start the server in a goroutine. // Start the server in a goroutine.
go func() { go func() {
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
log.Fatalf("ListenAndServe(): %v", err) log.Errorf("ListenAndServe(): %v", err)
select {
case errChan <- err:
default:
}
} }
}() }()

View File

@@ -65,20 +65,20 @@ func DoLogin(cfg *config.Config, projectID string, options *LoginOptions) {
authenticator := sdkAuth.NewGeminiAuthenticator() authenticator := sdkAuth.NewGeminiAuthenticator()
record, errLogin := authenticator.Login(ctx, cfg, loginOpts) record, errLogin := authenticator.Login(ctx, cfg, loginOpts)
if errLogin != nil { if errLogin != nil {
log.Fatalf("Gemini authentication failed: %v", errLogin) log.Errorf("Gemini authentication failed: %v", errLogin)
return return
} }
storage, okStorage := record.Storage.(*gemini.GeminiTokenStorage) storage, okStorage := record.Storage.(*gemini.GeminiTokenStorage)
if !okStorage || storage == nil { if !okStorage || storage == nil {
log.Fatal("Gemini authentication failed: unsupported token storage") log.Error("Gemini authentication failed: unsupported token storage")
return return
} }
geminiAuth := gemini.NewGeminiAuth() geminiAuth := gemini.NewGeminiAuth()
httpClient, errClient := geminiAuth.GetAuthenticatedClient(ctx, storage, cfg, options.NoBrowser) httpClient, errClient := geminiAuth.GetAuthenticatedClient(ctx, storage, cfg, options.NoBrowser)
if errClient != nil { if errClient != nil {
log.Fatalf("Gemini authentication failed: %v", errClient) log.Errorf("Gemini authentication failed: %v", errClient)
return return
} }
@@ -86,7 +86,7 @@ func DoLogin(cfg *config.Config, projectID string, options *LoginOptions) {
projects, errProjects := fetchGCPProjects(ctx, httpClient) projects, errProjects := fetchGCPProjects(ctx, httpClient)
if errProjects != nil { if errProjects != nil {
log.Fatalf("Failed to get project list: %v", errProjects) log.Errorf("Failed to get project list: %v", errProjects)
return return
} }
@@ -98,11 +98,11 @@ func DoLogin(cfg *config.Config, projectID string, options *LoginOptions) {
selectedProjectID := promptForProjectSelection(projects, strings.TrimSpace(projectID), promptFn) selectedProjectID := promptForProjectSelection(projects, strings.TrimSpace(projectID), promptFn)
projectSelections, errSelection := resolveProjectSelections(selectedProjectID, projects) projectSelections, errSelection := resolveProjectSelections(selectedProjectID, projects)
if errSelection != nil { if errSelection != nil {
log.Fatalf("Invalid project selection: %v", errSelection) log.Errorf("Invalid project selection: %v", errSelection)
return return
} }
if len(projectSelections) == 0 { if len(projectSelections) == 0 {
log.Fatal("No project selected; aborting login.") log.Error("No project selected; aborting login.")
return return
} }
@@ -116,7 +116,7 @@ func DoLogin(cfg *config.Config, projectID string, options *LoginOptions) {
showProjectSelectionHelp(storage.Email, projects) showProjectSelectionHelp(storage.Email, projects)
return return
} }
log.Fatalf("Failed to complete user setup: %v", errSetup) log.Errorf("Failed to complete user setup: %v", errSetup)
return return
} }
finalID := strings.TrimSpace(storage.ProjectID) finalID := strings.TrimSpace(storage.ProjectID)
@@ -133,11 +133,11 @@ func DoLogin(cfg *config.Config, projectID string, options *LoginOptions) {
for _, pid := range activatedProjects { for _, pid := range activatedProjects {
isChecked, errCheck := checkCloudAPIIsEnabled(ctx, httpClient, pid) isChecked, errCheck := checkCloudAPIIsEnabled(ctx, httpClient, pid)
if errCheck != nil { if errCheck != nil {
log.Fatalf("Failed to check if Cloud AI API is enabled for %s: %v", pid, errCheck) log.Errorf("Failed to check if Cloud AI API is enabled for %s: %v", pid, errCheck)
return return
} }
if !isChecked { if !isChecked {
log.Fatalf("Failed to check if Cloud AI API is enabled for project %s. If you encounter an error message, please create an issue.", pid) log.Errorf("Failed to check if Cloud AI API is enabled for project %s. If you encounter an error message, please create an issue.", pid)
return return
} }
} }
@@ -153,7 +153,7 @@ func DoLogin(cfg *config.Config, projectID string, options *LoginOptions) {
savedPath, errSave := store.Save(ctx, record) savedPath, errSave := store.Save(ctx, record)
if errSave != nil { if errSave != nil {
log.Fatalf("Failed to save token to file: %v", errSave) log.Errorf("Failed to save token to file: %v", errSave)
return return
} }
@@ -555,6 +555,7 @@ func checkCloudAPIIsEnabled(ctx context.Context, httpClient *http.Client, projec
continue continue
} }
} }
_ = resp.Body.Close()
return false, fmt.Errorf("project activation required: %s", errMessage) return false, fmt.Errorf("project activation required: %s", errMessage)
} }
return true, nil return true, nil

View File

@@ -45,12 +45,13 @@ func StartService(cfg *config.Config, configPath string, localPassword string) {
service, err := builder.Build() service, err := builder.Build()
if err != nil { if err != nil {
log.Fatalf("failed to build proxy service: %v", err) log.Errorf("failed to build proxy service: %v", err)
return
} }
err = service.Run(runCtx) err = service.Run(runCtx)
if err != nil && !errors.Is(err, context.Canceled) { if err != nil && !errors.Is(err, context.Canceled) {
log.Fatalf("proxy service exited with error: %v", err) log.Errorf("proxy service exited with error: %v", err)
} }
} }

View File

@@ -29,30 +29,30 @@ func DoVertexImport(cfg *config.Config, keyPath string) {
} }
rawPath := strings.TrimSpace(keyPath) rawPath := strings.TrimSpace(keyPath)
if rawPath == "" { if rawPath == "" {
log.Fatalf("vertex-import: missing service account key path") log.Errorf("vertex-import: missing service account key path")
return return
} }
data, errRead := os.ReadFile(rawPath) data, errRead := os.ReadFile(rawPath)
if errRead != nil { if errRead != nil {
log.Fatalf("vertex-import: read file failed: %v", errRead) log.Errorf("vertex-import: read file failed: %v", errRead)
return return
} }
var sa map[string]any var sa map[string]any
if errUnmarshal := json.Unmarshal(data, &sa); errUnmarshal != nil { if errUnmarshal := json.Unmarshal(data, &sa); errUnmarshal != nil {
log.Fatalf("vertex-import: invalid service account json: %v", errUnmarshal) log.Errorf("vertex-import: invalid service account json: %v", errUnmarshal)
return return
} }
// Validate and normalize private_key before saving // Validate and normalize private_key before saving
normalizedSA, errFix := vertex.NormalizeServiceAccountMap(sa) normalizedSA, errFix := vertex.NormalizeServiceAccountMap(sa)
if errFix != nil { if errFix != nil {
log.Fatalf("vertex-import: %v", errFix) log.Errorf("vertex-import: %v", errFix)
return return
} }
sa = normalizedSA sa = normalizedSA
email, _ := sa["client_email"].(string) email, _ := sa["client_email"].(string)
projectID, _ := sa["project_id"].(string) projectID, _ := sa["project_id"].(string)
if strings.TrimSpace(projectID) == "" { if strings.TrimSpace(projectID) == "" {
log.Fatalf("vertex-import: project_id missing in service account json") log.Errorf("vertex-import: project_id missing in service account json")
return return
} }
if strings.TrimSpace(email) == "" { if strings.TrimSpace(email) == "" {
@@ -92,7 +92,7 @@ func DoVertexImport(cfg *config.Config, keyPath string) {
} }
path, errSave := store.Save(context.Background(), record) path, errSave := store.Save(context.Background(), record)
if errSave != nil { if errSave != nil {
log.Fatalf("vertex-import: save credential failed: %v", errSave) log.Errorf("vertex-import: save credential failed: %v", errSave)
return return
} }
fmt.Printf("Vertex credentials imported: %s\n", path) fmt.Printf("Vertex credentials imported: %s\n", path)