From 8bd2921faca2edcf115eac53eda8b547dcb4ea9f Mon Sep 17 00:00:00 2001 From: Duologic Date: Fri, 3 Jul 2020 09:22:18 +0200 Subject: [PATCH 1/2] fix: don't panic when return is nil If the scrape fails, the return is nil for either project or regionList. We should not try to access project.Quotas or regionList.Items in that case. Bonus: Even if the regionList call fails, we can still return the project level results. fixes #8 --- main.go | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/main.go b/main.go index 6acfa6d..a377f1f 100644 --- a/main.go +++ b/main.go @@ -71,7 +71,7 @@ func (e *Exporter) scrape() (up float64, prj *compute.Project, rgl *compute.Regi regionList, err := e.service.Regions.List(e.project).Do() if err != nil { log.Errorf("Failure when querying region quotas: %v", err) - return 0, nil, nil + return 0, project, nil } return 1, project, regionList @@ -91,16 +91,20 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { up, project, regionList := e.scrape() - for _, quota := range project.Quotas { - ch <- prometheus.MustNewConstMetric(limitDesc, prometheus.GaugeValue, quota.Limit, e.project, "", quota.Metric) - ch <- prometheus.MustNewConstMetric(usageDesc, prometheus.GaugeValue, quota.Usage, e.project, "", quota.Metric) + if project != nil { + for _, quota := range project.Quotas { + ch <- prometheus.MustNewConstMetric(limitDesc, prometheus.GaugeValue, quota.Limit, e.project, "", quota.Metric) + ch <- prometheus.MustNewConstMetric(usageDesc, prometheus.GaugeValue, quota.Usage, e.project, "", quota.Metric) + } } - for _, region := range regionList.Items { - regionName := region.Name - for _, quota := range region.Quotas { - ch <- prometheus.MustNewConstMetric(limitDesc, prometheus.GaugeValue, quota.Limit, e.project, regionName, quota.Metric) - ch <- prometheus.MustNewConstMetric(usageDesc, prometheus.GaugeValue, quota.Usage, e.project, regionName, quota.Metric) + if regionList != nil { + for _, region := range regionList.Items { + regionName := region.Name + for _, quota := range region.Quotas { + ch <- prometheus.MustNewConstMetric(limitDesc, prometheus.GaugeValue, quota.Limit, e.project, regionName, quota.Metric) + ch <- prometheus.MustNewConstMetric(usageDesc, prometheus.GaugeValue, quota.Usage, e.project, regionName, quota.Metric) + } } } From 3359e03a8b6abc0142b5e49f2607ececa0a0f9bb Mon Sep 17 00:00:00 2001 From: Duologic Date: Fri, 3 Jul 2020 09:32:40 +0200 Subject: [PATCH 2/2] fix: NewExporter only takes project parameter --- main_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main_test.go b/main_test.go index 1eaf9ac..b279435 100644 --- a/main_test.go +++ b/main_test.go @@ -8,7 +8,7 @@ import ( func TestScrape(t *testing.T) { // TestSuccessfulConnection - exporter, _ := NewExporter("credentials.json", os.Getenv("GCP_PROJECT")) + exporter, _ := NewExporter(os.Getenv("GCP_PROJECT")) up, _, _ := exporter.scrape() if up == 0 { t.Errorf("TestSuccessfulConnection: up=%v, expected=1", up) @@ -16,7 +16,7 @@ func TestScrape(t *testing.T) { // TestFailedConnection // Set the project name to "503" since the Google Compute API will append this to the end of the BasePath - exporter, _ = NewExporter("credentials.json", "503") + exporter, _ = NewExporter("503") exporter.service.BasePath = "https://httpbin.org/status/" up, _, _ = exporter.scrape() if up != 0 {