uffizzi_core 2.0.18 → 2.0.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/clients/uffizzi_core/azure_registry_client.rb +9 -6
- data/app/clients/uffizzi_core/container_registry_request_decorator.rb +11 -0
- data/app/clients/uffizzi_core/docker_hub_client.rb +12 -9
- data/app/clients/uffizzi_core/docker_registry_client.rb +12 -8
- data/app/clients/uffizzi_core/github_container_registry_client.rb +17 -11
- data/app/clients/uffizzi_core/google_registry_client.rb +9 -6
- data/app/controller_modules/uffizzi_core/api/cli/v1/projects/deployments_controller_module.rb +5 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers_controller.rb +8 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments_controller.rb +3 -0
- data/app/errors/uffizzi_core/compose_file/build_error.rb +6 -1
- data/app/errors/uffizzi_core/compose_file/secrets_error.rb +6 -1
- data/app/errors/uffizzi_core/compose_file_error.rb +19 -0
- data/app/errors/uffizzi_core/container_registry_error.rb +25 -0
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/check_credentials_form.rb +9 -4
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/template_form.rb +12 -10
- data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/containers_policy.rb +4 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +2 -1
- data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +3 -1
- data/app/services/uffizzi_core/compose_file/errors_service.rb +8 -0
- data/app/services/uffizzi_core/container_registry/azure_service.rb +1 -3
- data/app/services/uffizzi_core/container_registry/docker_hub_service.rb +5 -11
- data/app/services/uffizzi_core/container_registry/docker_registry_service.rb +2 -2
- data/app/services/uffizzi_core/container_registry/github_container_registry_service.rb +1 -9
- data/app/services/uffizzi_core/container_registry/google_service.rb +1 -3
- data/app/services/uffizzi_core/container_registry_service.rb +2 -0
- data/app/services/uffizzi_core/container_service.rb +28 -0
- data/config/locales/en.yml +8 -0
- data/config/routes.rb +1 -0
- data/lib/uffizzi_core/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c6052d327892d715fdae978c23f607e4f31ba2829f433bb60e67621da7ace14
|
4
|
+
data.tar.gz: c5ce343ecba716c0a92fd206983e126de77949235e2ff4f596557458952b203e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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 |
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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 =
|
13
|
+
@jwt = authenticate
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
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 !
|
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 !
|
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
|
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 |
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
11
|
-
|
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 |
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
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 |
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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 |
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
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 |
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
@@ -3,7 +3,10 @@
|
|
3
3
|
# @resource Deployment
|
4
4
|
|
5
5
|
class UffizziCore::Api::Cli::V1::Projects::DeploymentsController < UffizziCore::Api::Cli::V1::Projects::ApplicationController
|
6
|
+
include UffizziCore::Api::Cli::V1::Projects::DeploymentsControllerModule
|
7
|
+
|
6
8
|
before_action :authorize_uffizzi_core_api_cli_v1_projects_deployments
|
9
|
+
before_action :check_account_state, only: [:create, :update]
|
7
10
|
|
8
11
|
# Get a list of active deployements for a project
|
9
12
|
#
|
@@ -1,4 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class UffizziCore::ComposeFile::BuildError <
|
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 <
|
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.
|
21
|
+
containers.each do |container|
|
20
22
|
container_registry_service = UffizziCore::ContainerRegistryService.init_by_container(container)
|
21
|
-
|
22
|
-
next
|
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:
|
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb
CHANGED
@@ -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
|
-
|
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
|
@@ -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
|
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 =
|
25
|
+
@client = client(credential)
|
28
26
|
|
29
|
-
unless @client.
|
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 =
|
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).
|
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
|
-
|
8
|
+
client.manifests(namespace: image_data[:namespace], image: image_data[:name], tag: image_data[:tag])
|
9
9
|
|
10
|
-
|
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).
|
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).
|
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
|
data/config/locales/en.yml
CHANGED
@@ -10,6 +10,7 @@ en:
|
|
10
10
|
invalid_compose_message: |
|
11
11
|
:exclamation: **Preview failed: invalid compose**
|
12
12
|
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
|
data/lib/uffizzi_core/version.rb
CHANGED
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.
|
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:
|
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
|
@@ -747,6 +748,7 @@ files:
|
|
747
748
|
- app/contexts/uffizzi_core/base_context.rb
|
748
749
|
- app/contexts/uffizzi_core/project_context.rb
|
749
750
|
- app/contexts/uffizzi_core/webhooks_context.rb
|
751
|
+
- app/controller_modules/uffizzi_core/api/cli/v1/projects/deployments_controller_module.rb
|
750
752
|
- app/controllers/concerns/uffizzi_core/auth_management.rb
|
751
753
|
- app/controllers/concerns/uffizzi_core/authorization_concern.rb
|
752
754
|
- app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb
|
@@ -773,6 +775,8 @@ files:
|
|
773
775
|
- app/errors/uffizzi_core/compose_file/credential_error.rb
|
774
776
|
- app/errors/uffizzi_core/compose_file/parse_error.rb
|
775
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
|
776
780
|
- app/errors/uffizzi_core/deployment/image_pull_error.rb
|
777
781
|
- app/errors/uffizzi_core/deployment/labels_not_found_error.rb
|
778
782
|
- app/errors/uffizzi_core/deployment_not_found_error.rb
|