uffizzi_core 2.1.29 → 2.2.0
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/controller_client.rb +40 -23
- data/app/controller_modules/uffizzi_core/api/cli/v1/projects/clusters_controller_module.rb +9 -0
- data/app/controllers/concerns/uffizzi_core/auth_management.rb +17 -1
- data/app/controllers/uffizzi_core/api/cli/v1/accounts/projects_controller.rb +7 -1
- data/app/controllers/uffizzi_core/api/cli/v1/accounts_controller.rb +45 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/clusters_controller.rb +46 -0
- data/app/forms/uffizzi_core/api/cli/v1/cluster/create_form.rb +19 -0
- data/app/jobs/uffizzi_core/cluster/delete_job.rb +12 -0
- data/app/jobs/uffizzi_core/cluster/deploy_job.rb +11 -0
- data/app/jobs/uffizzi_core/cluster/manage_deploying_job.rb +11 -0
- data/app/jobs/uffizzi_core/config_file/apply_job.rb +1 -1
- data/app/jobs/uffizzi_core/deployment/create_credential_job.rb +1 -1
- data/app/jobs/uffizzi_core/deployment/create_job.rb +1 -1
- data/app/jobs/uffizzi_core/deployment/delete_job.rb +2 -1
- data/app/jobs/uffizzi_core/deployment/deploy_containers_job.rb +1 -1
- data/app/jobs/uffizzi_core/deployment/update_credential_job.rb +1 -1
- data/app/lib/uffizzi_core/concerns/models/account.rb +1 -0
- data/app/lib/uffizzi_core/concerns/models/cluster.rb +54 -0
- data/app/lib/uffizzi_core/concerns/models/deployment.rb +4 -0
- data/app/lib/uffizzi_core/concerns/models/project.rb +1 -0
- data/app/lib/uffizzi_core/concerns/models/user.rb +1 -0
- data/app/models/uffizzi_core/cluster.rb +5 -0
- data/app/policies/uffizzi_core/api/cli/v1/accounts/projects_policy.rb +4 -0
- data/app/policies/uffizzi_core/api/cli/v1/accounts_policy.rb +11 -0
- data/app/policies/uffizzi_core/api/cli/v1/projects/clusters_policy.rb +19 -0
- data/app/repositories/uffizzi_core/account_repo.rb +1 -0
- data/app/repositories/uffizzi_core/cluster_repo.rb +10 -0
- data/app/serializers/uffizzi_core/api/cli/v1/account_serializer.rb +9 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/cluster_serializer.rb +7 -0
- data/app/serializers/uffizzi_core/controller/create_cluster/cluster_serializer.rb +9 -0
- data/app/services/uffizzi_core/cluster_service.rb +44 -0
- data/app/services/uffizzi_core/controller_service.rb +43 -21
- data/app/services/uffizzi_core/logs_service.rb +1 -1
- data/config/routes.rb +5 -2
- data/db/migrate/20230613101901_create_clusters.rb +19 -0
- data/lib/uffizzi_core/version.rb +1 -1
- data/lib/uffizzi_core.rb +1 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3857b5cc3f90f134b4ce7275290e460c4abf7868dcdc8d3940390efbab73fc9
|
4
|
+
data.tar.gz: 99d1c61e2af05d005a2c30314bf726ed2f68442c8cafaf1c036fc5294294d286
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9437c1c50d81bd7e6de3419ae81ef1d4035204b1e153249ae2a233918faf36e9267f6b58b200a73a77b335f5d03f4c2f7b1aebf39d7ed08e765b31941663da3d
|
7
|
+
data.tar.gz: 574c4e039f9f5a6ad4204b696ba6778eeb5ed88d729a5cda724b9d3a20e790f01547cf4b16c3a88bdd105da388bcd2c99e6e00194a8210d5c407845055bc1d93
|
@@ -1,28 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class UffizziCore::ControllerClient
|
4
|
+
class ConnectionError < StandardError; end
|
5
|
+
|
4
6
|
attr_accessor :connection
|
5
7
|
|
6
|
-
def initialize
|
7
|
-
@connection = build_connection
|
8
|
+
def initialize(connection_settings)
|
9
|
+
@connection = build_connection(connection_settings)
|
8
10
|
end
|
9
11
|
|
10
12
|
def apply_config_file(deployment_id:, config_file_id:, body:)
|
11
13
|
connection.post("/deployments/#{deployment_id}/config_files/#{config_file_id}", body)
|
12
14
|
end
|
13
15
|
|
14
|
-
def deployment(deployment_id:)
|
15
|
-
get("/deployments/#{deployment_id}")
|
16
|
-
end
|
17
|
-
|
18
|
-
def create_deployment(deployment_id:, body:)
|
19
|
-
connection.post("/deployments/#{deployment_id}", body)
|
20
|
-
end
|
21
|
-
|
22
|
-
def delete_deployment(deployment_id:)
|
23
|
-
connection.delete("/deployments/#{deployment_id}")
|
24
|
-
end
|
25
|
-
|
26
16
|
def deployment_containers(deployment_id:)
|
27
17
|
get("/deployments/#{deployment_id}/containers")
|
28
18
|
end
|
@@ -68,34 +58,61 @@ class UffizziCore::ControllerClient
|
|
68
58
|
get('/deployments/usage_metrics/containers', query_params)
|
69
59
|
end
|
70
60
|
|
61
|
+
def create_namespace(body:)
|
62
|
+
post('/namespaces', body)
|
63
|
+
end
|
64
|
+
|
65
|
+
def namespace(namespace:)
|
66
|
+
get("/namespaces/#{namespace}")
|
67
|
+
end
|
68
|
+
|
69
|
+
def delete_namespace(namespace:)
|
70
|
+
connection.delete("/namespaces/#{namespace}")
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_cluster(namespace:, body:)
|
74
|
+
post("/namespaces/#{namespace}/cluster", body)
|
75
|
+
end
|
76
|
+
|
77
|
+
def show_cluster(namespace:, name:)
|
78
|
+
get("/namespaces/#{namespace}/cluster/#{name}")
|
79
|
+
end
|
80
|
+
|
71
81
|
private
|
72
82
|
|
73
83
|
def get(url, params = {})
|
74
|
-
|
84
|
+
make_request(:get, url, params)
|
85
|
+
end
|
86
|
+
|
87
|
+
def post(url, params = {})
|
88
|
+
make_request(:post, url, params)
|
89
|
+
end
|
90
|
+
|
91
|
+
def make_request(method, url, params)
|
92
|
+
response = connection.send(method, url, params)
|
75
93
|
body = response.body
|
76
94
|
underscored_body = UffizziCore::Converters.deep_underscore_keys(body)
|
77
95
|
|
78
96
|
RequestResult.quiet.new(code: response.status, result: underscored_body)
|
97
|
+
rescue Faraday::ServerError
|
98
|
+
raise ConnectionError
|
79
99
|
end
|
80
100
|
|
81
|
-
def build_connection
|
82
|
-
|
83
|
-
login = controller.login
|
84
|
-
password = controller.password
|
85
|
-
url = controller.url
|
86
|
-
connection = controller.connection
|
101
|
+
def build_connection(settings)
|
102
|
+
connection = settings.connection
|
87
103
|
handled_exceptions = Faraday::Request::Retry::DEFAULT_EXCEPTIONS + [Faraday::ConnectionFailed]
|
88
104
|
|
89
|
-
Faraday.new(url) do |conn|
|
105
|
+
Faraday.new(settings.url) do |conn|
|
90
106
|
conn.options.timeout = connection.timeout
|
91
107
|
conn.options.open_timeout = connection.open_timeout
|
92
|
-
conn.request(:basic_auth, login, password)
|
108
|
+
conn.request(:basic_auth, settings.login, settings.password)
|
93
109
|
conn.request(:json)
|
94
110
|
conn.request(:retry,
|
95
111
|
max: connection.retires_count,
|
96
112
|
interval: connection.next_retry_timeout_seconds,
|
97
113
|
exceptions: handled_exceptions)
|
98
114
|
conn.response(:json)
|
115
|
+
conn.response(:raise_error)
|
99
116
|
conn.adapter(Faraday.default_adapter)
|
100
117
|
end
|
101
118
|
end
|
@@ -14,7 +14,23 @@ module UffizziCore::AuthManagement
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def current_user
|
17
|
-
@current_user ||= UffizziCore::User.find_by(id:
|
17
|
+
@current_user ||= UffizziCore::User.find_by(id: current_user_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
def auth_token
|
21
|
+
header = request.headers['Authorization']
|
22
|
+
header&.split(' ')&.last
|
23
|
+
end
|
24
|
+
|
25
|
+
def current_user_id
|
26
|
+
return session[:user_id] if session[:user_id].present?
|
27
|
+
return unless auth_token.present?
|
28
|
+
|
29
|
+
decoded_token = UffizziCore::TokenService.decode(auth_token)
|
30
|
+
return unless decoded_token
|
31
|
+
return if decoded_token.first['expires_at'] < DateTime.now
|
32
|
+
|
33
|
+
decoded_token.first['user_id']
|
18
34
|
end
|
19
35
|
|
20
36
|
def authenticate_request!
|
@@ -5,6 +5,12 @@
|
|
5
5
|
class UffizziCore::Api::Cli::V1::Accounts::ProjectsController < UffizziCore::Api::Cli::V1::Accounts::ApplicationController
|
6
6
|
before_action :authorize_uffizzi_core_api_cli_v1_accounts_projects
|
7
7
|
|
8
|
+
def index
|
9
|
+
projects = resource_account.projects.active
|
10
|
+
|
11
|
+
respond_with projects, each_serializer: UffizziCore::Api::Cli::V1::ShortProjectSerializer
|
12
|
+
end
|
13
|
+
|
8
14
|
# Create a project
|
9
15
|
#
|
10
16
|
# @path [POST] /api/cli/v1/accounts/{account_id}/projects
|
@@ -17,7 +23,7 @@ class UffizziCore::Api::Cli::V1::Accounts::ProjectsController < UffizziCore::Api
|
|
17
23
|
|
18
24
|
def create
|
19
25
|
project_form = UffizziCore::Api::Cli::V1::Project::CreateForm.new(project_params)
|
20
|
-
project_form.account =
|
26
|
+
project_form.account = resource_account
|
21
27
|
UffizziCore::ProjectService.add_users_to_project!(project_form, project_form.account) if project_form.save
|
22
28
|
|
23
29
|
respond_with project_form
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @resource Project
|
4
|
+
|
5
|
+
class UffizziCore::Api::Cli::V1::AccountsController < UffizziCore::Api::Cli::V1::ApplicationController
|
6
|
+
before_action :authorize_uffizzi_core_api_cli_v1_accounts
|
7
|
+
|
8
|
+
# Get accounts of current user
|
9
|
+
#
|
10
|
+
# @path [GET] /api/cli/v1/accounts
|
11
|
+
#
|
12
|
+
# @response [object<accounts: Array<object<id: integer, name: string>> >] 200 OK
|
13
|
+
# @response 401 Not authorized
|
14
|
+
def index
|
15
|
+
accounts = current_user.accounts.order(name: :desc)
|
16
|
+
|
17
|
+
respond_with accounts
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get account by name
|
21
|
+
#
|
22
|
+
# @path [GET] /api/cli/v1/accounts/{name}
|
23
|
+
#
|
24
|
+
# @response [object<account: <object<id: integer, name: string, projects: Array<object<id: integer, slug: string>>>> >] 200 OK
|
25
|
+
# @response 401 Not authorized
|
26
|
+
def show
|
27
|
+
respond_with resource_account
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def policy_context
|
33
|
+
account = resource_account || current_user.default_account
|
34
|
+
|
35
|
+
UffizziCore::AccountContext.new(current_user, user_access_module, account, params)
|
36
|
+
end
|
37
|
+
|
38
|
+
def resource_account
|
39
|
+
@resource_account ||= if params[:name]
|
40
|
+
current_user.accounts.find_by!(name: params[:name])
|
41
|
+
else
|
42
|
+
current_user.default_account
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::Api::Cli::V1::Projects::ClustersController < UffizziCore::Api::Cli::V1::Projects::ApplicationController
|
4
|
+
include UffizziCore::Api::Cli::V1::Projects::ClustersControllerModule
|
5
|
+
|
6
|
+
before_action :authorize_uffizzi_core_api_cli_v1_projects_clusters
|
7
|
+
before_action :stop_if_deployment_forbidden, only: [:create]
|
8
|
+
after_action :update_show_trial_quota_exceeded_warning, only: [:create, :destroy]
|
9
|
+
|
10
|
+
def index
|
11
|
+
clusters = resource_project.clusters.enabled
|
12
|
+
|
13
|
+
respond_with clusters
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
cluster_form = UffizziCore::Api::Cli::V1::Cluster::CreateForm.new(cluster_params)
|
18
|
+
cluster_form.project = resource_project
|
19
|
+
cluster_form.deployed_by = current_user
|
20
|
+
return respond_with cluster_form unless cluster_form.save
|
21
|
+
|
22
|
+
UffizziCore::ClusterService.start_deploy(cluster_form)
|
23
|
+
|
24
|
+
respond_with cluster_form
|
25
|
+
end
|
26
|
+
|
27
|
+
def show
|
28
|
+
respond_with resource_cluster
|
29
|
+
end
|
30
|
+
|
31
|
+
def destroy
|
32
|
+
resource_cluster.disable!
|
33
|
+
|
34
|
+
head(:no_content)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def resource_cluster
|
40
|
+
@resource_cluster ||= resource_project.clusters.enabled.find_by!(name: params[:name])
|
41
|
+
end
|
42
|
+
|
43
|
+
def cluster_params
|
44
|
+
params.require(:cluster)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::Api::Cli::V1::Cluster::CreateForm < UffizziCore::Cluster
|
4
|
+
include UffizziCore::ApplicationForm
|
5
|
+
|
6
|
+
permit :name, :manifest
|
7
|
+
|
8
|
+
validate :check_manifest, if: -> { manifest.present? }
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def check_manifest
|
13
|
+
YAML.load_stream(manifest)
|
14
|
+
rescue Psych::SyntaxError => e
|
15
|
+
err = [e.problem, e.context].compact.join(' ')
|
16
|
+
|
17
|
+
errors.add(:manifest, err)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::Cluster::DeleteJob < UffizziCore::ApplicationJob
|
4
|
+
sidekiq_options queue: :deployments, retry: 5
|
5
|
+
|
6
|
+
def perform(id)
|
7
|
+
Rails.logger.info("DEPLOYMENT_PROCESS cluster_id=#{id} DeleteJob")
|
8
|
+
|
9
|
+
cluster = UffizziCore::Cluster.find(id)
|
10
|
+
UffizziCore::ControllerService.delete_namespace(cluster)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::Cluster::DeployJob < UffizziCore::ApplicationJob
|
4
|
+
sidekiq_options queue: :deployments, retry: 5
|
5
|
+
|
6
|
+
def perform(id)
|
7
|
+
cluster = UffizziCore::Cluster.find(id)
|
8
|
+
|
9
|
+
UffizziCore::ClusterService.deploy_cluster(cluster)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::Cluster::ManageDeployingJob < UffizziCore::ApplicationJob
|
4
|
+
sidekiq_options queue: :deployments, retry: 5
|
5
|
+
|
6
|
+
def perform(id, try = 1)
|
7
|
+
cluster = UffizziCore::Cluster.find(id)
|
8
|
+
|
9
|
+
UffizziCore::ClusterService.manage_deploying(cluster, try)
|
10
|
+
end
|
11
|
+
end
|
@@ -28,7 +28,7 @@ class UffizziCore::ConfigFile::ApplyJob < UffizziCore::ApplicationJob
|
|
28
28
|
return
|
29
29
|
end
|
30
30
|
|
31
|
-
unless UffizziCore::ControllerService.
|
31
|
+
unless UffizziCore::ControllerService.namespace_exists?(deployment)
|
32
32
|
raise UffizziCore::DeploymentNotFoundError,
|
33
33
|
deployment_id
|
34
34
|
end
|
@@ -29,7 +29,7 @@ class UffizziCore::Deployment::CreateCredentialJob < UffizziCore::ApplicationJob
|
|
29
29
|
return
|
30
30
|
end
|
31
31
|
|
32
|
-
unless UffizziCore::ControllerService.
|
32
|
+
unless UffizziCore::ControllerService.namespace_exists?(deployment)
|
33
33
|
raise UffizziCore::DeploymentNotFoundError,
|
34
34
|
deployment_id
|
35
35
|
end
|
@@ -8,7 +8,7 @@ class UffizziCore::Deployment::CreateJob < UffizziCore::ApplicationJob
|
|
8
8
|
|
9
9
|
deployment = UffizziCore::Deployment.find(id)
|
10
10
|
|
11
|
-
UffizziCore::ControllerService.
|
11
|
+
UffizziCore::ControllerService.create_namespace(deployment)
|
12
12
|
|
13
13
|
UffizziCore::Deployment::CreateCredentialsJob.perform_async(deployment.id)
|
14
14
|
end
|
@@ -6,6 +6,7 @@ class UffizziCore::Deployment::DeleteJob < UffizziCore::ApplicationJob
|
|
6
6
|
def perform(id)
|
7
7
|
Rails.logger.info("DEPLOYMENT_PROCESS deployment_id=#{id} DeleteJob")
|
8
8
|
|
9
|
-
UffizziCore::
|
9
|
+
deployment = UffizziCore::Deployment.find(id)
|
10
|
+
UffizziCore::ControllerService.delete_namespace(deployment)
|
10
11
|
end
|
11
12
|
end
|
@@ -27,7 +27,7 @@ class UffizziCore::Deployment::DeployContainersJob < UffizziCore::ApplicationJob
|
|
27
27
|
return
|
28
28
|
end
|
29
29
|
|
30
|
-
raise UffizziCore::DeploymentNotFoundError, id unless UffizziCore::ControllerService.
|
30
|
+
raise UffizziCore::DeploymentNotFoundError, id unless UffizziCore::ControllerService.namespace_exists?(deployment)
|
31
31
|
|
32
32
|
UffizziCore::DeploymentService.deploy_containers(deployment, repeated)
|
33
33
|
end
|
@@ -29,7 +29,7 @@ class UffizziCore::Deployment::UpdateCredentialJob < UffizziCore::ApplicationJob
|
|
29
29
|
return
|
30
30
|
end
|
31
31
|
|
32
|
-
unless UffizziCore::ControllerService.
|
32
|
+
unless UffizziCore::ControllerService.namespace_exists?(deployment)
|
33
33
|
raise UffizziCore::DeploymentNotFoundError,
|
34
34
|
deployment_id
|
35
35
|
end
|
@@ -23,6 +23,7 @@ module UffizziCore::Concerns::Models::Account
|
|
23
23
|
has_many :projects, dependent: :destroy
|
24
24
|
has_many :deployments, through: :projects
|
25
25
|
has_many :payments, dependent: :destroy
|
26
|
+
has_many :clusters, through: :projects
|
26
27
|
|
27
28
|
aasm(:sso_state) do
|
28
29
|
state :connection_not_configured, initial: true
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UffizziCore::Concerns::Models::Cluster
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include UffizziCore::ClusterRepo
|
6
|
+
|
7
|
+
included do
|
8
|
+
include AASM
|
9
|
+
|
10
|
+
self.table_name = UffizziCore.table_names[:clusters]
|
11
|
+
|
12
|
+
belongs_to :project, class_name: UffizziCore::Project.name
|
13
|
+
belongs_to :deployed_by, class_name: UffizziCore::User.name, foreign_key: :deployed_by_id, optional: true
|
14
|
+
validates_uniqueness_of :name, conditions: -> { enabled }, scope: :project_id
|
15
|
+
validates :name, presence: true, format: { with: /\A[a-zA-Z0-9-]*\z/ }
|
16
|
+
|
17
|
+
aasm(:state) do
|
18
|
+
state :deploying_namespace, initial: true
|
19
|
+
state :failed_deploy_namespace
|
20
|
+
state :deploying
|
21
|
+
state :deployed
|
22
|
+
state :failed
|
23
|
+
state :disabled
|
24
|
+
|
25
|
+
event :start_deploying do
|
26
|
+
transitions from: [:deploying_namespace], to: :deploying
|
27
|
+
end
|
28
|
+
|
29
|
+
event :fail_deploy_namespace do
|
30
|
+
transitions from: [:deploying_namespace], to: :failed_deploy_namespace
|
31
|
+
end
|
32
|
+
|
33
|
+
event :finish_deploy do
|
34
|
+
transitions from: [:deploying], to: :deployed
|
35
|
+
end
|
36
|
+
|
37
|
+
event :fail do
|
38
|
+
transitions from: [:deploying], to: :failed
|
39
|
+
end
|
40
|
+
|
41
|
+
event :disable, after: :after_disable do
|
42
|
+
transitions from: [:failed_deploy_namespace, :deploying, :deployed, :failed], to: :disabled
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def after_disable
|
47
|
+
UffizziCore::Cluster::DeleteJob.perform_async(id)
|
48
|
+
end
|
49
|
+
|
50
|
+
def namespace
|
51
|
+
"cluster-#{id}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -22,6 +22,7 @@ module UffizziCore::Concerns::Models::Project
|
|
22
22
|
has_many :compose_files, dependent: :destroy
|
23
23
|
has_many :secrets, dependent: :destroy, as: :resource
|
24
24
|
has_many :host_volume_files, dependent: :destroy
|
25
|
+
has_many :clusters, dependent: :destroy
|
25
26
|
|
26
27
|
validates :name, presence: true, uniqueness: { scope: :account, message: 'Name already exists' }
|
27
28
|
validates :slug, presence: true, uniqueness: { message: 'Project slug already taken' }
|
@@ -20,6 +20,7 @@ module UffizziCore::Concerns::Models::User
|
|
20
20
|
has_many :user_projects, dependent: :destroy
|
21
21
|
has_many :projects, through: :user_projects
|
22
22
|
has_many :deployments, class_name: UffizziCore::Deployment.name, foreign_key: :deployed_by_id, dependent: :nullify
|
23
|
+
has_many :clusters, foreign_key: :deployed_by_id
|
23
24
|
|
24
25
|
has_one_attached :avatar
|
25
26
|
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class UffizziCore::Api::Cli::V1::Accounts::ProjectsPolicy < UffizziCore::ApplicationPolicy
|
4
|
+
def index?
|
5
|
+
context.user_access_module.any_access_to_account?(context.user, context.account)
|
6
|
+
end
|
7
|
+
|
4
8
|
def create?
|
5
9
|
context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
|
6
10
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::Api::Cli::V1::AccountsPolicy < UffizziCore::ApplicationPolicy
|
4
|
+
def index?
|
5
|
+
context.user.present?
|
6
|
+
end
|
7
|
+
|
8
|
+
def show?
|
9
|
+
context.user_access_module.any_access_to_account?(context.user, context.account)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::Api::Cli::V1::Projects::ClustersPolicy < UffizziCore::ApplicationPolicy
|
4
|
+
def index?
|
5
|
+
context.user_access_module.any_access_to_project?(context.user, context.project)
|
6
|
+
end
|
7
|
+
|
8
|
+
def show?
|
9
|
+
context.user_access_module.any_access_to_project?(context.user, context.project)
|
10
|
+
end
|
11
|
+
|
12
|
+
def create?
|
13
|
+
context.user_access_module.admin_or_developer_access_to_project?(context.user, context.project)
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy?
|
17
|
+
context.user_access_module.admin_or_developer_access_to_project?(context.user, context.project)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UffizziCore::ClusterRepo
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
scope :deployed, -> { where(state: UffizziCore::Cluster::STATE_DEPLOYED) }
|
8
|
+
scope :enabled, -> { where.not(state: UffizziCore::Cluster::STATE_DISABLED) }
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UffizziCore::ClusterService
|
4
|
+
class << self
|
5
|
+
def start_deploy(cluster)
|
6
|
+
UffizziCore::Cluster::DeployJob.perform_async(cluster.id)
|
7
|
+
end
|
8
|
+
|
9
|
+
def deploy_cluster(cluster)
|
10
|
+
begin
|
11
|
+
UffizziCore::ControllerService.create_namespace(cluster)
|
12
|
+
rescue UffizziCore::ControllerClient::ConnectionError
|
13
|
+
return cluster.fail_deploy_namespace!
|
14
|
+
end
|
15
|
+
|
16
|
+
cluster.start_deploying!
|
17
|
+
|
18
|
+
begin
|
19
|
+
UffizziCore::ControllerService.create_cluster(cluster)
|
20
|
+
rescue UffizziCore::ControllerClient::ConnectionError
|
21
|
+
return cluster.fail!
|
22
|
+
end
|
23
|
+
|
24
|
+
UffizziCore::Cluster::ManageDeployingJob.perform_in(5.seconds, cluster.id)
|
25
|
+
end
|
26
|
+
|
27
|
+
def manage_deploying(cluster, try)
|
28
|
+
return if cluster.disabled?
|
29
|
+
return cluster.fail! if try > Settings.vcluster.max_creation_retry_count
|
30
|
+
|
31
|
+
deployed_cluster = UffizziCore::ControllerService.show_cluster(cluster)
|
32
|
+
|
33
|
+
if deployed_cluster.status.ready && deployed_cluster.status.kube_config.present?
|
34
|
+
cluster.finish_deploy
|
35
|
+
cluster.kubeconfig = deployed_cluster.status.kube_config
|
36
|
+
cluster.save!
|
37
|
+
|
38
|
+
return
|
39
|
+
end
|
40
|
+
|
41
|
+
UffizziCore::Cluster::ManageDeployingJob.perform_in(5.seconds, cluster.id, ++try)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -9,16 +9,7 @@ class UffizziCore::ControllerService
|
|
9
9
|
config_file: UffizziCore::Controller::ApplyConfigFile::ConfigFileSerializer.new(config_file).as_json,
|
10
10
|
}
|
11
11
|
|
12
|
-
controller_client.apply_config_file(deployment_id: deployment.id, config_file_id: config_file.id, body: body)
|
13
|
-
end
|
14
|
-
|
15
|
-
def create_deployment(deployment)
|
16
|
-
body = UffizziCore::Controller::CreateDeployment::DeploymentSerializer.new(deployment).as_json
|
17
|
-
controller_client.create_deployment(deployment_id: deployment.id, body: body)
|
18
|
-
end
|
19
|
-
|
20
|
-
def delete_deployment(deployment_id)
|
21
|
-
controller_client.delete_deployment(deployment_id: deployment_id)
|
12
|
+
controller_client(deployment).apply_config_file(deployment_id: deployment.id, config_file_id: config_file.id, body: body)
|
22
13
|
end
|
23
14
|
|
24
15
|
def apply_credential(deployment, credential)
|
@@ -29,11 +20,11 @@ class UffizziCore::ControllerService
|
|
29
20
|
options = { image: image }
|
30
21
|
|
31
22
|
body = UffizziCore::Controller::CreateCredential::CredentialSerializer.new(credential, options).as_json
|
32
|
-
controller_client.apply_credential(deployment_id: deployment.id, body: body)
|
23
|
+
controller_client(deployment).apply_credential(deployment_id: deployment.id, body: body)
|
33
24
|
end
|
34
25
|
|
35
26
|
def delete_credential(deployment, credential)
|
36
|
-
controller_client.delete_credential(deployment_id: deployment.id, credential_id: credential.id)
|
27
|
+
controller_client(deployment).delete_credential(deployment_id: deployment.id, credential_id: credential.id)
|
37
28
|
end
|
38
29
|
|
39
30
|
def deploy_containers(deployment, containers)
|
@@ -65,11 +56,11 @@ class UffizziCore::ControllerService
|
|
65
56
|
body = password_protection_module.add_password_configuration(body, deployment.project_id)
|
66
57
|
end
|
67
58
|
|
68
|
-
controller_client.deploy_containers(deployment_id: deployment.id, body: body)
|
59
|
+
controller_client(deployment).deploy_containers(deployment_id: deployment.id, body: body)
|
69
60
|
end
|
70
61
|
|
71
|
-
def
|
72
|
-
controller_client.
|
62
|
+
def namespace_exists?(deployable)
|
63
|
+
controller_client(deployable).namespace(namespace: deployable.namespace).code == 200
|
73
64
|
end
|
74
65
|
|
75
66
|
def fetch_deployment_events(deployment)
|
@@ -77,22 +68,53 @@ class UffizziCore::ControllerService
|
|
77
68
|
end
|
78
69
|
|
79
70
|
def fetch_pods(deployment)
|
80
|
-
pods = controller_client.deployment_containers(deployment_id: deployment.id).result || []
|
71
|
+
pods = controller_client(deployment).deployment_containers(deployment_id: deployment.id).result || []
|
81
72
|
pods.filter { |pod| pod.metadata.name.start_with?(Settings.controller.namespace_prefix) }
|
82
73
|
end
|
83
74
|
|
84
|
-
def fetch_namespace(
|
85
|
-
controller_client.
|
75
|
+
def fetch_namespace(deployable)
|
76
|
+
controller_client(deployable).namespace(namespace: deployable.namespace).result || nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def create_namespace(deployable)
|
80
|
+
body = { namespace: deployable.namespace }
|
81
|
+
controller_client(deployable).create_namespace(body: body).result || nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def delete_namespace(deployable)
|
85
|
+
controller_client(deployable).delete_namespace(namespace: deployable.namespace)
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_cluster(cluster)
|
89
|
+
body = UffizziCore::Controller::CreateCluster::ClusterSerializer.new(cluster).as_json
|
90
|
+
controller_client(cluster).create_cluster(namespace: cluster.namespace, body: body).result
|
91
|
+
end
|
92
|
+
|
93
|
+
def show_cluster(cluster)
|
94
|
+
controller_client(cluster).show_cluster(namespace: cluster.namespace, name: cluster.name).result
|
95
|
+
end
|
96
|
+
|
97
|
+
def delete_cluster(cluster)
|
98
|
+
controller_client(cluster).delete_cluster(namespace: cluster.namespace)
|
86
99
|
end
|
87
100
|
|
88
101
|
private
|
89
102
|
|
90
103
|
def request_events(deployment)
|
91
|
-
controller_client.deployment_containers_events(deployment_id: deployment.id)
|
104
|
+
controller_client(deployment).deployment_containers_events(deployment_id: deployment.id)
|
92
105
|
end
|
93
106
|
|
94
|
-
def controller_client
|
95
|
-
|
107
|
+
def controller_client(deployable)
|
108
|
+
settings = case deployable
|
109
|
+
when UffizziCore::Deployment
|
110
|
+
Settings.controller
|
111
|
+
when UffizziCore::Cluster
|
112
|
+
Settings.vcluster_controller
|
113
|
+
else
|
114
|
+
raise StandardError, "Deployable #{deployable.class.name} undefined"
|
115
|
+
end
|
116
|
+
|
117
|
+
UffizziCore::ControllerClient.new(settings)
|
96
118
|
end
|
97
119
|
end
|
98
120
|
end
|
data/config/routes.rb
CHANGED
@@ -10,6 +10,7 @@ UffizziCore::Engine.routes.draw do
|
|
10
10
|
resources :projects, only: ['index', 'show', 'destroy'], param: :slug do
|
11
11
|
scope module: :projects do
|
12
12
|
resource :compose_file, only: ['show', 'create', 'destroy']
|
13
|
+
resources :clusters, only: [:index, :create, :show, :destroy], param: :name
|
13
14
|
resources :deployments, only: ['index', 'show', 'create', 'destroy', 'update'] do
|
14
15
|
post :deploy_containers, on: :member
|
15
16
|
scope module: :deployments do
|
@@ -41,9 +42,11 @@ UffizziCore::Engine.routes.draw do
|
|
41
42
|
resource :session, only: ['create']
|
42
43
|
end
|
43
44
|
|
44
|
-
resources :accounts, only: []
|
45
|
+
resources :accounts, only: ['show'], param: :name
|
46
|
+
|
47
|
+
resources :accounts, only: ['index'] do
|
45
48
|
scope module: :accounts do
|
46
|
-
resources :projects, only: ['create']
|
49
|
+
resources :projects, only: ['index', 'create']
|
47
50
|
resources :credentials, only: ['index', 'create', 'update', 'destroy'], param: :type do
|
48
51
|
member do
|
49
52
|
get :check_credential
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateClusters < ActiveRecord::Migration[6.1]
|
4
|
+
def change
|
5
|
+
create_table('uffizzi_core_clusters', force: :cascade) do |t|
|
6
|
+
t.references :project, null: false,
|
7
|
+
foreign_key: true,
|
8
|
+
index: { name: :index_cluster_on_project_id },
|
9
|
+
foreign_key: { to_table: :uffizzi_core_projects }
|
10
|
+
t.bigint 'deployed_by_id', foreign_key: true
|
11
|
+
t.string 'state'
|
12
|
+
t.string 'name'
|
13
|
+
t.text 'manifest'
|
14
|
+
t.text 'kubeconfig'
|
15
|
+
|
16
|
+
t.timestamps
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/uffizzi_core/version.rb
CHANGED
data/lib/uffizzi_core.rb
CHANGED
@@ -35,6 +35,7 @@ module UffizziCore
|
|
35
35
|
accounts: :uffizzi_core_accounts,
|
36
36
|
activity_items: :uffizzi_core_activity_items,
|
37
37
|
builds: :uffizzi_core_builds,
|
38
|
+
clusters: :uffizzi_core_clusters,
|
38
39
|
comments: :uffizzi_core_comments,
|
39
40
|
compose_files: :uffizzi_core_compose_files,
|
40
41
|
config_files: :uffizzi_core_config_files,
|
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.
|
4
|
+
version: 2.2.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: 2023-
|
12
|
+
date: 2023-07-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aasm
|
@@ -762,6 +762,7 @@ files:
|
|
762
762
|
- app/contexts/uffizzi_core/base_context.rb
|
763
763
|
- app/contexts/uffizzi_core/project_context.rb
|
764
764
|
- app/contexts/uffizzi_core/webhooks_context.rb
|
765
|
+
- app/controller_modules/uffizzi_core/api/cli/v1/projects/clusters_controller_module.rb
|
765
766
|
- app/controller_modules/uffizzi_core/api/cli/v1/projects/deployments_controller_module.rb
|
766
767
|
- app/controller_modules/uffizzi_core/api/cli/v1/projects_controller_module.rb
|
767
768
|
- app/controllers/concerns/uffizzi_core/auth_management.rb
|
@@ -770,10 +771,12 @@ files:
|
|
770
771
|
- app/controllers/uffizzi_core/api/cli/v1/accounts/application_controller.rb
|
771
772
|
- app/controllers/uffizzi_core/api/cli/v1/accounts/credentials_controller.rb
|
772
773
|
- app/controllers/uffizzi_core/api/cli/v1/accounts/projects_controller.rb
|
774
|
+
- app/controllers/uffizzi_core/api/cli/v1/accounts_controller.rb
|
773
775
|
- app/controllers/uffizzi_core/api/cli/v1/application_controller.rb
|
774
776
|
- app/controllers/uffizzi_core/api/cli/v1/ci/application_controller.rb
|
775
777
|
- app/controllers/uffizzi_core/api/cli/v1/ci/sessions_controller.rb
|
776
778
|
- app/controllers/uffizzi_core/api/cli/v1/projects/application_controller.rb
|
779
|
+
- app/controllers/uffizzi_core/api/cli/v1/projects/clusters_controller.rb
|
777
780
|
- app/controllers/uffizzi_core/api/cli/v1/projects/compose_files_controller.rb
|
778
781
|
- app/controllers/uffizzi_core/api/cli/v1/projects/deployments/activity_items_controller.rb
|
779
782
|
- app/controllers/uffizzi_core/api/cli/v1/projects/deployments/application_controller.rb
|
@@ -798,6 +801,7 @@ files:
|
|
798
801
|
- app/forms/uffizzi_core/api/cli/v1/account/credential/check_credential_form.rb
|
799
802
|
- app/forms/uffizzi_core/api/cli/v1/account/credential/create_form.rb
|
800
803
|
- app/forms/uffizzi_core/api/cli/v1/account/credential/update_form.rb
|
804
|
+
- app/forms/uffizzi_core/api/cli/v1/cluster/create_form.rb
|
801
805
|
- app/forms/uffizzi_core/api/cli/v1/compose_file/check_credentials_form.rb
|
802
806
|
- app/forms/uffizzi_core/api/cli/v1/compose_file/cli_form.rb
|
803
807
|
- app/forms/uffizzi_core/api/cli/v1/compose_file/create_form.rb
|
@@ -819,6 +823,9 @@ files:
|
|
819
823
|
- app/jobs/uffizzi_core/account/update_credential_job.rb
|
820
824
|
- app/jobs/uffizzi_core/activity_item/docker/update_digest_job.rb
|
821
825
|
- app/jobs/uffizzi_core/application_job.rb
|
826
|
+
- app/jobs/uffizzi_core/cluster/delete_job.rb
|
827
|
+
- app/jobs/uffizzi_core/cluster/deploy_job.rb
|
828
|
+
- app/jobs/uffizzi_core/cluster/manage_deploying_job.rb
|
822
829
|
- app/jobs/uffizzi_core/config_file/apply_job.rb
|
823
830
|
- app/jobs/uffizzi_core/deployment/create_credential_job.rb
|
824
831
|
- app/jobs/uffizzi_core/deployment/create_credentials_job.rb
|
@@ -830,6 +837,7 @@ files:
|
|
830
837
|
- app/jobs/uffizzi_core/deployment/update_credential_job.rb
|
831
838
|
- app/lib/uffizzi_core/concerns/models/account.rb
|
832
839
|
- app/lib/uffizzi_core/concerns/models/activity_item.rb
|
840
|
+
- app/lib/uffizzi_core/concerns/models/cluster.rb
|
833
841
|
- app/lib/uffizzi_core/concerns/models/comment.rb
|
834
842
|
- app/lib/uffizzi_core/concerns/models/compose_file.rb
|
835
843
|
- app/lib/uffizzi_core/concerns/models/config_file.rb
|
@@ -863,6 +871,7 @@ files:
|
|
863
871
|
- app/models/uffizzi_core/activity_item/github.rb
|
864
872
|
- app/models/uffizzi_core/activity_item/memory_limit.rb
|
865
873
|
- app/models/uffizzi_core/application_record.rb
|
874
|
+
- app/models/uffizzi_core/cluster.rb
|
866
875
|
- app/models/uffizzi_core/comment.rb
|
867
876
|
- app/models/uffizzi_core/compose_file.rb
|
868
877
|
- app/models/uffizzi_core/config_file.rb
|
@@ -903,6 +912,8 @@ files:
|
|
903
912
|
- app/models/uffizzi_core/user_project.rb
|
904
913
|
- app/policies/uffizzi_core/api/cli/v1/accounts/credentials_policy.rb
|
905
914
|
- app/policies/uffizzi_core/api/cli/v1/accounts/projects_policy.rb
|
915
|
+
- app/policies/uffizzi_core/api/cli/v1/accounts_policy.rb
|
916
|
+
- app/policies/uffizzi_core/api/cli/v1/projects/clusters_policy.rb
|
906
917
|
- app/policies/uffizzi_core/api/cli/v1/projects/compose_files_policy.rb
|
907
918
|
- app/policies/uffizzi_core/api/cli/v1/projects/deployments/activity_items_policy.rb
|
908
919
|
- app/policies/uffizzi_core/api/cli/v1/projects/deployments/containers_policy.rb
|
@@ -914,6 +925,7 @@ files:
|
|
914
925
|
- app/repositories/uffizzi_core/account_repo.rb
|
915
926
|
- app/repositories/uffizzi_core/activity_item_repo.rb
|
916
927
|
- app/repositories/uffizzi_core/basic_order_repo.rb
|
928
|
+
- app/repositories/uffizzi_core/cluster_repo.rb
|
917
929
|
- app/repositories/uffizzi_core/comment_repo.rb
|
918
930
|
- app/repositories/uffizzi_core/compose_file_repo.rb
|
919
931
|
- app/repositories/uffizzi_core/config_file_repo.rb
|
@@ -931,12 +943,14 @@ files:
|
|
931
943
|
- app/repositories/uffizzi_core/usage_repo.rb
|
932
944
|
- app/repositories/uffizzi_core/user_repo.rb
|
933
945
|
- app/responders/uffizzi_core/json_responder.rb
|
946
|
+
- app/serializers/uffizzi_core/api/cli/v1/account_serializer.rb
|
934
947
|
- app/serializers/uffizzi_core/api/cli/v1/accounts/credential_serializer.rb
|
935
948
|
- app/serializers/uffizzi_core/api/cli/v1/accounts/project_serializer.rb
|
936
949
|
- app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb
|
937
950
|
- app/serializers/uffizzi_core/api/cli/v1/project_serializer/account_serializer.rb
|
938
951
|
- app/serializers/uffizzi_core/api/cli/v1/project_serializer/compose_file_serializer.rb
|
939
952
|
- app/serializers/uffizzi_core/api/cli/v1/project_serializer/deployment_serializer.rb
|
953
|
+
- app/serializers/uffizzi_core/api/cli/v1/projects/cluster_serializer.rb
|
940
954
|
- app/serializers/uffizzi_core/api/cli/v1/projects/compose_file_serializer.rb
|
941
955
|
- app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer.rb
|
942
956
|
- app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb
|
@@ -953,6 +967,7 @@ files:
|
|
953
967
|
- app/serializers/uffizzi_core/api/cli/v1/user_serializer/account_serializer.rb
|
954
968
|
- app/serializers/uffizzi_core/base_serializer.rb
|
955
969
|
- app/serializers/uffizzi_core/controller/apply_config_file/config_file_serializer.rb
|
970
|
+
- app/serializers/uffizzi_core/controller/create_cluster/cluster_serializer.rb
|
956
971
|
- app/serializers/uffizzi_core/controller/create_credential/credential_serializer.rb
|
957
972
|
- app/serializers/uffizzi_core/controller/create_deployment/deployment_serializer.rb
|
958
973
|
- app/serializers/uffizzi_core/controller/deploy_containers/compose_file_serializer.rb
|
@@ -964,6 +979,7 @@ files:
|
|
964
979
|
- app/serializers/uffizzi_core/controller/deploy_containers/host_volume_file_serializer.rb
|
965
980
|
- app/services/uffizzi_core/account_service.rb
|
966
981
|
- app/services/uffizzi_core/activity_item_service.rb
|
982
|
+
- app/services/uffizzi_core/cluster_service.rb
|
967
983
|
- app/services/uffizzi_core/compose_file/builders/container_builder_service.rb
|
968
984
|
- app/services/uffizzi_core/compose_file/builders/container_config_files_builder_service.rb
|
969
985
|
- app/services/uffizzi_core/compose_file/builders/container_host_volume_files_builder_service.rb
|
@@ -1043,6 +1059,7 @@ files:
|
|
1043
1059
|
- db/migrate/20230111000000_add_state_to_memberships.rb
|
1044
1060
|
- db/migrate/20230306142513_add_last_deploy_at_to_deployments.rb
|
1045
1061
|
- db/migrate/20230406154451_add_full_image_name_to_container.rb
|
1062
|
+
- db/migrate/20230613101901_create_clusters.rb
|
1046
1063
|
- db/seeds.rb
|
1047
1064
|
- lib/tasks/uffizzi_core_tasks.rake
|
1048
1065
|
- lib/uffizzi_core.rb
|