k8y 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +2 -2
 - data/DECISIONLOG.md +14 -0
 - data/Rakefile +20 -3
 - data/k8y.gemspec +2 -2
 - data/lib/k8y/client/api_builder.rb +1 -1
 - data/lib/k8y/client.rb +1 -0
 - data/lib/k8y/error.rb +1 -0
 - data/lib/k8y/group_version.rb +1 -0
 - data/lib/k8y/kubeconfig/auth_info.rb +16 -2
 - data/lib/k8y/kubeconfig/auth_provider.rb +13 -0
 - data/lib/k8y/kubeconfig/user.rb +1 -0
 - data/lib/k8y/resource.rb +12 -0
 - data/lib/k8y/rest/auth/auth_base.rb +1 -2
 - data/lib/k8y/rest/auth/factory.rb +4 -3
 - data/lib/k8y/rest/auth/providers/factory.rb +1 -1
 - data/lib/k8y/rest/auth/providers/gcp/application_default_provider.rb +3 -5
 - data/lib/k8y/rest/auth/providers/gcp/command_provider.rb +3 -3
 - data/lib/k8y/rest/auth/providers/gcp/factory.rb +8 -12
 - data/lib/k8y/rest/auth/providers/provider_base.rb +12 -3
 - data/lib/k8y/rest/auth/token_store.rb +29 -0
 - data/lib/k8y/rest/client.rb +49 -18
 - data/lib/k8y/rest/config.rb +8 -7
 - data/lib/k8y/rest/config_validator.rb +1 -0
 - data/lib/k8y/rest/connection.rb +22 -5
 - data/lib/k8y/rest/error.rb +8 -0
 - data/lib/k8y/rest/request_wrapper.rb +22 -0
 - data/lib/k8y/rest/response_formatter.rb +6 -5
 - data/lib/k8y/rest/transport.rb +1 -0
 - data/lib/k8y/rest.rb +1 -0
 - data/lib/k8y/version.rb +1 -1
 - data/lib/k8y.rb +1 -0
 - metadata +22 -17
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: a5320e2541c6887f3f654b04d76121467d4b80328164cb6489a2c47496291d65
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 6ad43159e2bc56e4dfd96bf06fc279781789e48c342bffb11122ffa6d4ae97f2
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 6092e6243c294e24404993c891749d653623cc161b609003f12f5ae0d6c2665c2775902394ead30519d4761bce3c8dd11713132251dbecadcde4697698c5eb4b
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 7820369a97588da212de66325c3879a59d5ad49e3baca6a1405eebcd0f397cadb33c3cb100cd85e9a10339038e71c4a9da2700e85535f7cd84ce482c21cc4b91
         
     | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/DECISIONLOG.md
    ADDED
    
    | 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Purpose of this document
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            This document serves as a historical record of certain design decisions as they're made, in the hope that, down the line, it will be clear why certain implementations were chosen over others, and to inform future development. Any new feature or architectural change that relies on careful judgement of tradeoffs and/or assumptions should be documented.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            # Authorization
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            For `auth-provider` based authorization, K8y exposes the `ProviderBase` class which all concrete provider implementations should implement. Subclasses should implement a single method: `#token`. The `#token` method is used in 3 instances:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            - To generate a token if one doesn't exist
         
     | 
| 
      
 10 
     | 
    
         
            +
            - To store generated tokens in the token store
         
     | 
| 
      
 11 
     | 
    
         
            +
            - To regenerate expired tokens
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            This approach makes it easy to design new `auth-providers`: they just need to implement a single method and token configuration, regeneration, and reuse, occurs transparently. The tradeoff is slightly less fine-grained control over global (e.g process-wide) client settings. Another complicating factor is that the authorization config (for the `REST`) client is not context-aware. Instead, `TokenStore` keys tokens to the `REST::Client`s host (e.g. `https://1.2.3.4`). This makes it effectively impossible for the same process to use different tokens between clients targeting the same API server host. For now, this seems like a decent tradeoff: I'm having trouble imagining when/where such a case might be useful.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
    
        data/Rakefile
    CHANGED
    
    | 
         @@ -5,19 +5,36 @@ require "rake/testtask" 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            task default: ["test"]
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
            desc("Run test suite")
         
     | 
| 
      
 8 
     | 
    
         
            +
            desc("Run unit/integration test suite")
         
     | 
| 
       9 
9 
     | 
    
         
             
            Rake::TestTask.new(:test) do |task|
         
     | 
| 
      
 10 
     | 
    
         
            +
              task.libs << "test"
         
     | 
| 
      
 11 
     | 
    
         
            +
              task.libs << "lib"
         
     | 
| 
      
 12 
     | 
    
         
            +
              task.test_files = FileList[
         
     | 
| 
      
 13 
     | 
    
         
            +
                "test/unit/**/*_test.rb",
         
     | 
| 
      
 14 
     | 
    
         
            +
                "test/integration/**/*_test.rb",
         
     | 
| 
      
 15 
     | 
    
         
            +
              ]
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            desc("Run unit test suite")
         
     | 
| 
      
 19 
     | 
    
         
            +
            Rake::TestTask.new(:test_unit) do |task|
         
     | 
| 
       10 
20 
     | 
    
         
             
              task.libs << "test"
         
     | 
| 
       11 
21 
     | 
    
         
             
              task.libs << "lib"
         
     | 
| 
       12 
22 
     | 
    
         
             
              task.test_files = FileList["test/unit/**/*_test.rb"]
         
     | 
| 
       13 
23 
     | 
    
         
             
            end
         
     | 
| 
       14 
24 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
            desc("Run  
     | 
| 
      
 25 
     | 
    
         
            +
            desc("Run integration test suite")
         
     | 
| 
       16 
26 
     | 
    
         
             
            Rake::TestTask.new(:test_integration) do |task|
         
     | 
| 
      
 27 
     | 
    
         
            +
              task.libs << "test"
         
     | 
| 
      
 28 
     | 
    
         
            +
              task.libs << "lib"
         
     | 
| 
      
 29 
     | 
    
         
            +
              task.test_files = FileList["test/integration/**/*_test.rb"]
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            desc("Run in-cluster integrations tests")
         
     | 
| 
      
 33 
     | 
    
         
            +
            Rake::TestTask.new(:test_cluster) do |task|
         
     | 
| 
       17 
34 
     | 
    
         
             
              ENV["PARALLELIZE_ME"] = ENV.fetch("PARALLELIZE_ME", "1")
         
     | 
| 
       18 
35 
     | 
    
         
             
              ENV["MT_CPU"] = ENV.fetch("MT_CPU", "8")
         
     | 
| 
       19 
36 
     | 
    
         
             
              task.libs << "test"
         
     | 
| 
       20 
37 
     | 
    
         
             
              task.libs << "lib"
         
     | 
| 
       21 
     | 
    
         
            -
              task.test_files = FileList["test/ 
     | 
| 
      
 38 
     | 
    
         
            +
              task.test_files = FileList["test/cluster_integration/**/*_test.rb"]
         
     | 
| 
       22 
39 
     | 
    
         
             
              task.warning = false
         
     | 
| 
       23 
40 
     | 
    
         
             
            end
         
     | 
    
        data/k8y.gemspec
    CHANGED
    
    | 
         @@ -27,10 +27,10 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       27 
27 
     | 
    
         
             
              spec.require_paths = ["lib"]
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
              spec.add_dependency("activesupport", "~> 6.0")
         
     | 
| 
       30 
     | 
    
         
            -
              spec.add_dependency("faraday", "~> 1. 
     | 
| 
      
 30 
     | 
    
         
            +
              spec.add_dependency("faraday", "~> 1.8")
         
     | 
| 
      
 31 
     | 
    
         
            +
              spec.add_dependency("googleauth")
         
     | 
| 
       31 
32 
     | 
    
         
             
              spec.add_dependency("railties", "~> 6.0")
         
     | 
| 
       32 
33 
     | 
    
         
             
              spec.add_dependency("recursive-open-struct", "~>1.1")
         
     | 
| 
       33 
     | 
    
         
            -
              spec.add_dependency("googleauth")
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
              spec.add_development_dependency("byebug", "~> 11")
         
     | 
| 
       36 
36 
     | 
    
         
             
              spec.add_development_dependency("minitest", "~> 5")
         
     | 
| 
         @@ -27,7 +27,7 @@ module K8y 
     | 
|
| 
       27 
27 
     | 
    
         
             
                  end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
                  def build!
         
     | 
| 
       30 
     | 
    
         
            -
                    rest_config = REST::Config.from_kubeconfig(config, path: api.path)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    rest_config = REST::Config.from_kubeconfig(config, context: context, path: api.path)
         
     | 
| 
       31 
31 
     | 
    
         
             
                    rest_client = REST::Client.new(connection: REST::Connection.from_config(rest_config))
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
                    response = rest_client.get(as: :raw)
         
     | 
    
        data/lib/k8y/client.rb
    CHANGED
    
    
    
        data/lib/k8y/error.rb
    CHANGED
    
    
    
        data/lib/k8y/group_version.rb
    CHANGED
    
    
| 
         @@ -1,10 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative "auth_provider"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
       2 
5 
     | 
    
         
             
            module K8y
         
     | 
| 
       3 
6 
     | 
    
         
             
              module Kubeconfig
         
     | 
| 
       4 
7 
     | 
    
         
             
                class AuthInfo
         
     | 
| 
       5 
8 
     | 
    
         
             
                  attr_reader :client_certificate, :client_certificate_data, :client_key, :client_key_data, :token, :token_file,
         
     | 
| 
       6 
9 
     | 
    
         
             
                    :as, :as_groups, :as_user_extra, :username, :password, :auth_provider, :exec_options, :extensions,
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
10 
     | 
    
         
             
                    def self.from_hash(hash)
         
     | 
| 
       9 
11 
     | 
    
         
             
                      new(
         
     | 
| 
       10 
12 
     | 
    
         
             
                        client_certificate: hash.fetch("client-certificate", nil),
         
     | 
| 
         @@ -18,7 +20,7 @@ module K8y 
     | 
|
| 
       18 
20 
     | 
    
         
             
                        as_user_extra: hash.fetch("as-user-extra", nil),
         
     | 
| 
       19 
21 
     | 
    
         
             
                        username: hash.fetch("username", nil),
         
     | 
| 
       20 
22 
     | 
    
         
             
                        password: hash.fetch("password", nil),
         
     | 
| 
       21 
     | 
    
         
            -
                        auth_provider: hash.fetch("auth-provider", nil),
         
     | 
| 
      
 23 
     | 
    
         
            +
                        auth_provider: AuthProvider.new(hash.fetch("auth-provider", nil)),
         
     | 
| 
       22 
24 
     | 
    
         
             
                        exec_options: hash.fetch("exec", nil),
         
     | 
| 
       23 
25 
     | 
    
         
             
                        extensions: hash.fetch("extensions", nil)
         
     | 
| 
       24 
26 
     | 
    
         
             
                      )
         
     | 
| 
         @@ -42,6 +44,18 @@ module K8y 
     | 
|
| 
       42 
44 
     | 
    
         
             
                    @exec_options = exec_options
         
     | 
| 
       43 
45 
     | 
    
         
             
                    @extensions = extensions
         
     | 
| 
       44 
46 
     | 
    
         
             
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def strategy
         
     | 
| 
      
 49 
     | 
    
         
            +
                    if username && password
         
     | 
| 
      
 50 
     | 
    
         
            +
                      :basic
         
     | 
| 
      
 51 
     | 
    
         
            +
                    elsif token
         
     | 
| 
      
 52 
     | 
    
         
            +
                      :token
         
     | 
| 
      
 53 
     | 
    
         
            +
                    elsif auth_provider.present?
         
     | 
| 
      
 54 
     | 
    
         
            +
                      :auth_provider
         
     | 
| 
      
 55 
     | 
    
         
            +
                    else
         
     | 
| 
      
 56 
     | 
    
         
            +
                      :default
         
     | 
| 
      
 57 
     | 
    
         
            +
                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
       45 
59 
     | 
    
         
             
                end
         
     | 
| 
       46 
60 
     | 
    
         
             
              end
         
     | 
| 
       47 
61 
     | 
    
         
             
            end
         
     | 
    
        data/lib/k8y/kubeconfig/user.rb
    CHANGED
    
    
    
        data/lib/k8y/resource.rb
    ADDED
    
    
| 
         @@ -9,11 +9,12 @@ module K8y 
     | 
|
| 
       9 
9 
     | 
    
         
             
                module Auth
         
     | 
| 
       10 
10 
     | 
    
         
             
                  class Factory
         
     | 
| 
       11 
11 
     | 
    
         
             
                    def from_auth_info(auth_info)
         
     | 
| 
       12 
     | 
    
         
            -
                       
     | 
| 
      
 12 
     | 
    
         
            +
                      case auth_info.strategy
         
     | 
| 
      
 13 
     | 
    
         
            +
                      when :basic
         
     | 
| 
       13 
14 
     | 
    
         
             
                        Basic.new(username: auth_info.username, password: auth_info.password)
         
     | 
| 
       14 
     | 
    
         
            -
                       
     | 
| 
      
 15 
     | 
    
         
            +
                      when :token
         
     | 
| 
       15 
16 
     | 
    
         
             
                        Token.new(token: auth_info.token)
         
     | 
| 
       16 
     | 
    
         
            -
                       
     | 
| 
      
 17 
     | 
    
         
            +
                      when :auth_provider
         
     | 
| 
       17 
18 
     | 
    
         
             
                        Providers::Factory.new.from_auth_provider(auth_info.auth_provider)
         
     | 
| 
       18 
19 
     | 
    
         
             
                      else
         
     | 
| 
       19 
20 
     | 
    
         
             
                        AuthBase.new
         
     | 
| 
         @@ -15,14 +15,12 @@ module K8y 
     | 
|
| 
       15 
15 
     | 
    
         
             
                          "https://www.googleapis.com/auth/userinfo.email",
         
     | 
| 
       16 
16 
     | 
    
         
             
                        ]
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                        # able to hold on to transparently keep client connections alive and
         
     | 
| 
       21 
     | 
    
         
            -
                        # healthy.
         
     | 
| 
      
 18 
     | 
    
         
            +
                        private
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       22 
20 
     | 
    
         
             
                        def token
         
     | 
| 
       23 
21 
     | 
    
         
             
                          creds = Google::Auth.get_application_default(SCOPES)
         
     | 
| 
       24 
22 
     | 
    
         
             
                          creds.apply({})
         
     | 
| 
       25 
     | 
    
         
            -
                          creds.access_token
         
     | 
| 
      
 23 
     | 
    
         
            +
                          @token = creds.access_token
         
     | 
| 
       26 
24 
     | 
    
         
             
                        end
         
     | 
| 
       27 
25 
     | 
    
         
             
                      end
         
     | 
| 
       28 
26 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -25,6 +25,8 @@ module K8y 
     | 
|
| 
       25 
25 
     | 
    
         
             
                          @token_key = token_key
         
     | 
| 
       26 
26 
     | 
    
         
             
                        end
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
      
 28 
     | 
    
         
            +
                        private
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
       28 
30 
     | 
    
         
             
                        def token
         
     | 
| 
       29 
31 
     | 
    
         
             
                          out, err, st = Open3.capture3(cmd, *args.split)
         
     | 
| 
       30 
32 
     | 
    
         | 
| 
         @@ -33,12 +35,10 @@ module K8y 
     | 
|
| 
       33 
35 
     | 
    
         
             
                          extract_token(out, token_key)
         
     | 
| 
       34 
36 
     | 
    
         
             
                        end
         
     | 
| 
       35 
37 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                        private
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
38 
     | 
    
         
             
                        def extract_token(output, key)
         
     | 
| 
       39 
39 
     | 
    
         
             
                          path =
         
     | 
| 
       40 
40 
     | 
    
         
             
                            key
         
     | 
| 
       41 
     | 
    
         
            -
                              .gsub(/\A{(.*)}\z/,  
     | 
| 
      
 41 
     | 
    
         
            +
                              .gsub(/\A{(.*)}\z/, "\\1") # {.foo.bar} -> .foo.bar
         
     | 
| 
       42 
42 
     | 
    
         
             
                              .sub(/\A\./, "") # .foo.bar -> foo.bar
         
     | 
| 
       43 
43 
     | 
    
         
             
                              .split(".")
         
     | 
| 
       44 
44 
     | 
    
         
             
                          JSON.parse(output).dig(*path)
         
     | 
| 
         @@ -11,21 +11,17 @@ module K8y 
     | 
|
| 
       11 
11 
     | 
    
         
             
                      Error = Class.new(Error)
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                      class Factory
         
     | 
| 
       14 
     | 
    
         
            -
                        MissingConfigError = Class.new(Error)
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
14 
     | 
    
         
             
                        def from_auth_provider(provider)
         
     | 
| 
       17 
     | 
    
         
            -
                          config = provider 
     | 
| 
       18 
     | 
    
         
            -
                          raise MissingConfigError unless config
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
                          config = provider.config
         
     | 
| 
       20 
16 
     | 
    
         
             
                          # see https://github.com/kubernetes/client-go/blob/master/plugin/pkg/client/auth/gcp/gcp.go#L58
         
     | 
| 
       21 
     | 
    
         
            -
                          if config 
     | 
| 
      
 17 
     | 
    
         
            +
                          if config&.public_send(:"cmd-path")
         
     | 
| 
       22 
18 
     | 
    
         
             
                            CommandProvider.new(
         
     | 
| 
       23 
     | 
    
         
            -
                              access_token: config 
     | 
| 
       24 
     | 
    
         
            -
                              cmd_args: config 
     | 
| 
       25 
     | 
    
         
            -
                              cmd_path: config 
     | 
| 
       26 
     | 
    
         
            -
                              expiry: config 
     | 
| 
       27 
     | 
    
         
            -
                              expiry_key: config 
     | 
| 
       28 
     | 
    
         
            -
                              token_key: config 
     | 
| 
      
 19 
     | 
    
         
            +
                              access_token: config.public_send(:"access-token"),
         
     | 
| 
      
 20 
     | 
    
         
            +
                              cmd_args: config.public_send(:"cmd-args"),
         
     | 
| 
      
 21 
     | 
    
         
            +
                              cmd_path: config.public_send(:"cmd-path"),
         
     | 
| 
      
 22 
     | 
    
         
            +
                              expiry: config.expiry,
         
     | 
| 
      
 23 
     | 
    
         
            +
                              expiry_key: config.public_send(:"expiry-key"),
         
     | 
| 
      
 24 
     | 
    
         
            +
                              token_key: config.public_send(:"token-key"),
         
     | 
| 
       29 
25 
     | 
    
         
             
                            )
         
     | 
| 
       30 
26 
     | 
    
         
             
                          else
         
     | 
| 
       31 
27 
     | 
    
         
             
                            ApplicationDefaultProvider.new
         
     | 
| 
         @@ -4,10 +4,19 @@ module K8y 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module REST
         
     | 
| 
       5 
5 
     | 
    
         
             
                module Auth
         
     | 
| 
       6 
6 
     | 
    
         
             
                  module Providers
         
     | 
| 
       7 
     | 
    
         
            -
                    class ProviderBase
         
     | 
| 
       8 
     | 
    
         
            -
                       
     | 
| 
      
 7 
     | 
    
         
            +
                    class ProviderBase < AuthBase
         
     | 
| 
      
 8 
     | 
    
         
            +
                      def configure_connection(connection)
         
     | 
| 
      
 9 
     | 
    
         
            +
                        connection.request(:authorization, "Bearer", -> { TokenStore[connection.host] ||= token })
         
     | 
| 
      
 10 
     | 
    
         
            +
                      end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                      def generate_token!(connection)
         
     | 
| 
      
 13 
     | 
    
         
            +
                        TokenStore[connection.host] = token
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                      private
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
       9 
18 
     | 
    
         
             
                      def token
         
     | 
| 
       10 
     | 
    
         
            -
                        raise NotImplementedError
         
     | 
| 
      
 19 
     | 
    
         
            +
                        raise NotImplementedError, "subclasses of ProviderBase must implement #token"
         
     | 
| 
       11 
20 
     | 
    
         
             
                      end
         
     | 
| 
       12 
21 
     | 
    
         
             
                    end
         
     | 
| 
       13 
22 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module K8y
         
     | 
| 
      
 4 
     | 
    
         
            +
              module REST
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Auth
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class TokenStore
         
     | 
| 
      
 7 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                      def [](hostname)
         
     | 
| 
      
 9 
     | 
    
         
            +
                        lock.synchronize { store[hostname] }
         
     | 
| 
      
 10 
     | 
    
         
            +
                      end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                      def []=(hostname, token)
         
     | 
| 
      
 13 
     | 
    
         
            +
                        lock.synchronize { store[hostname] = token }
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                      private
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                      def store
         
     | 
| 
      
 19 
     | 
    
         
            +
                        @store ||= {}
         
     | 
| 
      
 20 
     | 
    
         
            +
                      end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                      def lock
         
     | 
| 
      
 23 
     | 
    
         
            +
                        @lock ||= Mutex.new
         
     | 
| 
      
 24 
     | 
    
         
            +
                      end
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/k8y/rest/client.rb
    CHANGED
    
    | 
         @@ -1,23 +1,27 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require "faraday"
         
     | 
| 
       4 
3 
     | 
    
         
             
            require "base64"
         
     | 
| 
       5 
     | 
    
         
            -
            require " 
     | 
| 
      
 4 
     | 
    
         
            +
            require "faraday"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "forwardable"
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            require_relative "config"
         
     | 
| 
       8 
8 
     | 
    
         
             
            require_relative "connection"
         
     | 
| 
      
 9 
     | 
    
         
            +
            require_relative "request_wrapper"
         
     | 
| 
       9 
10 
     | 
    
         
             
            require_relative "response_formatter"
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
            module K8y
         
     | 
| 
       12 
13 
     | 
    
         
             
              module REST
         
     | 
| 
       13 
14 
     | 
    
         
             
                class Client
         
     | 
| 
      
 15 
     | 
    
         
            +
                  extend Forwardable
         
     | 
| 
       14 
16 
     | 
    
         
             
                  attr_reader :connection
         
     | 
| 
       15 
17 
     | 
    
         | 
| 
      
 18 
     | 
    
         
            +
                  def_delegators(:connection, :base_path)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       16 
20 
     | 
    
         
             
                  class << self
         
     | 
| 
       17 
21 
     | 
    
         
             
                    def from_config(config)
         
     | 
| 
       18 
22 
     | 
    
         
             
                      new(
         
     | 
| 
       19 
23 
     | 
    
         
             
                        connection: Connection.new(
         
     | 
| 
       20 
     | 
    
         
            -
                           
     | 
| 
      
 24 
     | 
    
         
            +
                          base_path: config.base_path,
         
     | 
| 
       21 
25 
     | 
    
         
             
                          ssl: config.transport.to_faraday_options,
         
     | 
| 
       22 
26 
     | 
    
         
             
                          auth: config.auth
         
     | 
| 
       23 
27 
     | 
    
         
             
                        )
         
     | 
| 
         @@ -25,48 +29,75 @@ module K8y 
     | 
|
| 
       25 
29 
     | 
    
         
             
                    end
         
     | 
| 
       26 
30 
     | 
    
         
             
                  end
         
     | 
| 
       27 
31 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                  def host
         
     | 
| 
       29 
     | 
    
         
            -
                    connection.host
         
     | 
| 
       30 
     | 
    
         
            -
                  end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
32 
     | 
    
         
             
                  def initialize(connection:)
         
     | 
| 
       33 
33 
     | 
    
         
             
                    @connection = connection
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @request_wrapper = RequestWrapper.new
         
     | 
| 
       34 
35 
     | 
    
         
             
                  end
         
     | 
| 
       35 
36 
     | 
    
         | 
| 
       36 
37 
     | 
    
         
             
                  def get(path = "", headers: {}, as: :ros)
         
     | 
| 
       37 
     | 
    
         
            -
                     
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
                    with_wrapper do
         
     | 
| 
      
 39 
     | 
    
         
            +
                      response = connection.get(formatted_uri(path))
         
     | 
| 
      
 40 
     | 
    
         
            +
                      format_response(response, as: as)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
       39 
42 
     | 
    
         
             
                  end
         
     | 
| 
       40 
43 
     | 
    
         | 
| 
       41 
44 
     | 
    
         
             
                  def post(path = "", data:, headers: {}, as: :ros)
         
     | 
| 
       42 
     | 
    
         
            -
                     
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
      
 45 
     | 
    
         
            +
                    with_wrapper do
         
     | 
| 
      
 46 
     | 
    
         
            +
                      response = connection.post(formatted_uri(path), data, headers)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      format_response(response, as: as)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
       44 
49 
     | 
    
         
             
                  end
         
     | 
| 
       45 
50 
     | 
    
         | 
| 
       46 
51 
     | 
    
         
             
                  def put(path = "", data:, headers: {}, as: :ros)
         
     | 
| 
       47 
     | 
    
         
            -
                     
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
      
 52 
     | 
    
         
            +
                    with_wrapper do
         
     | 
| 
      
 53 
     | 
    
         
            +
                      response = connection.put(formatted_uri(path), data, headers)
         
     | 
| 
      
 54 
     | 
    
         
            +
                      format_response(response, as: as)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    end
         
     | 
| 
       49 
56 
     | 
    
         
             
                  end
         
     | 
| 
       50 
57 
     | 
    
         | 
| 
       51 
58 
     | 
    
         
             
                  def patch(path = "", strategy:, data:, headers: {}, as: :ros)
         
     | 
| 
       52 
     | 
    
         
            -
                     
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
      
 59 
     | 
    
         
            +
                    with_wrapper do
         
     | 
| 
      
 60 
     | 
    
         
            +
                      response = connection.patch(formatted_uri(path), data, headers)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      format_response(response, as: as)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
       54 
63 
     | 
    
         
             
                  end
         
     | 
| 
       55 
64 
     | 
    
         | 
| 
       56 
65 
     | 
    
         
             
                  def delete(path = "", headers: {}, as: :ros)
         
     | 
| 
       57 
     | 
    
         
            -
                     
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
      
 66 
     | 
    
         
            +
                    with_wrapper do
         
     | 
| 
      
 67 
     | 
    
         
            +
                      response = connection.delete(formatted_uri(path))
         
     | 
| 
      
 68 
     | 
    
         
            +
                      format_response(response, as: as)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
       59 
70 
     | 
    
         
             
                  end
         
     | 
| 
       60 
71 
     | 
    
         | 
| 
       61 
72 
     | 
    
         
             
                  private
         
     | 
| 
       62 
73 
     | 
    
         | 
| 
      
 74 
     | 
    
         
            +
                  attr_reader :request_wrapper
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
       63 
76 
     | 
    
         
             
                  def formatted_uri(path = "")
         
     | 
| 
       64 
     | 
    
         
            -
                    File.join(connection. 
     | 
| 
      
 77 
     | 
    
         
            +
                    File.join(connection.base_path, path)
         
     | 
| 
       65 
78 
     | 
    
         
             
                  end
         
     | 
| 
       66 
79 
     | 
    
         | 
| 
       67 
80 
     | 
    
         
             
                  def format_response(response, as: :ros)
         
     | 
| 
       68 
81 
     | 
    
         
             
                    ResponseFormatter.new(response).format(as: as)
         
     | 
| 
       69 
82 
     | 
    
         
             
                  end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  # I apologize for the ugly code, but it's relatively straightforward.
         
     | 
| 
      
 85 
     | 
    
         
            +
                  # If the request returns an Unauthorized response, try generating a new token and retry the request.
         
     | 
| 
      
 86 
     | 
    
         
            +
                  # If that fails, raise the error to the caller as normal.
         
     | 
| 
      
 87 
     | 
    
         
            +
                  def with_wrapper(&block)
         
     | 
| 
      
 88 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 89 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 90 
     | 
    
         
            +
                        yield
         
     | 
| 
      
 91 
     | 
    
         
            +
                      rescue Faraday::Error => e
         
     | 
| 
      
 92 
     | 
    
         
            +
                        request_wrapper.handle(e, retry_unauthorized: true)
         
     | 
| 
      
 93 
     | 
    
         
            +
                      end
         
     | 
| 
      
 94 
     | 
    
         
            +
                    rescue RetriableUnauthorizedError
         
     | 
| 
      
 95 
     | 
    
         
            +
                      connection.generate_token!
         
     | 
| 
      
 96 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
                  rescue Faraday::Error => e
         
     | 
| 
      
 99 
     | 
    
         
            +
                    request_wrapper.handle(e)
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
       70 
101 
     | 
    
         
             
                end
         
     | 
| 
       71 
102 
     | 
    
         
             
              end
         
     | 
| 
       72 
103 
     | 
    
         
             
            end
         
     | 
    
        data/lib/k8y/rest/config.rb
    CHANGED
    
    | 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       2 
3 
     | 
    
         
             
            require_relative "config_validator"
         
     | 
| 
       3 
4 
     | 
    
         
             
            require_relative "transport"
         
     | 
| 
       4 
5 
     | 
    
         
             
            require_relative "auth"
         
     | 
| 
         @@ -6,29 +7,29 @@ require_relative "auth" 
     | 
|
| 
       6 
7 
     | 
    
         
             
            module K8y
         
     | 
| 
       7 
8 
     | 
    
         
             
              module REST
         
     | 
| 
       8 
9 
     | 
    
         
             
                class Config
         
     | 
| 
       9 
     | 
    
         
            -
                  attr_reader : 
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :base_path, :transport, :auth
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
                  class << self
         
     | 
| 
       12 
     | 
    
         
            -
                    def from_kubeconfig(kubeconfig, path:)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    def from_kubeconfig(kubeconfig, context: nil, path: "/")
         
     | 
| 
       13 
14 
     | 
    
         
             
                      context = context ? context : kubeconfig.current_context
         
     | 
| 
       14 
15 
     | 
    
         
             
                      ConfigValidator.new(kubeconfig, context: context).validate!
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
       16 
17 
     | 
    
         
             
                      cluster = kubeconfig.cluster_for_context(context)
         
     | 
| 
       17 
     | 
    
         
            -
                       
     | 
| 
       18 
     | 
    
         
            -
                      transport = if URI( 
     | 
| 
      
 18 
     | 
    
         
            +
                      base_path = File.join(cluster.server, path)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      transport = if URI(base_path).scheme == "https"
         
     | 
| 
       19 
20 
     | 
    
         
             
                        Transport.from_kubeconfig(kubeconfig, context: context)
         
     | 
| 
       20 
21 
     | 
    
         
             
                      end
         
     | 
| 
       21 
22 
     | 
    
         
             
                      auth = Auth.from_kubeconfig(kubeconfig, context: context)
         
     | 
| 
       22 
23 
     | 
    
         
             
                      new(
         
     | 
| 
       23 
     | 
    
         
            -
                         
     | 
| 
      
 24 
     | 
    
         
            +
                        base_path: base_path,
         
     | 
| 
       24 
25 
     | 
    
         
             
                        transport: transport,
         
     | 
| 
       25 
26 
     | 
    
         
             
                        auth: auth
         
     | 
| 
       26 
27 
     | 
    
         
             
                      )
         
     | 
| 
       27 
28 
     | 
    
         
             
                    end
         
     | 
| 
       28 
29 
     | 
    
         
             
                  end
         
     | 
| 
       29 
30 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                  def initialize( 
     | 
| 
       31 
     | 
    
         
            -
                    @ 
     | 
| 
      
 31 
     | 
    
         
            +
                  def initialize(base_path:, transport:, auth:)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @base_path = base_path
         
     | 
| 
       32 
33 
     | 
    
         
             
                    @transport = transport
         
     | 
| 
       33 
34 
     | 
    
         
             
                    @auth = auth
         
     | 
| 
       34 
35 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/k8y/rest/connection.rb
    CHANGED
    
    | 
         @@ -2,12 +2,15 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require "forwardable"
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
            require_relative "auth/token_store"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       5 
7 
     | 
    
         
             
            module K8y
         
     | 
| 
       6 
8 
     | 
    
         
             
              module REST
         
     | 
| 
       7 
9 
     | 
    
         
             
                class Connection
         
     | 
| 
       8 
10 
     | 
    
         
             
                  extend Forwardable
         
     | 
| 
       9 
11 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
                  attr_reader : 
     | 
| 
      
 12 
     | 
    
         
            +
                  attr_reader :base_path, :connection
         
     | 
| 
      
 13 
     | 
    
         
            +
                  attr_accessor :token_store
         
     | 
| 
       11 
14 
     | 
    
         | 
| 
       12 
15 
     | 
    
         
             
                  VERBS = [:get, :post, :put, :patch, :delete]
         
     | 
| 
       13 
16 
     | 
    
         
             
                  def_delegators(:connection, *VERBS)
         
     | 
| 
         @@ -15,17 +18,31 @@ module K8y 
     | 
|
| 
       15 
18 
     | 
    
         
             
                  class << self
         
     | 
| 
       16 
19 
     | 
    
         
             
                    # Initialize a Connection object using a provided REST::Config instance
         
     | 
| 
       17 
20 
     | 
    
         
             
                    def from_config(config)
         
     | 
| 
       18 
     | 
    
         
            -
                      new( 
     | 
| 
      
 21 
     | 
    
         
            +
                      new(base_path: config.base_path, ssl: config.transport.to_faraday_options, auth: config.auth)
         
     | 
| 
       19 
22 
     | 
    
         
             
                    end
         
     | 
| 
       20 
23 
     | 
    
         
             
                  end
         
     | 
| 
       21 
24 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                  def initialize( 
     | 
| 
       23 
     | 
    
         
            -
                    @ 
     | 
| 
       24 
     | 
    
         
            -
                    @ 
     | 
| 
      
 25 
     | 
    
         
            +
                  def initialize(base_path:, ssl:, auth:, &conn_options)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @base_path = base_path
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @auth = auth
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @connection = Faraday.new(base_path, ssl: ssl) do |connection|
         
     | 
| 
      
 29 
     | 
    
         
            +
                      connection.use(Faraday::Response::RaiseError)
         
     | 
| 
       25 
30 
     | 
    
         
             
                      auth.configure_connection(connection)
         
     | 
| 
       26 
31 
     | 
    
         
             
                      yield connection if block_given?
         
     | 
| 
       27 
32 
     | 
    
         
             
                    end
         
     | 
| 
       28 
33 
     | 
    
         
             
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def generate_token!
         
     | 
| 
      
 36 
     | 
    
         
            +
                    auth.generate_token!(self) if auth.respond_to?(:generate_token!)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def host
         
     | 
| 
      
 40 
     | 
    
         
            +
                    URI(base_path).host
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  private
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  attr_reader :auth
         
     | 
| 
       29 
46 
     | 
    
         
             
                end
         
     | 
| 
       30 
47 
     | 
    
         
             
              end
         
     | 
| 
       31 
48 
     | 
    
         
             
            end
         
     | 
    
        data/lib/k8y/rest/error.rb
    CHANGED
    
    | 
         @@ -1,6 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       2 
3 
     | 
    
         
             
            module K8y
         
     | 
| 
       3 
4 
     | 
    
         
             
              module REST
         
     | 
| 
       4 
5 
     | 
    
         
             
                Error = Class.new(Error)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                HTTPError = Class.new(Error)
         
     | 
| 
      
 8 
     | 
    
         
            +
                ClientError = Class.new(HTTPError)
         
     | 
| 
      
 9 
     | 
    
         
            +
                NotFoundError = Class.new(ClientError)
         
     | 
| 
      
 10 
     | 
    
         
            +
                RetriableUnauthorizedError = Class.new(ClientError)
         
     | 
| 
      
 11 
     | 
    
         
            +
                UnauthorizedError = Class.new(ClientError)
         
     | 
| 
      
 12 
     | 
    
         
            +
                ServerError = Class.new(HTTPError)
         
     | 
| 
       5 
13 
     | 
    
         
             
              end
         
     | 
| 
       6 
14 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module K8y
         
     | 
| 
      
 4 
     | 
    
         
            +
              module REST
         
     | 
| 
      
 5 
     | 
    
         
            +
                class RequestWrapper
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def handle(exception, retry_unauthorized: false)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    code = exception.response_status
         
     | 
| 
      
 8 
     | 
    
         
            +
                    if code == 401 && retry_unauthorized
         
     | 
| 
      
 9 
     | 
    
         
            +
                      raise RetriableUnauthorizedError, exception
         
     | 
| 
      
 10 
     | 
    
         
            +
                    elsif code == 401
         
     | 
| 
      
 11 
     | 
    
         
            +
                      raise UnauthorizedError, exception
         
     | 
| 
      
 12 
     | 
    
         
            +
                    elsif code == 404
         
     | 
| 
      
 13 
     | 
    
         
            +
                      raise NotFoundError, exception
         
     | 
| 
      
 14 
     | 
    
         
            +
                    elsif code >= 500
         
     | 
| 
      
 15 
     | 
    
         
            +
                      raise ServerError, exception
         
     | 
| 
      
 16 
     | 
    
         
            +
                    else
         
     | 
| 
      
 17 
     | 
    
         
            +
                      raise HTTPError, exception
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       2 
3 
     | 
    
         
             
            module K8y
         
     | 
| 
       3 
4 
     | 
    
         
             
              module REST
         
     | 
| 
       4 
5 
     | 
    
         
             
                class ResponseFormatter
         
     | 
| 
         @@ -13,7 +14,7 @@ module K8y 
     | 
|
| 
       13 
14 
     | 
    
         
             
                  def format(as: :ros)
         
     | 
| 
       14 
15 
     | 
    
         
             
                    case as
         
     | 
| 
       15 
16 
     | 
    
         
             
                    when :ros
         
     | 
| 
       16 
     | 
    
         
            -
                       
     | 
| 
      
 17 
     | 
    
         
            +
                      build_k8y_resource_response(response.body)
         
     | 
| 
       17 
18 
     | 
    
         
             
                    when :raw
         
     | 
| 
       18 
19 
     | 
    
         
             
                      response
         
     | 
| 
       19 
20 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -23,14 +24,14 @@ module K8y 
     | 
|
| 
       23 
24 
     | 
    
         | 
| 
       24 
25 
     | 
    
         
             
                  private
         
     | 
| 
       25 
26 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                  def  
     | 
| 
      
 27 
     | 
    
         
            +
                  def build_k8y_resource_response(body)
         
     | 
| 
       27 
28 
     | 
    
         
             
                    data = JSON.parse(body)
         
     | 
| 
       28 
29 
     | 
    
         
             
                    if item_list?(data)
         
     | 
| 
       29 
     | 
    
         
            -
                      data.fetch("items").map { |item|  
     | 
| 
      
 30 
     | 
    
         
            +
                      data.fetch("items").map { |item| Resource.new(item) }
         
     | 
| 
       30 
31 
     | 
    
         
             
                    elsif resources_list?(data)
         
     | 
| 
       31 
     | 
    
         
            -
                      data.fetch("resources").map { |item|  
     | 
| 
      
 32 
     | 
    
         
            +
                      data.fetch("resources").map { |item| Resource.new(item) }
         
     | 
| 
       32 
33 
     | 
    
         
             
                    else
         
     | 
| 
       33 
     | 
    
         
            -
                       
     | 
| 
      
 34 
     | 
    
         
            +
                      Resource.new(data)
         
     | 
| 
       34 
35 
     | 
    
         
             
                    end
         
     | 
| 
       35 
36 
     | 
    
         
             
                  end
         
     | 
| 
       36 
37 
     | 
    
         | 
    
        data/lib/k8y/rest/transport.rb
    CHANGED
    
    
    
        data/lib/k8y/rest.rb
    CHANGED
    
    
    
        data/lib/k8y/version.rb
    CHANGED
    
    
    
        data/lib/k8y.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: k8y
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.4.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Timothy Smith
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2021-10- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2021-10-30 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: activesupport
         
     | 
| 
         @@ -30,56 +30,56 @@ dependencies: 
     | 
|
| 
       30 
30 
     | 
    
         
             
                requirements:
         
     | 
| 
       31 
31 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       32 
32 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       33 
     | 
    
         
            -
                    version: '1. 
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '1.8'
         
     | 
| 
       34 
34 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       35 
35 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       36 
36 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       37 
37 
     | 
    
         
             
                requirements:
         
     | 
| 
       38 
38 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       39 
39 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       40 
     | 
    
         
            -
                    version: '1. 
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '1.8'
         
     | 
| 
       41 
41 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       42 
     | 
    
         
            -
              name:  
     | 
| 
      
 42 
     | 
    
         
            +
              name: googleauth
         
     | 
| 
       43 
43 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       44 
44 
     | 
    
         
             
                requirements:
         
     | 
| 
       45 
     | 
    
         
            -
                - - " 
     | 
| 
      
 45 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       46 
46 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       47 
     | 
    
         
            -
                    version: ' 
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
       48 
48 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       49 
49 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       50 
50 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       51 
51 
     | 
    
         
             
                requirements:
         
     | 
| 
       52 
     | 
    
         
            -
                - - " 
     | 
| 
      
 52 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       53 
53 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       54 
     | 
    
         
            -
                    version: ' 
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
       55 
55 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       56 
     | 
    
         
            -
              name:  
     | 
| 
      
 56 
     | 
    
         
            +
              name: railties
         
     | 
| 
       57 
57 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       58 
58 
     | 
    
         
             
                requirements:
         
     | 
| 
       59 
59 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       60 
60 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       61 
     | 
    
         
            -
                    version: ' 
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '6.0'
         
     | 
| 
       62 
62 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       63 
63 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       64 
64 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       65 
65 
     | 
    
         
             
                requirements:
         
     | 
| 
       66 
66 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       67 
67 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       68 
     | 
    
         
            -
                    version: ' 
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '6.0'
         
     | 
| 
       69 
69 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       70 
     | 
    
         
            -
              name:  
     | 
| 
      
 70 
     | 
    
         
            +
              name: recursive-open-struct
         
     | 
| 
       71 
71 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       72 
72 
     | 
    
         
             
                requirements:
         
     | 
| 
       73 
     | 
    
         
            -
                - - " 
     | 
| 
      
 73 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       74 
74 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       75 
     | 
    
         
            -
                    version: ' 
     | 
| 
      
 75 
     | 
    
         
            +
                    version: '1.1'
         
     | 
| 
       76 
76 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       77 
77 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       78 
78 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       79 
79 
     | 
    
         
             
                requirements:
         
     | 
| 
       80 
     | 
    
         
            -
                - - " 
     | 
| 
      
 80 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       81 
81 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       82 
     | 
    
         
            -
                    version: ' 
     | 
| 
      
 82 
     | 
    
         
            +
                    version: '1.1'
         
     | 
| 
       83 
83 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       84 
84 
     | 
    
         
             
              name: byebug
         
     | 
| 
       85 
85 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -203,6 +203,7 @@ files: 
     | 
|
| 
       203 
203 
     | 
    
         
             
            - ".gitignore"
         
     | 
| 
       204 
204 
     | 
    
         
             
            - ".rubocop.yml"
         
     | 
| 
       205 
205 
     | 
    
         
             
            - CHANGELOG.md
         
     | 
| 
      
 206 
     | 
    
         
            +
            - DECISIONLOG.md
         
     | 
| 
       206 
207 
     | 
    
         
             
            - Gemfile
         
     | 
| 
       207 
208 
     | 
    
         
             
            - LICENSE.txt
         
     | 
| 
       208 
209 
     | 
    
         
             
            - README.md
         
     | 
| 
         @@ -221,10 +222,12 @@ files: 
     | 
|
| 
       221 
222 
     | 
    
         
             
            - lib/k8y/group_version.rb
         
     | 
| 
       222 
223 
     | 
    
         
             
            - lib/k8y/kubeconfig.rb
         
     | 
| 
       223 
224 
     | 
    
         
             
            - lib/k8y/kubeconfig/auth_info.rb
         
     | 
| 
      
 225 
     | 
    
         
            +
            - lib/k8y/kubeconfig/auth_provider.rb
         
     | 
| 
       224 
226 
     | 
    
         
             
            - lib/k8y/kubeconfig/cluster.rb
         
     | 
| 
       225 
227 
     | 
    
         
             
            - lib/k8y/kubeconfig/config.rb
         
     | 
| 
       226 
228 
     | 
    
         
             
            - lib/k8y/kubeconfig/context.rb
         
     | 
| 
       227 
229 
     | 
    
         
             
            - lib/k8y/kubeconfig/user.rb
         
     | 
| 
      
 230 
     | 
    
         
            +
            - lib/k8y/resource.rb
         
     | 
| 
       228 
231 
     | 
    
         
             
            - lib/k8y/rest.rb
         
     | 
| 
       229 
232 
     | 
    
         
             
            - lib/k8y/rest/auth.rb
         
     | 
| 
       230 
233 
     | 
    
         
             
            - lib/k8y/rest/auth/auth_base.rb
         
     | 
| 
         @@ -236,11 +239,13 @@ files: 
     | 
|
| 
       236 
239 
     | 
    
         
             
            - lib/k8y/rest/auth/providers/gcp/factory.rb
         
     | 
| 
       237 
240 
     | 
    
         
             
            - lib/k8y/rest/auth/providers/provider_base.rb
         
     | 
| 
       238 
241 
     | 
    
         
             
            - lib/k8y/rest/auth/token.rb
         
     | 
| 
      
 242 
     | 
    
         
            +
            - lib/k8y/rest/auth/token_store.rb
         
     | 
| 
       239 
243 
     | 
    
         
             
            - lib/k8y/rest/client.rb
         
     | 
| 
       240 
244 
     | 
    
         
             
            - lib/k8y/rest/config.rb
         
     | 
| 
       241 
245 
     | 
    
         
             
            - lib/k8y/rest/config_validator.rb
         
     | 
| 
       242 
246 
     | 
    
         
             
            - lib/k8y/rest/connection.rb
         
     | 
| 
       243 
247 
     | 
    
         
             
            - lib/k8y/rest/error.rb
         
     | 
| 
      
 248 
     | 
    
         
            +
            - lib/k8y/rest/request_wrapper.rb
         
     | 
| 
       244 
249 
     | 
    
         
             
            - lib/k8y/rest/response_formatter.rb
         
     | 
| 
       245 
250 
     | 
    
         
             
            - lib/k8y/rest/transport.rb
         
     | 
| 
       246 
251 
     | 
    
         
             
            - lib/k8y/version.rb
         
     |