uffizzi_core 2.1.29 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|