dapp 0.12.8 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/dapp +0 -4
- data/config/en/common.yml +1 -0
- data/config/en/net_status.yml +5 -0
- data/lib/dapp.rb +20 -8
- data/lib/dapp/cli.rb +2 -5
- data/lib/dapp/cli/command/base.rb +1 -5
- data/lib/dapp/dapp.rb +0 -22
- data/lib/dapp/dapp/shellout/streaming.rb +2 -2
- data/lib/dapp/deployment/cli/command/deployment.rb +1 -3
- data/lib/dapp/deployment/cli/command/deployment/apply.rb +1 -1
- data/lib/dapp/deployment/dapp/dapp.rb +0 -2
- data/lib/dapp/dimg/cli/command/base.rb +4 -0
- data/lib/dapp/dimg/config/directive/git_artifact_remote.rb +1 -3
- data/lib/dapp/dimg/dimg.rb +1 -0
- data/lib/dapp/dimg/dimg/path.rb +0 -6
- data/lib/dapp/helper/trivia.rb +4 -0
- data/lib/dapp/kube.rb +1 -0
- data/lib/dapp/kube/cli/cli.rb +1 -0
- data/lib/dapp/kube/cli/command/base.rb +14 -0
- data/lib/dapp/kube/cli/command/kube.rb +21 -0
- data/lib/dapp/kube/cli/command/kube/deploy.rb +30 -0
- data/lib/dapp/kube/cli/command/kube/dismiss.rb +21 -0
- data/lib/dapp/kube/cli/command/kube/secret_file_encrypt.rb +23 -0
- data/lib/dapp/kube/cli/command/kube/secret_generate.rb +13 -0
- data/lib/dapp/kube/cli/command/kube/secret_key_generate.rb +13 -0
- data/lib/dapp/kube/dapp/command/common.rb +29 -0
- data/lib/dapp/kube/dapp/command/deploy.rb +192 -0
- data/lib/dapp/kube/dapp/command/dismiss.rb +25 -0
- data/lib/dapp/kube/dapp/command/secret_file_encrypt.rb +22 -0
- data/lib/dapp/{deployment → kube}/dapp/command/secret_generate.rb +3 -3
- data/lib/dapp/{deployment → kube}/dapp/command/secret_key_generate.rb +2 -2
- data/lib/dapp/kube/dapp/dapp.rb +16 -0
- data/lib/dapp/kube/error/base.rb +7 -0
- data/lib/dapp/kube/error/command.rb +7 -0
- data/lib/dapp/kube/kubernetes.rb +191 -0
- data/lib/dapp/kube/secret.rb +93 -0
- data/lib/dapp/version.rb +1 -1
- metadata +23 -37
- data/lib/dapp/dapp/sentry.rb +0 -112
- data/lib/dapp/deployment/cli/command/deployment/secret_generate.rb +0 -13
- data/lib/dapp/deployment/cli/command/deployment/secret_key_generate.rb +0 -13
- data/lib/dapp/helper/url.rb +0 -23
@@ -0,0 +1,29 @@
|
|
1
|
+
module Dapp
|
2
|
+
module Kube
|
3
|
+
module Dapp
|
4
|
+
module Command
|
5
|
+
module Common
|
6
|
+
def kube_check_helm!
|
7
|
+
raise Error::Command, code: :helm_not_found if shellout('which helm').exitstatus == 1
|
8
|
+
end
|
9
|
+
|
10
|
+
def kube_release_name
|
11
|
+
"#{name}-#{kube_namespace}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def kube_namespace
|
15
|
+
options[:namespace].tr('_', '-')
|
16
|
+
end
|
17
|
+
|
18
|
+
def secret
|
19
|
+
@secret ||= Secret.new(ENV['DAPP_SECRET_KEY']) if ENV.key?('DAPP_SECRET_KEY')
|
20
|
+
end
|
21
|
+
|
22
|
+
def kubernetes
|
23
|
+
@kubernetes ||= Kubernetes.new(namespace: kube_namespace)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
module Dapp
|
2
|
+
module Kube
|
3
|
+
module Dapp
|
4
|
+
module Command
|
5
|
+
module Deploy
|
6
|
+
def kube_deploy
|
7
|
+
raise Error::Command, code: :helm_directory_not_exist unless kube_chart_path.exist?
|
8
|
+
kube_check_helm!
|
9
|
+
kube_check_helm_chart!
|
10
|
+
|
11
|
+
repo = option_repo
|
12
|
+
image_version = options[:image_version]
|
13
|
+
validate_repo_name!(repo)
|
14
|
+
validate_tag_name!(image_version)
|
15
|
+
|
16
|
+
begin
|
17
|
+
kube_copy_chart
|
18
|
+
kube_helm_decode_secrets
|
19
|
+
kube_generate_helm_chart_tpl
|
20
|
+
|
21
|
+
additional_values = [].tap do |options|
|
22
|
+
options << "--values #{kube_chart_path("values/#{kube_namespace}.yaml")}" if kube_chart_path("values/#{kube_namespace}.yaml").exist?
|
23
|
+
options << "--values #{kube_tmp_chart_secret_values_path.exist? ? kube_tmp_chart_secret_values_path : kube_chart_secret_values_path}" if kube_chart_secret_values_path.exist?
|
24
|
+
end
|
25
|
+
|
26
|
+
set_options = [].tap do |options|
|
27
|
+
options << "--set global.dapp.repo=#{repo}"
|
28
|
+
options << "--set global.dapp.image_version=#{image_version}"
|
29
|
+
options << "--set global.namespace=#{kube_namespace}"
|
30
|
+
options << "--set global.env=#{kube_namespace}"
|
31
|
+
end
|
32
|
+
|
33
|
+
kube_flush_hooks_jobs(additional_values, set_options)
|
34
|
+
kube_run_deploy(additional_values, set_options)
|
35
|
+
ensure
|
36
|
+
if dev_mode?
|
37
|
+
log_info "Temporary chart directory: #{kube_tmp_chart_path}"
|
38
|
+
else
|
39
|
+
FileUtils.rm_rf(kube_tmp_chart_path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def kube_copy_chart
|
45
|
+
FileUtils.cp_r("#{kube_chart_path}/.", kube_tmp_chart_path)
|
46
|
+
end
|
47
|
+
|
48
|
+
def kube_helm_decode_secrets
|
49
|
+
if secret.nil?
|
50
|
+
log_warning(desc: { code: :dapp_secret_key_not_found }) if kube_chart_secret_values_path.file? || kube_chart_secret_path.directory?
|
51
|
+
else
|
52
|
+
kube_helm_decode_secret_values
|
53
|
+
kube_helm_decode_secret_files
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def kube_helm_decode_secret_values
|
58
|
+
return unless kube_chart_secret_values_path.file?
|
59
|
+
decoded_data = kube_helm_decode_json(YAML::load(kube_chart_secret_values_path.read))
|
60
|
+
kube_tmp_chart_secret_values_path.write(decoded_data.to_yaml)
|
61
|
+
end
|
62
|
+
|
63
|
+
def kube_helm_decode_json(json)
|
64
|
+
decode_value = proc do |value|
|
65
|
+
case value
|
66
|
+
when Array then value.map { |v| decode_value.call(v) }
|
67
|
+
when Hash then kube_helm_decode_json(value)
|
68
|
+
else
|
69
|
+
secret.extract(value)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
json.each { |k, v| json[k] = decode_value.call(v) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def kube_helm_decode_secret_files
|
76
|
+
return unless kube_chart_secret_path.directory?
|
77
|
+
Dir.glob(kube_chart_secret_path.join('**/*')).each do |entry|
|
78
|
+
next unless File.file?(entry)
|
79
|
+
secret_relative_path = Pathname(entry).subpath_of(kube_chart_secret_path)
|
80
|
+
IO.binwrite(kube_tmp_chart_secret_path(secret_relative_path), secret.extract(IO.binread(entry)))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def kube_generate_helm_chart_tpl
|
85
|
+
secret_directory = secret.nil? ? 'secret' : kube_tmp_chart_secret_path.subpath_of(kube_tmp_chart_path)
|
86
|
+
cont = <<-EOF
|
87
|
+
{{/* vim: set filetype=mustache: */}}
|
88
|
+
|
89
|
+
{{- define "dapp_secret_file" -}}
|
90
|
+
{{- $relative_file_path := index . 0 -}}
|
91
|
+
{{- $context := index . 1 -}}
|
92
|
+
{{- $context.Files.Get (print "#{secret_directory}/" $relative_file_path) -}}
|
93
|
+
{{- end -}}
|
94
|
+
EOF
|
95
|
+
kube_tmp_chart_path('templates/dapp_secret_file.tpl').write(cont)
|
96
|
+
end
|
97
|
+
|
98
|
+
def kube_flush_hooks_jobs(additional_values, set_options)
|
99
|
+
return if (config_jobs_names = kube_helm_hooks_jobs_to_delete(additional_values, set_options).keys).empty?
|
100
|
+
kube_job_list.reject { |name| config_jobs_names.include? name }.each do
|
101
|
+
log_process("Delete hooks job `#{job_name}` for release #{kube_release_name} ", short: true) { kube_delete_job!(name) }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def kube_helm_hooks_jobs_to_delete(additional_values, set_options)
|
106
|
+
generator = proc do |text|
|
107
|
+
text.split(/# Source.*|---/).reject {|c| c.strip.empty? }.map {|c| YAML::load(c) }.reduce({}) do |objects, c|
|
108
|
+
objects[c['kind']] ||= {}
|
109
|
+
objects[c['kind']][(c['metadata'] || {})['name']] = c
|
110
|
+
objects
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
args = [kube_release_name, kube_tmp_chart_path, additional_values, set_options, kube_helm_extra_options(dry_run: true)].flatten
|
115
|
+
output = shellout!("helm upgrade #{args.join(' ')}", log_verbose: false).stdout
|
116
|
+
|
117
|
+
manifest_start_index = output.lines.index("MANIFEST:\n") + 1
|
118
|
+
hook_start_index = output.lines.index("HOOKS:\n") + 1
|
119
|
+
configs = generator.call(output.lines[hook_start_index..manifest_start_index-1].join)
|
120
|
+
|
121
|
+
(configs['Job'] || []).reject do |_, c|
|
122
|
+
c['metadata'] ||= {}
|
123
|
+
c['metadata']['annotations'] ||= {}
|
124
|
+
c['metadata']['annotations']['helm.sh/resource-policy'] == 'keep'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def kube_job_list
|
129
|
+
kubernetes.job_list['items'].map { |i| i['metadata']['name'] }
|
130
|
+
end
|
131
|
+
|
132
|
+
def kube_delete_job!(name)
|
133
|
+
kubernetes.delete_job!(name)
|
134
|
+
loop do
|
135
|
+
break unless kubernetes.job?(name)
|
136
|
+
sleep 1
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def kube_run_deploy(additional_values, set_options)
|
141
|
+
log_process("Deploy release #{kube_release_name} ", verbose: true) do
|
142
|
+
args = [kube_release_name, kube_tmp_chart_path, additional_values, set_options, kube_helm_extra_options].flatten
|
143
|
+
kubernetes.create_namespace!(kube_namespace) unless kubernetes.namespace?(kube_namespace)
|
144
|
+
shellout! "helm upgrade #{args.join(' ')}", force_log: true
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def kube_check_helm_chart!
|
149
|
+
raise Error::Command, code: :project_helm_chart_not_found, data: { path: kube_chart_path } unless kube_chart_path.exist?
|
150
|
+
end
|
151
|
+
|
152
|
+
def kube_helm_extra_options(dry_run: dry_run?)
|
153
|
+
[].tap do |options|
|
154
|
+
options << "--namespace #{kube_namespace}"
|
155
|
+
options << '--install'
|
156
|
+
options << '--wait'
|
157
|
+
options << '--timeout 1800'
|
158
|
+
|
159
|
+
options << '--dry-run' if dry_run
|
160
|
+
options << '--debug' if dry_run || log_verbose?
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def kube_tmp_chart_secret_values_path
|
165
|
+
kube_tmp_chart_path('decoded-secret-values.yaml')
|
166
|
+
end
|
167
|
+
|
168
|
+
def kube_tmp_chart_secret_path(*path)
|
169
|
+
kube_tmp_chart_path('decoded-secret', *path).tap { |p| p.parent.mkpath }
|
170
|
+
end
|
171
|
+
|
172
|
+
def kube_tmp_chart_path(*path)
|
173
|
+
@kube_tmp_path ||= Dir.mktmpdir('dapp-secret-', options[:tmp_dir_prefix] || '/tmp')
|
174
|
+
make_path(@kube_tmp_path, *path).expand_path.tap { |p| p.parent.mkpath }
|
175
|
+
end
|
176
|
+
|
177
|
+
def kube_chart_secret_values_path
|
178
|
+
kube_chart_path('secret-values.yaml').expand_path
|
179
|
+
end
|
180
|
+
|
181
|
+
def kube_chart_secret_path(*path)
|
182
|
+
kube_chart_path('secret', *path).expand_path
|
183
|
+
end
|
184
|
+
|
185
|
+
def kube_chart_path(*path)
|
186
|
+
make_path(self.path, '.helm', *path).expand_path
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Dapp
|
2
|
+
module Kube
|
3
|
+
module Dapp
|
4
|
+
module Command
|
5
|
+
module Dismiss
|
6
|
+
def kube_dismiss
|
7
|
+
kube_check_helm!
|
8
|
+
kube_check_helm_release!
|
9
|
+
log_process("Delete release #{kube_release_name} ", verbose: true) do
|
10
|
+
with_log_indent do
|
11
|
+
shellout! "helm delete #{kube_release_name} --purge"
|
12
|
+
kubernetes.delete_namespace!(kube_namespace) if options[:with_namespace]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def kube_check_helm_release!
|
18
|
+
pr = shellout("helm list | grep #{kube_release_name}")
|
19
|
+
raise Error::Command, code: :helm_release_not_exist, data: { name: kube_release_name } if pr.status == 1 || pr.stdout.empty?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Dapp
|
2
|
+
module Kube
|
3
|
+
module Dapp
|
4
|
+
module Command
|
5
|
+
module SecretFileEncrypt
|
6
|
+
def kube_secret_file_encrypt(file_path)
|
7
|
+
raise Error::Command, code: :secret_key_not_found if secret.nil?
|
8
|
+
raise Error::Command, code: :file_not_exist, data: { path: File.expand_path(file_path) } unless File.exist?(file_path)
|
9
|
+
|
10
|
+
encrypted_data = secret.generate(IO.binread(file_path))
|
11
|
+
if (output_file_path = options[:output_file_path]).nil?
|
12
|
+
puts encrypted_data
|
13
|
+
else
|
14
|
+
FileUtils.mkpath File.dirname(output_file_path)
|
15
|
+
IO.binwrite(output_file_path, encrypted_data)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Dapp
|
2
|
-
module
|
2
|
+
module Kube
|
3
3
|
module Dapp
|
4
4
|
module Command
|
5
5
|
module SecretGenerate
|
6
|
-
def
|
6
|
+
def kube_secret_generate
|
7
7
|
raise Error::Command, code: :secret_key_not_found if secret.nil?
|
8
|
-
unless (data = $stdin.gets(nil)).nil?
|
8
|
+
unless (data = $stdin.noecho { |s| s.gets(nil) }).nil?
|
9
9
|
puts unless data.end_with?("\n")
|
10
10
|
puts secret.generate(data)
|
11
11
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Dapp
|
2
|
+
module Kube
|
3
|
+
module Dapp
|
4
|
+
module Dapp
|
5
|
+
include Command::Deploy
|
6
|
+
include Command::Dismiss
|
7
|
+
include Command::SecretGenerate
|
8
|
+
include Command::SecretKeyGenerate
|
9
|
+
include Command::SecretFileEncrypt
|
10
|
+
include Command::Common
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
::Dapp::Dapp.send(:include, ::Dapp::Kube::Dapp::Dapp)
|
@@ -0,0 +1,191 @@
|
|
1
|
+
module Dapp
|
2
|
+
module Kube
|
3
|
+
class Kubernetes
|
4
|
+
def initialize(namespace: nil)
|
5
|
+
@namespace = namespace
|
6
|
+
@query_parameters = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def namespace
|
10
|
+
@namespace || 'default'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Чтобы не перегружать методы явной передачей namespace.
|
14
|
+
# Данный метод может пригодиться только в ситуации, когда надо указать другой namespace,
|
15
|
+
# в большинстве случаев используется namespace из конструктора.
|
16
|
+
def with_namespace(namespace, &blk)
|
17
|
+
old_namespace = @namespace
|
18
|
+
begin
|
19
|
+
@namespace = namespace
|
20
|
+
return yield
|
21
|
+
ensure
|
22
|
+
@namespace = old_namespace
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def with_query(query, &blk)
|
27
|
+
old_query = @query_parameters
|
28
|
+
begin
|
29
|
+
@query_parameters = query
|
30
|
+
return yield
|
31
|
+
ensure
|
32
|
+
@query_parameters = old_query
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# NOTICE: Название метода аналогично kind'у выдаваемого результата.
|
37
|
+
# NOTICE: В данном случае в результате kind=DeploymentList.
|
38
|
+
# NOTICE: Методы создания/обновления/удаления сущностей kubernetes заканчиваются на '!'. Например, create_deployment!.
|
39
|
+
|
40
|
+
{
|
41
|
+
'/api/v1' => [:service, :replicationcontroller, :pod],
|
42
|
+
'/apis/extensions/v1beta1' => [:deployment, :replicaset],
|
43
|
+
'/apis/batch/v1' => [:job]
|
44
|
+
}.each do |api, objects|
|
45
|
+
objects.each do |object|
|
46
|
+
define_method :"#{object}_list" do |**query_parameters|
|
47
|
+
request!(:get, "#{api}/namespaces/#{namespace}/#{object}s", **query_parameters)
|
48
|
+
end
|
49
|
+
|
50
|
+
define_method object do |name, **query_parameters|
|
51
|
+
request!(:get, "#{api}/namespaces/#{namespace}/#{object}s/#{name}", **query_parameters)
|
52
|
+
end
|
53
|
+
|
54
|
+
define_method "#{object}_status" do |name, **query_parameters|
|
55
|
+
request!(:get, "#{api}/namespaces/#{namespace}/#{object}s/#{name}/status", **query_parameters)
|
56
|
+
end
|
57
|
+
|
58
|
+
define_method :"create_#{object}!" do |spec, **query_parameters|
|
59
|
+
request!(:post, "#{api}/namespaces/#{namespace}/#{object}s", body: spec, **query_parameters)
|
60
|
+
end
|
61
|
+
|
62
|
+
define_method :"replace_#{object}!" do |name, spec, **query_parameters|
|
63
|
+
request!(:put, "#{api}/namespaces/#{namespace}/#{object}s/#{name}", body: spec, **query_parameters)
|
64
|
+
end
|
65
|
+
|
66
|
+
define_method :"delete_#{object}!" do |name, **query_parameters|
|
67
|
+
request!(:delete, "#{api}/namespaces/#{namespace}/#{object}s/#{name}", **query_parameters)
|
68
|
+
end
|
69
|
+
|
70
|
+
define_method :"delete_#{object}s!" do |**query_parameters|
|
71
|
+
request!(:delete, "#{api}/namespaces/#{namespace}/#{object}s", **query_parameters)
|
72
|
+
end
|
73
|
+
|
74
|
+
define_method :"#{object}?" do |name, **query_parameters|
|
75
|
+
public_send(:"#{object}_list", **query_parameters)['items'].map { |item| item['metadata']['name'] }.include?(name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def namespace_list(**query_parameters)
|
81
|
+
request!(:get, '/api/v1/namespaces', **query_parameters)
|
82
|
+
end
|
83
|
+
|
84
|
+
def namespace?(name, **query_parameters)
|
85
|
+
namespace_list(**query_parameters)['items'].map { |item| item['metadata']['name'] }.include?(name)
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_namespace!(name, **query_parameters)
|
89
|
+
request!(:post, '/api/v1/namespaces', body: { metadata: { name: name } }, **query_parameters)
|
90
|
+
end
|
91
|
+
|
92
|
+
def delete_namespace!(name, **query_parameters)
|
93
|
+
request!(:delete, "/api/v1/namespaces/#{name}", **query_parameters)
|
94
|
+
end
|
95
|
+
|
96
|
+
def pod_log(name, follow: false, **query_parameters, &blk)
|
97
|
+
excon_parameters = follow ? { response_block: blk } : {}
|
98
|
+
request!(:get,
|
99
|
+
"/api/v1/namespaces/#{namespace}/pods/#{name}/log",
|
100
|
+
excon_parameters: excon_parameters,
|
101
|
+
**{ follow: follow }.merge(query_parameters))
|
102
|
+
rescue Excon::Error::Timeout
|
103
|
+
raise Error::Timeout
|
104
|
+
end
|
105
|
+
|
106
|
+
def event_list(**query_parameters)
|
107
|
+
request!(:get, "/api/v1/namespaces/#{namespace}/events", **query_parameters)
|
108
|
+
end
|
109
|
+
|
110
|
+
protected
|
111
|
+
|
112
|
+
# query_parameters — соответствует 'Query Parameters' в документации kubernetes
|
113
|
+
# excon_parameters — соответствует опциям Excon
|
114
|
+
# body — hash для http-body, соответствует 'Body Parameters' в документации kubernetes, опционален
|
115
|
+
def request!(method, path, body: nil, excon_parameters: {}, **query_parameters)
|
116
|
+
with_connection(excon_parameters: excon_parameters) do |conn|
|
117
|
+
request_parameters = {method: method, path: path, query: @query_parameters.merge(query_parameters)}
|
118
|
+
request_parameters[:body] = JSON.dump(body) if body
|
119
|
+
load_body! conn.request(request_parameters), request_parameters
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def load_body!(response, request_parameters)
|
124
|
+
response_ok = response.status.to_s.start_with? '2'
|
125
|
+
|
126
|
+
if response_ok
|
127
|
+
JSON.parse(response.body)
|
128
|
+
else
|
129
|
+
err_data = {}
|
130
|
+
err_data[:response_http_status] = response.status
|
131
|
+
if response_body = (JSON.parse(response.body) rescue nil)
|
132
|
+
err_data[:response_body] = response_body
|
133
|
+
else
|
134
|
+
err_data[:response_raw_body] = response.body
|
135
|
+
end
|
136
|
+
err_data[:request_parameters] = request_parameters
|
137
|
+
|
138
|
+
if response.status.to_s.start_with? '5'
|
139
|
+
raise Error::Base, code: :server_error, data: err_data
|
140
|
+
elsif response.status.to_s == '404'
|
141
|
+
raise Error::NotFound, data: err_data
|
142
|
+
else not response.status.to_s.start_with? '2'
|
143
|
+
raise Error::Base, code: :bad_request, data: err_data
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def with_connection(excon_parameters: {}, &blk)
|
149
|
+
old_ssl_ca_file = Excon.defaults[:ssl_ca_file]
|
150
|
+
old_middlewares = Excon.defaults[:middlewares].dup
|
151
|
+
|
152
|
+
begin
|
153
|
+
Excon.defaults[:ssl_ca_file] = kube_config.fetch('clusters', [{}]).first.fetch('cluster', {}).fetch('certificate-authority', nil)
|
154
|
+
Excon.defaults[:middlewares] << Excon::Middleware::RedirectFollower
|
155
|
+
|
156
|
+
return yield Excon.new(kube_server_url, **kube_server_options(excon_parameters))
|
157
|
+
ensure
|
158
|
+
Excon.defaults[:ssl_ca_file] = old_ssl_ca_file
|
159
|
+
Excon.defaults[:middlewares] = old_middlewares
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def kube_server_url
|
164
|
+
@kube_server_url ||= begin
|
165
|
+
kube_config.fetch('clusters', [{}]).first.fetch('cluster', {}).fetch('server', nil).tap do |url|
|
166
|
+
begin
|
167
|
+
Excon.new(url, **kube_server_options).get
|
168
|
+
rescue Excon::Error::Socket
|
169
|
+
raise Error::ConnectionRefused, code: :kube_server_connection_refused, data: { url: url }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def kube_server_options(excon_parameters = {})
|
176
|
+
{ client_cert: kube_config.fetch('users', [{}]).first.fetch('user', {}).fetch('client-certificate', nil),
|
177
|
+
client_key: kube_config.fetch('users', [{}]).first.fetch('user', {}).fetch('client-key', nil) }.merge(excon_parameters)
|
178
|
+
end
|
179
|
+
|
180
|
+
def kube_config
|
181
|
+
@kube_config ||= begin
|
182
|
+
if File.exist?((kube_config_path = File.join(ENV['HOME'], '.kube/config')))
|
183
|
+
YAML.load_file(kube_config_path)
|
184
|
+
else
|
185
|
+
raise Error::Base, code: :kube_config_not_found, data: { path: kube_config_path }
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|