uffizzi-core 0.1.12

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 (257) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/README.md +52 -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 +141 -0
  14. data/app/clients/uffizzi_core/github_container_registry_client/request_result.rb +7 -0
  15. data/app/clients/uffizzi_core/github_container_registry_client.rb +52 -0
  16. data/app/clients/uffizzi_core/google_registry_client/request_result.rb +5 -0
  17. data/app/clients/uffizzi_core/google_registry_client.rb +42 -0
  18. data/app/contexts/uffizzi_core/base_context.rb +12 -0
  19. data/app/contexts/uffizzi_core/project_context.rb +13 -0
  20. data/app/contexts/uffizzi_core/webhooks_context.rb +9 -0
  21. data/app/controllers/concerns/uffizzi_core/auth_management.rb +23 -0
  22. data/app/controllers/concerns/uffizzi_core/authorization_concern.rb +38 -0
  23. data/app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb +19 -0
  24. data/app/controllers/uffizzi_core/api/cli/v1/account/application_controller.rb +7 -0
  25. data/app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb +91 -0
  26. data/app/controllers/uffizzi_core/api/cli/v1/application_controller.rb +5 -0
  27. data/app/controllers/uffizzi_core/api/cli/v1/projects/application_controller.rb +11 -0
  28. data/app/controllers/uffizzi_core/api/cli/v1/projects/compose_files_controller.rb +93 -0
  29. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/activity_items_controller.rb +36 -0
  30. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/application_controller.rb +7 -0
  31. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers/application_controller.rb +8 -0
  32. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers/logs_controller.rb +27 -0
  33. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers_controller.rb +24 -0
  34. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/events_controller.rb +29 -0
  35. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments_controller.rb +179 -0
  36. data/app/controllers/uffizzi_core/api/cli/v1/projects/secrets_controller.rb +61 -0
  37. data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +85 -0
  38. data/app/controllers/uffizzi_core/api/cli/v1/sessions_controller.rb +43 -0
  39. data/app/controllers/uffizzi_core/application_controller.rb +57 -0
  40. data/app/errors/uffizzi_core/compose_file/build_error.rb +4 -0
  41. data/app/errors/uffizzi_core/compose_file/credential_error.rb +4 -0
  42. data/app/errors/uffizzi_core/compose_file/parse_error.rb +4 -0
  43. data/app/errors/uffizzi_core/compose_file/secrets_error.rb +4 -0
  44. data/app/errors/uffizzi_core/deployment/image_pull_error.rb +10 -0
  45. data/app/errors/uffizzi_core/deployment_not_found_error.rb +10 -0
  46. data/app/forms/uffizzi_core/api/cli/v1/account/credential/check_credential_form.rb +16 -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 +22 -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 +92 -0
  55. data/app/forms/uffizzi_core/api/cli/v1/deployment/update_form.rb +90 -0
  56. data/app/forms/uffizzi_core/api/cli/v1/project/create_form.rb +7 -0
  57. data/app/forms/uffizzi_core/api/cli/v1/project/update_form.rb +10 -0
  58. data/app/forms/uffizzi_core/api/cli/v1/secret/bulk_assign_form.rb +39 -0
  59. data/app/forms/uffizzi_core/api/cli/v1/session_create_form.rb +29 -0
  60. data/app/forms/uffizzi_core/api/cli/v1/template/create_form.rb +65 -0
  61. data/app/forms/uffizzi_core/application_form.rb +11 -0
  62. data/app/forms/uffizzi_core/application_form_without_active_record.rb +17 -0
  63. data/app/forms/uffizzi_core/mass_assignment_control_concern.rb +22 -0
  64. data/app/helpers/uffizzi_core/application_helper.rb +6 -0
  65. data/app/jobs/uffizzi_core/account/create_credential_job.rb +10 -0
  66. data/app/jobs/uffizzi_core/activity_item/docker/update_digest_job.rb +11 -0
  67. data/app/jobs/uffizzi_core/application_job.rb +7 -0
  68. data/app/jobs/uffizzi_core/config_file/apply_job.rb +31 -0
  69. data/app/jobs/uffizzi_core/credential/docker_hub/create_webhook_job.rb +15 -0
  70. data/app/jobs/uffizzi_core/deployment/create_credential_job.rb +32 -0
  71. data/app/jobs/uffizzi_core/deployment/create_credentials_job.rb +17 -0
  72. data/app/jobs/uffizzi_core/deployment/create_job.rb +15 -0
  73. data/app/jobs/uffizzi_core/deployment/create_webhooks_job.rb +13 -0
  74. data/app/jobs/uffizzi_core/deployment/delete_credential_job.rb +13 -0
  75. data/app/jobs/uffizzi_core/deployment/delete_job.rb +11 -0
  76. data/app/jobs/uffizzi_core/deployment/deploy_containers_job.rb +27 -0
  77. data/app/jobs/uffizzi_core/deployment/manage_deploy_activity_item_job.rb +38 -0
  78. data/app/lib/uffizzi_core/concerns/models/activity_item.rb +39 -0
  79. data/app/lib/uffizzi_core/concerns/models/credential.rb +65 -0
  80. data/app/lib/uffizzi_core/concerns/models/repo.rb +33 -0
  81. data/app/lib/uffizzi_core/rbac/user_access_service.rb +45 -0
  82. data/app/mailers/uffizzi_core/application_mailer.rb +8 -0
  83. data/app/models/concerns/uffizzi_core/hashid_concern.rb +25 -0
  84. data/app/models/concerns/uffizzi_core/state_machine_concern.rb +16 -0
  85. data/app/models/uffizzi_core/account.rb +83 -0
  86. data/app/models/uffizzi_core/activity_item/docker.rb +4 -0
  87. data/app/models/uffizzi_core/activity_item/github.rb +4 -0
  88. data/app/models/uffizzi_core/activity_item/memory_limit.rb +4 -0
  89. data/app/models/uffizzi_core/activity_item.rb +53 -0
  90. data/app/models/uffizzi_core/application_record.rb +7 -0
  91. data/app/models/uffizzi_core/build.rb +39 -0
  92. data/app/models/uffizzi_core/comment.rb +16 -0
  93. data/app/models/uffizzi_core/compose_file.rb +57 -0
  94. data/app/models/uffizzi_core/config_file.rb +24 -0
  95. data/app/models/uffizzi_core/container.rb +100 -0
  96. data/app/models/uffizzi_core/container_config_file.rb +8 -0
  97. data/app/models/uffizzi_core/continuous_preview.rb +4 -0
  98. data/app/models/uffizzi_core/coupon.rb +5 -0
  99. data/app/models/uffizzi_core/credential/amazon.rb +4 -0
  100. data/app/models/uffizzi_core/credential/azure.rb +4 -0
  101. data/app/models/uffizzi_core/credential/docker_hub.rb +4 -0
  102. data/app/models/uffizzi_core/credential/github.rb +4 -0
  103. data/app/models/uffizzi_core/credential/github_container_registry.rb +4 -0
  104. data/app/models/uffizzi_core/credential/google.rb +4 -0
  105. data/app/models/uffizzi_core/credential.rb +61 -0
  106. data/app/models/uffizzi_core/database.rb +4 -0
  107. data/app/models/uffizzi_core/database_offering.rb +4 -0
  108. data/app/models/uffizzi_core/deployment.rb +86 -0
  109. data/app/models/uffizzi_core/event.rb +13 -0
  110. data/app/models/uffizzi_core/invitation.rb +27 -0
  111. data/app/models/uffizzi_core/membership.rb +16 -0
  112. data/app/models/uffizzi_core/payment.rb +11 -0
  113. data/app/models/uffizzi_core/price.rb +9 -0
  114. data/app/models/uffizzi_core/product.rb +11 -0
  115. data/app/models/uffizzi_core/project.rb +67 -0
  116. data/app/models/uffizzi_core/rating.rb +20 -0
  117. data/app/models/uffizzi_core/repo/amazon.rb +4 -0
  118. data/app/models/uffizzi_core/repo/azure.rb +4 -0
  119. data/app/models/uffizzi_core/repo/docker_hub.rb +4 -0
  120. data/app/models/uffizzi_core/repo/github.rb +4 -0
  121. data/app/models/uffizzi_core/repo/github_container_registry.rb +4 -0
  122. data/app/models/uffizzi_core/repo/google.rb +4 -0
  123. data/app/models/uffizzi_core/repo.rb +29 -0
  124. data/app/models/uffizzi_core/role.rb +17 -0
  125. data/app/models/uffizzi_core/secret.rb +9 -0
  126. data/app/models/uffizzi_core/template.rb +19 -0
  127. data/app/models/uffizzi_core/user.rb +62 -0
  128. data/app/models/uffizzi_core/user_project.rb +14 -0
  129. data/app/policies/uffizzi_core/api/cli/v1/account/credentials_policy.rb +19 -0
  130. data/app/policies/uffizzi_core/api/cli/v1/projects/compose_files_policy.rb +15 -0
  131. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/activity_items_policy.rb +7 -0
  132. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/containers_policy.rb +7 -0
  133. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/events_policy.rb +7 -0
  134. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments_policy.rb +27 -0
  135. data/app/policies/uffizzi_core/api/cli/v1/projects/secrets_policy.rb +15 -0
  136. data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +19 -0
  137. data/app/policies/uffizzi_core/application_policy.rb +12 -0
  138. data/app/repositories/uffizzi_core/activity_item_repo.rb +9 -0
  139. data/app/repositories/uffizzi_core/basic_order_repo.rb +11 -0
  140. data/app/repositories/uffizzi_core/build_repo.rb +23 -0
  141. data/app/repositories/uffizzi_core/comment_repo.rb +11 -0
  142. data/app/repositories/uffizzi_core/compose_file_repo.rb +11 -0
  143. data/app/repositories/uffizzi_core/config_file_repo.rb +40 -0
  144. data/app/repositories/uffizzi_core/container_repo.rb +25 -0
  145. data/app/repositories/uffizzi_core/credential_repo.rb +31 -0
  146. data/app/repositories/uffizzi_core/deployment_repo.rb +24 -0
  147. data/app/repositories/uffizzi_core/event_repo.rb +9 -0
  148. data/app/repositories/uffizzi_core/membership_repo.rb +10 -0
  149. data/app/repositories/uffizzi_core/price_repo.rb +11 -0
  150. data/app/repositories/uffizzi_core/product_repo.rb +11 -0
  151. data/app/repositories/uffizzi_core/project_repo.rb +10 -0
  152. data/app/repositories/uffizzi_core/repo_repo.rb +10 -0
  153. data/app/repositories/uffizzi_core/template_repo.rb +87 -0
  154. data/app/repositories/uffizzi_core/usage_repo.rb +9 -0
  155. data/app/repositories/uffizzi_core/user_repo.rb +11 -0
  156. data/app/responders/uffizzi_core/json_responder.rb +13 -0
  157. data/app/serializers/uffizzi_core/api/cli/v1/account/credential_serializer.rb +9 -0
  158. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/compose_file_serializer.rb +7 -0
  159. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/deployment_serializer.rb +13 -0
  160. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +30 -0
  161. data/app/serializers/uffizzi_core/api/cli/v1/projects/compose_file_serializer.rb +7 -0
  162. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +32 -0
  163. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/user_serializer.rb +11 -0
  164. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer.rb +74 -0
  165. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/activity_item_serializer.rb +24 -0
  166. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer/config_file_serializer.rb +6 -0
  167. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer.rb +7 -0
  168. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer.rb +30 -0
  169. data/app/serializers/uffizzi_core/api/cli/v1/projects/secret_serializer.rb +5 -0
  170. data/app/serializers/uffizzi_core/api/cli/v1/short_project_serializer.rb +7 -0
  171. data/app/serializers/uffizzi_core/api/cli/v1/user_serializer/account_serializer.rb +5 -0
  172. data/app/serializers/uffizzi_core/api/cli/v1/user_serializer.rb +7 -0
  173. data/app/serializers/uffizzi_core/base_serializer.rb +7 -0
  174. data/app/serializers/uffizzi_core/controller/apply_config_file/config_file_serializer.rb +5 -0
  175. data/app/serializers/uffizzi_core/controller/create_credential/credential_serializer.rb +19 -0
  176. data/app/serializers/uffizzi_core/controller/create_deployment/deployment_serializer.rb +5 -0
  177. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer/container_config_file_serializer/config_file_serializer.rb +8 -0
  178. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer/container_config_file_serializer.rb +7 -0
  179. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +70 -0
  180. data/app/serializers/uffizzi_core/controller/deploy_containers/credential_serializer.rb +5 -0
  181. data/app/services/uffizzi_core/account_service.rb +21 -0
  182. data/app/services/uffizzi_core/activity_item_service.rb +88 -0
  183. data/app/services/uffizzi_core/amazon/credential_service.rb +31 -0
  184. data/app/services/uffizzi_core/amazon_service.rb +45 -0
  185. data/app/services/uffizzi_core/azure/credential_service.rb +18 -0
  186. data/app/services/uffizzi_core/compose_file/builders/config_files_builder_service.rb +31 -0
  187. data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +222 -0
  188. data/app/services/uffizzi_core/compose_file/builders/docker_repo_builder_service.rb +25 -0
  189. data/app/services/uffizzi_core/compose_file/builders/template_builder_service.rb +45 -0
  190. data/app/services/uffizzi_core/compose_file/builders/variables_builder_service.rb +58 -0
  191. data/app/services/uffizzi_core/compose_file/config_files_service.rb +52 -0
  192. data/app/services/uffizzi_core/compose_file/config_option_service.rb +41 -0
  193. data/app/services/uffizzi_core/compose_file/configs_options_service.rb +26 -0
  194. data/app/services/uffizzi_core/compose_file/container_service.rb +68 -0
  195. data/app/services/uffizzi_core/compose_file/continuous_preview_options_service.rb +57 -0
  196. data/app/services/uffizzi_core/compose_file/dependencies_service.rb +56 -0
  197. data/app/services/uffizzi_core/compose_file/errors_service.rb +46 -0
  198. data/app/services/uffizzi_core/compose_file/github_dependencies_service.rb +38 -0
  199. data/app/services/uffizzi_core/compose_file/ingress_options_service.rb +51 -0
  200. data/app/services/uffizzi_core/compose_file/parsers/services/healthcheck_parser_service.rb +73 -0
  201. data/app/services/uffizzi_core/compose_file/secrets_options_service.rb +28 -0
  202. data/app/services/uffizzi_core/compose_file/services_options/command_service.rb +18 -0
  203. data/app/services/uffizzi_core/compose_file/services_options/configs_service.rb +51 -0
  204. data/app/services/uffizzi_core/compose_file/services_options/deploy_service.rb +44 -0
  205. data/app/services/uffizzi_core/compose_file/services_options/entrypoint_service.rb +18 -0
  206. data/app/services/uffizzi_core/compose_file/services_options/env_file_service.rb +34 -0
  207. data/app/services/uffizzi_core/compose_file/services_options/environment_service.rb +20 -0
  208. data/app/services/uffizzi_core/compose_file/services_options/image_service.rb +89 -0
  209. data/app/services/uffizzi_core/compose_file/services_options/secrets_service.rb +35 -0
  210. data/app/services/uffizzi_core/compose_file/services_options_service.rb +57 -0
  211. data/app/services/uffizzi_core/compose_file/template_service.rb +55 -0
  212. data/app/services/uffizzi_core/compose_file/variables_service.rb +25 -0
  213. data/app/services/uffizzi_core/compose_file_service.rb +181 -0
  214. data/app/services/uffizzi_core/container_service.rb +42 -0
  215. data/app/services/uffizzi_core/controller_service.rb +86 -0
  216. data/app/services/uffizzi_core/credential_service.rb +44 -0
  217. data/app/services/uffizzi_core/deployment_service.rb +307 -0
  218. data/app/services/uffizzi_core/docker_hub/credential_service.rb +15 -0
  219. data/app/services/uffizzi_core/docker_hub_service.rb +77 -0
  220. data/app/services/uffizzi_core/github_container_registry/credential_service.rb +24 -0
  221. data/app/services/uffizzi_core/google/credential_service.rb +18 -0
  222. data/app/services/uffizzi_core/logs_service.rb +33 -0
  223. data/app/services/uffizzi_core/manage_activity_items_service.rb +159 -0
  224. data/app/services/uffizzi_core/project_service.rb +48 -0
  225. data/app/services/uffizzi_core/repo_service.rb +43 -0
  226. data/app/services/uffizzi_core/response_service.rb +13 -0
  227. data/app/services/uffizzi_core/starter_template_service.rb +200 -0
  228. data/app/services/uffizzi_core/template_service.rb +21 -0
  229. data/app/services/uffizzi_core/token_service.rb +19 -0
  230. data/app/services/uffizzi_core/user_access_service.rb +14 -0
  231. data/app/services/uffizzi_core/user_generator_service.rb +84 -0
  232. data/app/utils/uffizzi_core/converters.rb +33 -0
  233. data/app/validators/uffizzi_core/email_validator.rb +9 -0
  234. data/app/validators/uffizzi_core/environment_variable_list_validator.rb +15 -0
  235. data/app/validators/uffizzi_core/image_command_args_validator.rb +21 -0
  236. data/config/initializers/rswag_api.rb +15 -0
  237. data/config/initializers/rswag_ui.rb +15 -0
  238. data/config/initializers/swagger_yard.rb +17 -0
  239. data/config/locales/en.activerecord.yml +23 -0
  240. data/config/locales/en.yml +66 -0
  241. data/config/routes.rb +69 -0
  242. data/db/migrate/20220218121438_create_uffizzi_core_tables.rb +375 -0
  243. data/db/migrate/20220309110201_remove_secrets_from_projects.rb +7 -0
  244. data/db/migrate/20220310110150_create_project_secrets.rb +14 -0
  245. data/db/migrate/20220325113342_add_name_to_uffizzi_containers.rb +7 -0
  246. data/db/migrate/20220329123323_rename_project_secrets_to_secrets.rb +7 -0
  247. data/db/migrate/20220329124542_add_resource_to_secrets.rb +7 -0
  248. data/db/migrate/20220329143241_remove_project_ref_from_secrets.rb +7 -0
  249. data/db/migrate/20220419074956_add_health_check_to_containers.rb +7 -0
  250. data/db/migrate/20220525113412_rename_name_to_uffizzi_containers.rb +7 -0
  251. data/db/seeds.rb +16 -0
  252. data/lib/tasks/uffizzi_core_tasks.rake +19 -0
  253. data/lib/uffizzi_core/engine.rb +15 -0
  254. data/lib/uffizzi_core/version.rb +5 -0
  255. data/lib/uffizzi_core.rb +61 -0
  256. data/swagger/v1/swagger.json +1659 -0
  257. metadata +966 -0
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @resource Deployment
4
+
5
+ class UffizziCore::Api::Cli::V1::Projects::DeploymentsController < UffizziCore::Api::Cli::V1::Projects::ApplicationController
6
+ before_action :authorize_uffizzi_core_api_cli_v1_projects_deployments
7
+
8
+ # Get a list of active deployements for a project
9
+ #
10
+ # @path [GET] /api/cli/v1/projects/{project_slug}/deployments
11
+ #
12
+ # @parameter project_slug(required,path) [string] The project slug
13
+ #
14
+ # @response [Array<Deployment>] 200 OK
15
+ # @response 401 Not authorized
16
+ def index
17
+ respond_with deployments
18
+ end
19
+
20
+ # Get deployment information by id
21
+ #
22
+ # @path [GET] /api/cli/v1/projects/{project_slug}/deployments/{id}
23
+ #
24
+ # @parameter project_slug(required,path) [string] The project slug
25
+ #
26
+ # @response [Deployment] 200 OK
27
+ # @response [object<errors: object<title: string>>] 404 Not found
28
+ # @response 401 Not authorized
29
+ def show
30
+ respond_with deployment
31
+ end
32
+
33
+ # Create a deployment from a compose file
34
+ #
35
+ # @path [POST] /api/cli/v1/projects/{project_slug}/deployments
36
+ #
37
+ # @parameter project_slug(required,path) [string] The project slug
38
+ # @parameter params(required,body) [object<
39
+ # compose_file: object<path: string, source: string, content: string>,
40
+ # dependencies: Array<object<path: string, source: string, content: string>>>]
41
+ #
42
+ # @response [Deployment] 201 OK
43
+ # @response [object<errors: object<state: string>>] 422 Unprocessable Entity
44
+ # @response [object<errors: object<title: string>>] 404 Not found
45
+ # @response 401 Not authorized
46
+ def create
47
+ compose_file, errors = find_or_create_compose_file
48
+ return render_invalid_file if compose_file.invalid_file?
49
+ return render_errors(errors) if errors.present?
50
+
51
+ errors = check_credentials(compose_file)
52
+ return render_errors(errors) if errors.present?
53
+
54
+ deployment = UffizziCore::DeploymentService.create_from_compose(compose_file, resource_project, current_user)
55
+
56
+ respond_with deployment
57
+ end
58
+
59
+ # Update the deployment with new compose file
60
+ #
61
+ # @path [PUT] /api/cli/v1/projects/{project_slug}/deployments/{id}"
62
+ #
63
+ # @parameter project_slug(required,path) [string] The project slug
64
+ # @parameter params(required,body) [object<
65
+ # compose_file: object<path: string, source: string, content: string>,
66
+ # dependencies: Array<object<path: string, source: string, content: string>>>]
67
+ #
68
+ # @response [Deployment] 201 OK
69
+ # @response [object<errors: object<state: string>>] 422 Unprocessable Entity
70
+ # @response [object<errors: object<title: string>>] 404 Not found
71
+ # @response 401 Not authorized
72
+ def update
73
+ compose_file, errors = create_temporary_compose_file
74
+ return render_invalid_file if compose_file.invalid_file?
75
+ return render_errors(errors) if errors.present?
76
+
77
+ errors = check_credentials(compose_file)
78
+ return render_errors(errors) if errors.present?
79
+
80
+ deployment_id = params[:id]
81
+ deployment = UffizziCore::DeploymentService.update_from_compose(compose_file, resource_project, current_user, deployment_id)
82
+
83
+ respond_with deployment
84
+ end
85
+
86
+ # @path [POST] /api/cli/v1/projects/{project_slug}/deployments/{id}/deploy_containers
87
+ #
88
+ # @parameter project_slug(required,path) [string] The project slug
89
+ # @parameter id(required,path) [string] The id of the deployment
90
+ #
91
+ # @response 204 No Content
92
+ # @response [object<errors: object<title: string>>] 404 Not found
93
+ # @response 401 Not authorized
94
+ def deploy_containers
95
+ deployment = resource_project.deployments.active.find(params[:id])
96
+
97
+ deployment.update(deployed_by: current_user)
98
+
99
+ resource_project.config_files.by_deployment(deployment).each do |config_file|
100
+ UffizziCore::ConfigFile::ApplyJob.perform_async(deployment.id, config_file.id)
101
+ end
102
+
103
+ UffizziCore::Deployment::DeployContainersJob.perform_async(deployment.id)
104
+ end
105
+
106
+ # Disable deployment by id
107
+ #
108
+ # @path [DELETE] /api/cli/v1/projects/{project_slug}/deployments/{id}
109
+ #
110
+ # @parameter project_slug(required,path) [string] The project slug
111
+ #
112
+ # @response 204 No Content
113
+ # @response 401 Not authorized
114
+ def destroy
115
+ UffizziCore::DeploymentService.disable!(deployment)
116
+
117
+ head :no_content
118
+ end
119
+
120
+ private
121
+
122
+ def deployment
123
+ @deployment ||= deployments.find(params[:id])
124
+ end
125
+
126
+ def find_or_create_compose_file
127
+ existing_compose_file = resource_project.compose_file
128
+ if compose_file_params.present?
129
+ create_temporary_compose_file
130
+ else
131
+ raise ActiveRecord::RecordNotFound if existing_compose_file.blank?
132
+
133
+ errors = []
134
+ [existing_compose_file, errors]
135
+ end
136
+ end
137
+
138
+ def create_temporary_compose_file
139
+ create_params = {
140
+ project: resource_project,
141
+ user: current_user,
142
+ compose_file_params: compose_file_params,
143
+ dependencies: dependencies_params[:dependencies] || [],
144
+ }
145
+
146
+ kind = UffizziCore::ComposeFile.kind.temporary
147
+ UffizziCore::ComposeFileService.create(create_params, kind)
148
+ end
149
+
150
+ def check_credentials(compose_file)
151
+ credentials = resource_project.account.credentials
152
+ check_credentials_form = UffizziCore::Api::Cli::V1::ComposeFile::CheckCredentialsForm.new
153
+ check_credentials_form.compose_file = compose_file
154
+ check_credentials_form.credentials = credentials
155
+ return check_credentials_form.errors if check_credentials_form.invalid?
156
+
157
+ nil
158
+ end
159
+
160
+ def deployments
161
+ @deployments ||= resource_project.deployments.existed
162
+ end
163
+
164
+ def deployment_params
165
+ params.required(:deployment)
166
+ end
167
+
168
+ def compose_file_params
169
+ params[:compose_file]
170
+ end
171
+
172
+ def dependencies_params
173
+ params.permit(dependencies: [:name, :path, :source, :content])
174
+ end
175
+
176
+ def render_invalid_file
177
+ render json: { errors: { state: ['Invalid compose file'] } }, status: :unprocessable_entity
178
+ end
179
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @resource Project/Secrets
4
+ class UffizziCore::Api::Cli::V1::Projects::SecretsController < UffizziCore::Api::Cli::V1::Projects::ApplicationController
5
+ before_action :authorize_uffizzi_core_api_cli_v1_projects_secrets
6
+
7
+ # Get secrets for the project
8
+ #
9
+ # @path [GET] /api/cli/v1/projects/{project_slug}/secrets
10
+ # @parameter project_slug(required,path) [string]
11
+ # @response [object<secrets: Array<object<name: string, created_at: date, updated_at: date>>>] 200 OK
12
+ # @response 401 Not authorized
13
+ def index
14
+ respond_with resource_project.secrets, root: :secrets
15
+ end
16
+
17
+ # Add secret to project
18
+ #
19
+ # @path [POST] /api/cli/v1/projects/{project_slug}/secrets/bulk_create
20
+ # @parameter project_slug(required,path) [string]
21
+ # @parameter secrets(required,body) [object<secrets: Array<object <name: string, value: string>>>]
22
+ # @response [object<secrets: Array<object<name: string, created_at: date, updated_at: date>>>] 201 Created
23
+ # @response 422 A compose file already exists for this project
24
+ # @response 401 Not authorized
25
+ def bulk_create
26
+ secrets_form = UffizziCore::Api::Cli::V1::Secret::BulkAssignForm.new
27
+ secrets_form.secrets = resource_project.secrets
28
+ secrets_form.assign_secrets(secrets_params)
29
+ return respond_with secrets_form unless secrets_form.valid?
30
+
31
+ resource_project.secrets.replace(secrets_form.secrets)
32
+
33
+ UffizziCore::ProjectService.update_compose_secrets(resource_project)
34
+
35
+ respond_with resource_project.secrets, root: :secrets
36
+ end
37
+
38
+ # Delete a secret from project by secret name
39
+ #
40
+ # @path [DELETE] /api/cli/v1/projects/{project_slug}/secrets/{secret_name}
41
+ # @parameter project_slug(required,path) [string]
42
+ # @response [Project] 200 OK
43
+ # @response 404
44
+ # @response 401 Not authorized
45
+ def destroy
46
+ secret_name = CGI.unescape(params[:id])
47
+ secret = resource_project.secrets.find_by!(name: secret_name)
48
+
49
+ UffizziCore::ProjectService.update_compose_secret_errors(resource_project, secret)
50
+
51
+ secret.destroy
52
+
53
+ head :no_content
54
+ end
55
+
56
+ private
57
+
58
+ def secrets_params
59
+ params.require(:secrets)
60
+ end
61
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @resource Project
4
+
5
+ class UffizziCore::Api::Cli::V1::ProjectsController < UffizziCore::Api::Cli::V1::ApplicationController
6
+ before_action :authorize_uffizzi_core_api_cli_v1_projects
7
+
8
+ # Get projects of current user
9
+ #
10
+ # @path [GET] /api/cli/v1/projects
11
+ #
12
+ # @response [object<projects: Array<object<slug: string, name: string>> >] 200 OK
13
+ # @response 401 Not authorized
14
+ def index
15
+ projects = current_user.projects.active.order(updated_at: :desc)
16
+
17
+ respond_with projects, each_serializer: UffizziCore::Api::Cli::V1::ShortProjectSerializer
18
+ end
19
+
20
+ # Get a project by slug
21
+ #
22
+ # @path [GET] /api/cli/v1/projects/{slug}
23
+ #
24
+ # @response <object< project: Project>> 200 OK
25
+ # @response 404 Not Found
26
+ # @response 401 Not authorized
27
+ def show
28
+ project = current_user.projects.find_by!(slug: params[:slug])
29
+
30
+ respond_with project
31
+ end
32
+
33
+ # Create a project
34
+ #
35
+ # @path [POST] /api/cli/v1/projects
36
+ # @parameter params(required,body) [object<name: string, slug: string, description: string>]
37
+ #
38
+ # @response <object< project: Project>> 200 OK
39
+ # @response 404 Not Found
40
+ # @response 401 Not authorized
41
+ # @response [object<errors: object<password: string >>] 422 Unprocessable entity
42
+
43
+ def create
44
+ project_form = UffizziCore::Api::Cli::V1::Project::CreateForm.new(project_params)
45
+ project_form.account = current_user.organizational_account
46
+
47
+ if project_form.save
48
+ current_membership = current_user.memberships.find_by(account: current_user.organizational_account)
49
+ user_projects = []
50
+
51
+ if current_membership.developer?
52
+ user_projects << { project: project_form, user: current_user, role: UffizziCore::UserProject.role.developer }
53
+ end
54
+
55
+ current_user.organizational_account.memberships.where(role: UffizziCore::Membership.role.admin).map do |membership|
56
+ user_projects << { project: project_form, user: membership.user, role: UffizziCore::UserProject.role.admin }
57
+ end
58
+
59
+ UffizziCore::UserProject.create!(user_projects)
60
+ end
61
+
62
+ respond_with project_form
63
+ end
64
+
65
+ # Delete a project
66
+ #
67
+ # @path [DELETE] /api/cli/v1/projects/{slug}
68
+ #
69
+ # @response 204 No content
70
+ # @response 404 Not Found
71
+ # @response 401 Not authorized
72
+
73
+ def destroy
74
+ project = current_user.organizational_account.active_projects.find_by!(slug: params[:slug])
75
+ project.disable!
76
+
77
+ head :no_content
78
+ end
79
+
80
+ private
81
+
82
+ def project_params
83
+ params.require(:project)
84
+ end
85
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @resource Uffizzi
4
+
5
+ class UffizziCore::Api::Cli::V1::SessionsController < UffizziCore::Api::Cli::V1::ApplicationController
6
+ skip_before_action :authenticate_request!, only: [:create]
7
+
8
+ # Create session
9
+ #
10
+ # @path [POST] /api/cli/v1/session
11
+ #
12
+ # @parameter user(required,body) [object<email: string, password: string >]
13
+ # @response [object<user: object<accounts: Array<object<id: integer, state: string>> >>] 201 Created successfully
14
+ # @response [object<errors: object<password: string >>] 422 Unprocessable entity
15
+ def create
16
+ session_form = UffizziCore::Api::Cli::V1::SessionCreateForm.new(session_params)
17
+
18
+ if session_form.valid?
19
+ sign_in(session_form.user)
20
+
21
+ return respond_with session_form.user
22
+ end
23
+
24
+ respond_with session_form
25
+ end
26
+
27
+ # Destroy session
28
+ #
29
+ # @path [DELETE] /api/cli/v1/session
30
+ #
31
+ # @response 204 No Content
32
+ def destroy
33
+ sign_out
34
+
35
+ head :no_content
36
+ end
37
+
38
+ private
39
+
40
+ def session_params
41
+ params.require(:user).permit(:email, :password)
42
+ end
43
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ApplicationController < ActionController::Base
4
+ include Pundit
5
+ include UffizziCore::ResponseService
6
+ include UffizziCore::AuthManagement
7
+ include UffizziCore::AuthorizationConcern
8
+ include UffizziCore::DependencyInjectionConcern
9
+
10
+ DEFAULT_PAGE = 1
11
+ DEFAULT_PER_PAGE = 20
12
+
13
+ protect_from_forgery with: :exception
14
+ rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
15
+ RESCUABLE_EXCEPTIONS = [RuntimeError, TypeError, NameError, ArgumentError, SyntaxError].freeze
16
+ rescue_from *RESCUABLE_EXCEPTIONS do |exception|
17
+ render_server_error(exception)
18
+ end
19
+
20
+ before_action :authenticate_request!
21
+ skip_before_action :verify_authenticity_token
22
+ respond_to :json
23
+
24
+ def policy_context
25
+ UffizziCore::BaseContext.new(current_user, user_access_module, params)
26
+ end
27
+
28
+ def self.responder
29
+ UffizziCore::JsonResponder
30
+ end
31
+
32
+ def render_not_found
33
+ render json: { errors: { title: ['Resource Not Found'] } }, status: :not_found
34
+ end
35
+
36
+ def render_server_error(error)
37
+ render json: { errors: { title: [error] } }, status: :internal_server_error
38
+ end
39
+
40
+ def render_errors(errors)
41
+ json = { errors: errors }
42
+
43
+ render json: json, status: :unprocessable_entity
44
+ end
45
+
46
+ def q_param
47
+ params[:q] || ActionController::Parameters.new
48
+ end
49
+
50
+ def page
51
+ params[:page] || DEFAULT_PAGE
52
+ end
53
+
54
+ def per_page
55
+ params[:per_page] || DEFAULT_PER_PAGE
56
+ end
57
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ComposeFile::BuildError < StandardError
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ComposeFile::CredentialError < StandardError
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ComposeFile::ParseError < StandardError
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ComposeFile::SecretsError < StandardError
4
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Deployment::ImagePullError < StandardError
4
+ attr_reader :deployment_id
5
+
6
+ def initialize(deployment_id)
7
+ super
8
+ @deployment_id = deployment_id
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::DeploymentNotFoundError < StandardError
4
+ attr_reader :deployment_id
5
+
6
+ def initialize(deployment_id)
7
+ super
8
+ @deployment_id = deployment_id
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Account::Credential::CheckCredentialForm
4
+ include UffizziCore::ApplicationFormWithoutActiveRecord
5
+
6
+ attribute :type
7
+ attribute :account
8
+
9
+ validate :credential_exists?
10
+
11
+ private
12
+
13
+ def credential_exists?
14
+ errors.add(:type, 'Credential of that type already exist.') if account.credentials.by_type(type).exists?
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Account::Credential::CreateForm < UffizziCore::Credential
4
+ include UffizziCore::ApplicationForm
5
+
6
+ permit :type, :registry_url, :username, :password
7
+
8
+ validates :password, presence: { message: :password_blank }
9
+ validate :check_registry_url, if: -> { errors[:password].empty? }
10
+ validate :check_credential_correctness, if: -> { errors[:password].empty? }
11
+ validate :credential_exists?, if: -> { errors[:password].empty? }
12
+
13
+ private
14
+
15
+ def check_registry_url
16
+ errors.add(:registry_url, :invalid_scheme) if URI.parse(registry_url).scheme.nil?
17
+ end
18
+
19
+ def check_credential_correctness
20
+ errors.add(:username, :incorrect) unless UffizziCore::CredentialService.correct_credentials?(self)
21
+ end
22
+
23
+ def credential_exists?
24
+ errors.add(:type, :exist) if account.credentials.by_type(type).exists?
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ComposeFile::CheckCredentialsForm
4
+ include UffizziCore::ApplicationFormWithoutActiveRecord
5
+
6
+ attribute :compose_file
7
+ attribute :credentials
8
+
9
+ validate :check_containers_credentials
10
+
11
+ private
12
+
13
+ def check_containers_credentials
14
+ compose_content = Base64.decode64(compose_file.content)
15
+ compose_data = UffizziCore::ComposeFileService.parse(compose_content)
16
+
17
+ UffizziCore::ComposeFileService.containers_credentials(compose_data, credentials)
18
+ rescue UffizziCore::ComposeFile::CredentialError => e
19
+ errors.add(:credentials, e.message)
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ComposeFile::CliForm
4
+ include UffizziCore::ApplicationFormWithoutActiveRecord
5
+
6
+ attribute :compose_content_data, Hash
7
+ attribute :compose_data, Hash
8
+ attribute :compose_dependencies, Array
9
+ attribute :compose_repositories, Array
10
+ attribute :content, String
11
+
12
+ validates :content, presence: true
13
+
14
+ validate :check_compose_parsed_data, if: -> { errors[:content].empty? }
15
+
16
+ def check_compose_parsed_data
17
+ compose_content = Base64.decode64(content)
18
+ self.compose_data = UffizziCore::ComposeFileService.parse(compose_content)
19
+ rescue UffizziCore::ComposeFile::ParseError => e
20
+ errors.add(:content, e.message)
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ComposeFile::CreateForm < UffizziCore::ComposeFile
4
+ include UffizziCore::ApplicationForm
5
+
6
+ permit :source, :path, :content
7
+
8
+ validates :source, presence: true
9
+ validates :source, uniqueness: { scope: :project_id, message: 'A compose file with the same source already exists for this project' },
10
+ if: -> { kind.main? }
11
+ validates :path, presence: true
12
+ validates :content, presence: true
13
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ComposeFile::TemplateForm
4
+ include UffizziCore::ApplicationFormWithoutActiveRecord
5
+
6
+ SECRETS_ERROR_KEY = 'secret_variables'
7
+ TEMPLATE_BUILD_ERROR_KEY = 'template_build_error'
8
+
9
+ attribute :credentials
10
+ attribute :project, UffizziCore::Project
11
+ attribute :user, UffizziCore::User
12
+ attribute :compose_data, Hash
13
+ attribute :source, String
14
+ attribute :template_attributes, Hash
15
+ attribute :template_build_error, String
16
+ attribute :compose_dependencies, Array
17
+ attribute :compose_repositories, Array
18
+
19
+ validate :check_template_attributes
20
+
21
+ def assign_template_attributes!
22
+ self.template_attributes = UffizziCore::ComposeFileService.build_template_attributes(
23
+ compose_data,
24
+ source,
25
+ credentials,
26
+ project,
27
+ compose_dependencies,
28
+ compose_repositories,
29
+ )
30
+ rescue StandardError => e
31
+ self.template_build_error = e
32
+ end
33
+
34
+ private
35
+
36
+ def check_template_attributes
37
+ case template_build_error
38
+ when UffizziCore::ComposeFile::SecretsError
39
+ errors.add(SECRETS_ERROR_KEY, template_build_error.message)
40
+ when UffizziCore::ComposeFile::BuildError
41
+ errors.add(TEMPLATE_BUILD_ERROR_KEY, template_build_error.message)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ComposeFile::UpdateForm < UffizziCore::ComposeFile
4
+ include UffizziCore::ApplicationForm
5
+
6
+ permit :content, :source, :path
7
+
8
+ validates :content, presence: true
9
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ConfigFile::CreateForm < UffizziCore::ConfigFile
4
+ include UffizziCore::ApplicationForm
5
+
6
+ permit :filename, :kind, :payload
7
+
8
+ validates :filename, presence: true
9
+ validates :kind, presence: true
10
+ validates :payload, presence: true
11
+ end