diff --git a/README.md b/README.md index c8514b0..8d03341 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,8 @@ Not all objects which the Netbox API exposes are currently implemented. Implemen * Tenancy: * Tenant: `NetboxClientRuby.tenancy.tenants` * Tenant Groups: `NetboxClientRuby.tenancy.tenant_groups` + * Contact: `NetboxClientRuby.tenancy.contacts` + * Contact Groups: `NetboxClientRuby.tenancy.contact_groups` * Virtualization: * Cluster Types: `NetboxClientRuby.virtualization.cluster_types` * Cluster Groups: `NetboxClientRuby.virtualization.cluster_groups` @@ -243,7 +245,7 @@ Before opening a PR, please * extend the existing specs * run rspec * run rubocop and fix your warnings -* check if this README.md file needs adjustments +* check if this `README.md` file needs adjustments ## License diff --git a/lib/netbox_client_ruby/api/tenancy.rb b/lib/netbox_client_ruby/api/tenancy.rb index 8545644..03e8a0d 100644 --- a/lib/netbox_client_ruby/api/tenancy.rb +++ b/lib/netbox_client_ruby/api/tenancy.rb @@ -4,7 +4,9 @@ module NetboxClientRuby module Tenancy { tenants: Tenants, - tenant_groups: TenantGroups + tenant_groups: TenantGroups, + contacts: Contacts, + contact_groups: ContactGroups }.each_pair do |method_name, class_name| define_method(method_name) { class_name.new } module_function(method_name) @@ -12,7 +14,9 @@ module Tenancy { tenant: Tenant, - tenant_group: TenantGroup + tenant_group: TenantGroup, + contact: Contact, + contact_group: ContactGroup }.each_pair do |method_name, class_name| define_method(method_name) { |id| class_name.new id } module_function(method_name) diff --git a/lib/netbox_client_ruby/api/tenancy/contact.rb b/lib/netbox_client_ruby/api/tenancy/contact.rb new file mode 100644 index 0000000..9ec6e91 --- /dev/null +++ b/lib/netbox_client_ruby/api/tenancy/contact.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module Tenancy + class Contact + include Entity + + id id: :id + deletable true + path 'tenancy/contacts/:id/' + creation_path 'tenancy/contacts/' + object_fields group: proc { |raw_data| ContactGroup.new raw_data['id'] } + end + end +end diff --git a/lib/netbox_client_ruby/api/tenancy/contact_group.rb b/lib/netbox_client_ruby/api/tenancy/contact_group.rb new file mode 100644 index 0000000..0913a59 --- /dev/null +++ b/lib/netbox_client_ruby/api/tenancy/contact_group.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module Tenancy + class ContactGroup + include Entity + + id id: :id + deletable true + path 'tenancy/contact-groups/:id/' + creation_path 'tenancy/contact-groups/' + object_fields parent: proc { |raw_data| ContactGroup.new raw_data['id'] } + end + end +end diff --git a/lib/netbox_client_ruby/api/tenancy/contact_groups.rb b/lib/netbox_client_ruby/api/tenancy/contact_groups.rb new file mode 100644 index 0000000..3e56fb7 --- /dev/null +++ b/lib/netbox_client_ruby/api/tenancy/contact_groups.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module Tenancy + class ContactGroups + include Entities + + path 'tenancy/contact-groups/' + data_key 'results' + count_key 'count' + entity_creator :entity_creator + + private + + def entity_creator(raw_entity) + ContactGroup.new raw_entity['id'] + end + end + end +end diff --git a/lib/netbox_client_ruby/api/tenancy/contacts.rb b/lib/netbox_client_ruby/api/tenancy/contacts.rb new file mode 100644 index 0000000..392158e --- /dev/null +++ b/lib/netbox_client_ruby/api/tenancy/contacts.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module Tenancy + class Contacts + include Entities + + path 'tenancy/contacts/' + data_key 'results' + count_key 'count' + entity_creator :entity_creator + + private + + def entity_creator(raw_entity) + Contact.new raw_entity['id'] + end + end + end +end diff --git a/spec/fixtures/tenancy/contact-group_1.json b/spec/fixtures/tenancy/contact-group_1.json new file mode 100644 index 0000000..a7d8c52 --- /dev/null +++ b/spec/fixtures/tenancy/contact-group_1.json @@ -0,0 +1,7 @@ +{ + "id": 1, + "display": "Parent Customers", + "name": "Parent Customers", + "slug": "parent-customers", + "description": "Parent Contact contact group" +} diff --git a/spec/fixtures/tenancy/contact-group_2.json b/spec/fixtures/tenancy/contact-group_2.json new file mode 100644 index 0000000..a716d72 --- /dev/null +++ b/spec/fixtures/tenancy/contact-group_2.json @@ -0,0 +1,15 @@ +{ + "id": 2, + "display": "Child Customers", + "name": "Child Customers", + "slug": "child-customers", + "description": "Child contact group", + "parent": { + "id": 1, + "url": "http://localhost/api/tenancy/contact_groups/1/", + "display": "Parent Customers", + "name": "Parent Customers", + "slug": "parent-customers", + "description": "Parent Contact contact group" + } +} diff --git a/spec/fixtures/tenancy/contact-groups.json b/spec/fixtures/tenancy/contact-groups.json new file mode 100644 index 0000000..86c2934 --- /dev/null +++ b/spec/fixtures/tenancy/contact-groups.json @@ -0,0 +1,30 @@ +{ + "count": 2, + "next": null, + "previous": null, + "results": [ + { + "id": 1, + "display": "Parent Customers", + "name": "Parent Customers", + "slug": "parent-customers", + "description": "Parent Contact contact group", + "parent": null + }, + { + "id": 2, + "display": "Child Customers", + "name": "Child Customers", + "slug": "child-customers", + "description": "Child contact group", + "parent": { + "id": 1, + "url": "http://localhost/api/tenancy/contact_groups/1/", + "display": "Parent Customers", + "name": "Parent Customers", + "slug": "parent-customers", + "description": "Parent Contact contact group" + } + } + ] +} diff --git a/spec/fixtures/tenancy/contact_1.json b/spec/fixtures/tenancy/contact_1.json new file mode 100644 index 0000000..d9d8196 --- /dev/null +++ b/spec/fixtures/tenancy/contact_1.json @@ -0,0 +1,9 @@ +{ + "id": 1, + "name": "contact1", + "email": "contact1@customer.test", + "group": null, + "description": "", + "comments": "", + "custom_fields": {} +} diff --git a/spec/fixtures/tenancy/contact_2.json b/spec/fixtures/tenancy/contact_2.json new file mode 100644 index 0000000..8e57759 --- /dev/null +++ b/spec/fixtures/tenancy/contact_2.json @@ -0,0 +1,9 @@ +{ + "id": 2, + "name": "contact2", + "email": "contact2@customer.test", + "group": null, + "description": "", + "comments": "", + "custom_fields": {} +} diff --git a/spec/fixtures/tenancy/contact_3.json b/spec/fixtures/tenancy/contact_3.json new file mode 100644 index 0000000..4ee6242 --- /dev/null +++ b/spec/fixtures/tenancy/contact_3.json @@ -0,0 +1,16 @@ +{ + "id": 3, + "name": "tenant3", + "email": "contact3@customer.test", + "group": { + "id": 2, + "url": "http://localhost/api/tenancy/contact_groups/2/", + "display": "Child Customers", + "name": "Child Customers", + "slug": "child-customers", + "description": "Child contact group" + }, + "description": "", + "comments": "", + "custom_fields": {} +} diff --git a/spec/fixtures/tenancy/contacts.json b/spec/fixtures/tenancy/contacts.json new file mode 100644 index 0000000..7961618 --- /dev/null +++ b/spec/fixtures/tenancy/contacts.json @@ -0,0 +1,41 @@ +{ + "count": 3, + "next": null, + "previous": null, + "results": [ + { + "id": 3, + "name": "contact3", + "email": "contact3@customer.test", + "group": { + "id": 2, + "url": "http://localhost/api/tenancy/contact_groups/2/", + "display": "Child Customers", + "name": "Child Customers", + "slug": "child-customers", + "description": "Child contact group" + }, + "description": "", + "comments": "", + "custom_fields": {} + }, + { + "id": 1, + "name": "contact1", + "email": "contact1@customer.test", + "group": null, + "description": "", + "comments": "", + "custom_fields": {} + }, + { + "id": 2, + "name": "contact2", + "email": "contact2@customer.test", + "group": null, + "description": "", + "comments": "", + "custom_fields": {} + } + ] +} diff --git a/spec/netbox_client_ruby/api/tenancy/contact_group_spec.rb b/spec/netbox_client_ruby/api/tenancy/contact_group_spec.rb new file mode 100644 index 0000000..47ba97e --- /dev/null +++ b/spec/netbox_client_ruby/api/tenancy/contact_group_spec.rb @@ -0,0 +1,151 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::Tenancy::ContactGroup, faraday_stub: true do + let(:contact_group_id) { 1 } + let(:base_url) { '/api/tenancy/contact-groups/' } + let(:request_url) { "#{base_url}#{contact_group_id}/" } + let(:response) { File.read("spec/fixtures/tenancy/contact-group_#{contact_group_id}.json") } + + subject { NetboxClientRuby::Tenancy::ContactGroup.new contact_group_id } + + describe '#id' do + it 'shall be the expected id' do + expect(subject.id).to eq(contact_group_id) + end + end + + describe '#name' do + it 'should fetch 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('Parent Customers') + end + end + + describe '.parent' do + it 'should be nil' do + expect(subject.parent).to be_nil + end + + context 'Child Contact Group' do + let(:contact_group_id) { 2 } + + it 'should be a Contact Group object' do + parent_contact_group = subject.parent + expect(parent_contact_group).to be_a NetboxClientRuby::Tenancy::ContactGroup + expect(parent_contact_group.id).to eq(1) + end + end + end + + describe '.delete' do + let(:request_method) { :delete } + let(:response_status) { 204 } + let(:response) { nil } + + it 'should delete 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 'should update the object' do + expect(faraday).to receive(request_method).and_call_original + expect(subject.update(name: 'noob').name).to eq('Parent Customers') + end + end + + describe '.reload' do + it 'should reload 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 + let(:request_method) { :patch } + + subject do + entity = NetboxClientRuby::Tenancy::ContactGroup.new contact_group_id + entity.name = name + entity.slug = slug + entity + end + + 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('Parent Customers') + expect(subject.slug).to eq('parent-customers') + end + end + + context 'create' do + let(:request_method) { :post } + let(:request_url) { base_url } + + subject do + entity = NetboxClientRuby::Tenancy::ContactGroup.new + entity.name = name + entity.slug = slug + entity + end + + 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('Parent Customers') + expect(subject.slug).to eq('parent-customers') + end + end + end +end diff --git a/spec/netbox_client_ruby/api/tenancy/contact_spec.rb b/spec/netbox_client_ruby/api/tenancy/contact_spec.rb new file mode 100644 index 0000000..340ccd8 --- /dev/null +++ b/spec/netbox_client_ruby/api/tenancy/contact_spec.rb @@ -0,0 +1,151 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::Tenancy::Contact, faraday_stub: true do + let(:contact_id) { 1 } + let(:base_url) { '/api/tenancy/contacts/' } + let(:request_url) { "#{base_url}#{contact_id}/" } + let(:response) { File.read("spec/fixtures/tenancy/contact_#{contact_id}.json") } + + subject { NetboxClientRuby::Tenancy::Contact.new contact_id } + + describe '#id' do + it 'shall be the expected id' do + expect(subject.id).to eq(contact_id) + end + end + + describe '#name' do + it 'should fetch 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('contact1') + end + end + + describe '.group' do + it 'should be nil' do + expect(subject.group).to be_nil + end + + context 'Contact with Group' do + let(:contact_id) { 3 } + + it 'should be a ContactGroup object' do + contact_group = subject.group + expect(contact_group).to be_a NetboxClientRuby::Tenancy::ContactGroup + expect(contact_group.id).to eq(2) + end + end + end + + describe '.delete' do + let(:request_method) { :delete } + let(:response_status) { 204 } + let(:response) { nil } + + it 'should delete 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 'should update the object' do + expect(faraday).to receive(request_method).and_call_original + expect(subject.update(name: 'noob').name).to eq('contact1') + end + end + + describe '.reload' do + it 'should reload 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 + let(:request_method) { :patch } + + subject do + entity = NetboxClientRuby::Tenancy::Contact.new contact_id + entity.name = name + entity.slug = slug + entity + end + + 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('contact1') + expect(subject.email).to eq('contact1@customer.test') + end + end + + context 'create' do + let(:request_method) { :post } + let(:request_url) { base_url } + + subject do + entity = NetboxClientRuby::Tenancy::Contact.new + entity.name = name + entity.slug = slug + entity + end + + 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('contact1') + expect(subject.email).to eq('contact1@customer.test') + end + end + end +end diff --git a/spec/netbox_client_ruby/api/tenancy/contacts_groups_spec.rb b/spec/netbox_client_ruby/api/tenancy/contacts_groups_spec.rb new file mode 100644 index 0000000..762cae1 --- /dev/null +++ b/spec/netbox_client_ruby/api/tenancy/contacts_groups_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::Tenancy::ContactGroups, faraday_stub: true do + let(:expected_number_of_items) { 2 } + let(:expected_singular_type) { NetboxClientRuby::Tenancy::ContactGroup } + + let(:response) { File.read('spec/fixtures/tenancy/contact-groups.json') } + let(:request_url) { '/api/tenancy/contact-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 expected_number_of_items + end + end + + describe '#total' do + it 'shall be the expected total' do + expect(subject.total).to be expected_number_of_items + 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_number_of_items + end + + it 'returns single instances' do + subject.to_a.each do |element| + expect(element).to be_a expected_singular_type + end + end + end +end diff --git a/spec/netbox_client_ruby/api/tenancy/contacts_spec.rb b/spec/netbox_client_ruby/api/tenancy/contacts_spec.rb new file mode 100644 index 0000000..4b1ae31 --- /dev/null +++ b/spec/netbox_client_ruby/api/tenancy/contacts_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::Tenancy::Contacts, faraday_stub: true do + let(:response) { File.read('spec/fixtures/tenancy/contacts.json') } + let(:request_url) { '/api/tenancy/contacts/' } + 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 3 + end + end + + describe '#total' do + it 'shall be the expected total' do + expect(subject.total).to be 3 + 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 3 + end + + it 'returns single instances' do + subject.to_a.each do |element| + expect(element).to be_a NetboxClientRuby::Tenancy::Contact + end + end + end +end diff --git a/spec/netbox_client_ruby/api/tenancy/tenant_group_spec.rb b/spec/netbox_client_ruby/api/tenancy/tenant_group_spec.rb index 7665024..596888a 100644 --- a/spec/netbox_client_ruby/api/tenancy/tenant_group_spec.rb +++ b/spec/netbox_client_ruby/api/tenancy/tenant_group_spec.rb @@ -3,16 +3,16 @@ require 'spec_helper' RSpec.describe NetboxClientRuby::Tenancy::TenantGroup, faraday_stub: true do - let(:region_id) { 1 } + let(:tenant_group_id) { 1 } let(:base_url) { '/api/tenancy/tenant-groups/' } - let(:request_url) { "#{base_url}#{region_id}/" } - let(:response) { File.read("spec/fixtures/tenancy/tenant-group_#{region_id}.json") } + let(:request_url) { "#{base_url}#{tenant_group_id}/" } + let(:response) { File.read("spec/fixtures/tenancy/tenant-group_#{tenant_group_id}.json") } - subject { NetboxClientRuby::Tenancy::TenantGroup.new region_id } + subject { NetboxClientRuby::Tenancy::TenantGroup.new tenant_group_id } describe '#id' do it 'shall be the expected id' do - expect(subject.id).to eq(region_id) + expect(subject.id).to eq(tenant_group_id) end end @@ -67,7 +67,7 @@ let(:request_method) { :patch } subject do - entity = NetboxClientRuby::Tenancy::TenantGroup.new region_id + entity = NetboxClientRuby::Tenancy::TenantGroup.new tenant_group_id entity.name = name entity.slug = slug entity diff --git a/spec/netbox_client_ruby/api/tenancy/tenant_spec.rb b/spec/netbox_client_ruby/api/tenancy/tenant_spec.rb index 9aaadff..399e106 100644 --- a/spec/netbox_client_ruby/api/tenancy/tenant_spec.rb +++ b/spec/netbox_client_ruby/api/tenancy/tenant_spec.rb @@ -3,16 +3,16 @@ require 'spec_helper' RSpec.describe NetboxClientRuby::Tenancy::Tenant, faraday_stub: true do - let(:region_id) { 1 } + let(:tenant_id) { 1 } let(:base_url) { '/api/tenancy/tenants/' } - let(:request_url) { "#{base_url}#{region_id}/" } - let(:response) { File.read("spec/fixtures/tenancy/tenant_#{region_id}.json") } + let(:request_url) { "#{base_url}#{tenant_id}/" } + let(:response) { File.read("spec/fixtures/tenancy/tenant_#{tenant_id}.json") } - subject { NetboxClientRuby::Tenancy::Tenant.new region_id } + subject { NetboxClientRuby::Tenancy::Tenant.new tenant_id } describe '#id' do it 'shall be the expected id' do - expect(subject.id).to eq(region_id) + expect(subject.id).to eq(tenant_id) end end @@ -34,7 +34,7 @@ end context 'Tenant with Group' do - let(:region_id) { 3 } + let(:tenant_id) { 3 } it 'should be a TenantGroup object' do tenant_group = subject.group @@ -83,7 +83,7 @@ let(:request_method) { :patch } subject do - entity = NetboxClientRuby::Tenancy::Tenant.new region_id + entity = NetboxClientRuby::Tenancy::Tenant.new tenant_id entity.name = name entity.slug = slug entity diff --git a/spec/netbox_client_ruby/api/tenancy_spec.rb b/spec/netbox_client_ruby/api/tenancy_spec.rb index 25319f1..171b457 100644 --- a/spec/netbox_client_ruby/api/tenancy_spec.rb +++ b/spec/netbox_client_ruby/api/tenancy_spec.rb @@ -5,7 +5,9 @@ RSpec.describe NetboxClientRuby::Tenancy do { tenant_groups: NetboxClientRuby::Tenancy::TenantGroups, - tenants: NetboxClientRuby::Tenancy::Tenants + tenants: NetboxClientRuby::Tenancy::Tenants, + contact_groups: NetboxClientRuby::Tenancy::ContactGroups, + contacts: NetboxClientRuby::Tenancy::Contacts }.each do |method, klass| describe ".#{method}" do subject { described_class.public_send(method) }