dapp 0.29.2 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +5 -5
  2. data/bin/dapp +1 -23
  3. data/config/en/net_status.yml +5 -4
  4. data/lib/dapp.rb +1 -1
  5. data/lib/dapp/dapp/sentry.rb +11 -8
  6. data/lib/dapp/dimg/dapp/command/cleanup_repo.rb +33 -21
  7. data/lib/dapp/dimg/dimg/git_artifact.rb +2 -5
  8. data/lib/dapp/dimg/git_artifact.rb +41 -23
  9. data/lib/dapp/dimg/git_repo/base.rb +19 -39
  10. data/lib/dapp/dimg/git_repo/local.rb +15 -14
  11. data/lib/dapp/dimg/git_repo/remote.rb +32 -19
  12. data/lib/dapp/kube/cli/command/kube/deploy.rb +4 -0
  13. data/lib/dapp/kube/cli/command/kube/dismiss.rb +4 -0
  14. data/lib/dapp/kube/cli/command/kube/lint.rb +4 -0
  15. data/lib/dapp/kube/cli/command/kube/render.rb +4 -0
  16. data/lib/dapp/kube/cli/command/kube/value_get.rb +4 -0
  17. data/lib/dapp/kube/dapp/command/common.rb +21 -18
  18. data/lib/dapp/kube/dapp/command/minikube_setup.rb +6 -2
  19. data/lib/dapp/kube/helm/release.rb +1 -1
  20. data/lib/dapp/kube/helm/values.rb +3 -3
  21. data/lib/dapp/kube/kubernetes/client.rb +21 -90
  22. data/lib/dapp/kube/kubernetes/config.rb +129 -0
  23. data/lib/dapp/version.rb +1 -1
  24. metadata +6 -44
  25. data/lib/dapp/deployment/app.rb +0 -120
  26. data/lib/dapp/deployment/cli/cli.rb +0 -1
  27. data/lib/dapp/deployment/cli/command/base.rb +0 -14
  28. data/lib/dapp/deployment/cli/command/deployment.rb +0 -18
  29. data/lib/dapp/deployment/cli/command/deployment/apply.rb +0 -26
  30. data/lib/dapp/deployment/cli/command/deployment/mrproper.rb +0 -13
  31. data/lib/dapp/deployment/config/config.rb +0 -46
  32. data/lib/dapp/deployment/config/directive/app.rb +0 -28
  33. data/lib/dapp/deployment/config/directive/app/instance_methods.rb +0 -51
  34. data/lib/dapp/deployment/config/directive/base.rb +0 -13
  35. data/lib/dapp/deployment/config/directive/deployment.rb +0 -11
  36. data/lib/dapp/deployment/config/directive/expose.rb +0 -68
  37. data/lib/dapp/deployment/config/directive/group.rb +0 -27
  38. data/lib/dapp/deployment/config/directive/job.rb +0 -28
  39. data/lib/dapp/deployment/config/directive/mod/group.rb +0 -22
  40. data/lib/dapp/deployment/config/directive/mod/jobs.rb +0 -26
  41. data/lib/dapp/deployment/config/directive/namespace.rb +0 -26
  42. data/lib/dapp/deployment/config/directive/namespace/instance_methods.rb +0 -37
  43. data/lib/dapp/deployment/core_ext/hash.rb +0 -19
  44. data/lib/dapp/deployment/dapp/command/apply.rb +0 -71
  45. data/lib/dapp/deployment/dapp/command/common.rb +0 -17
  46. data/lib/dapp/deployment/dapp/command/mrproper.rb +0 -12
  47. data/lib/dapp/deployment/dapp/dapp.rb +0 -15
  48. data/lib/dapp/deployment/dapp/dappfile.rb +0 -23
  49. data/lib/dapp/deployment/deployment.rb +0 -46
  50. data/lib/dapp/deployment/error/app.rb +0 -7
  51. data/lib/dapp/deployment/error/default.rb +0 -7
  52. data/lib/dapp/deployment/error/deployment.rb +0 -7
  53. data/lib/dapp/deployment/error/kubernetes.rb +0 -7
  54. data/lib/dapp/deployment/kube_app.rb +0 -146
  55. data/lib/dapp/deployment/kube_base.rb +0 -97
  56. data/lib/dapp/deployment/kube_deployment.rb +0 -51
  57. data/lib/dapp/deployment/kubernetes.rb +0 -174
  58. data/lib/dapp/deployment/kubernetes/error.rb +0 -20
  59. data/lib/dapp/deployment/mod/jobs.rb +0 -37
  60. data/lib/dapp/deployment/mod/namespace.rb +0 -58
  61. data/lib/dapp/deployment/mod/system_environments.rb +0 -30
  62. data/lib/dapp/deployment/secret.rb +0 -93
  63. data/lib/dapp/kube/error/kubernetes.rb +0 -7
@@ -1,7 +0,0 @@
1
- module Dapp
2
- module Deployment
3
- module Error
4
- class App < Default; end
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Dapp
2
- module Deployment
3
- module Error
4
- class Default < ::Dapp::Error::Default; end
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Dapp
2
- module Deployment
3
- module Error
4
- class Deployment < Default; end
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Dapp
2
- module Deployment
3
- module Error
4
- class Kubernetes < Default; end
5
- end
6
- end
7
- end
@@ -1,146 +0,0 @@
1
- module Dapp
2
- module Deployment
3
- class KubeApp < KubeBase
4
- module Error
5
- class Base < ::Dapp::Deployment::Error::Deployment
6
- def initialize(**net_status)
7
- super(**net_status, context: :kube_app)
8
- end
9
- end
10
- end
11
-
12
- attr_reader :app
13
-
14
- def initialize(app)
15
- @app = app
16
- end
17
-
18
- def deployment
19
- app.deployment
20
- end
21
-
22
- def labels
23
- deployment.kube.labels.merge('dapp-app' => app.name)
24
- end
25
-
26
- [[:deployment, 'Deployment'], [:service, 'Service']].each do |(type, resource_name)|
27
- define_method "#{type}_exist?" do |name|
28
- public_send("existing_#{type}s_names").include?(name)
29
- end
30
-
31
- define_method "existing_#{type}s_names" do
32
- deployment.kubernetes.public_send(:"#{type}_list", labelSelector: labelSelector)['items'].map do |item|
33
- item['metadata']['name']
34
- end
35
- end
36
-
37
- define_method "#{type}_spec_changed?" do |name, spec|
38
- current_spec = deployment.kubernetes.public_send(type, name)
39
- current_spec != send(:"merge_kube_#{type}_spec", current_spec, spec)
40
- end
41
-
42
- define_method "delete_#{type}!" do |*args|
43
- deployment.kubernetes.public_send(:"delete_#{type}!", *args)
44
- end
45
-
46
- define_method "apply_#{type}!" do |name, spec|
47
- if app.kube.send(:"#{type}_exist?", name)
48
- if app.kube.send(:"#{type}_spec_changed?", name, spec)
49
- app.kube.send(:"replace_#{type}!", name, spec)
50
- else
51
- app.deployment.dapp.log_step("Kubernetes #{resource_name} #{name} is up to date")
52
- end
53
- else
54
- app.kube.send(:"create_#{type}!", spec)
55
- end
56
- end
57
- end
58
-
59
- def create_service!(conf_spec)
60
- srv = nil
61
- app.deployment.dapp.log_process("Creating kubernetes Service #{conf_spec['metadata']['name']}") do
62
- srv = app.deployment.kubernetes.create_service!(conf_spec)
63
- end
64
- _dump_service_info srv
65
- end
66
-
67
- def replace_service!(name, conf_spec)
68
- srv = nil
69
- app.deployment.dapp.log_process("Replacing kubernetes Service #{name}") do
70
- old_spec = deployment.kubernetes.service(name)
71
- new_spec = merge_kube_service_spec(old_spec, conf_spec)
72
- srv = app.deployment.kubernetes.replace_service!(name, new_spec)
73
- end
74
- _dump_service_info srv
75
- end
76
-
77
- def _dump_service_info(srv)
78
- app.deployment.dapp.log_info("type: #{srv['spec']['type']}")
79
- app.deployment.dapp.log_info("clusterIP: #{srv['spec']['clusterIP']}")
80
-
81
- srv['spec'].fetch('ports', []).each do |port|
82
- app.deployment.dapp.log_info("Port #{port['port']}:")
83
- app.deployment.dapp.with_log_indent do
84
- %w(protocol targetPort nodePort).each do |field_name|
85
- app.deployment.dapp.log_info("#{field_name}: #{_field_value_for_log(port[field_name])}")
86
- end
87
- end
88
- end
89
- end
90
-
91
- def create_deployment!(conf_spec)
92
- d = nil
93
- app.deployment.dapp.log_process("Creating kubernetes Deployment #{conf_spec['metadata']['name']}") do
94
- d = app.deployment.kubernetes.create_deployment!(conf_spec)
95
- end
96
- _wait_for_deployment(d)
97
- end
98
-
99
- def replace_deployment!(name, conf_spec)
100
- d = nil
101
- old_d_revision = nil
102
- app.deployment.dapp.log_process("Replacing kubernetes Deployment #{name}") do
103
- old_spec = deployment.kubernetes.deployment(name)
104
- old_d_revision = old_spec.fetch('metadata', {}).fetch('annotations', {}).fetch('deployment.kubernetes.io/revision', nil)
105
- new_spec = merge_kube_deployment_spec(old_spec, conf_spec)
106
- new_spec.fetch('metadata', {}).fetch('annotations', {}).delete('deployment.kubernetes.io/revision')
107
- d = app.deployment.kubernetes.replace_deployment!(name, new_spec)
108
- end
109
- _wait_for_deployment(d, old_d_revision: old_d_revision)
110
- end
111
-
112
- def _field_value_for_log(value)
113
- value ? value : '-'
114
- end
115
-
116
- def merge_kube_deployment_spec(spec1, spec2)
117
- merge_kube_controller_spec(spec1, spec2)
118
- end
119
-
120
- def merge_kube_service_spec(spec1, spec2)
121
- spec1.kube_in_depth_merge(spec2).tap do |spec|
122
- spec['metadata'] ||= {}
123
- metadata_labels = spec2.fetch('metadata', {}).fetch('labels', nil)
124
- spec['metadata']['labels'] = metadata_labels if metadata_labels
125
-
126
- spec['spec'] ||= {}
127
- spec_selector = spec2.fetch('spec', {}).fetch('selector', nil)
128
- spec['spec']['selector'] = spec_selector if spec_selector
129
- spec['spec']['ports'] = begin
130
- ports1 = spec1.fetch('spec', {}).fetch('ports', [])
131
- ports2 = spec2.fetch('spec', {}).fetch('ports', [])
132
- ports2.map do |port2|
133
- if (port1 = ports1.find { |p| p['name'] == port2['name'] }).nil?
134
- port2
135
- else
136
- port = port1.merge(port2)
137
- port.delete('nodePort') if spec['spec']['type'] == 'ClusterIP'
138
- port
139
- end
140
- end
141
- end
142
- end
143
- end
144
- end
145
- end
146
- end
@@ -1,97 +0,0 @@
1
- module Dapp
2
- module Deployment
3
- class KubeBase
4
- def pod_exist?(name)
5
- deployment.kubernetes.pod?(name, labelSelector: labelSelector)
6
- end
7
-
8
- def pod_succeeded?(name)
9
- return false unless pod_exist?(name)
10
- deployment.kubernetes.pod_status(name)['status']['phase'] == 'Succeeded'
11
- end
12
-
13
- def delete_pod!(name)
14
- deployment.kubernetes.delete_pod!(name)
15
- loop do
16
- break unless deployment.kubernetes.pod?(name)
17
- sleep 1
18
- end
19
- end
20
-
21
- def run_job!(spec, name)
22
- current_spec = deployment.kubernetes.create_pod!(spec)
23
-
24
- deployment.dapp.log_process(:pending) do
25
- loop do
26
- current_spec = deployment.kubernetes.pod_status(name)
27
- break if current_spec['status']['phase'] != 'Pending'
28
- unless current_spec['status']['containerStatuses'].nil?
29
- current_spec['status']['containerStatuses'].first['state'].each do |_, desc|
30
- if ['ErrImagePull', 'ImagePullBackOff'].include? desc['reason']
31
- raise Error::Deployment,
32
- code: :bootstrap_image_not_found,
33
- data: { reason: desc['reason'], message: desc['message'] }
34
- end
35
- end
36
- end
37
- sleep 1
38
- end
39
- end
40
-
41
- deployment.dapp.log_process(:running) do
42
- log_thread = Thread.new do
43
- begin
44
- deployment.kubernetes.pod_log(name, follow: true) { |chunk| puts chunk }
45
- rescue Kubernetes::Error::Timeout
46
- deployment.dapp.log_warning('Pod log: read timeout reached!')
47
- end
48
- end
49
-
50
- loop do
51
- current_spec = deployment.kubernetes.pod_status(name)
52
- break if current_spec['status']['phase'] != 'Running'
53
- sleep 1
54
- end
55
-
56
- sleep 1 # last chance to get a message
57
- log_thread.kill if log_thread.alive?
58
-
59
- phase = current_spec['status']['phase']
60
- if phase == 'Failed'
61
- current_spec['status']['containerStatuses'].first['state'].each do |status, desc|
62
- next if status == 'running'
63
- raise Error::Deployment,
64
- code: :bootstrap_command_failed,
65
- data: { reason: desc['reason'], message: desc['message'], exit_code: desc['exitCode'] }
66
- end
67
- end
68
- raise Error::Deployment,
69
- code: :bootstrap_failed,
70
- data: { phase: phase, message: current_spec['status']['message'] } unless phase == 'Succeeded'
71
- end
72
- end
73
-
74
- def merge_kube_controller_spec(spec1, spec2)
75
- spec1.kube_in_depth_merge(spec2).tap do |spec|
76
- spec['spec']['template']['spec']['containers'] = begin
77
- containers1 = spec1['spec']['template']['spec']['containers']
78
- containers2 = spec2['spec']['template']['spec']['containers']
79
- containers2.map do |container2|
80
- if (container1 = containers1.find { |c| c['name'] == container2['name'] }).nil?
81
- container2
82
- else
83
- container1.kube_in_depth_merge(container2)
84
- end
85
- end
86
- end
87
- end
88
- end
89
-
90
- protected
91
-
92
- def labelSelector
93
- labels.map {|key, value| "#{key}=#{value}"}.join(',')
94
- end
95
- end
96
- end
97
- end
@@ -1,51 +0,0 @@
1
- module Dapp
2
- module Deployment
3
- class KubeDeployment < KubeBase
4
- attr_reader :deployment
5
-
6
- def initialize(deployment)
7
- @deployment = deployment
8
- end
9
-
10
- def labels
11
- {'dapp' => deployment.dapp.name, 'dapp-deployment-version' => 1.to_s}
12
- end
13
-
14
- def delete_unknown_resources!
15
- # Удаление объектов, связанных с несуществующими более app'ами
16
- known_apps_names = deployment.apps.map(&:name)
17
- deployment.kubernetes.deployment_list(labelSelector: labelSelector)['items']
18
- .reject do |item|
19
- known_apps_names.include? item['metadata']['labels']['dapp-app']
20
- end
21
- .each do |item|
22
- deployment.dapp.log "Deleting Deployment '#{item['metadata']['name']}': unknown app '#{item['metadata']['labels']['dapp-app']}'"
23
- deployment.kubernetes.delete_deployment!(item['metadata']['name'])
24
- end
25
- deployment.kubernetes.service_list(labelSelector: labelSelector)['items']
26
- .reject do |item|
27
- known_apps_names.include? item['metadata']['labels']['dapp-app']
28
- end
29
- .each do |item|
30
- deployment.dapp.log "Deleting Service '#{item['metadata']['name']}': unknown app '#{item['metadata']['labels']['dapp-app']}'"
31
- deployment.kubernetes.delete_service!(item['metadata']['name'])
32
- end
33
-
34
- # Версионирование объектов из кода dapp, чтобы
35
- # иметь возможность автоматом удалить объекты,
36
- # созданные по старой логике
37
- old_versions_selector = "dapp=#{labels['dapp']},dapp-deployment-version notin (#{labels['dapp-deployment-version']})"
38
- deployment.kubernetes.deployment_list(labelSelector: old_versions_selector)['items']
39
- .each do |item|
40
- deployment.dapp.log "Deleting Deployment '#{item['metadata']['name']}': dapp-deployment-version changed from #{item['metadata']['labels']['dapp-deployment-version']} to #{labels['dapp-deployment-version']}"
41
- deployment.kubernetes.delete_deployment!(item['metadata']['name'])
42
- end
43
- deployment.kubernetes.service_list(labelSelector: old_versions_selector)['items']
44
- .each do |item|
45
- deployment.dapp.log "Deleting Service '#{item['metadata']['name']}': dapp-deployment-version changed from #{item['metadata']['labels']['dapp-deployment-version']} to #{labels['dapp-deployment-version']}"
46
- deployment.kubernetes.delete_service!(item['metadata']['name'])
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,174 +0,0 @@
1
- module Dapp
2
- module Deployment
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
- }.each do |api, objects|
44
- objects.each do |object|
45
- define_method :"#{object}_list" do |**query_parameters|
46
- request!(:get, "#{api}/namespaces/#{namespace}/#{object}s", **query_parameters)
47
- end
48
-
49
- define_method object do |name, **query_parameters|
50
- request!(:get, "#{api}/namespaces/#{namespace}/#{object}s/#{name}", **query_parameters)
51
- end
52
-
53
- define_method "#{object}_status" do |name, **query_parameters|
54
- request!(:get, "#{api}/namespaces/#{namespace}/#{object}s/#{name}/status", **query_parameters)
55
- end
56
-
57
- define_method :"create_#{object}!" do |spec, **query_parameters|
58
- request!(:post, "#{api}/namespaces/#{namespace}/#{object}s", body: spec, **query_parameters)
59
- end
60
-
61
- define_method :"replace_#{object}!" do |name, spec, **query_parameters|
62
- request!(:put, "#{api}/namespaces/#{namespace}/#{object}s/#{name}", body: spec, **query_parameters)
63
- end
64
-
65
- define_method :"delete_#{object}!" do |name, **query_parameters|
66
- request!(:delete, "#{api}/namespaces/#{namespace}/#{object}s/#{name}", **query_parameters)
67
- end
68
-
69
- define_method :"delete_#{object}s!" do |**query_parameters|
70
- request!(:delete, "#{api}/namespaces/#{namespace}/#{object}s", **query_parameters)
71
- end
72
-
73
- define_method :"#{object}?" do |name, **query_parameters|
74
- public_send(:"#{object}_list", **query_parameters)['items'].map { |item| item['metadata']['name'] }.include?(name)
75
- end
76
- end
77
- end
78
-
79
- def pod_log(name, follow: false, **query_parameters, &blk)
80
- excon_parameters = follow ? { response_block: blk } : {}
81
- request!(:get,
82
- "/api/v1/namespaces/#{namespace}/pods/#{name}/log",
83
- excon_parameters: excon_parameters,
84
- **{ follow: follow }.merge(query_parameters))
85
- rescue Excon::Error::Timeout
86
- raise Error::Timeout
87
- end
88
-
89
- def event_list(**query_parameters)
90
- request!(:get, "/api/v1/namespaces/#{namespace}/events", **query_parameters)
91
- end
92
-
93
- protected
94
-
95
- # query_parameters — соответствует 'Query Parameters' в документации kubernetes
96
- # excon_parameters — соответствует опциям Excon
97
- # body — hash для http-body, соответствует 'Body Parameters' в документации kubernetes, опционален
98
- def request!(method, path, body: nil, excon_parameters: {}, **query_parameters)
99
- with_connection(excon_parameters: excon_parameters) do |conn|
100
- request_parameters = {method: method, path: path, query: @query_parameters.merge(query_parameters)}
101
- request_parameters[:body] = JSON.dump(body) if body
102
- load_body! conn.request(request_parameters), request_parameters
103
- end
104
- end
105
-
106
- def load_body!(response, request_parameters)
107
- response_ok = response.status.to_s.start_with? '2'
108
-
109
- if response_ok
110
- JSON.parse(response.body)
111
- else
112
- err_data = {}
113
- err_data[:response_http_status] = response.status
114
- if response_body = (JSON.parse(response.body) rescue nil)
115
- err_data[:response_body] = response_body
116
- else
117
- err_data[:response_raw_body] = response.body
118
- end
119
- err_data[:request_parameters] = request_parameters
120
-
121
- if response.status.to_s.start_with? '5'
122
- raise Error::Default, code: :server_error, data: err_data
123
- elsif response.status.to_s == '404'
124
- raise Error::NotFound, data: err_data
125
- else not response.status.to_s.start_with? '2'
126
- raise Error::Default, code: :bad_request, data: err_data
127
- end
128
- end
129
- end
130
-
131
- def with_connection(excon_parameters: {}, &blk)
132
- old_ssl_ca_file = Excon.defaults[:ssl_ca_file]
133
- old_middlewares = Excon.defaults[:middlewares].dup
134
-
135
- begin
136
- Excon.defaults[:ssl_ca_file] = kube_config.fetch('clusters', [{}]).first.fetch('cluster', {}).fetch('certificate-authority', nil)
137
- Excon.defaults[:middlewares] << Excon::Middleware::RedirectFollower
138
-
139
- return yield Excon.new(kube_server_url, **kube_server_options(excon_parameters))
140
- ensure
141
- Excon.defaults[:ssl_ca_file] = old_ssl_ca_file
142
- Excon.defaults[:middlewares] = old_middlewares
143
- end
144
- end
145
-
146
- def kube_server_url
147
- @kube_server_url ||= begin
148
- kube_config.fetch('clusters', [{}]).first.fetch('cluster', {}).fetch('server', nil).tap do |url|
149
- begin
150
- Excon.new(url, **kube_server_options).get
151
- rescue Excon::Error::Socket
152
- raise Error::ConnectionRefused, code: :kube_server_connection_refused, data: { url: url }
153
- end
154
- end
155
- end
156
- end
157
-
158
- def kube_server_options(excon_parameters = {})
159
- { client_cert: kube_config.fetch('users', [{}]).first.fetch('user', {}).fetch('client-certificate', nil),
160
- client_key: kube_config.fetch('users', [{}]).first.fetch('user', {}).fetch('client-key', nil) }.merge(excon_parameters)
161
- end
162
-
163
- def kube_config
164
- @kube_config ||= begin
165
- if File.exist?((kube_config_path = File.join(ENV['HOME'], '.kube/config')))
166
- yaml_load_file(kube_config_path)
167
- else
168
- raise Error::Default, code: :kube_config_not_found, data: { path: kube_config_path }
169
- end
170
- end
171
- end
172
- end
173
- end
174
- end