From 85315ef3eda58c304a3015743d52bb3332e9c21d Mon Sep 17 00:00:00 2001 From: Nat Lasseter Date: Thu, 11 Dec 2025 16:26:28 +0000 Subject: [PATCH] Add Front and Rear Port entities --- README.md | 2 + lib/netbox_client_ruby/api/dcim.rb | 4 + lib/netbox_client_ruby/api/dcim/front_port.rb | 14 ++ .../api/dcim/front_ports.rb | 20 +++ lib/netbox_client_ruby/api/dcim/rear_port.rb | 14 ++ lib/netbox_client_ruby/api/dcim/rear_ports.rb | 20 +++ spec/fixtures/dcim/front-port_1.json | 10 ++ spec/fixtures/dcim/front-ports.json | 17 +++ spec/fixtures/dcim/rear-port_1.json | 10 ++ spec/fixtures/dcim/rear-ports.json | 17 +++ .../api/dcim/front_port_spec.rb | 138 ++++++++++++++++++ .../api/dcim/front_ports_spec.rb | 59 ++++++++ .../api/dcim/rear_port_spec.rb | 138 ++++++++++++++++++ .../api/dcim/rear_ports_spec.rb | 59 ++++++++ spec/netbox_client_ruby/api/dcim_spec.rb | 4 + 15 files changed, 526 insertions(+) create mode 100644 lib/netbox_client_ruby/api/dcim/front_port.rb create mode 100644 lib/netbox_client_ruby/api/dcim/front_ports.rb create mode 100644 lib/netbox_client_ruby/api/dcim/rear_port.rb create mode 100644 lib/netbox_client_ruby/api/dcim/rear_ports.rb create mode 100644 spec/fixtures/dcim/front-port_1.json create mode 100644 spec/fixtures/dcim/front-ports.json create mode 100644 spec/fixtures/dcim/rear-port_1.json create mode 100644 spec/fixtures/dcim/rear-ports.json create mode 100644 spec/netbox_client_ruby/api/dcim/front_port_spec.rb create mode 100644 spec/netbox_client_ruby/api/dcim/front_ports_spec.rb create mode 100644 spec/netbox_client_ruby/api/dcim/rear_port_spec.rb create mode 100644 spec/netbox_client_ruby/api/dcim/rear_ports_spec.rb diff --git a/README.md b/README.md index 8d03341..f983e36 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,7 @@ Not all objects which the Netbox API exposes are currently implemented. Implemen * Devices: `NetboxClientRuby.dcim.devices` * Device Roles: `NetboxClientRuby.dcim.device_roles` * Device Types: `NetboxClientRuby.dcim.device_types` + * Front Ports: `NetboxClientRuby.dcim.front_ports` * Interfaces: `NetboxClientRuby.dcim.interfaces` * Interface Connections: `NetboxClientRuby.dcim.interface_connections` * Manufacturers: `NetboxClientRuby.dcim.manufacturers` @@ -166,6 +167,7 @@ Not all objects which the Netbox API exposes are currently implemented. Implemen * Rack Groups: `NetboxClientRuby.dcim.rack_groups` * Rack Roles: `NetboxClientRuby.dcim.rack_roles` * Rack Reservations: `NetboxClientRuby.dcim.rack_reservations` + * Rear Ports: `NetboxClientRuby.dcim.rear_ports` * Regions: `NetboxClientRuby.dcim.regions` * Sites: `NetboxClientRuby.dcim.sites` * Virtual Chassis: `NetboxClientRuby.dcim.virtual_chassis_list` diff --git a/lib/netbox_client_ruby/api/dcim.rb b/lib/netbox_client_ruby/api/dcim.rb index 3386f50..a3cbe86 100644 --- a/lib/netbox_client_ruby/api/dcim.rb +++ b/lib/netbox_client_ruby/api/dcim.rb @@ -9,6 +9,7 @@ module DCIM devices: Devices, device_roles: DeviceRoles, device_types: DeviceTypes, + front_ports: FrontPorts, interfaces: Interfaces, interface_connections: InterfaceConnections, inventory_items: InventoryItems, @@ -22,6 +23,7 @@ module DCIM rack_groups: RackGroups, rack_reservations: RackReservations, rack_roles: RackRoles, + rear_ports: RearPorts, regions: Regions, sites: Sites, virtual_chassis_list: VirtualChassisList, @@ -36,6 +38,7 @@ module DCIM device: Device, device_role: DeviceRole, device_type: DeviceType, + front_port: FrontPort, interface: Interface, interface_connection: InterfaceConnection, inventory_item: InventoryItem, @@ -49,6 +52,7 @@ module DCIM rack_group: RackGroup, rack_reservation: RackReservation, rack_role: RackRole, + rear_port: RearPort, region: Region, site: Site, virtual_chassis: VirtualChassis, diff --git a/lib/netbox_client_ruby/api/dcim/front_port.rb b/lib/netbox_client_ruby/api/dcim/front_port.rb new file mode 100644 index 0000000..b5b7894 --- /dev/null +++ b/lib/netbox_client_ruby/api/dcim/front_port.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module DCIM + class FrontPort + include Entity + + id id: :id + deletable true + path 'dcim/front-ports/:id/' + creation_path 'dcim/front-ports/' + end + end +end diff --git a/lib/netbox_client_ruby/api/dcim/front_ports.rb b/lib/netbox_client_ruby/api/dcim/front_ports.rb new file mode 100644 index 0000000..35e336b --- /dev/null +++ b/lib/netbox_client_ruby/api/dcim/front_ports.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module DCIM + class FrontPorts + include Entities + + path 'dcim/front-ports/' + data_key 'results' + count_key 'count' + entity_creator :entity_creator + + private + + def entity_creator(raw_entity) + FrontPort.new raw_entity['id'] + end + end + end +end diff --git a/lib/netbox_client_ruby/api/dcim/rear_port.rb b/lib/netbox_client_ruby/api/dcim/rear_port.rb new file mode 100644 index 0000000..7a5b452 --- /dev/null +++ b/lib/netbox_client_ruby/api/dcim/rear_port.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module DCIM + class RearPort + include Entity + + id id: :id + deletable true + path 'dcim/rear-ports/:id/' + creation_path 'dcim/rear-ports/' + end + end +end diff --git a/lib/netbox_client_ruby/api/dcim/rear_ports.rb b/lib/netbox_client_ruby/api/dcim/rear_ports.rb new file mode 100644 index 0000000..9197f06 --- /dev/null +++ b/lib/netbox_client_ruby/api/dcim/rear_ports.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module DCIM + class RearPorts + include Entities + + path 'dcim/rear-ports/' + data_key 'results' + count_key 'count' + entity_creator :entity_creator + + private + + def entity_creator(raw_entity) + RearPort.new raw_entity['id'] + end + end + end +end diff --git a/spec/fixtures/dcim/front-port_1.json b/spec/fixtures/dcim/front-port_1.json new file mode 100644 index 0000000..a7673ad --- /dev/null +++ b/spec/fixtures/dcim/front-port_1.json @@ -0,0 +1,10 @@ +{ + "id": 1, + "name": "1", + "slug": "1", + "type": { + "value": "8p8c", + "label": "8P8C" + }, + "description": "The first front port" +} diff --git a/spec/fixtures/dcim/front-ports.json b/spec/fixtures/dcim/front-ports.json new file mode 100644 index 0000000..0c76b5a --- /dev/null +++ b/spec/fixtures/dcim/front-ports.json @@ -0,0 +1,17 @@ +{ + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "id": 1, + "name": "1", + "slug": "1", + "type": { + "value": "8p8c", + "label": "8P8C" + }, + "description": "The first front port" + } + ] +} diff --git a/spec/fixtures/dcim/rear-port_1.json b/spec/fixtures/dcim/rear-port_1.json new file mode 100644 index 0000000..4940a2b --- /dev/null +++ b/spec/fixtures/dcim/rear-port_1.json @@ -0,0 +1,10 @@ +{ + "id": 1, + "name": "1", + "slug": "1", + "type": { + "value": "8p8c", + "label": "8P8C" + }, + "description": "The first rear port" +} diff --git a/spec/fixtures/dcim/rear-ports.json b/spec/fixtures/dcim/rear-ports.json new file mode 100644 index 0000000..3660580 --- /dev/null +++ b/spec/fixtures/dcim/rear-ports.json @@ -0,0 +1,17 @@ +{ + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "id": 1, + "name": "1", + "slug": "1", + "type": { + "value": "8p8c", + "label": "8P8C" + }, + "description": "The first rear port" + } + ] +} diff --git a/spec/netbox_client_ruby/api/dcim/front_port_spec.rb b/spec/netbox_client_ruby/api/dcim/front_port_spec.rb new file mode 100644 index 0000000..382c69d --- /dev/null +++ b/spec/netbox_client_ruby/api/dcim/front_port_spec.rb @@ -0,0 +1,138 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::DCIM::FrontPort, faraday_stub: true do + subject { sut.new entity_id } + + let(:entity_id) { 1 } + let(:expected_name) { '1' } + let(:sut) { described_class } + let(:base_url) { '/api/dcim/front-ports/' } + + let(:request_url) { "#{base_url}#{entity_id}/" } + let(:response) { File.read("spec/fixtures/dcim/front-port_#{entity_id}.json") } + + describe '#id' do + it 'shall be the expected id' do + expect(subject.id).to eq(entity_id) + end + end + + describe '#name' do + it 'fetches the data' do + expect(faraday).to receive(:get).and_call_original + + expect(subject.name).to_not be_nil + end + + it 'shall be the expected name' do + expect(subject.name).to eq(expected_name) + end + end + + describe '.delete' do + let(:request_method) { :delete } + let(:response_status) { 204 } + let(:response) { nil } + + it 'deletes the object' do + expect(faraday).to receive(request_method).and_call_original + subject.delete + end + end + + describe '.update' do + let(:request_method) { :patch } + let(:request_params) { { 'name' => 'noob' } } + + it 'updates the object' do + expect(faraday).to receive(request_method).and_call_original + expect(subject.update(name: 'noob').name).to eq(expected_name) + end + end + + describe '.reload' do + it 'reloads the object' do + expect(faraday).to receive(request_method).twice.and_call_original + + subject.reload + subject.reload + end + end + + describe '.save' do + let(:name) { 'foobar' } + let(:slug) { name } + let(:request_params) { { 'name' => name, 'slug' => slug } } + + context 'update' do + subject do + region = sut.new entity_id + region.name = name + region.slug = slug + region + end + + let(:request_method) { :patch } + + it 'does not call PATCH until save is called' do + expect(faraday).to_not receive(request_method) + expect(faraday).to_not receive(:get) + + expect(subject.name).to eq(name) + expect(subject.slug).to eq(slug) + end + + it 'calls PATCH when save is called' do + expect(faraday).to receive(request_method).and_call_original + + expect(subject.save).to be(subject) + end + + it 'Reads the answer from the PATCH answer' do + expect(faraday).to receive(request_method).and_call_original + + subject.save + expect(subject.name).to eq(expected_name) + expect(subject.slug).to eq(expected_name) + end + end + + context 'create' do + subject do + region = sut.new + region.name = name + region.slug = slug + region + end + + let(:request_method) { :post } + let(:request_url) { base_url } + + it 'does not POST until save is called' do + expect(faraday).to_not receive(request_method) + expect(faraday).to_not receive(:get) + + expect(subject.name).to eq(name) + expect(subject.slug).to eq(slug) + end + + it 'POSTs the data upon a call of save' do + expect(faraday).to receive(request_method).and_call_original + + expect(subject.save).to be(subject) + end + + it 'Reads the answer from the POST' do + expect(faraday).to receive(request_method).and_call_original + + subject.save + + expect(subject.id).to be(1) + expect(subject.name).to eq(expected_name) + expect(subject.slug).to eq(expected_name) + end + end + end +end diff --git a/spec/netbox_client_ruby/api/dcim/front_ports_spec.rb b/spec/netbox_client_ruby/api/dcim/front_ports_spec.rb new file mode 100644 index 0000000..5bee79b --- /dev/null +++ b/spec/netbox_client_ruby/api/dcim/front_ports_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::DCIM::FrontPorts, faraday_stub: true do + let(:expected_length) { 1 } + let(:singular_type) { NetboxClientRuby::DCIM::FrontPort } + + let(:response) { File.read('spec/fixtures/dcim/front-ports.json') } + let(:request_url) { '/api/dcim/front-ports/' } + let(:request_url_params) do + { limit: NetboxClientRuby.config.netbox.pagination.default_limit } + end + + context 'unpaged fetch' do + describe '#length' do + it 'shall be the expected length' do + expect(subject.length).to be expected_length + end + end + + describe '#total' do + it 'shall be the expected total' do + expect(subject.total).to be expected_length + end + end + end + + describe '#reload' do + it 'fetches the correct data' do + expect(faraday).to receive(:get).and_call_original + subject.reload + end + + it 'caches the data' do + expect(faraday).to receive(:get).and_call_original + subject.total + subject.total + end + + it 'reloads the data' do + expect(faraday).to receive(:get).twice.and_call_original + subject.reload + subject.reload + end + end + + describe '#as_array' do + it 'return the correct amount' do + expect(subject.to_a.length).to be expected_length + end + + it 'returns FrontPort instances' do + subject.to_a.each do |element| + expect(element).to be_a singular_type + end + end + end +end diff --git a/spec/netbox_client_ruby/api/dcim/rear_port_spec.rb b/spec/netbox_client_ruby/api/dcim/rear_port_spec.rb new file mode 100644 index 0000000..4c876c7 --- /dev/null +++ b/spec/netbox_client_ruby/api/dcim/rear_port_spec.rb @@ -0,0 +1,138 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::DCIM::RearPort, faraday_stub: true do + subject { sut.new entity_id } + + let(:entity_id) { 1 } + let(:expected_name) { '1' } + let(:sut) { described_class } + let(:base_url) { '/api/dcim/rear-ports/' } + + let(:request_url) { "#{base_url}#{entity_id}/" } + let(:response) { File.read("spec/fixtures/dcim/rear-port_#{entity_id}.json") } + + describe '#id' do + it 'shall be the expected id' do + expect(subject.id).to eq(entity_id) + end + end + + describe '#name' do + it 'fetches the data' do + expect(faraday).to receive(:get).and_call_original + + expect(subject.name).to_not be_nil + end + + it 'shall be the expected name' do + expect(subject.name).to eq(expected_name) + end + end + + describe '.delete' do + let(:request_method) { :delete } + let(:response_status) { 204 } + let(:response) { nil } + + it 'deletes the object' do + expect(faraday).to receive(request_method).and_call_original + subject.delete + end + end + + describe '.update' do + let(:request_method) { :patch } + let(:request_params) { { 'name' => 'noob' } } + + it 'updates the object' do + expect(faraday).to receive(request_method).and_call_original + expect(subject.update(name: 'noob').name).to eq(expected_name) + end + end + + describe '.reload' do + it 'reloads the object' do + expect(faraday).to receive(request_method).twice.and_call_original + + subject.reload + subject.reload + end + end + + describe '.save' do + let(:name) { 'foobar' } + let(:slug) { name } + let(:request_params) { { 'name' => name, 'slug' => slug } } + + context 'update' do + subject do + region = sut.new entity_id + region.name = name + region.slug = slug + region + end + + let(:request_method) { :patch } + + it 'does not call PATCH until save is called' do + expect(faraday).to_not receive(request_method) + expect(faraday).to_not receive(:get) + + expect(subject.name).to eq(name) + expect(subject.slug).to eq(slug) + end + + it 'calls PATCH when save is called' do + expect(faraday).to receive(request_method).and_call_original + + expect(subject.save).to be(subject) + end + + it 'Reads the answer from the PATCH answer' do + expect(faraday).to receive(request_method).and_call_original + + subject.save + expect(subject.name).to eq(expected_name) + expect(subject.slug).to eq(expected_name) + end + end + + context 'create' do + subject do + region = sut.new + region.name = name + region.slug = slug + region + end + + let(:request_method) { :post } + let(:request_url) { base_url } + + it 'does not POST until save is called' do + expect(faraday).to_not receive(request_method) + expect(faraday).to_not receive(:get) + + expect(subject.name).to eq(name) + expect(subject.slug).to eq(slug) + end + + it 'POSTs the data upon a call of save' do + expect(faraday).to receive(request_method).and_call_original + + expect(subject.save).to be(subject) + end + + it 'Reads the answer from the POST' do + expect(faraday).to receive(request_method).and_call_original + + subject.save + + expect(subject.id).to be(1) + expect(subject.name).to eq(expected_name) + expect(subject.slug).to eq(expected_name) + end + end + end +end diff --git a/spec/netbox_client_ruby/api/dcim/rear_ports_spec.rb b/spec/netbox_client_ruby/api/dcim/rear_ports_spec.rb new file mode 100644 index 0000000..ca1ea8c --- /dev/null +++ b/spec/netbox_client_ruby/api/dcim/rear_ports_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::DCIM::RearPorts, faraday_stub: true do + let(:expected_length) { 1 } + let(:singular_type) { NetboxClientRuby::DCIM::RearPort } + + let(:response) { File.read('spec/fixtures/dcim/rear-ports.json') } + let(:request_url) { '/api/dcim/rear-ports/' } + let(:request_url_params) do + { limit: NetboxClientRuby.config.netbox.pagination.default_limit } + end + + context 'unpaged fetch' do + describe '#length' do + it 'shall be the expected length' do + expect(subject.length).to be expected_length + end + end + + describe '#total' do + it 'shall be the expected total' do + expect(subject.total).to be expected_length + end + end + end + + describe '#reload' do + it 'fetches the correct data' do + expect(faraday).to receive(:get).and_call_original + subject.reload + end + + it 'caches the data' do + expect(faraday).to receive(:get).and_call_original + subject.total + subject.total + end + + it 'reloads the data' do + expect(faraday).to receive(:get).twice.and_call_original + subject.reload + subject.reload + end + end + + describe '#as_array' do + it 'return the correct amount' do + expect(subject.to_a.length).to be expected_length + end + + it 'returns RearPort instances' do + subject.to_a.each do |element| + expect(element).to be_a singular_type + end + end + end +end diff --git a/spec/netbox_client_ruby/api/dcim_spec.rb b/spec/netbox_client_ruby/api/dcim_spec.rb index 823d747..9dd3ae5 100644 --- a/spec/netbox_client_ruby/api/dcim_spec.rb +++ b/spec/netbox_client_ruby/api/dcim_spec.rb @@ -12,6 +12,7 @@ module DCIM devices: Devices, device_roles: DeviceRoles, device_types: DeviceTypes, + front_ports: FrontPorts, interfaces: Interfaces, interface_connections: InterfaceConnections, inventory_items: InventoryItems, @@ -25,6 +26,7 @@ module DCIM rack_groups: RackGroups, rack_reservations: RackReservations, rack_roles: RackRoles, + rear_ports: RearPorts, regions: Regions, sites: Sites, virtual_chassis_list: VirtualChassisList, @@ -56,6 +58,7 @@ module DCIM device: Device, device_role: DeviceRole, device_type: DeviceType, + front_port: FrontPort, interface: Interface, interface_connection: InterfaceConnection, inventory_item: InventoryItem, @@ -69,6 +72,7 @@ module DCIM rack_group: RackGroup, rack_reservation: RackReservation, rack_role: RackRole, + rear_port: RearPort, region: Region, site: Site, virtual_chassis: VirtualChassis,