uffizzi_core 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/app/clients/uffizzi_core/docker_hub_client.rb +2 -0
  3. data/app/clients/uffizzi_core/github_container_registry_client/request_result.rb +7 -0
  4. data/app/clients/uffizzi_core/github_container_registry_client.rb +52 -0
  5. data/app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb +2 -2
  6. data/app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb +45 -9
  7. data/app/controllers/uffizzi_core/api/cli/v1/projects/compose_files_controller.rb +2 -2
  8. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/application_controller.rb +1 -1
  9. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments_controller.rb +41 -10
  10. data/app/controllers/uffizzi_core/api/cli/v1/projects/secrets_controller.rb +18 -26
  11. data/app/controllers/uffizzi_core/application_controller.rb +9 -3
  12. data/app/errors/uffizzi_core/deployment/image_pull_error.rb +10 -0
  13. data/app/forms/uffizzi_core/api/cli/v1/account/credential/check_credential_form.rb +16 -0
  14. data/app/forms/uffizzi_core/api/cli/v1/account/credential/create_form.rb +1 -1
  15. data/app/forms/uffizzi_core/api/cli/v1/compose_file/check_credentials_form.rb +2 -2
  16. data/app/forms/uffizzi_core/api/cli/v1/compose_file/cli_form.rb +1 -18
  17. data/app/forms/uffizzi_core/api/cli/v1/compose_file/template_form.rb +1 -1
  18. data/app/forms/uffizzi_core/api/cli/v1/deployment/update_form.rb +90 -0
  19. data/app/forms/uffizzi_core/api/cli/v1/project/update_form.rb +1 -31
  20. data/app/forms/uffizzi_core/api/cli/v1/secret/bulk_assign_form.rb +39 -0
  21. data/app/jobs/uffizzi_core/deployment/manage_deploy_activity_item_job.rb +22 -3
  22. data/app/lib/uffizzi_core/rbac/user_access_service.rb +12 -14
  23. data/app/models/uffizzi_core/account.rb +1 -19
  24. data/app/models/uffizzi_core/activity_item.rb +1 -6
  25. data/app/models/uffizzi_core/build.rb +1 -1
  26. data/app/models/uffizzi_core/comment.rb +1 -1
  27. data/app/models/uffizzi_core/compose_file.rb +1 -1
  28. data/app/models/uffizzi_core/config_file.rb +1 -1
  29. data/app/models/uffizzi_core/container.rb +1 -1
  30. data/app/models/uffizzi_core/container_config_file.rb +1 -1
  31. data/app/models/uffizzi_core/coupon.rb +1 -1
  32. data/app/models/uffizzi_core/credential/github_container_registry.rb +4 -0
  33. data/app/models/uffizzi_core/credential.rb +3 -6
  34. data/app/models/uffizzi_core/deployment.rb +11 -2
  35. data/app/models/uffizzi_core/event.rb +1 -1
  36. data/app/models/uffizzi_core/invitation.rb +1 -1
  37. data/app/models/uffizzi_core/membership.rb +1 -1
  38. data/app/models/uffizzi_core/payment.rb +1 -1
  39. data/app/models/uffizzi_core/price.rb +1 -1
  40. data/app/models/uffizzi_core/product.rb +1 -1
  41. data/app/models/uffizzi_core/project.rb +5 -11
  42. data/app/models/uffizzi_core/rating.rb +1 -1
  43. data/app/models/uffizzi_core/repo/github_container_registry.rb +4 -0
  44. data/app/models/uffizzi_core/repo.rb +1 -11
  45. data/app/models/uffizzi_core/role.rb +2 -2
  46. data/app/models/uffizzi_core/secret.rb +9 -0
  47. data/app/models/uffizzi_core/template.rb +1 -1
  48. data/app/models/uffizzi_core/user.rb +1 -1
  49. data/app/models/uffizzi_core/user_project.rb +1 -1
  50. data/app/policies/uffizzi_core/api/cli/v1/account/credentials_policy.rb +8 -0
  51. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments_policy.rb +4 -0
  52. data/app/repositories/uffizzi_core/credential_repo.rb +17 -22
  53. data/app/repositories/uffizzi_core/deployment_repo.rb +1 -0
  54. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +8 -0
  55. data/app/serializers/uffizzi_core/api/cli/v1/projects/secret_serializer.rb +5 -0
  56. data/app/serializers/uffizzi_core/controller/apply_config_file/config_file_serializer.rb +5 -0
  57. data/app/serializers/uffizzi_core/controller/create_credential/credential_serializer.rb +7 -3
  58. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer/container_config_file_serializer/config_file_serializer.rb +8 -0
  59. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer/container_config_file_serializer.rb +7 -0
  60. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +4 -3
  61. data/app/services/uffizzi_core/activity_item_service.rb +16 -26
  62. data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +11 -18
  63. data/app/services/uffizzi_core/compose_file/container_service.rb +13 -9
  64. data/app/services/uffizzi_core/compose_file/dependencies_service.rb +1 -0
  65. data/app/services/uffizzi_core/compose_file/services_options_service.rb +2 -2
  66. data/app/services/uffizzi_core/compose_file_service.rb +148 -0
  67. data/app/services/uffizzi_core/container_service.rb +1 -16
  68. data/app/services/uffizzi_core/controller_service.rb +7 -1
  69. data/app/services/uffizzi_core/credential_service.rb +2 -2
  70. data/app/services/uffizzi_core/deployment_service.rb +28 -7
  71. data/app/services/uffizzi_core/github_container_registry/credential_service.rb +24 -0
  72. data/app/services/uffizzi_core/manage_activity_items_service.rb +4 -19
  73. data/app/services/uffizzi_core/repo_service.rb +2 -137
  74. data/app/services/uffizzi_core/user_generator_service.rb +78 -0
  75. data/config/locales/en.activerecord.yml +5 -0
  76. data/config/locales/en.yml +4 -1
  77. data/config/routes.rb +6 -2
  78. data/db/migrate/20220309110201_remove_secrets_from_projects.rb +7 -0
  79. data/db/migrate/20220310110150_create_project_secrets.rb +14 -0
  80. data/db/migrate/20220329123323_rename_project_secrets_to_secrets.rb +7 -0
  81. data/db/migrate/20220329124542_add_resource_to_secrets.rb +7 -0
  82. data/db/migrate/20220329143241_remove_project_ref_from_secrets.rb +7 -0
  83. data/lib/tasks/uffizzi_core_tasks.rake +5 -0
  84. data/lib/uffizzi_core/engine.rb +35 -0
  85. data/lib/uffizzi_core/version.rb +1 -1
  86. data/lib/uffizzi_core.rb +1 -30
  87. data/swagger/v1/swagger.json +220 -11
  88. metadata +45 -25
  89. data/app/clients/uffizzi_core/github/app_client.rb +0 -19
  90. data/app/clients/uffizzi_core/github/installation_client.rb +0 -11
  91. data/app/clients/uffizzi_core/github/user_client.rb +0 -51
  92. data/app/errors/uffizzi_core/compose_file/not_found_error.rb +0 -4
  93. data/app/forms/uffizzi_core/api/cli/v1/project/delete_secret_form.rb +0 -27
  94. data/app/jobs/uffizzi_core/deployment/send_github_preview_message_job.rb +0 -13
  95. data/app/services/uffizzi_core/cli/compose_file_service.rb +0 -203
  96. data/app/services/uffizzi_core/compose_file/builders/github_repo_builder_service.rb +0 -59
  97. data/app/services/uffizzi_core/compose_file/services_options/build_service.rb +0 -93
  98. data/app/services/uffizzi_core/compose_file/update_service.rb +0 -29
  99. data/app/services/uffizzi_core/github/app_service.rb +0 -51
  100. data/app/services/uffizzi_core/github/credential_service.rb +0 -124
  101. data/app/services/uffizzi_core/github/message_service.rb +0 -20
  102. data/app/services/uffizzi_core/github_service.rb +0 -28
  103. data/app/services/uffizzi_core/user_access_service.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3fa1762e392d1748e189b83b1b546d4b6005034de25e15a00189f683d65764fa
4
- data.tar.gz: 7f361a77ac67122c8bdebf1112c4b5f7a4f541e3c55ac5f75568ffbaa0e48c20
3
+ metadata.gz: 49bbe08dfa41ecd2c4c9b6d2f488334db9ba40ec952b2a249d55e3be08b819aa
4
+ data.tar.gz: 37a606bcb357ef8b4b072b8be528c08a47569d8da3e3cf0fed00ec1aff110648
5
5
  SHA512:
6
- metadata.gz: 49a8755ddc0743460d1b0f52d787f4c6fe17a68291eabcd20efdd1661007750fdfdf4a336665b97c86500fc5c5f03c44eda25ed9ec9166d6c608be9298c30465
7
- data.tar.gz: 9132eb4e35621f7a45e0a41833448c329a320d10651a000e285edda8c96c06c3f5366f6658a83f527e941af3398c652b0ce66ebc1ef058df2b6d90f03b370dca
6
+ metadata.gz: 0fcd5124498ab741cb1d03cada959eb0b821f15f8aede73f225ac0ac3a983b8deafecbe7a5905e8256c5b6f6c370348a4d85d6701b718b07bf9f56de2aea0fb2
7
+ data.tar.gz: 007c508efa144dfa7d617e36f12c00e3895cc871c9dc6cdfb00e4affd19eac3fc9ef4112898e7acf513408cae6077ff1e0bd5c2c8ffa1c71375c950c085be28e
@@ -19,6 +19,8 @@ class UffizziCore::DockerHubClient
19
19
  response = connection.post(url, params)
20
20
  request_result = RequestResult.new(result: response.body)
21
21
  request_result.result.token
22
+ rescue NoMethodError
23
+ nil
22
24
  end
23
25
 
24
26
  def public_images(q:, page: 1, per_page: 25)
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::GithubContainerRegistryClient
4
+ class RequestResult < Hashie::Mash
5
+ disable_warnings :key
6
+ end
7
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::GithubContainerRegistryClient
4
+ attr_accessor :token, :registry_url
5
+
6
+ def initialize(registry_url:, username:, password:)
7
+ @registry_url = registry_url
8
+ @username = username
9
+ @password = password
10
+ @token = access_token&.result&.token
11
+ end
12
+
13
+ def access_token
14
+ service = URI.parse(registry_url).hostname
15
+ url = "/token?service=#{service}"
16
+
17
+ response = connection.get(url, {})
18
+
19
+ RequestResult.new(result: response.body)
20
+ end
21
+
22
+ def authentificated?
23
+ token.present?
24
+ end
25
+
26
+ def manifests(image:, tag:)
27
+ url = "/v2/#{@username}/#{image}/manifests/#{tag}"
28
+ response = token_connection.get(url)
29
+
30
+ RequestResult.quiet.new(result: response.body, headers: response.headers)
31
+ end
32
+
33
+ private
34
+
35
+ def connection
36
+ Faraday.new(registry_url) do |conn|
37
+ conn.request(:basic_auth, @username, @password)
38
+ conn.request(:json)
39
+ conn.response(:json)
40
+ conn.adapter(Faraday.default_adapter)
41
+ end
42
+ end
43
+
44
+ def token_connection
45
+ Faraday.new(registry_url) do |conn|
46
+ conn.request(:authorization, 'Bearer', token)
47
+ conn.request(:json)
48
+ conn.response(:json)
49
+ conn.adapter(Faraday.default_adapter)
50
+ end
51
+ end
52
+ end
@@ -4,7 +4,7 @@ module UffizziCore::DependencyInjectionConcern
4
4
  def user_access_module
5
5
  return unless module_exists?(:rbac)
6
6
 
7
- UffizziCore::UserAccessService.new(module_class(:rbac))
7
+ module_class(:rbac).new
8
8
  end
9
9
 
10
10
  private
@@ -14,6 +14,6 @@ module UffizziCore::DependencyInjectionConcern
14
14
  end
15
15
 
16
16
  def module_class(module_name)
17
- UffizziCore.dependencies[module_name]&.constantize
17
+ Rails.application.config.uffizzi_core[:dependencies][module_name]&.constantize
18
18
  end
19
19
  end
@@ -4,6 +4,17 @@
4
4
  class UffizziCore::Api::Cli::V1::Account::CredentialsController < UffizziCore::Api::Cli::V1::Account::ApplicationController
5
5
  before_action :authorize_uffizzi_core_api_cli_v1_account_credentials
6
6
 
7
+ # Get a list of accounts credential
8
+ #
9
+ # @path [GET] /api/cli/v1/account/credentials
10
+ #
11
+ # @parameter credential(required,body) [object<username:string, password: string, type:string>]
12
+ def index
13
+ credentials = resource_account.credentials.pluck(:type)
14
+
15
+ render json: { credentials: credentials }, status: :ok
16
+ end
17
+
7
18
  # rubocop:disable Layout/LineLength
8
19
  # Create account credential
9
20
  #
@@ -14,26 +25,39 @@ class UffizziCore::Api::Cli::V1::Account::CredentialsController < UffizziCore::A
14
25
  # @response [object<errors>] 422 Unprocessable entity
15
26
  #
16
27
  # @example
17
- # type can be one of UffizziCore::Credential::Amazon, UffizziCore::Credential::Azure, UffizziCore::Credential::DockerHub, UffizziCore::Credential::Google
28
+ # type can be one of UffizziCore::Credential::Amazon, UffizziCore::Credential::Azure, UffizziCore::Credential::DockerHub, UffizziCore::Credential::Google, UffizziCore::Credential::GithubContainerRegistry
18
29
  # rubocop:enable Layout/LineLength
19
30
  def create
20
31
  credential_form = UffizziCore::Api::Cli::V1::Account::Credential::CreateForm.new
21
32
  credential_form.assign_attributes(credential_params)
22
33
  credential_form.account = resource_account
23
- credential_form.registry_url = Settings.docker_hub.registry_url if credential_form.docker_hub?
24
- if credential_form.google?
25
- credential_form.registry_url = Settings.google.registry_url
26
- credential_form.username = '_json_key'
27
- end
34
+ credential_form.registry_url = registry_url(credential_form)
35
+ credential_form.username = '_json_key' if credential_form.google?
28
36
  credential_form.activate
29
37
 
30
- if credential_form.save
31
- UffizziCore::Account::CreateCredentialJob.perform_async(credential_form.id)
32
- end
38
+ UffizziCore::Account::CreateCredentialJob.perform_async(credential_form.id) if credential_form.save
33
39
 
34
40
  respond_with credential_form
35
41
  end
36
42
 
43
+ # Check if credential of the type already exists in the account
44
+ #
45
+ # @path [GET] /api/cli/v1/account/credentials/{type}/check_credential
46
+ #
47
+ # @parameter credential(required,body) [object<type:string>]
48
+ # @response 422 Unprocessable entity
49
+ # @response 200 OK
50
+ def check_credential
51
+ credential_form = UffizziCore::Api::Cli::V1::Account::Credential::CheckCredentialForm.new
52
+ credential_form.type = params[:type]
53
+ credential_form.account = resource_account
54
+ if credential_form.valid?
55
+ respond_with credential_form
56
+ else
57
+ respond_with credential_form.errors, status: :unprocessable_entity
58
+ end
59
+ end
60
+
37
61
  # Delete account credential
38
62
  #
39
63
  # @path [DELETE] /api/cli/v1/account/credentials/{type}
@@ -52,4 +76,16 @@ class UffizziCore::Api::Cli::V1::Account::CredentialsController < UffizziCore::A
52
76
  def credential_params
53
77
  params.require(:credential)
54
78
  end
79
+
80
+ def registry_url(credential_form)
81
+ if credential_form.docker_hub?
82
+ Settings.docker_hub.registry_url
83
+ elsif credential_form.google?
84
+ Settings.google.registry_url
85
+ elsif credential_form.github_container_registry?
86
+ Settings.github_container_registry.registry_url
87
+ else
88
+ credential_form.registry_url
89
+ end
90
+ end
55
91
  end
@@ -78,10 +78,10 @@ class UffizziCore::Api::Cli::V1::Projects::ComposeFilesController < UffizziCore:
78
78
  def create_or_update_compose_file(params)
79
79
  existing_compose_file = resource_project.compose_file
80
80
  if existing_compose_file.present?
81
- UffizziCore::Cli::ComposeFileService.update(existing_compose_file, params)
81
+ UffizziCore::ComposeFileService.update(existing_compose_file, params)
82
82
  else
83
83
  kind = UffizziCore::ComposeFile.kind.main
84
- UffizziCore::Cli::ComposeFileService.create(params, kind)
84
+ UffizziCore::ComposeFileService.create(params, kind)
85
85
  end
86
86
  end
87
87
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  class UffizziCore::Api::Cli::V1::Projects::Deployments::ApplicationController < UffizziCore::Api::Cli::V1::Projects::ApplicationController
4
4
  def resource_deployment
5
- @resource_deployment ||= resource_project.deployments.find(params[:deployment_id])
5
+ @resource_deployment ||= resource_project.deployments.active.find(params[:deployment_id])
6
6
  end
7
7
  end
@@ -56,6 +56,33 @@ class UffizziCore::Api::Cli::V1::Projects::DeploymentsController < UffizziCore::
56
56
  respond_with deployment
57
57
  end
58
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
+
59
86
  # @path [POST] /api/cli/v1/projects/{project_slug}/deployments/{id}/deploy_containers
60
87
  #
61
88
  # @parameter project_slug(required,path) [string] The project slug
@@ -99,15 +126,7 @@ class UffizziCore::Api::Cli::V1::Projects::DeploymentsController < UffizziCore::
99
126
  def find_or_create_compose_file
100
127
  existing_compose_file = resource_project.compose_file
101
128
  if compose_file_params.present?
102
- create_params = {
103
- project: resource_project,
104
- user: current_user,
105
- compose_file_params: compose_file_params,
106
- dependencies: dependencies_params[:dependencies] || [],
107
- }
108
-
109
- kind = UffizziCore::ComposeFile.kind.temporary
110
- UffizziCore::Cli::ComposeFileService.create(create_params, kind)
129
+ create_temporary_compose_file
111
130
  else
112
131
  raise ActiveRecord::RecordNotFound if existing_compose_file.blank?
113
132
 
@@ -116,6 +135,18 @@ class UffizziCore::Api::Cli::V1::Projects::DeploymentsController < UffizziCore::
116
135
  end
117
136
  end
118
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
+
119
150
  def check_credentials(compose_file)
120
151
  credentials = resource_project.account.credentials
121
152
  check_credentials_form = UffizziCore::Api::Cli::V1::ComposeFile::CheckCredentialsForm.new
@@ -127,7 +158,7 @@ class UffizziCore::Api::Cli::V1::Projects::DeploymentsController < UffizziCore::
127
158
  end
128
159
 
129
160
  def deployments
130
- @deployments ||= resource_project.deployments.active
161
+ @deployments ||= resource_project.deployments.existed
131
162
  end
132
163
 
133
164
  def deployment_params
@@ -8,13 +8,10 @@ class UffizziCore::Api::Cli::V1::Projects::SecretsController < UffizziCore::Api:
8
8
  #
9
9
  # @path [GET] /api/cli/v1/projects/{project_slug}/secrets
10
10
  # @parameter project_slug(required,path) [string]
11
- # @response [object<secrets: Array<object<name: string>> >] 200 OK
11
+ # @response [object<secrets: Array<object<name: string, created_at: date, updated_at: date>>>] 200 OK
12
12
  # @response 401 Not authorized
13
13
  def index
14
- project_secrets = resource_project.secrets.present? ? resource_project.secrets : []
15
- secrets = project_secrets.map { |secret| { name: secret['name'] } }
16
-
17
- render json: { secrets: secrets }, status: :ok
14
+ respond_with resource_project.secrets, root: :secrets
18
15
  end
19
16
 
20
17
  # Add secret to project
@@ -22,43 +19,38 @@ class UffizziCore::Api::Cli::V1::Projects::SecretsController < UffizziCore::Api:
22
19
  # @path [POST] /api/cli/v1/projects/{project_slug}/secrets/bulk_create
23
20
  # @parameter project_slug(required,path) [string]
24
21
  # @parameter secrets(required,body) [object<secrets: Array<object <name: string, value: string>>>]
25
- # @response [object<secrets: Array<object<name: string>>>] 201 Created
22
+ # @response [object<secrets: Array<object<name: string, created_at: date, updated_at: date>>>] 201 Created
26
23
  # @response 422 A compose file already exists for this project
27
24
  # @response 401 Not authorized
28
25
  def bulk_create
29
- project_form = resource_project.becomes(UffizziCore::Api::Cli::V1::Project::UpdateForm)
30
- project_form.assign_secrets!(secrets_params)
31
- return render json: { errors: project_form.errors }, status: :unprocessable_entity unless project_form.save
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
32
 
33
- UffizziCore::ProjectService.update_compose_secrets(project_form)
34
- secrets = project_form.secrets.map { |secret| { name: secret['name'] } }
33
+ UffizziCore::ProjectService.update_compose_secrets(resource_project)
35
34
 
36
- render json: { secrets: secrets }, status: :created
35
+ respond_with resource_project.secrets, root: :secrets
37
36
  end
38
37
 
39
- # Delete a secret from project by secret id
38
+ # Delete a secret from project by secret name
40
39
  #
41
- # @path [DELETE] /api/cli/v1/projects/{project_slug}/secrets/{id}
40
+ # @path [DELETE] /api/cli/v1/projects/{project_slug}/secrets/{secret_name}
42
41
  # @parameter project_slug(required,path) [string]
43
42
  # @response [Project] 200 OK
44
- # @response 422
43
+ # @response 404
45
44
  # @response 401 Not authorized
46
45
  def destroy
47
46
  secret_name = CGI.unescape(params[:id])
48
- secret = OpenStruct.new(name: secret_name)
49
- project_form = resource_project.becomes(UffizziCore::Api::Cli::V1::Project::DeleteSecretForm)
50
- project_form.secret = secret
47
+ secret = resource_project.secrets.find_by!(name: secret_name)
51
48
 
52
- if project_form.invalid?
53
- return respond_with project_form
54
- end
49
+ UffizziCore::ProjectService.update_compose_secret_errors(resource_project, secret)
55
50
 
56
- project_form.delete_secret!
57
- if project_form.save!(validate: false)
58
- UffizziCore::ProjectService.update_compose_secret_errors(project_form, secret)
59
- end
51
+ secret.destroy
60
52
 
61
- respond_with project_form
53
+ head :no_content
62
54
  end
63
55
 
64
56
  private
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::ApplicationController < ActionController::Base
4
- include Pundit
4
+ include Pundit::Authorization
5
5
  include UffizziCore::ResponseService
6
6
  include UffizziCore::AuthManagement
7
7
  include UffizziCore::AuthorizationConcern
@@ -12,11 +12,13 @@ class UffizziCore::ApplicationController < ActionController::Base
12
12
 
13
13
  protect_from_forgery with: :exception
14
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
15
19
 
16
20
  before_action :authenticate_request!
17
21
  skip_before_action :verify_authenticity_token
18
- rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
19
-
20
22
  respond_to :json
21
23
 
22
24
  def policy_context
@@ -31,6 +33,10 @@ class UffizziCore::ApplicationController < ActionController::Base
31
33
  render json: { errors: { title: ['Resource Not Found'] } }, status: :not_found
32
34
  end
33
35
 
36
+ def render_server_error(error)
37
+ render json: { errors: { title: [error] } }, status: :internal_server_error
38
+ end
39
+
34
40
  def render_errors(errors)
35
41
  json = { errors: errors }
36
42
 
@@ -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,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
@@ -21,6 +21,6 @@ class UffizziCore::Api::Cli::V1::Account::Credential::CreateForm < UffizziCore::
21
21
  end
22
22
 
23
23
  def credential_exists?
24
- errors.add(:type, :exist) if account.credentials.where(type: type).exists?
24
+ errors.add(:type, :exist) if account.credentials.by_type(type).exists?
25
25
  end
26
26
  end
@@ -12,9 +12,9 @@ class UffizziCore::Api::Cli::V1::ComposeFile::CheckCredentialsForm
12
12
 
13
13
  def check_containers_credentials
14
14
  compose_content = Base64.decode64(compose_file.content)
15
- compose_data = UffizziCore::Cli::ComposeFileService.parse(compose_content)
15
+ compose_data = UffizziCore::ComposeFileService.parse(compose_content)
16
16
 
17
- UffizziCore::Cli::ComposeFileService.containers_credentials(compose_data, credentials)
17
+ UffizziCore::ComposeFileService.containers_credentials(compose_data, credentials)
18
18
  rescue UffizziCore::ComposeFile::CredentialError => e
19
19
  errors.add(:credentials, e.message)
20
20
  end
@@ -3,7 +3,6 @@
3
3
  class UffizziCore::Api::Cli::V1::ComposeFile::CliForm
4
4
  include UffizziCore::ApplicationFormWithoutActiveRecord
5
5
 
6
- attribute :credential, UffizziCore::Credential
7
6
  attribute :compose_content_data, Hash
8
7
  attribute :compose_data, Hash
9
8
  attribute :compose_dependencies, Array
@@ -13,27 +12,11 @@ class UffizziCore::Api::Cli::V1::ComposeFile::CliForm
13
12
  validates :content, presence: true
14
13
 
15
14
  validate :check_compose_parsed_data, if: -> { errors[:content].empty? }
16
- validate :check_repositories, if: -> { credential.present? && errors[:content].empty? }
17
- validate :check_branches, if: -> { credential.present? && errors[:content].empty? }
18
15
 
19
16
  def check_compose_parsed_data
20
17
  compose_content = Base64.decode64(content)
21
- self.compose_data = UffizziCore::Cli::ComposeFileService.parse(compose_content)
18
+ self.compose_data = UffizziCore::ComposeFileService.parse(compose_content)
22
19
  rescue UffizziCore::ComposeFile::ParseError => e
23
20
  errors.add(:content, e.message)
24
21
  end
25
-
26
- def check_repositories
27
- self.compose_repositories = UffizziCore::Cli::ComposeFileService.load_repositories(compose_data, credential)
28
- rescue UffizziCore::ComposeFile::NotFoundError => e
29
- errors.add(:content, e.message)
30
- end
31
-
32
- def check_branches
33
- return if compose_repositories.blank?
34
-
35
- UffizziCore::Cli::ComposeFileService.check_github_branches(compose_data, compose_repositories, credential)
36
- rescue UffizziCore::ComposeFile::NotFoundError => e
37
- errors.add(:content, e.message)
38
- end
39
22
  end
@@ -19,7 +19,7 @@ class UffizziCore::Api::Cli::V1::ComposeFile::TemplateForm
19
19
  validate :check_template_attributes
20
20
 
21
21
  def assign_template_attributes!
22
- self.template_attributes = UffizziCore::Cli::ComposeFileService.build_template_attributes(
22
+ self.template_attributes = UffizziCore::ComposeFileService.build_template_attributes(
23
23
  compose_data,
24
24
  source,
25
25
  credentials,
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Deployment::UpdateForm < UffizziCore::Deployment
4
+ include UffizziCore::ApplicationForm
5
+
6
+ permit containers_attributes: [
7
+ :image,
8
+ :name,
9
+ :tag,
10
+ :port,
11
+ :public,
12
+ :memory_limit,
13
+ :memory_request,
14
+ :entrypoint,
15
+ :command,
16
+ :receive_incoming_requests,
17
+ :continuously_deploy,
18
+ { variables: [:name, :value],
19
+ secret_variables: [:name, :value],
20
+ repo_attributes: [
21
+ :namespace,
22
+ :name,
23
+ :slug,
24
+ :type,
25
+ :description,
26
+ :is_private,
27
+ :repository_id,
28
+ :branch,
29
+ :kind,
30
+ :dockerfile_path,
31
+ :dockerfile_context_path,
32
+ :deploy_preview_when_pull_request_is_opened,
33
+ :delete_preview_when_pull_request_is_closed,
34
+ :deploy_preview_when_image_tag_is_created,
35
+ :delete_preview_when_image_tag_is_updated,
36
+ :share_to_github,
37
+ :delete_preview_after,
38
+ { args: [:name, :value] },
39
+ ],
40
+ container_config_files_attributes: [
41
+ :config_file_id,
42
+ :mount_path,
43
+ ] },
44
+ ]
45
+
46
+ validate :check_all_containers_have_unique_ports
47
+ validate :check_exists_ingress_container
48
+ validate :check_max_memory_limit
49
+ validate :check_max_memory_request
50
+
51
+ def assign_dependences!(project, user)
52
+ self.project = project
53
+
54
+ self.containers = containers.map do |container|
55
+ container.repo.project = project if !container.repo.nil?
56
+
57
+ container
58
+ end
59
+
60
+ self.deployed_by = user
61
+
62
+ self
63
+ end
64
+
65
+ private
66
+
67
+ def check_all_containers_have_unique_ports
68
+ active_containers = containers.select(&:active?)
69
+
70
+ errors.add(:containers, :duplicate_ports) unless UffizziCore::DeploymentService.all_containers_have_unique_ports?(active_containers)
71
+ end
72
+
73
+ def check_exists_ingress_container
74
+ active_containers = containers.select(&:active?)
75
+
76
+ errors.add(:containers, :incorrect_ingress_container) unless UffizziCore::DeploymentService.ingress_container?(active_containers)
77
+ end
78
+
79
+ def check_max_memory_limit
80
+ return if UffizziCore::DeploymentService.valid_containers_memory_limit?(self)
81
+
82
+ errors.add(:containers, :max_memory_limit_error, max: project.account.container_memory_limit)
83
+ end
84
+
85
+ def check_max_memory_request
86
+ return if UffizziCore::DeploymentService.valid_containers_memory_request?(self)
87
+
88
+ errors.add(:containers, :max_memory_request_error, max: project.account.container_memory_limit)
89
+ end
90
+ end
@@ -2,39 +2,9 @@
2
2
 
3
3
  class UffizziCore::Api::Cli::V1::Project::UpdateForm < UffizziCore::Project
4
4
  include UffizziCore::ApplicationForm
5
- MAX_SECRET_KEY_LENGTH = 256
6
5
 
7
- permit :name, :slug, :description, secrets: [:name, :value]
6
+ permit :name, :slug, :description
8
7
 
9
8
  validates :name, presence: true, uniqueness: { scope: :account }
10
9
  validates :slug, presence: true, uniqueness: true
11
-
12
- validate :check_duplicates
13
- validate :check_length
14
-
15
- def assign_secrets!(new_secrets)
16
- existing_secrets = secrets.presence || []
17
-
18
- self.secrets = existing_secrets.union(new_secrets)
19
- end
20
-
21
- private
22
-
23
- def check_duplicates
24
- duplicates = []
25
- groupped_secrets = secrets.group_by { |secret| secret['name'] }
26
- groupped_secrets.each_pair do |key, value|
27
- duplicates << key if value.size > 1
28
- end
29
-
30
- error_message = I18n.t('secrets.duplicates_exists', secrets: duplicates.join(', '))
31
- errors.add(:secrets, error_message) if duplicates.present?
32
- end
33
-
34
- def check_length
35
- secrets_with_invalid_key_length = secrets.select { |secret| secret['name'].length > MAX_SECRET_KEY_LENGTH }
36
-
37
- error_message = I18n.t('secrets.invalid_key_length')
38
- errors.add(:secrets, error_message) if secrets_with_invalid_key_length.present?
39
- end
40
10
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Secret::BulkAssignForm
4
+ include UffizziCore::ApplicationFormWithoutActiveRecord
5
+ MAX_SECRET_KEY_LENGTH = 256
6
+
7
+ attribute :secrets, Array
8
+ validate :check_duplicates
9
+ validate :check_length
10
+
11
+ def assign_secrets(new_secrets)
12
+ return if new_secrets.blank?
13
+
14
+ new_secrets.each do |new_secret|
15
+ secret = UffizziCore::Secret.new(name: new_secret['name'], value: new_secret['value'])
16
+ secrets.append(secret)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def check_duplicates
23
+ duplicates = []
24
+ groupped_secrets = secrets.group_by { |secret| secret['name'] }
25
+ groupped_secrets.each_pair do |key, value|
26
+ duplicates << key if value.size > 1
27
+ end
28
+
29
+ error_message = I18n.t('secrets.duplicates_exists', secrets: duplicates.join(', '))
30
+ errors.add(:secrets, error_message) if duplicates.present?
31
+ end
32
+
33
+ def check_length
34
+ secrets_with_invalid_key_length = secrets.select { |secret| secret['name'].length > MAX_SECRET_KEY_LENGTH }
35
+
36
+ error_message = I18n.t('secrets.invalid_key_length')
37
+ errors.add(:secrets, error_message) if secrets_with_invalid_key_length.present?
38
+ end
39
+ end