uffizzi_core 0.1.11 → 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.
- checksums.yaml +4 -4
- data/README.md +6 -0
- data/app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb +3 -3
- data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +68 -2
- data/app/forms/uffizzi_core/api/cli/v1/deployment/create_form.rb +1 -0
- data/app/forms/uffizzi_core/api/cli/v1/project/create_form.rb +7 -0
- data/app/lib/uffizzi_core/concerns/models/activity_item.rb +39 -0
- data/app/lib/uffizzi_core/concerns/models/credential.rb +65 -0
- data/app/lib/uffizzi_core/concerns/models/repo.rb +33 -0
- data/app/lib/uffizzi_core/rbac/user_access_service.rb +24 -0
- data/app/models/uffizzi_core/project.rb +9 -2
- data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +12 -0
- data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/compose_file_serializer.rb +7 -0
- data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/deployment_serializer.rb +13 -0
- data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +24 -1
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +2 -1
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer.rb +1 -1
- data/app/serializers/uffizzi_core/api/cli/v1/short_project_serializer.rb +7 -0
- data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +16 -1
- data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +11 -7
- data/app/services/uffizzi_core/compose_file/config_option_service.rb +4 -0
- data/app/services/uffizzi_core/compose_file/parsers/services/healthcheck_parser_service.rb +73 -0
- data/app/services/uffizzi_core/compose_file/services_options_service.rb +2 -0
- data/app/services/uffizzi_core/compose_file/template_service.rb +4 -4
- data/app/services/uffizzi_core/compose_file_service.rb +1 -1
- data/app/services/uffizzi_core/deployment_service.rb +17 -5
- data/app/services/uffizzi_core/manage_activity_items_service.rb +1 -1
- data/app/services/uffizzi_core/project_service.rb +10 -0
- data/app/services/uffizzi_core/starter_template_service.rb +200 -0
- data/app/services/uffizzi_core/user_generator_service.rb +11 -5
- data/config/locales/en.yml +2 -0
- data/config/routes.rb +11 -1
- data/db/migrate/20220419074956_add_health_check_to_containers.rb +7 -0
- data/lib/tasks/uffizzi_core_tasks.rake +1 -1
- data/lib/uffizzi_core/version.rb +1 -1
- data/swagger/v1/swagger.json +174 -2
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43f66c059196fdf90a87f740f396bf781294f4dab94c221f38abc58caef7f141
|
4
|
+
data.tar.gz: 3f8aec775f29147cdc79b115401a28414ac19ee9146b9226ea62f5deb0de9083
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d90a4d0a13b2d7e899573c8484d6355d751a81bd9648443211b4fa4155f439ae40993a4f3dd18c2ec5079bb183093f0f78b7800d24f96d693a98b3ef9c81a48
|
7
|
+
data.tar.gz: a7dcc2e613d8d5293c070d66f4c1366534c0077c8d5d588906be93b389a51bb88c2951c9db2b68c5236e90933da51af775ae00516afbc34cd6f8c7148ce5bb51
|
data/README.md
CHANGED
@@ -15,7 +15,6 @@ class UffizziCore::Api::Cli::V1::Account::CredentialsController < UffizziCore::A
|
|
15
15
|
render json: { credentials: credentials }, status: :ok
|
16
16
|
end
|
17
17
|
|
18
|
-
# rubocop:disable Layout/LineLength
|
19
18
|
# Create account credential
|
20
19
|
#
|
21
20
|
# @path [POST] /api/cli/v1/account/credentials
|
@@ -25,8 +24,9 @@ class UffizziCore::Api::Cli::V1::Account::CredentialsController < UffizziCore::A
|
|
25
24
|
# @response [object<errors>] 422 Unprocessable entity
|
26
25
|
#
|
27
26
|
# @example
|
28
|
-
# type can be one of UffizziCore::Credential::Amazon, UffizziCore::Credential::Azure,
|
29
|
-
#
|
27
|
+
# type can be one of UffizziCore::Credential::Amazon, UffizziCore::Credential::Azure,
|
28
|
+
# UffizziCore::Credential::DockerHub, UffizziCore::Credential::Google, UffizziCore::Credential::GithubContainerRegistry
|
29
|
+
|
30
30
|
def create
|
31
31
|
credential_form = UffizziCore::Api::Cli::V1::Account::Credential::CreateForm.new
|
32
32
|
credential_form.assign_attributes(credential_params)
|
@@ -9,11 +9,77 @@ class UffizziCore::Api::Cli::V1::ProjectsController < UffizziCore::Api::Cli::V1:
|
|
9
9
|
#
|
10
10
|
# @path [GET] /api/cli/v1/projects
|
11
11
|
#
|
12
|
-
# @response [object<projects: Array<object<slug: string>> >] 200 OK
|
12
|
+
# @response [object<projects: Array<object<slug: string, name: string>> >] 200 OK
|
13
13
|
# @response 401 Not authorized
|
14
14
|
def index
|
15
15
|
projects = current_user.projects.active.order(updated_at: :desc)
|
16
16
|
|
17
|
-
respond_with projects
|
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)
|
18
84
|
end
|
19
85
|
end
|
@@ -16,6 +16,7 @@ class UffizziCore::Api::Cli::V1::Deployment::CreateForm < UffizziCore::Deploymen
|
|
16
16
|
:command,
|
17
17
|
:receive_incoming_requests,
|
18
18
|
:continuously_deploy,
|
19
|
+
{ healthcheck: {} },
|
19
20
|
{ variables: [:name, :value],
|
20
21
|
secret_variables: [:name, :value],
|
21
22
|
repo_attributes: [
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UffizziCore::Concerns::Models::ActivityItem
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
include UffizziCore::ActivityItemRepo
|
8
|
+
|
9
|
+
self.table_name = UffizziCore.table_names[:activity_items]
|
10
|
+
|
11
|
+
belongs_to :deployment
|
12
|
+
belongs_to :container
|
13
|
+
belongs_to :build, optional: true
|
14
|
+
|
15
|
+
has_many :events, dependent: :destroy
|
16
|
+
|
17
|
+
scope :docker, -> {
|
18
|
+
where(type: UffizziCore::ActivityItem::Docker.name)
|
19
|
+
}
|
20
|
+
|
21
|
+
scope :github, -> {
|
22
|
+
where(type: UffizziCore::ActivityItem::Github.name)
|
23
|
+
}
|
24
|
+
|
25
|
+
def docker?
|
26
|
+
type == UffizziCore::ActivityItem::Docker.name
|
27
|
+
end
|
28
|
+
|
29
|
+
def image
|
30
|
+
[namespace, name].compact.join('/')
|
31
|
+
end
|
32
|
+
|
33
|
+
def full_image
|
34
|
+
return "#{image}:#{tag}" if docker?
|
35
|
+
|
36
|
+
''
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UffizziCore::Concerns::Models::Credential
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
include AASM
|
8
|
+
include UffizziCore::CredentialRepo
|
9
|
+
|
10
|
+
self.table_name = UffizziCore.table_names[:credentials]
|
11
|
+
|
12
|
+
belongs_to :account
|
13
|
+
|
14
|
+
before_destroy :remove_token
|
15
|
+
|
16
|
+
validates :registry_url, presence: true
|
17
|
+
|
18
|
+
aasm :state, column: :state do
|
19
|
+
state :not_connected, initial: true
|
20
|
+
state :active
|
21
|
+
state :unauthorized
|
22
|
+
|
23
|
+
event :activate do
|
24
|
+
transitions from: [:not_connected, :unauthorized], to: :active
|
25
|
+
end
|
26
|
+
|
27
|
+
event :unauthorize do
|
28
|
+
transitions from: [:not_connected, :active], to: :unauthorized
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def github_container_registry?
|
33
|
+
type == UffizziCore::Credential::GithubContainerRegistry.name
|
34
|
+
end
|
35
|
+
|
36
|
+
def docker_hub?
|
37
|
+
type == UffizziCore::Credential::DockerHub.name
|
38
|
+
end
|
39
|
+
|
40
|
+
def azure?
|
41
|
+
type == UffizziCore::Credential::Azure.name
|
42
|
+
end
|
43
|
+
|
44
|
+
def google?
|
45
|
+
type == UffizziCore::Credential::Google.name
|
46
|
+
end
|
47
|
+
|
48
|
+
def amazon?
|
49
|
+
type == UffizziCore::Credential::Amazon.name
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def remove_token
|
55
|
+
account.projects.find_each do |project|
|
56
|
+
project.deployments.find_each do |deployment|
|
57
|
+
containers = deployment.containers
|
58
|
+
attributes = { continuously_deploy: UffizziCore::Container::STATE_DISABLED }
|
59
|
+
|
60
|
+
containers.with_docker_hub_repo.update_all(attributes) if docker_hub?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UffizziCore::Concerns::Models::Repo
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
extend Enumerize
|
8
|
+
include UffizziCore::RepoRepo
|
9
|
+
|
10
|
+
self.table_name = UffizziCore.table_names[:repos]
|
11
|
+
|
12
|
+
enumerize :kind, in: [:buildpacks18, :dockerfile, :dotnet, :gatsby, :barestatic], predicates: true
|
13
|
+
|
14
|
+
belongs_to :project
|
15
|
+
has_one :container, inverse_of: :repo, dependent: :destroy
|
16
|
+
has_many :builds, dependent: :destroy
|
17
|
+
|
18
|
+
validates :dockerfile_path, presence: true, if: :dockerfile?
|
19
|
+
validates :delete_preview_after, numericality: { greater_than: 0, only_integer: true }, allow_nil: true
|
20
|
+
|
21
|
+
def docker_hub?
|
22
|
+
type == UffizziCore::Repo::DockerHub.name
|
23
|
+
end
|
24
|
+
|
25
|
+
def azure?
|
26
|
+
type == UffizziCore::Repo::Azure.name
|
27
|
+
end
|
28
|
+
|
29
|
+
def google?
|
30
|
+
type == UffizziCore::Repo::Google.name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -6,10 +6,34 @@ module UffizziCore::Rbac::UserAccessService
|
|
6
6
|
true
|
7
7
|
end
|
8
8
|
|
9
|
+
def developer_access_to_account?(_user, _account)
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def viewer_access_to_account?(_user, _account)
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def admin_or_developer_access_to_account?(_user, _account)
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
9
21
|
def any_access_to_account?(_user, _account)
|
10
22
|
true
|
11
23
|
end
|
12
24
|
|
25
|
+
def admin_access_to_project?(_user, _project)
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def developer_access_to_project?(_user, _project)
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def viewer_access_to_project?(_user, _project)
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
13
37
|
def admin_or_developer_access_to_project?(_user, _project)
|
14
38
|
true
|
15
39
|
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# @model
|
3
|
+
# @model Project
|
4
4
|
# @property slug [string]
|
5
|
+
# @property name [string]
|
6
|
+
# @property description [string]
|
7
|
+
# @property created_at [date-time]
|
8
|
+
# @property secrets [string]
|
9
|
+
# @property default_compose [object<source: string>]
|
10
|
+
# @property deployments [object<id: integer, domain: string>]
|
5
11
|
|
6
12
|
class UffizziCore::Project < UffizziCore::ApplicationRecord
|
7
13
|
include AASM
|
@@ -23,7 +29,8 @@ class UffizziCore::Project < UffizziCore::ApplicationRecord
|
|
23
29
|
has_many :compose_files, dependent: :destroy
|
24
30
|
has_many :secrets, dependent: :destroy, as: :resource
|
25
31
|
|
26
|
-
validates :name, presence: true, uniqueness: { scope: :account }
|
32
|
+
validates :name, presence: true, uniqueness: { scope: :account, message: 'Name already exists' }
|
33
|
+
validates :slug, presence: true, uniqueness: { message: 'Project slug already taken' }
|
27
34
|
|
28
35
|
aasm(:state) do
|
29
36
|
state :active, initial: true
|
@@ -4,4 +4,16 @@ class UffizziCore::Api::Cli::V1::ProjectsPolicy < UffizziCore::ApplicationPolicy
|
|
4
4
|
def index?
|
5
5
|
context.user_access_module.any_access_to_account?(context.user, context.account)
|
6
6
|
end
|
7
|
+
|
8
|
+
def show?
|
9
|
+
context.user_access_module.any_access_to_account?(context.user, context.account)
|
10
|
+
end
|
11
|
+
|
12
|
+
def create?
|
13
|
+
context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy?
|
17
|
+
context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
|
18
|
+
end
|
7
19
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::Api::Cli::V1::ProjectSerializer::DeploymentSerializer < UffizziCore::BaseSerializer
|
4
|
+
type :deployment
|
5
|
+
|
6
|
+
attributes :id,
|
7
|
+
:preview_url,
|
8
|
+
:state
|
9
|
+
|
10
|
+
def preview_url
|
11
|
+
UffizziCore::DeploymentService.build_preview_url(object)
|
12
|
+
end
|
13
|
+
end
|
@@ -2,6 +2,29 @@
|
|
2
2
|
|
3
3
|
class UffizziCore::Api::Cli::V1::ProjectSerializer < UffizziCore::BaseSerializer
|
4
4
|
type :project
|
5
|
+
has_many :deployments
|
6
|
+
has_many :secrets
|
7
|
+
has_one :default_compose
|
5
8
|
|
6
|
-
attributes :
|
9
|
+
attributes :name,
|
10
|
+
:slug,
|
11
|
+
:description,
|
12
|
+
:created_at
|
13
|
+
|
14
|
+
def default_compose
|
15
|
+
object.compose_files.main.first
|
16
|
+
end
|
17
|
+
|
18
|
+
def deployments
|
19
|
+
object.deployments.active.map do |deployment|
|
20
|
+
deployment.state = UffizziCore::DeploymentService.failed?(deployment) ? 'failed' : 'active'
|
21
|
+
deployment
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def secrets
|
26
|
+
return [] unless object.secrets
|
27
|
+
|
28
|
+
object.secrets.map(&:name)
|
29
|
+
end
|
7
30
|
end
|
data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb
CHANGED
@@ -19,7 +19,8 @@ class UffizziCore::Api::Cli::V1::Projects::DeploymentSerializer::ContainerSerial
|
|
19
19
|
:public,
|
20
20
|
:repo_id,
|
21
21
|
:continuously_deploy,
|
22
|
-
:receive_incoming_requests
|
22
|
+
:receive_incoming_requests,
|
23
|
+
:healthcheck
|
23
24
|
|
24
25
|
def secret_variables
|
25
26
|
return unless object.secret_variables.present?
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class UffizziCore::Api::Cli::V1::Projects::Deployments::ContainerSerializer < UffizziCore::BaseSerializer
|
4
|
-
attributes :id, :name, :memory_limit, :memory_request, :continuously_deploy, :variables, :secret_variables
|
4
|
+
attributes :id, :name, :memory_limit, :memory_request, :continuously_deploy, :variables, :secret_variables, :healthcheck
|
5
5
|
|
6
6
|
has_many :container_config_files
|
7
7
|
|
@@ -15,7 +15,8 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
|
|
15
15
|
:target_port,
|
16
16
|
:public,
|
17
17
|
:controller_name,
|
18
|
-
:receive_incoming_requests
|
18
|
+
:receive_incoming_requests,
|
19
|
+
:healthcheck
|
19
20
|
|
20
21
|
has_many :container_config_files
|
21
22
|
|
@@ -52,4 +53,18 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
|
|
52
53
|
def command
|
53
54
|
object.command.blank? ? nil : JSON.parse(object.command)
|
54
55
|
end
|
56
|
+
|
57
|
+
def healthcheck
|
58
|
+
return {} if object.healthcheck.nil?
|
59
|
+
|
60
|
+
command = object.healthcheck['test']
|
61
|
+
new_command = if command.is_a?(Array)
|
62
|
+
items_to_remove = ['CMD', 'CMD-SHELL']
|
63
|
+
command.select { |item| items_to_remove.exclude?(item) }
|
64
|
+
elsif object.healthcheck['test'].is_a?(String)
|
65
|
+
command.split
|
66
|
+
end
|
67
|
+
|
68
|
+
object.healthcheck.merge(test: new_command)
|
69
|
+
end
|
55
70
|
end
|
@@ -17,18 +17,14 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
|
|
17
17
|
configs_data = container_data[:configs] || []
|
18
18
|
secrets = container_data[:secrets] || []
|
19
19
|
container_name = container_data[:container_name]
|
20
|
-
|
20
|
+
healthcheck_data = container_data[:healthcheck] || {}
|
21
21
|
|
22
22
|
env_file_dependencies = UffizziCore::ComposeFile::GithubDependenciesService.env_file_dependencies_for_container(compose_dependencies,
|
23
23
|
container_name)
|
24
24
|
configs_dependencies = UffizziCore::ComposeFile::GithubDependenciesService.configs_dependencies_for_container(compose_dependencies,
|
25
25
|
container_name)
|
26
|
-
|
27
26
|
is_ingress = ingress_container?(container_name, ingress_data)
|
28
|
-
repo_attributes =
|
29
|
-
|
30
|
-
repo_attributes = set_continuous_preview_attributes_to_repo(repo_attributes, continuous_preview_global_data.to_h,
|
31
|
-
continuous_preview_container_data.to_h)
|
27
|
+
repo_attributes = repo_attributes(container_data, continuous_preview_global_data)
|
32
28
|
|
33
29
|
{
|
34
30
|
tag: tag(image_data, repo_attributes),
|
@@ -51,6 +47,13 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
|
|
51
47
|
|
52
48
|
private
|
53
49
|
|
50
|
+
def repo_attributes(container_data, continuous_preview_global_data)
|
51
|
+
repo_attributes = build_repo_attributes(container_data)
|
52
|
+
continuous_preview_container_data = container_data[:'x-uffizzi-continuous-preview'] || container_data[:'x-uffizzi-continuous-previews']
|
53
|
+
|
54
|
+
set_continuous_preview_attributes_to_repo(repo_attributes, continuous_preview_global_data.to_h, continuous_preview_container_data.to_h)
|
55
|
+
end
|
56
|
+
|
54
57
|
def set_continuous_preview_attributes_to_repo(repo_attributes, global_data, container_data)
|
55
58
|
condition_attributes = [
|
56
59
|
:deploy_preview_when_pull_request_is_opened,
|
@@ -148,8 +151,9 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
|
|
148
151
|
memory_value
|
149
152
|
end
|
150
153
|
|
151
|
-
def build_repo_attributes(container_data
|
154
|
+
def build_repo_attributes(container_data)
|
152
155
|
repo_type = repo_type(container_data)
|
156
|
+
image_data = container_data[:image]
|
153
157
|
|
154
158
|
case repo_type
|
155
159
|
when UffizziCore::Repo::DockerHub.name
|
@@ -12,6 +12,10 @@ class UffizziCore::ComposeFile::ConfigOptionService
|
|
12
12
|
|
13
13
|
def config_options(compose_data)
|
14
14
|
compose_data.each_with_object([]) do |(key, value), keys|
|
15
|
+
if compose_data.equal?(value)
|
16
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.infinite_recursion', key: key)
|
17
|
+
end
|
18
|
+
|
15
19
|
keys << key
|
16
20
|
keys.concat(config_options(value)) if value.is_a?(Hash)
|
17
21
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
|
4
|
+
REQUIRED_START_COMMANDS = ['NONE', 'CMD', 'CMD-SHELL'].freeze
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def parse(healthcheck_data)
|
8
|
+
return {} if healthcheck_data.blank?
|
9
|
+
|
10
|
+
command = parse_command(healthcheck_data)
|
11
|
+
|
12
|
+
{
|
13
|
+
test: command,
|
14
|
+
interval: parse_time(healthcheck_data['interval']),
|
15
|
+
timeout: parse_time(healthcheck_data['timeout']),
|
16
|
+
retries: parse_retries(healthcheck_data['retries']),
|
17
|
+
start_period: parse_time(healthcheck_data['start_period']),
|
18
|
+
disable: parse_disable_option(healthcheck_data['disable'], command),
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def parse_command(healthcheck_data)
|
25
|
+
command = healthcheck_data['test']
|
26
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.string_or_array_error', option: :test) if command.nil?
|
27
|
+
|
28
|
+
case command
|
29
|
+
when Array
|
30
|
+
start_command = command.first
|
31
|
+
raise UffizziCore::ComposeFile::ParseError unless REQUIRED_START_COMMANDS.include?(start_command)
|
32
|
+
|
33
|
+
command
|
34
|
+
when String
|
35
|
+
command
|
36
|
+
else
|
37
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_type', option: :test)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_retries(value)
|
42
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_integer', option: :retries) unless value.is_a?(Integer)
|
43
|
+
end
|
44
|
+
|
45
|
+
def parse_time(value)
|
46
|
+
tokens = {
|
47
|
+
's' => 1,
|
48
|
+
'm' => 60,
|
49
|
+
'h' => (60 * 60),
|
50
|
+
'd' => (60 * 60 * 24),
|
51
|
+
}
|
52
|
+
|
53
|
+
time_parts = value.scan(/(\d+)(\w)/).compact
|
54
|
+
|
55
|
+
time_parts.reduce(0) do |acc, part|
|
56
|
+
amount, measure = part
|
57
|
+
acc += amount.to_i * tokens[measure]
|
58
|
+
|
59
|
+
acc
|
60
|
+
rescue StandardError
|
61
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_time_interval')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def parse_disable_option(value, command)
|
66
|
+
return true if command.is_a?(Array) && command.first == 'NONE'
|
67
|
+
return false if value.nil?
|
68
|
+
return value if value.in?([true, false])
|
69
|
+
|
70
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_bool_value', field: 'disable', value: value)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -42,6 +42,8 @@ class UffizziCore::ComposeFile::ServicesOptionsService
|
|
42
42
|
UffizziCore::ComposeFile::ServicesOptions::EntrypointService.parse(value)
|
43
43
|
when :command
|
44
44
|
UffizziCore::ComposeFile::ServicesOptions::CommandService.parse(value)
|
45
|
+
when :healthcheck
|
46
|
+
UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService.parse(value)
|
45
47
|
when :'x-uffizzi-continuous-preview', :'x-uffizzi-continuous-previews'
|
46
48
|
UffizziCore::ComposeFile::ContinuousPreviewOptionsService.parse(value)
|
47
49
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class UffizziCore::ComposeFile::TemplateService
|
4
|
-
def initialize(
|
4
|
+
def initialize(cli_form, project, user)
|
5
5
|
@project = project
|
6
6
|
@user = user
|
7
|
-
@compose_dependencies =
|
8
|
-
@compose_data =
|
9
|
-
@compose_repositories =
|
7
|
+
@compose_dependencies = cli_form.compose_dependencies
|
8
|
+
@compose_data = cli_form.compose_data
|
9
|
+
@compose_repositories = cli_form.compose_repositories
|
10
10
|
end
|
11
11
|
|
12
12
|
def create_template(compose_file_form)
|
@@ -158,7 +158,7 @@ module UffizziCore::ComposeFileService
|
|
158
158
|
|
159
159
|
def load_compose_data(compose_content)
|
160
160
|
begin
|
161
|
-
compose_data = YAML.safe_load(compose_content)
|
161
|
+
compose_data = YAML.safe_load(compose_content, aliases: true)
|
162
162
|
rescue Psych::SyntaxError
|
163
163
|
raise UffizziCore::ComposeFile::ParseError, 'Invalid compose file'
|
164
164
|
end
|