uffizzi_core 0.1.3

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 (240) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/README.md +46 -0
  4. data/Rakefile +31 -0
  5. data/app/assets/config/uffizzi_core_manifest.js +1 -0
  6. data/app/assets/stylesheets/uffizzi_core/application.css +15 -0
  7. data/app/clients/uffizzi_core/amazon_registry_client.rb +18 -0
  8. data/app/clients/uffizzi_core/azure_registry_client/request_result.rb +5 -0
  9. data/app/clients/uffizzi_core/azure_registry_client.rb +42 -0
  10. data/app/clients/uffizzi_core/controller_client/request_result.rb +5 -0
  11. data/app/clients/uffizzi_core/controller_client.rb +106 -0
  12. data/app/clients/uffizzi_core/docker_hub_client/request_result.rb +7 -0
  13. data/app/clients/uffizzi_core/docker_hub_client.rb +139 -0
  14. data/app/clients/uffizzi_core/github/app_client.rb +19 -0
  15. data/app/clients/uffizzi_core/github/installation_client.rb +11 -0
  16. data/app/clients/uffizzi_core/github/user_client.rb +51 -0
  17. data/app/clients/uffizzi_core/google_registry_client/request_result.rb +5 -0
  18. data/app/clients/uffizzi_core/google_registry_client.rb +42 -0
  19. data/app/contexts/uffizzi_core/base_context.rb +12 -0
  20. data/app/contexts/uffizzi_core/project_context.rb +13 -0
  21. data/app/contexts/uffizzi_core/webhooks_context.rb +9 -0
  22. data/app/controllers/concerns/uffizzi_core/auth_management.rb +23 -0
  23. data/app/controllers/concerns/uffizzi_core/authorization_concern.rb +38 -0
  24. data/app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb +19 -0
  25. data/app/controllers/uffizzi_core/api/cli/v1/account/application_controller.rb +7 -0
  26. data/app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb +55 -0
  27. data/app/controllers/uffizzi_core/api/cli/v1/application_controller.rb +5 -0
  28. data/app/controllers/uffizzi_core/api/cli/v1/projects/application_controller.rb +11 -0
  29. data/app/controllers/uffizzi_core/api/cli/v1/projects/compose_files_controller.rb +93 -0
  30. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/activity_items_controller.rb +36 -0
  31. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/application_controller.rb +7 -0
  32. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers/application_controller.rb +8 -0
  33. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers/logs_controller.rb +27 -0
  34. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers_controller.rb +24 -0
  35. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/events_controller.rb +29 -0
  36. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments_controller.rb +148 -0
  37. data/app/controllers/uffizzi_core/api/cli/v1/projects/secrets_controller.rb +69 -0
  38. data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +19 -0
  39. data/app/controllers/uffizzi_core/api/cli/v1/sessions_controller.rb +43 -0
  40. data/app/controllers/uffizzi_core/application_controller.rb +51 -0
  41. data/app/errors/uffizzi_core/compose_file/build_error.rb +4 -0
  42. data/app/errors/uffizzi_core/compose_file/credential_error.rb +4 -0
  43. data/app/errors/uffizzi_core/compose_file/not_found_error.rb +4 -0
  44. data/app/errors/uffizzi_core/compose_file/parse_error.rb +4 -0
  45. data/app/errors/uffizzi_core/compose_file/secrets_error.rb +4 -0
  46. data/app/errors/uffizzi_core/deployment_not_found_error.rb +10 -0
  47. data/app/forms/uffizzi_core/api/cli/v1/account/credential/create_form.rb +26 -0
  48. data/app/forms/uffizzi_core/api/cli/v1/compose_file/check_credentials_form.rb +21 -0
  49. data/app/forms/uffizzi_core/api/cli/v1/compose_file/cli_form.rb +39 -0
  50. data/app/forms/uffizzi_core/api/cli/v1/compose_file/create_form.rb +13 -0
  51. data/app/forms/uffizzi_core/api/cli/v1/compose_file/template_form.rb +44 -0
  52. data/app/forms/uffizzi_core/api/cli/v1/compose_file/update_form.rb +9 -0
  53. data/app/forms/uffizzi_core/api/cli/v1/config_file/create_form.rb +11 -0
  54. data/app/forms/uffizzi_core/api/cli/v1/deployment/create_form.rb +91 -0
  55. data/app/forms/uffizzi_core/api/cli/v1/project/delete_secret_form.rb +27 -0
  56. data/app/forms/uffizzi_core/api/cli/v1/project/update_form.rb +40 -0
  57. data/app/forms/uffizzi_core/api/cli/v1/session_create_form.rb +29 -0
  58. data/app/forms/uffizzi_core/api/cli/v1/template/create_form.rb +65 -0
  59. data/app/forms/uffizzi_core/application_form.rb +11 -0
  60. data/app/forms/uffizzi_core/application_form_without_active_record.rb +17 -0
  61. data/app/forms/uffizzi_core/mass_assignment_control_concern.rb +22 -0
  62. data/app/helpers/uffizzi_core/application_helper.rb +6 -0
  63. data/app/jobs/uffizzi_core/account/create_credential_job.rb +10 -0
  64. data/app/jobs/uffizzi_core/activity_item/docker/update_digest_job.rb +11 -0
  65. data/app/jobs/uffizzi_core/application_job.rb +7 -0
  66. data/app/jobs/uffizzi_core/config_file/apply_job.rb +31 -0
  67. data/app/jobs/uffizzi_core/credential/docker_hub/create_webhook_job.rb +15 -0
  68. data/app/jobs/uffizzi_core/deployment/create_credential_job.rb +32 -0
  69. data/app/jobs/uffizzi_core/deployment/create_credentials_job.rb +17 -0
  70. data/app/jobs/uffizzi_core/deployment/create_job.rb +15 -0
  71. data/app/jobs/uffizzi_core/deployment/create_webhooks_job.rb +13 -0
  72. data/app/jobs/uffizzi_core/deployment/delete_credential_job.rb +13 -0
  73. data/app/jobs/uffizzi_core/deployment/delete_job.rb +11 -0
  74. data/app/jobs/uffizzi_core/deployment/deploy_containers_job.rb +27 -0
  75. data/app/jobs/uffizzi_core/deployment/manage_deploy_activity_item_job.rb +19 -0
  76. data/app/jobs/uffizzi_core/deployment/send_github_preview_message_job.rb +13 -0
  77. data/app/lib/uffizzi_core/rbac/user_access_service.rb +21 -0
  78. data/app/mailers/uffizzi_core/application_mailer.rb +8 -0
  79. data/app/models/concerns/uffizzi_core/hashid_concern.rb +25 -0
  80. data/app/models/concerns/uffizzi_core/state_machine_concern.rb +16 -0
  81. data/app/models/uffizzi_core/account.rb +101 -0
  82. data/app/models/uffizzi_core/activity_item/docker.rb +4 -0
  83. data/app/models/uffizzi_core/activity_item/github.rb +4 -0
  84. data/app/models/uffizzi_core/activity_item/memory_limit.rb +4 -0
  85. data/app/models/uffizzi_core/activity_item.rb +58 -0
  86. data/app/models/uffizzi_core/application_record.rb +7 -0
  87. data/app/models/uffizzi_core/build.rb +39 -0
  88. data/app/models/uffizzi_core/comment.rb +16 -0
  89. data/app/models/uffizzi_core/compose_file.rb +57 -0
  90. data/app/models/uffizzi_core/config_file.rb +24 -0
  91. data/app/models/uffizzi_core/container.rb +100 -0
  92. data/app/models/uffizzi_core/container_config_file.rb +8 -0
  93. data/app/models/uffizzi_core/continuous_preview.rb +4 -0
  94. data/app/models/uffizzi_core/coupon.rb +5 -0
  95. data/app/models/uffizzi_core/credential/amazon.rb +4 -0
  96. data/app/models/uffizzi_core/credential/azure.rb +4 -0
  97. data/app/models/uffizzi_core/credential/docker_hub.rb +4 -0
  98. data/app/models/uffizzi_core/credential/github.rb +4 -0
  99. data/app/models/uffizzi_core/credential/google.rb +4 -0
  100. data/app/models/uffizzi_core/credential.rb +64 -0
  101. data/app/models/uffizzi_core/database.rb +4 -0
  102. data/app/models/uffizzi_core/database_offering.rb +4 -0
  103. data/app/models/uffizzi_core/deployment.rb +77 -0
  104. data/app/models/uffizzi_core/event.rb +13 -0
  105. data/app/models/uffizzi_core/invitation.rb +27 -0
  106. data/app/models/uffizzi_core/membership.rb +16 -0
  107. data/app/models/uffizzi_core/payment.rb +11 -0
  108. data/app/models/uffizzi_core/price.rb +9 -0
  109. data/app/models/uffizzi_core/product.rb +11 -0
  110. data/app/models/uffizzi_core/project.rb +66 -0
  111. data/app/models/uffizzi_core/rating.rb +20 -0
  112. data/app/models/uffizzi_core/repo/amazon.rb +4 -0
  113. data/app/models/uffizzi_core/repo/azure.rb +4 -0
  114. data/app/models/uffizzi_core/repo/docker_hub.rb +4 -0
  115. data/app/models/uffizzi_core/repo/github.rb +4 -0
  116. data/app/models/uffizzi_core/repo/google.rb +4 -0
  117. data/app/models/uffizzi_core/repo.rb +39 -0
  118. data/app/models/uffizzi_core/role.rb +17 -0
  119. data/app/models/uffizzi_core/template.rb +19 -0
  120. data/app/models/uffizzi_core/user.rb +62 -0
  121. data/app/models/uffizzi_core/user_project.rb +14 -0
  122. data/app/policies/uffizzi_core/api/cli/v1/account/credentials_policy.rb +11 -0
  123. data/app/policies/uffizzi_core/api/cli/v1/projects/compose_files_policy.rb +15 -0
  124. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/activity_items_policy.rb +7 -0
  125. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/containers_policy.rb +7 -0
  126. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/events_policy.rb +7 -0
  127. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments_policy.rb +23 -0
  128. data/app/policies/uffizzi_core/api/cli/v1/projects/secrets_policy.rb +15 -0
  129. data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +7 -0
  130. data/app/policies/uffizzi_core/application_policy.rb +12 -0
  131. data/app/repositories/uffizzi_core/activity_item_repo.rb +9 -0
  132. data/app/repositories/uffizzi_core/basic_order_repo.rb +11 -0
  133. data/app/repositories/uffizzi_core/build_repo.rb +23 -0
  134. data/app/repositories/uffizzi_core/comment_repo.rb +11 -0
  135. data/app/repositories/uffizzi_core/compose_file_repo.rb +11 -0
  136. data/app/repositories/uffizzi_core/config_file_repo.rb +40 -0
  137. data/app/repositories/uffizzi_core/container_repo.rb +25 -0
  138. data/app/repositories/uffizzi_core/credential_repo.rb +36 -0
  139. data/app/repositories/uffizzi_core/deployment_repo.rb +23 -0
  140. data/app/repositories/uffizzi_core/event_repo.rb +9 -0
  141. data/app/repositories/uffizzi_core/membership_repo.rb +10 -0
  142. data/app/repositories/uffizzi_core/price_repo.rb +11 -0
  143. data/app/repositories/uffizzi_core/product_repo.rb +11 -0
  144. data/app/repositories/uffizzi_core/project_repo.rb +10 -0
  145. data/app/repositories/uffizzi_core/repo_repo.rb +10 -0
  146. data/app/repositories/uffizzi_core/template_repo.rb +87 -0
  147. data/app/repositories/uffizzi_core/usage_repo.rb +9 -0
  148. data/app/repositories/uffizzi_core/user_repo.rb +11 -0
  149. data/app/responders/uffizzi_core/json_responder.rb +13 -0
  150. data/app/serializers/uffizzi_core/api/cli/v1/account/credential_serializer.rb +9 -0
  151. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +7 -0
  152. data/app/serializers/uffizzi_core/api/cli/v1/projects/compose_file_serializer.rb +7 -0
  153. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +23 -0
  154. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/user_serializer.rb +11 -0
  155. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer.rb +74 -0
  156. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/activity_item_serializer.rb +24 -0
  157. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer/config_file_serializer.rb +6 -0
  158. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer.rb +7 -0
  159. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer.rb +30 -0
  160. data/app/serializers/uffizzi_core/api/cli/v1/user_serializer/account_serializer.rb +5 -0
  161. data/app/serializers/uffizzi_core/api/cli/v1/user_serializer.rb +7 -0
  162. data/app/serializers/uffizzi_core/base_serializer.rb +7 -0
  163. data/app/serializers/uffizzi_core/controller/create_credential/credential_serializer.rb +17 -0
  164. data/app/serializers/uffizzi_core/controller/create_deployment/deployment_serializer.rb +5 -0
  165. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +53 -0
  166. data/app/serializers/uffizzi_core/controller/deploy_containers/credential_serializer.rb +5 -0
  167. data/app/services/uffizzi_core/account_service.rb +21 -0
  168. data/app/services/uffizzi_core/activity_item_service.rb +98 -0
  169. data/app/services/uffizzi_core/amazon/credential_service.rb +31 -0
  170. data/app/services/uffizzi_core/amazon_service.rb +45 -0
  171. data/app/services/uffizzi_core/azure/credential_service.rb +18 -0
  172. data/app/services/uffizzi_core/cli/compose_file_service.rb +203 -0
  173. data/app/services/uffizzi_core/compose_file/builders/config_files_builder_service.rb +31 -0
  174. data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +225 -0
  175. data/app/services/uffizzi_core/compose_file/builders/docker_repo_builder_service.rb +25 -0
  176. data/app/services/uffizzi_core/compose_file/builders/github_repo_builder_service.rb +59 -0
  177. data/app/services/uffizzi_core/compose_file/builders/template_builder_service.rb +45 -0
  178. data/app/services/uffizzi_core/compose_file/builders/variables_builder_service.rb +58 -0
  179. data/app/services/uffizzi_core/compose_file/config_files_service.rb +52 -0
  180. data/app/services/uffizzi_core/compose_file/config_option_service.rb +37 -0
  181. data/app/services/uffizzi_core/compose_file/configs_options_service.rb +26 -0
  182. data/app/services/uffizzi_core/compose_file/container_service.rb +64 -0
  183. data/app/services/uffizzi_core/compose_file/continuous_preview_options_service.rb +57 -0
  184. data/app/services/uffizzi_core/compose_file/dependencies_service.rb +55 -0
  185. data/app/services/uffizzi_core/compose_file/errors_service.rb +46 -0
  186. data/app/services/uffizzi_core/compose_file/github_dependencies_service.rb +38 -0
  187. data/app/services/uffizzi_core/compose_file/ingress_options_service.rb +49 -0
  188. data/app/services/uffizzi_core/compose_file/secrets_options_service.rb +28 -0
  189. data/app/services/uffizzi_core/compose_file/services_options/build_service.rb +93 -0
  190. data/app/services/uffizzi_core/compose_file/services_options/command_service.rb +18 -0
  191. data/app/services/uffizzi_core/compose_file/services_options/configs_service.rb +51 -0
  192. data/app/services/uffizzi_core/compose_file/services_options/deploy_service.rb +44 -0
  193. data/app/services/uffizzi_core/compose_file/services_options/entrypoint_service.rb +18 -0
  194. data/app/services/uffizzi_core/compose_file/services_options/env_file_service.rb +34 -0
  195. data/app/services/uffizzi_core/compose_file/services_options/environment_service.rb +20 -0
  196. data/app/services/uffizzi_core/compose_file/services_options/image_service.rb +89 -0
  197. data/app/services/uffizzi_core/compose_file/services_options/secrets_service.rb +35 -0
  198. data/app/services/uffizzi_core/compose_file/services_options_service.rb +55 -0
  199. data/app/services/uffizzi_core/compose_file/template_service.rb +55 -0
  200. data/app/services/uffizzi_core/compose_file/update_service.rb +29 -0
  201. data/app/services/uffizzi_core/compose_file/variables_service.rb +25 -0
  202. data/app/services/uffizzi_core/compose_file_service.rb +33 -0
  203. data/app/services/uffizzi_core/container_service.rb +57 -0
  204. data/app/services/uffizzi_core/controller_service.rb +80 -0
  205. data/app/services/uffizzi_core/credential_service.rb +44 -0
  206. data/app/services/uffizzi_core/deployment_service.rb +274 -0
  207. data/app/services/uffizzi_core/docker_hub/credential_service.rb +15 -0
  208. data/app/services/uffizzi_core/docker_hub_service.rb +77 -0
  209. data/app/services/uffizzi_core/github/app_service.rb +51 -0
  210. data/app/services/uffizzi_core/github/credential_service.rb +124 -0
  211. data/app/services/uffizzi_core/github/message_service.rb +20 -0
  212. data/app/services/uffizzi_core/github_service.rb +28 -0
  213. data/app/services/uffizzi_core/google/credential_service.rb +18 -0
  214. data/app/services/uffizzi_core/logs_service.rb +33 -0
  215. data/app/services/uffizzi_core/manage_activity_items_service.rb +166 -0
  216. data/app/services/uffizzi_core/project_service.rb +38 -0
  217. data/app/services/uffizzi_core/repo_service.rb +178 -0
  218. data/app/services/uffizzi_core/response_service.rb +13 -0
  219. data/app/services/uffizzi_core/template_service.rb +21 -0
  220. data/app/services/uffizzi_core/token_service.rb +19 -0
  221. data/app/services/uffizzi_core/user_access_service.rb +14 -0
  222. data/app/utils/uffizzi_core/converters.rb +33 -0
  223. data/app/validators/uffizzi_core/email_validator.rb +9 -0
  224. data/app/validators/uffizzi_core/environment_variable_list_validator.rb +15 -0
  225. data/app/validators/uffizzi_core/image_command_args_validator.rb +21 -0
  226. data/config/initializers/rswag_api.rb +15 -0
  227. data/config/initializers/rswag_ui.rb +15 -0
  228. data/config/initializers/swagger_yard.rb +17 -0
  229. data/config/locales/en.activerecord.yml +18 -0
  230. data/config/locales/en.yml +61 -0
  231. data/config/routes.rb +55 -0
  232. data/db/migrate/20220218121438_create_uffizzi_core_tables.rb +375 -0
  233. data/db/migrate/20220325113342_add_name_to_uffizzi_containers.rb +7 -0
  234. data/db/seeds.rb +16 -0
  235. data/lib/tasks/uffizzi_core_tasks.rake +14 -0
  236. data/lib/uffizzi_core/engine.rb +15 -0
  237. data/lib/uffizzi_core/version.rb +5 -0
  238. data/lib/uffizzi_core.rb +60 -0
  239. data/swagger/v1/swagger.json +1278 -0
  240. metadata +935 -0
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ComposeFile::TemplateService
4
+ def initialize(github_form, project, user)
5
+ @project = project
6
+ @user = user
7
+ @compose_dependencies = github_form.compose_dependencies
8
+ @compose_data = github_form.compose_data
9
+ @compose_repositories = github_form.compose_repositories
10
+ end
11
+
12
+ def create_template(compose_file_form)
13
+ compose_file_template_form = build_compose_file_template_form(compose_file_form)
14
+ return compose_file_template_form.errors if compose_file_template_form.invalid?
15
+
16
+ template_form = build_template_form(compose_file_form, compose_file_template_form)
17
+ return template_form.errors if template_form.invalid?
18
+
19
+ template_form.save
20
+
21
+ nil
22
+ end
23
+
24
+ private
25
+
26
+ def build_compose_file_template_form(compose_file_form)
27
+ credentials = @project.account.credentials
28
+ compose_file_template_form = UffizziCore::Api::Cli::V1::ComposeFile::TemplateForm.new
29
+ compose_file_template_form.compose_data = @compose_data
30
+ compose_file_template_form.source = compose_file_form.source
31
+ compose_file_template_form.credentials = credentials
32
+ compose_file_template_form.project = @project
33
+ compose_file_template_form.user = @user
34
+ compose_file_template_form.compose_dependencies = @compose_dependencies
35
+ compose_file_template_form.compose_repositories = @compose_repositories
36
+ compose_file_template_form.assign_template_attributes!
37
+
38
+ compose_file_template_form
39
+ end
40
+
41
+ def build_template_form(compose_file_form, compose_file_template_form)
42
+ attributes = compose_file_template_form.template_attributes
43
+ source = compose_file_template_form.source
44
+ template = compose_file_form.template
45
+ template = @project.templates.find_or_initialize_by(name: source) if !template.present?
46
+ template.assign_attributes(attributes)
47
+ template_form = template.becomes(UffizziCore::Api::Cli::V1::Template::CreateForm)
48
+ template_form.project = @project
49
+ template_form.added_by = @user
50
+ template_form.compose_file = compose_file_form
51
+ template_form.creation_source = UffizziCore::Template.creation_source.compose_file
52
+
53
+ template_form
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ComposeFile::UpdateService
4
+ def initialize(user, project)
5
+ @user = user
6
+ @project = project
7
+ end
8
+
9
+ def update(compose_file, params)
10
+ compose_file_form = compose_file.becomes(ComposeFile::UpdateForm)
11
+ compose_file_form.assign_attributes(params)
12
+ credential = compose_file_form.project.account.credentials.github.last
13
+ compose_file_github_form = ComposeFileService.create_compose_file_github_form(compose_file_form, credential)
14
+
15
+ if compose_file_github_form.invalid?
16
+ if compose_file_github_form.compose_content_data.present?
17
+ compose_file_form.content = compose_file_github_form.compose_content_data[:content]
18
+ end
19
+
20
+ return [compose_file_form, compose_file_github_form.errors]
21
+ end
22
+
23
+ compose_file_depedencies = compose_file_github_form.compose_dependencies
24
+ compose_file_form.payload['dependencies'] = ComposeFileService.prepare_compose_file_dependencies(compose_file_depedencies)
25
+ compose_file_form.content = compose_file_github_form.compose_content_data[:content]
26
+
27
+ ComposeFileService.persist!(compose_file_form, compose_file_github_form)
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::ComposeFile::VariablesService
4
+ def parse_variable_from_string(str)
5
+ variable_parts = str.split('=', 2)
6
+
7
+ parse_variable_from_array(variable_parts)
8
+ end
9
+
10
+ def parse_variable_from_array(arr)
11
+ name = arr.first.to_s
12
+ value = arr.last.to_s
13
+
14
+ build_variable(name, value)
15
+ end
16
+
17
+ def build_variable(name, value)
18
+ raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.no_variable_name', name: name, value: value) if name.blank?
19
+
20
+ {
21
+ name: name,
22
+ value: value,
23
+ }
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::ComposeFileService
4
+ class << self
5
+ def has_secret?(compose_file, secret)
6
+ containers = compose_file.template.payload['containers_attributes']
7
+
8
+ containers.any? { |container| UffizziCore::ComposeFile::ContainerService.has_secret?(container, secret) }
9
+ end
10
+
11
+ def update_secret!(compose_file, secret)
12
+ compose_file.template.payload['containers_attributes'].map do |container|
13
+ if UffizziCore::ComposeFile::ContainerService.has_secret?(container, secret)
14
+ container = UffizziCore::ComposeFile::ContainerService.update_secret(container, secret)
15
+ end
16
+
17
+ container
18
+ end
19
+
20
+ compose_file.template.save!
21
+
22
+ compose_file
23
+ end
24
+
25
+ def secrets_valid?(compose_file, secrets)
26
+ secret_names = secrets.pluck('name')
27
+
28
+ compose_file.template.payload['containers_attributes'].all? do |container|
29
+ container['secret_variables'].all? { |secret| secret_names.include?(secret['name']) }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ContainerService
4
+ PRIVILEGED_PORT_MAX = 1024
5
+
6
+ class << self
7
+ def should_build?(container)
8
+ container.repo_id && container.repo.github?
9
+ end
10
+
11
+ def pod_name(container)
12
+ return container.controller_name if container.controller_name.present?
13
+
14
+ formatted_name = if should_build?(container)
15
+ "#{UffizziCore::RepoService.image(container.repo)}-#{UffizziCore::RepoService.tag(container.repo)}"
16
+ else
17
+ container.image_name
18
+ end
19
+
20
+ formatted_name.parameterize.gsub('_', '-')
21
+ end
22
+
23
+ def target_port_value(container)
24
+ should_find_unused_port = container.repo&.github? && UffizziCore::RepoService.needs_target_port?(container.repo) &&
25
+ container.public && container.port <= PRIVILEGED_PORT_MAX
26
+ return UffizziCore::DeploymentService.find_unused_port(container.deployment) if should_find_unused_port
27
+
28
+ container.port
29
+ end
30
+
31
+ def defines_env?(container, name)
32
+ return false if container.variables.nil?
33
+
34
+ container.variables.select { |v| v['name'].downcase.to_sym == name.to_sym }.any?
35
+ end
36
+
37
+ def continuously_deploy_enabled?(container)
38
+ container.aasm(:continuously_deploy).current_state == UffizziCore::Container::STATE_ENABLED
39
+ end
40
+
41
+ def valid_memory_limit?(container)
42
+ max_memory_limit = container.deployment.project.account.container_memory_limit
43
+ container_memory_limit = container.memory_limit
44
+ return true if max_memory_limit.nil? || container_memory_limit.nil?
45
+
46
+ container_memory_limit <= max_memory_limit
47
+ end
48
+
49
+ def valid_memory_request?(container)
50
+ max_memory_limit = container.deployment.project.account.container_memory_limit
51
+ container_memory_request = container.memory_request
52
+ return true if max_memory_limit.nil? || container_memory_request.nil?
53
+
54
+ container_memory_request <= max_memory_limit
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::ControllerService
4
+ class << self
5
+ def apply_config_file(deployment, config_file)
6
+ body = {
7
+ config_file: UffizziCore::Controller::ApplyConfigFile::ConfigFileSerializer.new(config_file).as_json,
8
+ }
9
+
10
+ controller_client.apply_config_file(deployment_id: deployment.id, config_file_id: config_file.id, body: body)
11
+ end
12
+
13
+ def create_deployment(deployment)
14
+ body = UffizziCore::Controller::CreateDeployment::DeploymentSerializer.new(deployment).as_json
15
+ controller_client.create_deployment(deployment_id: deployment.id, body: body)
16
+ end
17
+
18
+ def update_deployment(deployment)
19
+ body = UffizziCore::Controller::UpdateDeployment::DeploymentSerializer.new(deployment).as_json
20
+ controller_client.update_deployment(deployment_id: deployment.id, body: body)
21
+ end
22
+
23
+ def delete_deployment(deployment_id)
24
+ controller_client.delete_deployment(deployment_id: deployment_id)
25
+ end
26
+
27
+ def apply_credential(deployment, credential)
28
+ body = UffizziCore::Controller::CreateCredential::CredentialSerializer.new(credential).as_json
29
+ controller_client.apply_credential(deployment_id: deployment.id, body: body)
30
+ end
31
+
32
+ def delete_credential(deployment, credential)
33
+ controller_client.delete_credential(deployment_id: deployment.id, credential_id: credential.id)
34
+ end
35
+
36
+ def deploy_containers(deployment, containers)
37
+ containers = containers.map do |container|
38
+ UffizziCore::Controller::DeployContainers::ContainerSerializer.new(container).as_json(include: '**')
39
+ end
40
+ credentials = deployment.credentials.deployable.map do |credential|
41
+ UffizziCore::Controller::DeployContainers::CredentialSerializer.new(credential).as_json
42
+ end
43
+
44
+ body = {
45
+ containers: containers,
46
+ credentials: credentials,
47
+ deployment_url: UffizziCore::DeploymentService.build_preview_url(deployment),
48
+ }
49
+
50
+ controller_client.deploy_containers(deployment_id: deployment.id, body: body)
51
+ end
52
+
53
+ def deployment_exists?(deployment)
54
+ controller_client.deployment(deployment_id: deployment.id).code == 200
55
+ end
56
+
57
+ def fetch_deployment_events(deployment)
58
+ request_events(deployment) || []
59
+ end
60
+
61
+ def fetch_pods(deployment)
62
+ pods = controller_client.deployment_containers(deployment_id: deployment.id).result || []
63
+ pods.filter { |pod| pod.metadata.name.start_with?(Settings.controller.namespace_prefix) }
64
+ end
65
+
66
+ def fetch_namespace(deployment)
67
+ controller_client.deployment(deployment_id: deployment.id).result || nil
68
+ end
69
+
70
+ private
71
+
72
+ def request_events(deployment)
73
+ controller_client.deployment_containers_events(deployment_id: deployment.id)
74
+ end
75
+
76
+ def controller_client
77
+ UffizziCore::ControllerClient.new
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::CredentialService
4
+ class << self
5
+ def correct_credentials?(credential)
6
+ status = case credential.type
7
+ when UffizziCore::Credential::DockerHub.name
8
+ UffizziCore::DockerHub::CredentialService.credential_correct?(credential)
9
+ when UffizziCore::Credential::Github.name
10
+ UffizziCore::Github::CredentialService.credential_correct?(credential)
11
+ when UffizziCore::Credential::Azure.name
12
+ UffizziCore::Azure::CredentialService.credential_correct?(credential)
13
+ when UffizziCore::Credential::Google.name
14
+ UffizziCore::Google::CredentialService.credential_correct?(credential)
15
+ when UffizziCore::Credential::Amazon.name
16
+ UffizziCore::Amazon::CredentialService.credential_correct?(credential)
17
+ else
18
+ false
19
+ end
20
+
21
+ if credential.persisted? && credential.active? && !status
22
+ Rails.logger.warn("broken credentials, credential_correct? credential_id=#{credential.id}")
23
+ credential.unauthorize!
24
+ end
25
+
26
+ status
27
+ end
28
+
29
+ def update_expired_credentials
30
+ currect_date = DateTime.now
31
+ credentials = UffizziCore::Credential::Amazon.active.where('updated_at < ?', currect_date - 10.hours)
32
+
33
+ credentials.each do |credential|
34
+ deployments = UffizziCore::Deployment.where(project_id: credential.account.projects.select(:id)).with_amazon_repos
35
+
36
+ deployments.each do |deployment|
37
+ UffizziCore::Deployment::CreateCredentialJob.perform_async(deployment.id, credential.id)
38
+ end
39
+
40
+ credential.update(updated_at: currect_date)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,274 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::DeploymentService
4
+ MIN_TARGET_PORT_RANGE = 37_000
5
+ MAX_TARGET_PORT_RANGE = 39_999
6
+
7
+ DEPLOYMENT_PROCESS_STATUSES = {
8
+ building: :building,
9
+ deploying: :deploying,
10
+ failed: :failed,
11
+ }.freeze
12
+
13
+ class << self
14
+ def create_from_compose(compose_file, project, user)
15
+ deployment_attributes = ActionController::Parameters.new(compose_file.template.payload)
16
+
17
+ deployment_form = UffizziCore::Api::Cli::V1::Deployment::CreateForm.new(deployment_attributes)
18
+ deployment_form.assign_dependences!(project, user)
19
+ deployment_form.compose_file = compose_file
20
+ deployment_form.creation_source = UffizziCore::Deployment.creation_source.compose_file_manual
21
+
22
+ if deployment_form.save
23
+ update_subdomain!(deployment_form)
24
+
25
+ UffizziCore::Deployment::CreateJob.perform_async(deployment_form.id)
26
+ UffizziCore::Deployment::CreateWebhooksJob.perform_async(deployment_form.id)
27
+ end
28
+
29
+ deployment_form
30
+ end
31
+
32
+ def deploy_containers(deployment, repeated = false)
33
+ if !repeated
34
+ create_activity_items(deployment)
35
+ update_controller_container_names(deployment)
36
+ end
37
+
38
+ case deployment_process_status(deployment)
39
+ when DEPLOYMENT_PROCESS_STATUSES[:building]
40
+ Rails.logger.info("DEPLOYMENT_PROCESS deployment_id=#{deployment.id} repeat deploy_containers")
41
+ UffizziCore::Deployment::DeployContainersJob.perform_in(1.minute, deployment.id, true)
42
+ when DEPLOYMENT_PROCESS_STATUSES[:deploying]
43
+ Rails.logger.info("DEPLOYMENT_PROCESS deployment_id=#{deployment.id} start deploying into controller")
44
+
45
+ containers = deployment.active_containers
46
+ containers = add_default_deployment_variables!(containers)
47
+
48
+ UffizziCore::ControllerService.deploy_containers(deployment, containers)
49
+ else
50
+ Rails.logger.info("DEPLOYMENT_PROCESS deployment_id=#{deployment.id} deployment has builds errors, stopping")
51
+ end
52
+ end
53
+
54
+ def disable!(deployment)
55
+ deployment.disable!
56
+ compose_file = deployment.compose_file || deployment.template&.compose_file
57
+ return unless compose_file&.kind&.temporary?
58
+
59
+ compose_file.destroy!
60
+ end
61
+
62
+ def build_subdomain(deployment)
63
+ if deployment.continuous_preview_payload.present?
64
+ continuous_preview_payload = deployment.continuous_preview_payload
65
+
66
+ return build_pull_request_subdomain(deployment) if continuous_preview_payload['pull_request'].present?
67
+ return build_docker_continuous_preview_subdomain(deployment) if continuous_preview_payload['docker'].present?
68
+ end
69
+
70
+ build_default_subdomain(deployment)
71
+ end
72
+
73
+ def build_pull_request_subdomain(deployment)
74
+ project = deployment.project
75
+ continuous_preview_payload = deployment.continuous_preview_payload
76
+ pull_request_payload = continuous_preview_payload['pull_request']
77
+ repo_name = pull_request_payload['repository_full_name'].split('/').last
78
+ deployment_name = name(deployment)
79
+
80
+ "pr#{pull_request_payload['id']}-#{deployment_name}.#{repo_name}.#{project.slug}"
81
+ end
82
+
83
+ def build_docker_continuous_preview_subdomain(deployment)
84
+ project = deployment.project
85
+ continuous_preview_payload = deployment.continuous_preview_payload
86
+ docker_payload = continuous_preview_payload['docker']
87
+ repo_name = docker_payload['image'].split('/').last.gsub('_', '-')
88
+ image_tag = docker_payload['tag'].gsub('_', '-')
89
+ deployment_name = name(deployment)
90
+
91
+ "#{image_tag}-#{deployment_name}.#{repo_name}.#{project.slug}"
92
+ end
93
+
94
+ def build_default_subdomain(deployment)
95
+ deployment_name = name(deployment)
96
+ slug = deployment.project.slug.to_s
97
+ "#{deployment_name}.#{slug}"
98
+ end
99
+
100
+ def build_preview_url(deployment)
101
+ "#{deployment.subdomain}.#{Settings.app.managed_dns_zone}"
102
+ end
103
+
104
+ def build_deployment_url(deployment)
105
+ "#{Settings.app.managed_dns_zone}/projects/#{deployment.project_id}/deployments"
106
+ end
107
+
108
+ def all_containers_have_unique_ports?(containers)
109
+ ports = containers.map(&:port).compact
110
+ containers.empty? || ports.size == ports.uniq.size
111
+ end
112
+
113
+ def valid_containers_memory_limit?(deployment)
114
+ containers = deployment.containers
115
+ container_memory_limit = deployment.project.account.container_memory_limit
116
+ return true if container_memory_limit.nil?
117
+
118
+ containers.all? { |container| container.memory_limit <= container_memory_limit }
119
+ end
120
+
121
+ def valid_containers_memory_request?(deployment)
122
+ containers = deployment.containers
123
+ container_memory_limit = deployment.project.account.container_memory_limit
124
+ return true if container_memory_limit.nil?
125
+
126
+ containers.all? { |container| container.memory_request <= container_memory_limit }
127
+ end
128
+
129
+ def ingress_container?(containers)
130
+ containers.empty? || containers.map(&:receive_incoming_requests).count(true) == 1
131
+ end
132
+
133
+ def find_unused_port(deployment)
134
+ selected_port = nil
135
+
136
+ Timeout.timeout(20) do
137
+ loop do
138
+ selected_port = rand(MIN_TARGET_PORT_RANGE..MAX_TARGET_PORT_RANGE)
139
+
140
+ break if !deployment.containers.exists?(target_port: selected_port)
141
+ end
142
+ end
143
+
144
+ selected_port
145
+ end
146
+
147
+ def setup_ingress_container(deployment, ingress_container, port)
148
+ old_deployment_subdomain = deployment.subdomain
149
+
150
+ containers = deployment.containers.active
151
+
152
+ UffizziCore::Container.transaction do
153
+ containers.update_all(receive_incoming_requests: false, port: nil, public: false)
154
+ containers.find(ingress_container.id).update!(port: port, public: true, receive_incoming_requests: true)
155
+ end
156
+
157
+ deployment.reload
158
+
159
+ new_deployment_subdomain = build_subdomain(deployment)
160
+
161
+ if new_deployment_subdomain != old_deployment_subdomain
162
+ deployment.update(subdomain: new_deployment_subdomain)
163
+ end
164
+
165
+ UffizziCore::Deployment::DeployContainersJob.perform_async(deployment.id)
166
+ end
167
+
168
+ def name(deployment)
169
+ "deployment-#{deployment.id}"
170
+ end
171
+
172
+ def update_subdomain!(deployment)
173
+ deployment.subdomain = build_subdomain(deployment)
174
+
175
+ deployment.save!
176
+ end
177
+
178
+ def create_webhooks(deployment)
179
+ credential = deployment.project.account.credentials.docker_hub.active.first
180
+
181
+ if !deployment.containers.with_docker_hub_repo.exists? || !credential.present?
182
+ Rails.logger.info("DEPLOYMENT_PROCESS deployment_id=#{deployment.id} create_webhooks no dockerhub containers or credential")
183
+ return
184
+ end
185
+
186
+ accounts = UffizziCore::DockerHubService.accounts(credential)
187
+
188
+ deployment.containers.with_docker_hub_repo.find_each do |container|
189
+ if !accounts.include?(container.repo.namespace)
190
+ logger_message = "DEPLOYMENT_PROCESS deployment_id=#{deployment.id} no namespace(#{container.repo.namespace})
191
+ in accounts(#{accounts.inspect})"
192
+ Rails.logger.info(logger_message)
193
+ next
194
+ end
195
+
196
+ UffizziCore::Credential::DockerHub::CreateWebhookJob.perform_async(credential.id, container.image, deployment.id)
197
+ end
198
+ end
199
+
200
+ def pull_request_payload_present?(deployment)
201
+ deployment.continuous_preview_payload.present? && deployment.continuous_preview_payload['pull_request'].present?
202
+ end
203
+
204
+ def failed?(deployment)
205
+ deployment_status = deployment_process_status(deployment)
206
+
207
+ deployment_status == DEPLOYMENT_PROCESS_STATUSES[:failed]
208
+ end
209
+
210
+ private
211
+
212
+ def deployment_process_status(deployment)
213
+ containers = deployment.active_containers
214
+ activity_items = containers.map { |container| container.activity_items.order_by_id.last }
215
+ events = activity_items.map { |activity_item| activity_item.events.order_by_id.last&.state }
216
+ events = events.flatten.uniq
217
+
218
+ return DEPLOYMENT_PROCESS_STATUSES[:failed] if events.include?(UffizziCore::Event.state.failed)
219
+ return DEPLOYMENT_PROCESS_STATUSES[:building] if events.include?(UffizziCore::Event.state.building)
220
+
221
+ DEPLOYMENT_PROCESS_STATUSES[:deploying]
222
+ end
223
+
224
+ def create_activity_items(deployment)
225
+ deployment.active_containers.each do |container|
226
+ repo = container.repo
227
+ activity_item = case repo.type
228
+ when UffizziCore::Repo::Github.name
229
+ UffizziCore::ActivityItemService.create_github_item!(repo, container)
230
+ else
231
+ UffizziCore::ActivityItemService.create_docker_item!(repo, container)
232
+ end
233
+
234
+ create_default_activity_item_event(activity_item)
235
+
236
+ if UffizziCore::RepoService.credential(repo).present? && activity_item.docker?
237
+ UffizziCore::ActivityItem::Docker::UpdateDigestJob.perform_async(activity_item.id)
238
+ end
239
+ UffizziCore::Deployment::ManageDeployActivityItemJob.perform_in(5.seconds, activity_item.id)
240
+ end
241
+ end
242
+
243
+ def create_default_activity_item_event(activity_item)
244
+ activity_item.events.create(state: UffizziCore::Event.state.building) if activity_item.github?
245
+ activity_item.events.create(state: UffizziCore::Event.state.deploying) if activity_item.docker?
246
+ end
247
+
248
+ def update_controller_container_names(deployment)
249
+ deployment.active_containers.each do |container|
250
+ next if container.controller_name.present?
251
+
252
+ controller_name = generate_controller_container_name(container)
253
+ container.update!(controller_name: controller_name)
254
+ end
255
+ end
256
+
257
+ def generate_controller_container_name(container)
258
+ Digest::SHA256.hexdigest("#{container.id}:#{container.image}")[0, 10]
259
+ end
260
+
261
+ def add_default_deployment_variables!(containers)
262
+ containers.each do |container|
263
+ envs = []
264
+ if container.port.present? && !UffizziCore::ContainerService.defines_env?(container, 'PORT')
265
+ envs.push('name' => 'PORT', 'value' => container.target_port.to_s)
266
+ end
267
+
268
+ container.variables = [] if container.variables.nil?
269
+
270
+ container.variables.push(*envs)
271
+ end
272
+ end
273
+ end
274
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::DockerHub::CredentialService
4
+ class << self
5
+ def credential_correct?(credential)
6
+ client(credential).authentificated?
7
+ end
8
+
9
+ private
10
+
11
+ def client(credential)
12
+ UffizziCore::DockerHubClient.new(credential)
13
+ end
14
+ end
15
+ end