uffizzi_core 1.0.0 → 1.0.2

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: 9e845782f77d940f0bf244d792b59cab89df2712937e6b77f3bec3bc62653f3b
4
- data.tar.gz: eb8a760d66cbdc40b7e441a783870483ca3c72ffe8fa212e4ee93aa9c9718bf1
3
+ metadata.gz: 520b79e2bc010eab840b4a6c4d31fe236c7b1e1a04714a42319399d904208b09
4
+ data.tar.gz: 4cdf4a4e66308a13bcb9740ea3aafb63d1de49c128fef7fb4d59731045ac1877
5
5
  SHA512:
6
- metadata.gz: 4e6093cb8c244cf7c22044add288ee501c94968436407d2138c32763806266d4877d6c915464cc988d868e91ac0ae50e47fac05408e7e2d432638bfd15929a0e
7
- data.tar.gz: 29c118eb1355950bf9ce5c590e4562490dec59fc1ca9cbbb4028d504f2a28b7cc155fd471f74948796a0f213cabe4c68330921dd9a6caa24ac41247e3f139bf6
6
+ metadata.gz: 8e44e43bb064368f55ca82ad30eb989ee8503a65a2daad496f50608d983c39da93543ec8ea6cddeef7cbcf1367bd1916bc929fc7015b5fd0121d6eb987333f2e
7
+ data.tar.gz: 414e34bec819810a75c0fe13ca4652ab0a26d271f1bedd8d11d9e50f9ebbd918f83209205c5a0a5005f8db2c59889114268a961b8a4a93ea270c43e37b43f498
@@ -23,6 +23,15 @@ class UffizziCore::DockerHubClient
23
23
  nil
24
24
  end
25
25
 
26
+ def repository(namespace:, image:)
27
+ url = "#{BASE_URL}/v2/repositories/#{namespace}/#{image}"
28
+
29
+ response = connection.get(url) do |request|
30
+ request.headers['Authorization'] = "JWT #{jwt}"
31
+ end
32
+ RequestResult.new(status: response.status, result: response.body)
33
+ end
34
+
26
35
  def public_images(q:, page: 1, per_page: 25)
27
36
  url = "#{BASE_URL}/api/content/v1/products/search"
28
37
  params = { page_size: per_page, q: q, type: :image, page: page }
@@ -17,10 +17,10 @@ class UffizziCore::Api::Cli::V1::Deployment::CreateForm < UffizziCore::Deploymen
17
17
  :command,
18
18
  :receive_incoming_requests,
19
19
  :continuously_deploy,
20
- { healthcheck: {} },
21
20
  { variables: [:name, :value],
22
21
  secret_variables: [:name, :value],
23
22
  volumes: [:source, :target, :type, :read_only],
23
+ healthcheck: [:test, :interval, :timeout, :retries, :start_period, :disable, { test: [] }],
24
24
  repo_attributes: [
25
25
  :namespace,
26
26
  :name,
@@ -19,6 +19,7 @@ class UffizziCore::Api::Cli::V1::Deployment::UpdateForm < UffizziCore::Deploymen
19
19
  { variables: [:name, :value],
20
20
  secret_variables: [:name, :value],
21
21
  volumes: [:source, :target, :type, :read_only],
22
+ healthcheck: [:test, :interval, :timeout, :retries, :start_period, :disable, { test: [] }],
22
23
  repo_attributes: [
23
24
  :namespace,
24
25
  :name,
@@ -18,10 +18,10 @@ class UffizziCore::Api::Cli::V1::Template::CreateForm < UffizziCore::Template
18
18
  :continuously_deploy,
19
19
  :service_name,
20
20
  :name,
21
- :healthcheck,
22
21
  { variables: [:name, :value],
23
22
  secret_variables: [:name, :value],
24
23
  volumes: [:source, :target, :type, :read_only],
24
+ healthcheck: [:test, :interval, :timeout, :retries, :start_period, :disable, { test: [] }],
25
25
  repo_attributes: [
26
26
  :namespace,
27
27
  :name,
@@ -53,7 +53,7 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
53
53
  end
54
54
 
55
55
  def healthcheck
56
- return {} if object.healthcheck.nil?
56
+ return {} if object.healthcheck.blank?
57
57
 
58
58
  command = object.healthcheck['test']
59
59
  new_command = if command.is_a?(Array)
@@ -63,6 +63,6 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
63
63
  command.split
64
64
  end
65
65
 
66
- object.healthcheck.merge(test: new_command)
66
+ object.healthcheck.merge('test' => new_command)
67
67
  end
68
68
  end
@@ -206,9 +206,11 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
206
206
 
207
207
  def build_docker_repo_attributes(image_data, credentials, scope, repo_type)
208
208
  credential = credentials.send(scope).first
209
- raise UffizziCore::ComposeFile::BuildError, I18n.t('compose.invalid_credential', value: scope) if credential.nil?
209
+ if UffizziCore::ComposeFile::ContainerService.image_available?(credential, image_data, scope)
210
+ return docker_builder(repo_type).build_attributes(image_data)
211
+ end
210
212
 
211
- docker_builder(repo_type).build_attributes(image_data)
213
+ raise UffizziCore::ComposeFile::BuildError, I18n.t('compose.unprocessable_image', value: scope)
212
214
  end
213
215
 
214
216
  def variables(variables_data, dependencies)
@@ -55,23 +55,32 @@ class UffizziCore::ComposeFile::ContainerService
55
55
 
56
56
  def credential_for_container(container, credentials)
57
57
  if UffizziCore::ComposeFile::ContainerService.azure?(container)
58
- detect_credential(credentials, :azure)
58
+ detect_credential(container, credentials, :azure)
59
59
  elsif UffizziCore::ComposeFile::ContainerService.docker_hub?(container)
60
- detect_credential(credentials, :docker_hub)
60
+ detect_credential(container, credentials, :docker_hub)
61
61
  elsif UffizziCore::ComposeFile::ContainerService.google?(container)
62
- detect_credential(credentials, :google)
62
+ detect_credential(container, ecredentials, :google)
63
63
  end
64
64
  end
65
65
 
66
- def detect_credential(credentials, type)
66
+ def detect_credential(container, credentials, type)
67
67
  credential = credentials.detect do |item|
68
68
  item.send("#{type}?")
69
69
  end
70
70
 
71
- error_message = "Invalid credential: #{type}"
72
- raise UffizziCore::ComposeFile::CredentialError.new(error_message) if credential.nil?
71
+ return credential if image_available?(credential, container[:image], type)
73
72
 
74
- credential
73
+ raise UffizziCore::ComposeFile::CredentialError.new(I18n.t('compose.unprocessable_image', value: type))
74
+ end
75
+
76
+ def image_available?(credential, image_data, type)
77
+ case type
78
+ when :docker_hub
79
+ UffizziCore::DockerHubService.image_available?(credential, image_data)
80
+ else
81
+ # TODO check image availability in other registry types
82
+ credential.present?
83
+ end
75
84
  end
76
85
  end
77
86
  end
@@ -11,10 +11,10 @@ class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
11
11
 
12
12
  {
13
13
  test: command,
14
- interval: parse_time(healthcheck_data['interval']),
15
- timeout: parse_time(healthcheck_data['timeout']),
14
+ interval: parse_time(:interval, healthcheck_data['interval']),
15
+ timeout: parse_time(:timeout, healthcheck_data['timeout']),
16
16
  retries: parse_retries(healthcheck_data['retries']),
17
- start_period: parse_time(healthcheck_data['start_period']),
17
+ start_period: parse_time(:start_period, healthcheck_data['start_period']),
18
18
  disable: parse_disable_option(healthcheck_data['disable'], command),
19
19
  }
20
20
  end
@@ -28,7 +28,11 @@ class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
28
28
  case command
29
29
  when Array
30
30
  start_command = command.first
31
- raise UffizziCore::ComposeFile::ParseError unless REQUIRED_START_COMMANDS.include?(start_command)
31
+
32
+ unless REQUIRED_START_COMMANDS.include?(start_command)
33
+ raise UffizziCore::ComposeFile::ParseError,
34
+ I18n.t('compose.required_start_commands', available_commands: REQUIRED_START_COMMANDS.join(', '))
35
+ end
32
36
 
33
37
  command
34
38
  when String
@@ -39,10 +43,22 @@ class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
39
43
  end
40
44
 
41
45
  def parse_retries(value)
42
- raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_integer', option: :retries) unless value.is_a?(Integer)
46
+ return if value.nil?
47
+
48
+ unless value.is_a?(Integer)
49
+ raise UffizziCore::ComposeFile::ParseError,
50
+ I18n.t('compose.invalid_retries', value: value)
51
+ end
52
+
53
+ value
43
54
  end
44
55
 
45
- def parse_time(value)
56
+ def parse_time(key, value)
57
+ return if value.nil?
58
+
59
+ error_message = I18n.t('compose.invalid_time_interval', key: key, value: value)
60
+ raise UffizziCore::ComposeFile::ParseError, error_message if value.is_a?(Integer)
61
+
46
62
  tokens = {
47
63
  's' => 1,
48
64
  'm' => 60,
@@ -58,7 +74,7 @@ class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
58
74
 
59
75
  acc
60
76
  rescue StandardError
61
- raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_time_interval')
77
+ raise UffizziCore::ComposeFile::ParseError, error_message
62
78
  end
63
79
  end
64
80
 
@@ -11,6 +11,16 @@ class UffizziCore::DockerHubService
11
11
  accounts_response.nil? ? [] : accounts_response.namespaces
12
12
  end
13
13
 
14
+ def image_available?(credential, image_data)
15
+ namespace = image_data[:namespace]
16
+ repo_name = image_data[:name]
17
+ client = UffizziCore::DockerHubClient.new(credential)
18
+ response = client.repository(namespace: namespace, image: repo_name)
19
+ return false if not_found?(response)
20
+
21
+ true
22
+ end
23
+
14
24
  def user_client(credential)
15
25
  return @client if @client&.credential&.username == credential.username
16
26
 
@@ -36,5 +46,9 @@ class UffizziCore::DockerHubService
36
46
  def public_docker_hub_client
37
47
  @public_docker_hub_client ||= UffizziCore::DockerHubClient.new
38
48
  end
49
+
50
+ def not_found?(response)
51
+ response.status == 404
52
+ end
39
53
  end
40
54
  end
@@ -17,7 +17,7 @@ en:
17
17
  no_services: Service services has neither an image nor a build context specified. At least one must be provided.
18
18
  no_ingress: Service ingress has not been defined.
19
19
  invalid_image_value: Invalid image value '%{value}'
20
- invalid_credential: Invalid credential '%{value}'
20
+ unprocessable_image: Invalid credential '%{value} or image does not exist'
21
21
  invalid_repo_type: Unsupported repo type
22
22
  repo_not_found: The specified repository doesn't exist '%{name}'
23
23
  ingress_port_not_specified: Ingress port not specified
@@ -56,8 +56,8 @@ en:
56
56
  project_secret_not_found: Project secret '%{secret}' not found
57
57
  continuous_preview_in_service_level: The option '%{option}' is not supported for service-level. Use 'x-uffizzi-continuous-preview' instead
58
58
  file_already_exists: A compose file already exists for this project. Run 'uffizzi compose update' to update this file or 'uffizzi compose rm' to remove it. For more options, see 'uffizzi compose --help'
59
- invalid_healthcheck_command: "Service '%{name}' defines an invalid healthcheck: when 'test' is a list the first item must be either NONE, CMD or CMD-SHELL"
60
- invalid_time_interval: The time interval should be in the following format '{hours}h{minutes}m{seconds}s'. At least one value must be present.
59
+ invalid_time_interval: "Invalid time interval: '%{key}:%{value}'. The time interval should be in the following format '{hours}h{minutes}m{seconds}s'. At least one value must be present."
60
+ invalid_retries: "Invalid retries value: 'retries:%{value}'. The value should be an integer."
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}'"
@@ -67,6 +67,7 @@ en:
67
67
  volume_type_not_supported: Volumes with type '%{type}' does not supported
68
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.
69
69
  invalid_volume_destination: Invalid volume specification '%{spec}' destination can't be '/'
70
+ required_start_commands: "When 'test' is a list the first item must be one of: '%{available_commands}'"
70
71
  secrets:
71
72
  duplicates_exists: Secret with key %{secrets} already exist.
72
73
  invalid_key_length: A secret key must be no longer than 256 characters.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UffizziCore
4
- VERSION = '1.0.0'
4
+ VERSION = '1.0.2'
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: 1.0.0
4
+ version: 1.0.2
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-31 00:00:00.000000000 Z
12
+ date: 2022-09-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aasm