uffizzi_core 2.1.18 → 2.1.19
Sign up to get free protection for your applications and to get access to all the features.
- 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/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +1 -33
- data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +7 -0
- data/app/services/uffizzi_core/compose_file/parsers/services/image_parser_service.rb +19 -82
- data/app/services/uffizzi_core/compose_file_service.rb +1 -1
- data/app/services/uffizzi_core/container_registry_service.rb +2 -3
- data/config/locales/en.yml +1 -0
- data/db/migrate/20230406154451_add_full_image_name_to_container.rb +7 -0
- data/lib/uffizzi_core/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba797af235e97eb6e8a82885dfa26e5ef451333937c874c6aaa958bfdc128efc
|
4
|
+
data.tar.gz: abbfad0cbba592e5230c2e2a5ac4ca4b2220e343a6ba36b770d52430a9836fb8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fa933fd65908f6313e68d5f91de1f5f4c7b99d946c9d6f486207677baee8f8518a266875d4cec4f5a95a39f40553595c1d5cd9290ffd37db8bcfa0e1d2fe61a
|
7
|
+
data.tar.gz: 00bd7079d17e53872cf3ff6e3b1ffda37bd445f47930e85737bff4bd1990dcb0f9d286f76e7b027854c6bd4e063f74b3318e3057408904abaead27c627713e6d
|
@@ -3,8 +3,7 @@
|
|
3
3
|
class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCore::BaseSerializer
|
4
4
|
attributes :id,
|
5
5
|
:kind,
|
6
|
-
:
|
7
|
-
:tag,
|
6
|
+
:full_image_name,
|
8
7
|
:variables,
|
9
8
|
:secret_variables,
|
10
9
|
:memory_limit,
|
@@ -24,26 +23,6 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
|
|
24
23
|
has_many :container_config_files
|
25
24
|
has_many :container_host_volume_files
|
26
25
|
|
27
|
-
def image
|
28
|
-
repo = object.repo
|
29
|
-
case repo.type
|
30
|
-
when
|
31
|
-
UffizziCore::Repo::Google.name,
|
32
|
-
UffizziCore::Repo::Amazon.name,
|
33
|
-
UffizziCore::Repo::Azure.name,
|
34
|
-
UffizziCore::Repo::GithubContainerRegistry.name,
|
35
|
-
UffizziCore::Repo::DockerRegistry.name
|
36
|
-
|
37
|
-
build_registry_image(repo)
|
38
|
-
else
|
39
|
-
object.image
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def tag
|
44
|
-
object.tag
|
45
|
-
end
|
46
|
-
|
47
26
|
def entrypoint
|
48
27
|
object.entrypoint.blank? ? nil : JSON.parse(object.entrypoint)
|
49
28
|
end
|
@@ -65,15 +44,4 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
|
|
65
44
|
|
66
45
|
object.healthcheck.merge('test' => new_command)
|
67
46
|
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def build_registry_image(repo)
|
72
|
-
credential = UffizziCore::RepoService.credential(repo)
|
73
|
-
return object.image if credential.blank?
|
74
|
-
|
75
|
-
registry_host = URI.parse(credential.registry_url).host
|
76
|
-
|
77
|
-
"#{registry_host}/#{object.image}"
|
78
|
-
end
|
79
47
|
end
|
@@ -33,6 +33,7 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
|
|
33
33
|
{
|
34
34
|
tag: tag(image_data, repo_attributes),
|
35
35
|
port: port(container_name, ingress_data),
|
36
|
+
full_image_name: full_image_name(image_data, build_data, repo_attributes),
|
36
37
|
image: image(container_data, image_data, build_data, credentials),
|
37
38
|
public: is_ingress,
|
38
39
|
entrypoint: entrypoint(container_data),
|
@@ -134,6 +135,12 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
|
|
134
135
|
container_registry.image_name(credentials)
|
135
136
|
end
|
136
137
|
|
138
|
+
def full_image_name(image_data, build_data, repo_attributes)
|
139
|
+
return image_data[:full_image_name] if image_data.present?
|
140
|
+
|
141
|
+
"#{build_data[:account_name]}/#{build_data[:repository_name]}:#{repo_attributes[:branch]}"
|
142
|
+
end
|
143
|
+
|
137
144
|
def ingress_container?(container_name, ingress)
|
138
145
|
ingress[:container_name] == container_name
|
139
146
|
end
|
@@ -1,104 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'docker_distribution'
|
4
|
+
|
3
5
|
class UffizziCore::ComposeFile::Parsers::Services::ImageParserService
|
6
|
+
DEFAULT_TAG = Settings.compose.default_tag
|
4
7
|
class << self
|
5
8
|
def parse(value)
|
6
9
|
return {} if value.blank?
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
formatted_image_path = image_path.downcase
|
14
|
-
if url?(formatted_image_path)
|
15
|
-
host, namespace, name = parse_image_url(formatted_image_path)
|
16
|
-
else
|
17
|
-
namespace, name = parse_docker_hub_image(formatted_image_path)
|
18
|
-
end
|
11
|
+
parsed_image = DockerDistribution::Normalize.parse_docker_ref(value)
|
12
|
+
image_path = parsed_image.path
|
13
|
+
namespace, name = get_namespace_and_name(image_path)
|
14
|
+
full_image_name = "#{[parsed_image.domain, parsed_image.path].compact.join('/')}:#{parsed_image.tag}"
|
19
15
|
|
20
16
|
{
|
21
|
-
registry_url:
|
17
|
+
registry_url: parsed_image.domain,
|
22
18
|
namespace: namespace,
|
23
19
|
name: name,
|
24
|
-
tag: tag,
|
20
|
+
tag: parsed_image.tag,
|
21
|
+
full_image_name: full_image_name,
|
25
22
|
}
|
23
|
+
rescue DockerDistribution::NameContainsUppercase
|
24
|
+
raise_parse_error(I18n.t('compose.image_name_contains_uppercase_value', value: value))
|
25
|
+
rescue DockerDistribution::ReferenceInvalidFormat, DockerDistribution::ParseNormalizedNamedError
|
26
|
+
raise_parse_error(I18n.t('compose.invalid_image_value', value: value))
|
26
27
|
end
|
27
28
|
|
28
29
|
private
|
29
30
|
|
30
|
-
def raise_parse_error(
|
31
|
-
raise UffizziCore::ComposeFile::ParseError,
|
32
|
-
end
|
33
|
-
|
34
|
-
def get_image_path_and_tag(value)
|
35
|
-
image_path_parts = value.split(':')
|
36
|
-
|
37
|
-
case image_path_parts.size
|
38
|
-
when 1
|
39
|
-
image_path_parts[0]
|
40
|
-
when 2
|
41
|
-
uri_pattern = /\A\w[\w.-]+:\d+\//
|
42
|
-
tag_pattern = /:\w[\w.-]*\z/
|
43
|
-
if uri_pattern.match?(value)
|
44
|
-
"#{image_path_parts[0]}:#{image_path_parts[1]}"
|
45
|
-
elsif tag_pattern.match?(value)
|
46
|
-
[image_path_parts[0], image_path_parts[1]]
|
47
|
-
else
|
48
|
-
raise_parse_error(value)
|
49
|
-
end
|
50
|
-
when 3
|
51
|
-
["#{image_path_parts[0]}:#{image_path_parts[1]}", image_path_parts[2]]
|
52
|
-
else
|
53
|
-
raise_parse_error(value)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def url?(image_path)
|
58
|
-
uri = URI(add_https_if_needed(image_path))
|
59
|
-
uri.host.present? && uri.host =~ /(localhost(:\d+)?|\w+\.(\w+\.)*\w+)/ && uri.path.present?
|
60
|
-
rescue URI::InvalidURIError
|
61
|
-
false
|
62
|
-
end
|
63
|
-
|
64
|
-
def add_https_if_needed(image_path)
|
65
|
-
image_path.start_with?('https://') ? image_path : "https://#{image_path}"
|
66
|
-
end
|
67
|
-
|
68
|
-
def parse_image_url(image_path)
|
69
|
-
uri = URI(add_https_if_needed(image_path))
|
70
|
-
host = "#{uri.host}:#{uri.port}"
|
71
|
-
path = uri.path.delete_prefix('/')
|
72
|
-
namespace, name = get_namespace_and_name(path)
|
73
|
-
[host, namespace, name]
|
74
|
-
end
|
75
|
-
|
76
|
-
def get_namespace_and_name(path)
|
77
|
-
path_parts = path.rpartition('/')
|
78
|
-
|
79
|
-
if path_parts.first.empty?
|
80
|
-
[nil, path_parts.last]
|
81
|
-
else
|
82
|
-
[path_parts.first, path_parts.last]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def parse_docker_hub_image(image_name)
|
87
|
-
if contains_account_name?(image_name)
|
88
|
-
namespace = image_name.split('/').first
|
89
|
-
name = image_name.split('/', 2).last.delete_suffix('/')
|
90
|
-
else
|
91
|
-
namespace = Settings.docker_hub.public_namespace
|
92
|
-
name = image_name
|
93
|
-
end
|
94
|
-
|
95
|
-
[namespace, name]
|
31
|
+
def raise_parse_error(message)
|
32
|
+
raise UffizziCore::ComposeFile::ParseError, message
|
96
33
|
end
|
97
34
|
|
98
|
-
def
|
99
|
-
|
35
|
+
def get_namespace_and_name(image_path)
|
36
|
+
return [nil, image_path] unless image_path.index('/').present?
|
100
37
|
|
101
|
-
|
38
|
+
image_path.split('/')
|
102
39
|
end
|
103
40
|
end
|
104
41
|
end
|
@@ -190,7 +190,7 @@ class UffizziCore::ComposeFileService
|
|
190
190
|
err = [e.problem, e.context].compact.join(' ')
|
191
191
|
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_file', err: err, line: e.line, column: e.column)
|
192
192
|
end
|
193
|
-
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.unsupported_file') if compose_data.nil?
|
193
|
+
raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.unsupported_file') if compose_data.nil? || compose_data.is_a?(String)
|
194
194
|
|
195
195
|
compose_data
|
196
196
|
end
|
@@ -11,9 +11,8 @@ class UffizziCore::ContainerRegistryService
|
|
11
11
|
|
12
12
|
def init_by_container(container)
|
13
13
|
registry_url = container.dig(:image, :registry_url)
|
14
|
-
repository_url = container.dig(:build, :repository_url)
|
15
14
|
|
16
|
-
return new(:docker_hub, container) if registry_url.
|
15
|
+
return new(:docker_hub, container) if registry_url.include?('docker.io')
|
17
16
|
return new(:azure, container) if registry_url.include?('azurecr.io')
|
18
17
|
return new(:google, container) if registry_url.include?('gcr.io')
|
19
18
|
return new(:amazon, container) if registry_url.include?('amazonaws.com')
|
@@ -71,7 +70,7 @@ class UffizziCore::ContainerRegistryService
|
|
71
70
|
end
|
72
71
|
|
73
72
|
def image_name(credentials)
|
74
|
-
if image_data[:registry_url].present? && [:google, :github_container_registry, :docker_registry].exclude?(type)
|
73
|
+
if image_data[:registry_url].present? && [:google, :github_container_registry, :docker_registry, :docker_hub].exclude?(type)
|
75
74
|
return image_data[:name]
|
76
75
|
end
|
77
76
|
|
data/config/locales/en.yml
CHANGED
@@ -19,6 +19,7 @@ en:
|
|
19
19
|
invalid_service_name: "Invalid service name '%{value}': a service name must consist of lower case alphanumeric characters, ''-'', and must start and end with an alphanumeric character"
|
20
20
|
no_ingress: Service ingress has not been defined.
|
21
21
|
invalid_image_value: Invalid image value '%{value}'
|
22
|
+
image_name_contains_uppercase_value: Image name '%{value}' contains uppercase characters
|
22
23
|
unprocessable_image: Invalid credential '%{value} or image does not exist'
|
23
24
|
invalid_repo_type: Unsupported repo type
|
24
25
|
repo_not_found: The specified repository doesn't exist '%{name}'
|
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: 2.1.
|
4
|
+
version: 2.1.19
|
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: 2023-04-
|
12
|
+
date: 2023-04-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aasm
|
@@ -137,6 +137,20 @@ dependencies:
|
|
137
137
|
- - "~>"
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '1.61'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: docker_distribution
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
type: :runtime
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
140
154
|
- !ruby/object:Gem::Dependency
|
141
155
|
name: dotenv
|
142
156
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1029,6 +1043,7 @@ files:
|
|
1029
1043
|
- db/migrate/20220927113647_add_additional_subdomains_to_containers.rb
|
1030
1044
|
- db/migrate/20230111000000_add_state_to_memberships.rb
|
1031
1045
|
- db/migrate/20230306142513_add_last_deploy_at_to_deployments.rb
|
1046
|
+
- db/migrate/20230406154451_add_full_image_name_to_container.rb
|
1032
1047
|
- db/seeds.rb
|
1033
1048
|
- lib/tasks/uffizzi_core_tasks.rake
|
1034
1049
|
- lib/uffizzi_core.rb
|