spec/elastic_apm/metadata/cloud_info_spec.rb (230 lines of code) (raw):

# Licensed to Elasticsearch B.V. under one or more contributor # license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright # ownership. Elasticsearch B.V. licenses this file to you 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. # frozen_string_literal: true require 'spec_helper' module ElasticAPM RSpec.describe Metadata::CloudInfo do module CloudExamples AWS_EXAMPLE = <<-JSON { "devpayProductCodes" : null, "marketplaceProductCodes" : [ "1abc2defghijklm3nopqrs4tu" ], "availabilityZone" : "us-west-2b", "privateIp" : "10.158.112.84", "version" : "2017-09-30", "instanceId" : "i-1234567890abcdef0", "billingProducts" : null, "instanceType" : "t2.micro", "accountId" : "123456789012", "imageId" : "ami-5fb8c835", "pendingTime" : "2016-11-19T16:32:11Z", "architecture" : "x86_64", "kernelId" : null, "ramdiskId" : null, "region" : "us-west-2" } JSON GCP_EXAMPLE = <<-JSON { "instance": { "id": 4306570268266786072, "machineType": "projects/513326162531/machineTypes/n1-standard-1", "name": "basepi-test", "zone": "projects/513326162531/zones/us-west3-a" }, "project": {"numericProjectId": 513326162531, "projectId": "elastic-apm"} } JSON GCP_NO_MACHINE_EXAMPLE = <<-JSON { "instance": { "id": 4306570268266786072, "name": "basepi-test", "zone": "projects/513326162531/zones/us-west3-a" }, "project": {"numericProjectId": 513326162531, "projectId": "elastic-apm"} } JSON GCP_NO_INSTANCE_EXAMPLE = <<-JSON { "project": {"numericProjectId": 513326162531, "projectId": "elastic-apm"} } JSON AZURE_EXAMPLE = <<-JSON { "location": "westus2", "name": "basepi-test", "resourceGroupName": "basepi-testing", "subscriptionId": "7657426d-c4c3-44ac-88a2-3b2cd59e6dba", "vmId": "e11ebedc-019d-427f-84dd-56cd4388d3a8", "vmScaleSetName": "", "vmSize": "Standard_D2s_v3", "zone": "" } JSON end describe '#fetch!' do let(:config) { Config.new } subject { described_class.new(config) } context 'aws' do let(:config) { Config.new(cloud_provider: 'aws') } before do @aws_mock = WebMock.stub_request(:get, Metadata::CloudInfo::AWS_URI) .to_return(body: CloudExamples::AWS_EXAMPLE) end it 'fetches metadata from aws' do subject.fetch! expect(subject.account_id).to eq '123456789012' expect(subject.instance_id).to eq 'i-1234567890abcdef0' expect(subject.availability_zone).to eq 'us-west-2b' expect(subject.provider).to eq 'aws' expect(subject.region).to eq 'us-west-2' expect(@aws_mock).to have_been_requested end end context 'gcp' do let(:config) { Config.new(cloud_provider: 'gcp') } before do @gcp_mock = WebMock.stub_request(:get, Metadata::CloudInfo::GCP_URI) .to_return(body: CloudExamples::GCP_EXAMPLE) end it 'fetches metadata from gcp' do subject.fetch! expect(subject.provider).to eq('gcp') expect(subject.instance_id).to eq("4306570268266786072") expect(subject.instance_name).to eq("basepi-test") expect(subject.project_id).to eq('elastic-apm') expect(subject.availability_zone).to eq('us-west3-a') expect(subject.region).to eq('us-west3') expect(subject.machine_type).to eq('n1-standard-1') expect(@gcp_mock).to have_been_requested end end context 'gcp no machine_type' do let (:config) { Config.new(cloud_provider: 'gcp') } before do @gcp_mock = WebMock.stub_request(:get, Metadata::CloudInfo::GCP_URI) .to_return(body: CloudExamples::GCP_NO_MACHINE_EXAMPLE) end it 'fetches metadata from gcp' do subject.fetch! expect(subject.provider).to eq('gcp') expect(subject.instance_id).to eq("4306570268266786072") expect(subject.instance_name).to eq("basepi-test") expect(subject.project_id).to eq('elastic-apm') expect(subject.availability_zone).to eq('us-west3-a') expect(subject.region).to eq('us-west3') expect(subject.machine_type).to be nil expect(@gcp_mock).to have_been_requested end end context 'gcp no instance' do let (:config) { Config.new(cloud_provider: 'gcp') } before do @gcp_mock = WebMock.stub_request(:get, Metadata::CloudInfo::GCP_URI) .to_return(body: CloudExamples::GCP_NO_INSTANCE_EXAMPLE) end it 'fetches metadata from gcp' do subject.fetch! expect(subject.provider).to eq('gcp') expect(subject.project_id).to eq('elastic-apm') expect(subject.instance_id).to be nil expect(subject.instance_name).to be nil expect(subject.availability_zone).to be nil expect(subject.region).to be nil expect(subject.machine_type).to be nil expect(@gcp_mock).to have_been_requested end end context 'azure' do let(:config) { Config.new(cloud_provider: 'azure') } before do @azure_mock = WebMock.stub_request(:get, Metadata::CloudInfo::AZURE_URI) .to_return(body: CloudExamples::AZURE_EXAMPLE) end it 'fetches metadata from azure' do subject.fetch! expect(subject.provider).to eq "azure" expect(subject.account_id).to eq "7657426d-c4c3-44ac-88a2-3b2cd59e6dba" expect(subject.instance_id).to eq "e11ebedc-019d-427f-84dd-56cd4388d3a8" expect(subject.instance_name).to eq "basepi-test" expect(subject.project_name).to eq "basepi-testing" expect(subject.machine_type).to eq "Standard_D2s_v3" expect(subject.region).to eq "westus2" expect(@azure_mock).to have_been_requested end end context 'azure app services' do let(:config) { Config.new(cloud_provider: 'azure') } before do WebMock.stub_request( :get, Metadata::CloudInfo::AZURE_URI ).to_raise(HTTP::ConnectionError) end it 'reads metadata from ENV' do with_env( 'WEBSITE_OWNER_NAME' => 'f5940f10-2e30-3e4d-a259-63451ba6dae4+elastic-apm-AustraliaEastwebspace', 'WEBSITE_INSTANCE_ID' => '__instance_id', 'WEBSITE_SITE_NAME' => '__site_name', 'WEBSITE_RESOURCE_GROUP' => '__resource_group' ) do subject.fetch! end expect(subject.provider).to eq "azure" expect(subject.account_id).to eq "f5940f10-2e30-3e4d-a259-63451ba6dae4" expect(subject.instance_id).to eq "__instance_id" expect(subject.instance_name).to eq "__site_name" expect(subject.project_name).to eq "__resource_group" expect(subject.region).to eq "AustraliaEast" end end context 'auto' do let(:config) { Config.new(cloud_provider: 'auto') } context 'timeouts' do it 'tries all three' do WebMock.stub_request( :get, Metadata::CloudInfo::AWS_URI ).to_timeout WebMock.stub_request( :get, Metadata::CloudInfo::GCP_URI ).to_timeout WebMock.stub_request( :get, Metadata::CloudInfo::AZURE_URI ).to_timeout subject.fetch! expect(subject.provider).to be nil end end context 'connection errors' do it 'tries all three' do WebMock.stub_request( :get, Metadata::CloudInfo::AWS_URI ).to_raise(HTTP::ConnectionError) WebMock.stub_request( :get, Metadata::CloudInfo::GCP_URI ).to_raise(HTTP::ConnectionError) WebMock.stub_request( :get, Metadata::CloudInfo::AZURE_URI ).to_raise(HTTP::ConnectionError) subject.fetch! expect(subject.provider).to be nil end end end context 'none' do let(:config) { Config.new(cloud_provider: 'none') } it 'tries none' do subject.fetch! expect(subject.provider).to be nil end end end end end