summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2017-11-02 15:10:46 +0100
committerKamil Trzcinski <ayufan@ayufan.eu>2017-11-02 15:10:46 +0100
commit64be8d70ae20928df351e495a3442bb6036bc3e7 (patch)
tree6eb01452391ccfa45d1dbaeae261d118d323bcc1
parent461c385ebca7ecb52d0b385fd61c856eb395481a (diff)
downloadgitlab-ce-64be8d70ae20928df351e495a3442bb6036bc3e7.tar.gz
Improve backend structure of data
-rw-r--r--app/controllers/projects/clusters/applications_controller.rb39
-rw-r--r--app/models/clusters/applications/helm.rb (renamed from app/models/clusters/kubernetes/helm_app.rb)11
-rw-r--r--app/models/clusters/cluster.rb19
-rw-r--r--app/models/clusters/kubernetes.rb16
-rw-r--r--app/models/clusters/platforms/kubernetes.rb4
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/project_services/kubernetes_service.rb6
-rw-r--r--app/presenters/clusters/cluster_presenter.rb6
-rw-r--r--app/serializers/cluster_app_entity.rb5
-rw-r--r--app/serializers/cluster_entity.rb13
-rw-r--r--app/services/clusters/base_helm_service.rb12
-rw-r--r--app/services/clusters/fetch_app_installation_status_service.rb4
-rw-r--r--app/services/clusters/finalize_app_installation_service.rb2
-rw-r--r--app/services/clusters/install_app_service.rb4
-rw-r--r--app/workers/concerns/cluster_app.rb5
-rw-r--r--config/routes/project.rb4
-rw-r--r--db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb8
-rw-r--r--db/schema.rb35
-rw-r--r--spec/models/clusters/kubernetes/helm_app_spec.rb2
-rw-r--r--spec/models/clusters/kubernetes_spec.rb9
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb1
21 files changed, 129 insertions, 77 deletions
diff --git a/app/controllers/projects/clusters/applications_controller.rb b/app/controllers/projects/clusters/applications_controller.rb
new file mode 100644
index 00000000000..438e1853435
--- /dev/null
+++ b/app/controllers/projects/clusters/applications_controller.rb
@@ -0,0 +1,39 @@
+class Projects::Clusters::ApplicationsController < Projects::ApplicationController
+ before_action :cluster
+ before_action :application_class, only: [:create]
+ before_action :authorize_read_cluster!
+ before_action :authorize_create_cluster!, only: [:create]
+
+ def new
+ end
+
+ def create
+ return render_404 if application
+
+ new_application = application_class.create(cluster: cluster)
+
+ respond_to do |format|
+ format.json do
+ if new_application.persisted?
+ head :ok
+ else
+ head :bad_request
+ end
+ end
+ end
+ end
+
+ private
+
+ def cluster
+ @cluster ||= project.clusters.find_by(cluster_id: params[:cluster_id]).present(current_user: current_user)
+ end
+
+ def application_class
+ Clusters::Cluster::Applications.find(params[:application])
+ end
+
+ def application
+ application_class.find_by(cluster: cluster)
+ end
+end
diff --git a/app/models/clusters/kubernetes/helm_app.rb b/app/models/clusters/applications/helm.rb
index 32c9e13a469..59e0076c8df 100644
--- a/app/models/clusters/kubernetes/helm_app.rb
+++ b/app/models/clusters/applications/helm.rb
@@ -1,14 +1,15 @@
module Clusters
- module Kubernetes
- class HelmApp < ActiveRecord::Base
+ module Applications
+ class Helm < ActiveRecord::Base
+ self.table_name = 'clusters_applications_helm'
+
NAME = 'helm'.freeze
include ::Clusters::Concerns::AppStatus
- belongs_to :kubernetes_service, class_name: 'KubernetesService', foreign_key: :service_id
- default_value_for :version, Gitlab::Clusters::Helm::HELM_VERSION
+ belongs_to :cluser, class_name: 'Clusters::Cluster', foreign_key: :cluster_id
- alias_method :cluster, :kubernetes_service
+ default_value_for :version, Gitlab::Clusters::Helm::HELM_VERSION
def name
NAME
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index ca09b939f34..c814f475adf 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -4,6 +4,10 @@ module Clusters
self.table_name = 'clusters'
+ APPLICATIONS = {
+ Clusters::Applications::Helm::NAME => Clusters::Applications::Helm
+ }
+
belongs_to :user
has_many :cluster_projects, class_name: 'Clusters::Project'
@@ -15,13 +19,14 @@ module Clusters
# We have to ":destroy" it today to ensure that we clean also the Kubernetes Integration
has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes', autosave: true, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_one :application_helm, class_name: 'Clusters::Applications::Helm'
+
accepts_nested_attributes_for :provider_gcp, update_only: true
accepts_nested_attributes_for :platform_kubernetes, update_only: true
validates :name, cluster_name: true
validate :restrict_modification, on: :update
- delegate :status, to: :provider, allow_nil: true
delegate :status_reason, to: :provider, allow_nil: true
delegate :status_name, to: :provider, allow_nil: true
delegate :on_creation?, to: :provider, allow_nil: true
@@ -38,6 +43,14 @@ module Clusters
scope :enabled, -> { where(enabled: true) }
scope :disabled, -> { where(enabled: false) }
+ def status_name
+ if provider
+ provider.status_name
+ else
+ :created
+ end
+ end
+
def provider
return provider_gcp if gcp?
end
@@ -53,6 +66,10 @@ module Clusters
end
alias_method :project, :first_project
+ def kubeclient
+ platform_kubernetes.kubeclient if kubernetes?
+ end
+
private
def restrict_modification
diff --git a/app/models/clusters/kubernetes.rb b/app/models/clusters/kubernetes.rb
deleted file mode 100644
index b68e2ae401e..00000000000
--- a/app/models/clusters/kubernetes.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-module Clusters
- module Kubernetes
- def self.table_name_prefix
- 'clusters_kubernetes_'
- end
-
- def self.app(app_name)
- case app_name
- when HelmApp::NAME
- HelmApp
- else
- raise ArgumentError, "Unknown app #{app_name}"
- end
- end
- end
-end
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 3ad2ffe531d..1197dfaefcb 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -60,6 +60,10 @@ module Clusters
self.class.namespace_for_project(project) if project
end
+ def kubeclient
+ @kubeclient ||= kubernetes_service.kubeclient if manages_kubernetes_service?
+ end
+
private
def enforce_namespace_to_lower_case
diff --git a/app/models/project.rb b/app/models/project.rb
index d9d9e12c947..a42e2553935 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -189,6 +189,7 @@ class Project < ActiveRecord::Base
has_one :cluster_project, class_name: 'Clusters::Project'
has_one :cluster, through: :cluster_project, class_name: 'Clusters::Cluster'
+ has_many :clusters, through: :cluster_project, class_name: 'Clusters::Cluster'
# Container repositories need to remove data from the container registry,
# which is not managed by the DB. Hence we're still using dependent: :destroy
diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb
index b4654e8d1ea..5080acffb3c 100644
--- a/app/models/project_services/kubernetes_service.rb
+++ b/app/models/project_services/kubernetes_service.rb
@@ -3,8 +3,6 @@ class KubernetesService < DeploymentService
include Gitlab::Kubernetes
include ReactiveCaching
- has_one :helm_app, class_name: 'Clusters::Kubernetes::HelmApp', foreign_key: :service_id
-
self.reactive_cache_key = ->(service) { [service.class.model_name.singular, service.project_id] }
# Namespace defaults to the project path, but can be overridden in case that
@@ -138,8 +136,8 @@ class KubernetesService < DeploymentService
{ pods: read_pods }
end
- def helm
- Gitlab::Clusters::Helm.new(build_kubeclient!)
+ def kubeclient
+ @kubeclient ||= build_kubeclient!
end
TEMPLATE_PLACEHOLDER = 'Kubernetes namespace'.freeze
diff --git a/app/presenters/clusters/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb
index 01cb59d0d44..5e11dac3bd2 100644
--- a/app/presenters/clusters/cluster_presenter.rb
+++ b/app/presenters/clusters/cluster_presenter.rb
@@ -5,5 +5,11 @@ module Clusters
def gke_cluster_url
"https://console.cloud.google.com/kubernetes/clusters/details/#{provider.zone}/#{name}" if gcp?
end
+
+ def applications
+ Clusters::Cluster::APPLICATIONS.map do |key, value|
+ value.find_by(cluster_id: id)
+ end.compact
+ end
end
end
diff --git a/app/serializers/cluster_app_entity.rb b/app/serializers/cluster_app_entity.rb
new file mode 100644
index 00000000000..7da2d4921a2
--- /dev/null
+++ b/app/serializers/cluster_app_entity.rb
@@ -0,0 +1,5 @@
+class ClusterAppEntity < Grape::Entity
+ expose :name
+ expose :status_name, as: :status
+ expose :status_reason
+end
diff --git a/app/serializers/cluster_entity.rb b/app/serializers/cluster_entity.rb
index 84ce34afb32..e775c68eb6b 100644
--- a/app/serializers/cluster_entity.rb
+++ b/app/serializers/cluster_entity.rb
@@ -3,16 +3,5 @@ class ClusterEntity < Grape::Entity
expose :status_name, as: :status
expose :status_reason
- expose :applications do |cluster, options|
- if cluster.created?
- {
- helm: { status: 'installed' },
- ingress: { status: 'error', status_reason: 'Missing namespace' },
- runner: { status: 'installing' },
- prometheus: { status: 'installable' }
- }
- else
- {}
- end
- end
+ expose :applications, using: ClusterAppEntity
end
diff --git a/app/services/clusters/base_helm_service.rb b/app/services/clusters/base_helm_service.rb
index b8ed52bf376..c7f7e2d0877 100644
--- a/app/services/clusters/base_helm_service.rb
+++ b/app/services/clusters/base_helm_service.rb
@@ -8,10 +8,16 @@ module Clusters
protected
- def helm
- return @helm if defined?(@helm)
+ def cluster
+ app.cluster
+ end
+
+ def kubeclient
+ cluster.kubeclient
+ end
- @helm = @app.cluster.helm
+ def helm_api
+ @helm ||= Gitlab::Clusters::Helm.new(kubeclient)
end
end
end
diff --git a/app/services/clusters/fetch_app_installation_status_service.rb b/app/services/clusters/fetch_app_installation_status_service.rb
index e21aa49bb43..9b281c77c49 100644
--- a/app/services/clusters/fetch_app_installation_status_service.rb
+++ b/app/services/clusters/fetch_app_installation_status_service.rb
@@ -3,8 +3,8 @@ module Clusters
def execute
return unless app.installing?
- phase = helm.installation_status(app)
- log = helm.installation_log(app) if phase == 'Failed'
+ phase = helm_api.installation_status(app)
+ log = helm_api.installation_log(app) if phase == 'Failed'
yield(phase, log) if block_given?
rescue KubeException => ke
app.make_errored!("Kubernetes error: #{ke.message}") unless app.errored?
diff --git a/app/services/clusters/finalize_app_installation_service.rb b/app/services/clusters/finalize_app_installation_service.rb
index c921747febc..b9d5da063eb 100644
--- a/app/services/clusters/finalize_app_installation_service.rb
+++ b/app/services/clusters/finalize_app_installation_service.rb
@@ -1,7 +1,7 @@
module Clusters
class FinalizeAppInstallationService < BaseHelmService
def execute
- helm.delete_installation_pod!(app)
+ helm_api.delete_installation_pod!(app)
app.make_errored!('Installation aborted') if aborted?
end
diff --git a/app/services/clusters/install_app_service.rb b/app/services/clusters/install_app_service.rb
index dd8556108d4..496af2495fd 100644
--- a/app/services/clusters/install_app_service.rb
+++ b/app/services/clusters/install_app_service.rb
@@ -4,14 +4,14 @@ module Clusters
return unless app.scheduled?
begin
- helm.install(app)
+ helm_api.install(app)
+
if app.make_installing
ClusterWaitForAppInstallationWorker.perform_in(
ClusterWaitForAppInstallationWorker::INITIAL_INTERVAL, app.name, app.id)
else
app.make_errored!("Failed to update app record; #{app.errors}")
end
-
rescue KubeException => ke
app.make_errored!("Kubernetes error: #{ke.message}")
rescue StandardError => e
diff --git a/app/workers/concerns/cluster_app.rb b/app/workers/concerns/cluster_app.rb
index 2170f8be6f6..a0202901f15 100644
--- a/app/workers/concerns/cluster_app.rb
+++ b/app/workers/concerns/cluster_app.rb
@@ -3,8 +3,9 @@ module ClusterApp
included do
def find_app(app_name, id)
- app = Clusters::Kubernetes.app(app_name).find(id)
- yield(app) if block_given?
+ Clusters::Applications.const_get(app_name.classify).find(id).try do |app|
+ yield(app) if block_given?
+ end
end
end
end
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 746c0c46677..a6a7c5e7482 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -190,6 +190,10 @@ constraints(ProjectUrlConstrainer.new) do
member do
get :status, format: :json
+
+ scope '*application' do
+ resource :applications, only: [:create]
+ end
end
end
diff --git a/db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb b/db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb
index 93611bf8a12..1035adfe2b5 100644
--- a/db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb
+++ b/db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb
@@ -1,12 +1,12 @@
class CreateClustersKubernetesHelmApps < ActiveRecord::Migration
def change
- create_table :clusters_kubernetes_helm_apps do |t|
- t.integer :status, null: false
+ create_table :clusters_applications_helm do |t|
+ t.references :cluster, null: false, unique: true, foreign_key: { on_delete: :cascade }
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :updated_at, null: false
-
- t.references :service, index: true, null: false, foreign_key: { on_delete: :cascade }
+
+ t.integer :status, null: false
t.string :version, null: false
t.text :status_reason
end
diff --git a/db/schema.rb b/db/schema.rb
index d76977d45f2..02df408b45e 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20171017145932) do
+ActiveRecord::Schema.define(version: 20171031100710) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -464,9 +464,7 @@ ActiveRecord::Schema.define(version: 20171017145932) do
create_table "cluster_platforms_kubernetes", force: :cascade do |t|
t.integer "cluster_id", null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.text "api_url"
+ t.string "api_url"
t.text "ca_cert"
t.string "namespace"
t.string "username"
@@ -474,6 +472,8 @@ ActiveRecord::Schema.define(version: 20171017145932) do
t.string "encrypted_password_iv"
t.text "encrypted_token"
t.string "encrypted_token_iv"
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
end
add_index "cluster_platforms_kubernetes", ["cluster_id"], name: "index_cluster_platforms_kubernetes_on_cluster_id", unique: true, using: :btree
@@ -491,33 +491,39 @@ ActiveRecord::Schema.define(version: 20171017145932) do
create_table "cluster_providers_gcp", force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "status"
- t.integer "num_nodes", null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
t.text "status_reason"
t.string "gcp_project_id", null: false
t.string "zone", null: false
+ t.integer "num_nodes", null: false
t.string "machine_type"
t.string "operation_id"
t.string "endpoint"
t.text "encrypted_access_token"
t.string "encrypted_access_token_iv"
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
end
add_index "cluster_providers_gcp", ["cluster_id"], name: "index_cluster_providers_gcp_on_cluster_id", unique: true, using: :btree
create_table "clusters", force: :cascade do |t|
- t.integer "user_id", null: false
- t.integer "provider_type"
- t.integer "platform_type"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
+ t.integer "user_id"
t.boolean "enabled", default: true
t.string "name", null: false
+ t.integer "provider_type"
+ t.integer "platform_type"
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
end
- add_index "clusters", ["enabled"], name: "index_clusters_on_enabled", using: :btree
- add_index "clusters", ["user_id"], name: "index_clusters_on_user_id", using: :btree
+ create_table "clusters_applications_helm", force: :cascade do |t|
+ t.integer "cluster_id", null: false
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.integer "status", null: false
+ t.string "version", null: false
+ t.text "status_reason"
+ end
create_table "container_repositories", force: :cascade do |t|
t.integer "project_id", null: false
@@ -1872,6 +1878,7 @@ ActiveRecord::Schema.define(version: 20171017145932) do
add_foreign_key "cluster_projects", "projects", on_delete: :cascade
add_foreign_key "cluster_providers_gcp", "clusters", on_delete: :cascade
add_foreign_key "clusters", "users", on_delete: :nullify
+ add_foreign_key "clusters_applications_helm", "clusters", on_delete: :cascade
add_foreign_key "container_repositories", "projects"
add_foreign_key "deploy_keys_projects", "projects", name: "fk_58a901ca7e", on_delete: :cascade
add_foreign_key "deployments", "projects", name: "fk_b9a3851b82", on_delete: :cascade
diff --git a/spec/models/clusters/kubernetes/helm_app_spec.rb b/spec/models/clusters/kubernetes/helm_app_spec.rb
index 27a1561ce6c..6e32e2e7037 100644
--- a/spec/models/clusters/kubernetes/helm_app_spec.rb
+++ b/spec/models/clusters/kubernetes/helm_app_spec.rb
@@ -1,7 +1,7 @@
require 'rails_helper'
require_relative '../kubernetes_spec'
-RSpec.describe Clusters::Kubernetes::HelmApp, type: :model do
+RSpec.describe Clusters::Applications::Helm, type: :model do
it_behaves_like 'a registered kubernetes app'
it { is_expected.to belong_to(:kubernetes_service) }
diff --git a/spec/models/clusters/kubernetes_spec.rb b/spec/models/clusters/kubernetes_spec.rb
deleted file mode 100644
index 5876f08250f..00000000000
--- a/spec/models/clusters/kubernetes_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-require 'rails_helper'
-
-RSpec.shared_examples 'a registered kubernetes app' do
- let(:name) { described_class::NAME }
-
- it 'can be retrieved with Clusters::Kubernetes.app' do
- expect(Clusters::Kubernetes.app(name)).to eq(described_class)
- end
-end
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 6d9fc28bf58..1c629155e1e 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -9,7 +9,6 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
describe 'Associations' do
it { is_expected.to belong_to :project }
- it { is_expected.to have_one(:helm_app) }
end
describe 'Validations' do