k8y 0.1.0 → 0.2.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 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