From 019e2bfcd1da973d9065ba33a7d638e910d06a76 Mon Sep 17 00:00:00 2001 From: Benny Lyne Amorsen Date: Wed, 8 Jul 2026 11:23:22 +0200 Subject: [PATCH] Add support for SiteGroups --- lib/netbox_client_ruby/api/dcim.rb | 2 + lib/netbox_client_ruby/api/dcim/site_group.rb | 15 ++ .../api/dcim/site_groups.rb | 20 +++ spec/fixtures/dcim/site-group_1.json | 6 + spec/fixtures/dcim/site-group_2.json | 12 ++ spec/fixtures/dcim/site-groups.json | 24 +++ .../api/dcim/site_group_spec.rb | 170 ++++++++++++++++++ .../api/dcim/site_groups_spec.rb | 56 ++++++ spec/netbox_client_ruby/api/dcim_spec.rb | 2 + 9 files changed, 307 insertions(+) create mode 100644 lib/netbox_client_ruby/api/dcim/site_group.rb create mode 100644 lib/netbox_client_ruby/api/dcim/site_groups.rb create mode 100644 spec/fixtures/dcim/site-group_1.json create mode 100644 spec/fixtures/dcim/site-group_2.json create mode 100644 spec/fixtures/dcim/site-groups.json create mode 100644 spec/netbox_client_ruby/api/dcim/site_group_spec.rb create mode 100644 spec/netbox_client_ruby/api/dcim/site_groups_spec.rb diff --git a/lib/netbox_client_ruby/api/dcim.rb b/lib/netbox_client_ruby/api/dcim.rb index 28a089a..b3e679c 100644 --- a/lib/netbox_client_ruby/api/dcim.rb +++ b/lib/netbox_client_ruby/api/dcim.rb @@ -28,6 +28,7 @@ module DCIM rear_ports: RearPorts, regions: Regions, sites: Sites, + site_groups: SiteGroups, virtual_chassis_list: VirtualChassisList, }.each_pair do |method_name, class_name| NetboxClientRuby.load_collection(self, method_name, class_name) @@ -59,6 +60,7 @@ module DCIM rear_port: RearPort, region: Region, site: Site, + site_group: SiteGroup, virtual_chassis: VirtualChassis, }.each_pair do |method_name, class_name| NetboxClientRuby.load_entity(self, method_name, class_name) diff --git a/lib/netbox_client_ruby/api/dcim/site_group.rb b/lib/netbox_client_ruby/api/dcim/site_group.rb new file mode 100644 index 0000000..dfeb4d5 --- /dev/null +++ b/lib/netbox_client_ruby/api/dcim/site_group.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module DCIM + class SiteGroup + include Entity + + id id: :id + deletable true + path 'dcim/site-groups/:id/' + creation_path 'dcim/site-groups/' + object_fields parent: proc { |raw_data| SiteGroup.new raw_data['id'] } + end + end +end diff --git a/lib/netbox_client_ruby/api/dcim/site_groups.rb b/lib/netbox_client_ruby/api/dcim/site_groups.rb new file mode 100644 index 0000000..832854b --- /dev/null +++ b/lib/netbox_client_ruby/api/dcim/site_groups.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module DCIM + class SiteGroups + include Entities + + path 'dcim/site-groups/' + data_key 'results' + count_key 'count' + entity_creator :entity_creator + + private + + def entity_creator(raw_entity) + SiteGroup.new raw_entity['id'] + end + end + end +end diff --git a/spec/fixtures/dcim/site-group_1.json b/spec/fixtures/dcim/site-group_1.json new file mode 100644 index 0000000..55a34b3 --- /dev/null +++ b/spec/fixtures/dcim/site-group_1.json @@ -0,0 +1,6 @@ +{ + "id": 1, + "name": "sitegroup1", + "slug": "sitegroup1", + "parent": null +} diff --git a/spec/fixtures/dcim/site-group_2.json b/spec/fixtures/dcim/site-group_2.json new file mode 100644 index 0000000..92e09dd --- /dev/null +++ b/spec/fixtures/dcim/site-group_2.json @@ -0,0 +1,12 @@ +{ + "id": 2, + "name": "sub_sitegroup1", + "slug": "sub_sitegroup1", + "parent": { + "id": 1, + "url": "http://localhost/api/dcim/site-groups/1/", + "name": "sitegroup1", + "slug": "sitegroup1" + } +} + diff --git a/spec/fixtures/dcim/site-groups.json b/spec/fixtures/dcim/site-groups.json new file mode 100644 index 0000000..7f3fce5 --- /dev/null +++ b/spec/fixtures/dcim/site-groups.json @@ -0,0 +1,24 @@ +{ + "count": 2, + "next": null, + "previous": null, + "results": [ + { + "id": 1, + "name": "sitegroup1", + "slug": "sitegroup1", + "parent": null + }, + { + "id": 2, + "name": "sub_sitegroup1", + "slug": "sub_sitegroup1", + "parent": { + "id": 1, + "url": "http://localhost/api/dcim/site-groups/1/", + "name": "sitegroup1", + "slug": "sitegroup1" + } + } + ] +} diff --git a/spec/netbox_client_ruby/api/dcim/site_group_spec.rb b/spec/netbox_client_ruby/api/dcim/site_group_spec.rb new file mode 100644 index 0000000..dd51205 --- /dev/null +++ b/spec/netbox_client_ruby/api/dcim/site_group_spec.rb @@ -0,0 +1,170 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::DCIM::SiteGroup, faraday_stub: true do + subject { described_class.new site_group_id } + + let(:site_group_id) { 1 } + let(:response) { File.read("spec/fixtures/dcim/site-group_#{site_group_id}.json") } + let(:request_url) { "/api/dcim/site-groups/#{site_group_id}/" } + + describe '#id' do + it 'shall be the expected id' do + expect(subject.id).to eq(site_group_id) + end + end + + describe '#name' do + it 'fetches the data' do + expect(faraday).to receive(:get).and_call_original + + subject.name + end + + it 'shall be the expected name' do + expect(subject.name).to eq('sitegroup1') + end + end + + describe '.parent' do + it 'is nil' do + expect(subject.parent).to be_nil + end + + context 'Sub SiteGroup' do + let(:site_group_id) { 2 } + + it 'is a SiteGroup object' do + parent_site_group = subject.parent + expect(parent_site_group).to be_a described_class + expect(parent_site_group.id).to eq(1) + end + 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('sitegroup1') + end + + context 'Sub SiteGroup' do + let(:site_group_id) { 2 } + + context 'delete a parent' do + let(:request_params) { { 'parent' => nil } } + + it 'removes the parent' do + expect(subject.update(parent: nil)).to be subject + end + end + + context 'add a parent' do + let(:request_params) { { 'parent' => 1 } } + + it 'adds a parent' do + expect(subject.update(parent: 1)).to be subject + end + end + 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 + site_group = described_class.new site_group_id + site_group.name = name + site_group.slug = slug + site_group + 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('sitegroup1') + expect(subject.slug).to eq('sitegroup1') + end + end + + context 'create' do + subject do + site_group = described_class.new + site_group.name = name + site_group.slug = slug + site_group + end + + let(:request_method) { :post } + let(:request_url) { '/api/dcim/site-groups/' } + + 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('sitegroup1') + expect(subject.slug).to eq('sitegroup1') + end + end + end +end diff --git a/spec/netbox_client_ruby/api/dcim/site_groups_spec.rb b/spec/netbox_client_ruby/api/dcim/site_groups_spec.rb new file mode 100644 index 0000000..2f5c3e7 --- /dev/null +++ b/spec/netbox_client_ruby/api/dcim/site_groups_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::DCIM::SiteGroups, faraday_stub: true do + let(:response) { File.read('spec/fixtures/dcim/site-groups.json') } + let(:request_url) { '/api/dcim/site-groups/' } + 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 2 + end + end + + describe '#total' do + it 'shall be the expected total' do + expect(subject.total).to be 2 + 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 2 + end + + it 'returns Site instances' do + subject.to_a.each do |element| + expect(element).to be_a NetboxClientRuby::DCIM::SiteGroup + 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 9dd3ae5..3bc4eed 100644 --- a/spec/netbox_client_ruby/api/dcim_spec.rb +++ b/spec/netbox_client_ruby/api/dcim_spec.rb @@ -29,6 +29,7 @@ module DCIM rear_ports: RearPorts, regions: Regions, sites: Sites, + site_groups: SiteGroups, virtual_chassis_list: VirtualChassisList, }.each do |method, expected_class| describe ".#{method}" do @@ -75,6 +76,7 @@ module DCIM rear_port: RearPort, region: Region, site: Site, + site_group: SiteGroup, virtual_chassis: VirtualChassis, }.each do |method, expected_class| describe ".#{method}" do