uffizzi_core 2.0.19 → 2.0.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/app/clients/uffizzi_core/azure_registry_client.rb +9 -6
  3. data/app/clients/uffizzi_core/container_registry_request_decorator.rb +11 -0
  4. data/app/clients/uffizzi_core/docker_hub_client.rb +12 -9
  5. data/app/clients/uffizzi_core/docker_registry_client.rb +12 -8
  6. data/app/clients/uffizzi_core/github_container_registry_client.rb +17 -11
  7. data/app/clients/uffizzi_core/google_registry_client.rb +9 -6
  8. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers_controller.rb +8 -0
  9. data/app/errors/uffizzi_core/compose_file/build_error.rb +6 -1
  10. data/app/errors/uffizzi_core/compose_file/secrets_error.rb +6 -1
  11. data/app/errors/uffizzi_core/compose_file_error.rb +19 -0
  12. data/app/errors/uffizzi_core/container_registry_error.rb +25 -0
  13. data/app/forms/uffizzi_core/api/cli/v1/compose_file/check_credentials_form.rb +9 -4
  14. data/app/forms/uffizzi_core/api/cli/v1/compose_file/template_form.rb +12 -10
  15. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/containers_policy.rb +4 -0
  16. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +2 -1
  17. data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +3 -1
  18. data/app/services/uffizzi_core/compose_file/errors_service.rb +8 -0
  19. data/app/services/uffizzi_core/container_registry/azure_service.rb +1 -3
  20. data/app/services/uffizzi_core/container_registry/docker_hub_service.rb +5 -11
  21. data/app/services/uffizzi_core/container_registry/docker_registry_service.rb +2 -2
  22. data/app/services/uffizzi_core/container_registry/github_container_registry_service.rb +1 -9
  23. data/app/services/uffizzi_core/container_registry/google_service.rb +1 -3
  24. data/app/services/uffizzi_core/container_registry_service.rb +2 -0
  25. data/app/services/uffizzi_core/container_service.rb +28 -0
  26. data/config/locales/en.yml +8 -0
  27. data/config/routes.rb +1 -0
  28. data/lib/uffizzi_core/version.rb +1 -1
  29. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56cc9e09a80d239e143e024ca46b35a716ee35ae540543937b2d6bc6828b1cb4
4
- data.tar.gz: f45e872ca5bd8715929214c6837784f582b08e46a5abe1e4cc4ff91b2c400115
3
+ metadata.gz: 9c6052d327892d715fdae978c23f607e4f31ba2829f433bb60e67621da7ace14
4
+ data.tar.gz: c5ce343ecba716c0a92fd206983e126de77949235e2ff4f596557458952b203e
5
5
  SHA512:
6
- metadata.gz: 62a62bf2c4a78e33831cf675a7e4d258d40254018939c907aa3d859a5454f916061de63c92f75382471b81186209507580126a799b8b5fb90beb141bcbd4917d
7
- data.tar.gz: fb5dd99d8253c1f5c12624b511db0d3a1e672d87f15cfb6cf3f16fca2b3880e11a4a67fc32a431c0038141c6295123fa441259a69cd469aa40ef64511cf435b4
6
+ metadata.gz: b4a3168cc3c0c07688bd8fdc9db228f296d2ed79bcc19299414b35f8a108e0ff67049c0604ce1edb976ed0c88f334d0c6fd2146658321d1096086bea57c19037
7
+ data.tar.gz: 869d36425dad9eaac7eee8fecd86c7b56e8d3102af9a2e4249a8ff5af55a047e5fa6d9125fab0835fd13f568d1d322b83f7e900b01bfff0dde4b6024d2834b8d
@@ -25,18 +25,21 @@ class UffizziCore::AzureRegistryClient
25
25
  RequestResult.new(result: response.body)
26
26
  end
27
27
 
28
- def authentificated?
28
+ def authenticated?
29
29
  token.present?
30
30
  end
31
31
 
32
32
  private
33
33
 
34
34
  def build_connection(registry_url, username, password)
35
- Faraday.new(registry_url) do |conn|
36
- conn.request(:basic_auth, username, password)
37
- conn.request(:json)
38
- conn.response(:json)
39
- conn.adapter(Faraday.default_adapter)
35
+ connection = Faraday.new(registry_url) do |faraday|
36
+ faraday.request(:basic_auth, username, password)
37
+ faraday.request(:json)
38
+ faraday.response(:json)
39
+ faraday.response(:raise_error)
40
+ faraday.adapter(Faraday.default_adapter)
40
41
  end
42
+
43
+ connection.extend(UffizziCore::ContainerRegistryRequestDecorator)
41
44
  end
42
45
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::ContainerRegistryRequestDecorator
4
+ [:get, :post, :head].each do |method|
5
+ define_method(method) do |url, params_or_body = nil, headers = nil, &block|
6
+ super(url, params_or_body, headers, &block)
7
+ rescue Faraday::ClientError => e
8
+ raise UffizziCore::ContainerRegistryError.new(e.response)
9
+ end
10
+ end
11
+ end
@@ -10,10 +10,10 @@ class UffizziCore::DockerHubClient
10
10
  @credential = credential
11
11
  return unless credential
12
12
 
13
- @jwt = authentificate
13
+ @jwt = authenticate
14
14
  end
15
15
 
16
- def authentificate
16
+ def authenticate
17
17
  params = { username: credential.username, password: credential.password }
18
18
  url = "#{BASE_URL}/v2/users/login/"
19
19
  response = connection.post(url, params)
@@ -42,7 +42,7 @@ class UffizziCore::DockerHubClient
42
42
  end
43
43
 
44
44
  def private_images(account:, page: 1, per_page: 25)
45
- raise NotAuthorizedError if !authentificated? || account.empty?
45
+ raise NotAuthorizedError if !authenticated? || account.empty?
46
46
 
47
47
  url = BASE_URL + "/v2/repositories/#{account}/"
48
48
  params = { page_size: per_page, page: page }
@@ -53,7 +53,7 @@ class UffizziCore::DockerHubClient
53
53
  end
54
54
 
55
55
  def accounts
56
- raise NotAuthorizedError if !authentificated?
56
+ raise NotAuthorizedError if !authenticated?
57
57
 
58
58
  url = "#{BASE_URL}/v2/repositories/namespaces/"
59
59
  response = connection.get(url) do |request|
@@ -96,17 +96,20 @@ class UffizziCore::DockerHubClient
96
96
  RequestResult.new(result: response.body)
97
97
  end
98
98
 
99
- def authentificated?
99
+ def authenticated?
100
100
  jwt.present?
101
101
  end
102
102
 
103
103
  private
104
104
 
105
105
  def build_connection
106
- Faraday.new do |conn|
107
- conn.request(:json)
108
- conn.response(:json)
109
- conn.adapter(Faraday.default_adapter)
106
+ connection = Faraday.new do |faraday|
107
+ faraday.request(:json)
108
+ faraday.response(:json)
109
+ faraday.response(:raise_error)
110
+ faraday.adapter(Faraday.default_adapter)
110
111
  end
112
+
113
+ connection.extend(UffizziCore::ContainerRegistryRequestDecorator)
111
114
  end
112
115
  end
@@ -7,8 +7,9 @@ class UffizziCore::DockerRegistryClient
7
7
  end
8
8
 
9
9
  def authenticated?
10
- response = @connection.head('/v2/')
11
- response.status == 200
10
+ @connection.head('/v2/')
11
+
12
+ true
12
13
  end
13
14
 
14
15
  def manifests(image:, tag:, namespace: nil)
@@ -22,12 +23,15 @@ class UffizziCore::DockerRegistryClient
22
23
  private
23
24
 
24
25
  def build_connection(registry_url, username, password)
25
- Faraday.new(registry_url) do |conn|
26
- conn.request(:basic_auth, username, password) if username.present? && password.present?
27
- conn.request(:json)
28
- conn.response(:json)
29
- conn.response(:follow_redirects)
30
- conn.adapter(Faraday.default_adapter)
26
+ connection = Faraday.new(registry_url) do |faraday|
27
+ faraday.request(:basic_auth, username, password) if username.present? && password.present?
28
+ faraday.request(:json)
29
+ faraday.response(:json)
30
+ faraday.response(:follow_redirects)
31
+ faraday.response(:raise_error)
32
+ faraday.adapter(Faraday.default_adapter)
31
33
  end
34
+
35
+ connection.extend(UffizziCore::ContainerRegistryRequestDecorator)
32
36
  end
33
37
  end
@@ -19,7 +19,7 @@ class UffizziCore::GithubContainerRegistryClient
19
19
  RequestResult.new(result: response.body)
20
20
  end
21
21
 
22
- def authentificated?
22
+ def authenticated?
23
23
  token.present?
24
24
  end
25
25
 
@@ -33,20 +33,26 @@ class UffizziCore::GithubContainerRegistryClient
33
33
  private
34
34
 
35
35
  def connection
36
- Faraday.new(registry_url) do |conn|
37
- conn.request(:basic_auth, @username, @password)
38
- conn.request(:json)
39
- conn.response(:json)
40
- conn.adapter(Faraday.default_adapter)
36
+ connection = Faraday.new(registry_url) do |faraday|
37
+ faraday.request(:basic_auth, @username, @password)
38
+ faraday.request(:json)
39
+ faraday.response(:json)
40
+ faraday.response(:raise_error)
41
+ faraday.adapter(Faraday.default_adapter)
41
42
  end
43
+
44
+ connection.extend(UffizziCore::ContainerRegistryRequestDecorator)
42
45
  end
43
46
 
44
47
  def token_connection
45
- Faraday.new(registry_url) do |conn|
46
- conn.request(:authorization, 'Bearer', token)
47
- conn.request(:json)
48
- conn.response(:json)
49
- conn.adapter(Faraday.default_adapter)
48
+ connection = Faraday.new(registry_url) do |faraday|
49
+ faraday.request(:authorization, 'Bearer', token)
50
+ faraday.request(:json)
51
+ faraday.response(:json)
52
+ faraday.response(:raise_error)
53
+ faraday.adapter(Faraday.default_adapter)
50
54
  end
55
+
56
+ connection.extend(UffizziCore::ContainerRegistryRequestDecorator)
51
57
  end
52
58
  end
@@ -25,18 +25,21 @@ class UffizziCore::GoogleRegistryClient
25
25
  RequestResult.new(result: response.body)
26
26
  end
27
27
 
28
- def authentificated?
28
+ def authenticated?
29
29
  token.present?
30
30
  end
31
31
 
32
32
  private
33
33
 
34
34
  def build_connection(registry_url, username, password)
35
- Faraday.new(registry_url) do |conn|
36
- conn.request(:basic_auth, username, password)
37
- conn.request(:json)
38
- conn.response(:json)
39
- conn.adapter(Faraday.default_adapter)
35
+ connection = Faraday.new(registry_url) do |faraday|
36
+ faraday.request(:basic_auth, username, password)
37
+ faraday.request(:json)
38
+ faraday.response(:json)
39
+ faraday.response(:raise_error)
40
+ faraday.adapter(Faraday.default_adapter)
40
41
  end
42
+
43
+ connection.extend(UffizziCore::ContainerRegistryRequestDecorator)
41
44
  end
42
45
  end
@@ -21,4 +21,12 @@ class UffizziCore::Api::Cli::V1::Projects::Deployments::ContainersController <
21
21
 
22
22
  respond_with containers
23
23
  end
24
+
25
+ def k8s_container_description
26
+ deployment ||= resource_project.deployments.existed.find(params[:deployment_id])
27
+ container = deployment.containers.active.find_by!(service_name: params[:container_name])
28
+ last_state = UffizziCore::ContainerService.last_state(container)
29
+
30
+ render json: { last_state: last_state }
31
+ end
24
32
  end
@@ -1,4 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::BuildError < StandardError
3
+ class UffizziCore::ComposeFile::BuildError < UffizziCore::ComposeFileError
4
+ def initialize(message, extra_errors = {})
5
+ error_key = UffizziCore::ComposeFile::ErrorsService::TEMPLATE_BUILD_ERROR_KEY
6
+
7
+ super(message, error_key, extra_errors)
8
+ end
4
9
  end
@@ -1,4 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::ComposeFile::SecretsError < StandardError
3
+ class UffizziCore::ComposeFile::SecretsError < UffizziCore::ComposeFileError
4
+ def initialize(message, extra_errors = {})
5
+ error_key = UffizziCore::ComposeFile::ErrorsService::SECRETS_ERROR_KEY
6
+
7
+ super(message, error_key, extra_errors)
8
+ end
4
9
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ComposeFileError < StandardError
4
+ attr_reader :errors
5
+
6
+ def initialize(message, error_key = nil, extra_errors = {})
7
+ if [NilClass, String].exclude?(error_key.class)
8
+ raise StandardError.new("#{self.class} arg 'error_key' should be a #{String} or #{NilClass}")
9
+ end
10
+
11
+ unless extra_errors.is_a?(Hash)
12
+ raise StandardError.new("#{self.class} arg 'extra_errors' should be a #{Hash}")
13
+ end
14
+
15
+ @errors = error_key.nil? ? {} : { error_key => message.to_s }.merge(extra_errors)
16
+
17
+ super(message)
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ContainerRegistryError < StandardError
4
+ attr_reader :errors, :error_key
5
+
6
+ def initialize(response)
7
+ prepared_errors = prepare_errors(response[:body], response[:status])
8
+ @error_key = UffizziCore::ComposeFile::ErrorsService::DOCKER_REGISTRY_CONTAINER_ERROR_KEY
9
+ @errors = { @error_key => prepared_errors }
10
+
11
+ super(prepared_errors.to_json)
12
+ end
13
+
14
+ private
15
+
16
+ def prepare_errors(body, status)
17
+ parsed_body = JSON.parse!(body.to_s)
18
+
19
+ parsed_body.fetch('errors', parsed_body)
20
+ rescue JSON::ParserError, TypeError
21
+ msg = body.empty? ? I18n.t('registry.error', code: status) : body
22
+
23
+ { message: msg }
24
+ end
25
+ end
@@ -3,6 +3,8 @@
3
3
  class UffizziCore::Api::Cli::V1::ComposeFile::CheckCredentialsForm
4
4
  include UffizziCore::ApplicationFormWithoutActiveRecord
5
5
 
6
+ attr_reader :type
7
+
6
8
  attribute :compose_file
7
9
  attribute :credentials
8
10
 
@@ -16,13 +18,16 @@ class UffizziCore::Api::Cli::V1::ComposeFile::CheckCredentialsForm
16
18
  compose_data = UffizziCore::ComposeFileService.parse(compose_content, compose_payload)
17
19
 
18
20
  containers = compose_data[:containers]
19
- containers.map do |container|
21
+ containers.each do |container|
20
22
  container_registry_service = UffizziCore::ContainerRegistryService.init_by_container(container)
21
- credential = container_registry_service.credential(credentials)
22
- next credential if container_registry_service.image_available?(credentials)
23
+ @type = container_registry_service.type
24
+ next if container_registry_service.image_available?(credentials)
23
25
 
24
- raise UffizziCore::ComposeFile::CredentialError.new(I18n.t('compose.unprocessable_image', value: container_registry_service.type))
26
+ raise UffizziCore::ComposeFile::CredentialError.new(I18n.t('compose.unprocessable_image', value: type))
25
27
  end
28
+ rescue UffizziCore::ContainerRegistryError => e
29
+ errors.add(:credentials, I18n.t('compose.unprocessable_image', value: type))
30
+ errors.add(e.error_key, e.message)
26
31
  rescue UffizziCore::ComposeFile::CredentialError => e
27
32
  errors.add(:credentials, e.message)
28
33
  end
@@ -3,9 +3,6 @@
3
3
  class UffizziCore::Api::Cli::V1::ComposeFile::TemplateForm
4
4
  include UffizziCore::ApplicationFormWithoutActiveRecord
5
5
 
6
- SECRETS_ERROR_KEY = 'secret_variables'
7
- TEMPLATE_BUILD_ERROR_KEY = 'template_build_error'
8
-
9
6
  attribute :credentials
10
7
  attribute :project, UffizziCore::Project
11
8
  attribute :user, UffizziCore::User
@@ -34,13 +31,18 @@ class UffizziCore::Api::Cli::V1::ComposeFile::TemplateForm
34
31
  private
35
32
 
36
33
  def check_template_attributes
37
- case template_build_error
38
- when UffizziCore::ComposeFile::SecretsError
39
- errors.add(SECRETS_ERROR_KEY, template_build_error.message)
40
- when UffizziCore::ComposeFile::BuildError
41
- errors.add(TEMPLATE_BUILD_ERROR_KEY, template_build_error.message)
42
- when StandardError
43
- raise template_build_error
34
+ readable_errors = [
35
+ UffizziCore::ComposeFile::SecretsError,
36
+ UffizziCore::ComposeFile::BuildError,
37
+ UffizziCore::ContainerRegistryError,
38
+ ]
39
+
40
+ if readable_errors.include?(template_build_error.class)
41
+ template_build_error.errors.each { |k, v| errors.add(k, v) }
42
+
43
+ return
44
44
  end
45
+
46
+ raise template_build_error if template_build_error.is_a?(StandardError)
45
47
  end
46
48
  end
@@ -4,4 +4,8 @@ class UffizziCore::Api::Cli::V1::Projects::Deployments::ContainersPolicy < Uffiz
4
4
  def index?
5
5
  context.user_access_module.any_access_to_project?(context.user, context.project)
6
6
  end
7
+
8
+ def k8s_container_description?
9
+ context.user_access_module.any_access_to_project?(context.user, context.project)
10
+ end
7
11
  end
@@ -21,7 +21,8 @@ class UffizziCore::Api::Cli::V1::Projects::DeploymentSerializer::ContainerSerial
21
21
  :continuously_deploy,
22
22
  :receive_incoming_requests,
23
23
  :healthcheck,
24
- :volumes
24
+ :volumes,
25
+ :service_name
25
26
 
26
27
  def secret_variables
27
28
  return unless object.secret_variables.present?
@@ -79,7 +79,9 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
79
79
  return docker_repo_builder.build_attributes(image_data)
80
80
  end
81
81
 
82
- raise UffizziCore::ComposeFile::BuildError, I18n.t('compose.unprocessable_image', value: container_registry.type)
82
+ UffizziCore::ComposeFile::ErrorsService.raise_build_error!(container_registry.type)
83
+ rescue UffizziCore::ContainerRegistryError => e
84
+ UffizziCore::ComposeFile::ErrorsService.raise_build_error!(container_registry.type, e.errors)
83
85
  end
84
86
 
85
87
  def set_continuous_preview_attributes_to_repo(repo_attributes, global_data, container_data)
@@ -2,6 +2,9 @@
2
2
 
3
3
  class UffizziCore::ComposeFile::ErrorsService
4
4
  SECRETS_ERROR_KEY = 'secret_variables'
5
+ TEMPLATE_BUILD_ERROR_KEY = 'template_build_error'
6
+ DOCKER_REGISTRY_CONTAINER_ERROR_KEY = 'docker_registry_container_error'
7
+
5
8
  class << self
6
9
  def has_error?(compose_file, error_code)
7
10
  error = compose_file.payload.dig('errors', error_code)
@@ -42,5 +45,10 @@ class UffizziCore::ComposeFile::ErrorsService
42
45
 
43
46
  compose_file
44
47
  end
48
+
49
+ def raise_build_error!(type, extra_errors = {})
50
+ msg = I18n.t('compose.unprocessable_image', value: type)
51
+ raise UffizziCore::ComposeFile::BuildError.new(msg, extra_errors)
52
+ end
45
53
  end
46
54
  end
@@ -7,9 +7,7 @@ class UffizziCore::ContainerRegistry::AzureService
7
7
  end
8
8
 
9
9
  def credential_correct?(credential)
10
- client(credential).authentificated?
11
- rescue URI::InvalidURIError, Faraday::ConnectionFailed
12
- false
10
+ client(credential).authenticated?
13
11
  end
14
12
 
15
13
  private
@@ -14,9 +14,7 @@ class UffizziCore::ContainerRegistry::DockerHubService
14
14
  def image_available?(credential, image_data)
15
15
  namespace = image_data[:namespace]
16
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)
17
+ client(credential).repository(namespace: namespace, image: repo_name)
20
18
 
21
19
  true
22
20
  end
@@ -24,9 +22,9 @@ class UffizziCore::ContainerRegistry::DockerHubService
24
22
  def user_client(credential)
25
23
  return @client if @client&.credential&.username == credential.username
26
24
 
27
- @client = UffizziCore::DockerHubClient.new(credential)
25
+ @client = client(credential)
28
26
 
29
- unless @client.authentificated?
27
+ unless @client.authenticated?
30
28
  Rails.logger.warn("broken credentials, DockerHubService credential_id=#{credential.id}")
31
29
  credential.unauthorize! unless credential.unauthorized?
32
30
  end
@@ -35,14 +33,14 @@ class UffizziCore::ContainerRegistry::DockerHubService
35
33
  end
36
34
 
37
35
  def digest(credential, image, tag)
38
- docker_hub_client = UffizziCore::DockerHubClient.new(credential)
36
+ docker_hub_client = client(credential)
39
37
  token = docker_hub_client.get_token(image).result.token
40
38
  response = docker_hub_client.digest(image: image, tag: tag, token: token)
41
39
  response.headers['docker-content-digest']
42
40
  end
43
41
 
44
42
  def credential_correct?(credential)
45
- client(credential).authentificated?
43
+ client(credential).authenticated?
46
44
  end
47
45
 
48
46
  private
@@ -50,9 +48,5 @@ class UffizziCore::ContainerRegistry::DockerHubService
50
48
  def client(credential)
51
49
  UffizziCore::DockerHubClient.new(credential)
52
50
  end
53
-
54
- def not_found?(response)
55
- response.status == 404
56
- end
57
51
  end
58
52
  end
@@ -5,9 +5,9 @@ class UffizziCore::ContainerRegistry::DockerRegistryService
5
5
  def image_available?(credential, image_data)
6
6
  client_params = build_client_params(credential, image_data)
7
7
  client = UffizziCore::DockerRegistryClient.new(**client_params)
8
- response = client.manifests(namespace: image_data[:namespace], image: image_data[:name], tag: image_data[:tag])
8
+ client.manifests(namespace: image_data[:namespace], image: image_data[:name], tag: image_data[:tag])
9
9
 
10
- response.status < 400
10
+ true
11
11
  end
12
12
 
13
13
  def credential_correct?(credential)
@@ -7,15 +7,7 @@ class UffizziCore::ContainerRegistry::GithubContainerRegistryService
7
7
  end
8
8
 
9
9
  def credential_correct?(credential)
10
- client(credential).authentificated?
11
- rescue URI::InvalidURIError, Faraday::ConnectionFailed
12
- false
13
- end
14
-
15
- def access_token(credential)
16
- client(credential).token
17
- rescue URI::InvalidURIError, Faraday::ConnectionFailed
18
- false
10
+ client(credential).authenticated?
19
11
  end
20
12
 
21
13
  private
@@ -13,9 +13,7 @@ class UffizziCore::ContainerRegistry::GoogleService
13
13
  end
14
14
 
15
15
  def credential_correct?(credential)
16
- client(credential).authentificated?
17
- rescue URI::InvalidURIError, Faraday::ConnectionFailed
18
- false
16
+ client(credential).authenticated?
19
17
  end
20
18
 
21
19
  private
@@ -62,6 +62,8 @@ class UffizziCore::ContainerRegistryService
62
62
 
63
63
  def credential_correct?(credential)
64
64
  service.credential_correct?(credential)
65
+ rescue URI::InvalidURIError, Faraday::ConnectionFailed, UffizziCore::ContainerRegistryError
66
+ false
65
67
  end
66
68
 
67
69
  def image_data
@@ -38,5 +38,33 @@ class UffizziCore::ContainerService
38
38
 
39
39
  container_memory_request <= max_memory_limit
40
40
  end
41
+
42
+ def last_state(container)
43
+ pods = pods_by_container(container)
44
+ container_status = container_status(container, pods)
45
+ return {} if container_status.blank? || container_status&.dig('last_state')&.blank?
46
+
47
+ container_status['last_state'].map do |code, state|
48
+ {
49
+ code: code,
50
+ reason: state.reason,
51
+ exit_code: state.exit_code,
52
+ started_at: state.started_at,
53
+ finished_at: state.finished_at,
54
+ }
55
+ end.first
56
+ end
57
+
58
+ private
59
+
60
+ def container_status(container, pods)
61
+ pods
62
+ .flat_map { |pod| pod&.status&.container_statuses }
63
+ .detect { |cs| cs.name.include?(container.controller_name) }
64
+ end
65
+
66
+ def pods_by_container(container)
67
+ UffizziCore::ControllerService.fetch_pods(container.deployment)
68
+ end
41
69
  end
42
70
  end
@@ -10,6 +10,7 @@ en:
10
10
  invalid_compose_message: |
11
11
  :exclamation: **Preview failed: invalid compose**
12
12
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Uffizzi was unable to deploy a preview of this pull request because the compose file in this branch is invalid.
13
+
13
14
  compose:
14
15
  unsupported_file: Unsupported compose file
15
16
  invalid_file: 'Syntax error: %{err} at line %{line} column %{column}'
@@ -70,14 +71,18 @@ en:
70
71
  required_start_commands: "When 'test' is a list the first item must be one of: '%{available_commands}'"
71
72
  volumes_should_be_array: Volumes '%{volumes}' should be an arra
72
73
  healthcheck_missing_required_option: "One of these options is required: %{required_options}"
74
+
73
75
  secrets:
74
76
  duplicates_exists: Secret with key %{secrets} already exist.
75
77
  invalid_key_length: A secret key must be no longer than 256 characters.
78
+
76
79
  deployment:
77
80
  invalid_state: Preview with ID deployment-%{id} %{state}
81
+
78
82
  session:
79
83
  unsupported_login_type: This type of login is not supported
80
84
  unauthorized: Unauthorized
85
+
81
86
  enumerize:
82
87
  credential:
83
88
  type:
@@ -87,3 +92,6 @@ en:
87
92
  "UffizziCore::Credential::Azure": "Azure"
88
93
  "UffizziCore::Credential::Google": "Google"
89
94
  "UffizziCore::Credential::Amazon": "Amazon"
95
+
96
+ registry:
97
+ error: Container registry returned a %{code} error
data/config/routes.rb CHANGED
@@ -16,6 +16,7 @@ UffizziCore::Engine.routes.draw do
16
16
  resources :activity_items, only: ['index']
17
17
  resources :events, only: ['index']
18
18
  resources :containers, only: ['index'], param: :name do
19
+ get :k8s_container_description
19
20
  scope module: :containers do
20
21
  resources :logs, only: ['index']
21
22
  resources :builds, only: [] do
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UffizziCore
4
- VERSION = '2.0.19'
4
+ VERSION = '2.0.20'
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.0.19
4
+ version: 2.0.20
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-12-29 00:00:00.000000000 Z
12
+ date: 2023-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aasm
@@ -732,6 +732,7 @@ files:
732
732
  - app/clients/uffizzi_core/amazon_registry_client.rb
733
733
  - app/clients/uffizzi_core/azure_registry_client.rb
734
734
  - app/clients/uffizzi_core/azure_registry_client/request_result.rb
735
+ - app/clients/uffizzi_core/container_registry_request_decorator.rb
735
736
  - app/clients/uffizzi_core/controller_client.rb
736
737
  - app/clients/uffizzi_core/controller_client/request_result.rb
737
738
  - app/clients/uffizzi_core/docker_hub_client.rb
@@ -774,6 +775,8 @@ files:
774
775
  - app/errors/uffizzi_core/compose_file/credential_error.rb
775
776
  - app/errors/uffizzi_core/compose_file/parse_error.rb
776
777
  - app/errors/uffizzi_core/compose_file/secrets_error.rb
778
+ - app/errors/uffizzi_core/compose_file_error.rb
779
+ - app/errors/uffizzi_core/container_registry_error.rb
777
780
  - app/errors/uffizzi_core/deployment/image_pull_error.rb
778
781
  - app/errors/uffizzi_core/deployment/labels_not_found_error.rb
779
782
  - app/errors/uffizzi_core/deployment_not_found_error.rb