uffizzi_core 1.0.0 → 1.0.2

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: 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