From e1d12ba9b988e61afb9317f3a132d6e2caa93923 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 13 Oct 2017 19:21:23 +0200 Subject: Refactor Clusters to be consisted from GcpProvider and KubernetesPlatform --- app/models/clusters/cluster.rb | 56 +++++++++ app/models/clusters/cluster_project.rb | 6 + app/models/clusters/platforms/kubernetes.rb | 172 ++++++++++++++++++++++++++++ app/models/clusters/providers/gcp.rb | 79 +++++++++++++ app/models/gcp/cluster.rb | 116 ------------------- app/models/project.rb | 4 +- 6 files changed, 316 insertions(+), 117 deletions(-) create mode 100644 app/models/clusters/cluster.rb create mode 100644 app/models/clusters/cluster_project.rb create mode 100644 app/models/clusters/platforms/kubernetes.rb create mode 100644 app/models/clusters/providers/gcp.rb delete mode 100644 app/models/gcp/cluster.rb (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb new file mode 100644 index 00000000000..d7b13ac88f2 --- /dev/null +++ b/app/models/clusters/cluster.rb @@ -0,0 +1,56 @@ +module Clusters + class Cluster < ActiveRecord::Base + include Presentable + + belongs_to :user + belongs_to :service + + enum :platform_type { + kubernetes: 1 + } + + enum :provider_type { + user: 0, + gcp: 1 + } + + has_many :cluster_projects + has_many :projects, through: :cluster_projects + + has_one :gcp_provider + has_one :kubernetes_platform + + accepts_nested_attributes_for :gcp_provider + accepts_nested_attributes_for :kubernetes_platform + + validates :kubernetes_platform, presence: true, if: :kubernetes? + validates :gcp_provider, presence: true, if: :gcp? + validate :restrict_modification, on: :update + + delegate :status, to: :provider, allow_nil: true + delegate :status_reason, to: :provider, allow_nil: true + + def restrict_modification + if provider&.on_creation? + errors.add(:base, "cannot modify during creation") + return false + end + + true + end + + def provider + return gcp_provider if gcp? + end + + def platform + return kubernetes_platform if kubernetes? + end + + def first_project + return @first_project if defined?(@first_project) + + @first_project = projects.first + end + end +end diff --git a/app/models/clusters/cluster_project.rb b/app/models/clusters/cluster_project.rb new file mode 100644 index 00000000000..7b139c2bb08 --- /dev/null +++ b/app/models/clusters/cluster_project.rb @@ -0,0 +1,6 @@ +module Clusters + class ClusterProject < ActiveRecord::Base + belongs_to :cluster + belongs_to :project + end +end diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb new file mode 100644 index 00000000000..aed6f733487 --- /dev/null +++ b/app/models/clusters/platforms/kubernetes.rb @@ -0,0 +1,172 @@ +module Clusters + module Platforms + class Kubernetes < ActiveRecord::Base + include Gitlab::Kubernetes + include ReactiveCaching + + TEMPLATE_PLACEHOLDER = 'Kubernetes namespace'.freeze + + self.reactive_cache_key = ->(service) { [service.class.model_name.singular, service.project_id] } + + belongs_to :cluster + + attr_encrypted :password, + mode: :per_attribute_iv, + key: Gitlab::Application.secrets.db_key_base, + algorithm: 'aes-256-cbc' + + attr_encrypted :token, + mode: :per_attribute_iv, + key: Gitlab::Application.secrets.db_key_base, + algorithm: 'aes-256-cbc' + + validates :namespace, + allow_blank: true, + length: 1..63, + format: { + with: Gitlab::Regex.kubernetes_namespace_regex, + message: Gitlab::Regex.kubernetes_namespace_regex_message + } + + validates :api_url, url: true, presence: true + validates :token, presence: true + + after_save :clear_reactive_cache! + + before_validation :enforce_namespace_to_lower_case + + def actual_namespace + if namespace.present? + namespace + else + default_namespace + end + end + + def predefined_variables + config = YAML.dump(kubeconfig) + + variables = [ + { key: 'KUBE_URL', value: api_url, public: true }, + { key: 'KUBE_TOKEN', value: token, public: false }, + { key: 'KUBE_NAMESPACE', value: actual_namespace, public: true }, + { key: 'KUBECONFIG', value: config, public: false, file: true } + ] + + if ca_pem.present? + variables << { key: 'KUBE_CA_PEM', value: ca_pem, public: true } + variables << { key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true } + end + + variables + end + + # Constructs a list of terminals from the reactive cache + # + # Returns nil if the cache is empty, in which case you should try again a + # short time later + def terminals(environment) + with_reactive_cache do |data| + pods = filter_by_label(data[:pods], app: environment.slug) + terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) } + terminals.each { |terminal| add_terminal_auth(terminal, terminal_auth) } + end + end + + # Caches resources in the namespace so other calls don't need to block on + # network access + def calculate_reactive_cache + return unless active? && project && !project.pending_delete? + + # We may want to cache extra things in the future + { pods: read_pods } + end + + def kubeconfig + to_kubeconfig( + url: api_url, + namespace: actual_namespace, + token: token, + ca_pem: ca_pem) + end + + def namespace_placeholder + default_namespace || TEMPLATE_PLACEHOLDER + end + + def default_namespace + "#{cluster.first_project.path}-#{cluster.first_project.id}" if cluster.first_project + end + + def read_secrets + kubeclient = build_kubeclient! + + kubeclient.get_secrets.as_json + rescue KubeException => err + raise err unless err.error_code == 404 + [] + end + + # Returns a hash of all pods in the namespace + def read_pods + kubeclient = build_kubeclient! + + kubeclient.get_pods(namespace: actual_namespace).as_json + rescue KubeException => err + raise err unless err.error_code == 404 + [] + end + + def kubeclient_ssl_options + opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER } + + if ca_pem.present? + opts[:cert_store] = OpenSSL::X509::Store.new + opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem)) + end + + opts + end + + private + + def build_kubeclient!(api_path: 'api', api_version: 'v1') + raise "Incomplete settings" unless api_url && actual_namespace && token + + ::Kubeclient::Client.new( + join_api_url(api_path), + api_version, + auth_options: kubeclient_auth_options, + ssl_options: kubeclient_ssl_options, + http_proxy_uri: ENV['http_proxy'] + ) + end + + def kubeclient_auth_options + return { username: username, password: password } if username + return { bearer_token: token } if token + end + + def join_api_url(api_path) + url = URI.parse(api_url) + prefix = url.path.sub(%r{/+\z}, '') + + url.path = [prefix, api_path].join("/") + + url.to_s + end + + def terminal_auth + { + token: token, + ca_pem: ca_pem, + max_session_time: current_application_settings.terminal_max_session_time + } + end + + def enforce_namespace_to_lower_case + self.namespace = self.namespace&.downcase + end + end + end +end diff --git a/app/models/clusters/providers/gcp.rb b/app/models/clusters/providers/gcp.rb new file mode 100644 index 00000000000..5d4618cfe87 --- /dev/null +++ b/app/models/clusters/providers/gcp.rb @@ -0,0 +1,79 @@ +module Clusters + module Providers + class Gcp < ActiveRecord::Base + belongs_to :cluster + + default_value_for :cluster_zone, 'us-central1-a' + default_value_for :cluster_size, 3 + default_value_for :machine_type, 'n1-standard-4' + + attr_encrypted :access_token, + mode: :per_attribute_iv, + key: Gitlab::Application.secrets.db_key_base, + algorithm: 'aes-256-cbc' + + validates :project_id, + length: 1..63, + format: { + with: Gitlab::Regex.kubernetes_namespace_regex, + message: Gitlab::Regex.kubernetes_namespace_regex_message + } + + validates :cluster_name, + length: 1..63, + format: { + with: Gitlab::Regex.kubernetes_namespace_regex, + message: Gitlab::Regex.kubernetes_namespace_regex_message + } + + validates :cluster_zone, presence: true + + validates :cluster_size, + presence: true, + numericality: { + only_integer: true, + greater_than: 0 + } + + state_machine :status, initial: :scheduled do + state :scheduled, value: 1 + state :creating, value: 2 + state :created, value: 3 + state :errored, value: 4 + + event :make_creating do + transition any - [:creating] => :creating + end + + event :make_created do + transition any - [:created] => :created + end + + event :make_errored do + transition any - [:errored] => :errored + end + + before_transition any => [:errored, :created] do |provider| + provider.token = nil + provider.operation_id = nil + provider.save! + end + + before_transition any => [:errored] do |provider, transition| + status_reason = transition.args.first + provider.status_reason = status_reason if status_reason + end + end + + def on_creation? + scheduled? || creating? + end + + def api_client + return unless access_token + + @api_client ||= GoogleApi::CloudPlatform::Client.new(access_token, nil) + end + end + end +end diff --git a/app/models/gcp/cluster.rb b/app/models/gcp/cluster.rb deleted file mode 100644 index 162a690c0e3..00000000000 --- a/app/models/gcp/cluster.rb +++ /dev/null @@ -1,116 +0,0 @@ -module Gcp - class Cluster < ActiveRecord::Base - extend Gitlab::Gcp::Model - include Presentable - - belongs_to :project, inverse_of: :cluster - belongs_to :user - belongs_to :service - - scope :enabled, -> { where(enabled: true) } - scope :disabled, -> { where(enabled: false) } - - default_value_for :gcp_cluster_zone, 'us-central1-a' - default_value_for :gcp_cluster_size, 3 - default_value_for :gcp_machine_type, 'n1-standard-4' - - attr_encrypted :password, - mode: :per_attribute_iv, - key: Gitlab::Application.secrets.db_key_base, - algorithm: 'aes-256-cbc' - - attr_encrypted :kubernetes_token, - mode: :per_attribute_iv, - key: Gitlab::Application.secrets.db_key_base, - algorithm: 'aes-256-cbc' - - attr_encrypted :gcp_token, - mode: :per_attribute_iv, - key: Gitlab::Application.secrets.db_key_base, - algorithm: 'aes-256-cbc' - - validates :gcp_project_id, - length: 1..63, - format: { - with: Gitlab::Regex.kubernetes_namespace_regex, - message: Gitlab::Regex.kubernetes_namespace_regex_message - } - - validates :gcp_cluster_name, - length: 1..63, - format: { - with: Gitlab::Regex.kubernetes_namespace_regex, - message: Gitlab::Regex.kubernetes_namespace_regex_message - } - - validates :gcp_cluster_zone, presence: true - - validates :gcp_cluster_size, - presence: true, - numericality: { - only_integer: true, - greater_than: 0 - } - - validates :project_namespace, - allow_blank: true, - length: 1..63, - format: { - with: Gitlab::Regex.kubernetes_namespace_regex, - message: Gitlab::Regex.kubernetes_namespace_regex_message - } - - # if we do not do status transition we prevent change - validate :restrict_modification, on: :update, unless: :status_changed? - - state_machine :status, initial: :scheduled do - state :scheduled, value: 1 - state :creating, value: 2 - state :created, value: 3 - state :errored, value: 4 - - event :make_creating do - transition any - [:creating] => :creating - end - - event :make_created do - transition any - [:created] => :created - end - - event :make_errored do - transition any - [:errored] => :errored - end - - before_transition any => [:errored, :created] do |cluster| - cluster.gcp_token = nil - cluster.gcp_operation_id = nil - end - - before_transition any => [:errored] do |cluster, transition| - status_reason = transition.args.first - cluster.status_reason = status_reason if status_reason - end - end - - def project_namespace_placeholder - "#{project.path}-#{project.id}" - end - - def on_creation? - scheduled? || creating? - end - - def api_url - 'https://' + endpoint if endpoint - end - - def restrict_modification - if on_creation? - errors.add(:base, "cannot modify during creation") - return false - end - - true - end - end -end diff --git a/app/models/project.rb b/app/models/project.rb index 4689b588906..bc263b63881 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -177,7 +177,9 @@ class Project < ActiveRecord::Base has_one :import_data, class_name: 'ProjectImportData', inverse_of: :project, autosave: true has_one :project_feature, inverse_of: :project has_one :statistics, class_name: 'ProjectStatistics' - has_one :cluster, class_name: 'Gcp::Cluster', inverse_of: :project + + has_many :cluster_projects, class_name: 'Clusters::ClusterProject' + has_one :cluster, through: :cluster_projects # Container repositories need to remove data from the container registry, # which is not managed by the DB. Hence we're still using dependent: :destroy -- cgit v1.2.1 From d0cff7f5855f91b5479f9fdaa39d8d95ec691a9e Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Mon, 23 Oct 2017 11:36:35 +0300 Subject: This works --- app/models/clusters/cluster.rb | 52 +++++++++++++++++------------ app/models/clusters/cluster_project.rb | 6 ---- app/models/clusters/platforms/kubernetes.rb | 39 +++++++++++++--------- app/models/clusters/project.rb | 8 +++++ app/models/clusters/providers/gcp.rb | 29 ++++++++-------- app/models/project.rb | 4 +-- 6 files changed, 77 insertions(+), 61 deletions(-) delete mode 100644 app/models/clusters/cluster_project.rb create mode 100644 app/models/clusters/project.rb (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index d7b13ac88f2..f1eedad8795 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -2,49 +2,46 @@ module Clusters class Cluster < ActiveRecord::Base include Presentable + self.table_name = 'clusters' + belongs_to :user - belongs_to :service - enum :platform_type { + enum platform_type: { kubernetes: 1 } - enum :provider_type { + enum provider_type: { user: 0, gcp: 1 } - has_many :cluster_projects - has_many :projects, through: :cluster_projects + has_many :cluster_projects, class_name: 'Clusters::Project' + has_many :projects, through: :cluster_projects, class_name: '::Project' - has_one :gcp_provider - has_one :kubernetes_platform + has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp' + has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes' - accepts_nested_attributes_for :gcp_provider - accepts_nested_attributes_for :kubernetes_platform + accepts_nested_attributes_for :provider_gcp + accepts_nested_attributes_for :platform_kubernetes - validates :kubernetes_platform, presence: true, if: :kubernetes? - validates :gcp_provider, presence: true, if: :gcp? + 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 - - def restrict_modification - if provider&.on_creation? - errors.add(:base, "cannot modify during creation") - return false - end - - true - end + delegate :status_name, to: :provider, allow_nil: true + delegate :on_creation?, to: :provider, allow_nil: true def provider - return gcp_provider if gcp? + return provider_gcp if gcp? end def platform - return kubernetes_platform if kubernetes? + return platform_kubernetes if kubernetes? + end + + def project + first_project end def first_project @@ -52,5 +49,16 @@ module Clusters @first_project = projects.first end + + private + + def restrict_modification + if provider&.on_creation? + errors.add(:base, "cannot modify during creation") + return false + end + + true + end end end diff --git a/app/models/clusters/cluster_project.rb b/app/models/clusters/cluster_project.rb deleted file mode 100644 index 7b139c2bb08..00000000000 --- a/app/models/clusters/cluster_project.rb +++ /dev/null @@ -1,6 +0,0 @@ -module Clusters - class ClusterProject < ActiveRecord::Base - belongs_to :cluster - belongs_to :project - end -end diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index aed6f733487..d9f8927f7cc 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -4,11 +4,13 @@ module Clusters include Gitlab::Kubernetes include ReactiveCaching + self.table_name = 'cluster_platforms_kubernetes' + TEMPLATE_PLACEHOLDER = 'Kubernetes namespace'.freeze - self.reactive_cache_key = ->(service) { [service.class.model_name.singular, service.project_id] } + self.reactive_cache_key = ->(kubernetes) { [kubernetes.class.model_name.singular, kubernetes.cluster_id] } - belongs_to :cluster + belongs_to :cluster, inverse_of: :platform_kubernetes, class_name: 'Clusters::Cluster' attr_encrypted :password, mode: :per_attribute_iv, @@ -28,8 +30,8 @@ module Clusters message: Gitlab::Regex.kubernetes_namespace_regex_message } - validates :api_url, url: true, presence: true - validates :token, presence: true + validates :api_url, url: true, presence: true, on: :update + validates :token, presence: true, on: :update after_save :clear_reactive_cache! @@ -53,9 +55,9 @@ module Clusters { key: 'KUBECONFIG', value: config, public: false, file: true } ] - if ca_pem.present? - variables << { key: 'KUBE_CA_PEM', value: ca_pem, public: true } - variables << { key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true } + if ca_cert.present? + variables << { key: 'KUBE_CA_PEM', value: ca_cert, public: true } + variables << { key: 'KUBE_CA_PEM_FILE', value: ca_cert, public: true, file: true } end variables @@ -76,7 +78,7 @@ module Clusters # Caches resources in the namespace so other calls don't need to block on # network access def calculate_reactive_cache - return unless active? && project && !project.pending_delete? + return unless active? && cluster.project && !cluster.project.pending_delete? # We may want to cache extra things in the future { pods: read_pods } @@ -87,15 +89,16 @@ module Clusters url: api_url, namespace: actual_namespace, token: token, - ca_pem: ca_pem) + ca_pem: ca_cert) end def namespace_placeholder default_namespace || TEMPLATE_PLACEHOLDER end - def default_namespace - "#{cluster.first_project.path}-#{cluster.first_project.id}" if cluster.first_project + def default_namespace(project = nil) + project ||= cluster&.project + "#{project.path}-#{project.id}" if project end def read_secrets @@ -120,9 +123,9 @@ module Clusters def kubeclient_ssl_options opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER } - if ca_pem.present? + if ca_cert.present? opts[:cert_store] = OpenSSL::X509::Store.new - opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem)) + opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_cert)) end opts @@ -131,7 +134,11 @@ module Clusters private def build_kubeclient!(api_path: 'api', api_version: 'v1') - raise "Incomplete settings" unless api_url && actual_namespace && token + raise "Incomplete settings" unless api_url && actual_namespace + + unless (username && password) || token + raise "Either username/password or token is required to access API" + end ::Kubeclient::Client.new( join_api_url(api_path), @@ -143,7 +150,7 @@ module Clusters end def kubeclient_auth_options - return { username: username, password: password } if username + return { username: username, password: password } if username && password return { bearer_token: token } if token end @@ -159,7 +166,7 @@ module Clusters def terminal_auth { token: token, - ca_pem: ca_pem, + ca_pem: ca_cert, max_session_time: current_application_settings.terminal_max_session_time } end diff --git a/app/models/clusters/project.rb b/app/models/clusters/project.rb new file mode 100644 index 00000000000..69088100420 --- /dev/null +++ b/app/models/clusters/project.rb @@ -0,0 +1,8 @@ +module Clusters + class Project < ActiveRecord::Base + self.table_name = 'cluster_projects' + + belongs_to :cluster, inverse_of: :projects, class_name: 'Clusters::Cluster' + belongs_to :project, inverse_of: :project, class_name: 'Project' + end +end diff --git a/app/models/clusters/providers/gcp.rb b/app/models/clusters/providers/gcp.rb index 5d4618cfe87..e4f109d2794 100644 --- a/app/models/clusters/providers/gcp.rb +++ b/app/models/clusters/providers/gcp.rb @@ -1,10 +1,12 @@ module Clusters module Providers class Gcp < ActiveRecord::Base - belongs_to :cluster + self.table_name = 'cluster_providers_gcp' - default_value_for :cluster_zone, 'us-central1-a' - default_value_for :cluster_size, 3 + belongs_to :cluster, inverse_of: :provider_gcp, class_name: 'Clusters::Cluster' + + default_value_for :zone, 'us-central1-a' + default_value_for :num_nodes, 3 default_value_for :machine_type, 'n1-standard-4' attr_encrypted :access_token, @@ -12,23 +14,16 @@ module Clusters key: Gitlab::Application.secrets.db_key_base, algorithm: 'aes-256-cbc' - validates :project_id, + validates :gcp_project_id, length: 1..63, format: { with: Gitlab::Regex.kubernetes_namespace_regex, message: Gitlab::Regex.kubernetes_namespace_regex_message } - validates :cluster_name, - length: 1..63, - format: { - with: Gitlab::Regex.kubernetes_namespace_regex, - message: Gitlab::Regex.kubernetes_namespace_regex_message - } - - validates :cluster_zone, presence: true + validates :zone, presence: true - validates :cluster_size, + validates :num_nodes, presence: true, numericality: { only_integer: true, @@ -54,9 +49,13 @@ module Clusters end before_transition any => [:errored, :created] do |provider| - provider.token = nil + provider.access_token = nil provider.operation_id = nil - provider.save! + end + + before_transition any => [:creating] do |provider, transition| + operation_id = transition.args.first + provider.operation_id = operation_id if operation_id end before_transition any => [:errored] do |provider, transition| diff --git a/app/models/project.rb b/app/models/project.rb index bc263b63881..70c75edcda3 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -178,8 +178,8 @@ class Project < ActiveRecord::Base has_one :project_feature, inverse_of: :project has_one :statistics, class_name: 'ProjectStatistics' - has_many :cluster_projects, class_name: 'Clusters::ClusterProject' - has_one :cluster, through: :cluster_projects + has_one :cluster_project, class_name: 'Clusters::Project' + has_one :cluster, 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 -- cgit v1.2.1 From 478e59fe8d82b99800a2613aa4d153bf692fbd6b Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Mon, 30 Oct 2017 03:48:45 +0900 Subject: specs for models. Improved details. --- app/models/clusters/cluster.rb | 26 +++++++-------- app/models/clusters/platforms/kubernetes.rb | 50 ++++++++++++++++------------- app/models/clusters/project.rb | 4 +-- app/models/clusters/providers/gcp.rb | 3 +- 4 files changed, 45 insertions(+), 38 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index f1eedad8795..4260fadb46d 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -6,15 +6,6 @@ module Clusters belongs_to :user - enum platform_type: { - kubernetes: 1 - } - - enum provider_type: { - user: 0, - gcp: 1 - } - has_many :cluster_projects, class_name: 'Clusters::Project' has_many :projects, through: :cluster_projects, class_name: '::Project' @@ -32,6 +23,18 @@ module Clusters delegate :status_name, to: :provider, allow_nil: true delegate :on_creation?, to: :provider, allow_nil: true + enum platform_type: { + kubernetes: 1 + } + + enum provider_type: { + user: 0, + gcp: 1 + } + + scope :enabled, -> { where(enabled: true) } + scope :disabled, -> { where(enabled: false) } + def provider return provider_gcp if gcp? end @@ -40,15 +43,12 @@ module Clusters return platform_kubernetes if kubernetes? end - def project - first_project - end - def first_project return @first_project if defined?(@first_project) @first_project = projects.first end + alias_method :project, :first_project private diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index d9f8927f7cc..b20b00ff51b 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -1,13 +1,11 @@ module Clusters module Platforms class Kubernetes < ActiveRecord::Base + include Gitlab::CurrentSettings include Gitlab::Kubernetes include ReactiveCaching self.table_name = 'cluster_platforms_kubernetes' - - TEMPLATE_PLACEHOLDER = 'Kubernetes namespace'.freeze - self.reactive_cache_key = ->(kubernetes) { [kubernetes.class.model_name.singular, kubernetes.cluster_id] } belongs_to :cluster, inverse_of: :platform_kubernetes, class_name: 'Clusters::Cluster' @@ -22,6 +20,8 @@ module Clusters key: Gitlab::Application.secrets.db_key_base, algorithm: 'aes-256-cbc' + before_validation :enforce_namespace_to_lower_case + validates :namespace, allow_blank: true, length: 1..63, @@ -34,8 +34,19 @@ module Clusters validates :token, presence: true, on: :update after_save :clear_reactive_cache! - - before_validation :enforce_namespace_to_lower_case + + alias_attribute :ca_pem, :ca_cert + + delegate :project, to: :cluster, allow_nil: true + delegate :enabled?, to: :cluster, allow_nil: true + + alias_method :active?, :enabled? + + class << self + def namespace_for_project(project) + "#{project.path}-#{project.id}" + end + end def actual_namespace if namespace.present? @@ -45,6 +56,10 @@ module Clusters end end + def default_namespace + self.class.namespace_for_project(project) if project + end + def predefined_variables config = YAML.dump(kubeconfig) @@ -55,9 +70,9 @@ module Clusters { key: 'KUBECONFIG', value: config, public: false, file: true } ] - if ca_cert.present? - variables << { key: 'KUBE_CA_PEM', value: ca_cert, public: true } - variables << { key: 'KUBE_CA_PEM_FILE', value: ca_cert, public: true, file: true } + if ca_pem.present? + variables << { key: 'KUBE_CA_PEM', value: ca_pem, public: true } + variables << { key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true } end variables @@ -78,7 +93,7 @@ module Clusters # Caches resources in the namespace so other calls don't need to block on # network access def calculate_reactive_cache - return unless active? && cluster.project && !cluster.project.pending_delete? + return unless active? && project && !project.pending_delete? # We may want to cache extra things in the future { pods: read_pods } @@ -89,16 +104,7 @@ module Clusters url: api_url, namespace: actual_namespace, token: token, - ca_pem: ca_cert) - end - - def namespace_placeholder - default_namespace || TEMPLATE_PLACEHOLDER - end - - def default_namespace(project = nil) - project ||= cluster&.project - "#{project.path}-#{project.id}" if project + ca_pem: ca_pem) end def read_secrets @@ -123,9 +129,9 @@ module Clusters def kubeclient_ssl_options opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER } - if ca_cert.present? + if ca_pem.present? opts[:cert_store] = OpenSSL::X509::Store.new - opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_cert)) + opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem)) end opts @@ -166,7 +172,7 @@ module Clusters def terminal_auth { token: token, - ca_pem: ca_cert, + ca_pem: ca_pem, max_session_time: current_application_settings.terminal_max_session_time } end diff --git a/app/models/clusters/project.rb b/app/models/clusters/project.rb index 69088100420..eeb734b20b8 100644 --- a/app/models/clusters/project.rb +++ b/app/models/clusters/project.rb @@ -2,7 +2,7 @@ module Clusters class Project < ActiveRecord::Base self.table_name = 'cluster_projects' - belongs_to :cluster, inverse_of: :projects, class_name: 'Clusters::Cluster' - belongs_to :project, inverse_of: :project, class_name: 'Project' + belongs_to :cluster, class_name: 'Clusters::Cluster' + belongs_to :project, class_name: '::Project' end end diff --git a/app/models/clusters/providers/gcp.rb b/app/models/clusters/providers/gcp.rb index e4f109d2794..7700ba86f1a 100644 --- a/app/models/clusters/providers/gcp.rb +++ b/app/models/clusters/providers/gcp.rb @@ -55,7 +55,8 @@ module Clusters before_transition any => [:creating] do |provider, transition| operation_id = transition.args.first - provider.operation_id = operation_id if operation_id + raise 'operation_id is required' unless operation_id + provider.operation_id = operation_id end before_transition any => [:errored] do |provider, transition| -- cgit v1.2.1 From d6744d98384192799c9b3a97ad0eaf69cb4d25ee Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Mon, 30 Oct 2017 21:55:18 +0900 Subject: specs for services. Improved details. --- app/models/clusters/cluster.rb | 2 +- app/models/clusters/platforms/kubernetes.rb | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 4260fadb46d..7af56adb613 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -13,7 +13,7 @@ module Clusters has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes' accepts_nested_attributes_for :provider_gcp - accepts_nested_attributes_for :platform_kubernetes + accepts_nested_attributes_for :platform_kubernetes, update_only: true validates :name, cluster_name: true validate :restrict_modification, on: :update diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index b20b00ff51b..1a4e293be65 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -111,9 +111,6 @@ module Clusters kubeclient = build_kubeclient! kubeclient.get_secrets.as_json - rescue KubeException => err - raise err unless err.error_code == 404 - [] end # Returns a hash of all pods in the namespace -- cgit v1.2.1 From 6a65e2f5f94781a69f3f7fb329483ead6bc81fd9 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Tue, 31 Oct 2017 17:47:48 +0900 Subject: specs for controller. Improved validation --- app/models/clusters/cluster.rb | 6 ++++-- app/models/clusters/platforms/kubernetes.rb | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 7af56adb613..091c91e3fb9 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -10,11 +10,13 @@ module Clusters has_many :projects, through: :cluster_projects, class_name: '::Project' has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp' - has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes' + has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes', validate: { if: :update } - accepts_nested_attributes_for :provider_gcp + accepts_nested_attributes_for :provider_gcp, update_only: true accepts_nested_attributes_for :platform_kubernetes, update_only: true + validates :provider_type, presence: true + validates :platform_type, presence: true validates :name, cluster_name: true validate :restrict_modification, on: :update diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 1a4e293be65..52022509d49 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -30,8 +30,8 @@ module Clusters message: Gitlab::Regex.kubernetes_namespace_regex_message } - validates :api_url, url: true, presence: true, on: :update - validates :token, presence: true, on: :update + validates :api_url, url: true, presence: true + validates :token, presence: true after_save :clear_reactive_cache! -- cgit v1.2.1 From 253bf69dda460869741bc6c9d864c789055b8013 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 1 Nov 2017 03:59:40 +0900 Subject: specs for feature --- app/models/clusters/cluster.rb | 2 +- app/models/clusters/platforms/kubernetes.rb | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 091c91e3fb9..177403dcf00 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -10,7 +10,7 @@ module Clusters has_many :projects, through: :cluster_projects, class_name: '::Project' has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp' - has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes', validate: { if: :update } + has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes' accepts_nested_attributes_for :provider_gcp, update_only: true accepts_nested_attributes_for :platform_kubernetes, update_only: true diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 52022509d49..e30ab805f1e 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -30,8 +30,10 @@ module Clusters message: Gitlab::Regex.kubernetes_namespace_regex_message } - validates :api_url, url: true, presence: true - validates :token, presence: true + # TODO: when cluster.gcp? skip validation when create a record + # TODO: when cluster.user? validates always + # validates :api_url, url: true, presence: true + # validates :token, presence: true after_save :clear_reactive_cache! -- cgit v1.2.1 From 6571efb6c3afd568c019e7bb46aba84328a4e821 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 1 Nov 2017 16:12:44 +0900 Subject: Fix spec. Fix usage ping. Fix warnings by adding new models and attributes. --- app/models/clusters/platforms/kubernetes.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index e30ab805f1e..52022509d49 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -30,10 +30,8 @@ module Clusters message: Gitlab::Regex.kubernetes_namespace_regex_message } - # TODO: when cluster.gcp? skip validation when create a record - # TODO: when cluster.user? validates always - # validates :api_url, url: true, presence: true - # validates :token, presence: true + validates :api_url, url: true, presence: true + validates :token, presence: true after_save :clear_reactive_cache! -- cgit v1.2.1 From ccf09824f6d3ef41db4be3b40aa99b6dfd0dc9ac Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 1 Nov 2017 12:57:05 +0100 Subject: Slim down Platforms::Kubernetes, and instead make it instrument KubernetesService --- app/models/clusters/cluster.rb | 7 +- app/models/clusters/platforms/kubernetes.rb | 141 +++++++--------------------- 2 files changed, 38 insertions(+), 110 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 177403dcf00..a3f6d20ba43 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -9,8 +9,11 @@ module Clusters has_many :cluster_projects, class_name: 'Clusters::Project' has_many :projects, through: :cluster_projects, class_name: '::Project' - has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp' - has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes' + # we force autosave to happen when we save `Cluster` model + has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp', autosave: true + + # 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 accepts_nested_attributes_for :provider_gcp, update_only: true accepts_nested_attributes_for :platform_kubernetes, update_only: true diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 52022509d49..4c3e270892e 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -2,11 +2,8 @@ module Clusters module Platforms class Kubernetes < ActiveRecord::Base include Gitlab::CurrentSettings - include Gitlab::Kubernetes - include ReactiveCaching self.table_name = 'cluster_platforms_kubernetes' - self.reactive_cache_key = ->(kubernetes) { [kubernetes.class.model_name.singular, kubernetes.cluster_id] } belongs_to :cluster, inverse_of: :platform_kubernetes, class_name: 'Clusters::Cluster' @@ -30,17 +27,24 @@ module Clusters message: Gitlab::Regex.kubernetes_namespace_regex_message } - validates :api_url, url: true, presence: true - validates :token, presence: true + # We expect to be `active?` only when enabled and cluster is created (the api_url is assigned) + with_options presence: true, if: :active? do + validates :api_url, url: true, presence: true + validates :token, presence: true + end - after_save :clear_reactive_cache! + # TODO: Glue code till we migrate Kubernetes Integration into Platforms::Kubernetes + after_save :update_kubernetes_integration! + after_destroy :destroy_kubernetes_integration! alias_attribute :ca_pem, :ca_cert delegate :project, to: :cluster, allow_nil: true delegate :enabled?, to: :cluster, allow_nil: true - alias_method :active?, :enabled? + def active? + enabled? && api_url.present? + end class << self def namespace_for_project(project) @@ -60,122 +64,43 @@ module Clusters self.class.namespace_for_project(project) if project end - def predefined_variables - config = YAML.dump(kubeconfig) - - variables = [ - { key: 'KUBE_URL', value: api_url, public: true }, - { key: 'KUBE_TOKEN', value: token, public: false }, - { key: 'KUBE_NAMESPACE', value: actual_namespace, public: true }, - { key: 'KUBECONFIG', value: config, public: false, file: true } - ] - - if ca_pem.present? - variables << { key: 'KUBE_CA_PEM', value: ca_pem, public: true } - variables << { key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true } - end - - variables - end - - # Constructs a list of terminals from the reactive cache - # - # Returns nil if the cache is empty, in which case you should try again a - # short time later - def terminals(environment) - with_reactive_cache do |data| - pods = filter_by_label(data[:pods], app: environment.slug) - terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) } - terminals.each { |terminal| add_terminal_auth(terminal, terminal_auth) } - end - end - - # Caches resources in the namespace so other calls don't need to block on - # network access - def calculate_reactive_cache - return unless active? && project && !project.pending_delete? - - # We may want to cache extra things in the future - { pods: read_pods } - end - - def kubeconfig - to_kubeconfig( - url: api_url, - namespace: actual_namespace, - token: token, - ca_pem: ca_pem) - end - - def read_secrets - kubeclient = build_kubeclient! + private - kubeclient.get_secrets.as_json + def enforce_namespace_to_lower_case + self.namespace = self.namespace&.downcase end - # Returns a hash of all pods in the namespace - def read_pods - kubeclient = build_kubeclient! + # TODO: glue code till we migrate Kubernetes Service into Platforms::Kubernetes class + def manages_kubernetes_service? + return true unless kubernetes_service&.active? - kubeclient.get_pods(namespace: actual_namespace).as_json - rescue KubeException => err - raise err unless err.error_code == 404 - [] + kubernetes_service.api_url == api_url end - def kubeclient_ssl_options - opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER } - - if ca_pem.present? - opts[:cert_store] = OpenSSL::X509::Store.new - opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem)) - end + def destroy_kubernetes_integration! + return unless manages_kubernetes_service? - opts + kubernetes_service.destroy! end - private - - def build_kubeclient!(api_path: 'api', api_version: 'v1') - raise "Incomplete settings" unless api_url && actual_namespace + def update_kubernetes_integration! + return raise 'Kubernetes service already configured' unless manages_kubernetes_service? - unless (username && password) || token - raise "Either username/password or token is required to access API" - end - - ::Kubeclient::Client.new( - join_api_url(api_path), - api_version, - auth_options: kubeclient_auth_options, - ssl_options: kubeclient_ssl_options, - http_proxy_uri: ENV['http_proxy'] + ensure_kubernetes_service.update!( + active: active?, + api_url: api_url, + namespace: namespace, + token: token, + ca_pem: ca_cert, ) end - def kubeclient_auth_options - return { username: username, password: password } if username && password - return { bearer_token: token } if token - end - - def join_api_url(api_path) - url = URI.parse(api_url) - prefix = url.path.sub(%r{/+\z}, '') - - url.path = [prefix, api_path].join("/") - - url.to_s + def kubernetes_service + @kubernetes_service ||= project.kubernetes_service || project.build_kubernetes_service end - def terminal_auth - { - token: token, - ca_pem: ca_pem, - max_session_time: current_application_settings.terminal_max_session_time - } - end - - def enforce_namespace_to_lower_case - self.namespace = self.namespace&.downcase + def ensure_kubernetes_service + @kubernetes_service ||= kubernetes_service || project.build_kubernetes_service end end end -- cgit v1.2.1 From 1427bdcadf5f4026d141a5c4e93db8b1b00fe40a Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 1 Nov 2017 13:56:27 +0100 Subject: Revert back FetchKubernetesTokenService --- app/models/clusters/cluster.rb | 2 -- app/models/clusters/platforms/kubernetes.rb | 8 ++------ 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index a3f6d20ba43..ca09b939f34 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -18,8 +18,6 @@ module Clusters accepts_nested_attributes_for :provider_gcp, update_only: true accepts_nested_attributes_for :platform_kubernetes, update_only: true - validates :provider_type, presence: true - validates :platform_type, presence: true validates :name, cluster_name: true validate :restrict_modification, on: :update diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 4c3e270892e..3ad2ffe531d 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -28,7 +28,7 @@ module Clusters } # We expect to be `active?` only when enabled and cluster is created (the api_url is assigned) - with_options presence: true, if: :active? do + with_options presence: true, if: :enabled? do validates :api_url, url: true, presence: true validates :token, presence: true end @@ -42,10 +42,6 @@ module Clusters delegate :project, to: :cluster, allow_nil: true delegate :enabled?, to: :cluster, allow_nil: true - def active? - enabled? && api_url.present? - end - class << self def namespace_for_project(project) "#{project.path}-#{project.id}" @@ -87,7 +83,7 @@ module Clusters return raise 'Kubernetes service already configured' unless manages_kubernetes_service? ensure_kubernetes_service.update!( - active: active?, + active: enabled?, api_url: api_url, namespace: namespace, token: token, -- cgit v1.2.1 From 6950f38f830079199c382c974b51ad73048a6939 Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Thu, 2 Nov 2017 11:14:10 +0100 Subject: Install k8s application with helm running inside the cluster --- app/models/clusters/concerns.rb | 4 +++ app/models/clusters/concerns/app_status.rb | 33 +++++++++++++++++++++++ app/models/clusters/kubernetes.rb | 16 +++++++++++ app/models/clusters/kubernetes/helm_app.rb | 18 +++++++++++++ app/models/project_services/kubernetes_service.rb | 6 +++++ 5 files changed, 77 insertions(+) create mode 100644 app/models/clusters/concerns.rb create mode 100644 app/models/clusters/concerns/app_status.rb create mode 100644 app/models/clusters/kubernetes.rb create mode 100644 app/models/clusters/kubernetes/helm_app.rb (limited to 'app/models') diff --git a/app/models/clusters/concerns.rb b/app/models/clusters/concerns.rb new file mode 100644 index 00000000000..cd09863bcfc --- /dev/null +++ b/app/models/clusters/concerns.rb @@ -0,0 +1,4 @@ +module Clusters + module Concerns + end +end diff --git a/app/models/clusters/concerns/app_status.rb b/app/models/clusters/concerns/app_status.rb new file mode 100644 index 00000000000..f6b817e9ce7 --- /dev/null +++ b/app/models/clusters/concerns/app_status.rb @@ -0,0 +1,33 @@ +module Clusters + module Concerns + module AppStatus + extend ActiveSupport::Concern + + included do + state_machine :status, initial: :scheduled do + state :errored, value: -1 + state :scheduled, value: 0 + state :installing, value: 1 + state :installed, value: 2 + + event :make_installing do + transition any - [:installing] => :installing + end + + event :make_installed do + transition any - [:installed] => :installed + end + + event :make_errored do + transition any - [:errored] => :errored + end + + before_transition any => [:errored] do |app_status, transition| + status_reason = transition.args.first + app_status.status_reason = status_reason if status_reason + end + end + end + end + end +end diff --git a/app/models/clusters/kubernetes.rb b/app/models/clusters/kubernetes.rb new file mode 100644 index 00000000000..b68e2ae401e --- /dev/null +++ b/app/models/clusters/kubernetes.rb @@ -0,0 +1,16 @@ +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/kubernetes/helm_app.rb b/app/models/clusters/kubernetes/helm_app.rb new file mode 100644 index 00000000000..32c9e13a469 --- /dev/null +++ b/app/models/clusters/kubernetes/helm_app.rb @@ -0,0 +1,18 @@ +module Clusters + module Kubernetes + class HelmApp < ActiveRecord::Base + 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 + + alias_method :cluster, :kubernetes_service + + def name + NAME + end + end + end +end diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb index 8ba07173c74..4b754b4d3ce 100644 --- a/app/models/project_services/kubernetes_service.rb +++ b/app/models/project_services/kubernetes_service.rb @@ -3,6 +3,8 @@ 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 @@ -136,6 +138,10 @@ class KubernetesService < DeploymentService { pods: read_pods } end + def helm + Gitlab::Clusters::Helm.new(build_kubeclient!) + end + TEMPLATE_PLACEHOLDER = 'Kubernetes namespace'.freeze private -- cgit v1.2.1 From 64be8d70ae20928df351e495a3442bb6036bc3e7 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 2 Nov 2017 15:10:46 +0100 Subject: Improve backend structure of data --- app/models/clusters/applications/helm.rb | 19 +++++++++++++++++++ app/models/clusters/cluster.rb | 19 ++++++++++++++++++- app/models/clusters/kubernetes.rb | 16 ---------------- app/models/clusters/kubernetes/helm_app.rb | 18 ------------------ app/models/clusters/platforms/kubernetes.rb | 4 ++++ app/models/project.rb | 1 + app/models/project_services/kubernetes_service.rb | 6 ++---- 7 files changed, 44 insertions(+), 39 deletions(-) create mode 100644 app/models/clusters/applications/helm.rb delete mode 100644 app/models/clusters/kubernetes.rb delete mode 100644 app/models/clusters/kubernetes/helm_app.rb (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb new file mode 100644 index 00000000000..59e0076c8df --- /dev/null +++ b/app/models/clusters/applications/helm.rb @@ -0,0 +1,19 @@ +module Clusters + module Applications + class Helm < ActiveRecord::Base + self.table_name = 'clusters_applications_helm' + + NAME = 'helm'.freeze + + include ::Clusters::Concerns::AppStatus + + belongs_to :cluser, class_name: 'Clusters::Cluster', foreign_key: :cluster_id + + default_value_for :version, Gitlab::Clusters::Helm::HELM_VERSION + + def name + NAME + end + end + end +end 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/kubernetes/helm_app.rb b/app/models/clusters/kubernetes/helm_app.rb deleted file mode 100644 index 32c9e13a469..00000000000 --- a/app/models/clusters/kubernetes/helm_app.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Clusters - module Kubernetes - class HelmApp < ActiveRecord::Base - 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 - - alias_method :cluster, :kubernetes_service - - def name - 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 -- cgit v1.2.1 From b129f06733c7994fb81cef4d0bae6d6611647a83 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 2 Nov 2017 23:19:11 +0900 Subject: Fix out of sync with KubernetesService. Remove namespace pramas from controller. Use time_with_zone in schema. Remove Gcp::Clusters from safe_model_attributes.ym --- app/models/clusters/cluster.rb | 6 +++++ app/models/clusters/platforms/kubernetes.rb | 37 +++++++++++++---------------- 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index ca09b939f34..955dba51745 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -21,10 +21,16 @@ module Clusters validates :name, cluster_name: true validate :restrict_modification, on: :update + # TODO: Move back this into Clusters::Platforms::Kubernetes in 10.3 + # We need callback here because `enabled` belongs to Clusters::Cluster + # Callbacks in Clusters::Platforms::Kubernetes will not be called after update + after_save :update_kubernetes_integration! + 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 + delegate :update_kubernetes_integration!, to: :platform, allow_nil: true enum platform_type: { kubernetes: 1 diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 3ad2ffe531d..8b00f1dac0b 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -1,8 +1,6 @@ module Clusters module Platforms class Kubernetes < ActiveRecord::Base - include Gitlab::CurrentSettings - self.table_name = 'cluster_platforms_kubernetes' belongs_to :cluster, inverse_of: :platform_kubernetes, class_name: 'Clusters::Cluster' @@ -28,13 +26,10 @@ module Clusters } # We expect to be `active?` only when enabled and cluster is created (the api_url is assigned) - with_options presence: true, if: :enabled? do - validates :api_url, url: true, presence: true - validates :token, presence: true - end + validates :api_url, url: true, presence: true + validates :token, presence: true # TODO: Glue code till we migrate Kubernetes Integration into Platforms::Kubernetes - after_save :update_kubernetes_integration! after_destroy :destroy_kubernetes_integration! alias_attribute :ca_pem, :ca_cert @@ -60,6 +55,18 @@ module Clusters self.class.namespace_for_project(project) if project end + def update_kubernetes_integration! + raise 'Kubernetes service already configured' unless manages_kubernetes_service? + + ensure_kubernetes_service.update!( + active: enabled?, + api_url: api_url, + namespace: namespace, + token: token, + ca_pem: ca_cert + ) + end + private def enforce_namespace_to_lower_case @@ -79,24 +86,12 @@ module Clusters kubernetes_service.destroy! end - def update_kubernetes_integration! - return raise 'Kubernetes service already configured' unless manages_kubernetes_service? - - ensure_kubernetes_service.update!( - active: enabled?, - api_url: api_url, - namespace: namespace, - token: token, - ca_pem: ca_cert, - ) - end - def kubernetes_service - @kubernetes_service ||= project.kubernetes_service || project.build_kubernetes_service + @kubernetes_service ||= project&.kubernetes_service end def ensure_kubernetes_service - @kubernetes_service ||= kubernetes_service || project.build_kubernetes_service + @kubernetes_service ||= kubernetes_service || project&.build_kubernetes_service end end end -- cgit v1.2.1 From 30938b898c5415d8ec5cdf6c9851c45c1464c1a0 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 2 Nov 2017 15:31:25 +0100 Subject: Fix and add applications controller --- app/models/clusters/applications/helm.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 59e0076c8df..a18a3f87bc4 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -7,7 +7,7 @@ module Clusters include ::Clusters::Concerns::AppStatus - belongs_to :cluser, class_name: 'Clusters::Cluster', foreign_key: :cluster_id + belongs_to :cluster, class_name: 'Clusters::Cluster', foreign_key: :cluster_id default_value_for :version, Gitlab::Clusters::Helm::HELM_VERSION -- cgit v1.2.1 From 31c256c154e7a8727de9e91b1353b9740f380dd8 Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Thu, 2 Nov 2017 16:57:18 +0100 Subject: General cleanup --- app/models/clusters/applications/helm.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index a18a3f87bc4..c35db143205 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -9,7 +9,7 @@ module Clusters belongs_to :cluster, class_name: 'Clusters::Cluster', foreign_key: :cluster_id - default_value_for :version, Gitlab::Clusters::Helm::HELM_VERSION + default_value_for :version, Gitlab::Kubernetes::Helm::HELM_VERSION def name NAME -- cgit v1.2.1 From a8d7e4bcb13e24426a531ef37d573e24d2547b81 Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Thu, 2 Nov 2017 17:08:56 +0100 Subject: Fix rubocop offenses --- app/models/clusters/cluster.rb | 2 +- app/models/clusters/platforms/kubernetes.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index c814f475adf..4513dd426e2 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -6,7 +6,7 @@ module Clusters APPLICATIONS = { Clusters::Applications::Helm::NAME => Clusters::Applications::Helm - } + }.freeze belongs_to :user diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 1197dfaefcb..0bb2972f7b7 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -91,7 +91,7 @@ module Clusters api_url: api_url, namespace: namespace, token: token, - ca_pem: ca_cert, + ca_pem: ca_cert ) end -- cgit v1.2.1 From 4d0a700da09be50291e40a11975b56f74051405b Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 2 Nov 2017 17:57:50 +0100 Subject: Expose applications as array via API --- app/models/clusters/applications/helm.rb | 2 +- app/models/clusters/cluster.rb | 6 ++++ app/models/clusters/concerns/app_status.rb | 33 --------------------- app/models/clusters/concerns/application_status.rb | 34 ++++++++++++++++++++++ 4 files changed, 41 insertions(+), 34 deletions(-) delete mode 100644 app/models/clusters/concerns/app_status.rb create mode 100644 app/models/clusters/concerns/application_status.rb (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index c35db143205..77c0c61d968 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -5,7 +5,7 @@ module Clusters NAME = 'helm'.freeze - include ::Clusters::Concerns::AppStatus + include ::Clusters::Concerns::ApplicationStatus belongs_to :cluster, class_name: 'Clusters::Cluster', foreign_key: :cluster_id diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 4513dd426e2..3fd8ffb6e92 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -51,6 +51,12 @@ module Clusters end end + def applications + [ + application_helm || build_application_helm + ] + end + def provider return provider_gcp if gcp? end diff --git a/app/models/clusters/concerns/app_status.rb b/app/models/clusters/concerns/app_status.rb deleted file mode 100644 index f6b817e9ce7..00000000000 --- a/app/models/clusters/concerns/app_status.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Clusters - module Concerns - module AppStatus - extend ActiveSupport::Concern - - included do - state_machine :status, initial: :scheduled do - state :errored, value: -1 - state :scheduled, value: 0 - state :installing, value: 1 - state :installed, value: 2 - - event :make_installing do - transition any - [:installing] => :installing - end - - event :make_installed do - transition any - [:installed] => :installed - end - - event :make_errored do - transition any - [:errored] => :errored - end - - before_transition any => [:errored] do |app_status, transition| - status_reason = transition.args.first - app_status.status_reason = status_reason if status_reason - end - end - end - end - end -end diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb new file mode 100644 index 00000000000..e1f4c7fdda8 --- /dev/null +++ b/app/models/clusters/concerns/application_status.rb @@ -0,0 +1,34 @@ +module Clusters + module Concerns + module ApplicationStatus + extend ActiveSupport::Concern + + included do + state_machine :status, initial: :installable do + state :errored, value: -1 + state :installable, value: 0 + state :scheduled, value: 1 + state :installing, value: 2 + state :installed, value: 3 + + event :make_installing do + transition any - [:installing] => :installing + end + + event :make_installed do + transition any - [:installed] => :installed + end + + event :make_errored do + transition any - [:errored] => :errored + end + + before_transition any => [:errored] do |app_status, transition| + status_reason = transition.args.first + app_status.status_reason = status_reason if status_reason + end + end + end + end + end +end -- cgit v1.2.1 From 3602c0b9874c6b93e6cf55e1cb0238951784604d Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 3 Nov 2017 03:37:32 +0900 Subject: Fix some tests --- app/models/clusters/platforms/kubernetes.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 8b00f1dac0b..a33534da8bb 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -58,7 +58,7 @@ module Clusters def update_kubernetes_integration! raise 'Kubernetes service already configured' unless manages_kubernetes_service? - ensure_kubernetes_service.update!( + ensure_kubernetes_service&.update!( active: enabled?, api_url: api_url, namespace: namespace, @@ -83,7 +83,7 @@ module Clusters def destroy_kubernetes_integration! return unless manages_kubernetes_service? - kubernetes_service.destroy! + kubernetes_service&.destroy! end def kubernetes_service -- cgit v1.2.1 From 4477f7bb5925d8d720e3e8272bd882fffcc04b28 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 3 Nov 2017 09:22:11 +0100 Subject: Fix nitpicks --- app/models/clusters/cluster.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 3fd8ffb6e92..7dae2234998 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -27,8 +27,8 @@ module Clusters 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 enum platform_type: { -- cgit v1.2.1 From 600d5f4fba4f73ef438db651d20da92080e5b3b0 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 3 Nov 2017 17:22:49 +0900 Subject: Fix tests. Remove NOT NULL constraint from cluster.user. --- app/models/clusters/platforms/kubernetes.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app/models') diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index a33534da8bb..b11701797c2 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -58,6 +58,9 @@ module Clusters def update_kubernetes_integration! raise 'Kubernetes service already configured' unless manages_kubernetes_service? + # This is neccesary, otheriwse enabled? returns true even though cluster updated with enabled: false + cluster.reload + ensure_kubernetes_service&.update!( active: enabled?, api_url: api_url, -- cgit v1.2.1 From c46417c5064867d72debb15c4e280db24c6ab73c Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Thu, 2 Nov 2017 18:55:02 +0100 Subject: Rename App to Applications --- app/models/clusters/concerns.rb | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 app/models/clusters/concerns.rb (limited to 'app/models') diff --git a/app/models/clusters/concerns.rb b/app/models/clusters/concerns.rb deleted file mode 100644 index cd09863bcfc..00000000000 --- a/app/models/clusters/concerns.rb +++ /dev/null @@ -1,4 +0,0 @@ -module Clusters - module Concerns - end -end -- cgit v1.2.1 From 08752e5d742a144ffb1ec7c8e07e7a558774fbfc Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Fri, 3 Nov 2017 10:02:30 +0100 Subject: Remove `Clusters::Applications::FetchInstallationStatusService` --- app/models/clusters/cluster.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 7dae2234998..77b299e46a0 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -52,7 +52,7 @@ module Clusters end def applications - [ + [ application_helm || build_application_helm ] end -- cgit v1.2.1 From 49210dfff12ba0fba5fdbcdc2c485fbbde43f83f Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Fri, 3 Nov 2017 11:10:50 +0100 Subject: Schedule k8s application installation with a service --- app/models/clusters/applications/helm.rb | 2 ++ app/models/clusters/concerns/application_status.rb | 8 ++++++++ 2 files changed, 10 insertions(+) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 77c0c61d968..54eca613ce3 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -11,6 +11,8 @@ module Clusters default_value_for :version, Gitlab::Kubernetes::Helm::HELM_VERSION + validates :cluster, presence: true + def name NAME end diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index e1f4c7fdda8..c5711fd0b58 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -23,6 +23,14 @@ module Clusters transition any - [:errored] => :errored end + event :make_scheduled do + transition %i(installable errored) => :scheduled + end + + before_transition any => [:scheduled] do |app_status, _| + app_status.status_reason = nil + end + before_transition any => [:errored] do |app_status, transition| status_reason = transition.args.first app_status.status_reason = status_reason if status_reason -- cgit v1.2.1 From cd88fa8f80710ec977a85ab8701570073c94f017 Mon Sep 17 00:00:00 2001 From: "micael.bergeron" Date: Wed, 1 Nov 2017 10:31:35 -0400 Subject: removed the #ensure_ref_fetched from all controllers also, I refactored the MergeRequest#fetch_ref method to express the side-effect that this method has. MergeRequest#fetch_ref -> MergeRequest#fetch_ref! Repository#fetch_source_branch -> Repository#fetch_source_branch! --- app/models/merge_request.rb | 27 +++------------------------ app/models/repository.rb | 4 ++-- 2 files changed, 5 insertions(+), 26 deletions(-) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 3133dc9e7eb..ccad8e102aa 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -426,7 +426,7 @@ class MergeRequest < ActiveRecord::Base end def create_merge_request_diff - fetch_ref + fetch_ref! # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/37435 Gitlab::GitalyClient.allow_n_plus_1_calls do @@ -811,29 +811,14 @@ class MergeRequest < ActiveRecord::Base end end - def fetch_ref - write_ref - update_column(:ref_fetched, true) + def fetch_ref! + target_project.repository.fetch_source_branch!(source_project.repository, source_branch, ref_path) end def ref_path "refs/#{Repository::REF_MERGE_REQUEST}/#{iid}/head" end - def ref_fetched? - super || - begin - computed_value = project.repository.ref_exists?(ref_path) - update_column(:ref_fetched, true) if computed_value - - computed_value - end - end - - def ensure_ref_fetched - fetch_ref unless ref_fetched? - end - def in_locked_state begin lock_mr @@ -975,10 +960,4 @@ class MergeRequest < ActiveRecord::Base project.merge_requests.merged.where(author_id: author_id).empty? end - - private - - def write_ref - target_project.repository.fetch_source_branch(source_project.repository, source_branch, ref_path) - end end diff --git a/app/models/repository.rb b/app/models/repository.rb index 44a1e9ce529..3b6285f786d 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -982,8 +982,8 @@ class Repository gitlab_shell.fetch_remote(raw_repository, remote, forced: forced, no_tags: no_tags) end - def fetch_source_branch(source_repository, source_branch, local_ref) - raw_repository.fetch_source_branch(source_repository.raw_repository, source_branch, local_ref) + def fetch_source_branch!(source_repository, source_branch, local_ref) + raw_repository.fetch_source_branch!(source_repository.raw_repository, source_branch, local_ref) end def compare_source_branch(target_branch_name, source_repository, source_branch_name, straight:) -- cgit v1.2.1 From c6c9b37b1d1c9304b0eef530adb4d32178adae16 Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Fri, 3 Nov 2017 19:20:29 +0100 Subject: Add Clusters::Applications::Helm tests --- app/models/clusters/applications/helm.rb | 8 +++++--- app/models/clusters/cluster.rb | 2 +- app/models/clusters/concerns/application_status.rb | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 54eca613ce3..42626a50175 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -3,8 +3,6 @@ module Clusters class Helm < ActiveRecord::Base self.table_name = 'clusters_applications_helm' - NAME = 'helm'.freeze - include ::Clusters::Concerns::ApplicationStatus belongs_to :cluster, class_name: 'Clusters::Cluster', foreign_key: :cluster_id @@ -13,8 +11,12 @@ module Clusters validates :cluster, presence: true + def self.application_name + self.to_s.demodulize.underscore + end + def name - NAME + self.class.application_name end end end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 242bae4eb3e..7d0be3d3739 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -5,7 +5,7 @@ module Clusters self.table_name = 'clusters' APPLICATIONS = { - Clusters::Applications::Helm::NAME => Clusters::Applications::Helm + Applications::Helm.application_name => Applications::Helm }.freeze belongs_to :user diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index c5711fd0b58..7bb68d75224 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -24,7 +24,7 @@ module Clusters end event :make_scheduled do - transition %i(installable errored) => :scheduled + transition any - [:scheduled] => :scheduled end before_transition any => [:scheduled] do |app_status, _| -- cgit v1.2.1 From d8223468ae2ae061020cc26336c51dc93cc75571 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 6 Nov 2017 10:41:27 +0100 Subject: Add ingress application --- app/models/clusters/applications/ingress.rb | 32 +++++++++++++++++++++++++++++ app/models/clusters/cluster.rb | 7 +++++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 app/models/clusters/applications/ingress.rb (limited to 'app/models') diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb new file mode 100644 index 00000000000..0554cf84ed7 --- /dev/null +++ b/app/models/clusters/applications/ingress.rb @@ -0,0 +1,32 @@ +module Clusters + module Applications + class Ingress < ActiveRecord::Base + self.table_name = 'clusters_applications_ingress' + + include ::Clusters::Concerns::ApplicationStatus + + belongs_to :cluster, class_name: 'Clusters::Cluster', foreign_key: :cluster_id + + validates :cluster, presence: true + + default_value_for :ingress_type, :nginx + default_value_for :version, :nginx + + enum ingress_type: { + nginx: 1 + } + + def self.application_name + self.to_s.demodulize.underscore + end + + def name + self.class.application_name + end + + def chart + 'stable/nginx-ingress' + end + end + end +end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 7d0be3d3739..cfed9c52860 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -5,7 +5,8 @@ module Clusters self.table_name = 'clusters' APPLICATIONS = { - Applications::Helm.application_name => Applications::Helm + Applications::Helm.application_name => Applications::Helm, + Applications::Ingress.application_name => Applications::Ingress }.freeze belongs_to :user @@ -20,6 +21,7 @@ module Clusters 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' + has_one :application_ingress, class_name: 'Clusters::Applications::Ingress' accepts_nested_attributes_for :provider_gcp, update_only: true accepts_nested_attributes_for :platform_kubernetes, update_only: true @@ -59,7 +61,8 @@ module Clusters def applications [ - application_helm || build_application_helm + application_helm || build_application_helm, + application_ingress || build_application_ingress ] end -- cgit v1.2.1 From 6902848a9c54f9eb1bfd82fe173ad0d5d62fe2d5 Mon Sep 17 00:00:00 2001 From: Markus Koller Date: Mon, 18 Sep 2017 15:03:24 +0200 Subject: Support custom attributes on projects --- app/models/project.rb | 1 + app/models/project_custom_attribute.rb | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 app/models/project_custom_attribute.rb (limited to 'app/models') diff --git a/app/models/project.rb b/app/models/project.rb index b04aec550b1..38ac7b20b05 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -213,6 +213,7 @@ class Project < ActiveRecord::Base has_many :active_runners, -> { active }, through: :runner_projects, source: :runner, class_name: 'Ci::Runner' has_one :auto_devops, class_name: 'ProjectAutoDevops' + has_many :custom_attributes, class_name: 'ProjectCustomAttribute' accepts_nested_attributes_for :variables, allow_destroy: true accepts_nested_attributes_for :project_feature, update_only: true diff --git a/app/models/project_custom_attribute.rb b/app/models/project_custom_attribute.rb new file mode 100644 index 00000000000..3f1a7b86a82 --- /dev/null +++ b/app/models/project_custom_attribute.rb @@ -0,0 +1,6 @@ +class ProjectCustomAttribute < ActiveRecord::Base + belongs_to :project + + validates :project, :key, :value, presence: true + validates :key, uniqueness: { scope: [:project_id] } +end -- cgit v1.2.1 From 1f773a8ef5a1f76166d0455c6a5e473278885c17 Mon Sep 17 00:00:00 2001 From: Markus Koller Date: Mon, 18 Sep 2017 17:07:38 +0200 Subject: Support custom attributes on groups --- app/models/group.rb | 1 + app/models/group_custom_attribute.rb | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 app/models/group_custom_attribute.rb (limited to 'app/models') diff --git a/app/models/group.rb b/app/models/group.rb index c660de7fcb6..8cf632fb566 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -26,6 +26,7 @@ class Group < Namespace has_many :notification_settings, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent has_many :labels, class_name: 'GroupLabel' has_many :variables, class_name: 'Ci::GroupVariable' + has_many :custom_attributes, class_name: 'GroupCustomAttribute' validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? } validate :visibility_level_allowed_by_projects diff --git a/app/models/group_custom_attribute.rb b/app/models/group_custom_attribute.rb new file mode 100644 index 00000000000..8157d602d67 --- /dev/null +++ b/app/models/group_custom_attribute.rb @@ -0,0 +1,6 @@ +class GroupCustomAttribute < ActiveRecord::Base + belongs_to :group + + validates :group, :key, :value, presence: true + validates :key, uniqueness: { scope: [:group_id] } +end -- cgit v1.2.1 From 001de85e7c6f86423aca0d245fdc83c57b374630 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 6 Nov 2017 11:03:58 +0100 Subject: Return empty applications if not Kubernetes [ci skip] --- app/models/clusters/cluster.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models') diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 7d0be3d3739..5b9bd6e548b 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -58,6 +58,8 @@ module Clusters end def applications + return [] unless kubernetes? + [ application_helm || build_application_helm ] -- cgit v1.2.1 From 503f21367051c18412d6bdf3d4586eaddaf69087 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 6 Oct 2017 11:45:23 +0200 Subject: Make sure that every job has a stage assigned --- app/models/commit_status.rb | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index f3888528940..7f2295dd4da 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -14,7 +14,6 @@ class CommitStatus < ActiveRecord::Base delegate :sha, :short_sha, to: :pipeline validates :pipeline, presence: true, unless: :importing? - validates :name, presence: true, unless: :importing? alias_attribute :author, :user @@ -46,6 +45,21 @@ class CommitStatus < ActiveRecord::Base runner_system_failure: 4 } + ## + # We still create some CommitStatuses outside of CreatePipelineService. + # + # These are pages deployments and external statuses. + # + before_create do |status| + next if status.stage_id.present? || importing? + + ensure_pipeline_stage! do |stage| + status.run_after_commit do + StageUpdateWorker.perform_async(stage.id) + end + end + end + state_machine :status do event :process do transition [:skipped, :manual] => :created @@ -174,4 +188,16 @@ class CommitStatus < ActiveRecord::Base v =~ /\d+/ ? v.to_i : v end end + + private + + def ensure_pipeline_stage! + attributes = { name: stage, pipeline: pipeline, project: project } + + Ci::Stage.create!(attributes).tap do |stage| + self.stage_id = stage.id + + yield stage + end + end end -- cgit v1.2.1 From e2828a60679495d716ed3824959794f4d5fbf5bb Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 6 Oct 2017 12:07:11 +0200 Subject: Use existing pipeline stage if stage already exists --- app/models/commit_status.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 7f2295dd4da..12e187024dd 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -192,12 +192,20 @@ class CommitStatus < ActiveRecord::Base private def ensure_pipeline_stage! - attributes = { name: stage, pipeline: pipeline, project: project } - - Ci::Stage.create!(attributes).tap do |stage| + (find_stage || create_stage!).tap do |stage| self.stage_id = stage.id yield stage end end + + def find_stage + pipeline.stages.find_by(name: stage) + end + + def create_stage! + Ci::Stage.create!(name: stage, + pipeline: pipeline, + project: project) + end end -- cgit v1.2.1 From 164b1df59025e9685e243dd89d943ff5b1122b44 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 11 Oct 2017 15:32:19 +0200 Subject: Extract ensure stage service from commit status class --- app/models/commit_status.rb | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) (limited to 'app/models') diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 12e187024dd..6b07dbdf3ea 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -50,13 +50,9 @@ class CommitStatus < ActiveRecord::Base # # These are pages deployments and external statuses. # - before_create do |status| - next if status.stage_id.present? || importing? - - ensure_pipeline_stage! do |stage| - status.run_after_commit do - StageUpdateWorker.perform_async(stage.id) - end + before_create unless: :importing? do + Ci::EnsureStageService.new(project, user).execute(self) do |stage| + self.run_after_commit { StageUpdateWorker.perform_async(stage.id) } end end @@ -188,24 +184,4 @@ class CommitStatus < ActiveRecord::Base v =~ /\d+/ ? v.to_i : v end end - - private - - def ensure_pipeline_stage! - (find_stage || create_stage!).tap do |stage| - self.stage_id = stage.id - - yield stage - end - end - - def find_stage - pipeline.stages.find_by(name: stage) - end - - def create_stage! - Ci::Stage.create!(name: stage, - pipeline: pipeline, - project: project) - end end -- cgit v1.2.1 From 9b58b8e363fd388635385085c58be3d4637eaa45 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Mon, 6 Nov 2017 22:20:44 +0900 Subject: Do not allow jobs to be erased --- app/models/ci/build.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 6ca46ae89c1..0d992c4c01f 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -192,6 +192,10 @@ module Ci project.build_timeout end + def owned_by?(current_user) + user == current_user + end + # A slugified version of the build ref, suitable for inclusion in URLs and # domain names. Rules: # -- cgit v1.2.1 From a10925e1c37e7dab19de346c553311adfaccb86c Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 3 Nov 2017 19:48:15 +0100 Subject: Reallow project paths ending in periods --- app/models/namespace.rb | 2 +- app/models/project.rb | 4 +--- app/models/user.rb | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 0601a61a926..4d401e7ba18 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -36,7 +36,7 @@ class Namespace < ActiveRecord::Base validates :path, presence: true, length: { maximum: 255 }, - dynamic_path: true + namespace_path: true validate :nesting_level_allowed diff --git a/app/models/project.rb b/app/models/project.rb index 2f9b80d0514..5a0cbfeb282 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -240,10 +240,8 @@ class Project < ActiveRecord::Base message: Gitlab::Regex.project_name_regex_message } validates :path, presence: true, - dynamic_path: true, + project_path: true, length: { maximum: 255 }, - format: { with: Gitlab::PathRegex.project_path_format_regex, - message: Gitlab::PathRegex.project_path_format_message }, uniqueness: { scope: :namespace_id } validates :namespace, presence: true diff --git a/app/models/user.rb b/app/models/user.rb index bcda4564595..87a6c63cfaa 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -146,7 +146,7 @@ class User < ActiveRecord::Base presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: Gitlab::Database::MAX_INT_VALUE } validates :username, - dynamic_path: true, + user_path: true, presence: true, uniqueness: { case_sensitive: false } -- cgit v1.2.1 From bb0543ef4782febe4dd0f26fc8a476b743fb86ca Mon Sep 17 00:00:00 2001 From: "micael.bergeron" Date: Mon, 6 Nov 2017 09:03:11 -0500 Subject: ignore the column before the migration reword the changelog remove dead code in the specs --- app/models/merge_request.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index ccad8e102aa..f80601f3484 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -8,7 +8,8 @@ class MergeRequest < ActiveRecord::Base include CreatedAtFilterable include TimeTrackable - ignore_column :locked_at + ignore_column :locked_at, + :ref_fetched belongs_to :target_project, class_name: "Project" belongs_to :source_project, class_name: "Project" -- cgit v1.2.1 From a99ad59e655d66fda8af7f2b89aced79b8bc1060 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Mon, 6 Nov 2017 23:06:10 +0900 Subject: Remove 10.3 comments (Tracked by a tech debts issue). Refactor spec factory name. Use ArgumentError --- app/models/clusters/providers/gcp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/clusters/providers/gcp.rb b/app/models/clusters/providers/gcp.rb index 7700ba86f1a..c4391729dd7 100644 --- a/app/models/clusters/providers/gcp.rb +++ b/app/models/clusters/providers/gcp.rb @@ -55,7 +55,7 @@ module Clusters before_transition any => [:creating] do |provider, transition| operation_id = transition.args.first - raise 'operation_id is required' unless operation_id + raise ArgumentError.new('operation_id is required') unless operation_id.present? provider.operation_id = operation_id end -- cgit v1.2.1 From 634a152760b1442a9f0ead3b73688f931c414882 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 6 Nov 2017 13:03:51 +0100 Subject: Make sure group and project creation is blocked for new users that are external by default --- app/models/user.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/user.rb b/app/models/user.rb index bcda4564595..ed70a50a514 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -164,7 +164,7 @@ class User < ActiveRecord::Base before_validation :set_notification_email, if: :email_changed? before_validation :set_public_email, if: :public_email_changed? before_save :ensure_incoming_email_token - before_save :ensure_user_rights_and_limits, if: :external_changed? + before_save :ensure_user_rights_and_limits, if: ->(user) { user.new_record? || user.external_changed? } before_save :skip_reconfirmation!, if: ->(user) { user.email_changed? && user.read_only_attribute?(:email) } before_save :check_for_verified_email, if: ->(user) { user.email_changed? && !user.new_record? } after_save :ensure_namespace_correct @@ -1139,8 +1139,9 @@ class User < ActiveRecord::Base self.can_create_group = false self.projects_limit = 0 else - self.can_create_group = gitlab_config.default_can_create_group - self.projects_limit = current_application_settings.default_projects_limit + # Only revert these back to the default if they weren't specifically changed in this update. + self.can_create_group = gitlab_config.default_can_create_group unless can_create_group_changed? + self.projects_limit = current_application_settings.default_projects_limit unless projects_limit_changed? end end -- cgit v1.2.1 From 5e7d68ef798c110204351ec089acd896271c4315 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 6 Nov 2017 13:48:34 +0000 Subject: Fix issue reopen Mattermost / Slack message When an issue is reopened, the action is 'reopen', but the state is 'opened' (as we don't have a separate 'reopened' state any more). Because we checked the action in one method and the state in another, this lead to a weird case where the mesage neither linked to the issue, nor contained an attachment with its details. Just checking the action is fine, as it's the most granular. --- app/models/project_services/chat_message/issue_message.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/project_services/chat_message/issue_message.rb b/app/models/project_services/chat_message/issue_message.rb index 1327b075858..3273f41dbd2 100644 --- a/app/models/project_services/chat_message/issue_message.rb +++ b/app/models/project_services/chat_message/issue_message.rb @@ -39,7 +39,7 @@ module ChatMessage private def message - if state == 'opened' + if opened_issue? "[#{project_link}] Issue #{state} by #{user_combined_name}" else "[#{project_link}] Issue #{issue_link} #{state} by #{user_combined_name}" -- cgit v1.2.1 From 61501a07cb9c1fff5a30662b3e3815976f2777cb Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Mon, 6 Nov 2017 15:43:02 +0100 Subject: Add Clusters::Applications services tests --- app/models/clusters/concerns/application_status.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index 7bb68d75224..c5711fd0b58 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -24,7 +24,7 @@ module Clusters end event :make_scheduled do - transition any - [:scheduled] => :scheduled + transition %i(installable errored) => :scheduled end before_transition any => [:scheduled] do |app_status, _| -- cgit v1.2.1 From ac927462dc1b9578de3a716e9e4ff551f424663b Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 6 Nov 2017 15:48:44 +0100 Subject: Add support for not_installable/scheduled and to not show created banner --- app/models/clusters/applications/helm.rb | 6 ++++++ app/models/clusters/applications/ingress.rb | 6 ++++++ app/models/clusters/cluster.rb | 5 +++-- app/models/clusters/concerns/application_status.rb | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 42626a50175..9bc5c026645 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -11,10 +11,16 @@ module Clusters validates :cluster, presence: true + after_initialize :set_initial_status + def self.application_name self.to_s.demodulize.underscore end + def set_initial_status + self.status = 0 unless cluster.platform_kubernetes_active? + end + def name self.class.application_name end diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index 0554cf84ed7..8cb1ed68de9 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -9,6 +9,8 @@ module Clusters validates :cluster, presence: true + after_initialize :set_initial_status + default_value_for :ingress_type, :nginx default_value_for :version, :nginx @@ -20,6 +22,10 @@ module Clusters self.to_s.demodulize.underscore end + def set_initial_status + self.status = 0 unless cluster.application_helm_installed? + end + def name self.class.application_name end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 90508e31e93..185d9473aab 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -39,6 +39,9 @@ module Clusters delegate :on_creation?, to: :provider, allow_nil: true delegate :update_kubernetes_integration!, to: :platform, allow_nil: true + delegate :active?, to: :platform_kubernetes, prefix: true, allow_nil: true + delegate :installed?, to: :application_helm, prefix: true, allow_nil: true + enum platform_type: { kubernetes: 1 } @@ -60,8 +63,6 @@ module Clusters end def applications - return [] unless kubernetes? - [ application_helm || build_application_helm, application_ingress || build_application_ingress diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index 7bb68d75224..7592dd55689 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -5,6 +5,7 @@ module Clusters included do state_machine :status, initial: :installable do + state :not_installable, value: -2 state :errored, value: -1 state :installable, value: 0 state :scheduled, value: 1 -- cgit v1.2.1 From 802e6653de7c67def245d86244f9223431618189 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 6 Nov 2017 15:50:55 +0100 Subject: Add active? to Platforms::Kubernetes --- app/models/clusters/platforms/kubernetes.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 74f7c9442db..6dc1ee810d3 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -74,6 +74,10 @@ module Clusters ) end + def active? + manages_kubernetes_service? + end + private def enforce_namespace_to_lower_case -- cgit v1.2.1 From f3a3566edc8fe24337b9df163f4699785061bb38 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 6 Nov 2017 15:48:44 +0100 Subject: Add support for not_installable/scheduled and to not show created banner --- app/models/clusters/applications/helm.rb | 6 ++++++ app/models/clusters/cluster.rb | 5 +++-- app/models/clusters/concerns/application_status.rb | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 42626a50175..9bc5c026645 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -11,10 +11,16 @@ module Clusters validates :cluster, presence: true + after_initialize :set_initial_status + def self.application_name self.to_s.demodulize.underscore end + def set_initial_status + self.status = 0 unless cluster.platform_kubernetes_active? + end + def name self.class.application_name end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 5b9bd6e548b..68759ebb6df 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -37,6 +37,9 @@ module Clusters delegate :on_creation?, to: :provider, allow_nil: true delegate :update_kubernetes_integration!, to: :platform, allow_nil: true + delegate :active?, to: :platform_kubernetes, prefix: true, allow_nil: true + delegate :installed?, to: :application_helm, prefix: true, allow_nil: true + enum platform_type: { kubernetes: 1 } @@ -58,8 +61,6 @@ module Clusters end def applications - return [] unless kubernetes? - [ application_helm || build_application_helm ] diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index 7bb68d75224..7592dd55689 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -5,6 +5,7 @@ module Clusters included do state_machine :status, initial: :installable do + state :not_installable, value: -2 state :errored, value: -1 state :installable, value: 0 state :scheduled, value: 1 -- cgit v1.2.1 From 895b6e5d80397fdd6cb5e1727a410a08f8a5b332 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 6 Nov 2017 15:50:55 +0100 Subject: Add active? to Platforms::Kubernetes --- app/models/clusters/platforms/kubernetes.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 74f7c9442db..6dc1ee810d3 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -74,6 +74,10 @@ module Clusters ) end + def active? + manages_kubernetes_service? + end + private def enforce_namespace_to_lower_case -- cgit v1.2.1 From d934d6504a9f1a706dbfc0b4a28c4cf8dbe8c8eb Mon Sep 17 00:00:00 2001 From: "micael.bergeron" Date: Mon, 6 Nov 2017 10:20:20 -0500 Subject: updated the ignore_column concern to support multiple columns This method is an ActiveRecord extension and it should behave like one. I expected this to work. --- app/models/concerns/ignorable_column.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/ignorable_column.rb b/app/models/concerns/ignorable_column.rb index eb9f3423e48..03793e8bcbb 100644 --- a/app/models/concerns/ignorable_column.rb +++ b/app/models/concerns/ignorable_column.rb @@ -21,8 +21,8 @@ module IgnorableColumn @ignored_columns ||= Set.new end - def ignore_column(name) - ignored_columns << name.to_s + def ignore_column(*names) + ignored_columns.merge(names.map(&:to_s)) end end end -- cgit v1.2.1 From ad937d270c3fb4337a091841dc41ee0135a8a840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 6 Nov 2017 16:29:13 +0100 Subject: Cache the root ref SHA in an instance variable in Repository#merged_to_root_ref? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/models/repository.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/repository.rb b/app/models/repository.rb index 69cddb36b2e..d445ef96322 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -906,13 +906,13 @@ class Repository branch = Gitlab::Git::Branch.find(self, branch_or_name) if branch - root_ref_sha = commit(root_ref).sha - same_head = branch.target == root_ref_sha + @root_ref_sha ||= commit(root_ref).sha + same_head = branch.target == @root_ref_sha merged = if pre_loaded_merged_branches pre_loaded_merged_branches.include?(branch.name) else - ancestor?(branch.target, root_ref_sha) + ancestor?(branch.target, @root_ref_sha) end !same_head && merged -- cgit v1.2.1 From afef38533727cf32a7be324243a25b4db5eb5498 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Tue, 7 Nov 2017 02:47:05 +0900 Subject: Add doc. Fix spec. Add erase_build in protected_ref rule --- app/models/ci/build.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 0d992c4c01f..1b2b0d17910 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -192,7 +192,7 @@ module Ci project.build_timeout end - def owned_by?(current_user) + def triggered_by?(current_user) user == current_user end -- cgit v1.2.1 From 9c76c44805effc7acb7d3cbd7ff4bd132cbbf100 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 6 Nov 2017 20:29:13 +0100 Subject: Fix small error [ci skip] --- app/models/clusters/applications/helm.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 9bc5c026645..c203beb4915 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -18,7 +18,7 @@ module Clusters end def set_initial_status - self.status = 0 unless cluster.platform_kubernetes_active? + self.status = 0 unless cluster&.platform_kubernetes_active? end def name -- cgit v1.2.1 From 8d7fbd09dc2da152c0377ff4f50e72ba084d60a3 Mon Sep 17 00:00:00 2001 From: bikebilly Date: Tue, 7 Nov 2017 09:46:04 +0100 Subject: Change new occurrencies of n1-default-4 --- app/models/clusters/providers/gcp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/clusters/providers/gcp.rb b/app/models/clusters/providers/gcp.rb index c4391729dd7..ee2e43ee9dd 100644 --- a/app/models/clusters/providers/gcp.rb +++ b/app/models/clusters/providers/gcp.rb @@ -7,7 +7,7 @@ module Clusters default_value_for :zone, 'us-central1-a' default_value_for :num_nodes, 3 - default_value_for :machine_type, 'n1-standard-4' + default_value_for :machine_type, 'n1-standard-2' attr_encrypted :access_token, mode: :per_attribute_iv, -- cgit v1.2.1 From 6228b65ff1503e2a3496544c15961139e1fb6cd4 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Tue, 7 Nov 2017 17:51:32 +0900 Subject: Fix static analysys in app/models/clusters/applications/helm.rb:15 --- app/models/clusters/applications/helm.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index c203beb4915..863f9b9d834 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -12,7 +12,7 @@ module Clusters validates :cluster, presence: true after_initialize :set_initial_status - + def self.application_name self.to_s.demodulize.underscore end -- cgit v1.2.1 From 3bf2abaa1cc26b8658d870e85d4fc9e60e621944 Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Tue, 7 Nov 2017 10:07:22 +0100 Subject: More restrictive state machine transitions in Clusters::ApplicationStatus --- app/models/clusters/concerns/application_status.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index 40140cb71cb..e73abfa9055 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -12,20 +12,20 @@ module Clusters state :installing, value: 2 state :installed, value: 3 + event :make_scheduled do + transition %i(installable errored) => :scheduled + end + event :make_installing do - transition any - [:installing] => :installing + transition %i(scheduled) => :installing end event :make_installed do - transition any - [:installed] => :installed + transition %i(installing) => :installed end event :make_errored do - transition any - [:errored] => :errored - end - - event :make_scheduled do - transition %i(installable errored) => :scheduled + transition any => :errored end before_transition any => [:scheduled] do |app_status, _| -- cgit v1.2.1 From 67e12219bf6257568f91c1a9c883e4821337c80d Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 7 Nov 2017 13:50:04 +0100 Subject: Rework initial state --- app/models/clusters/applications/helm.rb | 10 ++++++---- app/models/clusters/concerns/application_status.rb | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 863f9b9d834..d60bb7dcd02 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -11,14 +11,16 @@ module Clusters validates :cluster, presence: true - after_initialize :set_initial_status - def self.application_name self.to_s.demodulize.underscore end - def set_initial_status - self.status = 0 unless cluster&.platform_kubernetes_active? + def initial_status + if cluster&.platform_kubernetes_active? + :installable + else + :not_installable + end end def name diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index e73abfa9055..3e15da7fc32 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -4,7 +4,7 @@ module Clusters extend ActiveSupport::Concern included do - state_machine :status, initial: :installable do + state_machine :status, initial: ->(application) { application.initial_status } do state :not_installable, value: -2 state :errored, value: -1 state :installable, value: 0 -- cgit v1.2.1 From f96b5eae20dbba3c2ce79556c4a9b034a590ee39 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 7 Nov 2017 13:55:21 +0100 Subject: Fix initial_status --- app/models/clusters/applications/ingress.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index 8cb1ed68de9..c97e9db925e 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -9,8 +9,6 @@ module Clusters validates :cluster, presence: true - after_initialize :set_initial_status - default_value_for :ingress_type, :nginx default_value_for :version, :nginx @@ -22,8 +20,12 @@ module Clusters self.to_s.demodulize.underscore end - def set_initial_status - self.status = 0 unless cluster.application_helm_installed? + def initial_status + if cluster&.application_helm_installed? + :installable + else + :not_installable + end end def name -- cgit v1.2.1 From 0562b02bc2be0716be3cd11da151bf6531a8c59a Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Tue, 7 Nov 2017 13:58:36 +0100 Subject: Do not use %i() in state machines --- app/models/clusters/concerns/application_status.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index 3e15da7fc32..ce1b6621479 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -13,15 +13,15 @@ module Clusters state :installed, value: 3 event :make_scheduled do - transition %i(installable errored) => :scheduled + transition [:installable, :errored] => :scheduled end event :make_installing do - transition %i(scheduled) => :installing + transition [:scheduled] => :installing end event :make_installed do - transition %i(installing) => :installed + transition [:installing] => :installed end event :make_errored do -- cgit v1.2.1 From 3cb4614273bfc10a6d3acc98d7a450dbe9f1aaaf Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 7 Nov 2017 14:26:14 +0100 Subject: Fix initial status again --- app/models/clusters/applications/helm.rb | 10 ++++------ app/models/clusters/applications/ingress.rb | 10 ++++------ app/models/clusters/concerns/application_status.rb | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index d60bb7dcd02..0bbe5219715 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -11,16 +11,14 @@ module Clusters validates :cluster, presence: true + after_initialize :set_initial_status + def self.application_name self.to_s.demodulize.underscore end - def initial_status - if cluster&.platform_kubernetes_active? - :installable - else - :not_installable - end + def set_initial_status + self.status = 'installable' if cluster&.platform_kubernetes_active? end def name diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index c97e9db925e..02c14a33e23 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -12,6 +12,8 @@ module Clusters default_value_for :ingress_type, :nginx default_value_for :version, :nginx + after_initialize :set_initial_status + enum ingress_type: { nginx: 1 } @@ -20,12 +22,8 @@ module Clusters self.to_s.demodulize.underscore end - def initial_status - if cluster&.application_helm_installed? - :installable - else - :not_installable - end + def set_initial_status + self.status = 'installable' if cluster&.application_helm_installed? end def name diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index 3e15da7fc32..516fb0d1a7d 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -4,7 +4,7 @@ module Clusters extend ActiveSupport::Concern included do - state_machine :status, initial: ->(application) { application.initial_status } do + state_machine :status, initial: :not_installable do state :not_installable, value: -2 state :errored, value: -1 state :installable, value: 0 -- cgit v1.2.1 From 55d098c94b4f7e39931d5e4084be19872386fa18 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 7 Nov 2017 14:26:14 +0100 Subject: Fix initial status again --- app/models/clusters/applications/helm.rb | 10 ++++------ app/models/clusters/concerns/application_status.rb | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index d60bb7dcd02..0bbe5219715 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -11,16 +11,14 @@ module Clusters validates :cluster, presence: true + after_initialize :set_initial_status + def self.application_name self.to_s.demodulize.underscore end - def initial_status - if cluster&.platform_kubernetes_active? - :installable - else - :not_installable - end + def set_initial_status + self.status = 'installable' if cluster&.platform_kubernetes_active? end def name diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index ce1b6621479..7b7c8eac773 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -4,7 +4,7 @@ module Clusters extend ActiveSupport::Concern included do - state_machine :status, initial: ->(application) { application.initial_status } do + state_machine :status, initial: :not_installable do state :not_installable, value: -2 state :errored, value: -1 state :installable, value: 0 -- cgit v1.2.1 From ad6e650262c1c152fe5e7d7a09607286b8f9f750 Mon Sep 17 00:00:00 2001 From: Jarka Kadlecova Date: Tue, 7 Nov 2017 14:34:12 +0100 Subject: Refactor issuables index actions --- app/models/concerns/issuable.rb | 2 ++ app/models/issue.rb | 2 -- app/models/merge_request.rb | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index a928b9d6367..c008fb91a16 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -17,6 +17,8 @@ module Issuable include Importable include Editable include AfterCommitQueue + include Sortable + include CreatedAtFilterable # This object is used to gather issuable meta data for displaying # upvotes, downvotes, notes and closing merge requests count for issues and merge requests diff --git a/app/models/issue.rb b/app/models/issue.rb index fc590f9257e..3b3c7fb7f8b 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -5,11 +5,9 @@ class Issue < ActiveRecord::Base include Issuable include Noteable include Referable - include Sortable include Spammable include FasterCacheKeys include RelativePositioning - include CreatedAtFilterable include TimeTrackable DueDateStruct = Struct.new(:title, :name).freeze diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index f80601f3484..82d0ae90d77 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -3,9 +3,7 @@ class MergeRequest < ActiveRecord::Base include Issuable include Noteable include Referable - include Sortable include IgnorableColumn - include CreatedAtFilterable include TimeTrackable ignore_column :locked_at, -- cgit v1.2.1 From 760a154a032319a90e15dcf4d54ec1c1cdde9e1c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 7 Nov 2017 14:52:11 +0100 Subject: Fix tests for initial status --- app/models/clusters/applications/helm.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 0bbe5219715..7ea84841118 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -18,6 +18,8 @@ module Clusters end def set_initial_status + return unless not_installable? + self.status = 'installable' if cluster&.platform_kubernetes_active? end -- cgit v1.2.1 From e40021cd3cba0a889f43fcfec7b25c757391f11c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 7 Nov 2017 14:55:26 +0100 Subject: Fix ingress.rb --- app/models/clusters/applications/ingress.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models') diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index 02c14a33e23..c9584476f3c 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -23,6 +23,8 @@ module Clusters end def set_initial_status + return unless not_installable? + self.status = 'installable' if cluster&.application_helm_installed? end -- cgit v1.2.1 From 8ec618a6ede619d9f75279f03c03b24d106c79c7 Mon Sep 17 00:00:00 2001 From: Alessio Caiazza Date: Tue, 7 Nov 2017 15:26:14 +0100 Subject: Add Helm InstallCommand --- app/models/clusters/applications/helm.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 7ea84841118..c7949d11ef8 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -26,6 +26,10 @@ module Clusters def name self.class.application_name end + + def install_command + Gitlab::Kubernetes::Helm::InstallCommand.new(name, true) + end end end end -- cgit v1.2.1 From 1625adf5bab8faa4291fdce1e75174d7d1faa99d Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 7 Nov 2017 17:49:27 +0100 Subject: Make ingress to use install_command --- app/models/clusters/applications/ingress.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index c9584476f3c..44bd979741e 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -35,6 +35,10 @@ module Clusters def chart 'stable/nginx-ingress' end + + def install_command + Gitlab::Kubernetes::Helm::InstallCommand.new(name, false, chart) + end end end end -- cgit v1.2.1 From 44be82dd18c372862c2421a1934ff816f7cccd97 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 6 Oct 2017 16:50:54 +0200 Subject: Refactor User.find_by_any_email By using SQL::Union we can return a proper ActiveRecord::Relation, making it possible to select the columns we're interested in (instead of all of them). --- app/models/user.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'app/models') diff --git a/app/models/user.rb b/app/models/user.rb index aa88cda4dc0..8205c3e29b9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -269,16 +269,16 @@ class User < ActiveRecord::Base # Find a User by their primary email or any associated secondary email def find_by_any_email(email) - sql = 'SELECT * - FROM users - WHERE id IN ( - SELECT id FROM users WHERE email = :email - UNION - SELECT emails.user_id FROM emails WHERE email = :email - ) - LIMIT 1;' + by_any_email(email).take + end + + # Returns a relation containing all the users for the given Email address + def by_any_email(email) + users = where(email: email) + emails = joins(:emails).where(emails: { email: email }) + union = Gitlab::SQL::Union.new([users, emails]) - User.find_by_sql([sql, { email: email }]).first + from("(#{union.to_sql}) #{table_name}") end def filter(filter_name) -- cgit v1.2.1 From 4dfe26cd8b6863b7e6c81f5c280cdafe9b6e17b6 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 13 Oct 2017 18:50:36 +0200 Subject: Rewrite the GitHub importer from scratch Prior to this MR there were two GitHub related importers: * Github::Import: the main importer used for GitHub projects * Gitlab::GithubImport: importer that's somewhat confusingly used for importing Gitea projects (apparently they have a compatible API) This MR renames the Gitea importer to Gitlab::LegacyGithubImport and introduces a new GitHub importer in the Gitlab::GithubImport namespace. This new GitHub importer uses Sidekiq for importing multiple resources in parallel, though it also has the ability to import data sequentially should this be necessary. The new code is spread across the following directories: * lib/gitlab/github_import: this directory contains most of the importer code such as the classes used for importing resources. * app/workers/gitlab/github_import: this directory contains the Sidekiq workers, most of which simply use the code from the directory above. * app/workers/concerns/gitlab/github_import: this directory provides a few modules that are included in every GitHub importer worker. == Stages The import work is divided into separate stages, with each stage importing a specific set of data. Stages will schedule the work that needs to be performed, followed by scheduling a job for the "AdvanceStageWorker" worker. This worker will periodically check if all work is completed and schedule the next stage if this is the case. If work is not yet completed this worker will reschedule itself. Using this approach we don't have to block threads by calling `sleep()`, as doing so for large projects could block the thread from doing any work for many hours. == Retrying Work Workers will reschedule themselves whenever necessary. For example, hitting the GitHub API's rate limit will result in jobs rescheduling themselves. These jobs are not processed until the rate limit has been reset. == User Lookups Part of the importing process involves looking up user details in the GitHub API so we can map them to GitLab users. The old importer used an in-memory cache, but this obviously doesn't work when the work is spread across different threads. The new importer uses a Redis cache and makes sure we only perform API/database calls if absolutely necessary. Frequently used keys are refreshed, and lookup misses are also cached; removing the need for performing API/database calls if we know we don't have the data we're looking for. == Performance & Models The new importer in various places uses raw INSERT statements (as generated by `Gitlab::Database.bulk_insert`) instead of using Rails models. This allows us to bypass any validations and callbacks, drastically reducing the number of SQL queries and Gitaly RPC calls necessary to import projects. To ensure the code produces valid data the corresponding tests check if the produced rows are valid according to the model validation rules. --- app/models/project.rb | 41 +++++++++++++++++++++++++++++++++++++++++ app/models/repository.rb | 4 ++++ app/models/user.rb | 5 +++++ 3 files changed, 50 insertions(+) (limited to 'app/models') diff --git a/app/models/project.rb b/app/models/project.rb index 53df29dab02..bae16b6b2af 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -365,6 +365,7 @@ class Project < ActiveRecord::Base scope :abandoned, -> { where('projects.last_activity_at < ?', 6.months.ago) } scope :excluding_project, ->(project) { where.not(id: project) } + scope :import_started, -> { where(import_status: 'started') } state_machine :import_status, initial: :none do event :import_schedule do @@ -1190,6 +1191,10 @@ class Project < ActiveRecord::Base !!repository.exists? end + def wiki_repository_exists? + wiki.repository_exists? + end + # update visibility_level of forks def update_forks_visibility_level return unless visibility_level < visibility_level_was @@ -1433,6 +1438,31 @@ class Project < ActiveRecord::Base reload_repository! end + def after_import + repository.after_import + import_finish + remove_import_jid + update_project_counter_caches + end + + def update_project_counter_caches + classes = [ + Projects::OpenIssuesCountService, + Projects::OpenMergeRequestsCountService + ] + + classes.each do |klass| + klass.new(self).refresh_cache + end + end + + def remove_import_jid + return unless import_jid + + Gitlab::SidekiqStatus.unset(import_jid) + update_column(:import_jid, nil) + end + def running_or_pending_build_count(force: false) Rails.cache.fetch(['projects', id, 'running_or_pending_build_count'], force: force) do builds.running_or_pending.count(:all) @@ -1690,6 +1720,17 @@ class Project < ActiveRecord::Base Gitlab::ReferenceCounter.new(gl_repository(is_wiki: wiki)) end + # Refreshes the expiration time of the associated import job ID. + # + # This method can be used by asynchronous importers to refresh the status, + # preventing the StuckImportJobsWorker from marking the import as failed. + def refresh_import_jid_expiration + return unless import_jid + + Gitlab::SidekiqStatus + .set(import_jid, StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION) + end + private def storage diff --git a/app/models/repository.rb b/app/models/repository.rb index eb7766d040c..6bdee538172 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -973,6 +973,10 @@ class Repository raw_repository.fetch_source_branch!(source_repository.raw_repository, source_branch, local_ref) end + def remote_exists?(name) + raw_repository.remote_exists?(name) + end + def compare_source_branch(target_branch_name, source_repository, source_branch_name, straight:) raw_repository.compare_source_branch(target_branch_name, source_repository.raw_repository, source_branch_name, straight: straight) end diff --git a/app/models/user.rb b/app/models/user.rb index 8205c3e29b9..f436efd604f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -267,6 +267,11 @@ class User < ActiveRecord::Base end end + def for_github_id(id) + joins(:identities) + .where(identities: { provider: :github, extern_uid: id.to_s }) + end + # Find a User by their primary email or any associated secondary email def find_by_any_email(email) by_any_email(email).take -- cgit v1.2.1 From fec48c6e170fb0032cece5d8cc3b06bb45caee57 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 7 Nov 2017 17:11:37 +0100 Subject: Use Commit#notes and Note.for_commit_id when possible to make sure we use all the indexes available to us --- app/models/ci/pipeline.rb | 2 +- app/models/external_issue.rb | 4 ++++ app/models/merge_request.rb | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index ca65e81f27a..fcbe3d2b67b 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -409,7 +409,7 @@ module Ci end def notes - Note.for_commit_id(sha) + project.notes.for_commit_id(sha) end def process! diff --git a/app/models/external_issue.rb b/app/models/external_issue.rb index 0bf18e529f0..9ff56f229bc 100644 --- a/app/models/external_issue.rb +++ b/app/models/external_issue.rb @@ -47,4 +47,8 @@ class ExternalIssue id end + + def notes + Note.none + end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index f80601f3484..919391d2e47 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -578,7 +578,7 @@ class MergeRequest < ActiveRecord::Base commit_notes = Note .except(:order) .where(project_id: [source_project_id, target_project_id]) - .where(noteable_type: 'Commit', commit_id: commit_ids) + .for_commit_id(commit_ids) # We're using a UNION ALL here since this results in better performance # compared to using OR statements. We're using UNION ALL since the queries -- cgit v1.2.1 From c00fde606ee2d8f87a13c801efc3278396f6bb7f Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 7 Nov 2017 23:47:50 +0800 Subject: Make sure all pipelines would go to pending once Without this fix, pipeline could go from skipped to running directly, bypassing the transition for: [:created, :pending] => :running And this is responsible for setting up started_at. Without this fix, started_at would never be set. Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/39884 --- app/models/ci/pipeline.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index fcbe3d2b67b..19814864e50 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -66,8 +66,8 @@ module Ci state_machine :status, initial: :created do event :enqueue do - transition created: :pending - transition [:success, :failed, :canceled, :skipped] => :running + transition [:created, :skipped] => :pending + transition [:success, :failed, :canceled] => :running end event :run do -- cgit v1.2.1 From ebd51744729cb1b68754f8ba4d7f9adcec28d58d Mon Sep 17 00:00:00 2001 From: James Edwards-Jones Date: Wed, 8 Nov 2017 12:59:48 +0000 Subject: Handle forks in Gitlab::Checks::LfsIntegrity --- app/models/lfs_object.rb | 10 +--------- app/models/project.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'app/models') diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb index b7cf96abe83..fc586fa216e 100644 --- a/app/models/lfs_object.rb +++ b/app/models/lfs_object.rb @@ -6,16 +6,8 @@ class LfsObject < ActiveRecord::Base mount_uploader :file, LfsObjectUploader - def storage_project(project) - if project && project.forked? - storage_project(project.forked_from_project) - else - project - end - end - def project_allowed_access?(project) - projects.exists?(storage_project(project).id) + projects.exists?(project.lfs_storage_project.id) end def self.destroy_unreferenced diff --git a/app/models/project.rb b/app/models/project.rb index 3a300a4a03c..89db5b1300e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1042,6 +1042,18 @@ class Project < ActiveRecord::Base forked_from_project || fork_network&.root_project end + def lfs_storage_project + @lfs_storage_project ||= begin + result = self + + # TODO: Make this go to the fork_network root immeadiatly + # dependant on the discussion in: https://gitlab.com/gitlab-org/gitlab-ce/issues/39769 + result = result.fork_source while result&.forked? + + result || self + end + end + def personal? !group end -- cgit v1.2.1 From 2fbbba9a2958d51f9a6d8e0a7c4e06ec95ae18c0 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 9 Nov 2017 15:40:41 +0000 Subject: Always return full avatar URL for private/internal groups/projects when asset host is set --- app/models/concerns/avatarable.rb | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb index 2ec70203710..10659030910 100644 --- a/app/models/concerns/avatarable.rb +++ b/app/models/concerns/avatarable.rb @@ -4,15 +4,26 @@ module Avatarable def avatar_path(only_path: true) return unless self[:avatar].present? - # If only_path is true then use the relative path of avatar. - # Otherwise use full path (including host). asset_host = ActionController::Base.asset_host - gitlab_host = only_path ? gitlab_config.relative_url_root : gitlab_config.url + use_asset_host = asset_host.present? - # If asset_host is set then it is expected that assets are handled by a standalone host. - # That means we do not want to get GitLab's relative_url_root option anymore. - host = (asset_host.present? && (!respond_to?(:public?) || public?)) ? asset_host : gitlab_host + # Avatars for private and internal groups and projects require authentication to be viewed, + # which means they can only be served by Rails, on the regular GitLab host. + # If an asset host is configured, we need to return the fully qualified URL + # instead of only the avatar path, so that Rails doesn't prefix it with the asset host. + if use_asset_host && respond_to?(:public?) && !public? + use_asset_host = false + only_path = false + end - [host, avatar.url].join + url_base = "" + if use_asset_host + url_base << asset_host unless only_path + else + url_base << gitlab_config.base_url unless only_path + url_base << gitlab_config.relative_url_root + end + + url_base + avatar.url end end -- cgit v1.2.1 From ec73ecb0a88401932efc7b2b382db6905027b126 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 10 Nov 2017 13:39:57 +0000 Subject: Fix another timeout when searching for pipelines When we consider 'all' pipelines for MRs, we now mean: 1. The last 10,000 commits (unordered). 2. From the last 100 MR versions (newest first). This seems to fix the MRs that time out on GitLab.com. --- app/models/merge_request.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index efd8cca2947..dd4e67bc9da 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -865,7 +865,19 @@ class MergeRequest < ActiveRecord::Base # def all_commit_shas if persisted? - column_shas = MergeRequestDiffCommit.where(merge_request_diff: merge_request_diffs).limit(10_000).pluck('sha') + # MySQL doesn't support LIMIT in a subquery. + diffs_relation = + if Gitlab::Database.postgresql? + merge_request_diffs.order(id: :desc).limit(100) + else + merge_request_diffs + end + + column_shas = MergeRequestDiffCommit + .where(merge_request_diff: diffs_relation) + .limit(10_000) + .pluck('sha') + serialised_shas = merge_request_diffs.where.not(st_commits: nil).flat_map(&:commit_shas) (column_shas + serialised_shas).uniq -- cgit v1.2.1 From de301d13bb4f6d61cdaebfe186be6012c2f2096d Mon Sep 17 00:00:00 2001 From: "Jacob Vosmaer (GitLab)" Date: Fri, 10 Nov 2017 14:45:23 +0000 Subject: Prepare Repository#fetch_source_branch for migration --- app/models/repository.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/repository.rb b/app/models/repository.rb index 6bdee538172..3a89fa9264b 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1062,6 +1062,10 @@ class Repository blob_data_at(sha, path) end + def fetch_ref(source_repository, source_ref:, target_ref:) + raw_repository.fetch_ref(source_repository.raw_repository, source_ref: source_ref, target_ref: target_ref) + end + private # TODO Generice finder, later split this on finders by Ref or Oid -- cgit v1.2.1 From f39fe4d8db2d7fc6443c68aefff60f3eafcdf602 Mon Sep 17 00:00:00 2001 From: George Andrinopoulos Date: Sun, 29 Oct 2017 22:58:49 +0200 Subject: Add total time spent to milestones --- app/models/global_milestone.rb | 8 ++++++++ app/models/milestone.rb | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'app/models') diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index c0864769314..af4780f78d0 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -152,4 +152,12 @@ class GlobalMilestone @milestones.first.start_date end end + + def total_time_spent + issues.joins(:timelogs).sum(:time_spent) + merge_requests.joins(:timelogs).sum(:time_spent) + end + + def human_total_time_spent + Gitlab::TimeTrackingFormatter.output(total_time_spent) || 0 + end end diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 47e6b785c39..5e174a15c91 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -213,6 +213,14 @@ class Milestone < ActiveRecord::Base project_id.present? end + def total_time_spent + issues.joins(:timelogs).sum(:time_spent) + merge_requests.joins(:timelogs).sum(:time_spent) + end + + def human_total_time_spent + Gitlab::TimeTrackingFormatter.output(total_time_spent) || 0 + end + private # Milestone titles must be unique across project milestones and group milestones -- cgit v1.2.1 From d8462638e1b6faefe49c87c84ed819d525781a84 Mon Sep 17 00:00:00 2001 From: George Andrinopoulos Date: Thu, 2 Nov 2017 22:03:50 +0200 Subject: Fix collapsed sidebar messages and icon --- app/models/global_milestone.rb | 2 +- app/models/milestone.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index af4780f78d0..18af3c41d61 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -158,6 +158,6 @@ class GlobalMilestone end def human_total_time_spent - Gitlab::TimeTrackingFormatter.output(total_time_spent) || 0 + Gitlab::TimeTrackingFormatter.output(total_time_spent) end end diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 5e174a15c91..fa2dfcb694b 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -218,7 +218,7 @@ class Milestone < ActiveRecord::Base end def human_total_time_spent - Gitlab::TimeTrackingFormatter.output(total_time_spent) || 0 + Gitlab::TimeTrackingFormatter.output(total_time_spent) end private -- cgit v1.2.1 From 561693ad173b22dab54a0fdd5446f7637095272a Mon Sep 17 00:00:00 2001 From: George Andrinopoulos Date: Mon, 6 Nov 2017 20:18:20 +0200 Subject: Move total time spend calculation to milestoneish --- app/models/concerns/milestoneish.rb | 8 ++++++++ app/models/global_milestone.rb | 8 -------- app/models/milestone.rb | 8 -------- 3 files changed, 8 insertions(+), 16 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb index 710fc1ed647..7fe55f8402f 100644 --- a/app/models/concerns/milestoneish.rb +++ b/app/models/concerns/milestoneish.rb @@ -86,6 +86,14 @@ module Milestoneish false end + def total_issue_time_spent + issues.joins(:timelogs).sum(:time_spent) + end + + def human_total_issue_time_spent + Gitlab::TimeTrackingFormatter.output(total_issue_time_spent) + end + private def count_issues_by_state(user) diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index 18af3c41d61..c0864769314 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -152,12 +152,4 @@ class GlobalMilestone @milestones.first.start_date end end - - def total_time_spent - issues.joins(:timelogs).sum(:time_spent) + merge_requests.joins(:timelogs).sum(:time_spent) - end - - def human_total_time_spent - Gitlab::TimeTrackingFormatter.output(total_time_spent) - end end diff --git a/app/models/milestone.rb b/app/models/milestone.rb index fa2dfcb694b..47e6b785c39 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -213,14 +213,6 @@ class Milestone < ActiveRecord::Base project_id.present? end - def total_time_spent - issues.joins(:timelogs).sum(:time_spent) + merge_requests.joins(:timelogs).sum(:time_spent) - end - - def human_total_time_spent - Gitlab::TimeTrackingFormatter.output(total_time_spent) - end - private # Milestone titles must be unique across project milestones and group milestones -- cgit v1.2.1 From 8f6b3d7452447b5ef6c669c2ff5ad3b394e27dea Mon Sep 17 00:00:00 2001 From: George Andrinopoulos Date: Fri, 10 Nov 2017 22:18:42 +0200 Subject: Add externalized strings --- app/models/concerns/milestoneish.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb index 7fe55f8402f..7026f565706 100644 --- a/app/models/concerns/milestoneish.rb +++ b/app/models/concerns/milestoneish.rb @@ -87,7 +87,7 @@ module Milestoneish end def total_issue_time_spent - issues.joins(:timelogs).sum(:time_spent) + @total_issue_time_spent ||= issues.joins(:timelogs).sum(:time_spent) end def human_total_issue_time_spent -- cgit v1.2.1 From 3963f91ee355e26778dc6a6ccfd844af3cee194f Mon Sep 17 00:00:00 2001 From: George Andrinopoulos Date: Thu, 9 Nov 2017 21:34:21 +0200 Subject: Move update_project_counter_caches? out of issue and merge request --- app/models/issue.rb | 4 ---- app/models/merge_request.rb | 4 ---- 2 files changed, 8 deletions(-) (limited to 'app/models') diff --git a/app/models/issue.rb b/app/models/issue.rb index 3b3c7fb7f8b..b5abc8f57b0 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -262,10 +262,6 @@ class Issue < ActiveRecord::Base true end - def update_project_counter_caches? - state_changed? || confidential_changed? - end - def update_project_counter_caches Projects::OpenIssuesCountService.new(project).refresh_cache end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index dd4e67bc9da..f1a5cc73e83 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -958,10 +958,6 @@ class MergeRequest < ActiveRecord::Base true end - def update_project_counter_caches? - state_changed? - end - def update_project_counter_caches Projects::OpenMergeRequestsCountService.new(target_project).refresh_cache end -- cgit v1.2.1 From 1162d89ac49553c579ec4d049e74206893ff6302 Mon Sep 17 00:00:00 2001 From: Travis Miller Date: Mon, 13 Nov 2017 16:05:44 +0000 Subject: Add administrative endpoint to list all pages domains --- app/models/pages_domain.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb index 2e824cda525..43c77f3f2a2 100644 --- a/app/models/pages_domain.rb +++ b/app/models/pages_domain.rb @@ -69,6 +69,10 @@ class PagesDomain < ActiveRecord::Base current < x509.not_before || x509.not_after < current end + def expiration + x509&.not_after + end + def subject return unless x509 x509.subject.to_s -- cgit v1.2.1 From aefefbf11701042ae59a60818e3f957b30831dfd Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Mon, 13 Nov 2017 16:38:15 -0200 Subject: Prevents position update for image diff notes --- app/models/diff_note.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb index d88a92dc027..ae5f138a920 100644 --- a/app/models/diff_note.rb +++ b/app/models/diff_note.rb @@ -18,7 +18,8 @@ class DiffNote < Note validate :positions_complete validate :verify_supported - before_validation :set_original_position, :update_position, on: :create + before_validation :set_original_position, on: :create + before_validation :update_position, on: :create, if: :on_text? before_validation :set_line_code after_save :keep_around_commits -- cgit v1.2.1 From 022d8420ec0713909ff379e1e8d36c4e46bde3a3 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 9 Nov 2017 15:59:11 +0100 Subject: Include child projects a user can manage in namespace dropdowns These dropdown options are used for creating and transfering projects. --- app/models/user.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/user.rb b/app/models/user.rb index f436efd604f..ea10e2854d6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -921,7 +921,16 @@ class User < ActiveRecord::Base end def manageable_namespaces - @manageable_namespaces ||= [namespace] + owned_groups + masters_groups + @manageable_namespaces ||= [namespace] + manageable_groups + end + + def manageable_groups + union = Gitlab::SQL::Union.new([owned_groups.select(:id), + masters_groups.select(:id)]) + arel_union = Arel::Nodes::SqlLiteral.new(union.to_sql) + owned_and_master_groups = Group.where(Group.arel_table[:id].in(arel_union)) + + Gitlab::GroupHierarchy.new(owned_and_master_groups).base_and_descendants end def namespaces -- cgit v1.2.1 From e30cecbc27d45b384ace57a9f616a4d34acf9ec3 Mon Sep 17 00:00:00 2001 From: Jose Ivan Vargas Lopez Date: Wed, 15 Nov 2017 08:42:37 +0000 Subject: Resolve "Internationalization support for Prometheus Service Configuration" --- app/models/project_services/prometheus_service.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb index 217f753f05f..fa7b3f2bcaf 100644 --- a/app/models/project_services/prometheus_service.rb +++ b/app/models/project_services/prometheus_service.rb @@ -25,7 +25,7 @@ class PrometheusService < MonitoringService end def description - 'Prometheus monitoring' + s_('PrometheusService|Prometheus monitoring') end def self.to_param @@ -38,8 +38,8 @@ class PrometheusService < MonitoringService type: 'text', name: 'api_url', title: 'API URL', - placeholder: 'Prometheus API Base URL, like http://prometheus.example.com/', - help: 'By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server.', + placeholder: s_('PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/'), + help: s_('PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server.'), required: true } ] -- cgit v1.2.1 From 8da236611b5182a1105111904027ae3e74ed1682 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 15 Nov 2017 13:27:37 +0100 Subject: Prefer polymorphism over specific type checks in Import service --- app/models/project.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app/models') diff --git a/app/models/project.rb b/app/models/project.rb index bae16b6b2af..8da03e23057 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -704,10 +704,6 @@ class Project < ActiveRecord::Base import_type == 'gitea' end - def github_import? - import_type == 'github' - end - def check_limit unless creator.can_create_project? || namespace.kind == 'group' projects_limit = creator.projects_limit -- cgit v1.2.1 From f4c7fea613ad996d855180c9c25f3d0cdca5121a Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Wed, 15 Nov 2017 15:20:36 +0100 Subject: Fix dumping hashed storage based repository --- app/models/project_wiki.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 43de6809178..3eecbea8cbf 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -21,7 +21,7 @@ class ProjectWiki end delegate :empty?, to: :pages - delegate :repository_storage_path, to: :project + delegate :repository_storage_path, :hashed_storage?, to: :project def path @project.path + '.wiki' -- cgit v1.2.1 From 05c10c9bf77db2a9e37e61d1953ef0150289322d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 14 Nov 2017 18:55:00 +0100 Subject: Add total_time_spent to the `changes` hash in issuable Webhook payloads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/models/concerns/issuable.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index c008fb91a16..35090181bd9 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -255,7 +255,7 @@ module Issuable participants(user).include?(user) end - def to_hook_data(user, old_labels: [], old_assignees: []) + def to_hook_data(user, old_labels: [], old_assignees: [], old_total_time_spent: nil) changes = previous_changes if old_labels != labels @@ -270,6 +270,10 @@ module Issuable end end + if old_total_time_spent != total_time_spent + changes[:total_time_spent] = [old_total_time_spent, total_time_spent] + end + Gitlab::HookData::IssuableBuilder.new(self).build(user: user, changes: changes) end -- cgit v1.2.1 From 3e561736b2eb4866b75c57c01769586f058a2f8d Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 15 Nov 2017 15:47:10 +0100 Subject: Cache the number of user SSH keys By caching the number of personal SSH keys we reduce the number of queries necessary on pages such as ProjectsController#show (which can end up querying this data multiple times). The cache is refreshed/flushed whenever an SSH key is added, removed, or when a user is removed. --- app/models/key.rb | 8 ++++++++ app/models/user.rb | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/key.rb b/app/models/key.rb index f119b15c737..815fd1de909 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -27,8 +27,10 @@ class Key < ActiveRecord::Base after_commit :add_to_shell, on: :create after_create :post_create_hook + after_create :refresh_user_cache after_commit :remove_from_shell, on: :destroy after_destroy :post_destroy_hook + after_destroy :refresh_user_cache def key=(value) value&.delete!("\n\r") @@ -76,6 +78,12 @@ class Key < ActiveRecord::Base ) end + def refresh_user_cache + return unless user + + Users::KeysCountService.new(user).refresh_cache + end + def post_destroy_hook SystemHooksService.new.execute_hooks_for(self, :destroy) end diff --git a/app/models/user.rb b/app/models/user.rb index ea10e2854d6..be8112749bf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -170,6 +170,7 @@ class User < ActiveRecord::Base after_save :ensure_namespace_correct after_update :username_changed_hook, if: :username_changed? after_destroy :post_destroy_hook + after_destroy :remove_key_cache after_commit :update_emails_with_primary_email, on: :update, if: -> { previous_changes.key?('email') } after_commit :update_invalid_gpg_signatures, on: :update, if: -> { previous_changes.key?('email') } @@ -624,7 +625,9 @@ class User < ActiveRecord::Base end def require_ssh_key? - keys.count == 0 && Gitlab::ProtocolAccess.allowed?('ssh') + count = Users::KeysCountService.new(self).count + + count.zero? && Gitlab::ProtocolAccess.allowed?('ssh') end def require_password_creation? @@ -886,6 +889,10 @@ class User < ActiveRecord::Base system_hook_service.execute_hooks_for(self, :destroy) end + def remove_key_cache + Users::KeysCountService.new(self).delete_cache + end + def delete_async(deleted_by:, params: {}) block if params[:hard_delete] DeleteUserWorker.perform_async(deleted_by.id, id, params) -- cgit v1.2.1