k8y 0.1.0 → 0.2.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: 4af0d1dcdd836cab3430faa1d86ebad78e6aa9ed4d935a86a11ba0f4cc11f245
4
- data.tar.gz: f79b384ede82574419718223ab399ca2b4b1ee778d001433a4c0e721529cac69
3
+ metadata.gz: 967e0fcf49dc5ff373df45925be7c14ee0d8da75d12f348373cc70c72621ff23
4
+ data.tar.gz: e02d82838c724f96557d3769421a2ba40557dba6501f012433b1be64ef4204f9
5
5
  SHA512:
6
- metadata.gz: 3048c108fb78383700dbfbb3527645cde925ad2cd56dbe01f36d2728642240e9ce93ad6555150a519f16605f1c6d5337019e7dff6548fc416ec887bdf58f3390
7
- data.tar.gz: 0af26a9f575cbbe9b785c6ecb761df8d1cd97f731905b33f98a5d462562a0d2117f69fbe235c4dae311d05d3b281854c3121480bae3ffe3d9164c6419c2fc16a
6
+ metadata.gz: 5937b19b84140f2a81c0935bce8892c92ae709eb8382ce658297911f65790b311e847c92ae71887d33a6920beca1f8f69d535ab32ce125d6f697cbad0dd99c51
7
+ data.tar.gz: c4635b0a99227890b7ef4dc7c88ab285771d83ea5926a53b599e90f6e5ff20965c5b51b72ad062f513716b598322422eea53825d908094c9441ae32eac54cc59
data/CHANGELOG.md CHANGED
@@ -1 +1,17 @@
1
1
  ## next
2
+
3
+ ## 0.2.0
4
+
5
+ **Enhancements**
6
+
7
+ - K8y::Client::from_in_cluster for easily building in-cluster clients [#23](https://github.com/tsontario/k8y/pull/23)
8
+
9
+ **Testing**
10
+
11
+ - Integration test suite to run against (KinD) cluster [#11](https://github.com/tsontario/k8y/pull/11)
12
+ - Run integration tests in parallel [#22](https://github.com/tsontario/k8y/pull/22)
13
+
14
+ **Design**
15
+
16
+ - Move generated API methods (get_pods, delete_service, etc.) into separate API class, out of top-level K8y::Client::Client [#17](https://github.com/tsontario/k8y/pull/17)
17
+
data/k8y.gemspec CHANGED
@@ -13,8 +13,6 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/tsontario/k8y"
14
14
  spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
15
15
 
16
- # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
17
-
18
16
  spec.metadata["homepage_uri"] = spec.homepage
19
17
  spec.metadata["source_code_uri"] = spec.homepage
20
18
  spec.metadata["changelog_uri"] = spec.homepage
@@ -28,10 +26,10 @@ Gem::Specification.new do |spec|
28
26
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
27
  spec.require_paths = ["lib"]
30
28
 
29
+ spec.add_dependency("activesupport", "~> 6.0")
31
30
  spec.add_dependency("faraday", "~> 1.6")
32
- spec.add_dependency("recursive-open-struct", "~>1.1")
33
31
  spec.add_dependency("railties", "~> 6.0")
34
- spec.add_dependency("activesupport", "~> 6.0")
32
+ spec.add_dependency("recursive-open-struct", "~>1.1")
35
33
 
36
34
  spec.add_development_dependency("byebug", "~> 11")
37
35
  spec.add_development_dependency("minitest", "~> 5")
@@ -27,12 +27,13 @@ module K8y
27
27
  end
28
28
 
29
29
  def build!
30
- rest_client = RESTClient.new(config: config, context: context, path: api.path)
30
+ rest_config = REST::Config.from_kubeconfig(config, path: api.path)
31
+ rest_client = REST::Client.new(connection: REST::Connection.from_config(rest_config))
32
+
31
33
  response = rest_client.get(as: :raw)
32
34
  resource_descriptions = JSON.parse(response.body)["resources"].map do |resource_description|
33
35
  ResourceDescription.from_hash(resource_description)
34
36
  end
35
-
36
37
  resource_descriptions.each do |resource_description|
37
38
  next if resource_description.subresource?
38
39
 
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "rest_client"
4
3
  require_relative "api_builder"
5
4
  require_relative "apis"
6
5
 
@@ -22,10 +21,6 @@ module K8y
22
21
  apis.each { |api| APIBuilder.new(api: api, config: config, context: context.name).build! }
23
22
  end
24
23
 
25
- def set_context(context_name)
26
- @context = config.context(context_name)
27
- end
28
-
29
24
  def method_missing(method_name, *args, &block)
30
25
  candidate_apis = apis.apis_for_method(method_name)
31
26
  case candidate_apis.length
data/lib/k8y/client.rb CHANGED
@@ -13,5 +13,10 @@ module K8y
13
13
  def self.from_config(config, context: nil, group_versions: DEFAULT_GROUP_VERSIONS)
14
14
  Client.new(config: config, context: context || config.current_context, group_versions: group_versions)
15
15
  end
16
+
17
+ def self.from_in_cluster(group_versions: DEFAULT_GROUP_VERSIONS)
18
+ config = Kubeconfig.in_cluster_config
19
+ Client.new(config: config, context: Kubeconfig::IN_CLUSTER_NAME, group_versions: group_versions)
20
+ end
16
21
  end
17
22
  end
@@ -18,9 +18,7 @@ module K8y
18
18
  as_user_extra: hash.fetch("as-user-extra", nil),
19
19
  username: hash.fetch("username", nil),
20
20
  password: hash.fetch("password", nil),
21
- # TODO: this needs something like polymorphic classes, not just raw hash, eventually
22
21
  auth_provider: hash.fetch("auth-provider", nil),
23
- # TODO: This will likely benefit from actual domain models eventually, as well.
24
22
  exec_options: hash.fetch("exec", nil),
25
23
  extensions: hash.fetch("extensions", nil)
26
24
  )
@@ -23,7 +23,7 @@ module K8y
23
23
  @insecure_skip_tls_verify = insecure_skip_tls_verify
24
24
  @certificate_authority = certificate_authority
25
25
  @certificate_authority_data = certificate_authority_data
26
- @server = URI.parse(server)
26
+ @server = server
27
27
  end
28
28
  end
29
29
  end
@@ -28,7 +28,7 @@ module K8y
28
28
  raise Error, e
29
29
  end
30
30
 
31
- def initialize(api_version:, kind:, preferences:, clusters:, contexts:, users:, current_context:)
31
+ def initialize(api_version: "v1", kind: "Config", preferences: {}, clusters:, contexts:, users:, current_context:)
32
32
  @api_version = api_version
33
33
  @kind = kind
34
34
  @preferences = preferences
@@ -38,9 +38,11 @@ module K8y
38
38
  @current_context = current_context
39
39
  end
40
40
 
41
- def context(name)
42
- context = contexts.find { |c| c.name == name }
43
- raise ContextNotFoundError, "Could not find context #{name} in config" unless context
41
+ def context(context)
42
+ return context if context.is_a?(Context)
43
+
44
+ context = contexts.find { |c| c.name == context }
45
+ raise ContextNotFoundError, "Could not find context #{context} in config" unless context
44
46
  context
45
47
  end
46
48
 
@@ -56,13 +58,13 @@ module K8y
56
58
  user
57
59
  end
58
60
 
59
- def cluster_for_context(context_name)
60
- cluster_name = context(context_name).cluster
61
+ def cluster_for_context(context)
62
+ cluster_name = context(context).cluster
61
63
  cluster(cluster_name)
62
64
  end
63
65
 
64
- def user_for_context(context_name)
65
- user(context(context_name).user)
66
+ def user_for_context(context)
67
+ user(context(context).user)
66
68
  end
67
69
  end
68
70
  end
@@ -5,12 +5,51 @@ require_relative "kubeconfig/config"
5
5
  module K8y
6
6
  module Kubeconfig
7
7
  Error = Class.new(Error)
8
+ NotInClusterError = Class.new(Error)
8
9
 
9
- KUBECONFIG = ENV["KUBECONFIG"]
10
+ IN_CLUSTER_NAME = "in-cluster"
10
11
 
11
- def self.from_file(file = File.open(KUBECONFIG))
12
+ TOKEN_FILE = "/var/run/secrets/kubernetes.io/serviceaccount/token"
13
+ ROOT_CA_FILE = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
14
+
15
+ def self.from_file(file = File.open(ENV["KUBECONFIG"]))
12
16
  hash = YAML.safe_load(file.read, permitted_classes: [Date, Time])
13
17
  Config.from_hash(hash)
14
18
  end
19
+
20
+ def self.in_cluster_config
21
+ host = ENV.fetch("KUBERNETES_SERVICE_HOST", nil)
22
+ port = ENV.fetch("KUBERNETES_SERVICE_PORT", nil)
23
+ raise NotInClusterError unless host && port
24
+
25
+ token_data = File.read(TOKEN_FILE)
26
+ auth_info = AuthInfo.new(token: token_data, token_file: TOKEN_FILE)
27
+ user = User.new(
28
+ name: IN_CLUSTER_NAME,
29
+ auth_info: auth_info
30
+ )
31
+
32
+ ca_data = Base64.encode64(File.read(ROOT_CA_FILE))
33
+ cluster = Cluster.new(
34
+ name: IN_CLUSTER_NAME,
35
+ insecure_skip_tls_verify: false,
36
+ certificate_authority: nil,
37
+ certificate_authority_data: ca_data,
38
+ server: "https://#{host}:#{port}",
39
+ )
40
+ context = Context.new(
41
+ name: IN_CLUSTER_NAME,
42
+ cluster: IN_CLUSTER_NAME,
43
+ namespace: nil,
44
+ user: IN_CLUSTER_NAME
45
+ )
46
+
47
+ Config.new(
48
+ clusters: [cluster],
49
+ contexts: [context],
50
+ current_context: context,
51
+ users: [user]
52
+ )
53
+ end
15
54
  end
16
55
  end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+ module K8y
3
+ module REST
4
+ class Auth
5
+ InvalidAuthTypeError = Class.new(Error)
6
+
7
+ class << self
8
+ def from_kubeconfig(kubeconfig, context: nil)
9
+ context = context ? context : kubeconfig.current_context
10
+ auth_info = kubeconfig.user_for_context(context).auth_info
11
+
12
+ new(token: token(auth_info), username: auth_info.username, password: auth_info.password,
13
+ auth_provider: auth_provider(auth_info), exec_provider: exec_provider(auth_info))
14
+ end
15
+
16
+ private
17
+
18
+ def token(auth_info)
19
+ return auth_info.token if auth_info.token
20
+ File.read(auth_info.token_file) if auth_info.token_file
21
+ end
22
+
23
+ def auth_provider(auth_info)
24
+ # TODO
25
+ end
26
+
27
+ def exec_provider(auth_info)
28
+ # TODO
29
+ end
30
+ end
31
+
32
+ def initialize(token: nil, username: nil, password: nil, auth_provider: nil, exec_provider: nil)
33
+ @token = token
34
+ @username = username
35
+ @password = password
36
+ @auth_provider = auth_provider
37
+ @exec_provider = exec_provider
38
+ end
39
+
40
+ def configure_connection(connection)
41
+ case auth_type
42
+ when :basic
43
+ connection.basic_auth(username, password)
44
+ when :token
45
+ connection.headers[:Authorization] = "Bearer #{token}"
46
+ # TODO...
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ attr_reader :token, :username, :password, :auth_provider, :exec_provider
53
+
54
+ def auth_type
55
+ if username && password
56
+ :basic
57
+ elsif token
58
+ :token
59
+ elsif auth_provider
60
+ :auth_provider
61
+ elsif exec_provider
62
+ :exec_provider
63
+ else
64
+ :none
65
+ end
66
+ end
67
+
68
+ def basic?
69
+ auth_type == :basic
70
+ end
71
+
72
+ def token?
73
+ auth_type == :token
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "base64"
5
+ require "recursive_open_struct"
6
+
7
+ require_relative "config"
8
+ require_relative "connection"
9
+ require_relative "response_formatter"
10
+
11
+ module K8y
12
+ module REST
13
+ class Client
14
+ attr_reader :connection
15
+
16
+ class << self
17
+ def from_config(config)
18
+ new(
19
+ connection: Connection.new(
20
+ host: config.host,
21
+ ssl: config.transport.to_faraday_options,
22
+ auth: config.auth
23
+ )
24
+ )
25
+ end
26
+ end
27
+
28
+ def host
29
+ connection.host
30
+ end
31
+
32
+ def initialize(connection:)
33
+ @connection = connection
34
+ end
35
+
36
+ def get(path = "", headers: {}, as: :ros)
37
+ response = connection.get(formatted_uri(path))
38
+ format_response(response, as: as)
39
+ end
40
+
41
+ def post(path = "", data:, headers: {}, as: :ros)
42
+ response = connection.post(formatted_uri(path), data, headers)
43
+ format_response(response, as: as)
44
+ end
45
+
46
+ def put(path = "", data:, headers: {}, as: :ros)
47
+ response = connection.put(formatted_uri(path), data, headers)
48
+ format_response(response, as: as)
49
+ end
50
+
51
+ def patch(path = "", strategy:, data:, headers: {}, as: :ros)
52
+ response = connection.patch(formatted_uri(path), data, headers)
53
+ format_response(response, as: as)
54
+ end
55
+
56
+ def delete(path = "", headers: {}, as: :ros)
57
+ response = connection.delete(formatted_uri(path))
58
+ format_response(response, as: as)
59
+ end
60
+
61
+ private
62
+
63
+ def formatted_uri(path = "")
64
+ File.join(connection.host, path)
65
+ end
66
+
67
+ def format_response(response, as: :ros)
68
+ ResponseFormatter.new(response).format(as: as)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ require_relative "config_validator"
3
+ require_relative "transport"
4
+ require_relative "auth"
5
+
6
+ module K8y
7
+ module REST
8
+ class Config
9
+ attr_reader :host, :transport, :auth
10
+
11
+ class << self
12
+ def from_kubeconfig(kubeconfig, path:)
13
+ context = context ? context : kubeconfig.current_context
14
+ ConfigValidator.new(kubeconfig, context: context).validate!
15
+
16
+ cluster = kubeconfig.cluster_for_context(context)
17
+ host = File.join(cluster.server, path)
18
+ transport = if URI(host).scheme == "https"
19
+ Transport.from_kubeconfig(kubeconfig, context: context)
20
+ end
21
+ auth = Auth.from_kubeconfig(kubeconfig, context: context)
22
+ new(
23
+ host: host,
24
+ transport: transport,
25
+ auth: auth
26
+ )
27
+ end
28
+ end
29
+
30
+ def initialize(host:, transport:, auth:)
31
+ @host = host
32
+ @transport = transport
33
+ @auth = auth
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ module K8y
3
+ module REST
4
+ class ConfigValidator
5
+ class ValidationError < Error
6
+ def initialize(validation_errors)
7
+ super
8
+ @message = "Kubeconfig validation failed with the following errors: " + validation_errors.join(",")
9
+ end
10
+ end
11
+
12
+ VALIDATIONS = [
13
+ :validate_auth_info,
14
+ :validate_context,
15
+ :validate_cluster,
16
+ :validate_usable,
17
+ ].freeze
18
+
19
+ def initialize(kubeconfig, context:)
20
+ @kubeconfig = kubeconfig
21
+ @context = context
22
+ end
23
+
24
+ def validate!
25
+ errors = VALIDATIONS.map { |validation| send(validation) }.compact
26
+ raise ValidationError, errors if errors.present?
27
+ end
28
+
29
+ private
30
+
31
+ def validate_auth_info
32
+ # TODO
33
+ end
34
+
35
+ def validate_context
36
+ # TODO
37
+ end
38
+
39
+ def validate_cluster
40
+ # TODO
41
+ end
42
+
43
+ def validate_usable
44
+ # TODO
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module K8y
6
+ module REST
7
+ class Connection
8
+ extend Forwardable
9
+
10
+ attr_reader :host, :connection
11
+
12
+ VERBS = [:get, :post, :put, :patch, :delete]
13
+ def_delegators(:connection, *VERBS)
14
+
15
+ class << self
16
+ # Initialize a Connection object using a provided REST::Config instance
17
+ def from_config(config)
18
+ new(host: config.host, ssl: config.transport.to_faraday_options, auth: config.auth)
19
+ end
20
+ end
21
+
22
+ def initialize(host:, ssl:, auth:, &conn_options)
23
+ @host = host
24
+ @connection = Faraday.new(host, ssl: ssl) do |connection|
25
+ auth.configure_connection(connection)
26
+ yield connection if block_given?
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ module K8y
3
+ module REST
4
+ Error = Class.new(Error)
5
+ end
6
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module K8y
3
- module Client
3
+ module REST
4
4
  class ResponseFormatter
5
5
  UnsupportedResponseTypeError = Class.new(Error)
6
6
 
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+ module K8y
3
+ module REST
4
+ class Transport
5
+ attr_reader :cert_file, :key_file, :ca_file, :cert_data, :key_data, :ca_data
6
+
7
+ class << self
8
+ def from_kubeconfig(kubeconfig, context: nil)
9
+ context = context ? context : kubeconfig.current_context
10
+ cluster = kubeconfig.cluster_for_context(context)
11
+ auth_info = kubeconfig.user_for_context(context).auth_info
12
+
13
+ transport = new(cert_file: auth_info.client_certificate, key_file: auth_info.client_key,
14
+ ca_file: cluster.certificate_authority, cert_data: auth_info.client_certificate_data,
15
+ key_data: auth_info.client_key_data, ca_data: cluster.certificate_authority_data)
16
+ transport.reconcile!
17
+ transport
18
+ end
19
+ end
20
+
21
+ def initialize(cert_file: nil, key_file: nil, ca_file: nil, cert_data: nil, key_data: nil, ca_data: nil)
22
+ @cert_file = cert_file
23
+ @key_file = key_file
24
+ @ca_file = ca_file
25
+
26
+ @cert_data = cert_data
27
+ @key_data = key_data
28
+ @ca_data = ca_data
29
+ end
30
+
31
+ def reconcile!
32
+ return if reconciled?
33
+ reconcile_cert_data!
34
+ reconcile_key_data!
35
+ reconcile_ca_data!
36
+
37
+ @reconciled = true
38
+ end
39
+
40
+ def to_faraday_options
41
+ if ca_data
42
+ cert_store = OpenSSL::X509::Store.new
43
+ cert_store.add_cert(OpenSSL::X509::Certificate.new(ca_data))
44
+ end
45
+
46
+ {
47
+ client_cert: (OpenSSL::X509::Certificate.new(cert_data) if cert_data),
48
+ client_key: (OpenSSL::PKey::RSA.new(key_data) if key_data),
49
+ cert_store: cert_store,
50
+ verify: OpenSSL::SSL::VERIFY_PEER,
51
+ }
52
+ end
53
+
54
+ private
55
+
56
+ attr_reader :reconciled
57
+ attr_writer :cert_data, :key_data, :ca_data
58
+
59
+ def reconcile_cert_data!
60
+ @cert_data = if cert_data
61
+ Base64.decode64(cert_data)
62
+ elsif cert_file
63
+ File.read(cert_file)
64
+ end
65
+ end
66
+
67
+ def reconcile_key_data!
68
+ @key_data = if key_data
69
+ Base64.decode64(key_data)
70
+ elsif key_file
71
+ File.read(key_file)
72
+ end
73
+ end
74
+
75
+ def reconcile_ca_data!
76
+ @ca_data = if ca_data
77
+ Base64.decode64(ca_data)
78
+ elsif ca_file
79
+ File.read(ca_file)
80
+ end
81
+ end
82
+
83
+ def reconciled?
84
+ reconciled
85
+ end
86
+ end
87
+ end
88
+ end
data/lib/k8y/rest.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require_relative "rest/error"
3
+ require_relative "rest/client"
4
+
5
+ module K8y
6
+ module REST
7
+ end
8
+ end
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.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/k8y.rb CHANGED
@@ -7,3 +7,4 @@ require_relative "k8y/version"
7
7
  require_relative "k8y/kubeconfig"
8
8
  require_relative "k8y/group_version"
9
9
  require_relative "k8y/client"
10
+ require_relative "k8y/rest"
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: k8y
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.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-09-18 00:00:00.000000000 Z
11
+ date: 2021-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: faraday
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
19
+ version: '6.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.6'
26
+ version: '6.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: recursive-open-struct
28
+ name: faraday
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.1'
33
+ version: '1.6'
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.1'
40
+ version: '1.6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: railties
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,19 +53,19 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '6.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: activesupport
56
+ name: recursive-open-struct
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '6.0'
61
+ version: '1.1'
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: '6.0'
68
+ version: '1.1'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: byebug
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -203,8 +203,6 @@ files:
203
203
  - lib/k8y/client/apis.rb
204
204
  - lib/k8y/client/client.rb
205
205
  - lib/k8y/client/resource_description.rb
206
- - lib/k8y/client/response_formatter.rb
207
- - lib/k8y/client/rest_client.rb
208
206
  - lib/k8y/error.rb
209
207
  - lib/k8y/group_version.rb
210
208
  - lib/k8y/kubeconfig.rb
@@ -213,6 +211,15 @@ files:
213
211
  - lib/k8y/kubeconfig/config.rb
214
212
  - lib/k8y/kubeconfig/context.rb
215
213
  - lib/k8y/kubeconfig/user.rb
214
+ - lib/k8y/rest.rb
215
+ - lib/k8y/rest/auth.rb
216
+ - lib/k8y/rest/client.rb
217
+ - lib/k8y/rest/config.rb
218
+ - lib/k8y/rest/config_validator.rb
219
+ - lib/k8y/rest/connection.rb
220
+ - lib/k8y/rest/error.rb
221
+ - lib/k8y/rest/response_formatter.rb
222
+ - lib/k8y/rest/transport.rb
216
223
  - lib/k8y/version.rb
217
224
  homepage: https://github.com/tsontario/k8y
218
225
  licenses: []
@@ -1,90 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "faraday"
4
- require "base64"
5
- require "recursive_open_struct"
6
-
7
- require_relative "response_formatter"
8
-
9
- module K8y
10
- module Client
11
- class RESTClient
12
- attr_reader :context, :path
13
-
14
- def initialize(config:, context:, path: "")
15
- @config = config
16
- @context = context
17
- @path = path
18
-
19
- # TODO: generically handle auth depending on provided config
20
- hardcoded_auth
21
- end
22
-
23
- def get(sub_path = "", headers: {}, as: :ros)
24
- response = connection.get(formatted_uri(host, path, sub_path))
25
- format_response(response, as: as)
26
- end
27
-
28
- def post(sub_path = "", data:, headers: {}, as: :ros)
29
- response = connection.post(formatted_uri(host, path, sub_path), data, headers)
30
- format_response(response, as: as)
31
- end
32
-
33
- def put(sub_path = "", data:, headers: {}, as: :ros)
34
- response = connection.put(formatted_uri(host, path, sub_path), data, headers)
35
- format_response(response, as: as)
36
- end
37
-
38
- def patch(sub_path = "", strategy:, data:, headers: {}, as: :ros)
39
- response = connection.patch(formatted_uri(host, path, sub_path), data, headers)
40
- format_response(response, as: as)
41
- end
42
-
43
- def delete(sub_path = "", headers: {}, as: :ros)
44
- response = connection.delete(formatted_uri(host, path, sub_path))
45
- format_response(response, as: as)
46
- end
47
-
48
- private
49
-
50
- attr_reader :config, :connection
51
-
52
- def hardcoded_auth
53
- cert_store = OpenSSL::X509::Store.new
54
- cert_store.add_cert(OpenSSL::X509::Certificate.new(Base64.decode64(cluster.certificate_authority_data)))
55
- @connection = Faraday.new(
56
- host,
57
- ssl: {
58
- client_cert: OpenSSL::X509::Certificate.new(Base64.decode64(user.auth_info.client_certificate_data)),
59
- client_key: OpenSSL::PKey::RSA.new(Base64.decode64(user.auth_info.client_key_data)),
60
- cert_store: cert_store,
61
- }
62
- )
63
- end
64
-
65
- def host
66
- cluster.server
67
- end
68
-
69
- def cluster
70
- config.cluster_for_context(context)
71
- end
72
-
73
- def user
74
- config.user_for_context(context)
75
- end
76
-
77
- def formatted_uri(host, path, sub_path = "")
78
- if !sub_path.empty? && !path.end_with?("/")
79
- URI.join(host, "#{path}/", sub_path)
80
- else
81
- URI.join(host, path, sub_path)
82
- end
83
- end
84
-
85
- def format_response(response, as: :ros)
86
- ResponseFormatter.new(response).format(as: as)
87
- end
88
- end
89
- end
90
- end