Skip to content

Commit

Permalink
Add specs for config endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
lloeki committed Mar 15, 2023
1 parent 9230461 commit 82cb46b
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 19 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ DD_API_KEY=00000000000000000000000000000000
DD_METRIC_AGENT_PORT=8125
DD_TRACE_AGENT_PORT=8126
DD_INSTRUMENTATION_TELEMETRY_ENABLED=false
DD_REMOTE_CONFIGURATION_ENABLED=true
TEST_DDAGENT_VAR_RUN=/var/run/datadog
TEST_DDAGENT_UNIX_SOCKET=${TEST_DDAGENT_VAR_RUN}/apm.socket
TEST_DDAGENT_API_KEY=invalid_key_but_this_is_fine
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ services:
- "DD_API_KEY=${DD_API_KEY}"
- DD_HOSTNAME=dd-trace-rb-ci
- DD_APM_RECEIVER_SOCKET=/var/run/datadog/apm.socket
- DD_REMOTE_CONFIGURATION_ENABLED=true
expose:
- "8125/udp"
- "8126"
Expand Down
173 changes: 154 additions & 19 deletions spec/datadog/core/transport/http_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,31 @@
require 'datadog/core/transport/negotiation'

RSpec.describe Datadog::Core::Transport::HTTP do
shared_context 'HTTP connection stub' do
before do
request_class = case request_verb
when :get then ::Net::HTTP::Get
when :post then ::Net::HTTP::Post
else raise "bad verb: #{request_verb.inspect}"
end
http_request = instance_double(request_class)
allow(http_request).to receive(:body=)
allow(request_class).to receive(:new).and_return(http_request)

http_connection = instance_double(::Net::HTTP)
allow(::Net::HTTP).to receive(:new).and_return(http_connection)

allow(http_connection).to receive(:open_timeout=)
allow(http_connection).to receive(:read_timeout=)
allow(http_connection).to receive(:use_ssl=)

allow(http_connection).to receive(:start).and_yield(http_connection)

http_response = instance_double(::Net::HTTPResponse, body: response_body, code: response_code)
allow(http_connection).to receive(:request).with(http_request).and_return(http_response)
end
end

describe '.root' do
subject(:transport) { described_class.root(&client_options) }

Expand All @@ -15,6 +40,8 @@
it { is_expected.to be_a(Datadog::Core::Transport::Negotiation::Transport) }

describe '#send_info' do
include_context 'HTTP connection stub'

subject(:response) { transport.send_info }

let(:request_verb) { :get }
Expand All @@ -35,33 +62,141 @@
)
end

before do
request_class = case request_verb
when :get then ::Net::HTTP::Get
else raise "bad verb: #{request_verb.inspect}"
end
http_request = instance_double(request_class)
allow(request_class).to receive(:new).and_return(http_request)
it { is_expected.to be_a(Datadog::Core::Transport::HTTP::Negotiation::Response) }

it { is_expected.to be_ok }
it { is_expected.to have_attributes(:version => '42') }
it { is_expected.to have_attributes(:endpoints => ['/info', '/v0/path']) }
it { is_expected.to have_attributes(:config => { max_request_bytes: '1234' }) }
end
end

describe '.v7' do
subject(:transport) { described_class.v7(&client_options) }

http_connection = instance_double(::Net::HTTP)
allow(::Net::HTTP).to receive(:new).and_return(http_connection)
let(:client_options) { proc { |_client| } }

allow(http_connection).to receive(:open_timeout=)
allow(http_connection).to receive(:read_timeout=)
allow(http_connection).to receive(:use_ssl=)
it { is_expected.to be_a(Datadog::Core::Transport::Config::Transport) }

allow(http_connection).to receive(:start).and_yield(http_connection)
describe '#send_config' do
include_context 'HTTP connection stub'

http_response = instance_double(::Net::HTTPResponse, body: response_body, code: response_code)
allow(http_connection).to receive(:request).with(http_request).and_return(http_response)
let(:state) do
OpenStruct.new(
{
root_version: 1, # unverified mode, so 1
targets_version: 0, # from scratch, so zero
config_states: [], # from scratch, so empty
has_error: false, # from scratch, so false
error: '', # from scratch, so blank
opaque_backend_state: '', # from scratch, so blank
}
)
end

it { is_expected.to be_a(Datadog::Core::Transport::HTTP::Negotiation::Response) }
let(:id) { SecureRandom.uuid }

let(:products) { [] }

let(:capabilities) { 0 }

let(:capabilities_binary) do
capabilities
.to_s(16)
.tap { |s| s.size.odd? && s.prepend('0') }
.scan(/\h\h/)
.map { |e| e.to_i(16) }
.pack('C*')
end

let(:payload) do
{
client: {
state: {
root_version: state.root_version,
targets_version: state.targets_version,
config_states: state.config_states,
has_error: state.has_error,
error: state.error,
backend_client_state: state.opaque_backend_state,
},
id: id,
products: products,
is_tracer: true,
is_agent: false,
client_tracer: {
runtime_id: Datadog::Core::Environment::Identity.id,
language: Datadog::Core::Environment::Identity.lang,
tracer_version: Datadog::Core::Environment::Identity.tracer_version,
service: Datadog.configuration.service,
env: Datadog.configuration.env,
tags: [],
},
capabilities: Base64.encode64(capabilities_binary).chomp,
},
cached_target_files: [],
}
end

subject(:response) { transport.send_config(payload) }

let(:request_verb) { :post }

let(:response_code) { 200 }
let(:response_body) do
encode = Proc.new do |obj|
Base64.strict_encode64(obj).chomp
end

jencode = Proc.new do |obj|
Base64.strict_encode64(JSON.dump(obj)).chomp
end

JSON.dump(
{
roots: [
jencode.call({}),
jencode.call({}),
],
targets: jencode.call({
signed: {
expires: '2022-09-22T09:01:04Z',
targets: {
'datadog/42/PRODUCT/foo/config' => {
hashes: { sha256: 'd0b425e00e15a0d36b9b361f02bab63563aed6cb4665083905386c55d5b679fa' },
length: 8,
},
'employee/PRODUCT/bar/config' => {
hashes: { sha256: 'dab741b6289e7dccc1ed42330cae1accc2b755ce8079c2cd5d4b5366c9f769a6' },
length: 8,
},
}
}
}),
target_files: [
{
path: 'datadog/42/PRODUCT/foo/config',
raw: encode.call('content1'),
},
{
path: 'employee/PRODUCT/bar/config',
raw: encode.call('content2'),
},
],
client_configs: [
'datadog/42/PRODUCT/foo/config',
'employee/PRODUCT/bar/config',
],
}
)
end

it { is_expected.to be_a(Datadog::Core::Transport::HTTP::Config::Response) }

it { is_expected.to be_ok }
it { is_expected.to have_attributes(:version => '42') }
it { is_expected.to have_attributes(:endpoints => ['/info', '/v0/path']) }
it { is_expected.to have_attributes(:config => { max_request_bytes: '1234' }) }
it { is_expected.to have_attributes(:roots => be_a(Array)) }
it { is_expected.to have_attributes(:targets => be_a(Hash)) }
it { is_expected.to have_attributes(:target_files => be_a(Array)) }
end
end
end
75 changes: 75 additions & 0 deletions spec/datadog/core/transport/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,79 @@
it { is_expected.to_not have_attributes(:config => be_nil) }
end
end

describe '.v7' do
subject(:transport) { described_class.v7(&client_options) }

let(:client_options) { proc { |_client| } }

it { is_expected.to be_a(Datadog::Core::Transport::Config::Transport) }

describe '#send_config' do
let(:state) do
OpenStruct.new(
{
root_version: 1, # unverified mode, so 1
targets_version: 0, # from scratch, so zero
config_states: [], # from scratch, so empty
has_error: false, # from scratch, so false
error: '', # from scratch, so blank
opaque_backend_state: '', # from scratch, so blank
}
)
end

let(:id) { SecureRandom.uuid }

let(:products) { [] }

let(:capabilities) { 0 }

let(:capabilities_binary) do
capabilities
.to_s(16)
.tap { |s| s.size.odd? && s.prepend('0') }
.scan(/\h\h/)
.map { |e| e.to_i(16) }
.pack('C*')
end

let(:payload) do
{
client: {
state: {
root_version: state.root_version,
targets_version: state.targets_version,
config_states: state.config_states,
has_error: state.has_error,
error: state.error,
backend_client_state: state.opaque_backend_state,
},
id: id,
products: products,
is_tracer: true,
is_agent: false,
client_tracer: {
runtime_id: Datadog::Core::Environment::Identity.id,
language: Datadog::Core::Environment::Identity.lang,
tracer_version: Datadog::Core::Environment::Identity.tracer_version,
service: Datadog.configuration.service,
env: Datadog.configuration.env,
tags: [],
},
capabilities: Base64.encode64(capabilities_binary).chomp,
},
cached_target_files: [],
}
end

subject(:response) { transport.send_config(payload) }

it { is_expected.to be_a(Datadog::Core::Transport::HTTP::Config::Response) }

it { is_expected.to be_ok }
it { is_expected.to_not have_attributes(:roots => be_nil) }
it { is_expected.to_not have_attributes(:targets => be_nil) }
end
end
end

0 comments on commit 82cb46b

Please sign in to comment.