uffizzi_core 0.1.14 → 0.2.0

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/app/clients/uffizzi_core/docker_hub_client/not_authorized_error.rb +6 -0
  3. data/app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb +6 -0
  4. data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +57 -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/forms/uffizzi_core/api/cli/v1/template/create_form.rb +2 -0
  8. data/app/lib/uffizzi_core/rbac/user_access_service.rb +4 -0
  9. data/app/models/uffizzi_core/project.rb +9 -2
  10. data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +12 -0
  11. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/compose_file_serializer.rb +7 -0
  12. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/deployment_serializer.rb +13 -0
  13. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +28 -1
  14. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +2 -1
  15. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer.rb +1 -1
  16. data/app/serializers/uffizzi_core/api/cli/v1/short_project_serializer.rb +7 -0
  17. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer/container_config_file_serializer/config_file_serializer.rb +2 -2
  18. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +16 -1
  19. data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +13 -7
  20. data/app/services/uffizzi_core/compose_file/{configs_options_service.rb → parsers/configs_parser_service.rb} +1 -1
  21. data/app/services/uffizzi_core/compose_file/{continuous_preview_options_service.rb → parsers/continuous_preview_parser_service.rb} +1 -1
  22. data/app/services/uffizzi_core/compose_file/{ingress_options_service.rb → parsers/ingress_parser_service.rb} +1 -1
  23. data/app/services/uffizzi_core/compose_file/{secrets_options_service.rb → parsers/secrets_parser_service.rb} +1 -1
  24. data/app/services/uffizzi_core/compose_file/{services_options/command_service.rb → parsers/services/command_parser_service.rb} +1 -1
  25. data/app/services/uffizzi_core/compose_file/{services_options/configs_service.rb → parsers/services/configs_parser_service.rb} +1 -1
  26. data/app/services/uffizzi_core/compose_file/{services_options/deploy_service.rb → parsers/services/deploy_parser_service.rb} +1 -1
  27. data/app/services/uffizzi_core/compose_file/{services_options/entrypoint_service.rb → parsers/services/entrypoint_parser_service.rb} +1 -1
  28. data/app/services/uffizzi_core/compose_file/{services_options/env_file_service.rb → parsers/services/env_file_parser_service.rb} +1 -1
  29. data/app/services/uffizzi_core/compose_file/{services_options/environment_service.rb → parsers/services/environment_parser_service.rb} +2 -2
  30. data/app/services/uffizzi_core/compose_file/parsers/services/healthcheck_parser_service.rb +73 -0
  31. data/app/services/uffizzi_core/compose_file/{services_options/image_service.rb → parsers/services/image_parser_service.rb} +1 -1
  32. data/app/services/uffizzi_core/compose_file/{services_options/secrets_service.rb → parsers/services/secrets_parser_service.rb} +1 -1
  33. data/app/services/uffizzi_core/compose_file/{services_options_service.rb → parsers/services_parser_service.rb} +22 -12
  34. data/app/services/uffizzi_core/compose_file/{variables_service.rb → parsers/variables_parser_service.rb} +1 -1
  35. data/app/services/uffizzi_core/compose_file/template_service.rb +4 -4
  36. data/app/services/uffizzi_core/compose_file_service.rb +10 -6
  37. data/app/services/uffizzi_core/deployment_service.rb +3 -2
  38. data/app/services/uffizzi_core/project_service.rb +10 -0
  39. data/app/services/uffizzi_core/user_generator_service.rb +11 -5
  40. data/config/locales/en.yml +1 -0
  41. data/config/routes.rb +1 -1
  42. data/db/migrate/20220419074956_add_health_check_to_containers.rb +7 -0
  43. data/lib/tasks/uffizzi_core_tasks.rake +1 -1
  44. data/lib/uffizzi_core/version.rb +1 -1
  45. data/swagger/v1/swagger.json +173 -1
  46. metadata +23 -19
  47. data/app/lib/uffizzi_core/concerns/models/activity_item.rb +0 -39
  48. data/app/lib/uffizzi_core/concerns/models/credential.rb +0 -65
  49. data/app/lib/uffizzi_core/concerns/models/repo.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4aa056e4e94f8dbd93efddc149a68b583fe31090307048c1167df16b8842032
4
- data.tar.gz: f7c91d5144ebe0f7cf95cbe7f3241e85bae67ff79eac46465a5cb329b23dfac6
3
+ metadata.gz: a31b2584109bcdd076e1cb1254cd0f2449337f4bf23efa6b47666e43bb9e8f7b
4
+ data.tar.gz: 5c645f212bb2b5b328d2de38e6545b5b7af83095a5eccef66f38a240fade29b2
5
5
  SHA512:
6
- metadata.gz: c21e0edc0adf7905754850aabe30d4aec880029de985d90434c70f5bd2804dd7a44d87664f5e668b5bbac049cf6fda304c297c5ab44cc68a778d00d4fdf95b56
7
- data.tar.gz: 6aa9ac0ab849cf07720a3642222d51a258252be4ad658f2f878a6a0b54ee725fe7b8f7a3f29bd42037a62be22dc268bf339baf7dc043ad3c66b7de497692f4da
6
+ metadata.gz: 2f17aee88420476b88e898523e5611c87f8151119135618f68b0a9741f7de47490fb5652ee0658d572f024f4528c62a97bd5845a2bd3173cb27860870e272135
7
+ data.tar.gz: bb6da9566c8c67ec7d178ee79f811e0a2629d50d7677b7dd981247a9089866781c28e9b447c015bec311435383cda609afcc0b69bf9e51a513e615e526da2771
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::DockerHubClient
4
+ class NotAuthorizedError < StandardError
5
+ end
6
+ end
@@ -7,6 +7,12 @@ module UffizziCore::DependencyInjectionConcern
7
7
  UffizziCore::UserAccessService.new(module_class(:rbac))
8
8
  end
9
9
 
10
+ def build_parser_module
11
+ return unless module_exists?(:github)
12
+
13
+ module_class(:github)
14
+ end
15
+
10
16
  private
11
17
 
12
18
  def module_exists?(module_name)
@@ -9,11 +9,66 @@ 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
+ UffizziCore::ProjectService.add_users_to_project!(project_form, current_user)
49
+ end
50
+
51
+ respond_with project_form
52
+ end
53
+
54
+ # Delete a project
55
+ #
56
+ # @path [DELETE] /api/cli/v1/projects/{slug}
57
+ #
58
+ # @response 204 No content
59
+ # @response 404 Not Found
60
+ # @response 401 Not authorized
61
+
62
+ def destroy
63
+ project = current_user.organizational_account.active_projects.find_by!(slug: params[:slug])
64
+ project.disable!
65
+
66
+ head :no_content
67
+ end
68
+
69
+ private
70
+
71
+ def project_params
72
+ params.require(:project)
18
73
  end
19
74
  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
@@ -17,6 +17,8 @@ class UffizziCore::Api::Cli::V1::Template::CreateForm < UffizziCore::Template
17
17
  :receive_incoming_requests,
18
18
  :continuously_deploy,
19
19
  :service_name,
20
+ :name,
21
+ :healthcheck,
20
22
  { variables: [:name, :value],
21
23
  secret_variables: [:name, :value],
22
24
  repo_attributes: [
@@ -10,6 +10,10 @@ module UffizziCore::Rbac::UserAccessService
10
10
  true
11
11
  end
12
12
 
13
+ def admin_or_developer_access_to_account?(_user, _account)
14
+ true
15
+ end
16
+
13
17
  def admin_or_developer_access_to_project?(_user, _project)
14
18
  true
15
19
  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,33 @@
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 = if UffizziCore::DeploymentService.failed?(deployment)
21
+ UffizziCore::Deployment::STATE_FAILED
22
+ else
23
+ UffizziCore::Deployment::STATE_ACTIVE
24
+ end
25
+ deployment
26
+ end
27
+ end
28
+
29
+ def secrets
30
+ return [] unless object.secrets
31
+
32
+ object.secrets.map(&:name)
33
+ end
7
34
  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
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Metrics/LineLength
3
+ # rubocop:disable Layout/LineLength
4
4
  class UffizziCore::Controller::DeployContainers::ContainerSerializer::ContainerConfigFileSerializer::ConfigFileSerializer < UffizziCore::BaseSerializer
5
- # rubocop:enable Metrics/LineLength
5
+ # rubocop:enable Layout/LineLength
6
6
 
7
7
  attributes :id, :filename, :kind, :payload
8
8
  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),
@@ -46,11 +42,20 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
46
42
  receive_incoming_requests: is_ingress,
47
43
  container_config_files_attributes: config_files(configs_data, configs_dependencies),
48
44
  service_name: container_name,
45
+ name: container_name,
46
+ healthcheck: healthcheck_data,
49
47
  }
50
48
  end
51
49
 
52
50
  private
53
51
 
52
+ def repo_attributes(container_data, continuous_preview_global_data)
53
+ repo_attributes = build_repo_attributes(container_data)
54
+ continuous_preview_container_data = container_data[:'x-uffizzi-continuous-preview'] || container_data[:'x-uffizzi-continuous-previews']
55
+
56
+ set_continuous_preview_attributes_to_repo(repo_attributes, continuous_preview_global_data.to_h, continuous_preview_container_data.to_h)
57
+ end
58
+
54
59
  def set_continuous_preview_attributes_to_repo(repo_attributes, global_data, container_data)
55
60
  condition_attributes = [
56
61
  :deploy_preview_when_pull_request_is_opened,
@@ -148,8 +153,9 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
148
153
  memory_value
149
154
  end
150
155
 
151
- def build_repo_attributes(container_data, image_data, _build_data, credentials)
156
+ def build_repo_attributes(container_data)
152
157
  repo_type = repo_type(container_data)
158
+ image_data = container_data[:image]
153
159
 
154
160
  case repo_type
155
161
  when UffizziCore::Repo::DockerHub.name
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ConfigsOptionsService
3
+ class UffizziCore::ComposeFile::Parsers::ConfigsParserService
4
4
  class << self
5
5
  def parse(configs_data)
6
6
  return [] if configs_data.nil?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ContinuousPreviewOptionsService
3
+ class UffizziCore::ComposeFile::Parsers::ContinuousPreviewParserService
4
4
  class << self
5
5
  def parse(continuous_preview_data)
6
6
  return {} if continuous_preview_data.nil?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::IngressOptionsService
3
+ class UffizziCore::ComposeFile::Parsers::IngressParserService
4
4
  class << self
5
5
  def parse(ingress_data, services_data)
6
6
  raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.no_ingress') if ingress_data.nil?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::SecretsOptionsService
3
+ class UffizziCore::ComposeFile::Parsers::SecretsParserService
4
4
  class << self
5
5
  def parse(secrets_data)
6
6
  return [] if secrets_data.nil?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ServicesOptions::CommandService
3
+ class UffizziCore::ComposeFile::Parsers::Services::CommandParserService
4
4
  class << self
5
5
  def parse(command_data)
6
6
  return nil if command_data.blank?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ServicesOptions::ConfigsService
3
+ class UffizziCore::ComposeFile::Parsers::Services::ConfigsParserService
4
4
  class << self
5
5
  def parse(configs, global_configs_data)
6
6
  return [] if configs.nil?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ServicesOptions::DeployService
3
+ class UffizziCore::ComposeFile::Parsers::Services::DeployParserService
4
4
  class << self
5
5
  def parse(deploy_data)
6
6
  return {} if deploy_data.blank?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ServicesOptions::EntrypointService
3
+ class UffizziCore::ComposeFile::Parsers::Services::EntrypointParserService
4
4
  class << self
5
5
  def parse(entrypoint_data)
6
6
  return nil if entrypoint_data.blank?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ServicesOptions::EnvFileService
3
+ class UffizziCore::ComposeFile::Parsers::Services::EnvFileParserService
4
4
  class << self
5
5
  def parse(env_file)
6
6
  env_files = case env_file
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ServicesOptions::EnvironmentService
4
- extend UffizziCore::ComposeFile::VariablesService
3
+ class UffizziCore::ComposeFile::Parsers::Services::EnvironmentParserService
4
+ extend UffizziCore::ComposeFile::Parsers::VariablesParserService
5
5
 
6
6
  class << self
7
7
  def parse(environment)
@@ -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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ServicesOptions::ImageService
3
+ class UffizziCore::ComposeFile::Parsers::Services::ImageParserService
4
4
  class << self
5
5
  def parse(image)
6
6
  return {} if image.blank?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ServicesOptions::SecretsService
3
+ class UffizziCore::ComposeFile::Parsers::Services::SecretsParserService
4
4
  class << self
5
5
  def parse(secrets, global_secrets_data)
6
6
  return [] if secrets.nil?
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::ServicesOptionsService
3
+ class UffizziCore::ComposeFile::Parsers::ServicesParserService
4
4
  class << self
5
+ include UffizziCore::DependencyInjectionConcern
6
+
5
7
  def parse(services, global_configs_data, global_secrets_data, compose_payload)
6
8
  raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.no_services') if services.nil? || services.keys.empty?
7
9
 
@@ -18,32 +20,34 @@ class UffizziCore::ComposeFile::ServicesOptionsService
18
20
 
19
21
  private
20
22
 
21
- def prepare_service_data(service_name, service_data, global_configs_data, global_secrets_data, _compose_payload)
23
+ def prepare_service_data(service_name, service_data, global_configs_data, global_secrets_data, compose_payload)
22
24
  options_data = {}
23
25
  service_data.each_pair do |key, value|
24
26
  service_key = key.to_sym
25
27
 
26
28
  options_data[service_key] = case service_key
27
29
  when :image
28
- UffizziCore::ComposeFile::ServicesOptions::ImageService.parse(value)
30
+ UffizziCore::ComposeFile::Parsers::Services::ImageParserService.parse(value)
29
31
  when :build
30
- raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.not_implemented', option: :build)
32
+ check_and_parse_build_option(value, compose_payload)
31
33
  when :env_file
32
- UffizziCore::ComposeFile::ServicesOptions::EnvFileService.parse(value)
34
+ UffizziCore::ComposeFile::Parsers::Services::EnvFileParserService.parse(value)
33
35
  when :environment
34
- UffizziCore::ComposeFile::ServicesOptions::EnvironmentService.parse(value)
36
+ UffizziCore::ComposeFile::Parsers::Services::EnvironmentParserService.parse(value)
35
37
  when :configs
36
- UffizziCore::ComposeFile::ServicesOptions::ConfigsService.parse(value, global_configs_data)
38
+ UffizziCore::ComposeFile::Parsers::Services::ConfigsParserService.parse(value, global_configs_data)
37
39
  when :secrets
38
- UffizziCore::ComposeFile::ServicesOptions::SecretsService.parse(value, global_secrets_data)
40
+ UffizziCore::ComposeFile::Parsers::Services::SecretsParserService.parse(value, global_secrets_data)
39
41
  when :deploy
40
- UffizziCore::ComposeFile::ServicesOptions::DeployService.parse(value)
42
+ UffizziCore::ComposeFile::Parsers::Services::DeployParserService.parse(value)
41
43
  when :entrypoint
42
- UffizziCore::ComposeFile::ServicesOptions::EntrypointService.parse(value)
44
+ UffizziCore::ComposeFile::Parsers::Services::EntrypointParserService.parse(value)
43
45
  when :command
44
- UffizziCore::ComposeFile::ServicesOptions::CommandService.parse(value)
46
+ UffizziCore::ComposeFile::Parsers::Services::CommandParserService.parse(value)
47
+ when :healthcheck
48
+ UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService.parse(value)
45
49
  when :'x-uffizzi-continuous-preview', :'x-uffizzi-continuous-previews'
46
- UffizziCore::ComposeFile::ContinuousPreviewOptionsService.parse(value)
50
+ UffizziCore::ComposeFile::Parsers::ContinuousPreviewParserService.parse(value)
47
51
  end
48
52
  end
49
53
 
@@ -51,5 +55,11 @@ class UffizziCore::ComposeFile::ServicesOptionsService
51
55
 
52
56
  options_data
53
57
  end
58
+
59
+ def check_and_parse_build_option(value, compose_payload)
60
+ raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.not_implemented', option: :build) unless build_parser_module
61
+
62
+ build_parser_module.parse(value, compose_payload)
63
+ end
54
64
  end
55
65
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module UffizziCore::ComposeFile::VariablesService
3
+ module UffizziCore::ComposeFile::Parsers::VariablesParserService
4
4
  def parse_variable_from_string(str)
5
5
  variable_parts = str.split('=', 2)
6
6
 
@@ -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)