From ad9ff16fe99b858aceae1639d892d44b588891cb Mon Sep 17 00:00:00 2001 From: Alexey Basinov Date: Fri, 5 Apr 2024 09:50:29 -0700 Subject: [PATCH 1/5] Add support for Bare Metal Solution (BMS) machines --- detectors/gcp/bms.go | 53 ++++++++++++++++++++++ detectors/gcp/bms_test.go | 81 ++++++++++++++++++++++++++++++++++ detectors/gcp/detector.go | 3 ++ detectors/gcp/detector_test.go | 12 +++++ 4 files changed, 149 insertions(+) create mode 100644 detectors/gcp/bms.go create mode 100644 detectors/gcp/bms_test.go diff --git a/detectors/gcp/bms.go b/detectors/gcp/bms.go new file mode 100644 index 000000000..604ff45e4 --- /dev/null +++ b/detectors/gcp/bms.go @@ -0,0 +1,53 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gcp + +const ( + bmsProjectIDEnv = "BMS_PROJECT_ID" + bmsRegionEnv = "BMS_REGION" + bmsInstanceIDEnv = "BMS_INSTANCE_ID" +) + +// Use BMS_PROJECT_ID, BMS_REGION and BMS_INSTANCE_ID env vars as an indication that we are running on BMS. +func (d *Detector) onBMS() bool { + projectID, projectIDExists := d.os.LookupEnv(bmsProjectIDEnv) + region, regionExists := d.os.LookupEnv(bmsRegionEnv) + instanceID, instanceIDExists := d.os.LookupEnv(bmsInstanceIDEnv) + return projectIDExists && regionExists && instanceIDExists && projectID != "" && region != "" && instanceID != "" +} + +// BMSInstanceID returns the instance ID from the BMS_INSTANCE_ID environment variable. +func (d *Detector) BMSInstanceID() (string, error) { + if instanceID, found := d.os.LookupEnv(bmsInstanceIDEnv); found { + return instanceID, nil + } + return "", errEnvVarNotFound +} + +// BMSCloudRegion returns the region from the BMS_REGION environment variable. +func (d *Detector) BMSCloudRegion() (string, error) { + if region, found := d.os.LookupEnv(bmsRegionEnv); found { + return region, nil + } + return "", errEnvVarNotFound +} + +// BMSProjectID returns the project ID from the BMS_PROJECT_ID environment variable. +func (d *Detector) BMSProjectID() (string, error) { + if project, found := d.os.LookupEnv(bmsProjectIDEnv); found { + return project, nil + } + return "", errEnvVarNotFound +} diff --git a/detectors/gcp/bms_test.go b/detectors/gcp/bms_test.go new file mode 100644 index 000000000..6b494c7e4 --- /dev/null +++ b/detectors/gcp/bms_test.go @@ -0,0 +1,81 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gcp + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBMSInstanceID(t *testing.T) { + d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ + Vars: map[string]string{ + bmsInstanceIDEnv: "my-host-123", + }, + }) + instanceID, err := d.BMSInstanceID() + assert.NoError(t, err) + assert.Equal(t, instanceID, "my-host-123") +} + +func TestBMSInstanceIDErr(t *testing.T) { + d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ + Vars: map[string]string{}, + }) + instanceID, err := d.BMSInstanceID() + assert.Error(t, err) + assert.Equal(t, instanceID, "") +} + +func TestBMSBMSCloudRegion(t *testing.T) { + d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ + Vars: map[string]string{ + bmsRegionEnv: "us-central1", + }, + }) + region, err := d.BMSCloudRegion() + assert.NoError(t, err) + assert.Equal(t, region, "us-central1") +} + +func TestBMSCloudRegionErr(t *testing.T) { + d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ + Vars: map[string]string{}, + }) + region, err := d.BMSCloudRegion() + assert.Error(t, err) + assert.Equal(t, region, "") +} + +func TestBMSBMSProjectID(t *testing.T) { + d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ + Vars: map[string]string{ + bmsProjectIDEnv: "my-test-project", + }, + }) + projectID, err := d.BMSProjectID() + assert.NoError(t, err) + assert.Equal(t, projectID, "my-test-project") +} + +func TestBMSProjectIDErr(t *testing.T) { + d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ + Vars: map[string]string{}, + }) + projectID, err := d.BMSProjectID() + assert.Error(t, err) + assert.Equal(t, projectID, "") +} diff --git a/detectors/gcp/detector.go b/detectors/gcp/detector.go index 372621553..57eab9b46 100644 --- a/detectors/gcp/detector.go +++ b/detectors/gcp/detector.go @@ -40,11 +40,14 @@ const ( CloudFunctions AppEngineStandard AppEngineFlex + BMS ) // CloudPlatform returns the platform on which this program is running. func (d *Detector) CloudPlatform() Platform { switch { + case d.onBMS(): + return BMS case d.onGKE(): return GKE case d.onCloudFunctions(): diff --git a/detectors/gcp/detector_test.go b/detectors/gcp/detector_test.go index a513ba742..cdaabf1c8 100644 --- a/detectors/gcp/detector_test.go +++ b/detectors/gcp/detector_test.go @@ -90,6 +90,18 @@ func TestCloudPlatformCloudFunctions(t *testing.T) { assert.Equal(t, platform, CloudFunctions) } +func TestCloudPlatformBMS(t *testing.T) { + d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ + Vars: map[string]string{ + bmsInstanceIDEnv: "foo", + bmsProjectIDEnv: "bar", + bmsRegionEnv: "qux", + }, + }) + platform := d.CloudPlatform() + assert.Equal(t, platform, BMS) +} + func TestProjectID(t *testing.T) { d := NewTestDetector(&FakeMetadataProvider{ Project: "my-project", From f7c083823206742e9fadf412dc392bb308631151 Mon Sep 17 00:00:00 2001 From: Alexey Basinov Date: Fri, 5 Apr 2024 15:22:05 -0700 Subject: [PATCH 2/5] Update copyright year to 2024 --- detectors/gcp/bms.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/gcp/bms.go b/detectors/gcp/bms.go index 604ff45e4..122728227 100644 --- a/detectors/gcp/bms.go +++ b/detectors/gcp/bms.go @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From 623589779a378c96171f7da701d35b269fd62da9 Mon Sep 17 00:00:00 2001 From: Alexey Basinov Date: Fri, 5 Apr 2024 15:23:11 -0700 Subject: [PATCH 3/5] Update copyright year for bms_test.go --- detectors/gcp/gce_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/gcp/gce_test.go b/detectors/gcp/gce_test.go index bcf0b8d97..50d61f436 100644 --- a/detectors/gcp/gce_test.go +++ b/detectors/gcp/gce_test.go @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From c1108e5a52497a4d0ace9f1024f7bc8042e1fe6e Mon Sep 17 00:00:00 2001 From: Alexey Basinov Date: Fri, 5 Apr 2024 15:24:53 -0700 Subject: [PATCH 4/5] Update copyright year attempt #2 --- detectors/gcp/bms_test.go | 2 +- detectors/gcp/gce_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/detectors/gcp/bms_test.go b/detectors/gcp/bms_test.go index 6b494c7e4..c67729c17 100644 --- a/detectors/gcp/bms_test.go +++ b/detectors/gcp/bms_test.go @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/detectors/gcp/gce_test.go b/detectors/gcp/gce_test.go index 50d61f436..bcf0b8d97 100644 --- a/detectors/gcp/gce_test.go +++ b/detectors/gcp/gce_test.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From f33e99e3ea20401bcdf9449a7a1db488aa254c01 Mon Sep 17 00:00:00 2001 From: Alexey Basinov Date: Wed, 24 Apr 2024 16:15:06 -0700 Subject: [PATCH 5/5] Expand BMS abbreviation to Bare Metal Solution --- detectors/gcp/bms.go | 18 ++++++++++-------- detectors/gcp/bms_test.go | 24 ++++++++++++------------ detectors/gcp/detector.go | 6 +++--- detectors/gcp/detector_test.go | 4 ++-- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/detectors/gcp/bms.go b/detectors/gcp/bms.go index 122728227..d3992a4f7 100644 --- a/detectors/gcp/bms.go +++ b/detectors/gcp/bms.go @@ -20,32 +20,34 @@ const ( bmsInstanceIDEnv = "BMS_INSTANCE_ID" ) -// Use BMS_PROJECT_ID, BMS_REGION and BMS_INSTANCE_ID env vars as an indication that we are running on BMS. -func (d *Detector) onBMS() bool { +// onBareMetalSolution checks if the code is running on a Google Cloud Bare Metal Solution (BMS) by verifying +// the presence and non-empty values of BMS_PROJECT_ID, BMS_REGION, and BMS_INSTANCE_ID environment variables. +// For more information on Google Cloud Bare Metal Solution, see: https://cloud.google.com/bare-metal/docs +func (d *Detector) onBareMetalSolution() bool { projectID, projectIDExists := d.os.LookupEnv(bmsProjectIDEnv) region, regionExists := d.os.LookupEnv(bmsRegionEnv) instanceID, instanceIDExists := d.os.LookupEnv(bmsInstanceIDEnv) return projectIDExists && regionExists && instanceIDExists && projectID != "" && region != "" && instanceID != "" } -// BMSInstanceID returns the instance ID from the BMS_INSTANCE_ID environment variable. -func (d *Detector) BMSInstanceID() (string, error) { +// BareMetalSolutionInstanceID returns the instance ID from the BMS_INSTANCE_ID environment variable. +func (d *Detector) BareMetalSolutionInstanceID() (string, error) { if instanceID, found := d.os.LookupEnv(bmsInstanceIDEnv); found { return instanceID, nil } return "", errEnvVarNotFound } -// BMSCloudRegion returns the region from the BMS_REGION environment variable. -func (d *Detector) BMSCloudRegion() (string, error) { +// BareMetalSolutionCloudRegion returns the region from the BMS_REGION environment variable. +func (d *Detector) BareMetalSolutionCloudRegion() (string, error) { if region, found := d.os.LookupEnv(bmsRegionEnv); found { return region, nil } return "", errEnvVarNotFound } -// BMSProjectID returns the project ID from the BMS_PROJECT_ID environment variable. -func (d *Detector) BMSProjectID() (string, error) { +// BareMetalSolutionProjectID returns the project ID from the BMS_PROJECT_ID environment variable. +func (d *Detector) BareMetalSolutionProjectID() (string, error) { if project, found := d.os.LookupEnv(bmsProjectIDEnv); found { return project, nil } diff --git a/detectors/gcp/bms_test.go b/detectors/gcp/bms_test.go index c67729c17..1ea3485e4 100644 --- a/detectors/gcp/bms_test.go +++ b/detectors/gcp/bms_test.go @@ -20,62 +20,62 @@ import ( "github.com/stretchr/testify/assert" ) -func TestBMSInstanceID(t *testing.T) { +func TestBareMetalSolutionInstanceID(t *testing.T) { d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ Vars: map[string]string{ bmsInstanceIDEnv: "my-host-123", }, }) - instanceID, err := d.BMSInstanceID() + instanceID, err := d.BareMetalSolutionInstanceID() assert.NoError(t, err) assert.Equal(t, instanceID, "my-host-123") } -func TestBMSInstanceIDErr(t *testing.T) { +func TestBareMetalSolutionInstanceIDErr(t *testing.T) { d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ Vars: map[string]string{}, }) - instanceID, err := d.BMSInstanceID() + instanceID, err := d.BareMetalSolutionInstanceID() assert.Error(t, err) assert.Equal(t, instanceID, "") } -func TestBMSBMSCloudRegion(t *testing.T) { +func TestBareMetalSolutionCloudRegion(t *testing.T) { d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ Vars: map[string]string{ bmsRegionEnv: "us-central1", }, }) - region, err := d.BMSCloudRegion() + region, err := d.BareMetalSolutionCloudRegion() assert.NoError(t, err) assert.Equal(t, region, "us-central1") } -func TestBMSCloudRegionErr(t *testing.T) { +func TestBareMetalSolutionCloudRegionErr(t *testing.T) { d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ Vars: map[string]string{}, }) - region, err := d.BMSCloudRegion() + region, err := d.BareMetalSolutionCloudRegion() assert.Error(t, err) assert.Equal(t, region, "") } -func TestBMSBMSProjectID(t *testing.T) { +func TestBareMetalSolutionProjectID(t *testing.T) { d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ Vars: map[string]string{ bmsProjectIDEnv: "my-test-project", }, }) - projectID, err := d.BMSProjectID() + projectID, err := d.BareMetalSolutionProjectID() assert.NoError(t, err) assert.Equal(t, projectID, "my-test-project") } -func TestBMSProjectIDErr(t *testing.T) { +func TestBareMetalSolutionProjectIDErr(t *testing.T) { d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ Vars: map[string]string{}, }) - projectID, err := d.BMSProjectID() + projectID, err := d.BareMetalSolutionProjectID() assert.Error(t, err) assert.Equal(t, projectID, "") } diff --git a/detectors/gcp/detector.go b/detectors/gcp/detector.go index 57eab9b46..2cc62de09 100644 --- a/detectors/gcp/detector.go +++ b/detectors/gcp/detector.go @@ -40,14 +40,14 @@ const ( CloudFunctions AppEngineStandard AppEngineFlex - BMS + BareMetalSolution ) // CloudPlatform returns the platform on which this program is running. func (d *Detector) CloudPlatform() Platform { switch { - case d.onBMS(): - return BMS + case d.onBareMetalSolution(): + return BareMetalSolution case d.onGKE(): return GKE case d.onCloudFunctions(): diff --git a/detectors/gcp/detector_test.go b/detectors/gcp/detector_test.go index cdaabf1c8..4008e0835 100644 --- a/detectors/gcp/detector_test.go +++ b/detectors/gcp/detector_test.go @@ -90,7 +90,7 @@ func TestCloudPlatformCloudFunctions(t *testing.T) { assert.Equal(t, platform, CloudFunctions) } -func TestCloudPlatformBMS(t *testing.T) { +func TestCloudPlatformBareMetalSolution(t *testing.T) { d := NewTestDetector(&FakeMetadataProvider{}, &FakeOSProvider{ Vars: map[string]string{ bmsInstanceIDEnv: "foo", @@ -99,7 +99,7 @@ func TestCloudPlatformBMS(t *testing.T) { }, }) platform := d.CloudPlatform() - assert.Equal(t, platform, BMS) + assert.Equal(t, platform, BareMetalSolution) } func TestProjectID(t *testing.T) {