From 72af3a094d4ccf5e3670f4400b7af22072541cd5 Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Mon, 3 Aug 2020 20:59:03 -0500 Subject: [PATCH 01/12] feat: temporarily added EC2 resource detector --- .../package.json | 100 +++++------ .../node/detectors/AwsEc2DetectorTemp.ts | 170 ++++++++++++++++++ .../src/platform/node/detectors/index.ts | 1 + .../test/detectors/AwsEc2DetectorTemp.test.ts | 95 ++++++++++ 4 files changed, 307 insertions(+), 59 deletions(-) create mode 100644 packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2DetectorTemp.ts create mode 100644 packages/opentelemetry-resources/test/detectors/AwsEc2DetectorTemp.test.ts diff --git a/packages/opentelemetry-exporter-zipkin/package.json b/packages/opentelemetry-exporter-zipkin/package.json index 550b4e7be24..9f3346c0e71 100644 --- a/packages/opentelemetry-exporter-zipkin/package.json +++ b/packages/opentelemetry-exporter-zipkin/package.json @@ -1,61 +1,43 @@ { - "name": "@opentelemetry/exporter-zipkin", - "version": "0.10.2", - "description": "OpenTelemetry Zipkin Exporter allows the user to send collected traces to Zipkin.", - "main": "build/src/index.js", - "types": "build/src/index.d.ts", - "repository": "open-telemetry/opentelemetry-js", - "scripts": { - "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'", - "tdd": "npm run test -- --watch-extensions ts --watch", - "clean": "rimraf build/*", - "lint": "eslint . --ext .ts", - "lint:fix": "eslint . --ext .ts --fix", - "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", - "precompile": "tsc --version", - "version:update": "node ../../scripts/version-update.js", - "compile": "npm run version:update && tsc -p .", - "prepare": "npm run compile" - }, - "keywords": [ - "opentelemetry", - "nodejs", - "tracing", - "profiling" - ], - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - }, - "files": [ - "build/src/**/*.js", - "build/src/**/*.js.map", - "build/src/**/*.d.ts", - "doc", - "LICENSE", - "README.md" - ], - "publishConfig": { - "access": "public" - }, - "devDependencies": { - "@types/mocha": "8.0.0", - "@types/node": "14.0.27", - "codecov": "3.7.2", - "gts": "2.0.2", - "mocha": "7.2.0", - "nock": "12.0.3", - "nyc": "15.1.0", - "rimraf": "3.0.2", - "ts-mocha": "7.0.0", - "ts-node": "8.10.2", - "typescript": "3.9.7" - }, - "dependencies": { - "@opentelemetry/api": "^0.10.2", - "@opentelemetry/core": "^0.10.2", - "@opentelemetry/resources": "^0.10.2", - "@opentelemetry/tracing": "^0.10.2" - } + "name": "@opentelemetry/exporter-zipkin", + "version": "0.10.2", + "description": "OpenTelemetry Zipkin Exporter allows the user to send collected traces to Zipkin.", + "main": "build/src/index.js", + "types": "build/src/index.d.ts", + "repository": "open-telemetry/opentelemetry-js", + "keywords": [ + "opentelemetry", + "nodejs", + "tracing", + "profiling" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + }, + "files": [ + "build/src/**/*.js", + "build/src/**/*.js.map", + "build/src/**/*.d.ts", + "doc", + "LICENSE", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@types/mocha": "8.0.0", + "@types/node": "14.0.27", + "codecov": "3.7.2", + "gts": "2.0.2", + "mocha": "7.2.0", + "nock": "12.0.3", + "nyc": "15.1.0", + "rimraf": "3.0.2", + "ts-mocha": "7.0.0", + "ts-node": "8.10.2", + "typescript": "3.9.7" + } } diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2DetectorTemp.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2DetectorTemp.ts new file mode 100644 index 00000000000..079dc872619 --- /dev/null +++ b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2DetectorTemp.ts @@ -0,0 +1,170 @@ +/* + * 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 + * + * 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. + */ + +import * as http from 'http'; +import { Resource } from '../../../Resource'; +import { CLOUD_RESOURCE, HOST_RESOURCE } from '../../../constants'; +import { Detector } from '../../../types'; +import { ResourceDetectionConfigWithLogger } from '../../../config'; + +/** + * The AwsEc2Detector can be used to detect if a process is running in AWS EC2 + * and return a {@link Resource} populated with metadata about the EC2 + * instance. Returns an empty Resource if detection fails. + */ +class AwsEc2Detector implements Detector { + /** + * See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html + * for documentation about the AWS instance identity document endpoint. + */ + readonly HTTP_HEADER = 'http://'; + readonly AWS_IDMS_ENDPOINT = '169.254.169.254'; + readonly AWS_INSTANCE_TOKEN_DOCUMENT_PATH = '/latest/api/token'; + readonly AWS_INSTANCE_IDENTITY_DOCUMENT_PATH = + '/latest/dynamic/instance-identity/document'; + readonly AWS_INSTANCE_HOST_DOCUMENT_PATH = '/latest/meta-data/hostname'; + readonly AWS_INSTANCE_IDENTITY_DOCUMENT_URI = + 'http://169.254.169.254/latest/dynamic/instance-identity/document'; + readonly AWS_INSTANCE_TOKEN_DOCUMENT_URI = + 'http://169.254.169.254/latest/api/token'; + readonly AWS_INSTANCE_HOST_DOCUMENT_URI = + 'http://169.254.169.254/latest/meta-data/hostname' + + /** + * Attempts to connect and obtain an AWS instance Identity document. If the + * connection is succesful it returns a promise containing a {@link Resource} + * populated with instance metadata as labels. Returns a promise containing an + * empty {@link Resource} if the connection or parsing of the identity + * document fails. + * + * @param config The resource detection config with a required logger + */ + async detect(config: ResourceDetectionConfigWithLogger): Promise { + try { + const token = await this._fetchToken(); + const { + accountId, + instanceId, + instanceType, + region, + availabilityZone, + } = await this._fetchIdentity(token); + const hostname = await this._fetchHost(token); + + return new Resource({ + [CLOUD_RESOURCE.PROVIDER]: 'aws', + [CLOUD_RESOURCE.ACCOUNT_ID]: accountId, + [CLOUD_RESOURCE.REGION]: region, + [CLOUD_RESOURCE.ZONE]: availabilityZone, + [HOST_RESOURCE.ID]: instanceId, + [HOST_RESOURCE.TYPE]: instanceType, + [HOST_RESOURCE.NAME]: hostname, + [HOST_RESOURCE.HOSTNAME]: hostname, + }); + } catch (e) { + config.logger.debug(`AwsEc2Detector failed: ${e.message}`); + return Resource.empty(); + } + } + + private async _fetchToken(): Promise { + const options = { + host: this.AWS_IDMS_ENDPOINT, + path: this.AWS_INSTANCE_TOKEN_DOCUMENT_PATH, + port: 700, + method: "PUT", + timeout: 1000, + headers: { + "X-aws-ec2-metadata-token-ttl-seconds": "60", + }, + } + // const url = this.AWS_INSTANCE_TOKEN_DOCUMENT_URI; + return await this._fetchString(options); + } + + private async _fetchIdentity(token: string): Promise { + const options = { + host: this.AWS_IDMS_ENDPOINT, + path: this.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH, + port: 800, + method: "GET", + timeout: 1000, + headers: { + "X-aws-ec2-metadata-token": token, + } + } + // const url = this.AWS_INSTANCE_IDENTITY_DOCUMENT_URI; + const identity = await this._fetchString(options); + return JSON.parse(identity); + } + + private async _fetchHost(token: string): Promise { + const options = { + host: this.AWS_IDMS_ENDPOINT, + path: this.AWS_INSTANCE_HOST_DOCUMENT_PATH, + port: 900, + method: "GET", + timeout: 1000, + headers: { + "X-aws-ec2-metadata-token": token, + } + } + // const url = this.AWS_INSTANCE_HOST_DOCUMENT_URI; + return await this._fetchString(options); + } + + /** + * Establishes an HTTP connection to AWS instance document url. + * If the application is running on an EC2 instance, we should be able + * to get back a valid JSON document. Parses that document and stores + * the identity properties in a local map. + */ + private async _fetchString(options: Object): Promise { + return new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + req.abort(); + reject(new Error('EC2 metadata api request timed out.')); + }, 1000); + + const req = http.request(options, res => { + clearTimeout(timeoutId); + const { statusCode } = res; + res.setEncoding('utf8'); + let rawData = ''; + res.on('data', chunk => (rawData += chunk)); + res.on('end', () => { + if (statusCode && statusCode >= 200 && statusCode < 300) { + try { + resolve(rawData); + } catch (e) { + reject(e); + } + } else { + reject( + new Error('Failed to load page, status code: ' + statusCode) + ); + } + }); + }); + req.on('error', err => { + clearTimeout(timeoutId); + reject(err); + }); + }); + } +} + +export const awsEc2DetectorTemp = new AwsEc2Detector(); diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/index.ts b/packages/opentelemetry-resources/src/platform/node/detectors/index.ts index c0c3c37b2c8..1c1c735b086 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/index.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/index.ts @@ -17,3 +17,4 @@ export { awsEc2Detector } from './AwsEc2Detector'; export { envDetector } from './EnvDetector'; export { gcpDetector } from './GcpDetector'; +export { awsEc2DetectorTemp } from './AwsEc2DetectorTemp'; diff --git a/packages/opentelemetry-resources/test/detectors/AwsEc2DetectorTemp.test.ts b/packages/opentelemetry-resources/test/detectors/AwsEc2DetectorTemp.test.ts new file mode 100644 index 00000000000..5b1c909bbce --- /dev/null +++ b/packages/opentelemetry-resources/test/detectors/AwsEc2DetectorTemp.test.ts @@ -0,0 +1,95 @@ +/* + * 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 + * + * 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. + */ + +import * as nock from 'nock'; +import * as assert from 'assert'; +import { Resource } from '../../src'; +import { awsEc2DetectorTemp } from '../../src/platform/node/detectors/AwsEc2DetectorTemp'; +import { + assertCloudResource, + assertHostResource, + assertEmptyResource, +} from '../util/resource-assertions'; +import { NoopLogger } from '@opentelemetry/core'; +import { URL } from 'url'; + +const { origin: AWS_HOST, pathname: AWS_TOKEN_PATH } = new URL( + awsEc2DetectorTemp.AWS_INSTANCE_TOKEN_DOCUMENT_URI +); +const { origin: AWS_TEMP1, pathname: AWS_IDENTITY_PATH } = new URL( + awsEc2DetectorTemp.AWS_INSTANCE_IDENTITY_DOCUMENT_URI +); +const { origin: AWS_TEMP2, pathname: AWS_HOST_PATH } = new URL( + awsEc2DetectorTemp.AWS_INSTANCE_HOST_DOCUMENT_URI +); + +const mockedTokenResponse = 'my-token'; +const mockedIdentityResponse = { + instanceId: 'my-instance-id', + instanceType: 'my-instance-type', + accountId: 'my-account-id', + region: 'my-region', + availabilityZone: 'my-zone', +}; +const mockedHostResponse = 'my-hostname'; + +describe('awsEc2DetectorTemp', () => { + before(() => { + nock.disableNetConnect(); + nock.cleanAll(); + }); + + after(() => { + nock.enableNetConnect(); + }); + + describe('with successful request', () => { + it('should return aws_ec2_instance resource', async () => { + const scope = nock(AWS_HOST) + .persist() + .put(AWS_TOKEN_PATH, { "X-aws-ec2-metadata-token-ttl-seconds": "60"} ) + // .matchHeader("X-aws-ec2-metadata-token-ttl-seconds", "60") + .reply(200, () => mockedTokenResponse) + .get(AWS_IDENTITY_PATH) + // .matchHeader("X-aws-ec2-metadata-token", mockedTokenResponse) + .reply(200, () => mockedIdentityResponse) + .get(AWS_HOST_PATH) + // .matchHeader("X-aws-ec2-metadata-token", mockedTokenResponse) + .reply(200, () => mockedHostResponse); + + const resource: Resource = await awsEc2DetectorTemp.detect({ + logger: new NoopLogger(), + }); + + scope.done(); + + assert.ok(resource); + // assert.deepStrictEqual(resource, {1:1}); + assertCloudResource(resource, { + provider: 'aws', + accountId: 'my-account-id', + region: 'my-region', + zone: 'my-zone', + }); + assertHostResource(resource, { + id: 'my-instance-id', + hostType: 'my-instance-type', + name: 'my-hostname', + hostName: 'my-hostname', + }); + }); + }); +}); From 1f2b962aa490c6825b2ced2fd775c1ab3c266b83 Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Fri, 7 Aug 2020 15:01:27 -0500 Subject: [PATCH 02/12] feat: update EC2 Resource Detector to IDMSv2 and modified detect-resource --- .../platform/node/detectors/AwsEc2Detector.ts | 66 ++++++- .../node/detectors/AwsEc2DetectorTemp.ts | 170 ------------------ .../src/platform/node/detectors/index.ts | 1 - .../test/detect-resources.test.ts | 32 +++- .../test/detectors/AwsEc2Detector.test.ts | 94 ++++++++-- .../test/detectors/AwsEc2DetectorTemp.test.ts | 95 ---------- 6 files changed, 164 insertions(+), 294 deletions(-) delete mode 100644 packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2DetectorTemp.ts delete mode 100644 packages/opentelemetry-resources/test/detectors/AwsEc2DetectorTemp.test.ts diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts index 76fd11527ae..521df6d1590 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts @@ -30,8 +30,18 @@ class AwsEc2Detector implements Detector { * See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html * for documentation about the AWS instance identity document endpoint. */ + readonly HTTP_HEADER = 'http://'; + readonly AWS_IDMS_ENDPOINT = '169.254.169.254'; + readonly AWS_INSTANCE_TOKEN_DOCUMENT_PATH = '/latest/api/token'; + readonly AWS_INSTANCE_IDENTITY_DOCUMENT_PATH = + '/latest/dynamic/instance-identity/document'; + readonly AWS_INSTANCE_HOST_DOCUMENT_PATH = '/latest/meta-data/hostname'; readonly AWS_INSTANCE_IDENTITY_DOCUMENT_URI = 'http://169.254.169.254/latest/dynamic/instance-identity/document'; + readonly AWS_INSTANCE_TOKEN_DOCUMENT_URI = + 'http://169.254.169.254/latest/api/token'; + readonly AWS_INSTANCE_HOST_DOCUMENT_URI = + 'http://169.254.169.254/latest/meta-data/hostname'; /** * Attempts to connect and obtain an AWS instance Identity document. If the @@ -44,13 +54,16 @@ class AwsEc2Detector implements Detector { */ async detect(config: ResourceDetectionConfigWithLogger): Promise { try { + const token = await this._fetchToken(); const { accountId, instanceId, instanceType, region, availabilityZone, - } = await this._awsMetadataAccessor(); + } = await this._fetchIdentity(token); + const hostname = await this._fetchHost(token); + return new Resource({ [CLOUD_RESOURCE.PROVIDER]: 'aws', [CLOUD_RESOURCE.ACCOUNT_ID]: accountId, @@ -58,6 +71,8 @@ class AwsEc2Detector implements Detector { [CLOUD_RESOURCE.ZONE]: availabilityZone, [HOST_RESOURCE.ID]: instanceId, [HOST_RESOURCE.TYPE]: instanceType, + [HOST_RESOURCE.NAME]: hostname, + [HOST_RESOURCE.HOSTNAME]: hostname, }); } catch (e) { config.logger.debug(`AwsEc2Detector failed: ${e.message}`); @@ -65,20 +80,60 @@ class AwsEc2Detector implements Detector { } } + private async _fetchToken(): Promise { + const options = { + host: this.AWS_IDMS_ENDPOINT, + path: this.AWS_INSTANCE_TOKEN_DOCUMENT_PATH, + method: 'PUT', + timeout: 1000, + headers: { + 'X-aws-ec2-metadata-token-ttl-seconds': '60', + }, + }; + return await this._fetchString(options); + } + + private async _fetchIdentity(token: string): Promise { + const options = { + host: this.AWS_IDMS_ENDPOINT, + path: this.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH, + method: 'GET', + timeout: 1000, + headers: { + 'X-aws-ec2-metadata-token': token, + }, + }; + const identity = await this._fetchString(options); + return JSON.parse(identity); + } + + private async _fetchHost(token: string): Promise { + const options = { + host: this.AWS_IDMS_ENDPOINT, + path: this.AWS_INSTANCE_HOST_DOCUMENT_PATH, + method: 'GET', + timeout: 1000, + headers: { + 'X-aws-ec2-metadata-token': token, + }, + }; + return await this._fetchString(options); + } + /** - * Establishes an HTTP connection to AWS instance identity document url. + * Establishes an HTTP connection to AWS instance document url. * If the application is running on an EC2 instance, we should be able * to get back a valid JSON document. Parses that document and stores * the identity properties in a local map. */ - private async _awsMetadataAccessor(): Promise { + private async _fetchString(options: Record): Promise { return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { req.abort(); reject(new Error('EC2 metadata api request timed out.')); }, 1000); - const req = http.get(this.AWS_INSTANCE_IDENTITY_DOCUMENT_URI, res => { + const req = http.request(options, res => { clearTimeout(timeoutId); const { statusCode } = res; res.setEncoding('utf8'); @@ -87,7 +142,7 @@ class AwsEc2Detector implements Detector { res.on('end', () => { if (statusCode && statusCode >= 200 && statusCode < 300) { try { - resolve(JSON.parse(rawData)); + resolve(rawData); } catch (e) { reject(e); } @@ -102,6 +157,7 @@ class AwsEc2Detector implements Detector { clearTimeout(timeoutId); reject(err); }); + req.end(); }); } } diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2DetectorTemp.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2DetectorTemp.ts deleted file mode 100644 index 079dc872619..00000000000 --- a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2DetectorTemp.ts +++ /dev/null @@ -1,170 +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 - * - * 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. - */ - -import * as http from 'http'; -import { Resource } from '../../../Resource'; -import { CLOUD_RESOURCE, HOST_RESOURCE } from '../../../constants'; -import { Detector } from '../../../types'; -import { ResourceDetectionConfigWithLogger } from '../../../config'; - -/** - * The AwsEc2Detector can be used to detect if a process is running in AWS EC2 - * and return a {@link Resource} populated with metadata about the EC2 - * instance. Returns an empty Resource if detection fails. - */ -class AwsEc2Detector implements Detector { - /** - * See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html - * for documentation about the AWS instance identity document endpoint. - */ - readonly HTTP_HEADER = 'http://'; - readonly AWS_IDMS_ENDPOINT = '169.254.169.254'; - readonly AWS_INSTANCE_TOKEN_DOCUMENT_PATH = '/latest/api/token'; - readonly AWS_INSTANCE_IDENTITY_DOCUMENT_PATH = - '/latest/dynamic/instance-identity/document'; - readonly AWS_INSTANCE_HOST_DOCUMENT_PATH = '/latest/meta-data/hostname'; - readonly AWS_INSTANCE_IDENTITY_DOCUMENT_URI = - 'http://169.254.169.254/latest/dynamic/instance-identity/document'; - readonly AWS_INSTANCE_TOKEN_DOCUMENT_URI = - 'http://169.254.169.254/latest/api/token'; - readonly AWS_INSTANCE_HOST_DOCUMENT_URI = - 'http://169.254.169.254/latest/meta-data/hostname' - - /** - * Attempts to connect and obtain an AWS instance Identity document. If the - * connection is succesful it returns a promise containing a {@link Resource} - * populated with instance metadata as labels. Returns a promise containing an - * empty {@link Resource} if the connection or parsing of the identity - * document fails. - * - * @param config The resource detection config with a required logger - */ - async detect(config: ResourceDetectionConfigWithLogger): Promise { - try { - const token = await this._fetchToken(); - const { - accountId, - instanceId, - instanceType, - region, - availabilityZone, - } = await this._fetchIdentity(token); - const hostname = await this._fetchHost(token); - - return new Resource({ - [CLOUD_RESOURCE.PROVIDER]: 'aws', - [CLOUD_RESOURCE.ACCOUNT_ID]: accountId, - [CLOUD_RESOURCE.REGION]: region, - [CLOUD_RESOURCE.ZONE]: availabilityZone, - [HOST_RESOURCE.ID]: instanceId, - [HOST_RESOURCE.TYPE]: instanceType, - [HOST_RESOURCE.NAME]: hostname, - [HOST_RESOURCE.HOSTNAME]: hostname, - }); - } catch (e) { - config.logger.debug(`AwsEc2Detector failed: ${e.message}`); - return Resource.empty(); - } - } - - private async _fetchToken(): Promise { - const options = { - host: this.AWS_IDMS_ENDPOINT, - path: this.AWS_INSTANCE_TOKEN_DOCUMENT_PATH, - port: 700, - method: "PUT", - timeout: 1000, - headers: { - "X-aws-ec2-metadata-token-ttl-seconds": "60", - }, - } - // const url = this.AWS_INSTANCE_TOKEN_DOCUMENT_URI; - return await this._fetchString(options); - } - - private async _fetchIdentity(token: string): Promise { - const options = { - host: this.AWS_IDMS_ENDPOINT, - path: this.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH, - port: 800, - method: "GET", - timeout: 1000, - headers: { - "X-aws-ec2-metadata-token": token, - } - } - // const url = this.AWS_INSTANCE_IDENTITY_DOCUMENT_URI; - const identity = await this._fetchString(options); - return JSON.parse(identity); - } - - private async _fetchHost(token: string): Promise { - const options = { - host: this.AWS_IDMS_ENDPOINT, - path: this.AWS_INSTANCE_HOST_DOCUMENT_PATH, - port: 900, - method: "GET", - timeout: 1000, - headers: { - "X-aws-ec2-metadata-token": token, - } - } - // const url = this.AWS_INSTANCE_HOST_DOCUMENT_URI; - return await this._fetchString(options); - } - - /** - * Establishes an HTTP connection to AWS instance document url. - * If the application is running on an EC2 instance, we should be able - * to get back a valid JSON document. Parses that document and stores - * the identity properties in a local map. - */ - private async _fetchString(options: Object): Promise { - return new Promise((resolve, reject) => { - const timeoutId = setTimeout(() => { - req.abort(); - reject(new Error('EC2 metadata api request timed out.')); - }, 1000); - - const req = http.request(options, res => { - clearTimeout(timeoutId); - const { statusCode } = res; - res.setEncoding('utf8'); - let rawData = ''; - res.on('data', chunk => (rawData += chunk)); - res.on('end', () => { - if (statusCode && statusCode >= 200 && statusCode < 300) { - try { - resolve(rawData); - } catch (e) { - reject(e); - } - } else { - reject( - new Error('Failed to load page, status code: ' + statusCode) - ); - } - }); - }); - req.on('error', err => { - clearTimeout(timeoutId); - reject(err); - }); - }); - } -} - -export const awsEc2DetectorTemp = new AwsEc2Detector(); diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/index.ts b/packages/opentelemetry-resources/src/platform/node/detectors/index.ts index 1c1c735b086..c0c3c37b2c8 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/index.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/index.ts @@ -17,4 +17,3 @@ export { awsEc2Detector } from './AwsEc2Detector'; export { envDetector } from './EnvDetector'; export { gcpDetector } from './GcpDetector'; -export { awsEc2DetectorTemp } from './AwsEc2DetectorTemp'; diff --git a/packages/opentelemetry-resources/test/detect-resources.test.ts b/packages/opentelemetry-resources/test/detect-resources.test.ts index b607efa0d69..ad7d7001674 100644 --- a/packages/opentelemetry-resources/test/detect-resources.test.ts +++ b/packages/opentelemetry-resources/test/detect-resources.test.ts @@ -17,7 +17,6 @@ import * as nock from 'nock'; import * as sinon from 'sinon'; import * as assert from 'assert'; -import { URL } from 'url'; import { Resource, detectResources } from '../src'; import { awsEc2Detector } from '../src/platform/node/detectors'; import { @@ -43,17 +42,20 @@ const PROJECT_ID_PATH = BASE_PATH + '/project/project-id'; const ZONE_PATH = BASE_PATH + '/instance/zone'; const CLUSTER_NAME_PATH = BASE_PATH + '/instance/attributes/cluster-name'; -const { origin: AWS_HOST, pathname: AWS_PATH } = new URL( - awsEc2Detector.AWS_INSTANCE_IDENTITY_DOCUMENT_URI -); +const AWS_HOST = awsEc2Detector.HTTP_HEADER + awsEc2Detector.AWS_IDMS_ENDPOINT; +const AWS_TOKEN_PATH = awsEc2Detector.AWS_INSTANCE_TOKEN_DOCUMENT_PATH; +const AWS_IDENTITY_PATH = awsEc2Detector.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH; +const AWS_HOST_PATH = awsEc2Detector.AWS_INSTANCE_HOST_DOCUMENT_PATH; -const mockedAwsResponse = { +const mockedTokenResponse = 'my-token'; +const mockedIdentityResponse = { instanceId: 'my-instance-id', instanceType: 'my-instance-type', accountId: 'my-account-id', region: 'my-region', availabilityZone: 'my-zone', }; +const mockedHostResponse = 'my-hostname'; describe('detectResources', async () => { beforeEach(() => { @@ -89,7 +91,9 @@ describe('detectResources', async () => { .get(INSTANCE_PATH) .reply(200, {}, HEADERS); const awsScope = nock(AWS_HOST) - .get(AWS_PATH) + .persist() + .put(AWS_TOKEN_PATH) + .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') .replyWithError({ code: 'ENOTFOUND' }); const resource: Resource = await detectResources(); awsScope.done(); @@ -122,8 +126,16 @@ describe('detectResources', async () => { code: 'ENOTFOUND', }); const awsScope = nock(AWS_HOST) - .get(AWS_PATH) - .reply(200, () => mockedAwsResponse); + .persist() + .put(AWS_TOKEN_PATH) + .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .reply(200, () => mockedTokenResponse) + .get(AWS_IDENTITY_PATH) + .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .reply(200, () => mockedIdentityResponse) + .get(AWS_HOST_PATH) + .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .reply(200, () => mockedHostResponse); const resource: Resource = await detectResources(); gcpSecondaryScope.done(); gcpScope.done(); @@ -138,6 +150,8 @@ describe('detectResources', async () => { assertHostResource(resource, { id: 'my-instance-id', hostType: 'my-instance-type', + name: 'my-hostname', + hostName: 'my-hostname', }); assertServiceResource(resource, { instanceId: '627cc493', @@ -206,7 +220,7 @@ describe('detectResources', async () => { assert.ok( callArgsContains( mockedLoggerMethod, - 'AwsEc2Detector failed: Nock: Disallowed net connect for "169.254.169.254:80/latest/dynamic/instance-identity/document"' + 'AwsEc2Detector failed: Nock: Disallowed net connect for "169.254.169.254:80/latest/api/token"' ) ); // Test that the Env Detector successfully found its resource and populated it with the right values. diff --git a/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts b/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts index 9b9e6eb0355..42a9480c546 100644 --- a/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts +++ b/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts @@ -16,7 +16,6 @@ import * as nock from 'nock'; import * as assert from 'assert'; -import { URL } from 'url'; import { Resource } from '../../src'; import { awsEc2Detector } from '../../src/platform/node/detectors/AwsEc2Detector'; import { @@ -26,36 +25,49 @@ import { } from '../util/resource-assertions'; import { NoopLogger } from '@opentelemetry/core'; -const { origin: AWS_HOST, pathname: AWS_PATH } = new URL( - awsEc2Detector.AWS_INSTANCE_IDENTITY_DOCUMENT_URI -); +const AWS_HOST = awsEc2Detector.HTTP_HEADER + awsEc2Detector.AWS_IDMS_ENDPOINT; +const AWS_TOKEN_PATH = awsEc2Detector.AWS_INSTANCE_TOKEN_DOCUMENT_PATH; +const AWS_IDENTITY_PATH = awsEc2Detector.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH; +const AWS_HOST_PATH = awsEc2Detector.AWS_INSTANCE_HOST_DOCUMENT_PATH; -const mockedAwsResponse = { +const mockedTokenResponse = 'my-token'; +const mockedIdentityResponse = { instanceId: 'my-instance-id', instanceType: 'my-instance-type', accountId: 'my-account-id', region: 'my-region', availabilityZone: 'my-zone', }; +const mockedHostResponse = 'my-hostname'; -describe('awsEc2Detector', () => { - before(() => { +describe('awsEc2DetectorTemp', () => { + beforeEach(() => { nock.disableNetConnect(); nock.cleanAll(); }); - after(() => { + afterEach(() => { nock.enableNetConnect(); }); describe('with successful request', () => { it('should return aws_ec2_instance resource', async () => { const scope = nock(AWS_HOST) - .get(AWS_PATH) - .reply(200, () => mockedAwsResponse); + .persist() + .put(AWS_TOKEN_PATH) + .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .reply(200, () => mockedTokenResponse) + .get(AWS_IDENTITY_PATH) + .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .reply(200, () => mockedIdentityResponse) + .get(AWS_HOST_PATH) + .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .reply(200, () => mockedHostResponse); + const resource: Resource = await awsEc2Detector.detect({ logger: new NoopLogger(), }); + scope.done(); assert.ok(resource); @@ -68,18 +80,72 @@ describe('awsEc2Detector', () => { assertHostResource(resource, { id: 'my-instance-id', hostType: 'my-instance-type', + name: 'my-hostname', + hostName: 'my-hostname', }); }); }); - describe('with failing request', () => { - it('should return empty resource', async () => { - const scope = nock(AWS_HOST).get(AWS_PATH).replyWithError({ - code: 'ENOTFOUND', + describe('with unsuccessful request', () => { + it('should return empty resource when receiving error response code', async () => { + const scope = nock(AWS_HOST) + .persist() + .put(AWS_TOKEN_PATH) + .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .reply(200, () => mockedTokenResponse) + .get(AWS_IDENTITY_PATH) + .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .reply(200, () => mockedIdentityResponse) + .get(AWS_HOST_PATH) + .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .reply(404, () => new Error('NOT FOUND')); + + const resource: Resource = await awsEc2Detector.detect({ + logger: new NoopLogger(), + }); + + scope.done(); + + assert.ok(resource); + assertEmptyResource(resource); + }); + + it('should return empty resource when timeout', async () => { + const scope = nock(AWS_HOST) + .put(AWS_TOKEN_PATH) + .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .reply(200, () => mockedTokenResponse) + .get(AWS_IDENTITY_PATH) + .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .reply(200, () => mockedIdentityResponse) + .get(AWS_HOST_PATH) + .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .delayConnection(2000) + .reply(200, () => mockedHostResponse); + + const resource: Resource = await awsEc2Detector.detect({ + logger: new NoopLogger(), }); + + scope.done(); + + assert.ok(resource); + assertEmptyResource(resource); + }); + + it('should return empty resource when replied Error', async () => { + const scope = nock(AWS_HOST) + .put(AWS_TOKEN_PATH) + .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .reply(200, () => mockedTokenResponse) + .get(AWS_IDENTITY_PATH) + .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .replyWithError('NOT FOUND'); + const resource: Resource = await awsEc2Detector.detect({ logger: new NoopLogger(), }); + scope.done(); assert.ok(resource); diff --git a/packages/opentelemetry-resources/test/detectors/AwsEc2DetectorTemp.test.ts b/packages/opentelemetry-resources/test/detectors/AwsEc2DetectorTemp.test.ts deleted file mode 100644 index 5b1c909bbce..00000000000 --- a/packages/opentelemetry-resources/test/detectors/AwsEc2DetectorTemp.test.ts +++ /dev/null @@ -1,95 +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 - * - * 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. - */ - -import * as nock from 'nock'; -import * as assert from 'assert'; -import { Resource } from '../../src'; -import { awsEc2DetectorTemp } from '../../src/platform/node/detectors/AwsEc2DetectorTemp'; -import { - assertCloudResource, - assertHostResource, - assertEmptyResource, -} from '../util/resource-assertions'; -import { NoopLogger } from '@opentelemetry/core'; -import { URL } from 'url'; - -const { origin: AWS_HOST, pathname: AWS_TOKEN_PATH } = new URL( - awsEc2DetectorTemp.AWS_INSTANCE_TOKEN_DOCUMENT_URI -); -const { origin: AWS_TEMP1, pathname: AWS_IDENTITY_PATH } = new URL( - awsEc2DetectorTemp.AWS_INSTANCE_IDENTITY_DOCUMENT_URI -); -const { origin: AWS_TEMP2, pathname: AWS_HOST_PATH } = new URL( - awsEc2DetectorTemp.AWS_INSTANCE_HOST_DOCUMENT_URI -); - -const mockedTokenResponse = 'my-token'; -const mockedIdentityResponse = { - instanceId: 'my-instance-id', - instanceType: 'my-instance-type', - accountId: 'my-account-id', - region: 'my-region', - availabilityZone: 'my-zone', -}; -const mockedHostResponse = 'my-hostname'; - -describe('awsEc2DetectorTemp', () => { - before(() => { - nock.disableNetConnect(); - nock.cleanAll(); - }); - - after(() => { - nock.enableNetConnect(); - }); - - describe('with successful request', () => { - it('should return aws_ec2_instance resource', async () => { - const scope = nock(AWS_HOST) - .persist() - .put(AWS_TOKEN_PATH, { "X-aws-ec2-metadata-token-ttl-seconds": "60"} ) - // .matchHeader("X-aws-ec2-metadata-token-ttl-seconds", "60") - .reply(200, () => mockedTokenResponse) - .get(AWS_IDENTITY_PATH) - // .matchHeader("X-aws-ec2-metadata-token", mockedTokenResponse) - .reply(200, () => mockedIdentityResponse) - .get(AWS_HOST_PATH) - // .matchHeader("X-aws-ec2-metadata-token", mockedTokenResponse) - .reply(200, () => mockedHostResponse); - - const resource: Resource = await awsEc2DetectorTemp.detect({ - logger: new NoopLogger(), - }); - - scope.done(); - - assert.ok(resource); - // assert.deepStrictEqual(resource, {1:1}); - assertCloudResource(resource, { - provider: 'aws', - accountId: 'my-account-id', - region: 'my-region', - zone: 'my-zone', - }); - assertHostResource(resource, { - id: 'my-instance-id', - hostType: 'my-instance-type', - name: 'my-hostname', - hostName: 'my-hostname', - }); - }); - }); -}); From f198f3ef3f811120a0e4b2d401814a0998716a26 Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Fri, 7 Aug 2020 15:27:29 -0500 Subject: [PATCH 03/12] chore: fix weird package dependency changing --- .../package.json | 102 ++++++++++-------- 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/packages/opentelemetry-exporter-zipkin/package.json b/packages/opentelemetry-exporter-zipkin/package.json index 9f3346c0e71..ef9eb4187ca 100644 --- a/packages/opentelemetry-exporter-zipkin/package.json +++ b/packages/opentelemetry-exporter-zipkin/package.json @@ -1,43 +1,61 @@ { - "name": "@opentelemetry/exporter-zipkin", - "version": "0.10.2", - "description": "OpenTelemetry Zipkin Exporter allows the user to send collected traces to Zipkin.", - "main": "build/src/index.js", - "types": "build/src/index.d.ts", - "repository": "open-telemetry/opentelemetry-js", - "keywords": [ - "opentelemetry", - "nodejs", - "tracing", - "profiling" - ], - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - }, - "files": [ - "build/src/**/*.js", - "build/src/**/*.js.map", - "build/src/**/*.d.ts", - "doc", - "LICENSE", - "README.md" - ], - "publishConfig": { - "access": "public" - }, - "devDependencies": { - "@types/mocha": "8.0.0", - "@types/node": "14.0.27", - "codecov": "3.7.2", - "gts": "2.0.2", - "mocha": "7.2.0", - "nock": "12.0.3", - "nyc": "15.1.0", - "rimraf": "3.0.2", - "ts-mocha": "7.0.0", - "ts-node": "8.10.2", - "typescript": "3.9.7" - } -} + "name": "@opentelemetry/exporter-zipkin", + "version": "0.10.2", + "description": "OpenTelemetry Zipkin Exporter allows the user to send collected traces to Zipkin.", + "main": "build/src/index.js", + "types": "build/src/index.d.ts", + "repository": "open-telemetry/opentelemetry-js", + "scripts": { + "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'", + "tdd": "npm run test -- --watch-extensions ts --watch", + "clean": "rimraf build/*", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", + "precompile": "tsc --version", + "version:update": "node ../../scripts/version-update.js", + "compile": "npm run version:update && tsc -p .", + "prepare": "npm run compile" + }, + "keywords": [ + "opentelemetry", + "nodejs", + "tracing", + "profiling" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + }, + "files": [ + "build/src/**/*.js", + "build/src/**/*.js.map", + "build/src/**/*.d.ts", + "doc", + "LICENSE", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@types/mocha": "8.0.0", + "@types/node": "14.0.27", + "codecov": "3.7.2", + "gts": "2.0.2", + "mocha": "7.2.0", + "nock": "12.0.3", + "nyc": "15.1.0", + "rimraf": "3.0.2", + "ts-mocha": "7.0.0", + "ts-node": "8.10.2", + "typescript": "3.9.7" + }, + "dependencies": { + "@opentelemetry/api": "^0.10.2", + "@opentelemetry/core": "^0.10.2", + "@opentelemetry/resources": "^0.10.2", + "@opentelemetry/tracing": "^0.10.2" + } +} \ No newline at end of file From 8748fcf955313a245b5e8e5c332e4010f1c0101b Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Fri, 7 Aug 2020 15:28:46 -0500 Subject: [PATCH 04/12] chore: add final line for packages --- packages/opentelemetry-exporter-zipkin/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opentelemetry-exporter-zipkin/package.json b/packages/opentelemetry-exporter-zipkin/package.json index ef9eb4187ca..550b4e7be24 100644 --- a/packages/opentelemetry-exporter-zipkin/package.json +++ b/packages/opentelemetry-exporter-zipkin/package.json @@ -58,4 +58,4 @@ "@opentelemetry/resources": "^0.10.2", "@opentelemetry/tracing": "^0.10.2" } -} \ No newline at end of file +} From 328c56d444416120ddfc658b93741b87d1ad7f88 Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Tue, 11 Aug 2020 12:23:44 -0500 Subject: [PATCH 05/12] chore: modify descriptive type for _fetchString options --- .../src/platform/node/detectors/AwsEc2Detector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts index 521df6d1590..df8f5bb2ffa 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts @@ -126,7 +126,7 @@ class AwsEc2Detector implements Detector { * to get back a valid JSON document. Parses that document and stores * the identity properties in a local map. */ - private async _fetchString(options: Record): Promise { + private async _fetchString(options: http.RequestOptions): Promise { return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { req.abort(); From e2230b03e4f0b7040815ef476e03084299ad6dcd Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Tue, 11 Aug 2020 15:07:06 -0500 Subject: [PATCH 06/12] chore: remove unused variables --- .../src/platform/node/detectors/AwsEc2Detector.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts index df8f5bb2ffa..d3bf318259b 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts @@ -36,12 +36,6 @@ class AwsEc2Detector implements Detector { readonly AWS_INSTANCE_IDENTITY_DOCUMENT_PATH = '/latest/dynamic/instance-identity/document'; readonly AWS_INSTANCE_HOST_DOCUMENT_PATH = '/latest/meta-data/hostname'; - readonly AWS_INSTANCE_IDENTITY_DOCUMENT_URI = - 'http://169.254.169.254/latest/dynamic/instance-identity/document'; - readonly AWS_INSTANCE_TOKEN_DOCUMENT_URI = - 'http://169.254.169.254/latest/api/token'; - readonly AWS_INSTANCE_HOST_DOCUMENT_URI = - 'http://169.254.169.254/latest/meta-data/hostname'; /** * Attempts to connect and obtain an AWS instance Identity document. If the From f46e74cee536c303cc0a64ecd106b4e1851df3ef Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Wed, 12 Aug 2020 13:59:48 -0500 Subject: [PATCH 07/12] chore: modified test name --- .../test/detectors/AwsEc2Detector.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts b/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts index 42a9480c546..c97ea2d56ef 100644 --- a/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts +++ b/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts @@ -40,7 +40,7 @@ const mockedIdentityResponse = { }; const mockedHostResponse = 'my-hostname'; -describe('awsEc2DetectorTemp', () => { +describe('awsEc2Detector', () => { beforeEach(() => { nock.disableNetConnect(); nock.cleanAll(); From e959ee56f10aa5e632f869721a2c63bb310f3ce4 Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Wed, 12 Aug 2020 17:15:22 -0500 Subject: [PATCH 08/12] refactor: replace request header with constant variables --- .../platform/node/detectors/AwsEc2Detector.ts | 8 ++++--- .../test/detect-resources.test.ts | 10 ++++---- .../test/detectors/AwsEc2Detector.test.ts | 24 ++++++++++--------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts index d3bf318259b..ea678457f87 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts @@ -36,6 +36,8 @@ class AwsEc2Detector implements Detector { readonly AWS_INSTANCE_IDENTITY_DOCUMENT_PATH = '/latest/dynamic/instance-identity/document'; readonly AWS_INSTANCE_HOST_DOCUMENT_PATH = '/latest/meta-data/hostname'; + readonly AWS_METADATA_TTL_HEADER = 'X-aws-ec2-metadata-token-ttl-seconds'; + readonly AWS_METADATA_TOKEN_HEADER = 'X-aws-ec2-metadata-token'; /** * Attempts to connect and obtain an AWS instance Identity document. If the @@ -81,7 +83,7 @@ class AwsEc2Detector implements Detector { method: 'PUT', timeout: 1000, headers: { - 'X-aws-ec2-metadata-token-ttl-seconds': '60', + [this.AWS_METADATA_TTL_HEADER]: '60', }, }; return await this._fetchString(options); @@ -94,7 +96,7 @@ class AwsEc2Detector implements Detector { method: 'GET', timeout: 1000, headers: { - 'X-aws-ec2-metadata-token': token, + [this.AWS_METADATA_TOKEN_HEADER]: token, }, }; const identity = await this._fetchString(options); @@ -108,7 +110,7 @@ class AwsEc2Detector implements Detector { method: 'GET', timeout: 1000, headers: { - 'X-aws-ec2-metadata-token': token, + [this.AWS_METADATA_TOKEN_HEADER]: token, }, }; return await this._fetchString(options); diff --git a/packages/opentelemetry-resources/test/detect-resources.test.ts b/packages/opentelemetry-resources/test/detect-resources.test.ts index ad7d7001674..0b5da5c3fcf 100644 --- a/packages/opentelemetry-resources/test/detect-resources.test.ts +++ b/packages/opentelemetry-resources/test/detect-resources.test.ts @@ -46,6 +46,8 @@ const AWS_HOST = awsEc2Detector.HTTP_HEADER + awsEc2Detector.AWS_IDMS_ENDPOINT; const AWS_TOKEN_PATH = awsEc2Detector.AWS_INSTANCE_TOKEN_DOCUMENT_PATH; const AWS_IDENTITY_PATH = awsEc2Detector.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH; const AWS_HOST_PATH = awsEc2Detector.AWS_INSTANCE_HOST_DOCUMENT_PATH; +const AWS_METADATA_TTL_HEADER = awsEc2Detector.AWS_METADATA_TTL_HEADER; +const AWS_METADATA_TOKEN_HEADER = awsEc2Detector.AWS_METADATA_TOKEN_HEADER; const mockedTokenResponse = 'my-token'; const mockedIdentityResponse = { @@ -93,7 +95,7 @@ describe('detectResources', async () => { const awsScope = nock(AWS_HOST) .persist() .put(AWS_TOKEN_PATH) - .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .matchHeader(AWS_METADATA_TTL_HEADER, '60') .replyWithError({ code: 'ENOTFOUND' }); const resource: Resource = await detectResources(); awsScope.done(); @@ -128,13 +130,13 @@ describe('detectResources', async () => { const awsScope = nock(AWS_HOST) .persist() .put(AWS_TOKEN_PATH) - .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .matchHeader(AWS_METADATA_TTL_HEADER, '60') .reply(200, () => mockedTokenResponse) .get(AWS_IDENTITY_PATH) - .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .matchHeader(AWS_METADATA_TOKEN_HEADER, mockedTokenResponse) .reply(200, () => mockedIdentityResponse) .get(AWS_HOST_PATH) - .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .matchHeader(AWS_METADATA_TOKEN_HEADER, mockedTokenResponse) .reply(200, () => mockedHostResponse); const resource: Resource = await detectResources(); gcpSecondaryScope.done(); diff --git a/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts b/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts index c97ea2d56ef..3a149a09525 100644 --- a/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts +++ b/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts @@ -29,6 +29,8 @@ const AWS_HOST = awsEc2Detector.HTTP_HEADER + awsEc2Detector.AWS_IDMS_ENDPOINT; const AWS_TOKEN_PATH = awsEc2Detector.AWS_INSTANCE_TOKEN_DOCUMENT_PATH; const AWS_IDENTITY_PATH = awsEc2Detector.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH; const AWS_HOST_PATH = awsEc2Detector.AWS_INSTANCE_HOST_DOCUMENT_PATH; +const AWS_METADATA_TTL_HEADER = awsEc2Detector.AWS_METADATA_TTL_HEADER; +const AWS_METADATA_TOKEN_HEADER = awsEc2Detector.AWS_METADATA_TOKEN_HEADER; const mockedTokenResponse = 'my-token'; const mockedIdentityResponse = { @@ -55,13 +57,13 @@ describe('awsEc2Detector', () => { const scope = nock(AWS_HOST) .persist() .put(AWS_TOKEN_PATH) - .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .matchHeader(AWS_METADATA_TTL_HEADER, '60') .reply(200, () => mockedTokenResponse) .get(AWS_IDENTITY_PATH) - .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .matchHeader(AWS_METADATA_TOKEN_HEADER, mockedTokenResponse) .reply(200, () => mockedIdentityResponse) .get(AWS_HOST_PATH) - .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .matchHeader(AWS_METADATA_TOKEN_HEADER, mockedTokenResponse) .reply(200, () => mockedHostResponse); const resource: Resource = await awsEc2Detector.detect({ @@ -91,13 +93,13 @@ describe('awsEc2Detector', () => { const scope = nock(AWS_HOST) .persist() .put(AWS_TOKEN_PATH) - .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .matchHeader(AWS_METADATA_TTL_HEADER, '60') .reply(200, () => mockedTokenResponse) .get(AWS_IDENTITY_PATH) - .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .matchHeader(AWS_METADATA_TOKEN_HEADER, mockedTokenResponse) .reply(200, () => mockedIdentityResponse) .get(AWS_HOST_PATH) - .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .matchHeader(AWS_METADATA_TOKEN_HEADER, mockedTokenResponse) .reply(404, () => new Error('NOT FOUND')); const resource: Resource = await awsEc2Detector.detect({ @@ -113,13 +115,13 @@ describe('awsEc2Detector', () => { it('should return empty resource when timeout', async () => { const scope = nock(AWS_HOST) .put(AWS_TOKEN_PATH) - .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .matchHeader(AWS_METADATA_TTL_HEADER, '60') .reply(200, () => mockedTokenResponse) .get(AWS_IDENTITY_PATH) - .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .matchHeader(AWS_METADATA_TOKEN_HEADER, mockedTokenResponse) .reply(200, () => mockedIdentityResponse) .get(AWS_HOST_PATH) - .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .matchHeader(AWS_METADATA_TOKEN_HEADER, mockedTokenResponse) .delayConnection(2000) .reply(200, () => mockedHostResponse); @@ -136,10 +138,10 @@ describe('awsEc2Detector', () => { it('should return empty resource when replied Error', async () => { const scope = nock(AWS_HOST) .put(AWS_TOKEN_PATH) - .matchHeader('X-aws-ec2-metadata-token-ttl-seconds', '60') + .matchHeader(AWS_METADATA_TTL_HEADER, '60') .reply(200, () => mockedTokenResponse) .get(AWS_IDENTITY_PATH) - .matchHeader('X-aws-ec2-metadata-token', mockedTokenResponse) + .matchHeader(AWS_METADATA_TOKEN_HEADER, mockedTokenResponse) .replyWithError('NOT FOUND'); const resource: Resource = await awsEc2Detector.detect({ From 9dafafd4dc93f2ba51ae1819cee555cf4d693949 Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Thu, 13 Aug 2020 14:52:48 -0500 Subject: [PATCH 09/12] chore: modify comment --- .../src/platform/node/detectors/AwsEc2Detector.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts index ea678457f87..36f668c51e4 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts @@ -28,7 +28,8 @@ import { ResourceDetectionConfigWithLogger } from '../../../config'; class AwsEc2Detector implements Detector { /** * See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html - * for documentation about the AWS instance identity document endpoint. + * for documentation about the AWS instance identity document + * and standard of IDMSv2. */ readonly HTTP_HEADER = 'http://'; readonly AWS_IDMS_ENDPOINT = '169.254.169.254'; From 64c418c5a6e69b9901f750b5b4b6a198a3608b50 Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Thu, 13 Aug 2020 15:56:26 -0500 Subject: [PATCH 10/12] refactor: remove HTTP_HEADER constant --- .../src/platform/node/detectors/AwsEc2Detector.ts | 1 - packages/opentelemetry-resources/test/detect-resources.test.ts | 2 +- .../test/detectors/AwsEc2Detector.test.ts | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts index 36f668c51e4..7a0b64e1ac2 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts @@ -31,7 +31,6 @@ class AwsEc2Detector implements Detector { * for documentation about the AWS instance identity document * and standard of IDMSv2. */ - readonly HTTP_HEADER = 'http://'; readonly AWS_IDMS_ENDPOINT = '169.254.169.254'; readonly AWS_INSTANCE_TOKEN_DOCUMENT_PATH = '/latest/api/token'; readonly AWS_INSTANCE_IDENTITY_DOCUMENT_PATH = diff --git a/packages/opentelemetry-resources/test/detect-resources.test.ts b/packages/opentelemetry-resources/test/detect-resources.test.ts index 0b5da5c3fcf..c893042e2db 100644 --- a/packages/opentelemetry-resources/test/detect-resources.test.ts +++ b/packages/opentelemetry-resources/test/detect-resources.test.ts @@ -42,7 +42,7 @@ const PROJECT_ID_PATH = BASE_PATH + '/project/project-id'; const ZONE_PATH = BASE_PATH + '/instance/zone'; const CLUSTER_NAME_PATH = BASE_PATH + '/instance/attributes/cluster-name'; -const AWS_HOST = awsEc2Detector.HTTP_HEADER + awsEc2Detector.AWS_IDMS_ENDPOINT; +const AWS_HOST = 'http://' + awsEc2Detector.AWS_IDMS_ENDPOINT; const AWS_TOKEN_PATH = awsEc2Detector.AWS_INSTANCE_TOKEN_DOCUMENT_PATH; const AWS_IDENTITY_PATH = awsEc2Detector.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH; const AWS_HOST_PATH = awsEc2Detector.AWS_INSTANCE_HOST_DOCUMENT_PATH; diff --git a/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts b/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts index 3a149a09525..910524d8688 100644 --- a/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts +++ b/packages/opentelemetry-resources/test/detectors/AwsEc2Detector.test.ts @@ -25,7 +25,7 @@ import { } from '../util/resource-assertions'; import { NoopLogger } from '@opentelemetry/core'; -const AWS_HOST = awsEc2Detector.HTTP_HEADER + awsEc2Detector.AWS_IDMS_ENDPOINT; +const AWS_HOST = 'http://' + awsEc2Detector.AWS_IDMS_ENDPOINT; const AWS_TOKEN_PATH = awsEc2Detector.AWS_INSTANCE_TOKEN_DOCUMENT_PATH; const AWS_IDENTITY_PATH = awsEc2Detector.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH; const AWS_HOST_PATH = awsEc2Detector.AWS_INSTANCE_HOST_DOCUMENT_PATH; From 06c1f79300dcc672cdad369ddb57e351c682b1b9 Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Thu, 13 Aug 2020 16:22:13 -0500 Subject: [PATCH 11/12] refactor: make time out value constant --- .../src/platform/node/detectors/AwsEc2Detector.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts index 7a0b64e1ac2..202ae1bbcc6 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts @@ -38,6 +38,7 @@ class AwsEc2Detector implements Detector { readonly AWS_INSTANCE_HOST_DOCUMENT_PATH = '/latest/meta-data/hostname'; readonly AWS_METADATA_TTL_HEADER = 'X-aws-ec2-metadata-token-ttl-seconds'; readonly AWS_METADATA_TOKEN_HEADER = 'X-aws-ec2-metadata-token'; + readonly MILLISECOND_TIME_OUT = 1000; /** * Attempts to connect and obtain an AWS instance Identity document. If the @@ -81,7 +82,7 @@ class AwsEc2Detector implements Detector { host: this.AWS_IDMS_ENDPOINT, path: this.AWS_INSTANCE_TOKEN_DOCUMENT_PATH, method: 'PUT', - timeout: 1000, + timeout: this.MILLISECOND_TIME_OUT, headers: { [this.AWS_METADATA_TTL_HEADER]: '60', }, @@ -94,7 +95,7 @@ class AwsEc2Detector implements Detector { host: this.AWS_IDMS_ENDPOINT, path: this.AWS_INSTANCE_IDENTITY_DOCUMENT_PATH, method: 'GET', - timeout: 1000, + timeout: this.MILLISECOND_TIME_OUT, headers: { [this.AWS_METADATA_TOKEN_HEADER]: token, }, @@ -108,7 +109,7 @@ class AwsEc2Detector implements Detector { host: this.AWS_IDMS_ENDPOINT, path: this.AWS_INSTANCE_HOST_DOCUMENT_PATH, method: 'GET', - timeout: 1000, + timeout: this.MILLISECOND_TIME_OUT, headers: { [this.AWS_METADATA_TOKEN_HEADER]: token, }, From 89f4c66e5c234c556aff840669937e5d3784e841 Mon Sep 17 00:00:00 2001 From: EdZou <1018766866@qq.com> Date: Mon, 17 Aug 2020 15:22:58 -0500 Subject: [PATCH 12/12] chore: revise the naming to IMDSv2 --- .../src/platform/node/detectors/AwsEc2Detector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts index e75841b4f68..3b7cf720d9d 100644 --- a/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts +++ b/packages/opentelemetry-resources/src/platform/node/detectors/AwsEc2Detector.ts @@ -29,7 +29,7 @@ class AwsEc2Detector implements Detector { /** * See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html * for documentation about the AWS instance identity document - * and standard of IDMSv2. + * and standard of IMDSv2. */ readonly AWS_IDMS_ENDPOINT = '169.254.169.254'; readonly AWS_INSTANCE_TOKEN_DOCUMENT_PATH = '/latest/api/token';