dapp 0.11.0 → 0.12.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.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/config/en/net_status.yml +36 -4
  3. data/lib/dapp.rb +84 -36
  4. data/lib/dapp/cli.rb +3 -2
  5. data/lib/dapp/cli/command/base.rb +69 -0
  6. data/lib/dapp/config/config.rb +17 -0
  7. data/lib/dapp/config/directive/base.rb +90 -3
  8. data/lib/dapp/dapp.rb +6 -14
  9. data/lib/dapp/dapp/dappfile.rb +20 -27
  10. data/lib/dapp/dapp/deps/base.rb +2 -2
  11. data/lib/dapp/dapp/lock.rb +1 -1
  12. data/lib/dapp/dapp/logging/base.rb +11 -7
  13. data/lib/dapp/dapp/logging/process.rb +4 -2
  14. data/lib/dapp/dapp/shellout/base.rb +2 -2
  15. data/lib/dapp/dapp/ssh_agent.rb +2 -2
  16. data/lib/dapp/deployment.rb +1 -0
  17. data/lib/dapp/deployment/app.rb +120 -0
  18. data/lib/dapp/deployment/cli/cli.rb +1 -0
  19. data/lib/dapp/deployment/cli/command/base.rb +14 -0
  20. data/lib/dapp/deployment/cli/command/deployment.rb +21 -0
  21. data/lib/dapp/deployment/cli/command/deployment/apply.rb +26 -0
  22. data/lib/dapp/deployment/cli/command/deployment/minikube_setup.rb +13 -0
  23. data/lib/dapp/deployment/cli/command/deployment/mrproper.rb +13 -0
  24. data/lib/dapp/deployment/cli/command/deployment/secret_generate.rb +13 -0
  25. data/lib/dapp/deployment/cli/command/deployment/secret_key_generate.rb +13 -0
  26. data/lib/dapp/deployment/config/config.rb +46 -0
  27. data/lib/dapp/deployment/config/directive/app.rb +28 -0
  28. data/lib/dapp/deployment/config/directive/app/instance_methods.rb +51 -0
  29. data/lib/dapp/deployment/config/directive/base.rb +13 -0
  30. data/lib/dapp/deployment/config/directive/deployment.rb +11 -0
  31. data/lib/dapp/deployment/config/directive/expose.rb +68 -0
  32. data/lib/dapp/deployment/config/directive/group.rb +27 -0
  33. data/lib/dapp/deployment/config/directive/job.rb +28 -0
  34. data/lib/dapp/deployment/config/directive/mod/group.rb +22 -0
  35. data/lib/dapp/deployment/config/directive/mod/jobs.rb +26 -0
  36. data/lib/dapp/deployment/config/directive/namespace.rb +26 -0
  37. data/lib/dapp/deployment/config/directive/namespace/instance_methods.rb +37 -0
  38. data/lib/dapp/deployment/core_ext/hash.rb +19 -0
  39. data/lib/dapp/deployment/dapp/command/apply.rb +83 -0
  40. data/lib/dapp/deployment/dapp/command/common.rb +17 -0
  41. data/lib/dapp/deployment/dapp/command/minikube_setup.rb +393 -0
  42. data/lib/dapp/deployment/dapp/command/mrproper.rb +12 -0
  43. data/lib/dapp/deployment/dapp/command/secret_generate.rb +17 -0
  44. data/lib/dapp/deployment/dapp/command/secret_key_generate.rb +13 -0
  45. data/lib/dapp/deployment/dapp/dapp.rb +18 -0
  46. data/lib/dapp/deployment/dapp/dappfile.rb +23 -0
  47. data/lib/dapp/deployment/deployment.rb +46 -0
  48. data/lib/dapp/deployment/error/app.rb +7 -0
  49. data/lib/dapp/deployment/error/base.rb +7 -0
  50. data/lib/dapp/deployment/error/command.rb +7 -0
  51. data/lib/dapp/deployment/error/config.rb +7 -0
  52. data/lib/dapp/deployment/error/deployment.rb +7 -0
  53. data/lib/dapp/deployment/error/kubernetes.rb +7 -0
  54. data/lib/dapp/deployment/kube_app.rb +277 -0
  55. data/lib/dapp/deployment/kube_base.rb +97 -0
  56. data/lib/dapp/deployment/kube_deployment.rb +51 -0
  57. data/lib/dapp/deployment/kubernetes.rb +174 -0
  58. data/lib/dapp/deployment/kubernetes/error.rb +20 -0
  59. data/lib/dapp/deployment/mod/jobs.rb +37 -0
  60. data/lib/dapp/deployment/mod/namespace.rb +58 -0
  61. data/lib/dapp/deployment/mod/system_environments.rb +30 -0
  62. data/lib/dapp/deployment/secret.rb +93 -0
  63. data/lib/dapp/dimg/artifact.rb +1 -1
  64. data/lib/dapp/dimg/build/stage/artifact_default.rb +35 -23
  65. data/lib/dapp/dimg/build/stage/base.rb +1 -1
  66. data/lib/dapp/dimg/build/stage/before_setup.rb +0 -2
  67. data/lib/dapp/dimg/build/stage/build_artifact.rb +0 -2
  68. data/lib/dapp/dimg/build/stage/ga_latest_patch.rb +2 -2
  69. data/lib/dapp/dimg/build/stage/install/install.rb +0 -1
  70. data/lib/dapp/dimg/build/stage/setup/setup.rb +0 -1
  71. data/lib/dapp/dimg/cli/cli.rb +1 -1
  72. data/lib/dapp/dimg/cli/command/base.rb +14 -0
  73. data/lib/dapp/dimg/cli/{dimg.rb → command/dimg.rb} +5 -7
  74. data/lib/dapp/dimg/cli/{bp.rb → command/dimg/bp.rb} +3 -3
  75. data/lib/dapp/dimg/cli/{build.rb → command/dimg/build.rb} +3 -3
  76. data/lib/dapp/dimg/cli/{build_context.rb → command/dimg/build_context.rb} +3 -3
  77. data/lib/dapp/dimg/cli/{build_context → command/dimg/build_context}/export.rb +4 -4
  78. data/lib/dapp/dimg/cli/{build_context → command/dimg/build_context}/import.rb +4 -4
  79. data/lib/dapp/dimg/cli/{cleanup.rb → command/dimg/cleanup.rb} +3 -3
  80. data/lib/dapp/dimg/cli/{list.rb → command/dimg/list.rb} +3 -3
  81. data/lib/dapp/dimg/cli/{mrproper.rb → command/dimg/mrproper.rb} +4 -4
  82. data/lib/dapp/dimg/cli/{push.rb → command/dimg/push.rb} +5 -5
  83. data/lib/dapp/dimg/cli/{run.rb → command/dimg/run.rb} +8 -8
  84. data/lib/dapp/dimg/cli/{spush.rb → command/dimg/spush.rb} +4 -4
  85. data/lib/dapp/dimg/cli/{stage_image.rb → command/dimg/stage_image.rb} +3 -3
  86. data/lib/dapp/dimg/cli/{stages.rb → command/dimg/stages.rb} +3 -3
  87. data/lib/dapp/dimg/cli/{stages → command/dimg/stages}/cleanup_local.rb +6 -6
  88. data/lib/dapp/dimg/cli/{stages → command/dimg/stages}/cleanup_repo.rb +5 -5
  89. data/lib/dapp/dimg/cli/{stages → command/dimg/stages}/flush_local.rb +5 -5
  90. data/lib/dapp/dimg/cli/{stages → command/dimg/stages}/flush_repo.rb +6 -6
  91. data/lib/dapp/dimg/cli/{stages → command/dimg/stages}/pull.rb +6 -6
  92. data/lib/dapp/dimg/cli/{stages → command/dimg/stages}/push.rb +6 -6
  93. data/lib/dapp/dimg/cli/{tag.rb → command/dimg/tag.rb} +6 -6
  94. data/lib/dapp/dimg/config/config.rb +20 -0
  95. data/lib/dapp/dimg/config/directive/artifact_dimg.rb +19 -0
  96. data/lib/dapp/dimg/config/directive/artifact_group.rb +45 -0
  97. data/lib/dapp/dimg/config/directive/dimg.rb +36 -0
  98. data/lib/dapp/dimg/config/directive/dimg/instance_methods.rb +149 -0
  99. data/lib/dapp/dimg/config/directive/dimg/validation.rb +128 -0
  100. data/lib/dapp/dimg/config/directive/dimg_group.rb +64 -0
  101. data/lib/dapp/dimg/config/directive/dimg_group_base.rb +46 -0
  102. data/lib/dapp/dimg/config/directive/docker/dimg.rb +4 -4
  103. data/lib/dapp/dimg/config/directive/shell/dimg.rb +1 -1
  104. data/lib/dapp/dimg/dapp/command/bp.rb +4 -4
  105. data/lib/dapp/dimg/dapp/command/build.rb +2 -2
  106. data/lib/dapp/dimg/dapp/command/build_context/common.rb +2 -2
  107. data/lib/dapp/dimg/dapp/command/build_context/export.rb +1 -1
  108. data/lib/dapp/dimg/dapp/command/build_context/import.rb +1 -1
  109. data/lib/dapp/dimg/dapp/command/cleanup.rb +1 -1
  110. data/lib/dapp/dimg/dapp/command/common.rb +19 -4
  111. data/lib/dapp/dimg/dapp/command/list.rb +1 -1
  112. data/lib/dapp/dimg/dapp/command/mrproper.rb +3 -3
  113. data/lib/dapp/dimg/dapp/command/push.rb +6 -5
  114. data/lib/dapp/dimg/dapp/command/run.rb +1 -1
  115. data/lib/dapp/dimg/dapp/command/spush.rb +4 -3
  116. data/lib/dapp/dimg/dapp/command/stage_image.rb +2 -2
  117. data/lib/dapp/dimg/dapp/command/stages/cleanup_local.rb +1 -1
  118. data/lib/dapp/dimg/dapp/command/stages/cleanup_repo.rb +3 -3
  119. data/lib/dapp/dimg/dapp/command/stages/common.rb +4 -4
  120. data/lib/dapp/dimg/dapp/command/stages/flush_local.rb +1 -1
  121. data/lib/dapp/dimg/dapp/command/stages/flush_repo.rb +1 -1
  122. data/lib/dapp/dimg/dapp/command/stages/pull.rb +5 -4
  123. data/lib/dapp/dimg/dapp/command/stages/push.rb +4 -3
  124. data/lib/dapp/dimg/dapp/command/tag.rb +3 -2
  125. data/lib/dapp/dimg/dapp/dapp.rb +33 -0
  126. data/lib/dapp/dimg/dapp/dappfile.rb +25 -0
  127. data/lib/dapp/dimg/dimg.rb +3 -3
  128. data/lib/dapp/dimg/dimg/path.rb +1 -1
  129. data/lib/dapp/dimg/dimg/stages.rb +1 -1
  130. data/lib/dapp/dimg/dimg/tags.rb +5 -5
  131. data/lib/dapp/dimg/docker_registry.rb +3 -7
  132. data/lib/dapp/dimg/git_artifact.rb +30 -14
  133. data/lib/dapp/dimg/git_repo/base.rb +13 -1
  134. data/lib/dapp/dimg/git_repo/own.rb +9 -1
  135. data/lib/dapp/dimg/image/docker.rb +9 -3
  136. data/lib/dapp/helper/cli.rb +3 -1
  137. data/lib/dapp/helper/net_status.rb +5 -1
  138. data/lib/dapp/helper/trivia.rb +1 -1
  139. data/lib/dapp/version.rb +2 -2
  140. metadata +84 -38
  141. data/lib/dapp/cli/base.rb +0 -63
  142. data/lib/dapp/config/base.rb +0 -54
  143. data/lib/dapp/dimg/build/stage/mod/git_artifact_dependencies.rb +0 -23
  144. data/lib/dapp/dimg/cli/base.rb +0 -16
  145. data/lib/dapp/dimg/config/artifact_dimg.rb +0 -17
  146. data/lib/dapp/dimg/config/artifact_group.rb +0 -43
  147. data/lib/dapp/dimg/config/base.rb +0 -7
  148. data/lib/dapp/dimg/config/dimg.rb +0 -24
  149. data/lib/dapp/dimg/config/dimg/instance_methods.rb +0 -179
  150. data/lib/dapp/dimg/config/dimg/validation.rb +0 -126
  151. data/lib/dapp/dimg/config/dimg_group.rb +0 -61
  152. data/lib/dapp/dimg/config/dimg_group_base.rb +0 -54
  153. data/lib/dapp/dimg/config/dimg_group_main.rb +0 -22
  154. data/lib/dapp/dimg/dapp/command.rb +0 -21
@@ -0,0 +1,97 @@
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, verbose: true) 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
@@ -0,0 +1,51 @@
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
@@ -0,0 +1,174 @@
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::Base, 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::Base, 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::Base, code: :kube_config_not_found, data: { path: kube_config_path }
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,20 @@
1
+ module Dapp
2
+ module Deployment
3
+ module Kubernetes::Error
4
+ class Base < ::Dapp::Deployment::Error::Kubernetes
5
+ def initialize(**net_status)
6
+ super(**net_status, context: :kubernetes)
7
+ end
8
+ end
9
+
10
+ class NotFound < Base
11
+ def initialize(**net_status)
12
+ super({code: :not_found}.merge(net_status))
13
+ end
14
+ end
15
+
16
+ class Timeout < Base; end
17
+ class ConnectionRefused < Base; end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ module Dapp
2
+ module Deployment
3
+ module Mod
4
+ module Jobs
5
+ [:bootstrap, :before_apply_job].each do |job|
6
+ define_method :"to_kube_#{job}_pods" do |repo, image_version|
7
+ to_kube_default_job_pods(job, repo, image_version)
8
+ end
9
+ end
10
+
11
+ def to_kube_default_job_pods(directive, repo, image_version)
12
+ return {} if (directive_config = config.public_send("_#{directive}")).empty?
13
+ {}.tap do |hash|
14
+ hash[name(directive)] = {}.tap do |pod|
15
+ pod['metadata'] = {}.tap do |metadata|
16
+ metadata['name'] = name(directive)
17
+ metadata['labels'] = kube.labels
18
+ end
19
+ pod['spec'] = {}.tap do |spec|
20
+ spec['restartPolicy'] = 'Never'
21
+ spec['containers'] = [].tap do |containers|
22
+ containers << {}.tap do |container|
23
+ container['imagePullPolicy'] = 'Always'
24
+ container['image'] = [repo, [directive_config._dimg || config._dimg, image_version].compact.join('-')].join(':')
25
+ container['name'] = name(directive)
26
+ container['command'] = directive_config._run unless directive_config._run.empty?
27
+ container['env'] = environments unless environments.empty?
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,58 @@
1
+ module Dapp
2
+ module Deployment
3
+ module Mod
4
+ module Namespace
5
+ def environment
6
+ config._environment
7
+ .merge(namespace_config_directive(:_environment) || {})
8
+ .merge(system_environments)
9
+ end
10
+
11
+ def secret_environment
12
+ return {} if secret.nil?
13
+ config._secret_environment
14
+ .merge(namespace_config_directive(:_secret_environment) || {})
15
+ .each_with_object({}) { |(k, v), environments| environments[k] = secret.extract(v) }
16
+ end
17
+
18
+ def environments
19
+ [environment, secret_environment]
20
+ .select { |env| !env.empty? }
21
+ .map { |h| h.map { |k, v| { 'name' => k.to_s, 'value' => v.to_s } } }
22
+ .flatten
23
+ end
24
+
25
+ def scale
26
+ namespace_config_directive(:_scale) || config._scale || 1
27
+ end
28
+
29
+ def namespace_config_directive(name)
30
+ return if namespace_config.nil?
31
+ namespace_config.send(name)
32
+ end
33
+
34
+ def namespace_config
35
+ @namespace_config = begin
36
+ error_class = Error.const_get(self.class.name.to_s.split('::').last)
37
+ if config._namespace.include?(namespace)
38
+ config._namespace[namespace]
39
+ elsif namespace.nil? || namespace == 'default'
40
+ if config._namespace.one?
41
+ config._namespace.values.first
42
+ elsif config._namespace.empty?
43
+ else
44
+ if namespace.nil?
45
+ raise error_class, code: :namespace_not_defined, data: { name: name }
46
+ else
47
+ raise error_class, code: :namespace_not_found, data: { namespace: namespace, name: name }
48
+ end
49
+ end
50
+ else
51
+ raise error_class, code: :namespace_not_found, data: { namespace: namespace, name: name }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ module Dapp
2
+ module Deployment
3
+ module Mod
4
+ module SystemEnvironments
5
+ protected
6
+
7
+ def system_environments
8
+ @system_environments ||= begin
9
+ [namespace_system_env_name_prefix, system_env_name_prefix].each_with_object({}) do |prefix, environments|
10
+ ENV.map do |k, v|
11
+ if k.start_with?(prefix)
12
+ key = k.sub(prefix, '')
13
+ environments[key] = v unless environments.key?(key)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def namespace_system_env_name_prefix
21
+ [system_env_name_prefix, namespace.to_s.tr('-', '_').upcase].join('_')
22
+ end
23
+
24
+ def system_env_name_prefix
25
+ 'DAPP_DEPLOYMENT'
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end