uffizzi_core 0.3.8 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc9d18f96d6809d2ff9ba942eb283d7b54e876e05bcb31cfc991ba3bbec9c241
4
- data.tar.gz: 01601aec07efaf6fe0cd292968ce9480efed6b1d1f0aaaac8a50bc9cd4bb5792
3
+ metadata.gz: d74f053e95889cc81420df79037dae73dfec491ad003336bd483c2a11fd85a54
4
+ data.tar.gz: f88cad281aebeff5539974da55309605475611b44334cf8123d02ace07a3a605
5
5
  SHA512:
6
- metadata.gz: c9cb8d9bc0d2ba8f6d759936a5a3137ba6a1db2ca87283e8ce35bc09bfd19204d477f054be4f0b695b4f877fb705af9b2377f04fd329f80bee97052c6559763b
7
- data.tar.gz: bc0d50ccaf1b9c17ab607452152522924f0a32567952907d035ae3167680ca1e03784a96f7cb4cc43f93cb3c3ce47d8a282fbc19acdf9a9a0bde90b9b4ffff46
6
+ metadata.gz: 47e76bf5ed74fdbb986df1400784439ada1bea3a045af398adcfae52bbb7baf7c3b81b5ea5c8c2c31100be30b3b99aea70dcda6a60ab67aecc860685d8b98fce
7
+ data.tar.gz: d668aa5535639216a3ad4b6cde717ddc363f3754ae1dd1c1b5d7d43da995c7829f1f14ac1dd496af60f6dc495e11099f2f23769e4aabe7647d3972ce7fdccc15
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::DockerRegistryClient::RequestResult < Hashie::Mash
4
+ disable_warnings :key
5
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::DockerRegistryClient
4
+ def initialize(credentials)
5
+ @registry_url = credentials.registry_url
6
+ @connection = build_connection(@registry_url, credentials.username, credentials.password)
7
+ end
8
+
9
+ def authenticated?
10
+ response = @connection.head('/v2/')
11
+ response.status == 200
12
+ end
13
+
14
+ private
15
+
16
+ def build_connection(registry_url, username, password)
17
+ Faraday.new(registry_url) do |conn|
18
+ conn.request(:basic_auth, username, password)
19
+ conn.request(:json)
20
+ conn.response(:json)
21
+ conn.adapter(Faraday.default_adapter)
22
+ end
23
+ end
24
+ end
@@ -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
+ # Possible types:
28
+ # UffizziCore::Credential::Amazon, UffizziCore::Credential::Azure, UffizziCore::Credential::DockerHub,
29
+ # UffizziCore::Credential::DockerRegistry, UffizziCore::Credential::Google, UffizziCore::Credential::GithubContainerRegistry
30
30
  def create
31
31
  credential_form = UffizziCore::Api::Cli::V1::Account::Credential::CreateForm.new
32
32
  credential_form.assign_attributes(credential_params)
@@ -37,6 +37,10 @@ module UffizziCore::Concerns::Models::Credential
37
37
  type == UffizziCore::Credential::DockerHub.name
38
38
  end
39
39
 
40
+ def docker_registry?
41
+ type == UffizziCore::Credential::DockerRegistry.name
42
+ end
43
+
40
44
  def azure?
41
45
  type == UffizziCore::Credential::Azure.name
42
46
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Credential::DockerRegistry < UffizziCore::Credential
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Repo::DockerRegistry < UffizziCore::Repo
4
+ end
@@ -6,6 +6,7 @@ module UffizziCore::CredentialRepo
6
6
  included do
7
7
  scope :by_type, ->(type) { where(type: type) }
8
8
  scope :docker_hub, -> { by_type(UffizziCore::Credential::DockerHub.name) }
9
+ scope :docker_registry, -> { by_type(UffizziCore::Credential::DockerRegistry.name) }
9
10
  scope :azure, -> { by_type(UffizziCore::Credential::Azure.name) }
10
11
  scope :google, -> { by_type(UffizziCore::Credential::Google.name) }
11
12
  scope :amazon, -> { by_type(UffizziCore::Credential::Amazon.name) }
@@ -13,6 +14,7 @@ module UffizziCore::CredentialRepo
13
14
  scope :deployable, -> {
14
15
  by_type([
15
16
  UffizziCore::Credential::DockerHub.name,
17
+ UffizziCore::Credential::DockerRegistry.name,
16
18
  UffizziCore::Credential::Azure.name,
17
19
  UffizziCore::Credential::Google.name,
18
20
  UffizziCore::Credential::Amazon.name,
@@ -24,13 +24,16 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
24
24
 
25
25
  def image
26
26
  repo = object.repo
27
- credential = UffizziCore::RepoService.credential(repo)
28
-
29
27
  case repo.type
30
- when UffizziCore::Repo::Google.name, UffizziCore::Repo::Amazon.name, UffizziCore::Repo::Azure.name,
31
- UffizziCore::Repo::GithubContainerRegistry.name
32
- registry_host = URI.parse(credential.registry_url).host
28
+ when
29
+ UffizziCore::Repo::Google.name,
30
+ UffizziCore::Repo::Amazon.name,
31
+ UffizziCore::Repo::Azure.name,
32
+ UffizziCore::Repo::GithubContainerRegistry.name,
33
+ UffizziCore::Repo::DockerRegistry.name
33
34
 
35
+ credential = UffizziCore::RepoService.credential(repo)
36
+ registry_host = URI.parse(credential.registry_url).host
34
37
  "#{registry_host}/#{object.image}"
35
38
  else
36
39
  object.image
@@ -107,7 +107,8 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
107
107
  def image_name(container_data, image_data)
108
108
  if image_data[:registry_url].present? &&
109
109
  !UffizziCore::ComposeFile::ContainerService.google?(container_data) &&
110
- !UffizziCore::ComposeFile::ContainerService.github_container_registry?(container_data)
110
+ !UffizziCore::ComposeFile::ContainerService.github_container_registry?(container_data) &&
111
+ !UffizziCore::ComposeFile::ContainerService.docker_registry?(container_data)
111
112
  image_data[:name]
112
113
  else
113
114
  "#{image_data[:namespace]}/#{image_data[:name]}"
@@ -166,6 +167,8 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
166
167
  case repo_type
167
168
  when UffizziCore::Repo::DockerHub.name
168
169
  build_docker_repo_attributes(image_data, credentials, :docker_hub, UffizziCore::Repo::DockerHub.name)
170
+ when UffizziCore::Repo::DockerRegistry.name
171
+ build_docker_repo_attributes(image_data, credentials, :docker_registry, UffizziCore::Repo::DockerRegistry.name)
169
172
  when UffizziCore::Repo::Azure.name
170
173
  build_docker_repo_attributes(image_data, credentials, :azure, UffizziCore::Repo::Azure.name)
171
174
  when UffizziCore::Repo::Google.name
@@ -184,6 +187,8 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
184
187
  UffizziCore::Repo::Azure.name
185
188
  elsif UffizziCore::ComposeFile::ContainerService.docker_hub?(container_data)
186
189
  UffizziCore::Repo::DockerHub.name
190
+ elsif UffizziCore::ComposeFile::ContainerService.docker_registry?(container_data)
191
+ UffizziCore::Repo::DockerRegistry.name
187
192
  elsif UffizziCore::ComposeFile::ContainerService.google?(container_data)
188
193
  UffizziCore::Repo::Google.name
189
194
  elsif UffizziCore::ComposeFile::ContainerService.github_container_registry?(container_data)
@@ -27,6 +27,15 @@ class UffizziCore::ComposeFile::ContainerService
27
27
  registry_url.nil? && repository_url.nil?
28
28
  end
29
29
 
30
+ def docker_registry?(container)
31
+ registry_url = container.dig(:image, :registry_url)
32
+ registry_domain_regexp = /(\w+\.\w{2,})(?::\d+)?\z/
33
+ registry_domain = registry_url.match(registry_domain_regexp)&.to_a&.last
34
+ return false if registry_url.nil? || registry_domain.nil?
35
+
36
+ ['amazonaws.com', 'azurecr.io', 'gcr.io', 'ghcr.io'].exclude?(registry_domain)
37
+ end
38
+
30
39
  def github_container_registry?(container)
31
40
  registry_url = container.dig(:image, :registry_url)
32
41
 
@@ -2,24 +2,23 @@
2
2
 
3
3
  class UffizziCore::ComposeFile::Parsers::Services::ImageParserService
4
4
  class << self
5
- def parse(image)
6
- return {} if image.blank?
5
+ def parse(value)
6
+ return {} if value.blank?
7
7
 
8
- image_parts = image.downcase.split(':')
9
- raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_image_value', value: image) if image_parts.count > 2
8
+ parse_error = UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_image_value', value: value)
9
+ image_path, tag = get_image_path_and_tag(value, parse_error)
10
+ raise parse_error if image_path.blank?
10
11
 
11
- image_name, tag = image_parts
12
12
  tag = Settings.compose.default_tag if tag.blank?
13
- raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_image_value', value: image) if image_name.blank?
14
13
 
15
- if valid_image_url?(image_name)
16
- url, namespace, name = parse_image_url(image_name)
14
+ if url?(image_path)
15
+ host, namespace, name = parse_image_url(image_path)
17
16
  else
18
- namespace, name = parse_docker_hub_image(image_name)
17
+ namespace, name = parse_docker_hub_image(image_path)
19
18
  end
20
19
 
21
20
  {
22
- registry_url: url,
21
+ registry_url: host,
23
22
  namespace: namespace,
24
23
  name: name,
25
24
  tag: tag,
@@ -28,44 +27,55 @@ class UffizziCore::ComposeFile::Parsers::Services::ImageParserService
28
27
 
29
28
  private
30
29
 
31
- def valid_image_url?(image_name)
32
- url = prepare_image_url(image_name)
33
-
34
- URI(url).host.present? && URI(url).host =~ /\w+\.\w+/ && URI(url).path.present?
35
- end
36
-
37
- def prepare_image_url(image_name)
38
- if image_name.start_with?('https://')
39
- image_name
30
+ def get_image_path_and_tag(value, parse_error)
31
+ image_path_parts = value.downcase.split(':')
32
+ case image_path_parts.size
33
+ when 1
34
+ image_path_parts[0]
35
+ when 2
36
+ uri_pattern = /\A\w[\w.-]+:\d+/
37
+ tag_pattern = /:\w[\w.-]*\z/
38
+ if uri_pattern.match?(value)
39
+ "#{image_path_parts[0]}:#{image_path_parts[1]}"
40
+ elsif tag_pattern.match?(value)
41
+ [image_path_parts[0], image_path_parts[1]]
42
+ else
43
+ raise parse_error
44
+ end
45
+ when 3
46
+ ["#{image_path_parts[0]}:#{image_path_parts[1]}", image_path_parts[2]]
40
47
  else
41
- "https://#{image_name}"
48
+ raise parse_error
42
49
  end
43
50
  end
44
51
 
45
- def parse_image_url(image_name)
46
- prepared_url = prepare_image_url(image_name)
47
-
48
- uri = URI(prepared_url)
49
- url = uri.host
50
- path = uri.path.delete_suffix('/').delete_prefix('/')
52
+ def url?(image_path)
53
+ uri = URI(add_https_if_needed(image_path))
54
+ uri.host.present? && uri.host =~ /\w+\.(\w+\.)*\w+/ && uri.path.present?
55
+ rescue URI::InvalidURIError
56
+ false
57
+ end
51
58
 
52
- namespace, name = parse_image_path(path)
59
+ def add_https_if_needed(image_path)
60
+ image_path.start_with?('https://') ? image_path : "https://#{image_path}"
61
+ end
53
62
 
54
- [url, namespace, name]
63
+ def parse_image_url(image_path)
64
+ uri = URI(add_https_if_needed(image_path))
65
+ host = "#{uri.host}:#{uri.port}"
66
+ path = uri.path.delete_prefix('/')
67
+ namespace, name = get_namespace_and_name(path)
68
+ [host, namespace, name]
55
69
  end
56
70
 
57
- def parse_image_path(path)
58
- path_parts = path.split('/', 2)
71
+ def get_namespace_and_name(path)
72
+ path_parts = path.rpartition('/')
59
73
 
60
- if path_parts.count == 1
61
- namespace = nil
62
- name = path_parts.first
74
+ if path_parts.first.empty?
75
+ [nil, path_parts.last]
63
76
  else
64
- namespace = path_parts.first
65
- name = path_parts.last
77
+ [path_parts.first, path_parts.last]
66
78
  end
67
-
68
- [namespace, name]
69
79
  end
70
80
 
71
81
  def parse_docker_hub_image(image_name)
@@ -6,6 +6,8 @@ class UffizziCore::CredentialService
6
6
  status = case credential.type
7
7
  when UffizziCore::Credential::DockerHub.name
8
8
  UffizziCore::DockerHub::CredentialService.credential_correct?(credential)
9
+ when UffizziCore::Credential::DockerRegistry.name
10
+ UffizziCore::DockerRegistry::CredentialService.credential_correct?(credential)
9
11
  when UffizziCore::Credential::GithubContainerRegistry.name
10
12
  UffizziCore::GithubContainerRegistry::CredentialService.credential_correct?(credential)
11
13
  when UffizziCore::Credential::Azure.name
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::DockerRegistry::CredentialService
4
+ class << self
5
+ def credential_correct?(credential)
6
+ client(credential).authenticated?
7
+ end
8
+
9
+ private
10
+
11
+ def client(credential)
12
+ UffizziCore::DockerRegistryClient.new(credential)
13
+ end
14
+ end
15
+ end
@@ -16,6 +16,8 @@ class UffizziCore::RepoService
16
16
  credentials.github_container_registry.first
17
17
  when UffizziCore::Repo::DockerHub.name
18
18
  credentials.docker_hub.first
19
+ when UffizziCore::Repo::DockerRegistry.name
20
+ credentials.docker_registry.first
19
21
  when UffizziCore::Repo::Azure.name
20
22
  credentials.azure.first
21
23
  when UffizziCore::Repo::Google.name
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UffizziCore
4
- VERSION = '0.3.8'
4
+ VERSION = '0.4.0'
5
5
  end
@@ -80,7 +80,7 @@
80
80
  "default": {
81
81
  "description": "Create account credential",
82
82
  "examples": {
83
- "application/json": "type can be one of UffizziCore::Credential::Amazon, UffizziCore::Credential::Azure, UffizziCore::Credential::DockerHub, UffizziCore::Credential::Google, UffizziCore::Credential::GithubContainerRegistry"
83
+ "application/json": "Possible types:\nUffizziCore::Credential::Amazon, UffizziCore::Credential::Azure, UffizziCore::Credential::DockerHub,\nUffizziCore::Credential::DockerRegistry, UffizziCore::Credential::Google, UffizziCore::Credential::GithubContainerRegistry"
84
84
  }
85
85
  },
86
86
  "201": {
@@ -1301,16 +1301,8 @@
1301
1301
  }
1302
1302
  ],
1303
1303
  "responses": {
1304
- "200": {
1305
- "description": "OK",
1306
- "schema": {
1307
- "type": "object",
1308
- "properties": {
1309
- "project": {
1310
- "$ref": "#/definitions/Project"
1311
- }
1312
- }
1313
- }
1304
+ "204": {
1305
+ "description": "No content"
1314
1306
  },
1315
1307
  "404": {
1316
1308
  "description": "Not Found"
@@ -1339,8 +1331,16 @@
1339
1331
  }
1340
1332
  ],
1341
1333
  "responses": {
1342
- "204": {
1343
- "description": "No content"
1334
+ "200": {
1335
+ "description": "OK",
1336
+ "schema": {
1337
+ "type": "object",
1338
+ "properties": {
1339
+ "project": {
1340
+ "$ref": "#/definitions/Project"
1341
+ }
1342
+ }
1343
+ }
1344
1344
  },
1345
1345
  "404": {
1346
1346
  "description": "Not Found"
@@ -1720,4 +1720,4 @@
1720
1720
  }
1721
1721
  }
1722
1722
  }
1723
- }
1723
+ }
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.3.8
4
+ version: 0.4.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-08-04 00:00:00.000000000 Z
12
+ date: 2022-08-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aasm
@@ -695,6 +695,8 @@ files:
695
695
  - app/clients/uffizzi_core/docker_hub_client.rb
696
696
  - app/clients/uffizzi_core/docker_hub_client/not_authorized_error.rb
697
697
  - app/clients/uffizzi_core/docker_hub_client/request_result.rb
698
+ - app/clients/uffizzi_core/docker_registry_client.rb
699
+ - app/clients/uffizzi_core/docker_registry_client/request_result.rb
698
700
  - app/clients/uffizzi_core/github_container_registry_client.rb
699
701
  - app/clients/uffizzi_core/github_container_registry_client/request_result.rb
700
702
  - app/clients/uffizzi_core/google_registry_client.rb
@@ -809,6 +811,7 @@ files:
809
811
  - app/models/uffizzi_core/credential/amazon.rb
810
812
  - app/models/uffizzi_core/credential/azure.rb
811
813
  - app/models/uffizzi_core/credential/docker_hub.rb
814
+ - app/models/uffizzi_core/credential/docker_registry.rb
812
815
  - app/models/uffizzi_core/credential/github.rb
813
816
  - app/models/uffizzi_core/credential/github_container_registry.rb
814
817
  - app/models/uffizzi_core/credential/google.rb
@@ -827,6 +830,7 @@ files:
827
830
  - app/models/uffizzi_core/repo/amazon.rb
828
831
  - app/models/uffizzi_core/repo/azure.rb
829
832
  - app/models/uffizzi_core/repo/docker_hub.rb
833
+ - app/models/uffizzi_core/repo/docker_registry.rb
830
834
  - app/models/uffizzi_core/repo/github.rb
831
835
  - app/models/uffizzi_core/repo/github_container_registry.rb
832
836
  - app/models/uffizzi_core/repo/google.rb
@@ -928,6 +932,7 @@ files:
928
932
  - app/services/uffizzi_core/deployment_service.rb
929
933
  - app/services/uffizzi_core/docker_hub/credential_service.rb
930
934
  - app/services/uffizzi_core/docker_hub_service.rb
935
+ - app/services/uffizzi_core/docker_registry/credential_service.rb
931
936
  - app/services/uffizzi_core/github_container_registry/credential_service.rb
932
937
  - app/services/uffizzi_core/google/credential_service.rb
933
938
  - app/services/uffizzi_core/google_service.rb