diff --git a/spec/pe_client/client_spec.rb b/spec/pe_client/client_spec.rb index da9c87a..f3e3141 100644 --- a/spec/pe_client/client_spec.rb +++ b/spec/pe_client/client_spec.rb @@ -48,7 +48,7 @@ end describe "#deep_dup" do - it "creates a deep duplicate of the client" do + it "creates an independent copy that preserves configuration" do client = described_class.new(api_key: api_key, base_url: base_url, ca_file: "/path/to/ca.pem") duplicate = client.deep_dup @@ -59,20 +59,6 @@ expect(duplicate.connection.ssl[:ca_file].object_id).not_to eq(client.connection.ssl[:ca_file].object_id) end - # Some API endpoints don't require an api_key - it "handles nil api_key in deep_dup" do - client_with_nil_api_key = described_class.new(api_key: nil, base_url: base_url, ca_file: nil) - duplicate = client_with_nil_api_key.deep_dup - expect(duplicate.api_key).to eq(nil) - end - - # While ca_file = nil is not recommended in production, we test it here to ensure - # that the deep_dup method handles nil values without raising errors. - it "handles nil ca_file in deep_dup" do - duplicate = client.deep_dup - expect(duplicate.connection.ssl[:ca_file]).to eq(nil) - end - it "preserves the provisioning block" do block_called = false provisioning_block = proc { |conn| block_called = true } @@ -122,55 +108,6 @@ expect(response).to eq({"location" => "https://example.com/new-location"}) end - it "raises BadRequestError on 400" do - stub_request(:get, "#{base_url}/test/path") - .to_return(status: 400, body: '{"error": "bad request"}', headers: {"Content-Type" => "application/json"}) - - expect { client.get("/test/path") }.to raise_error(PEClient::BadRequestError) - end - - it "raises UnauthorizedError on 401" do - stub_request(:get, "#{base_url}/test/path") - .to_return(status: 401, body: '{"error": "unauthorized"}', headers: {"Content-Type" => "application/json"}) - - expect { client.get("/test/path") }.to raise_error(PEClient::UnauthorizedError) - end - - it "raises ForbiddenError on 403" do - stub_request(:get, "#{base_url}/test/path") - .to_return(status: 403, body: '{"error": "forbidden"}', headers: {"Content-Type" => "application/json"}) - - expect { client.get("/test/path") }.to raise_error(PEClient::ForbiddenError) - end - - it "raises NotFoundError on 404" do - stub_request(:get, "#{base_url}/test/path") - .to_return(status: 404, body: '{"error": "not found"}', headers: {"Content-Type" => "application/json"}) - - expect { client.get("/test/path") }.to raise_error(PEClient::NotFoundError) - end - - it "raises ConflictError on 409" do - stub_request(:get, "#{base_url}/test/path") - .to_return(status: 409, body: '{"error": "conflict"}', headers: {"Content-Type" => "application/json"}) - - expect { client.get("/test/path") }.to raise_error(PEClient::ConflictError) - end - - it "raises ServerError on 500" do - stub_request(:get, "#{base_url}/test/path") - .to_return(status: 500, body: '{"error": "server error"}', headers: {"Content-Type" => "application/json"}) - - expect { client.get("/test/path") }.to raise_error(PEClient::ServerError) - end - - it "raises HTTPError on other status codes" do - stub_request(:get, "#{base_url}/test/path") - .to_return(status: 418, body: "I'm a teapot") - - expect { client.get("/test/path") }.to raise_error(PEClient::HTTPError) - end - it "handles 204 No Content" do stub_request(:get, "#{base_url}/test/path") .to_return(status: 204, body: "", headers: {}) @@ -178,6 +115,8 @@ response = client.get("/test/path") expect(response).to eq({}) end + + include_examples "http error handling", :get, "/test/path" end describe "#post" do @@ -317,173 +256,20 @@ end describe "resource methods" do - describe "#node_inventory_v1" do - it "returns a NodeInventoryV1 resource" do - resource = client.node_inventory_v1 - expect(resource).to be_a(PEClient::Resource::NodeInventoryV1) - end - - it "memorizes the resource" do - resource1 = client.node_inventory_v1 - resource2 = client.node_inventory_v1 - expect(resource1).to equal(resource2) - end - end - - describe "#rbac_v1" do - it "returns an RBACV1 resource" do - resource = client.rbac_v1 - expect(resource).to be_a(PEClient::Resource::RBACV1) - end - - it "memorizes the resource" do - resource1 = client.rbac_v1 - resource2 = client.rbac_v1 - expect(resource1).to equal(resource2) - end - end - - describe "#rbac_v2" do - it "returns an RBACV2 resource" do - resource = client.rbac_v2 - expect(resource).to be_a(PEClient::Resource::RBACV2) - end - - it "memorizes the resource" do - resource1 = client.rbac_v2 - resource2 = client.rbac_v2 - expect(resource1).to equal(resource2) - end - end - - describe "#node_classifier_v1" do - it "returns a NodeClassifierV1 resource" do - resource = client.node_classifier_v1 - expect(resource).to be_a(PEClient::Resource::NodeClassifierV1) - end - - it "memorizes the resource" do - resource1 = client.node_classifier_v1 - resource2 = client.node_classifier_v1 - expect(resource1).to equal(resource2) - end - end - - describe "#orchestrator_v1" do - it "returns an OrchestratorV1 resource" do - resource = client.orchestrator_v1 - expect(resource).to be_a(PEClient::Resource::OrchestratorV1) - end - - it "memorizes the resource" do - resource1 = client.orchestrator_v1 - resource2 = client.orchestrator_v1 - expect(resource1).to equal(resource2) - end - end - - describe "#code_manager_v1" do - it "returns a CodeManagerV1 resource" do - resource = client.code_manager_v1 - expect(resource).to be_a(PEClient::Resource::CodeManagerV1) - end - - it "memorizes the resource" do - resource1 = client.code_manager_v1 - resource2 = client.code_manager_v1 - expect(resource1).to equal(resource2) - end - end - - describe "#status_v1" do - it "returns a StatusV1 resource" do - resource = client.status_v1 - expect(resource).to be_a(PEClient::Resource::StatusV1) - end - - it "memorizes the resource" do - resource1 = client.status_v1 - resource2 = client.status_v1 - expect(resource1).to equal(resource2) - end - end - - describe "#activity_v1" do - it "returns an ActivityV1 resource" do - resource = client.activity_v1 - expect(resource).to be_a(PEClient::Resource::ActivityV1) - end - - it "memorizes the resource" do - resource1 = client.activity_v1 - resource2 = client.activity_v1 - expect(resource1).to equal(resource2) - end - end - - describe "#activity_v2" do - it "returns an ActivityV2 resource" do - resource = client.activity_v2 - expect(resource).to be_a(PEClient::Resource::ActivityV2) - end - - it "memorizes the resource" do - resource1 = client.activity_v2 - resource2 = client.activity_v2 - expect(resource1).to equal(resource2) - end - end - - describe "#metrics_v1" do - it "returns a MetricsV1 resource" do - resource = client.metrics_v1 - expect(resource).to be_a(PEClient::Resource::MetricsV1) - end - - it "memorizes the resource" do - resource1 = client.metrics_v1 - resource2 = client.metrics_v1 - expect(resource1).to equal(resource2) - end - end - - describe "#metrics_v2" do - it "returns a MetricsV2 resource" do - resource = client.metrics_v2 - expect(resource).to be_a(PEClient::Resource::MetricsV2) - end - - it "memorizes the resource" do - resource1 = client.metrics_v2 - resource2 = client.metrics_v2 - expect(resource1).to equal(resource2) - end - end - - describe "#puppet_admin_v1" do - it "returns a PuppetAdminV1 resource" do - resource = client.puppet_admin_v1 - expect(resource).to be_a(PEClient::Resource::PuppetAdminV1) - end - - it "memorizes the resource" do - resource1 = client.puppet_admin_v1 - resource2 = client.puppet_admin_v1 - expect(resource1).to equal(resource2) - end - end - - describe "#puppet_v3" do - it "returns a PuppetV3 resource" do - resource = client.puppet_v3 - expect(resource).to be_a(PEClient::Resource::PuppetV3) - end - - it "memorizes the resource" do - resource1 = client.puppet_v3 - resource2 = client.puppet_v3 - expect(resource1).to equal(resource2) - end - end + subject { client } + + include_examples "a memoized resource", :node_inventory_v1, "PEClient::Resource::NodeInventoryV1" + include_examples "a memoized resource", :rbac_v1, "PEClient::Resource::RBACV1" + include_examples "a memoized resource", :rbac_v2, "PEClient::Resource::RBACV2" + include_examples "a memoized resource", :node_classifier_v1, "PEClient::Resource::NodeClassifierV1" + include_examples "a memoized resource", :orchestrator_v1, "PEClient::Resource::OrchestratorV1" + include_examples "a memoized resource", :code_manager_v1, "PEClient::Resource::CodeManagerV1" + include_examples "a memoized resource", :status_v1, "PEClient::Resource::StatusV1" + include_examples "a memoized resource", :activity_v1, "PEClient::Resource::ActivityV1" + include_examples "a memoized resource", :activity_v2, "PEClient::Resource::ActivityV2" + include_examples "a memoized resource", :metrics_v1, "PEClient::Resource::MetricsV1" + include_examples "a memoized resource", :metrics_v2, "PEClient::Resource::MetricsV2" + include_examples "a memoized resource", :puppet_admin_v1, "PEClient::Resource::PuppetAdminV1" + include_examples "a memoized resource", :puppet_v3, "PEClient::Resource::PuppetV3" end end diff --git a/spec/pe_client/resources/activity_v1_spec.rb b/spec/pe_client/resources/activity_v1_spec.rb index 1b70d12..d3d1970 100644 --- a/spec/pe_client/resources/activity_v1_spec.rb +++ b/spec/pe_client/resources/activity_v1_spec.rb @@ -9,201 +9,41 @@ let(:resource) { described_class.new(client) } describe "#events" do - context "when retrieving events with service_id only" do - it "gets events for a specific service" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"service_id": "rbac", "subject": {"type": "user"}}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac") - expect(result).to eq({"commits" => [{"service_id" => "rbac", "subject" => {"type" => "user"}}]}) - end - end - - context "when filtering by subject_type" do - it "includes subject_type parameter" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&subject_type=user") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac", subject_type: "user") - expect(result).to be_a(Hash) - end - - it "includes subject_id parameter when subject_type is provided" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&subject_type=user&subject_id=user123&subject_id=user456") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"subject": {"id": "user123"}}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac", subject_type: "user", subject_id: ["user123", "user456"]) - expect(result).to be_a(Hash) - end - end - - context "when filtering by object_type" do - it "includes object_type parameter" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&object_type=role") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac", object_type: "role") - expect(result).to be_a(Hash) - end - - it "includes object_id parameter when object_type is provided" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&object_type=role&object_id=role1&object_id=role2") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"object": {"id": "role1"}}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac", object_type: "role", object_id: ["role1", "role2"]) - expect(result).to be_a(Hash) - end - end - - context "when using pagination parameters" do - it "includes offset parameter" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&offset=10") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac", offset: 10) - expect(result).to be_a(Hash) - end - - it "includes limit parameter" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&limit=50") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac", limit: 50) - expect(result).to be_a(Hash) - end - - it "includes order parameter for ascending order" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&order=asc") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac", order: "asc") - expect(result).to be_a(Hash) - end - - it "includes order parameter for descending order" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&order=desc") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac", order: "desc") - expect(result).to be_a(Hash) - end - - it "includes all pagination parameters together" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&offset=20&order=asc&limit=100") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac", offset: 20, order: "asc", limit: 100) - expect(result).to be_a(Hash) - end - end - - context "when filtering by time" do - it "includes after_service_commit_time parameter" do - timestamp = "2025-11-27T00:00:00Z" - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&after_service_commit_time=#{timestamp}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) + it "gets events for a specific service with minimal parameters" do + stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"commits": [{"service_id": "rbac", "subject": {"type": "user"}}]}', + headers: {"Content-Type" => "application/json"} + ) - result = resource.events(service_id: "rbac", after_service_commit_time: timestamp) - expect(result).to be_a(Hash) - end + result = resource.events(service_id: "rbac") + expect(result).to eq({"commits" => [{"service_id" => "rbac", "subject" => {"type" => "user"}}]}) end - context "when combining multiple filters" do - it "includes all filter parameters" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&subject_type=user&subject_id=user123&object_type=role&object_id=role1&offset=0&order=desc&limit=1000&after_service_commit_time=2025-11-01T00:00:00Z") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"service_id": "rbac", "subject": {"type": "user", "id": "user123"}, "object": {"type": "role", "id": "role1"}}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events( - service_id: "rbac", - subject_type: "user", - subject_id: ["user123"], - object_type: "role", - object_id: ["role1"], - offset: 0, - order: "desc", - limit: 1000, - after_service_commit_time: "2025-11-01T00:00:00Z" + it "supports all filter and pagination parameters" do + stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac&subject_type=user&subject_id=user123&object_type=role&object_id=role1&offset=20&order=desc&limit=100&after_service_commit_time=2025-11-01T00:00:00Z") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"commits": [{"service_id": "rbac", "subject": {"type": "user", "id": "user123"}, "object": {"type": "role", "id": "role1"}}]}', + headers: {"Content-Type" => "application/json"} ) - expect(result).to be_a(Hash) - expect(result["commits"]).to be_an(Array) - end - end - - context "when omitting optional parameters" do - it "only includes service_id when other parameters are nil" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v1/events?service_id=rbac") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - result = resource.events( - service_id: "rbac" - ) - expect(result).to be_a(Hash) - end + result = resource.events( + service_id: "rbac", + subject_type: "user", + subject_id: ["user123"], + object_type: "role", + object_id: ["role1"], + offset: 20, + order: "desc", + limit: 100, + after_service_commit_time: "2025-11-01T00:00:00Z" + ) + expect(result).to be_a(Hash) + expect(result["commits"]).to be_an(Array) end end end diff --git a/spec/pe_client/resources/activity_v2_spec.rb b/spec/pe_client/resources/activity_v2_spec.rb index 8de8288..af26123 100644 --- a/spec/pe_client/resources/activity_v2_spec.rb +++ b/spec/pe_client/resources/activity_v2_spec.rb @@ -9,274 +9,69 @@ let(:resource) { described_class.new(client) } describe "#events" do - context "when retrieving all events" do - it "gets events without any filters" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"service_id": "rbac"}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events - expect(result).to eq({"commits" => [{"service_id" => "rbac"}]}) - end - end - - context "when filtering by service_id" do - it "includes service_id parameter" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?service_id=rbac") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"service_id": "rbac"}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(service_id: "rbac") - expect(result).to be_a(Hash) - end - end - - context "when using pagination parameters" do - it "includes offset parameter" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?offset=10") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(offset: 10) - expect(result).to be_a(Hash) - end - - it "includes order parameter for ascending order" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?order=asc") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(order: "asc") - expect(result).to be_a(Hash) - end - - it "includes order parameter for descending order" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?order=desc") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(order: "desc") - expect(result).to be_a(Hash) - end - - it "includes limit parameter" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?limit=50") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(limit: 50) - expect(result).to be_a(Hash) - end - - it "includes all pagination parameters together" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?offset=20&order=asc&limit=100") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) + it "gets events without any filters" do + stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"commits": [{"service_id": "rbac"}]}', + headers: {"Content-Type" => "application/json"} + ) - result = resource.events(offset: 20, order: "asc", limit: 100) - expect(result).to be_a(Hash) - end + result = resource.events + expect(result).to eq({"commits" => [{"service_id" => "rbac"}]}) end - context "when filtering with query parameter" do - it "includes query with subject_id" do - query_param = [{subject_id: "user123"}] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"subject": {"id": "user123"}}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(query: query_param) - expect(result).to be_a(Hash) - end - - it "includes query with subject_type and subject_id" do - query_param = [{subject_type: "user", subject_id: "user123"}] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"subject": {"type": "user", "id": "user123"}}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(query: query_param) - expect(result).to be_a(Hash) - end - - it "includes query with object_type and object_id" do - query_param = [{object_type: "role", object_id: "role1"}] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"object": {"type": "role", "id": "role1"}}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(query: query_param) - expect(result).to be_a(Hash) - end - - it "includes query with ip_address" do - query_param = [{ip_address: "192.168.1.100"}] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"ip": "192.168.1.100"}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(query: query_param) - expect(result).to be_a(Hash) - end - - it "includes query with time range using start and end" do - query_param = [{start: "2025-11-01T00:00:00Z", end: "2025-11-27T23:59:59Z"}] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(query: query_param) - expect(result).to be_a(Hash) - end - - it "includes query with multiple filters" do - query_param = [ - {subject_type: "user", subject_id: "user123"}, - {object_type: "role", object_id: "role1"} - ] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(query: query_param) - expect(result).to be_a(Hash) - end - - it "includes query with symbol keys" do - query_param = [{subject_id: "user123", object_type: "role"}] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events(query: query_param) - expect(result).to be_a(Hash) - end - - it "includes query with string keys" do - query_param = [{"subject_id" => "user123", "object_type" => "role"}] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) + it "supports pagination parameters" do + stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?offset=20&order=asc&limit=100") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"commits": []}', + headers: {"Content-Type" => "application/json"} + ) - result = resource.events(query: query_param) - expect(result).to be_a(Hash) - end + result = resource.events(offset: 20, order: "asc", limit: 100) + expect(result).to be_a(Hash) end - context "when combining service_id with query filters" do - it "includes both service_id and query parameters" do - query_param = [{subject_id: "user123"}] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?service_id=rbac&query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"service_id": "rbac", "subject": {"id": "user123"}}]}', - headers: {"Content-Type" => "application/json"} - ) + it "supports complex query filters" do + query_param = [ + {subject_type: "user", subject_id: "user123"}, + {object_type: "role", object_id: "role1"}, + {ip_address: "192.168.1.100"}, + {start: "2025-11-01T00:00:00Z", end: "2025-11-27T23:59:59Z"} + ] + stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?query=#{CGI.escape(query_param.to_json)}") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"commits": []}', + headers: {"Content-Type" => "application/json"} + ) - result = resource.events(service_id: "rbac", query: query_param) - expect(result).to be_a(Hash) - end + result = resource.events(query: query_param) + expect(result).to be_a(Hash) end - context "when combining all parameters" do - it "includes service_id, pagination, and query parameters" do - query_param = [ - {subject_type: "user", subject_id: "user123"}, - {start: "2025-11-01T00:00:00Z", end: "2025-11-27T23:59:59Z"} - ] - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?service_id=rbac&offset=10&order=desc&limit=100&query=#{CGI.escape(query_param.to_json)}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": [{"service_id": "rbac"}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.events( - service_id: "rbac", - offset: 10, - order: "desc", - limit: 100, - query: query_param + it "combines service_id, pagination, and query parameters" do + query_param = [{subject_type: "user", subject_id: "user123"}] + stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events?service_id=rbac&offset=10&order=desc&limit=100&query=#{CGI.escape(query_param.to_json)}") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"commits": [{"service_id": "rbac"}]}', + headers: {"Content-Type" => "application/json"} ) - expect(result).to be_a(Hash) - end - end - - context "when omitting optional parameters" do - it "only includes non-nil parameters" do - stub_request(:get, "https://puppet.example.com:4433/activity-api/v2/events") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"commits": []}', - headers: {"Content-Type" => "application/json"} - ) - result = resource.events - expect(result).to be_a(Hash) - end + result = resource.events( + service_id: "rbac", + offset: 10, + order: "desc", + limit: 100, + query: query_param + ) + expect(result).to be_a(Hash) end end end diff --git a/spec/pe_client/resources/code_manager_v1_spec.rb b/spec/pe_client/resources/code_manager_v1_spec.rb index 83afe07..f8aa927 100644 --- a/spec/pe_client/resources/code_manager_v1_spec.rb +++ b/spec/pe_client/resources/code_manager_v1_spec.rb @@ -106,32 +106,6 @@ expect(result).to eq({"status" => "ok"}) end - it "includes optional prefix parameter" do - stub_request(:post, "#{base_url}/code-manager/v1/webhook?type=github&prefix=myprefix") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"status":"ok"}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.webhook(type: "github", prefix: "myprefix") - expect(result).to be_a(Hash) - end - - it "includes optional token parameter" do - stub_request(:post, "#{base_url}/code-manager/v1/webhook?type=gitlab&token=abc123") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"status":"ok"}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.webhook(type: "gitlab", token: "abc123") - expect(result).to be_a(Hash) - end - it "includes all optional parameters when provided" do stub_request(:post, "#{base_url}/code-manager/v1/webhook?type=bitbucket&prefix=custom&token=xyz789") .with(headers: {"X-Authentication" => api_key}) diff --git a/spec/pe_client/resources/metrics_v1_spec.rb b/spec/pe_client/resources/metrics_v1_spec.rb index 322a19c..fbee3ee 100644 --- a/spec/pe_client/resources/metrics_v1_spec.rb +++ b/spec/pe_client/resources/metrics_v1_spec.rb @@ -24,71 +24,36 @@ end describe "#get" do - context "when requesting a single metric" do - it "retrieves the requested MBean metric" do - metric_name = "java.lang:type=Memory" - stub_request(:get, "#{base_url}/metrics/v1/mbeans/#{metric_name}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"HeapMemoryUsage":{"used":1000000}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.get(metric_name) - expect(result).to eq({"HeapMemoryUsage" => {"used" => 1000000}}) - end - - it "returns a Hash for a single metric" do - metric_name = "java.lang:type=Runtime" - stub_request(:get, "#{base_url}/metrics/v1/mbeans/#{metric_name}") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"Uptime":123456}', - headers: {"Content-Type" => "application/json"} - ) + it "retrieves a single MBean metric" do + metric_name = "java.lang:type=Memory" + stub_request(:get, "#{base_url}/metrics/v1/mbeans/#{metric_name}") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"HeapMemoryUsage":{"used":1000000}}', + headers: {"Content-Type" => "application/json"} + ) - result = resource.get(metric_name) - expect(result).to be_a(Hash) - end + result = resource.get(metric_name) + expect(result).to eq({"HeapMemoryUsage" => {"used" => 1000000}}) end - context "when requesting multiple metrics" do - it "posts to the mbeans endpoint with an array of metrics" do - metrics = ["java.lang:type=Memory", "java.lang:type=Runtime"] - stub_request(:post, "#{base_url}/metrics/v1/mbeans") - .with( - body: '["java.lang:type=Memory","java.lang:type=Runtime"]', - headers: {"X-Authentication" => api_key, "Content-Type" => "application/json"} - ) - .to_return( - status: 200, - body: '[{"HeapMemoryUsage":{"used":1000000}},{"Uptime":123456}]', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.get(metrics) - expect(result).to be_an(Array) - expect(result.length).to eq(2) - end - - it "returns an Array for multiple metrics" do - metrics = ["java.lang:type=Memory", "java.lang:type=Runtime"] - stub_request(:post, "#{base_url}/metrics/v1/mbeans") - .with( - body: '["java.lang:type=Memory","java.lang:type=Runtime"]', - headers: {"X-Authentication" => api_key} - ) - .to_return( - status: 200, - body: '[{"metric1":"value1"},{"metric2":"value2"}]', - headers: {"Content-Type" => "application/json"} - ) + it "retrieves multiple MBean metrics" do + metrics = ["java.lang:type=Memory", "java.lang:type=Runtime"] + stub_request(:post, "#{base_url}/metrics/v1/mbeans") + .with( + body: '["java.lang:type=Memory","java.lang:type=Runtime"]', + headers: {"X-Authentication" => api_key, "Content-Type" => "application/json"} + ) + .to_return( + status: 200, + body: '[{"HeapMemoryUsage":{"used":1000000}},{"Uptime":123456}]', + headers: {"Content-Type" => "application/json"} + ) - result = resource.get(metrics) - expect(result).to be_an(Array) - end + result = resource.get(metrics) + expect(result).to be_an(Array) + expect(result.length).to eq(2) end end end diff --git a/spec/pe_client/resources/metrics_v2_spec.rb b/spec/pe_client/resources/metrics_v2_spec.rb index 6a6a93c..394c416 100644 --- a/spec/pe_client/resources/metrics_v2_spec.rb +++ b/spec/pe_client/resources/metrics_v2_spec.rb @@ -21,192 +21,123 @@ result = resource.list expect(result).to eq({"value" => {"java.lang" => {"type=Memory" => {}}}}) end + end - it "returns a Hash" do - stub_request(:get, "#{base_url}/metrics/v2/list") + describe "#read" do + it "retrieves orchestrator service metrics data" do + stub_request(:get, "#{base_url}/metrics/v2/read/java.util.logging:type=Logging/LoggerNames") .with(headers: {"X-Authentication" => api_key}) .to_return( status: 200, - body: '{"status":200}', + body: '{"value":["logger1","logger2"]}', headers: {"Content-Type" => "application/json"} ) - result = resource.list - expect(result).to be_a(Hash) + result = resource.read(mbean_names: "java.util.logging:type=Logging", attributes: "LoggerNames") + expect(result).to eq({"value" => ["logger1", "logger2"]}) end - end - describe "#read" do - context "with required parameters" do - it "retrieves orchestrator service metrics data" do - stub_request(:get, "#{base_url}/metrics/v2/read/java.util.logging:type=Logging/LoggerNames") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"value":["logger1","logger2"]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.read(mbean_names: "java.util.logging:type=Logging", attributes: "LoggerNames") - expect(result).to eq({"value" => ["logger1", "logger2"]}) - end - - it "returns a Hash" do - stub_request(:get, "#{base_url}/metrics/v2/read/java.lang:type=Memory/HeapMemoryUsage") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"value":{"used":1000000}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.read(mbean_names: "java.lang:type=Memory", attributes: "HeapMemoryUsage") - expect(result).to be_a(Hash) - end - end - - context "with multiple MBean names or attributes" do - it "supports comma-separated MBean names" do - stub_request(:get, "#{base_url}/metrics/v2/read/java.lang:name=*,type=GarbageCollector/CollectionCount") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"value":{"java.lang:name=PS Scavenge,type=GarbageCollector":{"CollectionCount":10}}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.read( - mbean_names: "java.lang:name=*,type=GarbageCollector", - attributes: "CollectionCount" + it "supports comma-separated MBean names" do + stub_request(:get, "#{base_url}/metrics/v2/read/java.lang:name=*,type=GarbageCollector/CollectionCount") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"value":{"java.lang:name=PS Scavenge,type=GarbageCollector":{"CollectionCount":10}}}', + headers: {"Content-Type" => "application/json"} ) - expect(result).to be_a(Hash) - end + + result = resource.read( + mbean_names: "java.lang:name=*,type=GarbageCollector", + attributes: "CollectionCount" + ) + expect(result).to be_a(Hash) end - context "with inner_path_filter" do - it "includes the inner path filter in the request" do - stub_request(:get, "#{base_url}/metrics/v2/read/java.lang:type=Memory/HeapMemoryUsage/used") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"value":1000000}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.read( - mbean_names: "java.lang:type=Memory", - attributes: "HeapMemoryUsage", - inner_path_filter: "used" + it "includes inner path filter when provided" do + stub_request(:get, "#{base_url}/metrics/v2/read/java.lang:type=Memory/HeapMemoryUsage/used") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"value":1000000}', + headers: {"Content-Type" => "application/json"} ) - expect(result).to eq({"value" => 1000000}) - end - end - context "without inner_path_filter" do - it "does not include inner_path_filter when nil" do - stub_request(:get, "#{base_url}/metrics/v2/read/java.lang:type=Memory/HeapMemoryUsage") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"value":{"used":1000000}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.read(mbean_names: "java.lang:type=Memory", attributes: "HeapMemoryUsage") - expect(result).to be_a(Hash) - end + result = resource.read( + mbean_names: "java.lang:type=Memory", + attributes: "HeapMemoryUsage", + inner_path_filter: "used" + ) + expect(result).to eq({"value" => 1000000}) end end describe "#complex_read" do - context "with a Hash body" do - it "posts a complex query to retrieve metrics data" do - request_body = { - type: "read", - mbean: "java.lang:type=Memory", - attribute: "HeapMemoryUsage", - path: "used" - } - - stub_request(:post, "#{base_url}/metrics/v2/read") - .with( - body: request_body.to_json, - headers: {"X-Authentication" => api_key, "Content-Type" => "application/json"} - ) - .to_return( - status: 200, - body: '{"value":1000000,"status":200}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.complex_read(request_body) - expect(result).to eq({"value" => 1000000, "status" => 200}) - end - - it "returns a Hash" do - stub_request(:post, "#{base_url}/metrics/v2/read") - .with( - body: '{"type":"read","mbean":"java.lang:type=Runtime"}', - headers: {"X-Authentication" => api_key} - ) - .to_return( - status: 200, - body: '{"value":{"Uptime":123456}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.complex_read({type: "read", mbean: "java.lang:type=Runtime"}) - expect(result).to be_a(Hash) - end + it "posts a complex query to retrieve metrics data" do + request_body = { + type: "read", + mbean: "java.lang:type=Memory", + attribute: "HeapMemoryUsage", + path: "used" + } + + stub_request(:post, "#{base_url}/metrics/v2/read") + .with( + body: request_body.to_json, + headers: {"X-Authentication" => api_key, "Content-Type" => "application/json"} + ) + .to_return( + status: 200, + body: '{"value":1000000,"status":200}', + headers: {"Content-Type" => "application/json"} + ) + + result = resource.complex_read(request_body) + expect(result).to eq({"value" => 1000000, "status" => 200}) end - context "with an Array of Hashes body" do - it "posts multiple complex queries" do - request_body = [ - {type: "read", mbean: "java.lang:type=Memory", attribute: "HeapMemoryUsage"}, - {type: "read", mbean: "java.lang:type=Runtime", attribute: "Uptime"} - ] - - stub_request(:post, "#{base_url}/metrics/v2/read") - .with( - body: request_body.to_json, - headers: {"X-Authentication" => api_key, "Content-Type" => "application/json"} - ) - .to_return( - status: 200, - body: '{"results":[{"value":{"used":1000000},"status":200},{"value":123456,"status":200}]}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.complex_read(request_body) - expect(result).to be_a(Hash) - expect(result["results"]).to be_an(Array) - end + it "posts multiple complex queries" do + request_body = [ + {type: "read", mbean: "java.lang:type=Memory", attribute: "HeapMemoryUsage"}, + {type: "read", mbean: "java.lang:type=Runtime", attribute: "Uptime"} + ] + + stub_request(:post, "#{base_url}/metrics/v2/read") + .with( + body: request_body.to_json, + headers: {"X-Authentication" => api_key, "Content-Type" => "application/json"} + ) + .to_return( + status: 200, + body: '{"results":[{"value":{"used":1000000},"status":200},{"value":123456,"status":200}]}', + headers: {"Content-Type" => "application/json"} + ) + + result = resource.complex_read(request_body) + expect(result).to be_a(Hash) + expect(result["results"]).to be_an(Array) end - context "with Jolokia protocol" do - it "supports Jolokia protocol requests" do - jolokia_request = { - type: "read", - mbean: "java.lang:type=Memory", - attribute: ["HeapMemoryUsage", "NonHeapMemoryUsage"], - config: {ignoreErrors: true} - } - - stub_request(:post, "#{base_url}/metrics/v2/read") - .with( - body: jolokia_request.to_json, - headers: {"X-Authentication" => api_key} - ) - .to_return( - status: 200, - body: '{"value":{"HeapMemoryUsage":{},"NonHeapMemoryUsage":{}},"status":200}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.complex_read(jolokia_request) - expect(result).to be_a(Hash) - end + it "supports Jolokia protocol requests" do + jolokia_request = { + type: "read", + mbean: "java.lang:type=Memory", + attribute: ["HeapMemoryUsage", "NonHeapMemoryUsage"], + config: {ignoreErrors: true} + } + + stub_request(:post, "#{base_url}/metrics/v2/read") + .with( + body: jolokia_request.to_json, + headers: {"X-Authentication" => api_key} + ) + .to_return( + status: 200, + body: '{"value":{"HeapMemoryUsage":{},"NonHeapMemoryUsage":{}},"status":200}', + headers: {"Content-Type" => "application/json"} + ) + + result = resource.complex_read(jolokia_request) + expect(result).to be_a(Hash) end end end diff --git a/spec/pe_client/resources/node_classifier_v1_spec.rb b/spec/pe_client/resources/node_classifier_v1_spec.rb index 811edf3..cad4036 100644 --- a/spec/pe_client/resources/node_classifier_v1_spec.rb +++ b/spec/pe_client/resources/node_classifier_v1_spec.rb @@ -6,161 +6,18 @@ let(:api_key) { "test_api_key" } let(:base_url) { "https://puppet.example.com:8143" } let(:client) { PEClient::Client.new(api_key: api_key, base_url: base_url, ca_file: nil) } - let(:resource) { described_class.new(client) } - - describe "#groups" do - it "returns a Groups resource" do - groups = resource.groups - expect(groups).to be_a(PEClient::Resource::NodeClassifierV1::Groups) - end - - it "memorizes the resource" do - groups1 = resource.groups - groups2 = resource.groups - expect(groups1).to equal(groups2) - end - end - - describe "#classes" do - it "returns a Classes resource" do - classes = resource.classes - expect(classes).to be_a(PEClient::Resource::NodeClassifierV1::Classes) - end - - it "memorizes the resource" do - classes1 = resource.classes - classes2 = resource.classes - expect(classes1).to equal(classes2) - end - end - - describe "#classification" do - it "returns a Classification resource" do - classification = resource.classification - expect(classification).to be_a(PEClient::Resource::NodeClassifierV1::Classification) - end - - it "memorizes the resource" do - classification1 = resource.classification - classification2 = resource.classification - expect(classification1).to equal(classification2) - end - end - - describe "#commands" do - it "returns a Commands resource" do - commands = resource.commands - expect(commands).to be_a(PEClient::Resource::NodeClassifierV1::Commands) - end - - it "memorizes the resource" do - commands1 = resource.commands - commands2 = resource.commands - expect(commands1).to equal(commands2) - end - end - - describe "#environments" do - it "returns an Environments resource" do - environments = resource.environments - expect(environments).to be_a(PEClient::Resource::NodeClassifierV1::Environments) - end - - it "memorizes the resource" do - environments1 = resource.environments - environments2 = resource.environments - expect(environments1).to equal(environments2) - end - end - - describe "#nodes" do - it "returns a Nodes resource" do - nodes = resource.nodes - expect(nodes).to be_a(PEClient::Resource::NodeClassifierV1::Nodes) - end - - it "memorizes the resource" do - nodes1 = resource.nodes - nodes2 = resource.nodes - expect(nodes1).to equal(nodes2) - end - end - - describe "#group_children" do - it "returns a GroupChildren resource" do - group_children = resource.group_children - expect(group_children).to be_a(PEClient::Resource::NodeClassifierV1::GroupChildren) - end - - it "memorizes the resource" do - group_children1 = resource.group_children - group_children2 = resource.group_children - expect(group_children1).to equal(group_children2) - end - end - - describe "#rules" do - it "returns a Rules resource" do - rules = resource.rules - expect(rules).to be_a(PEClient::Resource::NodeClassifierV1::Rules) - end - - it "memorizes the resource" do - rules1 = resource.rules - rules2 = resource.rules - expect(rules1).to equal(rules2) - end - end - - describe "#import_hierarchy" do - it "returns an ImportHierarchy resource" do - import_hierarchy = resource.import_hierarchy - expect(import_hierarchy).to be_a(PEClient::Resource::NodeClassifierV1::ImportHierarchy) - end - - it "memorizes the resource" do - import_hierarchy1 = resource.import_hierarchy - import_hierarchy2 = resource.import_hierarchy - expect(import_hierarchy1).to equal(import_hierarchy2) - end - end - - describe "#last_class_update" do - it "returns a LastClassUpdate resource" do - last_class_update = resource.last_class_update - expect(last_class_update).to be_a(PEClient::Resource::NodeClassifierV1::LastClassUpdate) - end - - it "memorizes the resource" do - last_class_update1 = resource.last_class_update - last_class_update2 = resource.last_class_update - expect(last_class_update1).to equal(last_class_update2) - end - end - - describe "#update_classes" do - it "returns an UpdateClasses resource" do - update_classes = resource.update_classes - expect(update_classes).to be_a(PEClient::Resource::NodeClassifierV1::UpdateClasses) - end - - it "memorizes the resource" do - update_classes1 = resource.update_classes - update_classes2 = resource.update_classes - expect(update_classes1).to equal(update_classes2) - end - end - - describe "#validation" do - it "returns a Validation resource" do - validation = resource.validation - expect(validation).to be_a(PEClient::Resource::NodeClassifierV1::Validation) - end - - it "memorizes the resource" do - validation1 = resource.validation - validation2 = resource.validation - expect(validation1).to equal(validation2) - end - end + subject(:resource) { described_class.new(client) } + + include_examples "a memoized resource", :groups, "PEClient::Resource::NodeClassifierV1::Groups" + include_examples "a memoized resource", :classes, "PEClient::Resource::NodeClassifierV1::Classes" + include_examples "a memoized resource", :classification, "PEClient::Resource::NodeClassifierV1::Classification" + include_examples "a memoized resource", :commands, "PEClient::Resource::NodeClassifierV1::Commands" + include_examples "a memoized resource", :environments, "PEClient::Resource::NodeClassifierV1::Environments" + include_examples "a memoized resource", :nodes, "PEClient::Resource::NodeClassifierV1::Nodes" + include_examples "a memoized resource", :group_children, "PEClient::Resource::NodeClassifierV1::GroupChildren" + include_examples "a memoized resource", :rules, "PEClient::Resource::NodeClassifierV1::Rules" + include_examples "a memoized resource", :import_hierarchy, "PEClient::Resource::NodeClassifierV1::ImportHierarchy" + include_examples "a memoized resource", :last_class_update, "PEClient::Resource::NodeClassifierV1::LastClassUpdate" + include_examples "a memoized resource", :update_classes, "PEClient::Resource::NodeClassifierV1::UpdateClasses" + include_examples "a memoized resource", :validation, "PEClient::Resource::NodeClassifierV1::Validation" end diff --git a/spec/pe_client/resources/node_inventory_v1_spec.rb b/spec/pe_client/resources/node_inventory_v1_spec.rb index e6c37f4..1cb337f 100644 --- a/spec/pe_client/resources/node_inventory_v1_spec.rb +++ b/spec/pe_client/resources/node_inventory_v1_spec.rb @@ -9,107 +9,34 @@ let(:resource) { described_class.new(client) } describe "#connections" do - it "queries all connections with default parameters" do + it "queries connections with all parameters" do stub_request(:post, "https://puppet.example.com:8143/inventory/v1/query/connections") .with( - body: "{}", + body: '{"certnames":["node1.example.com"],"sensitive":true,"extract":["type","parameters"]}', headers: {"X-Authentication" => api_key} ) .to_return(status: 200, body: '{"connection_id": "1"}', headers: {"Content-Type" => "application/json"}) - response = resource.connections - expect(response).to eq({"connection_id" => "1"}) - end - - it "includes certnames when provided" do - stub_request(:post, "https://puppet.example.com:8143/inventory/v1/query/connections") - .with( - body: '{"certnames":["node1.example.com","node2.example.com"]}', - headers: {"X-Authentication" => api_key} - ) - .to_return(status: 200, body: '{"connection_id": "1"}', headers: {"Content-Type" => "application/json"}) - - response = resource.connections(certnames: ["node1.example.com", "node2.example.com"]) - expect(response).to eq({"connection_id" => "1"}) - end - - it "includes sensitive parameter when true" do - stub_request(:post, "https://puppet.example.com:8143/inventory/v1/query/connections") - .with( - body: '{"sensitive":true}', - headers: {"X-Authentication" => api_key} - ) - .to_return(status: 200, body: '{"connection_id": "1"}', headers: {"Content-Type" => "application/json"}) - - response = resource.connections(sensitive: true) - expect(response).to eq({"connection_id" => "1"}) - end - - it "includes extract parameter when provided" do - stub_request(:post, "https://puppet.example.com:8143/inventory/v1/query/connections") - .with( - body: '{"extract":["type","parameters"]}', - headers: {"X-Authentication" => api_key} - ) - .to_return(status: 200, body: '{"connection_id": "1"}', headers: {"Content-Type" => "application/json"}) - - response = resource.connections(extract: ["type", "parameters"]) + response = resource.connections( + certnames: ["node1.example.com"], + sensitive: true, + extract: ["type", "parameters"] + ) expect(response).to eq({"connection_id" => "1"}) end end describe "#create_connections" do - it "creates a new connection with required parameters" do - stub_request(:post, "https://puppet.example.com:8143/inventory/v1/command/create-connection") - .with( - body: '{"certnames":["node1.example.com"],"type":"ssh","parameters":{},"sensitive_parameters":{},"duplicates":"error"}', - headers: {"X-Authentication" => api_key} - ) - .to_return(status: 200, body: '{"connection_id": "new-id"}', headers: {"Content-Type" => "application/json"}) - - response = resource.create_connections( - certnames: ["node1.example.com"], - type: "ssh" - ) - expect(response).to eq({"connection_id" => "new-id"}) - end - - it "includes parameters when provided" do - stub_request(:post, "https://puppet.example.com:8143/inventory/v1/command/create-connection") - .with( - body: hash_including("parameters" => {"port" => 22}), - headers: {"X-Authentication" => api_key} - ) - .to_return(status: 200, body: '{"connection_id": "new-id"}', headers: {"Content-Type" => "application/json"}) - - response = resource.create_connections( - certnames: ["node1.example.com"], - type: "ssh", - parameters: {port: 22} - ) - expect(response).to eq({"connection_id" => "new-id"}) - end - - it "includes sensitive_parameters when provided" do - stub_request(:post, "https://puppet.example.com:8143/inventory/v1/command/create-connection") - .with( - body: hash_including("sensitive_parameters" => {"password" => "secret"}), - headers: {"X-Authentication" => api_key} - ) - .to_return(status: 200, body: '{"connection_id": "new-id"}', headers: {"Content-Type" => "application/json"}) - - response = resource.create_connections( - certnames: ["node1.example.com"], - type: "ssh", - sensitive_parameters: {password: "secret"} - ) - expect(response).to eq({"connection_id" => "new-id"}) - end - - it "accepts replace for duplicates parameter" do + it "creates a new connection with all parameters" do stub_request(:post, "https://puppet.example.com:8143/inventory/v1/command/create-connection") .with( - body: hash_including("duplicates" => "replace"), + body: hash_including( + "certnames" => ["node1.example.com"], + "type" => "ssh", + "parameters" => {"port" => 22}, + "sensitive_parameters" => {"password" => "secret"}, + "duplicates" => "replace" + ), headers: {"X-Authentication" => api_key} ) .to_return(status: 200, body: '{"connection_id": "new-id"}', headers: {"Content-Type" => "application/json"}) @@ -117,6 +44,8 @@ response = resource.create_connections( certnames: ["node1.example.com"], type: "ssh", + parameters: {port: 22}, + sensitive_parameters: {password: "secret"}, duplicates: "replace" ) expect(response).to eq({"connection_id" => "new-id"}) diff --git a/spec/pe_client/resources/orchestrator_v1/jobs_spec.rb b/spec/pe_client/resources/orchestrator_v1/jobs_spec.rb index d4a9871..7199c51 100644 --- a/spec/pe_client/resources/orchestrator_v1/jobs_spec.rb +++ b/spec/pe_client/resources/orchestrator_v1/jobs_spec.rb @@ -37,21 +37,8 @@ expect(response).to eq({"id" => "1234", "name" => "deploy", "state" => "finished"}) end - it "retrieves jobs with query parameters" do - stub_request(:get, "#{base_url}/orchestrator/v1/jobs?limit=10&offset=0&order=asc&order_by=timestamp") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[]}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.get(limit: 10, offset: 0, order_by: "timestamp", order: "asc") - expect(response).to eq({"items" => []}) - end - - it "retrieves jobs filtered by type" do - stub_request(:get, "#{base_url}/orchestrator/v1/jobs?type=task") + it "retrieves jobs with all query parameters" do + stub_request(:get, "#{base_url}/orchestrator/v1/jobs?limit=10&max_finish_timestamp=2025-11-25T23:59:59Z&min_finish_timestamp=2025-11-01T00:00:00Z&offset=0&order=asc&order_by=timestamp&type=task") .with(headers: {"X-Authentication" => api_key}) .to_return( status: 200, @@ -59,47 +46,26 @@ headers: {"Content-Type" => "application/json"} ) - response = resource.get(type: "task") - expect(response).to eq({"items" => [{"id" => "1234", "type" => "task"}]}) - end - - it "retrieves jobs filtered by timestamp range" do - stub_request(:get, "#{base_url}/orchestrator/v1/jobs?min_finish_timestamp=2025-11-01T00:00:00Z&max_finish_timestamp=2025-11-25T23:59:59Z") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[]}', - headers: {"Content-Type" => "application/json"} - ) - response = resource.get( + limit: 10, + offset: 0, + order_by: "timestamp", + order: "asc", + type: "task", min_finish_timestamp: "2025-11-01T00:00:00Z", max_finish_timestamp: "2025-11-25T23:59:59Z" ) - expect(response).to eq({"items" => []}) + expect(response).to eq({"items" => [{"id" => "1234", "type" => "task"}]}) end end describe "#nodes" do - it "retrieves information about nodes associated with a job" do - stub_request(:get, "#{base_url}/orchestrator/v1/jobs/#{job_id}/nodes") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[{"name":"node1.example.com","state":"finished"}]}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.nodes(job_id) - expect(response).to eq({"items" => [{"name" => "node1.example.com", "state" => "finished"}]}) - end - - it "retrieves nodes with query parameters" do + it "retrieves nodes with all query parameters" do stub_request(:get, "#{base_url}/orchestrator/v1/jobs/#{job_id}/nodes?limit=10&offset=0&order=asc&order_by=name&state=finished") .with(headers: {"X-Authentication" => api_key}) .to_return( status: 200, - body: '{"items":[]}', + body: '{"items":[{"name":"node1.example.com","state":"finished"}]}', headers: {"Content-Type" => "application/json"} ) @@ -111,7 +77,7 @@ order: "asc", state: "finished" ) - expect(response).to eq({"items" => []}) + expect(response).to eq({"items" => [{"name" => "node1.example.com", "state" => "finished"}]}) end end @@ -131,20 +97,7 @@ end describe "#events" do - it "retrieves a list of events that occurred during a job" do - stub_request(:get, "#{base_url}/orchestrator/v1/jobs/#{job_id}/events") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[{"id":1,"type":"started"}]}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.events(job_id) - expect(response).to eq({"items" => [{"id" => 1, "type" => "started"}]}) - end - - it "retrieves events starting from a specific event ID" do + it "retrieves events with optional start parameter" do stub_request(:get, "#{base_url}/orchestrator/v1/jobs/#{job_id}/events?start=5") .with(headers: {"X-Authentication" => api_key}) .to_return( diff --git a/spec/pe_client/resources/orchestrator_v1/plan_jobs_spec.rb b/spec/pe_client/resources/orchestrator_v1/plan_jobs_spec.rb index 60704ae..a5607c6 100644 --- a/spec/pe_client/resources/orchestrator_v1/plan_jobs_spec.rb +++ b/spec/pe_client/resources/orchestrator_v1/plan_jobs_spec.rb @@ -37,34 +37,8 @@ expect(response).to eq({"name" => 1234, "plan_name" => "mymodule::myplan", "state" => "finished"}) end - it "retrieves plan jobs with query parameters" do - stub_request(:get, "#{base_url}/orchestrator/v1/plan_jobs?limit=10&offset=0&order=asc&order_by=timestamp") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[]}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.get(limit: 10, offset: 0, order_by: "timestamp", order: "asc") - expect(response).to eq({"items" => []}) - end - - it "retrieves plan jobs excluding results" do - stub_request(:get, "#{base_url}/orchestrator/v1/plan_jobs?results=exclude") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[]}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.get(results: "exclude") - expect(response).to eq({"items" => []}) - end - - it "retrieves plan jobs filtered by timestamp range" do - stub_request(:get, "#{base_url}/orchestrator/v1/plan_jobs?min_finish_timestamp=2025-11-01T00:00:00Z&max_finish_timestamp=2025-11-25T23:59:59Z") + it "retrieves plan jobs with all query parameters" do + stub_request(:get, "#{base_url}/orchestrator/v1/plan_jobs?limit=10&max_finish_timestamp=2025-11-25T23:59:59Z&min_finish_timestamp=2025-11-01T00:00:00Z&offset=0&order=asc&order_by=timestamp&results=exclude") .with(headers: {"X-Authentication" => api_key}) .to_return( status: 200, @@ -73,6 +47,11 @@ ) response = resource.get( + limit: 10, + offset: 0, + order_by: "timestamp", + order: "asc", + results: "exclude", min_finish_timestamp: "2025-11-01T00:00:00Z", max_finish_timestamp: "2025-11-25T23:59:59Z" ) @@ -81,20 +60,7 @@ end describe "#events" do - it "retrieves a list of events for a plan job" do - stub_request(:get, "#{base_url}/orchestrator/v1/plan_jobs/#{job_id}/events") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[{"id":1,"type":"started"}]}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.events(job_id: job_id) - expect(response).to eq({"items" => [{"id" => 1, "type" => "started"}]}) - end - - it "retrieves events starting from a specific event ID" do + it "retrieves events with optional start parameter" do stub_request(:get, "#{base_url}/orchestrator/v1/plan_jobs/#{job_id}/events?start=5") .with(headers: {"X-Authentication" => api_key}) .to_return( diff --git a/spec/pe_client/resources/orchestrator_v1/plans_spec.rb b/spec/pe_client/resources/orchestrator_v1/plans_spec.rb index 988ded7..f68dd8b 100644 --- a/spec/pe_client/resources/orchestrator_v1/plans_spec.rb +++ b/spec/pe_client/resources/orchestrator_v1/plans_spec.rb @@ -23,43 +23,17 @@ expect(response).to eq({"items" => [{"name" => "mymodule::plan1"}, {"name" => "mymodule::plan2"}]}) end - it "lists all plans in a specific environment" do - stub_request(:get, "#{base_url}/orchestrator/v1/plans?environment=production") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[{"name":"mymodule::plan1"}]}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.get(environment: "production") - expect(response).to eq({"items" => [{"name" => "mymodule::plan1"}]}) - end - - it "gets information about a specific plan" do - stub_request(:get, "#{base_url}/orchestrator/v1/plans/mymodule/myplan") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"name":"mymodule::myplan","metadata":{"description":"My plan"}}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.get(module_name: "mymodule", plan_name: "myplan") - expect(response).to eq({"name" => "mymodule::myplan", "metadata" => {"description" => "My plan"}}) - end - - it "gets information about a specific plan in a specific environment" do + it "gets information about a specific plan with environment parameter" do stub_request(:get, "#{base_url}/orchestrator/v1/plans/mymodule/myplan?environment=production") .with(headers: {"X-Authentication" => api_key}) .to_return( status: 200, - body: '{"name":"mymodule::myplan","environment":"production"}', + body: '{"name":"mymodule::myplan","environment":"production","metadata":{"description":"My plan"}}', headers: {"Content-Type" => "application/json"} ) response = resource.get(module_name: "mymodule", plan_name: "myplan", environment: "production") - expect(response).to eq({"name" => "mymodule::myplan", "environment" => "production"}) + expect(response).to eq({"name" => "mymodule::myplan", "environment" => "production", "metadata" => {"description" => "My plan"}}) end end end diff --git a/spec/pe_client/resources/orchestrator_v1/scheduled_jobs_spec.rb b/spec/pe_client/resources/orchestrator_v1/scheduled_jobs_spec.rb index d585aec..b5ccbe4 100644 --- a/spec/pe_client/resources/orchestrator_v1/scheduled_jobs_spec.rb +++ b/spec/pe_client/resources/orchestrator_v1/scheduled_jobs_spec.rb @@ -37,21 +37,8 @@ expect(response).to eq({"id" => "sched-job-123", "type" => "deploy", "environment" => "production"}) end - it "retrieves scheduled jobs with query parameters" do - stub_request(:get, "#{base_url}/orchestrator/v1/scheduled_jobs/environment_jobs?limit=10&offset=0&order=asc&order_by=next_run_time") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[]}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.get(limit: 10, offset: 0, order_by: "next_run_time", order: "asc") - expect(response).to eq({"items" => []}) - end - - it "retrieves scheduled jobs filtered by type" do - stub_request(:get, "#{base_url}/orchestrator/v1/scheduled_jobs/environment_jobs?type=task") + it "retrieves scheduled jobs with all query parameters" do + stub_request(:get, "#{base_url}/orchestrator/v1/scheduled_jobs/environment_jobs?limit=10&offset=0&order=asc&order_by=next_run_time&type=task") .with(headers: {"X-Authentication" => api_key}) .to_return( status: 200, @@ -59,7 +46,7 @@ headers: {"Content-Type" => "application/json"} ) - response = resource.get(type: "task") + response = resource.get(limit: 10, offset: 0, order_by: "next_run_time", order: "asc", type: "task") expect(response).to eq({"items" => [{"id" => "sched-job-456", "type" => "task"}]}) end end diff --git a/spec/pe_client/resources/orchestrator_v1/tasks_spec.rb b/spec/pe_client/resources/orchestrator_v1/tasks_spec.rb index 710c27a..7117de1 100644 --- a/spec/pe_client/resources/orchestrator_v1/tasks_spec.rb +++ b/spec/pe_client/resources/orchestrator_v1/tasks_spec.rb @@ -23,43 +23,17 @@ expect(response).to eq({"items" => [{"name" => "package"}, {"name" => "service"}]}) end - it "lists all tasks in a specific environment" do - stub_request(:get, "#{base_url}/orchestrator/v1/tasks?environment=production") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"items":[{"name":"package"}]}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.get(environment: "production") - expect(response).to eq({"items" => [{"name" => "package"}]}) - end - - it "gets information about a specific task" do - stub_request(:get, "#{base_url}/orchestrator/v1/tasks/mymodule/mytask") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"name":"mymodule::mytask","metadata":{"description":"My task"}}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.get(module_name: "mymodule", task_name: "mytask") - expect(response).to eq({"name" => "mymodule::mytask", "metadata" => {"description" => "My task"}}) - end - - it "gets information about a specific task in a specific environment" do + it "gets information about a specific task with environment parameter" do stub_request(:get, "#{base_url}/orchestrator/v1/tasks/mymodule/mytask?environment=production") .with(headers: {"X-Authentication" => api_key}) .to_return( status: 200, - body: '{"name":"mymodule::mytask","environment":"production"}', + body: '{"name":"mymodule::mytask","environment":"production","metadata":{"description":"My task"}}', headers: {"Content-Type" => "application/json"} ) response = resource.get(module_name: "mymodule", task_name: "mytask", environment: "production") - expect(response).to eq({"name" => "mymodule::mytask", "environment" => "production"}) + expect(response).to eq({"name" => "mymodule::mytask", "environment" => "production", "metadata" => {"description" => "My task"}}) end end end diff --git a/spec/pe_client/resources/orchestrator_v1_spec.rb b/spec/pe_client/resources/orchestrator_v1_spec.rb index 8ef7b59..01fa11e 100644 --- a/spec/pe_client/resources/orchestrator_v1_spec.rb +++ b/spec/pe_client/resources/orchestrator_v1_spec.rb @@ -6,7 +6,7 @@ let(:api_key) { "test_api_key" } let(:base_url) { "https://puppet.example.com:8143" } let(:client) { PEClient::Client.new(api_key: api_key, base_url: base_url, ca_file: nil) } - let(:resource) { described_class.new(client) } + subject(:resource) { described_class.new(client) } describe "#get" do it "retrieves metadata about the orchestrator API" do @@ -24,8 +24,8 @@ end describe "#usage" do - it "retrieves daily node usage without parameters" do - stub_request(:get, "#{base_url}/orchestrator/v1/usage") + it "retrieves daily node usage with all parameters" do + stub_request(:get, "#{base_url}/orchestrator/v1/usage?start_date=2025-11-01&end_date=2025-11-25&events=exclude") .with(headers: {"X-Authentication" => api_key}) .to_return( status: 200, @@ -33,138 +33,17 @@ headers: {"Content-Type" => "application/json"} ) - response = resource.usage + response = resource.usage(start_date: "2025-11-01", end_date: "2025-11-25", events: "exclude") expect(response).to eq({"node_count" => 100}) end - - it "retrieves daily node usage with date range" do - stub_request(:get, "#{base_url}/orchestrator/v1/usage?start_date=2025-11-01&end_date=2025-11-25") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"node_count": 100}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.usage(start_date: "2025-11-01", end_date: "2025-11-25") - expect(response).to eq({"node_count" => 100}) - end - - it "retrieves daily node usage excluding events" do - stub_request(:get, "#{base_url}/orchestrator/v1/usage?events=exclude") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"node_count": 100}', - headers: {"Content-Type" => "application/json"} - ) - - response = resource.usage(events: "exclude") - expect(response).to eq({"node_count" => 100}) - end - end - - describe "#command" do - it "returns a Command resource" do - command = resource.command - expect(command).to be_a(PEClient::Resource::OrchestratorV1::Command) - end - - it "memorizes the resource" do - command1 = resource.command - command2 = resource.command - expect(command1).to equal(command2) - end - end - - describe "#inventory" do - it "returns an Inventory resource" do - inventory = resource.inventory - expect(inventory).to be_a(PEClient::Resource::OrchestratorV1::Inventory) - end - - it "memorizes the resource" do - inventory1 = resource.inventory - inventory2 = resource.inventory - expect(inventory1).to equal(inventory2) - end end - describe "#jobs" do - it "returns a Jobs resource" do - jobs = resource.jobs - expect(jobs).to be_a(PEClient::Resource::OrchestratorV1::Jobs) - end - - it "memorizes the resource" do - jobs1 = resource.jobs - jobs2 = resource.jobs - expect(jobs1).to equal(jobs2) - end - end - - describe "#scheduled_jobs" do - it "returns a ScheduledJobs resource" do - scheduled_jobs = resource.scheduled_jobs - expect(scheduled_jobs).to be_a(PEClient::Resource::OrchestratorV1::ScheduledJobs) - end - - it "memorizes the resource" do - scheduled_jobs1 = resource.scheduled_jobs - scheduled_jobs2 = resource.scheduled_jobs - expect(scheduled_jobs1).to equal(scheduled_jobs2) - end - end - - describe "#plans" do - it "returns a Plans resource" do - plans = resource.plans - expect(plans).to be_a(PEClient::Resource::OrchestratorV1::Plans) - end - - it "memorizes the resource" do - plans1 = resource.plans - plans2 = resource.plans - expect(plans1).to equal(plans2) - end - end - - describe "#plan_jobs" do - it "returns a PlanJobs resource" do - plan_jobs = resource.plan_jobs - expect(plan_jobs).to be_a(PEClient::Resource::OrchestratorV1::PlanJobs) - end - - it "memorizes the resource" do - plan_jobs1 = resource.plan_jobs - plan_jobs2 = resource.plan_jobs - expect(plan_jobs1).to equal(plan_jobs2) - end - end - - describe "#tasks" do - it "returns a Tasks resource" do - tasks = resource.tasks - expect(tasks).to be_a(PEClient::Resource::OrchestratorV1::Tasks) - end - - it "memorizes the resource" do - tasks1 = resource.tasks - tasks2 = resource.tasks - expect(tasks1).to equal(tasks2) - end - end - - describe "#scopes" do - it "returns a Scopes resource" do - scopes = resource.scopes - expect(scopes).to be_a(PEClient::Resource::OrchestratorV1::Scopes) - end - - it "memorizes the resource" do - scopes1 = resource.scopes - scopes2 = resource.scopes - expect(scopes1).to equal(scopes2) - end - end + include_examples "a memoized resource", :command, "PEClient::Resource::OrchestratorV1::Command" + include_examples "a memoized resource", :inventory, "PEClient::Resource::OrchestratorV1::Inventory" + include_examples "a memoized resource", :jobs, "PEClient::Resource::OrchestratorV1::Jobs" + include_examples "a memoized resource", :scheduled_jobs, "PEClient::Resource::OrchestratorV1::ScheduledJobs" + include_examples "a memoized resource", :plans, "PEClient::Resource::OrchestratorV1::Plans" + include_examples "a memoized resource", :plan_jobs, "PEClient::Resource::OrchestratorV1::PlanJobs" + include_examples "a memoized resource", :tasks, "PEClient::Resource::OrchestratorV1::Tasks" + include_examples "a memoized resource", :scopes, "PEClient::Resource::OrchestratorV1::Scopes" end diff --git a/spec/pe_client/resources/puppet_ca.v1/certificate_status_spec.rb b/spec/pe_client/resources/puppet_ca.v1/certificate_status_spec.rb index c20d247..511d32e 100644 --- a/spec/pe_client/resources/puppet_ca.v1/certificate_status_spec.rb +++ b/spec/pe_client/resources/puppet_ca.v1/certificate_status_spec.rb @@ -11,350 +11,191 @@ let(:certname) { "test-node.example.com" } describe "#get" do - context "when retrieving a signed certificate" do - it "gets the certificate status for the specified node" do - response_body = { - "name" => certname, + it "gets the certificate status for a signed certificate" do + response_body = { + "name" => certname, + "state" => "signed", + "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", + "fingerprints" => { + "SHA1" => "E5:B0:F5:0B:7D:E4:70:78:AC:64:D1:72:C3:26:EB:06:2C:4A:45:F0", + "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", + "SHA512" => "69:AD:BB:92:5C:A0:E1:3A:93:EF:08:93:4D:7F:6E:F7:E8:4B:4F:77:62:46:D7:63:A3:04:F7:29:5E:AA:96:74:BE:EF:09:12:2A:CA:97:29:1E:98:BE:58:07:D8:D2:9A:29:65:0E:9D:E3:ED:F9:E5:53:81:E2:BA:90:6F:12:86" + }, + "dns_alt_names" => [ + "DNS:puppet", + "DNS:test-node.example.com" + ] + } + + stub_request(:get, "#{base_url}/puppet-ca/v1/certificate_status/#{certname}") + .to_return( + status: 200, + body: response_body.to_json, + headers: {"Content-Type" => "application/json"} + ) + + result = resource.get(certname) + expect(result).to be_a(Hash) + expect(result["name"]).to eq(certname) + expect(result["state"]).to eq("signed") + expect(result["fingerprint"]).to be_a(String) + expect(result["fingerprints"]).to be_a(Hash) + expect(result["dns_alt_names"]).to be_an(Array) + end + end + + describe "#list" do + it "gets information about all known certificates without filter" do + response_body = [ + { + "name" => "node1.example.com", "state" => "signed", "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", "fingerprints" => { - "SHA1" => "E5:B0:F5:0B:7D:E4:70:78:AC:64:D1:72:C3:26:EB:06:2C:4A:45:F0", - "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", - "SHA512" => "69:AD:BB:92:5C:A0:E1:3A:93:EF:08:93:4D:7F:6E:F7:E8:4B:4F:77:62:46:D7:63:A3:04:F7:29:5E:AA:96:74:BE:EF:09:12:2A:CA:97:29:1E:98:BE:58:07:D8:D2:9A:29:65:0E:9D:E3:ED:F9:E5:53:81:E2:BA:90:6F:12:86" + "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16" }, - "dns_alt_names" => [ - "DNS:puppet", - "DNS:test-node.example.com" - ] - } - - stub_request(:get, "#{base_url}/puppet-ca/v1/certificate_status/#{certname}") - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.get(certname) - expect(result).to be_a(Hash) - expect(result["name"]).to eq(certname) - expect(result["state"]).to eq("signed") - expect(result["fingerprint"]).to be_a(String) - expect(result["fingerprints"]).to be_a(Hash) - expect(result["dns_alt_names"]).to be_an(Array) - end - end - - context "when retrieving a requested certificate" do - it "gets the certificate status for a pending request" do - response_body = { - "name" => certname, + "dns_alt_names" => ["DNS:node1.example.com"] + }, + { + "name" => "node2.example.com", "state" => "requested", "fingerprint" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2", "fingerprints" => { - "SHA1" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0", - "SHA256" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2", - "SHA512" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2" - }, - "dns_alt_names" => ["DNS:test-node.example.com"] - } - - stub_request(:get, "#{base_url}/puppet-ca/v1/certificate_status/#{certname}") - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.get(certname) - expect(result).to be_a(Hash) - expect(result["name"]).to eq(certname) - expect(result["state"]).to eq("requested") - end - end - end - - describe "#list" do - context "when listing all certificates without filter" do - it "gets information about all known certificates" do - response_body = [ - { - "name" => "node1.example.com", - "state" => "signed", - "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", - "fingerprints" => { - "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16" - }, - "dns_alt_names" => ["DNS:node1.example.com"] - }, - { - "name" => "node2.example.com", - "state" => "requested", - "fingerprint" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2", - "fingerprints" => { - "SHA256" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2" - }, - "dns_alt_names" => ["DNS:node2.example.com"] + "SHA256" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2" }, - { - "name" => "node3.example.com", - "state" => "revoked", - "fingerprint" => "B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2", - "fingerprints" => { - "SHA256" => "B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2" - }, - "dns_alt_names" => ["DNS:node3.example.com"] - } - ] - - stub_request(:get, "#{base_url}/puppet-ca/v1/certificate_statuses/any_key") - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.list - expect(result).to be_an(Array) - expect(result.length).to eq(3) - expect(result[0]["name"]).to eq("node1.example.com") - expect(result[0]["state"]).to eq("signed") - expect(result[1]["state"]).to eq("requested") - expect(result[2]["state"]).to eq("revoked") - end - end - - context "when filtering by requested state" do - it "gets only requested certificates" do - response_body = [ - { - "name" => "node2.example.com", - "state" => "requested", - "fingerprint" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2", - "fingerprints" => { - "SHA256" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2" - }, - "dns_alt_names" => ["DNS:node2.example.com"] - }, - { - "name" => "node4.example.com", - "state" => "requested", - "fingerprint" => "D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2", - "fingerprints" => { - "SHA256" => "D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2" - }, - "dns_alt_names" => ["DNS:node4.example.com"] - } - ] - - stub_request(:get, "#{base_url}/puppet-ca/v1/certificate_statuses/any_key?state=requested") - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.list(state: "requested") - expect(result).to be_an(Array) - expect(result.length).to eq(2) - expect(result.all? { |cert| cert["state"] == "requested" }).to be true - end - end - - context "when filtering by signed state" do - it "gets only signed certificates" do - response_body = [ - { - "name" => "node1.example.com", - "state" => "signed", - "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", - "fingerprints" => { - "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16" - } - } - ] - - stub_request(:get, "#{base_url}/puppet-ca/v1/certificate_statuses/any_key?state=signed") - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.list(state: "signed") - expect(result).to be_an(Array) - expect(result.all? { |cert| cert["state"] == "signed" }).to be true - end - end - - context "when filtering by revoked state" do - it "gets only revoked certificates" do - response_body = [ - { - "name" => "node3.example.com", - "state" => "revoked", - "fingerprint" => "B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2", - "fingerprints" => { - "SHA256" => "B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2" - } - } - ] - - stub_request(:get, "#{base_url}/puppet-ca/v1/certificate_statuses/any_key?state=revoked") - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.list(state: "revoked") - expect(result).to be_an(Array) - expect(result.all? { |cert| cert["state"] == "revoked" }).to be true - end - end - end - - describe "#update" do - context "when signing a certificate request" do - it "updates the certificate status to signed" do - response_body = { - "name" => certname, - "state" => "signed", - "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", + "dns_alt_names" => ["DNS:node2.example.com"] + }, + { + "name" => "node3.example.com", + "state" => "revoked", + "fingerprint" => "B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2", "fingerprints" => { - "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16" + "SHA256" => "B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2" }, - "dns_alt_names" => ["DNS:test-node.example.com"] + "dns_alt_names" => ["DNS:node3.example.com"] } - - stub_request(:put, "#{base_url}/puppet-ca/v1/certificate_status/#{certname}") - .with(body: {desired_state: "signed"}) - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.update(certname, "signed") - expect(result).to be_a(Hash) - expect(result["name"]).to eq(certname) - expect(result["state"]).to eq("signed") - end + ] + + stub_request(:get, "#{base_url}/puppet-ca/v1/certificate_statuses/any_key") + .to_return( + status: 200, + body: response_body.to_json, + headers: {"Content-Type" => "application/json"} + ) + + result = resource.list + expect(result).to be_an(Array) + expect(result.length).to eq(3) + expect(result[0]["name"]).to eq("node1.example.com") + expect(result[0]["state"]).to eq("signed") + expect(result[1]["state"]).to eq("requested") + expect(result[2]["state"]).to eq("revoked") end - context "when signing a certificate request with a custom TTL" do - it "updates the certificate status to signed with specified TTL" do - response_body = { - "name" => certname, - "state" => "signed", - "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", + it "filters certificates by state parameter" do + response_body = [ + { + "name" => "node2.example.com", + "state" => "requested", + "fingerprint" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2", "fingerprints" => { - "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16" + "SHA256" => "A1:B2:C3:D4:E5:F6:A7:B8:C9:D0:E1:F2:A3:B4:C5:D6:E7:F8:A9:B0:C1:D2:E3:F4:A5:B6:C7:D8:E9:F0:A1:B2" }, - "dns_alt_names" => ["DNS:test-node.example.com"] - } - - stub_request(:put, "#{base_url}/puppet-ca/v1/certificate_status/#{certname}") - .with(body: {desired_state: "signed", cert_ttl: "2y"}) - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.update(certname, "signed", cert_ttl: "2y") - expect(result).to be_a(Hash) - expect(result["name"]).to eq(certname) - expect(result["state"]).to eq("signed") - end - end - - context "when signing with numeric TTL in seconds" do - it "updates the certificate status to signed with numeric TTL" do - response_body = { - "name" => certname, - "state" => "signed", - "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16" - } - - stub_request(:put, "#{base_url}/puppet-ca/v1/certificate_status/#{certname}") - .with(body: {desired_state: "signed", cert_ttl: 31536000}) - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.update(certname, "signed", cert_ttl: 31536000) - expect(result).to be_a(Hash) - expect(result["state"]).to eq("signed") - end - end - - context "when revoking a certificate" do - it "updates the certificate status to revoked" do - response_body = { - "name" => certname, - "state" => "revoked", - "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", + "dns_alt_names" => ["DNS:node2.example.com"] + }, + { + "name" => "node4.example.com", + "state" => "requested", + "fingerprint" => "D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2", "fingerprints" => { - "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16" + "SHA256" => "D1:E2:F3:A4:B5:C6:D7:E8:F9:A0:B1:C2:D3:E4:F5:A6:B7:C8:D9:E0:F1:A2:B3:C4:D5:E6:F7:A8:B9:C0:D1:E2" }, - "dns_alt_names" => ["DNS:test-node.example.com"] + "dns_alt_names" => ["DNS:node4.example.com"] } - - stub_request(:put, "#{base_url}/puppet-ca/v1/certificate_status/#{certname}") - .with(body: {desired_state: "revoked"}) - .to_return( - status: 200, - body: response_body.to_json, - headers: {"Content-Type" => "application/json"} - ) - - result = resource.update(certname, "revoked") - expect(result).to be_a(Hash) - expect(result["name"]).to eq(certname) - expect(result["state"]).to eq("revoked") - end + ] + + stub_request(:get, "#{base_url}/puppet-ca/v1/certificate_statuses/any_key?state=requested") + .to_return( + status: 200, + body: response_body.to_json, + headers: {"Content-Type" => "application/json"} + ) + + result = resource.list(state: "requested") + expect(result).to be_an(Array) + expect(result.length).to eq(2) + expect(result.all? { |cert| cert["state"] == "requested" }).to be true end end - describe "#delete" do - context "when deleting SSL information for a host" do - it "deletes all SSL information for the specified hostname" do - hostname = "test-node.example.com" - response_body = "Deleted for #{hostname}: Puppet::SSL::Certificate, Puppet::SSL::Key" - - stub_request(:delete, "#{base_url}/puppet-ca/v1/certificate_status/#{hostname}") - .to_return( - status: 200, - body: response_body, - headers: {"Content-Type" => "text/plain"} - ) - - result = resource.delete(hostname) - expect(result).to be_a(String) - expect(result).to include("Deleted for #{hostname}") - expect(result).to include("Puppet::SSL::Certificate") - end + describe "#update" do + it "updates the certificate status to signed with custom TTL" do + response_body = { + "name" => certname, + "state" => "signed", + "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", + "fingerprints" => { + "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16" + }, + "dns_alt_names" => ["DNS:test-node.example.com"] + } + + stub_request(:put, "#{base_url}/puppet-ca/v1/certificate_status/#{certname}") + .with(body: {desired_state: "signed", cert_ttl: "2y"}) + .to_return( + status: 200, + body: response_body.to_json, + headers: {"Content-Type" => "application/json"} + ) + + result = resource.update(certname, "signed", cert_ttl: "2y") + expect(result).to be_a(Hash) + expect(result["name"]).to eq(certname) + expect(result["state"]).to eq("signed") end - context "when deleting a non-existent host" do - it "handles deletion of a host without SSL information" do - hostname = "nonexistent.example.com" - response_body = "Nothing was deleted" - - stub_request(:delete, "#{base_url}/puppet-ca/v1/certificate_status/#{hostname}") - .to_return( - status: 200, - body: response_body, - headers: {"Content-Type" => "text/plain"} - ) + it "updates the certificate status to revoked" do + response_body = { + "name" => certname, + "state" => "revoked", + "fingerprint" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16", + "fingerprints" => { + "SHA256" => "C2:FD:F0:1A:9F:A7:BD:F2:87:D6:0D:F8:D0:43:B1:E0:63:E2:5F:33:92:A2:B9:93:8A:56:20:38:E6:70:A4:16" + }, + "dns_alt_names" => ["DNS:test-node.example.com"] + } + + stub_request(:put, "#{base_url}/puppet-ca/v1/certificate_status/#{certname}") + .with(body: {desired_state: "revoked"}) + .to_return( + status: 200, + body: response_body.to_json, + headers: {"Content-Type" => "application/json"} + ) + + result = resource.update(certname, "revoked") + expect(result).to be_a(Hash) + expect(result["name"]).to eq(certname) + expect(result["state"]).to eq("revoked") + end + end - result = resource.delete(hostname) - expect(result).to be_a(String) - expect(result).to eq("Nothing was deleted") - end + describe "#delete" do + it "deletes all SSL information for the specified hostname" do + hostname = "test-node.example.com" + response_body = "Deleted for #{hostname}: Puppet::SSL::Certificate, Puppet::SSL::Key" + + stub_request(:delete, "#{base_url}/puppet-ca/v1/certificate_status/#{hostname}") + .to_return( + status: 200, + body: response_body, + headers: {"Content-Type" => "text/plain"} + ) + + result = resource.delete(hostname) + expect(result).to be_a(String) + expect(result).to include("Deleted for #{hostname}") + expect(result).to include("Puppet::SSL::Certificate") end end end diff --git a/spec/pe_client/resources/puppet_ca_v1_spec.rb b/spec/pe_client/resources/puppet_ca_v1_spec.rb index 0fb0d39..ff0345b 100644 --- a/spec/pe_client/resources/puppet_ca_v1_spec.rb +++ b/spec/pe_client/resources/puppet_ca_v1_spec.rb @@ -94,55 +94,10 @@ end end - describe "#certificate_request" do - it "returns a CertificateRequest resource" do - result = resource.certificate_request - expect(result).to be_a(PEClient::Resource::PuppetCAV1::CertificateRequest) - end - - it "caches the CertificateRequest instance" do - result1 = resource.certificate_request - result2 = resource.certificate_request - expect(result1).to equal(result2) - end - end - - describe "#certificate_status" do - it "returns a CertificateStatus resource" do - result = resource.certificate_status - expect(result).to be_a(PEClient::Resource::PuppetCAV1::CertificateStatus) - end - - it "caches the CertificateStatus instance" do - result1 = resource.certificate_status - result2 = resource.certificate_status - expect(result1).to equal(result2) - end - end + subject(:resource) { described_class.new(client) } - describe "#certificate_revocation_list" do - it "returns a CertificateRevocationList resource" do - result = resource.certificate_revocation_list - expect(result).to be_a(PEClient::Resource::PuppetCAV1::CertificateRevocationList) - end - - it "caches the CertificateRevocationList instance" do - result1 = resource.certificate_revocation_list - result2 = resource.certificate_revocation_list - expect(result1).to equal(result2) - end - end - - describe "#bulk_certificate_sign" do - it "returns a BulkCertificateSign resource" do - result = resource.bulk_certificate_sign - expect(result).to be_a(PEClient::Resource::PuppetCAV1::BulkCertificateSign) - end - - it "caches the BulkCertificateSign instance" do - result1 = resource.bulk_certificate_sign - result2 = resource.bulk_certificate_sign - expect(result1).to equal(result2) - end - end + include_examples "a memoized resource", :certificate_request, "PEClient::Resource::PuppetCAV1::CertificateRequest" + include_examples "a memoized resource", :certificate_status, "PEClient::Resource::PuppetCAV1::CertificateStatus" + include_examples "a memoized resource", :certificate_revocation_list, "PEClient::Resource::PuppetCAV1::CertificateRevocationList" + include_examples "a memoized resource", :bulk_certificate_sign, "PEClient::Resource::PuppetCAV1::BulkCertificateSign" end diff --git a/spec/pe_client/resources/puppet_v3/file_bucket_spec.rb b/spec/pe_client/resources/puppet_v3/file_bucket_spec.rb index 6a47e09..4e05e6e 100644 --- a/spec/pe_client/resources/puppet_v3/file_bucket_spec.rb +++ b/spec/pe_client/resources/puppet_v3/file_bucket_spec.rb @@ -170,19 +170,4 @@ expect(result).to eq("correctmd5hash") end end - - describe "BASE_PATH constant" do - it "uses /puppet/v3/file_bucket_file as base path" do - expect(described_class::BASE_PATH).to eq("/puppet/v3/file_bucket_file") - end - end - - describe "HEADERS constant" do - it "includes Content-Type and Accept headers for octet-stream" do - expect(described_class::HEADERS).to eq({ - "Content-Type": "application/octet-stream", - Accept: "application/octet-stream" - }) - end - end end diff --git a/spec/pe_client/resources/puppet_v3/file_metadata_spec.rb b/spec/pe_client/resources/puppet_v3/file_metadata_spec.rb index 6ffe107..fb2dafa 100644 --- a/spec/pe_client/resources/puppet_v3/file_metadata_spec.rb +++ b/spec/pe_client/resources/puppet_v3/file_metadata_spec.rb @@ -290,16 +290,4 @@ expect(result).to be_an(Array) end end - - describe "BASE_PATH constant" do - it "uses /puppet/v3/file_metadata as base path" do - expect(described_class::BASE_PATH).to eq("/puppet/v3/file_metadata") - end - end - - describe "SEARCH_BASE_PATH constant" do - it "uses /puppet/v3/file_metadatas as search base path" do - expect(described_class::SEARCH_BASE_PATH).to eq("/puppet/v3/file_metadatas") - end - end end diff --git a/spec/pe_client/resources/puppet_v3_spec.rb b/spec/pe_client/resources/puppet_v3_spec.rb index 800d4a4..027c400 100644 --- a/spec/pe_client/resources/puppet_v3_spec.rb +++ b/spec/pe_client/resources/puppet_v3_spec.rb @@ -418,52 +418,9 @@ end end - describe "#file_bucket" do - it "returns a FileBucket resource" do - file_bucket = resource.file_bucket - expect(file_bucket).to be_a(PEClient::Resource::PuppetV3::FileBucket) - end - - it "memorizes the resource" do - file_bucket1 = resource.file_bucket - file_bucket2 = resource.file_bucket - expect(file_bucket1).to equal(file_bucket2) - end - end - - describe "#file_metadata" do - it "returns a FileMetadata resource" do - file_metadata = resource.file_metadata - expect(file_metadata).to be_a(PEClient::Resource::PuppetV3::FileMetadata) - end - - it "memorizes the resource" do - file_metadata1 = resource.file_metadata - file_metadata2 = resource.file_metadata - expect(file_metadata1).to equal(file_metadata2) - end - end + subject(:resource) { described_class.new(client) } - describe "PORT constant" do - it "uses port 8140 by default" do - expect(described_class::PORT).to eq(8140) - end - - it "initializes with port 8140" do - resource_client = resource.instance_variable_get(:@client) - expect(resource_client.connection.url_prefix.port).to eq(8140) - end - - it "accepts a custom port parameter" do - custom_resource = described_class.new(client, port: 9140) - resource_client = custom_resource.instance_variable_get(:@client) - expect(resource_client.connection.url_prefix.port).to eq(9140) - end - end - - describe "BASE_PATH constant" do - it "uses /puppet/v3 as base path" do - expect(described_class::BASE_PATH).to eq("/puppet/v3") - end - end + include_examples "a memoized resource", :file_bucket, "PEClient::Resource::PuppetV3::FileBucket" + include_examples "a memoized resource", :file_metadata, "PEClient::Resource::PuppetV3::FileMetadata" + include_examples "a resource with port", 8140 end diff --git a/spec/pe_client/resources/rbac_v1_spec.rb b/spec/pe_client/resources/rbac_v1_spec.rb index 27d36bb..619a884 100644 --- a/spec/pe_client/resources/rbac_v1_spec.rb +++ b/spec/pe_client/resources/rbac_v1_spec.rb @@ -6,122 +6,15 @@ let(:api_key) { "test_api_key" } let(:base_url) { "https://puppet.example.com:8143" } let(:client) { PEClient::Client.new(api_key: api_key, base_url: base_url, ca_file: nil) } - let(:resource) { described_class.new(client) } - - describe "#users" do - it "returns a Users resource" do - users = resource.users - expect(users).to be_a(PEClient::Resource::RBACV1::Users) - end - - it "memorizes the resource" do - users1 = resource.users - users2 = resource.users - expect(users1).to equal(users2) - end - end - - describe "#groups" do - it "returns a Groups resource" do - groups = resource.groups - expect(groups).to be_a(PEClient::Resource::RBACV1::Groups) - end - - it "memorizes the resource" do - groups1 = resource.groups - groups2 = resource.groups - expect(groups1).to equal(groups2) - end - end - - describe "#roles" do - it "returns a Roles resource" do - roles = resource.roles - expect(roles).to be_a(PEClient::Resource::RBACV1::Roles) - end - - it "memorizes the resource" do - roles1 = resource.roles - roles2 = resource.roles - expect(roles1).to equal(roles2) - end - end - - describe "#permissions" do - it "returns a Permissions resource" do - permissions = resource.permissions - expect(permissions).to be_a(PEClient::Resource::RBACV1::Permissions) - end - - it "memorizes the resource" do - permissions1 = resource.permissions - permissions2 = resource.permissions - expect(permissions1).to equal(permissions2) - end - end - - describe "#tokens" do - it "returns a Tokens resource" do - tokens = resource.tokens - expect(tokens).to be_a(PEClient::Resource::RBACV1::Tokens) - end - - it "memorizes the resource" do - tokens1 = resource.tokens - tokens2 = resource.tokens - expect(tokens1).to equal(tokens2) - end - end - - describe "#ldap" do - it "returns an LDAP resource" do - ldap = resource.ldap - expect(ldap).to be_a(PEClient::Resource::RBACV1::LDAP) - end - - it "memorizes the resource" do - ldap1 = resource.ldap - ldap2 = resource.ldap - expect(ldap1).to equal(ldap2) - end - end - - describe "#saml" do - it "returns a SAML resource" do - saml = resource.saml - expect(saml).to be_a(PEClient::Resource::RBACV1::SAML) - end - - it "memorizes the resource" do - saml1 = resource.saml - saml2 = resource.saml - expect(saml1).to equal(saml2) - end - end - - describe "#passwords" do - it "returns a Passwords resource" do - passwords = resource.passwords - expect(passwords).to be_a(PEClient::Resource::RBACV1::Passwords) - end - - it "memorizes the resource" do - passwords1 = resource.passwords - passwords2 = resource.passwords - expect(passwords1).to equal(passwords2) - end - end - - describe "#disclaimer" do - it "returns a Disclaimer resource" do - disclaimer = resource.disclaimer - expect(disclaimer).to be_a(PEClient::Resource::RBACV1::Disclaimer) - end - - it "memorizes the resource" do - disclaimer1 = resource.disclaimer - disclaimer2 = resource.disclaimer - expect(disclaimer1).to equal(disclaimer2) - end - end + subject(:resource) { described_class.new(client) } + + include_examples "a memoized resource", :users, "PEClient::Resource::RBACV1::Users" + include_examples "a memoized resource", :groups, "PEClient::Resource::RBACV1::Groups" + include_examples "a memoized resource", :roles, "PEClient::Resource::RBACV1::Roles" + include_examples "a memoized resource", :permissions, "PEClient::Resource::RBACV1::Permissions" + include_examples "a memoized resource", :tokens, "PEClient::Resource::RBACV1::Tokens" + include_examples "a memoized resource", :ldap, "PEClient::Resource::RBACV1::LDAP" + include_examples "a memoized resource", :saml, "PEClient::Resource::RBACV1::SAML" + include_examples "a memoized resource", :passwords, "PEClient::Resource::RBACV1::Passwords" + include_examples "a memoized resource", :disclaimer, "PEClient::Resource::RBACV1::Disclaimer" end diff --git a/spec/pe_client/resources/rbac_v2_spec.rb b/spec/pe_client/resources/rbac_v2_spec.rb index 83a0e40..ab34c60 100644 --- a/spec/pe_client/resources/rbac_v2_spec.rb +++ b/spec/pe_client/resources/rbac_v2_spec.rb @@ -6,57 +6,10 @@ let(:api_key) { "test_api_key" } let(:base_url) { "https://puppet.example.com:8143" } let(:client) { PEClient::Client.new(api_key: api_key, base_url: base_url, ca_file: nil) } - let(:resource) { described_class.new(client) } + subject(:resource) { described_class.new(client) } - describe "#users" do - it "returns a Users resource" do - users = resource.users - expect(users).to be_a(PEClient::Resource::RBACV2::Users) - end - - it "memorizes the resource" do - users1 = resource.users - users2 = resource.users - expect(users1).to equal(users2) - end - end - - describe "#groups" do - it "returns a Groups resource" do - groups = resource.groups - expect(groups).to be_a(PEClient::Resource::RBACV2::Groups) - end - - it "memorizes the resource" do - groups1 = resource.groups - groups2 = resource.groups - expect(groups1).to equal(groups2) - end - end - - describe "#tokens" do - it "returns a Tokens resource" do - tokens = resource.tokens - expect(tokens).to be_a(PEClient::Resource::RBACV2::Tokens) - end - - it "memorizes the resource" do - tokens1 = resource.tokens - tokens2 = resource.tokens - expect(tokens1).to equal(tokens2) - end - end - - describe "#ldap" do - it "returns an LDAP resource" do - ldap = resource.ldap - expect(ldap).to be_a(PEClient::Resource::RBACV2::LDAP) - end - - it "memorizes the resource" do - ldap1 = resource.ldap - ldap2 = resource.ldap - expect(ldap1).to equal(ldap2) - end - end + include_examples "a memoized resource", :users, "PEClient::Resource::RBACV2::Users" + include_examples "a memoized resource", :groups, "PEClient::Resource::RBACV2::Groups" + include_examples "a memoized resource", :tokens, "PEClient::Resource::RBACV2::Tokens" + include_examples "a memoized resource", :ldap, "PEClient::Resource::RBACV2::LDAP" end diff --git a/spec/pe_client/resources/status_v1_spec.rb b/spec/pe_client/resources/status_v1_spec.rb index 3614053..d83d13f 100644 --- a/spec/pe_client/resources/status_v1_spec.rb +++ b/spec/pe_client/resources/status_v1_spec.rb @@ -2,128 +2,28 @@ require_relative "../../../lib/pe_client/resources/status.v1" -RSpec.describe PEClient::Resource::StatusV1 do - let(:api_key) { "test_api_key" } - let(:base_url) { "https://puppet.example.com:8143" } - let(:client) { PEClient::Client.new(api_key: api_key, base_url: base_url, ca_file: nil) } - let(:resource) { described_class.new(client) } - - describe "#console_services" do - context "when retrieving all services" do - it "gets all console services" do - stub_request(:get, "https://puppet.example.com:4433/status/v1/services") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"activity-service": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.console_services - expect(result).to eq({"activity-service" => {"state" => "running"}}) - end - - it "includes level parameter when provided" do - stub_request(:get, "https://puppet.example.com:4433/status/v1/services?level=critical") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"activity-service": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.console_services(level: "critical") - expect(result).to be_a(Hash) - end - - it "includes timeout parameter when provided" do - stub_request(:get, "https://puppet.example.com:4433/status/v1/services?timeout=60") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"activity-service": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.console_services(timeout: 60) - expect(result).to be_a(Hash) - end +RSpec.shared_examples "a service status endpoint" do |service_type, service_names, port| + let(:service_base_url) { "https://puppet.example.com:#{port}" } - it "includes both level and timeout parameters when provided" do - stub_request(:get, "https://puppet.example.com:4433/status/v1/services?level=debug&timeout=60") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"activity-service": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.console_services(level: "debug", timeout: 60) - expect(result).to be_a(Hash) - end - end - - context "when retrieving a specific service" do - it "gets a specific console service" do - stub_request(:get, "https://puppet.example.com:4433/status/v1/services/activity-service") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"state": "running"}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.console_services(service_name: "activity-service") - expect(result).to eq({"state" => "running"}) - end - - it "includes level parameter for specific service" do - stub_request(:get, "https://puppet.example.com:4433/status/v1/services/rbac-service?level=info") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"state": "running"}', - headers: {"Content-Type" => "application/json"} - ) + context "when retrieving all services" do + it "gets all #{service_type} services with optional parameters" do + stub_request(:get, "#{service_base_url}/status/v1/services?level=debug&timeout=60") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '{"service": {"state": "running"}}', + headers: {"Content-Type" => "application/json"} + ) - result = resource.console_services(service_name: "rbac-service", level: "info") - expect(result).to be_a(Hash) - end + result = resource.public_send("#{service_type}_services", level: "debug", timeout: 60) + expect(result).to be_a(Hash) end end - describe "#puppet_server_services" do - context "when retrieving all services" do - it "gets all puppet server services" do - stub_request(:get, "https://puppet.example.com:8140/status/v1/services") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"server": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.puppet_server_services - expect(result).to eq({"server" => {"state" => "running"}}) - end - - it "includes level parameter when provided" do - stub_request(:get, "https://puppet.example.com:8140/status/v1/services?level=debug") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"server": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.puppet_server_services(level: "debug") - expect(result).to be_a(Hash) - end - end - - context "when retrieving a specific service" do - it "gets a specific puppet server service" do - stub_request(:get, "https://puppet.example.com:8140/status/v1/services/server") + context "when retrieving a specific service" do + service_names.each do |service_name| + it "gets a #{service_type} #{service_name} service" do + stub_request(:get, "#{service_base_url}/status/v1/services/#{service_name}") .with(headers: {"X-Authentication" => api_key}) .to_return( status: 200, @@ -131,228 +31,79 @@ headers: {"Content-Type" => "application/json"} ) - result = resource.puppet_server_services(service_name: "server") + result = resource.public_send("#{service_type}_services", service_name: service_name) expect(result).to eq({"state" => "running"}) end end end +end - describe "#orchestrator_services" do - context "when retrieving all services" do - it "gets all orchestrator services" do - stub_request(:get, "https://puppet.example.com:8143/status/v1/services") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"orchestrator-service": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.orchestrator_services - expect(result).to eq({"orchestrator-service" => {"state" => "running"}}) - end - - it "includes timeout parameter when provided" do - stub_request(:get, "https://puppet.example.com:8143/status/v1/services?timeout=45") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"orchestrator-service": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.orchestrator_services(timeout: 45) - expect(result).to be_a(Hash) - end - end +RSpec.shared_examples "a simple service status endpoint" do |service_type, port| + let(:service_base_url) { "https://puppet.example.com:#{port}" } - context "when retrieving a specific service" do - it "gets a specific orchestrator service" do - stub_request(:get, "https://puppet.example.com:8143/status/v1/services/orchestrator-service") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"state": "running"}', - headers: {"Content-Type" => "application/json"} - ) + it "gets simple status for all #{service_type} services" do + stub_request(:get, "#{service_base_url}/status/v1/simple") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '"running"', + headers: {"Content-Type" => "application/json"} + ) - result = resource.orchestrator_services(service_name: "orchestrator-service") - expect(result).to eq({"state" => "running"}) - end - end + result = resource.public_send("#{service_type}_simple") + expect(result).to eq("running") end - describe "#puppetdb_services" do - context "when retrieving all services" do - it "gets all puppetdb services" do - stub_request(:get, "https://puppet.example.com:8081/status/v1/services") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"puppetdb-service": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.puppetdb_services - expect(result).to eq({"puppetdb-service" => {"state" => "running"}}) - end - - it "includes level and timeout parameters when provided" do - stub_request(:get, "https://puppet.example.com:8081/status/v1/services?level=info&timeout=30") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"puppetdb-service": {"state": "running"}}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.puppetdb_services(level: "info", timeout: 30) - expect(result).to be_a(Hash) - end - end + it "gets simple status for a specific #{service_type} service" do + stub_request(:get, "#{service_base_url}/status/v1/simple/test-service") + .with(headers: {"X-Authentication" => api_key}) + .to_return( + status: 200, + body: '"running"', + headers: {"Content-Type" => "application/json"} + ) + + result = resource.public_send("#{service_type}_simple", service_name: "test-service") + expect(result).to eq("running") + end +end - context "when retrieving a specific service" do - it "gets a specific puppetdb service" do - stub_request(:get, "https://puppet.example.com:8081/status/v1/services/puppetdb-service") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"state": "running"}', - headers: {"Content-Type" => "application/json"} - ) +RSpec.describe PEClient::Resource::StatusV1 do + let(:api_key) { "test_api_key" } + let(:base_url) { "https://puppet.example.com:8143" } + let(:client) { PEClient::Client.new(api_key: api_key, base_url: base_url, ca_file: nil) } + let(:resource) { described_class.new(client) } - result = resource.puppetdb_services(service_name: "puppetdb-service") - expect(result).to eq({"state" => "running"}) - end - end + describe "#console_services" do + include_examples "a service status endpoint", :console, ["activity-service", "classifier-service", "rbac-service"], 4433 end describe "#console_simple" do - context "when retrieving all services" do - it "gets simple status for all console services" do - stub_request(:get, "https://puppet.example.com:4433/status/v1/simple") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '"running"', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.console_simple - expect(result).to eq("running") - end - end - - context "when retrieving a specific service" do - it "gets simple status for a specific console service" do - stub_request(:get, "https://puppet.example.com:4433/status/v1/simple/activity-service") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '"running"', - headers: {"Content-Type" => "application/json"} - ) + include_examples "a simple service status endpoint", :console, 4433 + end - result = resource.console_simple(service_name: "activity-service") - expect(result).to eq("running") - end - end + describe "#puppet_server_services" do + include_examples "a service status endpoint", :puppet_server, ["broker-service", "code-manager-service", "server"], 8140 end describe "#puppet_server_simple" do - context "when retrieving all services" do - it "gets simple status for all puppet server services" do - stub_request(:get, "https://puppet.example.com:8140/status/v1/simple") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '"running"', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.puppet_server_simple - expect(result).to eq("running") - end - end - - context "when retrieving a specific service" do - it "gets simple status for a specific puppet server service" do - stub_request(:get, "https://puppet.example.com:8140/status/v1/simple/server") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '"running"', - headers: {"Content-Type" => "application/json"} - ) + include_examples "a simple service status endpoint", :puppet_server, 8140 + end - result = resource.puppet_server_simple(service_name: "server") - expect(result).to eq("running") - end - end + describe "#orchestrator_services" do + include_examples "a service status endpoint", :orchestrator, ["broker-service", "orchestrator-service"], 8143 end describe "#orchestrator_simple" do - context "when retrieving all services" do - it "gets simple status for all orchestrator services" do - stub_request(:get, "https://puppet.example.com:8143/status/v1/simple") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '"running"', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.orchestrator_simple - expect(result).to eq("running") - end - end - - context "when retrieving a specific service" do - it "gets simple status for a specific orchestrator service" do - stub_request(:get, "https://puppet.example.com:8143/status/v1/simple/orchestrator-service") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '"running"', - headers: {"Content-Type" => "application/json"} - ) + include_examples "a simple service status endpoint", :orchestrator, 8143 + end - result = resource.orchestrator_simple(service_name: "orchestrator-service") - expect(result).to eq("running") - end - end + describe "#puppetdb_services" do + include_examples "a service status endpoint", :puppetdb, ["puppetdb-service"], 8081 end describe "#puppetdb_simple" do - context "when retrieving all services" do - it "gets simple status for all puppetdb services" do - stub_request(:get, "https://puppet.example.com:8081/status/v1/simple") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '"running"', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.puppetdb_simple - expect(result).to eq("running") - end - end - - context "when retrieving a specific service" do - it "gets simple status for a specific puppetdb service" do - stub_request(:get, "https://puppet.example.com:8081/status/v1/simple/puppetdb-service") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '"running"', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.puppetdb_simple(service_name: "puppetdb-service") - expect(result).to eq("running") - end - end + include_examples "a simple service status endpoint", :puppetdb, 8081 end describe "#pe_jruby_metrics" do @@ -369,19 +120,6 @@ expect(result).to be_a(Hash) expect(result).to have_key("state") end - - it "accepts custom level parameter" do - stub_request(:get, "https://puppet.example.com:8140/status/v1/services/pe-jruby-metrics?level=info") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"state": "running"}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.pe_jruby_metrics(level: "info") - expect(result).to be_a(Hash) - end end describe "#pe_master" do @@ -398,19 +136,6 @@ expect(result).to be_a(Hash) expect(result).to have_key("state") end - - it "accepts custom level parameter" do - stub_request(:get, "https://puppet.example.com:8140/status/v1/services/pe-master?level=critical") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"state": "running"}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.pe_master(level: "critical") - expect(result).to be_a(Hash) - end end describe "#pe_puppet_profiler" do @@ -427,18 +152,5 @@ expect(result).to be_a(Hash) expect(result).to have_key("state") end - - it "accepts custom level parameter" do - stub_request(:get, "https://puppet.example.com:8140/status/v1/services/pe-puppet-profiler?level=info") - .with(headers: {"X-Authentication" => api_key}) - .to_return( - status: 200, - body: '{"state": "running"}', - headers: {"Content-Type" => "application/json"} - ) - - result = resource.pe_puppet_profiler(level: "info") - expect(result).to be_a(Hash) - end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ddf615a..b3ac113 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -7,6 +7,9 @@ ENV["RBS_TEST_LOGLEVEL"] ||= "fatal" require "rbs/test/setup" +# Load shared examples +Dir[File.join(__dir__, "support", "shared_examples", "*.rb")].each { |f| require f } + RSpec.configure do |config| # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = ".rspec_status" diff --git a/spec/support/shared_examples/http_error_handling.rb b/spec/support/shared_examples/http_error_handling.rb new file mode 100644 index 0000000..f1bcb7a --- /dev/null +++ b/spec/support/shared_examples/http_error_handling.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +# Shared examples for HTTP client error handling +RSpec.shared_examples "http error handling" do |method, path, options = {}| + [[400, PEClient::BadRequestError], + [401, PEClient::UnauthorizedError], + [403, PEClient::ForbiddenError], + [404, PEClient::NotFoundError], + [409, PEClient::ConflictError], + [500, PEClient::ServerError], + [418, PEClient::HTTPError]].each do |status_code, error_class| + it "raises #{error_class.name} on #{status_code}" do + stub_request(method, "#{base_url}#{path}") + .to_return(status: status_code, body: '{"error": "test"}', headers: {"Content-Type" => "application/json"}) + + expect { + if options[:params] + client.public_send(method, path, **options) + else + client.public_send(method, path) + end + }.to raise_error(error_class) + end + end +end diff --git a/spec/support/shared_examples/resource_behavior.rb b/spec/support/shared_examples/resource_behavior.rb new file mode 100644 index 0000000..c15c16d --- /dev/null +++ b/spec/support/shared_examples/resource_behavior.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Shared examples for resource behavior patterns +RSpec.shared_examples "a memoized resource" do |method_name, expected_class_name| + describe "##{method_name}" do + it "returns the correct type and memoizes the resource" do + resource1 = subject.public_send(method_name) + resource2 = subject.public_send(method_name) + + expected_class = Object.const_get(expected_class_name.to_s) + expect(resource1).to be_a(expected_class) + expect(resource1).to equal(resource2) + end + end +end + +RSpec.shared_examples "a resource with port" do |default_port| + it "initializes with the default port" do + resource_client = subject.instance_variable_get(:@client) + expect(resource_client.connection.url_prefix.port).to eq(default_port) + end + + it "accepts a custom port parameter" do + custom_resource = described_class.new(client, port: default_port + 1000) + resource_client = custom_resource.instance_variable_get(:@client) + expect(resource_client.connection.url_prefix.port).to eq(default_port + 1000) + end +end