diff --git a/CHANGELOG.md b/CHANGELOG.md index 097640f605ea..b3203ba3ff24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,10 @@ ## Unreleased -## 🛑 Breaking changes 🛑 +### 🛑 Breaking changes 🛑 + +- `jmxreceiver`: Remove properties & groovyscript parameters from JMX Receiver. Add ResourceAttributes & LogLevel parameter to supply some of the removed functionality with reduced attack surface (#9685) +- `resourcedetectionprocessor`: 'gke' and 'gce' resource detectors are replaced with a single 'gcp' detector (#10347) ### 🚩 Deprecations 🚩 @@ -17,6 +20,7 @@ ### 🧰 Bug fixes 🧰 - `tanzuobservabilityexporter`: Improve how negative values in exponential histograms are handled. (#10135) +- `resourcedetectionprocessor`: GCP resource detector now properly detects zone/region on GKE (#10347) ## v0.52.0 diff --git a/cmd/configschema/go.mod b/cmd/configschema/go.mod index 5bdb085428c9..48674e454a5e 100644 --- a/cmd/configschema/go.mod +++ b/cmd/configschema/go.mod @@ -45,6 +45,7 @@ require ( github.com/DataDog/datadog-go v4.8.2+incompatible // indirect github.com/DataDog/sketches-go v1.4.1 // indirect github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector v0.30.2-0.20220512190557-875976f87023 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.6.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.30.1 // indirect diff --git a/cmd/configschema/go.sum b/cmd/configschema/go.sum index c6f6b120f271..e5af0286ae13 100644 --- a/cmd/configschema/go.sum +++ b/cmd/configschema/go.sum @@ -165,6 +165,8 @@ github.com/DataDog/zstd v1.5.0 h1:+K/VEwIAaPcHiMtQvpLD4lqW7f0Gk3xdYZmI1hD+CXo= github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 h1:KeNholpO2xKjgaaSyd+DyQRrsQjhbSeS7qe4nEw8aQw= github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962/go.mod h1:kC29dT1vFpj7py2OvG1khBdQpo3kInWP+6QipLbdngo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.31.0 h1:EnFLvwFv8onlnjYFSrQ4EMSm6uWRBZHOItR/Tz0Jnqk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.31.0/go.mod h1:s7Gpwj0tk7XnVCm4BQEmx/mbS36SuTCY/vMB2SNxe8o= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector v0.30.2-0.20220512190557-875976f87023 h1:a5qaC/K40oknHppvTFqQZkLMY7XZSvWyxcG/T6W6DF8= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector v0.30.2-0.20220512190557-875976f87023/go.mod h1:kXt5P2nDYWk6ltkQi+YmcGCNMwS54nnYfLm8jrU0APk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.6.1 h1:LNl8Tg6N6qChoiM6lKC1Z44Z+CkPAdYx45L/lJDgThs= diff --git a/go.mod b/go.mod index 3028f0192192..9eb045eb1354 100644 --- a/go.mod +++ b/go.mod @@ -176,6 +176,7 @@ require ( github.com/DataDog/datadog-go v4.8.2+incompatible // indirect github.com/DataDog/sketches-go v1.4.1 // indirect github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector v0.30.2-0.20220512190557-875976f87023 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.6.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.30.1 // indirect diff --git a/go.sum b/go.sum index 28eb9ba46ab2..c91ec65f0834 100644 --- a/go.sum +++ b/go.sum @@ -165,6 +165,8 @@ github.com/DataDog/zstd v1.5.0 h1:+K/VEwIAaPcHiMtQvpLD4lqW7f0Gk3xdYZmI1hD+CXo= github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 h1:KeNholpO2xKjgaaSyd+DyQRrsQjhbSeS7qe4nEw8aQw= github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962/go.mod h1:kC29dT1vFpj7py2OvG1khBdQpo3kInWP+6QipLbdngo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.31.0 h1:EnFLvwFv8onlnjYFSrQ4EMSm6uWRBZHOItR/Tz0Jnqk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.31.0/go.mod h1:s7Gpwj0tk7XnVCm4BQEmx/mbS36SuTCY/vMB2SNxe8o= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector v0.30.2-0.20220512190557-875976f87023 h1:a5qaC/K40oknHppvTFqQZkLMY7XZSvWyxcG/T6W6DF8= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector v0.30.2-0.20220512190557-875976f87023/go.mod h1:kXt5P2nDYWk6ltkQi+YmcGCNMwS54nnYfLm8jrU0APk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.6.1 h1:LNl8Tg6N6qChoiM6lKC1Z44Z+CkPAdYx45L/lJDgThs= diff --git a/processor/resourcedetectionprocessor/factory.go b/processor/resourcedetectionprocessor/factory.go index dc3f76176638..706adc4896a0 100644 --- a/processor/resourcedetectionprocessor/factory.go +++ b/processor/resourcedetectionprocessor/factory.go @@ -36,8 +36,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/consul" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/docker" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/env" - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp/gce" - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp/gke" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/system" ) @@ -69,8 +68,10 @@ func NewFactory() component.ProcessorFactory { eks.TypeStr: eks.NewDetector, elasticbeanstalk.TypeStr: elasticbeanstalk.NewDetector, env.TypeStr: env.NewDetector, - gce.TypeStr: gce.NewDetector, - gke.TypeStr: gke.NewDetector, + gcp.TypeStr: gcp.NewDetector, + // TODO(#10348): Remove GKE and GCE after the v0.54.0 release. + gcp.DeprecatedGKETypeStr: gcp.NewDetector, + gcp.DeprecatedGCETypeStr: gcp.NewDetector, system.TypeStr: system.NewDetector, }) @@ -201,6 +202,9 @@ func (f *factory) getResourceProvider( return provider, nil } + // TODO(#10348): Remove this after the v0.54.0 release. + configuredDetectors = gcp.DeduplicateDetectors(params, configuredDetectors) + detectorTypes := make([]internal.DetectorType, 0, len(configuredDetectors)) for _, key := range configuredDetectors { detectorTypes = append(detectorTypes, internal.DetectorType(strings.TrimSpace(key))) diff --git a/processor/resourcedetectionprocessor/go.mod b/processor/resourcedetectionprocessor/go.mod index 60fa845fabc9..c7200952970a 100644 --- a/processor/resourcedetectionprocessor/go.mod +++ b/processor/resourcedetectionprocessor/go.mod @@ -4,6 +4,7 @@ go 1.17 require ( cloud.google.com/go/compute v1.6.1 + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.31.0 github.com/Showmax/go-fqdn v1.0.0 github.com/aws/aws-sdk-go v1.44.20 github.com/census-instrumentation/opencensus-proto v0.3.0 diff --git a/processor/resourcedetectionprocessor/go.sum b/processor/resourcedetectionprocessor/go.sum index b37e4ce5d5ba..d574ec8071a3 100644 --- a/processor/resourcedetectionprocessor/go.sum +++ b/processor/resourcedetectionprocessor/go.sum @@ -63,6 +63,8 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.31.0 h1:EnFLvwFv8onlnjYFSrQ4EMSm6uWRBZHOItR/Tz0Jnqk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.31.0/go.mod h1:s7Gpwj0tk7XnVCm4BQEmx/mbS36SuTCY/vMB2SNxe8o= github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= diff --git a/processor/resourcedetectionprocessor/internal/gcp/gce/gce.go b/processor/resourcedetectionprocessor/internal/gcp/gce/gce.go deleted file mode 100644 index 2b137845ed9c..000000000000 --- a/processor/resourcedetectionprocessor/internal/gcp/gce/gce.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// 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 -// -// http://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 gce provides a detector that loads resource information from -// the GCE metatdata -package gce // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp/gce" - -import ( - "context" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/pdata/pcommon" - conventions "go.opentelemetry.io/collector/semconv/v1.6.1" - "go.uber.org/multierr" - - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" -) - -// TypeStr is type of detector. -const TypeStr = "gce" - -var _ internal.Detector = (*Detector)(nil) - -type Detector struct { - metadata gcp.Metadata -} - -func NewDetector(component.ProcessorCreateSettings, internal.DetectorConfig) (internal.Detector, error) { - return &Detector{metadata: &gcp.MetadataImpl{}}, nil -} - -func (d *Detector) Detect(context.Context) (resource pcommon.Resource, schemaURL string, err error) { - res := pcommon.NewResource() - - if !d.metadata.OnGCE() { - return res, "", nil - } - - attr := res.Attributes() - cloudErr := multierr.Combine(d.initializeCloudAttributes(attr)...) - hostErr := multierr.Combine(d.initializeHostAttributes(attr)...) - return res, conventions.SchemaURL, multierr.Append(cloudErr, hostErr) -} - -func (d *Detector) initializeCloudAttributes(attr pcommon.Map) []error { - attr.InsertString(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderGCP) - attr.InsertString(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPComputeEngine) - - var errors []error - - projectID, err := d.metadata.ProjectID() - if err != nil { - errors = append(errors, err) - } else { - attr.InsertString(conventions.AttributeCloudAccountID, projectID) - } - - zone, err := d.metadata.Zone() - if err != nil { - errors = append(errors, err) - } else { - attr.InsertString(conventions.AttributeCloudAvailabilityZone, zone) - } - - return errors -} - -func (d *Detector) initializeHostAttributes(attr pcommon.Map) []error { - var errors []error - - hostname, err := d.metadata.Hostname() - if err != nil { - errors = append(errors, err) - } else { - attr.InsertString(conventions.AttributeHostName, hostname) - } - - instanceID, err := d.metadata.InstanceID() - if err != nil { - errors = append(errors, err) - } else { - attr.InsertString(conventions.AttributeHostID, instanceID) - } - - hostType, err := d.metadata.Get("instance/machine-type") - if err != nil { - errors = append(errors, err) - } else { - attr.InsertString(conventions.AttributeHostType, hostType) - } - - return errors -} diff --git a/processor/resourcedetectionprocessor/internal/gcp/gce/gce_test.go b/processor/resourcedetectionprocessor/internal/gcp/gce/gce_test.go deleted file mode 100644 index 789a11602bee..000000000000 --- a/processor/resourcedetectionprocessor/internal/gcp/gce/gce_test.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// 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 -// -// http://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 gce - -import ( - "context" - "errors" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.opentelemetry.io/collector/component/componenttest" - conventions "go.opentelemetry.io/collector/semconv/v1.6.1" - - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" -) - -func TestNewDetector(t *testing.T) { - d, err := NewDetector(componenttest.NewNopProcessorCreateSettings(), nil) - assert.NotNil(t, d) - assert.NoError(t, err) -} - -func TestDetectTrue(t *testing.T) { - md := &gcp.MockMetadata{} - md.On("OnGCE").Return(true) - md.On("ProjectID").Return("1", nil) - md.On("Zone").Return("zone", nil) - md.On("Hostname").Return("hostname", nil) - md.On("InstanceID").Return("2", nil) - md.On("InstanceName").Return("name", nil) - md.On("Get", "instance/machine-type").Return("machine-type", nil) - - detector := &Detector{metadata: md} - res, schemaURL, err := detector.Detect(context.Background()) - - require.NoError(t, err) - assert.Equal(t, conventions.SchemaURL, schemaURL) - - expected := internal.NewResource(map[string]interface{}{ - conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, - conventions.AttributeCloudPlatform: conventions.AttributeCloudPlatformGCPComputeEngine, - conventions.AttributeCloudAccountID: "1", - conventions.AttributeCloudAvailabilityZone: "zone", - - conventions.AttributeHostID: "2", - conventions.AttributeHostName: "hostname", - conventions.AttributeHostType: "machine-type", - }) - - res.Attributes().Sort() - expected.Attributes().Sort() - assert.Equal(t, expected, res) -} - -func TestDetectFalse(t *testing.T) { - md := &gcp.MockMetadata{} - md.On("OnGCE").Return(false) - - detector := &Detector{metadata: md} - res, _, err := detector.Detect(context.Background()) - - require.NoError(t, err) - assert.True(t, internal.IsEmptyResource(res)) -} - -func TestDetectError(t *testing.T) { - md := &gcp.MockMetadata{} - md.On("OnGCE").Return(true) - md.On("ProjectID").Return("", errors.New("err1")) - md.On("Zone").Return("", errors.New("err2")) - md.On("Hostname").Return("", errors.New("err3")) - md.On("InstanceID").Return("", errors.New("err4")) - md.On("InstanceName").Return("", errors.New("err5")) - md.On("Get", "instance/machine-type").Return("", errors.New("err6")) - - detector := &Detector{metadata: md} - res, _, err := detector.Detect(context.Background()) - - assert.EqualError(t, err, "err1; err2; err3; err4; err6") - - expected := internal.NewResource(map[string]interface{}{ - conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, - conventions.AttributeCloudPlatform: conventions.AttributeCloudPlatformGCPComputeEngine, - }) - - res.Attributes().Sort() - expected.Attributes().Sort() - assert.Equal(t, expected, res) -} diff --git a/processor/resourcedetectionprocessor/internal/gcp/gcp.go b/processor/resourcedetectionprocessor/internal/gcp/gcp.go new file mode 100644 index 000000000000..0ab73e86a3d7 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/gcp/gcp.go @@ -0,0 +1,166 @@ +// Copyright The OpenTelemetry Authors +// +// 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 +// +// http://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 "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" + +import ( + "context" + "fmt" + + "cloud.google.com/go/compute/metadata" + "github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/pdata/pcommon" + conventions "go.opentelemetry.io/collector/semconv/v1.6.1" + "go.uber.org/multierr" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" +) + +const ( + // TypeStr is type of detector. + TypeStr = "gcp" + // 'gke' and 'gce' detectors are replaced with the unified 'gcp' detector + // TODO(#10348): Remove these after the v0.54.0 release. + DeprecatedGKETypeStr = "gke" + DeprecatedGCETypeStr = "gce" +) + +// NewDetector returns a detector which can detect resource attributes on: +// * Google Compute Engine (GCE). +// * Google Kubernetes Engine (GKE). +// * Google App Engine (GAE). +// * Cloud Run. +// * Cloud Functions. +func NewDetector(_ component.ProcessorCreateSettings, _ internal.DetectorConfig) (internal.Detector, error) { + return &detector{detector: gcp.NewDetector()}, nil +} + +type detector struct { + detector gcpDetector +} + +func (d *detector) Detect(context.Context) (resource pcommon.Resource, schemaURL string, err error) { + res := pcommon.NewResource() + if !metadata.OnGCE() { + return res, "", nil + } + b := &resourceBuilder{attrs: res.Attributes()} + b.attrs.InsertString(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderGCP) + b.add(conventions.AttributeCloudAccountID, d.detector.ProjectID) + + switch d.detector.CloudPlatform() { + case gcp.GKE: + b.attrs.InsertString(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPKubernetesEngine) + b.addZoneOrRegion(d.detector.GKEAvailabilityZoneOrRegion) + b.add(conventions.AttributeK8SClusterName, d.detector.GKEClusterName) + b.add(conventions.AttributeHostID, d.detector.GKEHostID) + b.add(conventions.AttributeHostName, d.detector.GKEHostName) + case gcp.CloudRun: + b.attrs.InsertString(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPCloudRun) + b.add(conventions.AttributeFaaSName, d.detector.FaaSName) + b.add(conventions.AttributeFaaSVersion, d.detector.FaaSVersion) + b.add(conventions.AttributeFaaSID, d.detector.FaaSID) + b.add(conventions.AttributeCloudRegion, d.detector.FaaSCloudRegion) + case gcp.CloudFunctions: + b.attrs.InsertString(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPCloudFunctions) + b.add(conventions.AttributeFaaSName, d.detector.FaaSName) + b.add(conventions.AttributeFaaSVersion, d.detector.FaaSVersion) + b.add(conventions.AttributeFaaSID, d.detector.FaaSID) + b.add(conventions.AttributeCloudRegion, d.detector.FaaSCloudRegion) + case gcp.AppEngine: + b.attrs.InsertString(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPAppEngine) + b.addZoneAndRegion(d.detector.AppEngineAvailabilityZoneAndRegion) + b.add(conventions.AttributeFaaSName, d.detector.AppEngineServiceName) + b.add(conventions.AttributeFaaSVersion, d.detector.AppEngineServiceVersion) + b.add(conventions.AttributeFaaSID, d.detector.AppEngineServiceInstance) + case gcp.GCE: + b.attrs.InsertString(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPComputeEngine) + b.addZoneAndRegion(d.detector.GCEAvailabilityZoneAndRegion) + b.add(conventions.AttributeHostType, d.detector.GCEHostType) + b.add(conventions.AttributeHostID, d.detector.GCEHostID) + b.add(conventions.AttributeHostName, d.detector.GCEHostName) + default: + // We don't support this platform yet, so just return with what we have + } + return res, conventions.SchemaURL, multierr.Combine(b.errs...) +} + +// resourceBuilder simplifies constructing resources using GCP detection +// library functions. +type resourceBuilder struct { + errs []error + attrs pcommon.Map +} + +func (r *resourceBuilder) add(key string, detect func() (string, error)) { + if v, err := detect(); err == nil { + r.attrs.InsertString(key, v) + } else { + r.errs = append(r.errs, err) + } +} + +// zoneAndRegion functions are expected to return zone, region, err. +func (r *resourceBuilder) addZoneAndRegion(detect func() (string, string, error)) { + if zone, region, err := detect(); err == nil { + r.attrs.InsertString(conventions.AttributeCloudAvailabilityZone, zone) + r.attrs.InsertString(conventions.AttributeCloudRegion, region) + } else { + r.errs = append(r.errs, err) + } +} + +func (r *resourceBuilder) addZoneOrRegion(detect func() (string, gcp.LocationType, error)) { + if v, locType, err := detect(); err == nil { + switch locType { + case gcp.Zone: + r.attrs.InsertString(conventions.AttributeCloudAvailabilityZone, v) + case gcp.Region: + r.attrs.InsertString(conventions.AttributeCloudRegion, v) + default: + r.errs = append(r.errs, fmt.Errorf("location must be zone or region. Got %v", locType)) + } + } else { + r.errs = append(r.errs, err) + } +} + +// DeduplicateDetectors ensures only one of ['gcp','gke','gce'] are present in +// the list of detectors. Currently, users configure both GCE and GKE detectors +// when running on GKE. Resource merge would fail in this case if we don't +// deduplicate, which would break users. +// TODO(#10348): Remove this function after the v0.54.0 release. +func DeduplicateDetectors(set component.ProcessorCreateSettings, detectors []string) []string { + out := []string{} + var found bool + for _, d := range detectors { + switch d { + case DeprecatedGKETypeStr: + set.Logger.Warn("The 'gke' detector is deprecated. Use the 'gcp' detector instead.") + case DeprecatedGCETypeStr: + set.Logger.Warn("The 'gce' detector is deprecated. Use the 'gcp' detector instead.") + case TypeStr: + default: + out = append(out, d) + continue + } + // ensure we only keep the first GCP detector we find. + if !found { + found = true + out = append(out, d) + } + } + return out +} diff --git a/processor/resourcedetectionprocessor/internal/gcp/gcp_test.go b/processor/resourcedetectionprocessor/internal/gcp/gcp_test.go new file mode 100644 index 000000000000..4d52aa88f4a0 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/gcp/gcp_test.go @@ -0,0 +1,397 @@ +// Copyright The OpenTelemetry Authors +// +// 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 +// +// http://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 "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" + +import ( + "context" + "fmt" + "os" + "testing" + + "github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp" + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/pdata/pcommon" + conventions "go.opentelemetry.io/collector/semconv/v1.6.1" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" +) + +func TestDetect(t *testing.T) { + // Set this before all tests to ensure metadata.onGCE() returns true + err := os.Setenv("GCE_METADATA_HOST", "169.254.169.254") + assert.NoError(t, err) + + for _, tc := range []struct { + desc string + detector internal.Detector + expectErr bool + expectedResource pcommon.Resource + }{ + { + desc: "zonal GKE cluster", + detector: &detector{detector: &fakeGCPDetector{ + projectID: "my-project", + cloudPlatform: gcp.GKE, + gkeHostID: "1472385723456792345", + gkeHostName: "my-gke-node-1234", + gkeClusterName: "my-cluster", + gkeAvailabilityZone: "us-central1-c", + }}, + expectedResource: internal.NewResource(map[string]interface{}{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, + conventions.AttributeCloudAccountID: "my-project", + conventions.AttributeCloudPlatform: conventions.AttributeCloudPlatformGCPKubernetesEngine, + conventions.AttributeK8SClusterName: "my-cluster", + conventions.AttributeCloudAvailabilityZone: "us-central1-c", + conventions.AttributeHostID: "1472385723456792345", + conventions.AttributeHostName: "my-gke-node-1234", + }), + }, + { + desc: "regional GKE cluster", + detector: &detector{detector: &fakeGCPDetector{ + projectID: "my-project", + cloudPlatform: gcp.GKE, + gkeHostID: "1472385723456792345", + gkeHostName: "my-gke-node-1234", + gkeClusterName: "my-cluster", + gkeRegion: "us-central1", + }}, + expectedResource: internal.NewResource(map[string]interface{}{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, + conventions.AttributeCloudAccountID: "my-project", + conventions.AttributeCloudPlatform: conventions.AttributeCloudPlatformGCPKubernetesEngine, + conventions.AttributeK8SClusterName: "my-cluster", + conventions.AttributeCloudRegion: "us-central1", + conventions.AttributeHostID: "1472385723456792345", + conventions.AttributeHostName: "my-gke-node-1234", + }), + }, + { + desc: "GCE", + detector: &detector{detector: &fakeGCPDetector{ + projectID: "my-project", + cloudPlatform: gcp.GCE, + gceHostID: "1472385723456792345", + gceHostName: "my-gke-node-1234", + gceHostType: "n1-standard1", + gceAvailabilityZone: "us-central1-c", + gceRegion: "us-central1", + }}, + expectedResource: internal.NewResource(map[string]interface{}{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, + conventions.AttributeCloudAccountID: "my-project", + conventions.AttributeCloudPlatform: conventions.AttributeCloudPlatformGCPComputeEngine, + conventions.AttributeHostID: "1472385723456792345", + conventions.AttributeHostName: "my-gke-node-1234", + conventions.AttributeHostType: "n1-standard1", + conventions.AttributeCloudRegion: "us-central1", + conventions.AttributeCloudAvailabilityZone: "us-central1-c", + }), + }, + { + desc: "Cloud Run", + detector: &detector{detector: &fakeGCPDetector{ + projectID: "my-project", + cloudPlatform: gcp.CloudRun, + faaSID: "1472385723456792345", + faaSCloudRegion: "us-central1", + faaSName: "my-service", + faaSVersion: "123456", + }}, + expectedResource: internal.NewResource(map[string]interface{}{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, + conventions.AttributeCloudAccountID: "my-project", + conventions.AttributeCloudPlatform: conventions.AttributeCloudPlatformGCPCloudRun, + conventions.AttributeCloudRegion: "us-central1", + conventions.AttributeFaaSName: "my-service", + conventions.AttributeFaaSVersion: "123456", + conventions.AttributeFaaSID: "1472385723456792345", + }), + }, + { + desc: "Cloud Functions", + detector: &detector{detector: &fakeGCPDetector{ + projectID: "my-project", + cloudPlatform: gcp.CloudFunctions, + faaSID: "1472385723456792345", + faaSCloudRegion: "us-central1", + faaSName: "my-service", + faaSVersion: "123456", + }}, + expectedResource: internal.NewResource(map[string]interface{}{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, + conventions.AttributeCloudAccountID: "my-project", + conventions.AttributeCloudPlatform: conventions.AttributeCloudPlatformGCPCloudFunctions, + conventions.AttributeCloudRegion: "us-central1", + conventions.AttributeFaaSName: "my-service", + conventions.AttributeFaaSVersion: "123456", + conventions.AttributeFaaSID: "1472385723456792345", + }), + }, + { + desc: "App Engine", + detector: &detector{detector: &fakeGCPDetector{ + projectID: "my-project", + cloudPlatform: gcp.AppEngine, + appEngineServiceInstance: "1472385723456792345", + appEngineAvailabilityZone: "us-central1-c", + appEngineRegion: "us-central1", + appEngineServiceName: "my-service", + appEngineServiceVersion: "123456", + }}, + expectedResource: internal.NewResource(map[string]interface{}{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, + conventions.AttributeCloudAccountID: "my-project", + conventions.AttributeCloudPlatform: conventions.AttributeCloudPlatformGCPAppEngine, + conventions.AttributeCloudRegion: "us-central1", + conventions.AttributeCloudAvailabilityZone: "us-central1-c", + conventions.AttributeFaaSName: "my-service", + conventions.AttributeFaaSVersion: "123456", + conventions.AttributeFaaSID: "1472385723456792345", + }), + }, + { + desc: "Unknown Platform", + detector: &detector{detector: &fakeGCPDetector{ + projectID: "my-project", + cloudPlatform: gcp.UnknownPlatform, + }}, + expectedResource: internal.NewResource(map[string]interface{}{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, + conventions.AttributeCloudAccountID: "my-project", + }), + }, + { + desc: "error", + detector: &detector{detector: &fakeGCPDetector{ + err: fmt.Errorf("failed to get metadata"), + }}, + expectErr: true, + expectedResource: internal.NewResource(map[string]interface{}{ + conventions.AttributeCloudProvider: conventions.AttributeCloudProviderGCP, + }), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + res, schema, err := tc.detector.Detect(context.TODO()) + if tc.expectErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + assert.Equal(t, conventions.SchemaURL, schema) + tc.expectedResource.Attributes().Sort() + res.Attributes().Sort() + assert.Equal(t, tc.expectedResource, res, "Resource object returned is incorrect") + }) + } +} + +// fakeGCPDetector implements gcpDetector and uses fake values. +type fakeGCPDetector struct { + err error + projectID string + cloudPlatform gcp.Platform + gkeAvailabilityZone string + gkeRegion string + gkeClusterName string + gkeHostID string + gkeHostName string + faaSName string + faaSVersion string + faaSID string + faaSCloudRegion string + appEngineAvailabilityZone string + appEngineRegion string + appEngineServiceName string + appEngineServiceVersion string + appEngineServiceInstance string + gceAvailabilityZone string + gceRegion string + gceHostType string + gceHostID string + gceHostName string +} + +func (f *fakeGCPDetector) ProjectID() (string, error) { + if f.err != nil { + return "", f.err + } + return f.projectID, nil +} + +func (f *fakeGCPDetector) CloudPlatform() gcp.Platform { + return f.cloudPlatform +} + +func (f *fakeGCPDetector) GKEAvailabilityZoneOrRegion() (string, gcp.LocationType, error) { + if f.err != nil { + return "", gcp.UndefinedLocation, f.err + } + if f.gkeAvailabilityZone != "" { + return f.gkeAvailabilityZone, gcp.Zone, nil + } + return f.gkeRegion, gcp.Region, nil +} + +func (f *fakeGCPDetector) GKEClusterName() (string, error) { + if f.err != nil { + return "", f.err + } + return f.gkeClusterName, nil +} + +func (f *fakeGCPDetector) GKEHostID() (string, error) { + if f.err != nil { + return "", f.err + } + return f.gkeHostID, nil +} + +func (f *fakeGCPDetector) GKEHostName() (string, error) { + if f.err != nil { + return "", f.err + } + return f.gkeHostName, nil +} + +func (f *fakeGCPDetector) FaaSName() (string, error) { + if f.err != nil { + return "", f.err + } + return f.faaSName, nil +} + +func (f *fakeGCPDetector) FaaSVersion() (string, error) { + if f.err != nil { + return "", f.err + } + return f.faaSVersion, nil +} + +func (f *fakeGCPDetector) FaaSID() (string, error) { + if f.err != nil { + return "", f.err + } + return f.faaSID, nil +} + +func (f *fakeGCPDetector) FaaSCloudRegion() (string, error) { + if f.err != nil { + return "", f.err + } + return f.faaSCloudRegion, nil +} + +func (f *fakeGCPDetector) AppEngineAvailabilityZoneAndRegion() (string, string, error) { + if f.err != nil { + return "", "", f.err + } + return f.appEngineAvailabilityZone, f.appEngineRegion, nil +} + +func (f *fakeGCPDetector) AppEngineServiceName() (string, error) { + if f.err != nil { + return "", f.err + } + return f.appEngineServiceName, nil +} + +func (f *fakeGCPDetector) AppEngineServiceVersion() (string, error) { + if f.err != nil { + return "", f.err + } + return f.appEngineServiceVersion, nil +} + +func (f *fakeGCPDetector) AppEngineServiceInstance() (string, error) { + if f.err != nil { + return "", f.err + } + return f.appEngineServiceInstance, nil +} + +func (f *fakeGCPDetector) GCEAvailabilityZoneAndRegion() (string, string, error) { + if f.err != nil { + return "", "", f.err + } + return f.gceAvailabilityZone, f.gceRegion, nil +} + +func (f *fakeGCPDetector) GCEHostType() (string, error) { + if f.err != nil { + return "", f.err + } + return f.gceHostType, nil +} + +func (f *fakeGCPDetector) GCEHostID() (string, error) { + if f.err != nil { + return "", f.err + } + return f.gceHostID, nil +} + +func (f *fakeGCPDetector) GCEHostName() (string, error) { + if f.err != nil { + return "", f.err + } + return f.gceHostName, nil +} + +func TestDeduplicateDetectors(t *testing.T) { + for _, tc := range []struct { + desc string + in []string + expected []string + }{ + { + desc: "empty", + expected: []string{}, + }, + { + desc: "single gcp", + in: []string{"gcp"}, + expected: []string{"gcp"}, + }, + { + desc: "single gce", + in: []string{"gce"}, + expected: []string{"gce"}, + }, + { + desc: "single gke", + in: []string{"gke"}, + expected: []string{"gke"}, + }, + { + desc: "multi", + in: []string{"gcp", "gce", "gke"}, + expected: []string{"gcp"}, + }, + { + desc: "multi with others", + in: []string{"foo", "gcp", "gce", "bar", "gke"}, + expected: []string{"foo", "gcp", "bar"}, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + out := DeduplicateDetectors(componenttest.NewNopProcessorCreateSettings(), tc.in) + assert.Equal(t, tc.expected, out) + }) + } +} diff --git a/processor/resourcedetectionprocessor/internal/gcp/gke/gke.go b/processor/resourcedetectionprocessor/internal/gcp/gke/gke.go deleted file mode 100644 index 532c6f5264cc..000000000000 --- a/processor/resourcedetectionprocessor/internal/gcp/gke/gke.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// 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 -// -// http://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 gke // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp/gke" - -import ( - "context" - "os" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/pdata/pcommon" - conventions "go.opentelemetry.io/collector/semconv/v1.6.1" - "go.uber.org/zap" - - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" -) - -const ( - // TypeStr is type of detector. - TypeStr = "gke" - - // GCE metadata attribute containing the GKE cluster name. - clusterNameAttribute = "cluster-name" - - // Environment variable that is set when running on Kubernetes. - kubernetesServiceHostEnvVar = "KUBERNETES_SERVICE_HOST" -) - -var _ internal.Detector = (*Detector)(nil) - -type Detector struct { - log *zap.Logger - metadata gcp.Metadata -} - -func NewDetector(params component.ProcessorCreateSettings, _ internal.DetectorConfig) (internal.Detector, error) { - return &Detector{log: params.Logger, metadata: &gcp.MetadataImpl{}}, nil -} - -// Detect detects associated resources when running in GKE environment. -func (gke *Detector) Detect(ctx context.Context) (resource pcommon.Resource, schemaURL string, err error) { - res := pcommon.NewResource() - - // Check if on GCP. - if !gke.metadata.OnGCE() { - return res, "", nil - } - - attr := res.Attributes() - attr.InsertString(conventions.AttributeCloudProvider, conventions.AttributeCloudProviderGCP) - - // Check if running on k8s. - if os.Getenv(kubernetesServiceHostEnvVar) == "" { - return res, "", nil - } - - attr.InsertString(conventions.AttributeCloudPlatform, conventions.AttributeCloudPlatformGCPKubernetesEngine) - - if clusterName, err := gke.metadata.InstanceAttributeValue(clusterNameAttribute); err != nil { - gke.log.Warn("Unable to determine GKE cluster name", zap.Error(err)) - } else if clusterName != "" { - attr.InsertString(conventions.AttributeK8SClusterName, clusterName) - } - - return res, conventions.SchemaURL, nil -} diff --git a/processor/resourcedetectionprocessor/internal/gcp/gke/gke_test.go b/processor/resourcedetectionprocessor/internal/gcp/gke/gke_test.go deleted file mode 100644 index e8139d0677af..000000000000 --- a/processor/resourcedetectionprocessor/internal/gcp/gke/gke_test.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// 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 -// -// http://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 gke - -import ( - "context" - "errors" - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.opentelemetry.io/collector/component/componenttest" - conventions "go.opentelemetry.io/collector/semconv/v1.6.1" - "go.uber.org/zap" - - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" -) - -func TestNotGCE(t *testing.T) { - metadata := &gcp.MockMetadata{} - detector := &Detector{ - log: zap.NewNop(), - metadata: metadata, - } - - metadata.On("OnGCE").Return(false) - res, _, err := detector.Detect(context.Background()) - require.NoError(t, err) - assert.Equal(t, 0, res.Attributes().Len()) - - metadata.AssertExpectations(t) -} - -func TestDetectWithoutCluster(t *testing.T) { - metadata := &gcp.MockMetadata{} - detector := &Detector{ - log: zap.NewNop(), - metadata: metadata, - } - - metadata.On("OnGCE").Return(true) - metadata.On("InstanceAttributeValue", "cluster-name").Return("", errors.New("no cluster")) - - require.NoError(t, os.Setenv("KUBERNETES_SERVICE_HOST", "localhost")) - - res, schemaURL, err := detector.Detect(context.Background()) - require.NoError(t, err) - assert.Equal(t, conventions.SchemaURL, schemaURL) - - assert.Equal(t, map[string]interface{}{ - "cloud.provider": "gcp", - "cloud.platform": "gcp_kubernetes_engine", - }, internal.AttributesToMap(res.Attributes())) - - metadata.AssertExpectations(t) -} - -func TestDetectWithoutK8s(t *testing.T) { - metadata := &gcp.MockMetadata{} - detector := &Detector{ - log: zap.NewNop(), - metadata: metadata, - } - - metadata.On("OnGCE").Return(true) - - require.NoError(t, os.Unsetenv("KUBERNETES_SERVICE_HOST")) - - res, _, err := detector.Detect(context.Background()) - require.NoError(t, err) - - assert.Equal(t, map[string]interface{}{ - "cloud.provider": "gcp", - }, internal.AttributesToMap(res.Attributes())) - - metadata.AssertExpectations(t) -} - -func TestDetector_Detect(t *testing.T) { - metadata := &gcp.MockMetadata{} - detector := &Detector{ - log: zap.NewNop(), - metadata: metadata, - } - - metadata.On("OnGCE").Return(true) - metadata.On("InstanceAttributeValue", "cluster-name").Return("cluster-a", nil) - - require.NoError(t, os.Setenv("KUBERNETES_SERVICE_HOST", "localhost")) - - res, schemaURL, err := detector.Detect(context.Background()) - require.NoError(t, err) - assert.Equal(t, conventions.SchemaURL, schemaURL) - - assert.Equal(t, map[string]interface{}{ - "cloud.provider": "gcp", - "cloud.platform": "gcp_kubernetes_engine", - "k8s.cluster.name": "cluster-a", - }, internal.AttributesToMap(res.Attributes())) - - metadata.AssertExpectations(t) -} - -func TestNewDetector(t *testing.T) { - detector, err := NewDetector(componenttest.NewNopProcessorCreateSettings(), nil) - assert.NoError(t, err) - assert.NotNil(t, detector) -} diff --git a/processor/resourcedetectionprocessor/internal/gcp/metadata.go b/processor/resourcedetectionprocessor/internal/gcp/metadata.go deleted file mode 100644 index 934699dafd07..000000000000 --- a/processor/resourcedetectionprocessor/internal/gcp/metadata.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// 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 -// -// http://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 "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" - -import "cloud.google.com/go/compute/metadata" - -type Metadata interface { - OnGCE() bool - ProjectID() (string, error) - Zone() (string, error) - Hostname() (string, error) - InstanceAttributeValue(attr string) (string, error) - InstanceID() (string, error) - InstanceName() (string, error) - Get(suffix string) (string, error) -} - -type MetadataImpl struct{} - -var _ Metadata = (*MetadataImpl)(nil) - -func (m *MetadataImpl) OnGCE() bool { - return metadata.OnGCE() -} - -func (m *MetadataImpl) ProjectID() (string, error) { - return metadata.ProjectID() -} - -func (m *MetadataImpl) Zone() (string, error) { - return metadata.Zone() -} - -func (m *MetadataImpl) Hostname() (string, error) { - return metadata.Hostname() -} - -func (m *MetadataImpl) InstanceAttributeValue(attr string) (string, error) { - return metadata.InstanceAttributeValue(attr) -} - -func (m *MetadataImpl) InstanceID() (string, error) { - return metadata.InstanceID() -} - -func (m *MetadataImpl) InstanceName() (string, error) { - return metadata.InstanceName() -} - -func (m *MetadataImpl) Get(suffix string) (string, error) { - return metadata.Get(suffix) -} diff --git a/processor/resourcedetectionprocessor/internal/gcp/metadata_test.go b/processor/resourcedetectionprocessor/internal/gcp/metadata_test.go deleted file mode 100644 index 4d388676f4a3..000000000000 --- a/processor/resourcedetectionprocessor/internal/gcp/metadata_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// 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 -// -// http://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. - -// nolint:errcheck -package gcp - -import ( - "testing" -) - -func TestGCEMetadata(t *testing.T) { - metadata := &MetadataImpl{} - metadata.OnGCE() - metadata.ProjectID() - metadata.Zone() - metadata.Hostname() - metadata.InstanceAttributeValue("") - metadata.InstanceID() - metadata.InstanceName() - metadata.Get("") -} diff --git a/processor/resourcedetectionprocessor/internal/gcp/mockmetadata.go b/processor/resourcedetectionprocessor/internal/gcp/mockmetadata.go deleted file mode 100644 index e2fe0dee02bb..000000000000 --- a/processor/resourcedetectionprocessor/internal/gcp/mockmetadata.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// 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 -// -// http://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 "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" - -import ( - "github.com/stretchr/testify/mock" -) - -var _ Metadata = (*MockMetadata)(nil) - -type MockMetadata struct { - mock.Mock -} - -func (m *MockMetadata) OnGCE() bool { - return m.MethodCalled("OnGCE").Bool(0) -} - -func (m *MockMetadata) ProjectID() (string, error) { - args := m.MethodCalled("ProjectID") - return args.String(0), args.Error(1) -} - -func (m *MockMetadata) Zone() (string, error) { - args := m.MethodCalled("Zone") - return args.String(0), args.Error(1) -} - -func (m *MockMetadata) Hostname() (string, error) { - args := m.MethodCalled("Hostname") - return args.String(0), args.Error(1) -} - -func (m *MockMetadata) InstanceAttributeValue(attr string) (string, error) { - args := m.MethodCalled("InstanceAttributeValue", attr) - return args.String(0), args.Error(1) -} - -func (m *MockMetadata) InstanceID() (string, error) { - args := m.MethodCalled("InstanceID") - return args.String(0), args.Error(1) -} - -func (m *MockMetadata) InstanceName() (string, error) { - args := m.MethodCalled("InstanceName") - return args.String(0), args.Error(1) -} - -func (m *MockMetadata) Get(suffix string) (string, error) { - args := m.MethodCalled("Get", suffix) - return args.String(0), args.Error(1) -} diff --git a/processor/resourcedetectionprocessor/internal/gcp/mockmetadata_test.go b/processor/resourcedetectionprocessor/internal/gcp/mockmetadata_test.go deleted file mode 100644 index 4996eb2df949..000000000000 --- a/processor/resourcedetectionprocessor/internal/gcp/mockmetadata_test.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// 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 -// -// http://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. - -// nolint:errcheck -package gcp - -import ( - "testing" -) - -func TestMockGCEMetadata(t *testing.T) { - metadata := &MockMetadata{} - metadata.On("OnGCE").Return(false) - metadata.On("ProjectID").Return("", nil) - metadata.On("Zone").Return("", nil) - metadata.On("Hostname").Return("", nil) - metadata.On("InstanceAttributeValue", "").Return("", nil) - metadata.On("InstanceID").Return("", nil) - metadata.On("InstanceName").Return("", nil) - metadata.On("Get", "").Return("", nil) - - metadata.OnGCE() - metadata.ProjectID() - metadata.Zone() - metadata.Hostname() - metadata.InstanceAttributeValue("") - metadata.InstanceID() - metadata.InstanceName() - metadata.Get("") - - metadata.AssertExpectations(t) -} diff --git a/processor/resourcedetectionprocessor/internal/gcp/types.go b/processor/resourcedetectionprocessor/internal/gcp/types.go new file mode 100644 index 000000000000..4f55402f8e12 --- /dev/null +++ b/processor/resourcedetectionprocessor/internal/gcp/types.go @@ -0,0 +1,42 @@ +// Copyright The OpenTelemetry Authors +// +// 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 +// +// http://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 "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" + +import "github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp" + +// gcpDetector can detect attributes of GCP environments. +// It is implemented by +// github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp +// and is defined here for testing. +type gcpDetector interface { + ProjectID() (string, error) + CloudPlatform() gcp.Platform + GKEAvailabilityZoneOrRegion() (string, gcp.LocationType, error) + GKEClusterName() (string, error) + GKEHostID() (string, error) + GKEHostName() (string, error) + FaaSName() (string, error) + FaaSVersion() (string, error) + FaaSID() (string, error) + FaaSCloudRegion() (string, error) + AppEngineAvailabilityZoneAndRegion() (string, string, error) + AppEngineServiceName() (string, error) + AppEngineServiceVersion() (string, error) + AppEngineServiceInstance() (string, error) + GCEAvailabilityZoneAndRegion() (string, string, error) + GCEHostType() (string, error) + GCEHostID() (string, error) + GCEHostName() (string, error) +} diff --git a/processor/resourcedetectionprocessor/resourcedetection_processor_test.go b/processor/resourcedetectionprocessor/resourcedetection_processor_test.go index 5d3c219e3e90..de27654c3a8c 100644 --- a/processor/resourcedetectionprocessor/resourcedetection_processor_test.go +++ b/processor/resourcedetectionprocessor/resourcedetection_processor_test.go @@ -38,7 +38,7 @@ import ( internaldata "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/opencensus" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/env" - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp/gce" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" ) type MockDetector struct { @@ -311,7 +311,7 @@ func BenchmarkConsumeTracesDefault(b *testing.B) { } func BenchmarkConsumeTracesAll(b *testing.B) { - cfg := &Config{Override: true, Detectors: []string{env.TypeStr, gce.TypeStr}} + cfg := &Config{Override: true, Detectors: []string{env.TypeStr, gcp.TypeStr}} benchmarkConsumeTraces(b, cfg) } @@ -333,7 +333,7 @@ func BenchmarkConsumeMetricsDefault(b *testing.B) { } func BenchmarkConsumeMetricsAll(b *testing.B) { - cfg := &Config{Override: true, Detectors: []string{env.TypeStr, gce.TypeStr}} + cfg := &Config{Override: true, Detectors: []string{env.TypeStr, gcp.TypeStr}} benchmarkConsumeMetrics(b, cfg) } @@ -355,6 +355,6 @@ func BenchmarkConsumeLogsDefault(b *testing.B) { } func BenchmarkConsumeLogsAll(b *testing.B) { - cfg := &Config{Override: true, Detectors: []string{env.TypeStr, gce.TypeStr}} + cfg := &Config{Override: true, Detectors: []string{env.TypeStr, gcp.TypeStr}} benchmarkConsumeLogs(b, cfg) }