Commit c3ed82b5 authored by Gabriel Mazetto's avatar Gabriel Mazetto

Initial displaying of Geo Nodes > Projects

parent 127c60a0
......@@ -14,7 +14,19 @@ class Admin::GeoNodesController < Admin::ApplicationController
end
def projects
@nodes = GeoNode.all.order(:id)
finder = Geo::ProjectRegistryStatusFinder.new
case params[:sync_status]
when 'never'
@projects = finder.never_synced_projects.page(params[:page])
when 'failed'
@registries = finder.failed_projects.page(params[:page])
when 'pending'
@registries = finder.pending_projects.page(params[:page])
else
@registries = finder.synced_projects.page(params[:page])
end
# Gitlab::Geo.current_node.projects.includes(:project_registry).page(params[:page])
end
def create
......
module Geo
# Finders specific for Project status listing and inspecting
#
# This finders works slightly different than the ones used to trigger
# synchronization, as we are concerned in filtering for displaying rather then
# filtering for processing.
class ProjectRegistryStatusFinder < RegistryFinder
# Returns any project registry which project is fully synced
#
# We consider fully synced any project without pending actions
# or failures
def synced_projects
Geo::ProjectRegistry.all.includes(:project)
end
# Return any project registry which project is pending to update
#
# We include here only projects that have successfully synced before.
# We exclude projects that have tried to resync already and had failures
def pending_projects
no_repository_sync_failure = project_registry[:repository_retry_count].eq(nil)
no_wiki_sync_failure = project_registry[:wiki_retry_count].eq(nil)
Geo::ProjectRegistry.where(
project_registry[:resync_repository].eq(true)
.or(project_registry[:resync_wiki].eq(true))
.and(no_repository_sync_failure.and(no_wiki_sync_failure))
).includes(:project)
end
# Return any project registry which project has a failure
#
# Both types of failures are included: Synchronization and Verification
def failed_projects
Geo::ProjectRegistry.failed.includes(:project)
end
# Return projects that has never been fully synced
#
# We include here both projects without a corresponding ProjectRegistry
# or projects that have never successfully synced.
#
# @return [Geo::Fdw::Project] Projects that has never been fully synced
def never_synced_projects
no_project_registry = project_registry[:project_id].eq(nil)
no_repository_synced = project_registry[:last_repository_successful_sync_at].eq(nil)
Geo::Fdw::Project.joins("LEFT OUTER JOIN project_registry ON (project_registry.project_id = #{Geo::Fdw::Project.table_name}.id)").where(no_project_registry.or(no_repository_synced)).includes(:project_registry)
end
private
def project_registry
Geo::ProjectRegistry.arel_table
end
end
end
......@@ -23,6 +23,7 @@ module EE
belongs_to :mirror_user, foreign_key: 'mirror_user_id', class_name: 'User'
has_one :repository_state, class_name: 'ProjectRepositoryState', inverse_of: :project
has_one :project_registry, class_name: 'Geo::ProjectRegistry', inverse_of: :project
has_one :push_rule, ->(project) { project&.feature_available?(:push_rules) ? all : none }
has_one :index_status
has_one :jenkins_service
......
......@@ -2,6 +2,8 @@ module Geo
module Fdw
class Project < ::Geo::BaseFdw
self.table_name = Gitlab::Geo::Fdw.table('projects')
has_one :project_registry, class_name: 'Geo::ProjectRegistry'
end
end
end
......@@ -21,6 +21,7 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
validates :project, presence: true, uniqueness: true
scope :never_synced, -> { where(last_repository_synced_at: nil) }
scope :dirty, -> { where(arel_table[:resync_repository].eq(true).or(arel_table[:resync_wiki].eq(true))) }
scope :synced_repos, -> { where(resync_repository: false) }
scope :synced_wikis, -> { where(resync_wiki: false) }
......
- @registries.each do |project_registry|
.card.project-card.prepend-top-15
.card-header{id: "project-#{project_registry.project.id}-header"}
%h5.mb-0.mt-0.p-2.d-flex
%button.btn.btn-link.btn-card-header.d-flex.flex-fill{ type: 'button', data: { toggle: 'collapse', target: "#project-#{project_registry.project.id}" }, 'aria-expanded' => 'true', 'aria-controls' => "project-#{project_registry.project.id}" }
= sprite_icon('chevron-down', size: 18, css_class: 'card-expand-icon')
= sprite_icon('chevron-up', size: 18, css_class: 'card-collapse-icon')
%strong.header-text
= project_registry.project.name
%button.btn.btn-outline-primary.btn-sm{ type: 'button' }
Resync
.collapse.show{id: "project-#{project_registry.project.id}", 'aria-labelledby' => "project-#{project_registry.project.id}-header" }
.card-body
.container
.row
.col-sm.project-status-container
.project-status-title.text-muted
Next sync scheduled at
.project-status-content
= distance_of_time_in_words(Time.now, project_registry.repository_retry_at) if project_registry.repository_retry_at
.col-sm.project-status-container
.project-status-title.text-muted
Last sync attempt
.project-status-content
= distance_of_time_in_words(Time.now, project_registry.last_repository_synced_at)
.col-sm.project-status-container
.project-status-title.text-muted
Retry counts
.project-status-content
= project_registry.repository_retry_count
.col-sm.project-status-container
.project-status-title.text-muted
Error message
.project-status-content.font-weight-bold
= project_registry.last_repository_sync_failure
- @projects.each do |project|
.card.project-card.prepend-top-15
.card-header{id: "project-#{project.id}-header"}
%h5.mb-0.mt-0.p-2.d-flex
%button.btn.btn-link.btn-card-header.d-flex.flex-fill{ type: 'button', data: { toggle: 'collapse', target: "#project-#{project.id}" }, 'aria-expanded' => 'true', 'aria-controls' => "project-#{project.id}" }
= sprite_icon('chevron-down', size: 18, css_class: 'card-expand-icon')
= sprite_icon('chevron-up', size: 18, css_class: 'card-collapse-icon')
%strong.header-text
= project.name
%button.btn.btn-outline-primary.btn-sm{ type: 'button' }
Resync
.collapse.show{id: "project-#{project.id}", 'aria-labelledby' => "project-#{project.id}-header" }
.card-body
.container
.row
.col-sm.project-status-container
.project-status-title.text-muted
Next sync scheduled at
.project-status-content
= distance_of_time_in_words(Time.now, project.project_registry.repository_retry_at) if project.project_registry&.repository_retry_at
.col-sm.project-status-container
.project-status-title.text-muted
Last sync attempt
.project-status-content
= distance_of_time_in_words(Time.now, project.project_registry.last_repository_synced_at) if project.project_registry&.last_repository_synced_at
.col-sm.project-status-container
.project-status-title.text-muted
Retry counts
.project-status-content
= project.project_registry.repository_retry_count if project.project_registry
.col-sm.project-status-container
.project-status-title.text-muted
Error message
.project-status-content.font-weight-bold
= project.project_registry.last_repository_sync_failure if project.project_registry
......@@ -10,85 +10,20 @@
= nav_link(opts) do
= link_to projects_admin_geo_nodes_path do
= _("All")
= nav_link(html_options: { class: active_when(params[:sync_status] == "1") }) do
= link_to projects_admin_geo_nodes_path(sync_status: "1") do
= nav_link(html_options: { class: active_when(params[:sync_status] == 'pending') }) do
= link_to projects_admin_geo_nodes_path(sync_status: 'pending') do
= _("Pending")
= nav_link(html_options: { class: active_when(params[:sync_status] == "2") }) do
= link_to projects_admin_geo_nodes_path(sync_status: "2") do
= _("Failures")
= nav_link(html_options: { class: active_when(params[:sync_status] == "3") }) do
= link_to projects_admin_geo_nodes_path(sync_status: "3") do
= nav_link(html_options: { class: active_when(params[:sync_status] == 'failed') }) do
= link_to projects_admin_geo_nodes_path(sync_status: 'failed') do
= _("Failed")
= nav_link(html_options: { class: active_when(params[:sync_status] == 'never') }) do
= link_to projects_admin_geo_nodes_path(sync_status: 'never') do
= _("Never")
.card.project-card.prepend-top-15
#gitlab-ce-header.card-header
%h5.mb-0.mt-0.p-2.d-flex
%button.btn.btn-link.btn-card-header.d-flex.flex-fill{ type: 'button', data: { toggle: 'collapse', target: '#gitlab-ce' }, 'aria-expanded' => 'true', 'aria-controls' => 'gitlab-ce' }
= sprite_icon('chevron-down', size: 18, css_class: 'card-expand-icon')
= sprite_icon('chevron-up', size: 18, css_class: 'card-collapse-icon')
%strong.header-text
GitLab Community Edition
%button.btn.btn-outline-primary.btn-sm{ type: 'button' }
Resync
#gitlab-ce.collapse.show{ 'aria-labelledby' => 'gitlab-ce-header' }
.card-body
.container
.row
.col-sm.project-status-container
.project-status-title.text-muted
Next sync scheduled at
.project-status-content
5 mins later
.col-sm.project-status-container
.project-status-title.text-muted
Last sync attempt
.project-status-content
Yesterday 10:00 pm
.col-sm.project-status-container
.project-status-title.text-muted
Retry counts
.project-status-content
5
.col-sm.project-status-container
.project-status-title.text-muted
Error message
.project-status-content.font-weight-bold
Could not move repository out of the way
- case params[:sync_status]
- when 'never'
= render(partial: 'never')
- else
= render(partial: 'all')
.card.project-card
#gitlab-ee-header.card-header
%h5.mb-0.mt-0.p-2.d-flex
%button.btn.btn-link.btn-card-header.d-flex.flex-fill{ type: 'button', data: { toggle: 'collapse', target: '#gitlab-ee' }, 'aria-expanded' => 'true', 'aria-controls' => 'gitlab-ee' }
= sprite_icon('chevron-down', size: 18, css_class: 'card-expand-icon')
= sprite_icon('chevron-up', size: 18, css_class: 'card-collapse-icon')
%strong.header-text
GitLab Enterprise Edition
%button.btn.btn-outline-primary.btn-sm{ type: 'button' }
Resync
#gitlab-ee.collapse.show{ 'aria-labelledby' => 'gitlab-ee-header' }
.card-body
.container
.row
.col-sm.project-status-container
.project-status-title.text-muted
Next sync scheduled at
.project-status-content
5 mins later
.col-sm.project-status-container
.project-status-title.text-muted
Last sync attempt
.project-status-content
Yesterday 10:00 pm
.col-sm.project-status-container
.project-status-title.text-muted
Retry counts
.project-status-content
5
.col-sm.project-status-container
.project-status-title.text-muted
Error message
.project-status-content.font-weight-bold
Could not move repository out of the way
......@@ -339,6 +339,7 @@ project:
- prometheus_alerts
- software_license_policies
- repository_languages
- project_registry
award_emoji:
- awardable
- user
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment