k8y 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3eff2fb332ede35caba339504a2c23ef9fb860b0741bcaaa89186f7e6e66af42
4
- data.tar.gz: 39f451e5d2966311dd688efd8f3b8c14a7e8a84caf37038de8446dd4f46f954b
3
+ metadata.gz: a5320e2541c6887f3f654b04d76121467d4b80328164cb6489a2c47496291d65
4
+ data.tar.gz: 6ad43159e2bc56e4dfd96bf06fc279781789e48c342bffb11122ffa6d4ae97f2
5
5
  SHA512:
6
- metadata.gz: 408213ee541f715a98fa1c2905110e94a41aea9f6cfa1b88a2908874c766d84264973ecf0c704bd7f4a05e0bc87e3f52dbea618a959a6a07ffec1c3a92155cad
7
- data.tar.gz: 43ddd9865d31d1b33b5c954b7afbadf2f2d8aae39862a980a2005c78b9b6de97bf69d1cd7ac770444a86783f1a437cb1563a58af20049d90ef5edb544a67ce4a
6
+ metadata.gz: 6092e6243c294e24404993c891749d653623cc161b609003f12f5ae0d6c2665c2775902394ead30519d4761bce3c8dd11713132251dbecadcde4697698c5eb4b
7
+ data.tar.gz: 7820369a97588da212de66325c3879a59d5ad49e3baca6a1405eebcd0f397cadb33c3cb100cd85e9a10339038e71c4a9da2700e85535f7cd84ce482c21cc4b91
data/.gitignore CHANGED
@@ -8,8 +8,8 @@
8
8
  /tmp/
9
9
  /.DS_Store
10
10
 
11
- # Rake-able scratch working directory
12
- /scratch
11
+ # Debug sessions
12
+ debug_session.rb
13
13
 
14
14
  # Ignore lockfile for gem
15
15
  Gemfile.lock
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 in-cluster integrations tests")
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/integration/**/*_test.rb"]
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.6")
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
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative "client/client"
3
4
 
4
5
  module K8y
data/lib/k8y/error.rb CHANGED
@@ -1,2 +1,3 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class Error < StandardError; end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module K8y
3
4
  class GroupVersion
4
5
  attr_reader :group, :version
@@ -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
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "recursive-open-struct"
4
+
5
+ module K8y
6
+ module Kubeconfig
7
+ class AuthProvider < RecursiveOpenStruct
8
+ def present?
9
+ to_h.present?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative "auth_info"
3
4
 
4
5
  module K8y
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "recursive-open-struct"
4
+
5
+ module K8y
6
+ class Resource < RecursiveOpenStruct
7
+ def initialize(hash, args = {})
8
+ args[:recurse_over_arrays] = true
9
+ super(hash, args)
10
+ end
11
+ end
12
+ end
@@ -4,8 +4,7 @@ module K8y
4
4
  module REST
5
5
  module Auth
6
6
  class AuthBase
7
- def configure_connection(connection)
8
- end
7
+ def configure_connection(connection); end
9
8
  end
10
9
  end
11
10
  end
@@ -9,11 +9,12 @@ module K8y
9
9
  module Auth
10
10
  class Factory
11
11
  def from_auth_info(auth_info)
12
- if auth_info.username && auth_info.password
12
+ case auth_info.strategy
13
+ when :basic
13
14
  Basic.new(username: auth_info.username, password: auth_info.password)
14
- elsif auth_info.token
15
+ when :token
15
16
  Token.new(token: auth_info.token)
16
- elsif auth_info.auth_provider
17
+ when :auth_provider
17
18
  Providers::Factory.new.from_auth_provider(auth_info.auth_provider)
18
19
  else
19
20
  AuthBase.new
@@ -11,7 +11,7 @@ module K8y
11
11
  class Factory
12
12
  UnnamedProviderError = Class.new(Error)
13
13
  def from_auth_provider(provider)
14
- case provider[:name]
14
+ case provider.name
15
15
  when "gcp"
16
16
  GCP::Factory.new.from_auth_provider(provider)
17
17
  when nil
@@ -15,14 +15,12 @@ module K8y
15
15
  "https://www.googleapis.com/auth/userinfo.email",
16
16
  ]
17
17
 
18
- # #get_application_default actually returns a full oauth2 token payload
19
- # This gives us, among other things, a refresh token, that we should be
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/, '\\1') # {.foo.bar} -> .foo.bar
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[:config]
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[:"cmd-path"]
17
+ if config&.public_send(:"cmd-path")
22
18
  CommandProvider.new(
23
- access_token: config[:"access-token"],
24
- cmd_args: config[:"cmd-args"],
25
- cmd_path: config[:"cmd-path"],
26
- expiry: config[:expiry],
27
- expiry_key: config[:"expiry-key"],
28
- token_key: config[:"token-key"]
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
- # TODO: public API not finalized; subject to change
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
@@ -1,23 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "faraday"
4
3
  require "base64"
5
- require "recursive_open_struct"
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
- host: config.host,
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
- response = connection.get(formatted_uri(path))
38
- format_response(response, as: as)
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
- response = connection.post(formatted_uri(path), data, headers)
43
- format_response(response, as: as)
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
- response = connection.put(formatted_uri(path), data, headers)
48
- format_response(response, as: as)
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
- response = connection.patch(formatted_uri(path), data, headers)
53
- format_response(response, as: as)
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
- response = connection.delete(formatted_uri(path))
58
- format_response(response, as: as)
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.host, path)
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
@@ -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 :host, :transport, :auth
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
- host = File.join(cluster.server, path)
18
- transport = if URI(host).scheme == "https"
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
- host: host,
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(host:, transport:, auth:)
31
- @host = host
31
+ def initialize(base_path:, transport:, auth:)
32
+ @base_path = base_path
32
33
  @transport = transport
33
34
  @auth = auth
34
35
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module K8y
3
4
  module REST
4
5
  class ConfigValidator
@@ -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 :host, :connection
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(host: config.host, ssl: config.transport.to_faraday_options, auth: config.auth)
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(host:, ssl:, auth:, &conn_options)
23
- @host = host
24
- @connection = Faraday.new(host, ssl: ssl) do |connection|
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
@@ -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
- build_recursive_open_struct_response(response.body)
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 build_recursive_open_struct_response(body)
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| RecursiveOpenStruct.new(item, recurse_over_arrays: true) }
30
+ data.fetch("items").map { |item| Resource.new(item) }
30
31
  elsif resources_list?(data)
31
- data.fetch("resources").map { |item| RecursiveOpenStruct.new(item, recurse_over_arrays: true) }
32
+ data.fetch("resources").map { |item| Resource.new(item) }
32
33
  else
33
- RecursiveOpenStruct.new(data, recurse_over_arrays: true)
34
+ Resource.new(data)
34
35
  end
35
36
  end
36
37
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module K8y
3
4
  module REST
4
5
  class Transport
data/lib/k8y/rest.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative "rest/error"
3
4
  require_relative "rest/client"
4
5
 
data/lib/k8y/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module K8y
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/k8y.rb CHANGED
@@ -4,6 +4,7 @@ require "active_support/core_ext/object/blank"
4
4
 
5
5
  require_relative "k8y/error"
6
6
  require_relative "k8y/version"
7
+ require_relative "k8y/resource"
7
8
  require_relative "k8y/kubeconfig"
8
9
  require_relative "k8y/group_version"
9
10
  require_relative "k8y/client"
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.3.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-03 00:00:00.000000000 Z
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.6'
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.6'
40
+ version: '1.8'
41
41
  - !ruby/object:Gem::Dependency
42
- name: railties
42
+ name: googleauth
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '6.0'
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: '6.0'
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: recursive-open-struct
56
+ name: railties
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.1'
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: '1.1'
68
+ version: '6.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: googleauth
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: '0'
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: '0'
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