uffizzi_core 0.2.5 → 0.3.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.
- checksums.yaml +4 -4
- data/app/forms/uffizzi_core/api/cli/v1/deployment/create_form.rb +1 -0
- data/app/forms/uffizzi_core/api/cli/v1/deployment/update_form.rb +1 -0
- data/app/forms/uffizzi_core/api/cli/v1/template/create_form.rb +1 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +2 -1
- data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +3 -1
- data/app/services/uffizzi_core/amazon_service.rb +0 -14
- data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +4 -0
- data/app/services/uffizzi_core/compose_file/parsers/services/volumes_service.rb +94 -0
- data/app/services/uffizzi_core/compose_file/parsers/services_parser_service.rb +9 -3
- data/app/services/uffizzi_core/compose_file/parsers/volumes_parser_service.rb +23 -0
- data/app/services/uffizzi_core/compose_file_service.rb +3 -2
- data/app/services/uffizzi_core/controller_service.rb +1 -1
- data/app/services/uffizzi_core/credential_service.rb +1 -1
- data/app/services/uffizzi_core/deployment_service.rb +1 -1
- data/app/services/uffizzi_core/docker_hub_service.rb +1 -1
- data/app/services/uffizzi_core/google_service.rb +21 -0
- data/app/services/uffizzi_core/project_service.rb +1 -1
- data/app/services/uffizzi_core/repo_service.rb +1 -1
- data/config/locales/en.yml +5 -0
- data/db/migrate/20220422151523_add_volumes_to_uffizzi_core_containers.rb +7 -0
- data/lib/uffizzi_core/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40e3a8b7bbd915a1e861fbc7cff0b188741c49be50aa02d8ee05e790e47038a3
|
4
|
+
data.tar.gz: d02d1b3eba6bfbc471266dd28f23200a43cc88c71e7139c1d5bf43c915292f31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bff4a31ff842379bd0907336285b65f31052b58d55ecd104632d483304e07722b75d2591eba942c6583e99ea4f3d23c08765a42b1b102e478f031b5001c4ff4
|
7
|
+
data.tar.gz: 7d0e59f416be2ed26806363b85efa090eb3b02a3ba34546cd5103467d0f80566ddcb7f34270250c8112e65e2c2e35f2ce8dd6fab22f7fb958207e89f72c749f9
|
@@ -19,6 +19,7 @@ class UffizziCore::Api::Cli::V1::Deployment::CreateForm < UffizziCore::Deploymen
|
|
19
19
|
{ healthcheck: {} },
|
20
20
|
{ variables: [:name, :value],
|
21
21
|
secret_variables: [:name, :value],
|
22
|
+
volumes: [:source, :target, :type, :read_only],
|
22
23
|
repo_attributes: [
|
23
24
|
:namespace,
|
24
25
|
:name,
|
@@ -17,6 +17,7 @@ class UffizziCore::Api::Cli::V1::Deployment::UpdateForm < UffizziCore::Deploymen
|
|
17
17
|
:continuously_deploy,
|
18
18
|
{ variables: [:name, :value],
|
19
19
|
secret_variables: [:name, :value],
|
20
|
+
volumes: [:source, :target, :type, :read_only],
|
20
21
|
repo_attributes: [
|
21
22
|
:namespace,
|
22
23
|
:name,
|
@@ -21,6 +21,7 @@ class UffizziCore::Api::Cli::V1::Template::CreateForm < UffizziCore::Template
|
|
21
21
|
:healthcheck,
|
22
22
|
{ variables: [:name, :value],
|
23
23
|
secret_variables: [:name, :value],
|
24
|
+
volumes: [:source, :target, :type, :read_only],
|
24
25
|
repo_attributes: [
|
25
26
|
:namespace,
|
26
27
|
:name,
|
data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb
CHANGED
@@ -20,7 +20,8 @@ class UffizziCore::Api::Cli::V1::Projects::DeploymentSerializer::ContainerSerial
|
|
20
20
|
:repo_id,
|
21
21
|
:continuously_deploy,
|
22
22
|
:receive_incoming_requests,
|
23
|
-
:healthcheck
|
23
|
+
:healthcheck,
|
24
|
+
:volumes
|
24
25
|
|
25
26
|
def secret_variables
|
26
27
|
return unless object.secret_variables.present?
|
@@ -16,20 +16,6 @@ class UffizziCore::AmazonService
|
|
16
16
|
parsed_host[3]
|
17
17
|
end
|
18
18
|
|
19
|
-
def process_webhook(event, event_data)
|
20
|
-
case event
|
21
|
-
when 'PUSH'
|
22
|
-
source = UffizziCore::Repo::Amazon.name
|
23
|
-
image = event_data['repository-name']
|
24
|
-
tag = event_data['image-tag']
|
25
|
-
|
26
|
-
UffizziCore::ContinuouslyDeployService.run_docker_registry_process(source, image, tag)
|
27
|
-
UffizziCore::ContinuousPreviewService.run_docker_registry_process(source, image, tag)
|
28
|
-
else
|
29
|
-
Rails.logger.warn("Amazon #{event} event doesn't support")
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
19
|
private
|
34
20
|
|
35
21
|
def client(credential)
|
@@ -9,6 +9,7 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
|
|
9
9
|
@repositories = repositories
|
10
10
|
end
|
11
11
|
|
12
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
12
13
|
def build_attributes(container_data, ingress_data, continuous_preview_global_data, compose_dependencies)
|
13
14
|
image_data = container_data[:image] || {}
|
14
15
|
build_data = container_data[:build] || {}
|
@@ -18,6 +19,7 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
|
|
18
19
|
secrets = container_data[:secrets] || []
|
19
20
|
container_name = container_data[:container_name]
|
20
21
|
healthcheck_data = container_data[:healthcheck] || {}
|
22
|
+
volumes = container_data[:volumes] || []
|
21
23
|
|
22
24
|
env_file_dependencies = UffizziCore::ComposeFile::GithubDependenciesService.env_file_dependencies_for_container(compose_dependencies,
|
23
25
|
container_name)
|
@@ -44,8 +46,10 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
|
|
44
46
|
service_name: container_name,
|
45
47
|
name: container_name,
|
46
48
|
healthcheck: healthcheck_data,
|
49
|
+
volumes: volumes,
|
47
50
|
}
|
48
51
|
end
|
52
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
49
53
|
|
50
54
|
private
|
51
55
|
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::ComposeFile::Parsers::Services::VolumesService
|
4
|
+
HOST_VOLUME_TYPE = :host
|
5
|
+
NAMED_VOLUME_TYPE = :named
|
6
|
+
ANONYMOUS_VOLUME_TYPE = :anonymous
|
7
|
+
READONLY_OPTION = 'ro'
|
8
|
+
READ_WRITE_OPTION = 'rw'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def parse(volumes, named_volumes_names, service_name)
|
12
|
+
return [] if volumes.blank?
|
13
|
+
|
14
|
+
volumes.map do |volume|
|
15
|
+
volume_data = case volume
|
16
|
+
when String
|
17
|
+
process_short_syntax(volume, named_volumes_names, service_name)
|
18
|
+
when Hash
|
19
|
+
process_long_syntax(volume, named_volumes_names, service_name)
|
20
|
+
else
|
21
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_type', option: :volumes)
|
22
|
+
end
|
23
|
+
|
24
|
+
volume_data
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def process_short_syntax(volume_data, named_volumes_names, service_name)
|
31
|
+
volume_parts = volume_data.split(':').map(&:strip)
|
32
|
+
has_read_only = volume_parts.include?(READONLY_OPTION)
|
33
|
+
part1, part2 = volume_parts
|
34
|
+
source_path = part1
|
35
|
+
target_path = [READONLY_OPTION, READ_WRITE_OPTION].include?(part2.to_s.downcase) ? nil : part2
|
36
|
+
|
37
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.volume_prop_is_required', prop_name: 'source') if source_path.blank?
|
38
|
+
|
39
|
+
volume_type = volume_type(source_path, target_path)
|
40
|
+
|
41
|
+
check_named_volume_existence(source_path, target_path, named_volumes_names, service_name) if volume_type == NAMED_VOLUME_TYPE
|
42
|
+
|
43
|
+
{
|
44
|
+
source: source_path,
|
45
|
+
target: target_path,
|
46
|
+
type: volume_type,
|
47
|
+
read_only: has_read_only,
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def process_long_syntax(volume_data, named_volumes_names, service_name)
|
52
|
+
source_path = volume_data['source'].to_s.strip
|
53
|
+
target_path = volume_data['target'].to_s.strip
|
54
|
+
has_read_only = volume_data['read_only'].present?
|
55
|
+
|
56
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.volume_prop_is_required', prop_name: 'source') if source_path.blank?
|
57
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.volume_prop_is_required', prop_name: 'target') if target_path.blank?
|
58
|
+
|
59
|
+
volume_type = volume_type(source_path, target_path)
|
60
|
+
|
61
|
+
check_named_volume_existence(source_path, target_path, named_volumes_names, service_name) if volume_type == NAMED_VOLUME_TYPE
|
62
|
+
|
63
|
+
{
|
64
|
+
source: source_path,
|
65
|
+
target: target_path,
|
66
|
+
type: volume_type,
|
67
|
+
read_only: has_read_only,
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def volume_type(source_path, target_path)
|
72
|
+
if path?(source_path) && path?(target_path)
|
73
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.volume_type_not_supported', type: HOST_VOLUME_TYPE)
|
74
|
+
end
|
75
|
+
|
76
|
+
return ANONYMOUS_VOLUME_TYPE if path?(source_path) && target_path.blank?
|
77
|
+
return NAMED_VOLUME_TYPE if source_path.present? && !path?(source_path) && path?(target_path)
|
78
|
+
|
79
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.volume_path_is_invalid', path: [source_path, target_path].join(':'))
|
80
|
+
end
|
81
|
+
|
82
|
+
def path?(path)
|
83
|
+
/^(\/|\.\/|~\/)/.match?(path)
|
84
|
+
end
|
85
|
+
|
86
|
+
def check_named_volume_existence(source_path, target_path, named_volumes_names, service_name)
|
87
|
+
return if named_volumes_names.include?(source_path)
|
88
|
+
|
89
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.named_volume_not_exists', source_path: source_path,
|
90
|
+
target_path: target_path,
|
91
|
+
service_name: service_name)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -4,11 +4,12 @@ class UffizziCore::ComposeFile::Parsers::ServicesParserService
|
|
4
4
|
class << self
|
5
5
|
include UffizziCore::DependencyInjectionConcern
|
6
6
|
|
7
|
-
def parse(services, global_configs_data, global_secrets_data, compose_payload)
|
7
|
+
def parse(services, global_configs_data, global_secrets_data, compose_payload, global_named_volume_names)
|
8
8
|
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.no_services') if services.nil? || services.keys.empty?
|
9
9
|
|
10
10
|
services.keys.map do |service|
|
11
|
-
service_data = prepare_service_data(service, services.fetch(service), global_configs_data,
|
11
|
+
service_data = prepare_service_data(service, services.fetch(service), global_configs_data,
|
12
|
+
global_secrets_data, compose_payload, global_named_volume_names)
|
12
13
|
|
13
14
|
if service_data[:image].blank? && service_data[:build].blank?
|
14
15
|
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.image_build_no_specified', value: service)
|
@@ -20,7 +21,8 @@ class UffizziCore::ComposeFile::Parsers::ServicesParserService
|
|
20
21
|
|
21
22
|
private
|
22
23
|
|
23
|
-
def prepare_service_data(service_name, service_data, global_configs_data,
|
24
|
+
def prepare_service_data(service_name, service_data, global_configs_data,
|
25
|
+
global_secrets_data, compose_payload, global_named_volume_names)
|
24
26
|
options_data = {}
|
25
27
|
service_data.each_pair do |key, value|
|
26
28
|
service_key = key.to_sym
|
@@ -48,6 +50,10 @@ class UffizziCore::ComposeFile::Parsers::ServicesParserService
|
|
48
50
|
UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService.parse(value)
|
49
51
|
when :'x-uffizzi-continuous-preview', :'x-uffizzi-continuous-previews'
|
50
52
|
UffizziCore::ComposeFile::Parsers::ContinuousPreviewParserService.parse(value)
|
53
|
+
when :volumes
|
54
|
+
UffizziCore::ComposeFile::Parsers::Services::VolumesService.parse(value,
|
55
|
+
global_named_volume_names,
|
56
|
+
service_name)
|
51
57
|
end
|
52
58
|
end
|
53
59
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::ComposeFile::Parsers::VolumesParserService
|
4
|
+
VALID_VOLUME_NAME_REGEX = /^[a-zA-Z0-9._-]+$/.freeze
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def parse(volumes_data)
|
8
|
+
return [] if volumes_data.nil?
|
9
|
+
|
10
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_type', option: :volumes) unless volumes_data.is_a?(Hash)
|
11
|
+
|
12
|
+
volume_names = volumes_data.keys
|
13
|
+
volume_names.each do |volume_name|
|
14
|
+
unless volume_name.match?(VALID_VOLUME_NAME_REGEX)
|
15
|
+
raise UffizziCore::ComposeFile::ParseError,
|
16
|
+
I18n.t('compose.volume_invalid_name', name: volume_name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
volume_names
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
class UffizziCore::ComposeFileService
|
4
4
|
class << self
|
5
5
|
def create(params, kind)
|
6
6
|
compose_file_form = create_compose_form(params, kind)
|
@@ -19,13 +19,14 @@ module UffizziCore::ComposeFileService
|
|
19
19
|
check_config_options_format(compose_data)
|
20
20
|
configs_data = UffizziCore::ComposeFile::Parsers::ConfigsParserService.parse(compose_data['configs'])
|
21
21
|
secrets_data = UffizziCore::ComposeFile::Parsers::SecretsParserService.parse(compose_data['secrets'])
|
22
|
+
named_volume_names = UffizziCore::ComposeFile::Parsers::VolumesParserService.parse(compose_data['volumes'])
|
22
23
|
containers_data = UffizziCore::ComposeFile::Parsers::ServicesParserService.parse(
|
23
24
|
compose_data['services'],
|
24
25
|
configs_data,
|
25
26
|
secrets_data,
|
26
27
|
compose_payload,
|
28
|
+
named_volume_names,
|
27
29
|
)
|
28
|
-
|
29
30
|
continuous_preview_option = UffizziCore::ComposeFile::ConfigOptionService.continuous_preview_option(compose_data)
|
30
31
|
continuous_preview_data = UffizziCore::ComposeFile::Parsers::ContinuousPreviewParserService.parse(continuous_preview_option)
|
31
32
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::GoogleService
|
4
|
+
class << self
|
5
|
+
def digest(credential, image, tag)
|
6
|
+
response = registry_client(credential).manifests(image: image, tag: tag)
|
7
|
+
|
8
|
+
response.headers['docker-content-digest']
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def registry_client(credential)
|
14
|
+
UffizziCore::GoogleRegistryClient.new(
|
15
|
+
registry_url: credential.registry_url,
|
16
|
+
username: credential.username,
|
17
|
+
password: credential.password,
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/config/locales/en.yml
CHANGED
@@ -61,6 +61,11 @@ en:
|
|
61
61
|
string_or_array_error: "'%{option}' contains an invalid type, it should be a string, or an array"
|
62
62
|
not_implemented: "'%{option}' option is not implemented"
|
63
63
|
infinite_recursion: "Found infinite recursion for key '%{key}'"
|
64
|
+
volume_path_is_invalid: The path '%{path}' is invalid
|
65
|
+
volume_prop_is_required: The '%{prop_name}' is a required property
|
66
|
+
volume_invalid_name: "Volumes value '%{name}' does not match any of the regexes: '^[a-zA-Z0-9._-]+$'"
|
67
|
+
volume_type_not_supported: Volumes with type '%{type}' does not supported
|
68
|
+
named_volume_not_exists: Named volume '%{source_path}:%{target_path}' is used in service '%{service_name}' but no declaration was found in the volumes section.
|
64
69
|
secrets:
|
65
70
|
duplicates_exists: Secret with key %{secrets} already exist.
|
66
71
|
invalid_key_length: A secret key must be no longer than 256 characters.
|
data/lib/uffizzi_core/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uffizzi_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Thurman
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-07-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aasm
|
@@ -913,8 +913,10 @@ files:
|
|
913
913
|
- app/services/uffizzi_core/compose_file/parsers/services/healthcheck_parser_service.rb
|
914
914
|
- app/services/uffizzi_core/compose_file/parsers/services/image_parser_service.rb
|
915
915
|
- app/services/uffizzi_core/compose_file/parsers/services/secrets_parser_service.rb
|
916
|
+
- app/services/uffizzi_core/compose_file/parsers/services/volumes_service.rb
|
916
917
|
- app/services/uffizzi_core/compose_file/parsers/services_parser_service.rb
|
917
918
|
- app/services/uffizzi_core/compose_file/parsers/variables_parser_service.rb
|
919
|
+
- app/services/uffizzi_core/compose_file/parsers/volumes_parser_service.rb
|
918
920
|
- app/services/uffizzi_core/compose_file/template_service.rb
|
919
921
|
- app/services/uffizzi_core/compose_file_service.rb
|
920
922
|
- app/services/uffizzi_core/container_service.rb
|
@@ -925,6 +927,7 @@ files:
|
|
925
927
|
- app/services/uffizzi_core/docker_hub_service.rb
|
926
928
|
- app/services/uffizzi_core/github_container_registry/credential_service.rb
|
927
929
|
- app/services/uffizzi_core/google/credential_service.rb
|
930
|
+
- app/services/uffizzi_core/google_service.rb
|
928
931
|
- app/services/uffizzi_core/logs_service.rb
|
929
932
|
- app/services/uffizzi_core/manage_activity_items_service.rb
|
930
933
|
- app/services/uffizzi_core/project_service.rb
|
@@ -952,6 +955,7 @@ files:
|
|
952
955
|
- db/migrate/20220329124542_add_resource_to_secrets.rb
|
953
956
|
- db/migrate/20220329143241_remove_project_ref_from_secrets.rb
|
954
957
|
- db/migrate/20220419074956_add_health_check_to_containers.rb
|
958
|
+
- db/migrate/20220422151523_add_volumes_to_uffizzi_core_containers.rb
|
955
959
|
- db/migrate/20220525113412_rename_name_to_uffizzi_containers.rb
|
956
960
|
- db/seeds.rb
|
957
961
|
- lib/tasks/uffizzi_core_tasks.rake
|