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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -0
  3. data/app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb +3 -3
  4. data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +68 -2
  5. data/app/forms/uffizzi_core/api/cli/v1/deployment/create_form.rb +1 -0
  6. data/app/forms/uffizzi_core/api/cli/v1/project/create_form.rb +7 -0
  7. data/app/lib/uffizzi_core/concerns/models/activity_item.rb +39 -0
  8. data/app/lib/uffizzi_core/concerns/models/credential.rb +65 -0
  9. data/app/lib/uffizzi_core/concerns/models/repo.rb +33 -0
  10. data/app/lib/uffizzi_core/rbac/user_access_service.rb +24 -0
  11. data/app/models/uffizzi_core/project.rb +9 -2
  12. data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +12 -0
  13. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/compose_file_serializer.rb +7 -0
  14. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/deployment_serializer.rb +13 -0
  15. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +24 -1
  16. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +2 -1
  17. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer.rb +1 -1
  18. data/app/serializers/uffizzi_core/api/cli/v1/short_project_serializer.rb +7 -0
  19. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +16 -1
  20. data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +11 -7
  21. data/app/services/uffizzi_core/compose_file/config_option_service.rb +4 -0
  22. data/app/services/uffizzi_core/compose_file/parsers/services/healthcheck_parser_service.rb +73 -0
  23. data/app/services/uffizzi_core/compose_file/services_options_service.rb +2 -0
  24. data/app/services/uffizzi_core/compose_file/template_service.rb +4 -4
  25. data/app/services/uffizzi_core/compose_file_service.rb +1 -1
  26. data/app/services/uffizzi_core/deployment_service.rb +17 -5
  27. data/app/services/uffizzi_core/manage_activity_items_service.rb +1 -1
  28. data/app/services/uffizzi_core/project_service.rb +10 -0
  29. data/app/services/uffizzi_core/starter_template_service.rb +200 -0
  30. data/app/services/uffizzi_core/user_generator_service.rb +11 -5
  31. data/config/locales/en.yml +2 -0
  32. data/config/routes.rb +11 -1
  33. data/db/migrate/20220419074956_add_health_check_to_containers.rb +7 -0
  34. data/lib/tasks/uffizzi_core_tasks.rake +1 -1
  35. data/lib/uffizzi_core/version.rb +1 -1
  36. data/swagger/v1/swagger.json +174 -2
  37. metadata +12 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48e413ec49645c1e18d15251bcfa9ceaf94309be078fd46befbfd97894d9318e
4
- data.tar.gz: 213cd12f3c9216b851ccd16c44562da68c954a03f126fd35ec683119ee7b8755
3
+ metadata.gz: 43f66c059196fdf90a87f740f396bf781294f4dab94c221f38abc58caef7f141
4
+ data.tar.gz: 3f8aec775f29147cdc79b115401a28414ac19ee9146b9226ea62f5deb0de9083
5
5
  SHA512:
6
- metadata.gz: 339656968a5609d9674536a6bd36518f2efb33afe30bf77ef2c56d158fe3b1b7a9f27da8dd76dcc8c1f35ad5624121a2914482d296b0b2e5afe9025735dda974
7
- data.tar.gz: b5369f15696f2e011b1be386c1ee1b4660a0e5733e09030d0af8095612337cf544e2be0adfce7b3410f0338bd64e7e0d479a0f0f779360d9c99eb6990261670f
6
+ metadata.gz: 4d90a4d0a13b2d7e899573c8484d6355d751a81bd9648443211b4fa4155f439ae40993a4f3dd18c2ec5079bb183093f0f78b7800d24f96d693a98b3ef9c81a48
7
+ data.tar.gz: a7dcc2e613d8d5293c070d66f4c1366534c0077c8d5d588906be93b389a51bb88c2951c9db2b68c5236e90933da51af775ae00516afbc34cd6f8c7148ce5bb51
data/README.md CHANGED
@@ -44,3 +44,9 @@ Or install it yourself as:
44
44
  ```bash
45
45
  $ gem install uffizzi_core
46
46
  ```
47
+
48
+ ## Migrations
49
+ After adding a new migration, ru the following command:
50
+ ```
51
+ rake uffizzi_core:install
52
+ ```
@@ -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, UffizziCore::Credential::DockerHub, UffizziCore::Credential::Google, UffizziCore::Credential::GithubContainerRegistry
29
- # rubocop:enable Layout/LineLength
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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Project::CreateForm < UffizziCore::Project
4
+ include UffizziCore::ApplicationForm
5
+
6
+ permit :name, :slug, :description
7
+ end
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ProjectSerializer::ComposeFileSerializer < UffizziCore::BaseSerializer
4
+ type :compose_file
5
+
6
+ attributes :source
7
+ 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 :slug
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
@@ -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
 
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ShortProjectSerializer < UffizziCore::BaseSerializer
4
+ type :project
5
+
6
+ attributes :name, :slug
7
+ end
@@ -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
- continuous_preview_container_data = container_data[:'x-uffizzi-continuous-preview'] || container_data[:'x-uffizzi-continuous-previews']
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 = build_repo_attributes(container_data, image_data, build_data, credentials)
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, image_data, _build_data, credentials)
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(github_form, project, user)
4
+ def initialize(cli_form, project, user)
5
5
  @project = project
6
6
  @user = user
7
- @compose_dependencies = github_form.compose_dependencies
8
- @compose_data = github_form.compose_data
9
- @compose_repositories = github_form.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