From 4fae46f2726a8466bf0eb24414c05bc9ca477d68 Mon Sep 17 00:00:00 2001 From: Matt Wynne Date: Thu, 9 Apr 2026 16:35:57 -0700 Subject: [PATCH] Handle empty/incomplete gcloud config file When ~/.config/gcloud/configurations/config_default exists but is empty or missing the [core] section, return nil with a warning log instead of crashing. This lets the credential fallback chain continue. --- lib/goth/config.ex | 15 +++++++++-- .../home/gcloud/configurations/config_empty | 0 .../home/gcloud/configurations/config_no_core | 3 +++ test/goth/config_test.exs | 27 +++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test/data/home/gcloud/configurations/config_empty create mode 100644 test/data/home/gcloud/configurations/config_no_core diff --git a/lib/goth/config.ex b/lib/goth/config.ex index 82439dc..b945f77 100644 --- a/lib/goth/config.ex +++ b/lib/goth/config.ex @@ -235,8 +235,19 @@ defmodule Goth.Config do if File.regular?(configuration_file) do configuration_data = configuration_file |> File.read!() |> decode_ini() - # Only retrieve the required data. - %{"project_id" => configuration_data["core"]["project"], "actor_email" => configuration_data["core"]["account"]} + case configuration_data do + %{"core" => %{"project" => project, "account" => account}} -> + %{"project_id" => project, "actor_email" => account} + + _ -> + Logger.warning( + "Gcloud configuration file #{configuration_file} is missing " <> + "required [core] section with project and account settings. " <> + "Run 'gcloud init' or delete this file to resolve." + ) + + nil + end else nil end diff --git a/test/data/home/gcloud/configurations/config_empty b/test/data/home/gcloud/configurations/config_empty new file mode 100644 index 0000000..e69de29 diff --git a/test/data/home/gcloud/configurations/config_no_core b/test/data/home/gcloud/configurations/config_no_core new file mode 100644 index 0000000..97d3f15 --- /dev/null +++ b/test/data/home/gcloud/configurations/config_no_core @@ -0,0 +1,3 @@ +[compute] +zone = us-central1-c +region = us-central1 diff --git a/test/goth/config_test.exs b/test/goth/config_test.exs index 3b8b1b1..d314430 100644 --- a/test/goth/config_test.exs +++ b/test/goth/config_test.exs @@ -150,6 +150,33 @@ defmodule Goth.ConfigTest do Application.start(:goth) end + test "get_configuration_data returns nil for empty config file" do + import ExUnit.CaptureLog + + path = Path.expand("test/data/home/gcloud/configurations/config_empty") + + log = + capture_log(fn -> + assert Config.get_configuration_data(path) == nil + end) + + assert log =~ "missing required [core] section" + assert log =~ "Run 'gcloud init' or delete this file" + end + + test "get_configuration_data returns nil for config file missing [core] section" do + import ExUnit.CaptureLog + + path = Path.expand("test/data/home/gcloud/configurations/config_no_core") + + log = + capture_log(fn -> + assert Config.get_configuration_data(path) == nil + end) + + assert log =~ "missing required [core] section" + end + test "GOOGLE_APPLICATION_CREDENTIALS is read" do # The test configuration sets an example JSON blob. We override it briefly # during this test.