From 4da6d9f6c327c63c06431664ca303f571e0dcdcd Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 15 Feb 2018 17:54:04 -0800 Subject: [PATCH] support parsed json and parsed json with symbolized keys --- README.md | 5 ++ lib/kubeclient/common.rb | 39 ++++++++------ test/test_kubeclient.rb | 112 +++++++++++++++++++++------------------ 3 files changed, 88 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index ace68ea5..c03f8295 100644 --- a/README.md +++ b/README.md @@ -304,6 +304,11 @@ pods = client.get_pods as: :raw node = client.get_node "127.0.0.1", as: :raw ``` +Other formats are: + - `:ros` (default) for `RecursiveOpenStruct` + - `:parsed` for `JSON.parse` + - `:parsed_symbolized` for `JSON.parse(..., symbolize_names: true)` + #### Delete an entity (by name) For example: `delete_pod "pod name"` , `delete_replication_controller "rc name"`, `delete_node "node name"`, `delete_secret "secret name"` diff --git a/lib/kubeclient/common.rb b/lib/kubeclient/common.rb index faa5cc5f..d2c42e60 100644 --- a/lib/kubeclient/common.rb +++ b/lib/kubeclient/common.rb @@ -427,22 +427,31 @@ def api private def format_response(as, body, list_type = nil) - return body if as == :raw - - result = JSON.parse(body) - - if list_type - resource_version = - result.fetch('resourceVersion') do - result.fetch('metadata', {}).fetch('resourceVersion', nil) - end - - # result['items'] might be nil due to https://github.com/kubernetes/kubernetes/issues/13096 - collection = result['items'].to_a.map { |item| Kubeclient::Resource.new(item) } - - Kubeclient::Common::EntityList.new(list_type, resource_version, collection) + case as + when :raw + body + when :parsed + JSON.parse(body) + when :parsed_symbolized + JSON.parse(body, symbolize_names: true) + when :ros + result = JSON.parse(body) + + if list_type + resource_version = + result.fetch('resourceVersion') do + result.fetch('metadata', {}).fetch('resourceVersion', nil) + end + + # result['items'] might be nil due to https://github.com/kubernetes/kubernetes/issues/13096 + collection = result['items'].to_a.map { |item| Kubeclient::Resource.new(item) } + + Kubeclient::Common::EntityList.new(list_type, resource_version, collection) + else + Kubeclient::Resource.new(result) + end else - Kubeclient::Resource.new(result) + raise ArgumentError, "Unsupported format #{as.inspect}" end end diff --git a/test/test_kubeclient.rb b/test/test_kubeclient.rb index a107e776..ab2c64e0 100644 --- a/test/test_kubeclient.rb +++ b/test/test_kubeclient.rb @@ -43,8 +43,7 @@ def test_no_version_passed def test_pass_proxy uri = URI::HTTP.build(host: 'localhost', port: 8080) proxy_uri = URI::HTTP.build(host: 'myproxyhost', port: 8888) - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list client = Kubeclient::Client.new(uri, http_proxy_uri: proxy_uri) rest_client = client.rest_client @@ -56,8 +55,7 @@ def test_pass_proxy end def test_exception - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list stub_request(:post, %r{/services}) .to_return(body: open_test_file('namespace_exception.json'), status: 409) @@ -99,7 +97,6 @@ def test_api stub_request(:get, 'http://localhost:8080/api') .to_return(status: 200, body: open_test_file('versions_list.json')) - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') response = client.api assert_includes(response, 'versions') end @@ -178,13 +175,10 @@ def test_api_valid_with_non_json end def test_nonjson_exception - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list stub_request(:get, %r{/servic}) .to_return(body: open_test_file('service_illegal_json_404.json'), status: 404) - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') - exception = assert_raises(Kubeclient::ResourceNotFoundError) do client.get_services end @@ -194,13 +188,10 @@ def test_nonjson_exception end def test_nonjson_exception_raw - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list stub_request(:get, %r{/servic}) .to_return(body: open_test_file('service_illegal_json_404.json'), status: 404) - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') - exception = assert_raises(Kubeclient::ResourceNotFoundError) do client.get_services(as: :raw) end @@ -210,12 +201,9 @@ def test_nonjson_exception_raw end def test_entity_list - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) - stub_request(:get, %r{/services}) - .to_return(body: open_test_file('entity_list.json'), status: 200) + stub_core_api_list + stub_get_services - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') services = client.get_services refute_empty(services) @@ -229,12 +217,9 @@ def test_entity_list end def test_entity_list_raw - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) - stub_request(:get, %r{/services}) - .to_return(body: open_test_file('entity_list.json'), status: 200) + stub_core_api_list + stub_get_services - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') response = client.get_services(as: :raw) refute_empty(response) @@ -243,14 +228,37 @@ def test_entity_list_raw assert_requested(:get, 'http://localhost:8080/api/v1/services', times: 1) end + def test_entity_list_parsed + stub_core_api_list + stub_get_services + + response = client.get_services(as: :parsed) + assert_equal Hash, response.class + assert_equal %w[metadata spec status], response['items'].first.keys + end + + def test_entity_list_parsed_symbolized + stub_core_api_list + stub_get_services + + response = client.get_services(as: :parsed_symbolized) + assert_equal Hash, response.class + assert_equal %i[metadata spec status], response[:items].first.keys + end + + def test_entity_list_unknown + stub_core_api_list + stub_get_services + + e = assert_raises(ArgumentError) { client.get_services(as: :whoops) } + assert_equal 'Unsupported format :whoops', e.message + end + def test_entity_list_raw_failure - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list stub_request(:get, %r{/services}) .to_return(body: open_test_file('entity_list.json'), status: 500) - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') - exception = assert_raises(Kubeclient::HttpError) { client.get_services(as: :raw) } assert_equal('500 Internal Server Error', exception.message) assert_equal(500, exception.error_code) @@ -259,12 +267,9 @@ def test_entity_list_raw_failure def test_entities_with_label_selector selector = 'component=apiserver' - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) - stub_request(:get, %r{/services}) - .to_return(body: open_test_file('entity_list.json'), status: 200) + stub_core_api_list + stub_get_services - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') services = client.get_services(label_selector: selector) assert_instance_of(Kubeclient::Common::EntityList, services) @@ -278,12 +283,9 @@ def test_entities_with_label_selector def test_entities_with_field_selector selector = 'involvedObject.name=redis-master' - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) - stub_request(:get, %r{/services}) - .to_return(body: open_test_file('entity_list.json'), status: 200) + stub_core_api_list + stub_get_services - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') services = client.get_services(field_selector: selector) assert_instance_of(Kubeclient::Common::EntityList, services) @@ -295,20 +297,17 @@ def test_entities_with_field_selector end def test_empty_list - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list stub_request(:get, %r{/pods}) .to_return(body: open_test_file('empty_pod_list.json'), status: 200) - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') pods = client.get_pods assert_instance_of(Kubeclient::Common::EntityList, pods) assert_equal(0, pods.size) end def test_get_all - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list stub_request(:get, %r{/bindings}) .to_return(body: open_test_file('bindings_list.json'), status: 404) @@ -361,7 +360,6 @@ def test_get_all stub_request(:get, %r{/serviceaccounts}) .to_return(body: open_test_file('service_account_list.json'), status: 200) - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') result = client.all_entities assert_equal(16, result.keys.size) assert_instance_of(Kubeclient::Common::EntityList, result['node']) @@ -386,8 +384,7 @@ def test_get_all end def test_get_all_raw - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list stub_request(:get, %r{/bindings}) .to_return(body: open_test_file('bindings_list.json'), status: 404) @@ -440,7 +437,6 @@ def test_get_all_raw stub_request(:get, %r{/serviceaccounts}) .to_return(body: open_test_file('service_account_list.json'), status: 200) - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') result = client.all_entities(as: :raw) assert_equal(16, result.keys.size) @@ -692,8 +688,7 @@ def test_bearer_token_file_not_exist end def test_api_bearer_token_file_success - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list stub_request(:get, 'http://localhost:8080/api/v1/pods') .with(headers: { Authorization: 'Bearer valid_token' }) .to_return(body: open_test_file('pod_list.json'), status: 200) @@ -711,8 +706,7 @@ def test_api_bearer_token_file_success end def test_proxy_url - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list client = Kubeclient::Client.new('http://host:8080', 'v1') assert_equal( @@ -772,12 +766,10 @@ def test_attr_readers def test_nil_items # handle https://github.com/kubernetes/kubernetes/issues/13096 - stub_request(:get, %r{/api/v1$}) - .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + stub_core_api_list stub_request(:get, %r{/persistentvolumeclaims}) .to_return(body: open_test_file('persistent_volume_claims_nil_items.json'), status: 200) - client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1') client.get_persistent_volume_claims end @@ -842,6 +834,20 @@ def assert_default_open_timeout(actual) private + def stub_get_services + stub_request(:get, %r{/services}) + .to_return(body: open_test_file('entity_list.json'), status: 200) + end + + def stub_core_api_list + stub_request(:get, %r{/api/v1$}) + .to_return(body: open_test_file('core_api_resource_list.json'), status: 200) + end + + def client + @client ||= Kubeclient::Client.new('http://localhost:8080/api/', 'v1') + end + # dup method creates a shallow copy which is not good in this case # since rename_keys changes the input hash # hence need to create a deep_copy