uffizzi_core 2.1.18 → 2.1.19

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd14a19fefa5a0eb7f004a65b25a5c4cb3c517c9a8c7c53248eb5ea510e4d543
4
- data.tar.gz: 6f2ec4218d5f41aa53c5ce36eb94ad27c45770019be1ad84f979f67c3c02e416
3
+ metadata.gz: ba797af235e97eb6e8a82885dfa26e5ef451333937c874c6aaa958bfdc128efc
4
+ data.tar.gz: abbfad0cbba592e5230c2e2a5ac4ca4b2220e343a6ba36b770d52430a9836fb8
5
5
  SHA512:
6
- metadata.gz: bb0253b21dab789cd8aa07d3d68bde5ef2936cfeff7294179356e96fbef558a432e69a58398425d858ac19c35bde5de7af703e5743d48e0364fd16592184a955
7
- data.tar.gz: a6721ce9a827f50cb533159440c168372e6db339802a4b46564c2a608ce3fb1a9077dfc5c1651bd868ad87e7d18c45dbe9212230b7c16a267b9979e68b08e15d
6
+ metadata.gz: 6fa933fd65908f6313e68d5f91de1f5f4c7b99d946c9d6f486207677baee8f8518a266875d4cec4f5a95a39f40553595c1d5cd9290ffd37db8bcfa0e1d2fe61a
7
+ data.tar.gz: 00bd7079d17e53872cf3ff6e3b1ffda37bd445f47930e85737bff4bd1990dcb0f9d286f76e7b027854c6bd4e063f74b3318e3057408904abaead27c627713e6d
@@ -9,6 +9,7 @@ class UffizziCore::Api::Cli::V1::Deployment::CreateForm < UffizziCore::Deploymen
9
9
  :image,
10
10
  :service_name,
11
11
  :tag,
12
+ :full_image_name,
12
13
  :port,
13
14
  :public,
14
15
  :memory_limit,
@@ -9,6 +9,7 @@ class UffizziCore::Api::Cli::V1::Deployment::UpdateForm < UffizziCore::Deploymen
9
9
  :service_name,
10
10
  :tag,
11
11
  :port,
12
+ :full_image_name,
12
13
  :public,
13
14
  :memory_limit,
14
15
  :memory_request,
@@ -3,8 +3,7 @@
3
3
  class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCore::BaseSerializer
4
4
  attributes :id,
5
5
  :kind,
6
- :image,
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
- image_path, tag = get_image_path_and_tag(value)
9
- raise_parse_error(value) if image_path.blank?
10
-
11
- tag = Settings.compose.default_tag if tag.blank?
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: host,
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(value)
31
- raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_image_value', value: value)
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 contains_account_name?(image_name)
99
- image_name_parts = image_name.split('/')
35
+ def get_namespace_and_name(image_path)
36
+ return [nil, image_path] unless image_path.index('/').present?
100
37
 
101
- image_name_parts.count > 1
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.blank? && repository_url.blank?
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
 
@@ -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}'
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddFullImageNameToContainer < ActiveRecord::Migration[6.1]
4
+ def change
5
+ add_column(:uffizzi_core_containers, :full_image_name, :string)
6
+ end
7
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UffizziCore
4
- VERSION = '2.1.18'
4
+ VERSION = '2.1.19'
5
5
  end
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.18
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-10 00:00:00.000000000 Z
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