uffizzi_core 0.1.3 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/clients/uffizzi_core/docker_hub_client.rb +2 -0
- data/app/clients/uffizzi_core/github_container_registry_client/request_result.rb +7 -0
- data/app/clients/uffizzi_core/github_container_registry_client.rb +52 -0
- data/app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb +2 -2
- data/app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb +45 -9
- data/app/controllers/uffizzi_core/api/cli/v1/projects/compose_files_controller.rb +2 -2
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/application_controller.rb +1 -1
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments_controller.rb +41 -10
- data/app/controllers/uffizzi_core/api/cli/v1/projects/secrets_controller.rb +18 -26
- data/app/controllers/uffizzi_core/application_controller.rb +9 -3
- data/app/errors/uffizzi_core/deployment/image_pull_error.rb +10 -0
- data/app/forms/uffizzi_core/api/cli/v1/account/credential/check_credential_form.rb +16 -0
- data/app/forms/uffizzi_core/api/cli/v1/account/credential/create_form.rb +1 -1
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/check_credentials_form.rb +2 -2
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/cli_form.rb +1 -18
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/template_form.rb +1 -1
- data/app/forms/uffizzi_core/api/cli/v1/deployment/update_form.rb +90 -0
- data/app/forms/uffizzi_core/api/cli/v1/project/update_form.rb +1 -31
- data/app/forms/uffizzi_core/api/cli/v1/secret/bulk_assign_form.rb +39 -0
- data/app/jobs/uffizzi_core/deployment/manage_deploy_activity_item_job.rb +22 -3
- data/app/lib/uffizzi_core/rbac/user_access_service.rb +12 -14
- data/app/models/uffizzi_core/account.rb +1 -19
- data/app/models/uffizzi_core/activity_item.rb +1 -6
- data/app/models/uffizzi_core/build.rb +1 -1
- data/app/models/uffizzi_core/comment.rb +1 -1
- data/app/models/uffizzi_core/compose_file.rb +1 -1
- data/app/models/uffizzi_core/config_file.rb +1 -1
- data/app/models/uffizzi_core/container.rb +1 -1
- data/app/models/uffizzi_core/container_config_file.rb +1 -1
- data/app/models/uffizzi_core/coupon.rb +1 -1
- data/app/models/uffizzi_core/credential/github_container_registry.rb +4 -0
- data/app/models/uffizzi_core/credential.rb +3 -6
- data/app/models/uffizzi_core/deployment.rb +11 -2
- data/app/models/uffizzi_core/event.rb +1 -1
- data/app/models/uffizzi_core/invitation.rb +1 -1
- data/app/models/uffizzi_core/membership.rb +1 -1
- data/app/models/uffizzi_core/payment.rb +1 -1
- data/app/models/uffizzi_core/price.rb +1 -1
- data/app/models/uffizzi_core/product.rb +1 -1
- data/app/models/uffizzi_core/project.rb +5 -11
- data/app/models/uffizzi_core/rating.rb +1 -1
- data/app/models/uffizzi_core/repo/github_container_registry.rb +4 -0
- data/app/models/uffizzi_core/repo.rb +1 -11
- data/app/models/uffizzi_core/role.rb +2 -2
- data/app/models/uffizzi_core/secret.rb +9 -0
- data/app/models/uffizzi_core/template.rb +1 -1
- data/app/models/uffizzi_core/user.rb +1 -1
- data/app/models/uffizzi_core/user_project.rb +1 -1
- data/app/policies/uffizzi_core/api/cli/v1/account/credentials_policy.rb +8 -0
- data/app/policies/uffizzi_core/api/cli/v1/projects/deployments_policy.rb +4 -0
- data/app/repositories/uffizzi_core/credential_repo.rb +17 -22
- data/app/repositories/uffizzi_core/deployment_repo.rb +1 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +8 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/secret_serializer.rb +5 -0
- data/app/serializers/uffizzi_core/controller/apply_config_file/config_file_serializer.rb +5 -0
- data/app/serializers/uffizzi_core/controller/create_credential/credential_serializer.rb +7 -3
- data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer/container_config_file_serializer/config_file_serializer.rb +8 -0
- data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer/container_config_file_serializer.rb +7 -0
- data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +4 -3
- data/app/services/uffizzi_core/activity_item_service.rb +16 -26
- data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +11 -18
- data/app/services/uffizzi_core/compose_file/container_service.rb +13 -9
- data/app/services/uffizzi_core/compose_file/dependencies_service.rb +1 -0
- data/app/services/uffizzi_core/compose_file/services_options_service.rb +2 -2
- data/app/services/uffizzi_core/compose_file_service.rb +148 -0
- data/app/services/uffizzi_core/container_service.rb +1 -16
- data/app/services/uffizzi_core/controller_service.rb +7 -1
- data/app/services/uffizzi_core/credential_service.rb +2 -2
- data/app/services/uffizzi_core/deployment_service.rb +28 -7
- data/app/services/uffizzi_core/github_container_registry/credential_service.rb +24 -0
- data/app/services/uffizzi_core/manage_activity_items_service.rb +4 -19
- data/app/services/uffizzi_core/repo_service.rb +2 -137
- data/app/services/uffizzi_core/user_generator_service.rb +78 -0
- data/config/locales/en.activerecord.yml +5 -0
- data/config/locales/en.yml +4 -1
- data/config/routes.rb +6 -2
- data/db/migrate/20220309110201_remove_secrets_from_projects.rb +7 -0
- data/db/migrate/20220310110150_create_project_secrets.rb +14 -0
- data/db/migrate/20220329123323_rename_project_secrets_to_secrets.rb +7 -0
- data/db/migrate/20220329124542_add_resource_to_secrets.rb +7 -0
- data/db/migrate/20220329143241_remove_project_ref_from_secrets.rb +7 -0
- data/lib/tasks/uffizzi_core_tasks.rake +5 -0
- data/lib/uffizzi_core/engine.rb +35 -0
- data/lib/uffizzi_core/version.rb +1 -1
- data/lib/uffizzi_core.rb +1 -30
- data/swagger/v1/swagger.json +220 -11
- metadata +40 -21
- data/app/clients/uffizzi_core/github/app_client.rb +0 -19
- data/app/clients/uffizzi_core/github/installation_client.rb +0 -11
- data/app/clients/uffizzi_core/github/user_client.rb +0 -51
- data/app/errors/uffizzi_core/compose_file/not_found_error.rb +0 -4
- data/app/forms/uffizzi_core/api/cli/v1/project/delete_secret_form.rb +0 -27
- data/app/jobs/uffizzi_core/deployment/send_github_preview_message_job.rb +0 -13
- data/app/services/uffizzi_core/cli/compose_file_service.rb +0 -203
- data/app/services/uffizzi_core/compose_file/builders/github_repo_builder_service.rb +0 -59
- data/app/services/uffizzi_core/compose_file/services_options/build_service.rb +0 -93
- data/app/services/uffizzi_core/compose_file/update_service.rb +0 -29
- data/app/services/uffizzi_core/github/app_service.rb +0 -51
- data/app/services/uffizzi_core/github/credential_service.rb +0 -124
- data/app/services/uffizzi_core/github/message_service.rb +0 -20
- data/app/services/uffizzi_core/github_service.rb +0 -28
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 503ded723d48c023e0c47bc007b75e704927ba6bb13e9ea672feb573b45a2b95
|
4
|
+
data.tar.gz: ac2d0d440e82ea78fc3a5cca1f2dcac89a9db129a4cd2eee4ca712fad2be53d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46299f40846b2ef159fdd856f58cb47584907b26f1a16341007d5c6137f15a4afd905233f8db1e9d33252e652c218a4dba6ac216f59bb09ed00f6627c2b4643b
|
7
|
+
data.tar.gz: 2b1816b02b108dbd24ace6e4a6761fca714a62cd2226048ab2266b59bc09a9861a5f2cc425345326207feec9eeaa6f0ae1e3a539bbca8d2006ac8686fdb90edd
|
@@ -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
|
-
|
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
|
-
|
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 =
|
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::
|
81
|
+
UffizziCore::ComposeFileService.update(existing_compose_file, params)
|
82
82
|
else
|
83
83
|
kind = UffizziCore::ComposeFile.kind.main
|
84
|
-
UffizziCore::
|
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
|
-
|
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.
|
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
|
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
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
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(
|
34
|
-
secrets = project_form.secrets.map { |secret| { name: secret['name'] } }
|
33
|
+
UffizziCore::ProjectService.update_compose_secrets(resource_project)
|
35
34
|
|
36
|
-
|
35
|
+
respond_with resource_project.secrets, root: :secrets
|
37
36
|
end
|
38
37
|
|
39
|
-
# Delete a secret from project by secret
|
38
|
+
# Delete a secret from project by secret name
|
40
39
|
#
|
41
|
-
# @path [DELETE] /api/cli/v1/projects/{project_slug}/secrets/{
|
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
|
43
|
+
# @response 404
|
45
44
|
# @response 401 Not authorized
|
46
45
|
def destroy
|
47
46
|
secret_name = CGI.unescape(params[:id])
|
48
|
-
secret =
|
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
|
-
|
53
|
-
return respond_with project_form
|
54
|
-
end
|
49
|
+
UffizziCore::ProjectService.update_compose_secret_errors(resource_project, secret)
|
55
50
|
|
56
|
-
|
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
|
-
|
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,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.
|
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::
|
15
|
+
compose_data = UffizziCore::ComposeFileService.parse(compose_content)
|
16
16
|
|
17
|
-
UffizziCore::
|
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::
|
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::
|
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
|
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
|