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 +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
|