Commit d3381b32 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch '208147-fj-add-geo-replication-group-wikis' into 'master'

Include group wikis in Geo replication [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!54914
parents 3d59c8a7 b63f476d
...@@ -20,6 +20,7 @@ ActiveSupport::Inflector.inflections do |inflect| ...@@ -20,6 +20,7 @@ ActiveSupport::Inflector.inflections do |inflect|
event_log event_log
file_registry file_registry
group_view group_view
group_wiki_repository_registry
job_artifact_registry job_artifact_registry
lfs_object_registry lfs_object_registry
package_file_registry package_file_registry
......
...@@ -217,6 +217,12 @@ configuration option in `gitlab.yml`. These metrics are served from the ...@@ -217,6 +217,12 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_snippet_repositories_synced` | Gauge | 13.4 | Number of syncable snippets synced on secondary | `url` | | `geo_snippet_repositories_synced` | Gauge | 13.4 | Number of syncable snippets synced on secondary | `url` |
| `geo_snippet_repositories_failed` | Gauge | 13.4 | Number of syncable snippets failed on secondary | `url` | | `geo_snippet_repositories_failed` | Gauge | 13.4 | Number of syncable snippets failed on secondary | `url` |
| `geo_snippet_repositories_registry` | Gauge | 13.4 | Number of syncable snippets in the registry | `url` | | `geo_snippet_repositories_registry` | Gauge | 13.4 | Number of syncable snippets in the registry | `url` |
| `geo_group_wiki_repositories` | Gauge | 13.10 | Number of group wikis on primary | `url` |
| `geo_group_wiki_repositories_checksummed` | Gauge | 13.10 | Number of group wikis checksummed on primary | `url` |
| `geo_group_wiki_repositories_checksum_failed` | Gauge | 13.10 | Number of group wikis failed to calculate the checksum on primary | `url` |
| `geo_group_wiki_repositories_synced` | Gauge | 13.10 | Number of syncable group wikis synced on secondary | `url` |
| `geo_group_wiki_repositories_failed` | Gauge | 13.10 | Number of syncable group wikis failed on secondary | `url` |
| `geo_group_wiki_repositories_registry` | Gauge | 13.10 | Number of syncable group wikis in the registry | `url` |
| `limited_capacity_worker_running_jobs` | Gauge | 13.5 | Number of running jobs | `worker` | | `limited_capacity_worker_running_jobs` | Gauge | 13.5 | Number of running jobs | `worker` |
| `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` | | `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` |
| `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` | | `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` |
......
...@@ -383,7 +383,12 @@ Example response: ...@@ -383,7 +383,12 @@ Example response:
"snippet_repositories_checksum_failed_count": 0, "snippet_repositories_checksum_failed_count": 0,
"snippet_repositories_registry_count": 10, "snippet_repositories_registry_count": 10,
"snippet_repositories_synced_count": 6, "snippet_repositories_synced_count": 6,
"snippet_repositories_failed_count": 3 "snippet_repositories_failed_count": 3,
"group_wiki_repositories_checksummed_count": 10,
"group_wiki_repositories_checksum_failed_count": 0,
"group_wiki_repositories_registry_count": 10,
"group_wiki_repositories_synced_count": 6,
"group_wiki_repositories_failed_count": 3
}, },
{ {
"geo_node_id": 2, "geo_node_id": 2,
...@@ -477,7 +482,12 @@ Example response: ...@@ -477,7 +482,12 @@ Example response:
"snippet_repositories_checksum_failed_count": 0, "snippet_repositories_checksum_failed_count": 0,
"snippet_repositories_registry_count": 10, "snippet_repositories_registry_count": 10,
"snippet_repositories_synced_count": 6, "snippet_repositories_synced_count": 6,
"snippet_repositories_failed_count": 3 "snippet_repositories_failed_count": 3,
"group_wiki_repositories_checksummed_count": 10,
"group_wiki_repositories_checksum_failed_count": 0,
"group_wiki_repositories_registry_count": 10,
"group_wiki_repositories_synced_count": 6,
"group_wiki_repositories_failed_count": 3
} }
] ]
``` ```
......
...@@ -2139,6 +2139,7 @@ Represents an external issue. ...@@ -2139,6 +2139,7 @@ Represents an external issue.
| `containerRepositoriesMaxCapacity` | Int | The maximum concurrency of container repository sync for this secondary node. | | `containerRepositoriesMaxCapacity` | Int | The maximum concurrency of container repository sync for this secondary node. |
| `enabled` | Boolean | Indicates whether this Geo node is enabled. | | `enabled` | Boolean | Indicates whether this Geo node is enabled. |
| `filesMaxCapacity` | Int | The maximum concurrency of LFS/attachment backfill for this secondary node. | | `filesMaxCapacity` | Int | The maximum concurrency of LFS/attachment backfill for this secondary node. |
| `groupWikiRepositoryRegistries` | GroupWikiRepositoryRegistryConnection | Find group wiki repository registries on this Geo node. Available only when feature flag `geo_group_wiki_repository_replication` is enabled. |
| `id` | ID! | ID of this GeoNode. | | `id` | ID! | ID of this GeoNode. |
| `internalUrl` | String | The URL defined on the primary node that secondary nodes should use to contact it. | | `internalUrl` | String | The URL defined on the primary node that secondary nodes should use to contact it. |
| `mergeRequestDiffRegistries` | MergeRequestDiffRegistryConnection | Find merge request diff registries on this Geo node. | | `mergeRequestDiffRegistries` | MergeRequestDiffRegistryConnection | Find merge request diff registries on this Geo node. |
...@@ -2282,6 +2283,21 @@ Contains statistics about a group. ...@@ -2282,6 +2283,21 @@ Contains statistics about a group.
| ----- | ---- | ----------- | | ----- | ---- | ----------- |
| `releaseStats` | GroupReleaseStats | Statistics related to releases within the group. | | `releaseStats` | GroupReleaseStats | Statistics related to releases within the group. |
### `GroupWikiRepositoryRegistry`
Represents the Geo sync and verification state of a group wiki repository.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `createdAt` | Time | Timestamp when the GroupWikiRepositoryRegistry was created |
| `groupWikiRepositoryId` | ID! | ID of the Group Wiki Repository. |
| `id` | ID! | ID of the GroupWikiRepositoryRegistry |
| `lastSyncFailure` | String | Error message during sync of the GroupWikiRepositoryRegistry |
| `lastSyncedAt` | Time | Timestamp of the most recent successful sync of the GroupWikiRepositoryRegistry |
| `retryAt` | Time | Timestamp after which the GroupWikiRepositoryRegistry should be resynced |
| `retryCount` | Int | Number of consecutive failed sync attempts of the GroupWikiRepositoryRegistry |
| `state` | RegistryState | Sync state of the GroupWikiRepositoryRegistry |
### `HttpIntegrationCreatePayload` ### `HttpIntegrationCreatePayload`
Autogenerated return type of HttpIntegrationCreate. Autogenerated return type of HttpIntegrationCreate.
......
# frozen_string_literal: true
module Geo
class GroupWikiRepositoryRegistryFinder
include FrameworkRegistryFinder
end
end
# frozen_string_literal: true
module Resolvers
module Geo
class GroupWikiRepositoryRegistriesResolver < BaseResolver
type ::Types::Geo::GeoNodeType.connection_type, null: true
include RegistriesResolver
end
end
end
...@@ -38,6 +38,11 @@ module Types ...@@ -38,6 +38,11 @@ module Types
null: true, null: true,
resolver: ::Resolvers::Geo::TerraformStateVersionRegistriesResolver, resolver: ::Resolvers::Geo::TerraformStateVersionRegistriesResolver,
description: 'Find terraform state version registries on this Geo node.' description: 'Find terraform state version registries on this Geo node.'
field :group_wiki_repository_registries, ::Types::Geo::GroupWikiRepositoryRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::GroupWikiRepositoryRegistriesResolver,
description: 'Find group wiki repository registries on this Geo node.',
feature_flag: :geo_group_wiki_repository_replication
end end
end end
end end
# frozen_string_literal: true
module Types
module Geo
# rubocop:disable Graphql/AuthorizeTypes because it is included
class GroupWikiRepositoryRegistryType < BaseObject
include ::Types::Geo::RegistryType
graphql_name 'GroupWikiRepositoryRegistry'
description 'Represents the Geo sync and verification state of a group wiki repository'
field :group_wiki_repository_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Group Wiki Repository.'
end
end
end
# frozen_string_literal: true
class Geo::GroupWikiRepositoryRegistry < Geo::BaseRegistry
include Geo::ReplicableRegistry
MODEL_CLASS = ::GroupWikiRepository
MODEL_FOREIGN_KEY = :group_wiki_repository_id
belongs_to :group_wiki_repository, class_name: 'GroupWikiRepository'
end
# frozen_string_literal: true # frozen_string_literal: true
class GroupWikiRepository < ApplicationRecord class GroupWikiRepository < ApplicationRecord
include ::Gitlab::Geo::ReplicableModel
include EachBatch include EachBatch
include Shardable include Shardable
with_replicator Geo::GroupWikiRepositoryReplicator
belongs_to :group belongs_to :group
validates :group, :disk_path, presence: true, uniqueness: true validates :group, :disk_path, presence: true, uniqueness: true
delegate :repository_storage, to: :group
def self.replicables_for_current_secondary(primary_key_in)
node = ::Gitlab::Geo.current_node
replicables = if !node.selective_sync?
all
elsif node.selective_sync_by_namespaces?
group_wiki_repositories_for_selected_namespaces
elsif node.selective_sync_by_shards?
group_wiki_repositories_for_selected_shards
else
self.none
end
replicables.primary_key_in(primary_key_in)
end
def self.group_wiki_repositories_for_selected_namespaces
self.joins(:group).where(group_id: ::Gitlab::Geo.current_node.namespaces_for_group_owned_replicables.select(:id))
end
def self.group_wiki_repositories_for_selected_shards
self.for_repository_storage(::Gitlab::Geo.current_node.selective_sync_shards)
end
def pool_repository
nil
end
def repository
group.wiki.repository
end
end end
# frozen_string_literal: true
module Geo
class GroupWikiRepositoryReplicator < Gitlab::Geo::Replicator
include ::Geo::RepositoryReplicatorStrategy
def self.model
::GroupWikiRepository
end
def self.git_access_class
::Gitlab::GitAccessWiki
end
def repository
model_record.repository
end
def self.replication_enabled_by_default?
false
end
end
end
...@@ -10,7 +10,13 @@ module EE ...@@ -10,7 +10,13 @@ module EE
super.tap do |group| super.tap do |group|
delete_dependency_proxy_blobs(group) delete_dependency_proxy_blobs(group)
log_audit_event unless group&.persisted? unless group&.persisted?
log_audit_event
if ::Gitlab::Geo.primary? && group.group_wiki_repository
group.group_wiki_repository.replicator.handle_after_destroy
end
end
end end
end end
......
...@@ -26,12 +26,13 @@ module EE ...@@ -26,12 +26,13 @@ module EE
def process_wiki_changes(post_received, wiki) def process_wiki_changes(post_received, wiki)
super super
# TODO: Support Geo for group wikis. return unless ::Gitlab::Geo.primary?
# https://gitlab.com/gitlab-org/gitlab/-/issues/208147
return unless wiki.is_a?(ProjectWiki)
if ::Gitlab::Geo.primary? if wiki.is_a?(ProjectWiki)
::Geo::RepositoryUpdatedService.new(wiki.repository).execute ::Geo::RepositoryUpdatedService.new(wiki.repository).execute
else
group_wiki_repository = wiki.group.group_wiki_repository
group_wiki_repository.replicator.handle_after_update if group_wiki_repository
end end
end end
......
...@@ -25,7 +25,8 @@ module Geo ...@@ -25,7 +25,8 @@ module Geo
Geo::ProjectRegistry, Geo::ProjectRegistry,
Geo::TerraformStateVersionRegistry, Geo::TerraformStateVersionRegistry,
Geo::UploadRegistry, Geo::UploadRegistry,
Geo::SnippetRepositoryRegistry Geo::SnippetRepositoryRegistry,
Geo::GroupWikiRepositoryRegistry
].freeze ].freeze
BATCH_SIZE = 10000 BATCH_SIZE = 10000
......
---
title: Include group wikis in Geo replication
merge_request: 54914
author:
type: added
---
name: geo_group_wiki_repository_replication
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54914
rollout_issue_url:
milestone: '13.10'
type: development
group: group::geo
default_enabled: false
# frozen_string_literal: true
class CreateGroupWikiRepositoryRegistry < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
create_table :group_wiki_repository_registry, id: :bigserial, force: :cascade do |t|
t.datetime_with_timezone :retry_at
t.datetime_with_timezone :last_synced_at
t.datetime_with_timezone :created_at, null: false
t.bigint :group_wiki_repository_id, null: false
t.integer :state, default: 0, null: false, limit: 2
t.integer :retry_count, default: 0, limit: 2
t.text :last_sync_failure
t.boolean :force_to_redownload
t.boolean :missing_on_primary
t.index :group_wiki_repository_id, name: :index_g_wiki_repository_registry_on_group_wiki_repository_id, unique: true
t.index :retry_at
t.index :state
end
add_text_limit :group_wiki_repository_registry, :last_sync_failure, 255
end
def down
drop_table :group_wiki_repository_registry
end
end
...@@ -63,6 +63,21 @@ ActiveRecord::Schema.define(version: 2021_02_25_200858) do ...@@ -63,6 +63,21 @@ ActiveRecord::Schema.define(version: 2021_02_25_200858) do
t.index ["success"], name: "index_file_registry_on_success" t.index ["success"], name: "index_file_registry_on_success"
end end
create_table "group_wiki_repository_registry", force: :cascade do |t|
t.datetime_with_timezone "retry_at"
t.datetime_with_timezone "last_synced_at"
t.datetime_with_timezone "created_at", null: false
t.bigint "group_wiki_repository_id", null: false
t.integer "state", limit: 2, default: 0, null: false
t.integer "retry_count", limit: 2, default: 0
t.text "last_sync_failure"
t.boolean "force_to_redownload"
t.boolean "missing_on_primary"
t.index ["group_wiki_repository_id"], name: "index_g_wiki_repository_registry_on_group_wiki_repository_id", unique: true
t.index ["retry_at"], name: "index_group_wiki_repository_registry_on_retry_at"
t.index ["state"], name: "index_group_wiki_repository_registry_on_state"
end
create_table "job_artifact_registry", id: :serial, force: :cascade do |t| create_table "job_artifact_registry", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "created_at" t.datetime_with_timezone "created_at"
t.datetime_with_timezone "retry_at" t.datetime_with_timezone "retry_at"
......
...@@ -57,6 +57,8 @@ module EE ...@@ -57,6 +57,8 @@ module EE
end end
def can_read_group? def can_read_group?
return true if geo?
if user if user
user.can?(:read_group, group) user.can?(:read_group, group)
else else
......
...@@ -23,7 +23,8 @@ module Gitlab ...@@ -23,7 +23,8 @@ module Gitlab
::Geo::MergeRequestDiffReplicator, ::Geo::MergeRequestDiffReplicator,
::Geo::PackageFileReplicator, ::Geo::PackageFileReplicator,
::Geo::TerraformStateVersionReplicator, ::Geo::TerraformStateVersionReplicator,
::Geo::SnippetRepositoryReplicator ::Geo::SnippetRepositoryReplicator,
::Geo::GroupWikiRepositoryReplicator
].freeze ].freeze
def self.current_node def self.current_node
......
# frozen_string_literal: true
FactoryBot.define do
factory :geo_group_wiki_repository_registry, class: 'Geo::GroupWikiRepositoryRegistry' do
group_wiki_repository
state { Geo::GroupWikiRepositoryRegistry.state_value(:pending) }
trait :synced do
state { Geo::GroupWikiRepositoryRegistry.state_value(:synced) }
last_synced_at { 5.days.ago }
end
trait :failed do
state { Geo::GroupWikiRepositoryRegistry.state_value(:failed) }
last_synced_at { 1.day.ago }
retry_count { 2 }
last_sync_failure { 'Random error' }
end
trait :started do
state { Geo::GroupWikiRepositoryRegistry.state_value(:started) }
last_synced_at { 1.day.ago }
retry_count { 0 }
end
end
end
# frozen_string_literal: true
FactoryBot.define do
factory :group_wiki_repository do
group
after(:build) do |group_wiki_repository, _|
group_wiki_repository.shard_name = group_wiki_repository.repository_storage
group_wiki_repository.disk_path = group_wiki_repository.group.wiki.storage.disk_path
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::GroupWikiRepositoryRegistryFinder do
it_behaves_like 'a framework registry finder', :geo_group_wiki_repository_registry
end
...@@ -96,6 +96,18 @@ ...@@ -96,6 +96,18 @@
"snippet_repositories_verification_total_count", "snippet_repositories_verification_total_count",
"snippet_repositories_verified_count", "snippet_repositories_verified_count",
"snippet_repositories_verified_in_percentage", "snippet_repositories_verified_in_percentage",
"group_wiki_repositories_count",
"group_wiki_repositories_checksum_total_count",
"group_wiki_repositories_checksummed_count",
"group_wiki_repositories_checksum_failed_count",
"group_wiki_repositories_synced_count",
"group_wiki_repositories_failed_count",
"group_wiki_repositories_registry_count",
"group_wiki_repositories_verification_total_count",
"group_wiki_repositories_verified_count",
"group_wiki_repositories_verification_failed_count",
"group_wiki_repositories_synced_in_percentage",
"group_wiki_repositories_verified_in_percentage",
"repositories_verified_count", "repositories_verified_count",
"repositories_verification_failed_count", "repositories_verification_failed_count",
"repositories_verification_total_count", "repositories_verification_total_count",
...@@ -229,6 +241,18 @@ ...@@ -229,6 +241,18 @@
"snippet_repositories_verification_total_count": { "type": ["integer", "null"] }, "snippet_repositories_verification_total_count": { "type": ["integer", "null"] },
"snippet_repositories_verified_count": { "type": ["integer", "null"] }, "snippet_repositories_verified_count": { "type": ["integer", "null"] },
"snippet_repositories_verified_in_percentage": { "type": "string" }, "snippet_repositories_verified_in_percentage": { "type": "string" },
"group_wiki_repositories_count": { "type": ["integer", "null"] },
"group_wiki_repositories_checksummed_count": { "type": ["integer", "null"] },
"group_wiki_repositories_checksum_failed_count": { "type": ["integer", "null"] },
"group_wiki_repositories_checksum_total_count": { "type": ["integer", "null"] },
"group_wiki_repositories_registry_count": { "type": ["integer", "null"] },
"group_wiki_repositories_failed_count": { "type": ["integer", "null"] },
"group_wiki_repositories_synced_count": { "type": ["integer", "null"] },
"group_wiki_repositories_synced_in_percentage": { "type": "string" },
"group_wiki_repositories_verification_failed_count": { "type": ["integer", "null"] },
"group_wiki_repositories_verification_total_count": { "type": ["integer", "null"] },
"group_wiki_repositories_verified_count": { "type": ["integer", "null"] },
"group_wiki_repositories_verified_in_percentage": { "type": "string" },
"repositories_verified_count": { "type": ["integer", "null"] }, "repositories_verified_count": { "type": ["integer", "null"] },
"repositories_verification_failed_count": { "type": ["integer", "null"] }, "repositories_verification_failed_count": { "type": ["integer", "null"] },
"repositories_verification_total_count": { "type": ["integer", "null"] }, "repositories_verification_total_count": { "type": ["integer", "null"] },
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::Geo::GroupWikiRepositoryRegistriesResolver do
it_behaves_like 'a Geo registries resolver', :geo_group_wiki_repository_registry
end
...@@ -13,7 +13,7 @@ RSpec.describe GitlabSchema.types['GeoNode'] do ...@@ -13,7 +13,7 @@ RSpec.describe GitlabSchema.types['GeoNode'] do
selective_sync_type selective_sync_shards selective_sync_namespaces selective_sync_type selective_sync_shards selective_sync_namespaces
minimum_reverification_interval merge_request_diff_registries minimum_reverification_interval merge_request_diff_registries
package_file_registries snippet_repository_registries package_file_registries snippet_repository_registries
terraform_state_version_registries terraform_state_version_registries group_wiki_repository_registries
] ]
expect(described_class).to have_graphql_fields(*expected_fields) expect(described_class).to have_graphql_fields(*expected_fields)
......
...@@ -108,6 +108,14 @@ RSpec.describe Gitlab::GitAccessWiki do ...@@ -108,6 +108,14 @@ RSpec.describe Gitlab::GitAccessWiki do
end end
end end
context 'when actor is geo' do
let(:user) { :geo }
it 'gives access to download wiki code' do
expect { subject }.not_to raise_error
end
end
context 'the group is public' do context 'the group is public' do
let(:group) { create(:group, :public, :wiki_repo) } let(:group) { create(:group, :public, :wiki_repo) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::GroupWikiRepositoryRegistry, :geo, type: :model do
let_it_be(:registry) { create(:geo_group_wiki_repository_registry) }
specify 'factory is valid' do
expect(registry).to be_valid
end
include_examples 'a Geo framework registry'
end
...@@ -1162,6 +1162,7 @@ RSpec.describe GeoNodeStatus, :geo do ...@@ -1162,6 +1162,7 @@ RSpec.describe GeoNodeStatus, :geo do
Geo::PackageFileReplicator | :package_file | :geo_package_file_registry Geo::PackageFileReplicator | :package_file | :geo_package_file_registry
Geo::TerraformStateVersionReplicator | :terraform_state_version | :geo_terraform_state_version_registry Geo::TerraformStateVersionReplicator | :terraform_state_version | :geo_terraform_state_version_registry
Geo::SnippetRepositoryReplicator | :snippet_repository | :geo_snippet_repository_registry Geo::SnippetRepositoryReplicator | :snippet_repository | :geo_snippet_repository_registry
Geo::GroupWikiRepositoryReplicator | :group_wiki_repository | :geo_group_wiki_repository_registry
end end
with_them do with_them do
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe GroupWikiRepository do RSpec.describe GroupWikiRepository, :geo do
describe 'associations' do describe 'associations' do
it { is_expected.to belong_to(:shard) } it { is_expected.to belong_to(:shard) }
it { is_expected.to belong_to(:group) } it { is_expected.to belong_to(:group) }
...@@ -20,4 +20,109 @@ RSpec.describe GroupWikiRepository do ...@@ -20,4 +20,109 @@ RSpec.describe GroupWikiRepository do
it { is_expected.to validate_uniqueness_of(:disk_path) } it { is_expected.to validate_uniqueness_of(:disk_path) }
end end
end end
describe 'Geo Replication' do
include EE::GeoHelpers
let(:node) { create(:geo_node) }
before do
stub_current_geo_node(node)
end
context 'with root group and subgroup wikis' do
let_it_be(:root_group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: root_group) }
let_it_be(:root_group_wiki_repository) { create(:group_wiki_repository, group: root_group) }
let_it_be(:subgroup_wiki_repository) { create(:group_wiki_repository, group: subgroup) }
let_it_be(:broken_wiki_repository) { create(:group_wiki_repository, shard_name: 'broken') }
describe '#in_replicables_for_current_secondary?' do
it 'all returns true if all are replicated' do
[
root_group_wiki_repository,
subgroup_wiki_repository,
broken_wiki_repository
].each do |repository|
expect(repository.in_replicables_for_current_secondary?).to be true
end
end
context 'with selective sync by namespace' do
before do
node.update!(selective_sync_type: 'namespaces', namespaces: [root_group])
end
it 'returns true for groups' do
expect(root_group_wiki_repository.in_replicables_for_current_secondary?).to be true
end
it 'returns true for subgroups' do
expect(subgroup_wiki_repository.in_replicables_for_current_secondary?).to be true
end
end
context 'with selective sync by shard' do
before do
node.update!(selective_sync_type: 'shards', selective_sync_shards: ['default'])
end
it 'returns true for groups in the shard' do
expect(root_group_wiki_repository.in_replicables_for_current_secondary?).to be true
expect(subgroup_wiki_repository.in_replicables_for_current_secondary?).to be true
end
it 'returns false for group wiki repositories not in an included shard' do
expect(broken_wiki_repository.in_replicables_for_current_secondary?).to be false
end
end
end
describe '#replicables_for_current_secondary' do
it 'returns all group wiki repositories without selective sync' do
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to match_array([
root_group_wiki_repository,
subgroup_wiki_repository,
broken_wiki_repository
])
end
context 'with selective sync by namespace' do
it 'returns group wiki repositories that belong to the namespaces and descendants' do
node.update!(selective_sync_type: 'namespaces', namespaces: [root_group])
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to match_array([
root_group_wiki_repository,
subgroup_wiki_repository
])
end
it 'returns group wiki repositories that belong to the namespace' do
node.update!(selective_sync_type: 'namespaces', namespaces: [subgroup])
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to match_array([
subgroup_wiki_repository
])
end
end
context 'with selective sync by shard' do
it 'returns group wiki repositories that belong to the shards' do
node.update!(selective_sync_type: 'shards', selective_sync_shards: ['default'])
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to match_array([
root_group_wiki_repository,
subgroup_wiki_repository
])
end
end
it 'returns nothing if an unrecognised selective sync type is used' do
node.update_attribute(:selective_sync_type, 'unknown')
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to be_empty
end
end
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::GroupWikiRepositoryReplicator do
let(:model_record) { build(:group_wiki_repository, group: create(:group)) }
include_examples 'a repository replicator'
end
...@@ -30,4 +30,11 @@ RSpec.describe 'Gets registries' do ...@@ -30,4 +30,11 @@ RSpec.describe 'Gets registries' do
registry_factory: :geo_terraform_state_version_registry, registry_factory: :geo_terraform_state_version_registry,
registry_foreign_key_field_name: 'terraformStateVersionId' registry_foreign_key_field_name: 'terraformStateVersionId'
} }
it_behaves_like 'gets registries for', {
field_name: 'groupWikiRepositoryRegistries',
registry_class_name: 'GroupWikiRepositoryRegistry',
registry_factory: :geo_group_wiki_repository_registry,
registry_foreign_key_field_name: 'groupWikiRepositoryId'
}
end end
...@@ -45,4 +45,36 @@ RSpec.describe Groups::DestroyService do ...@@ -45,4 +45,36 @@ RSpec.describe Groups::DestroyService do
expect { subject.execute }.to change { DependencyProxy::Blob.count }.by(-1) expect { subject.execute }.to change { DependencyProxy::Blob.count }.by(-1)
end end
end end
context 'when on a Geo primary node' do
before do
allow(Gitlab::Geo).to receive(:primary?) { true }
end
context 'when group_wiki_repository does not exist' do
it 'does not call replicator to update Geo' do
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator).never
subject.execute
end
end
it 'calls replicator to update Geo' do
group.wiki.create_wiki_repository
expect(group.group_wiki_repository.replicator).to receive(:handle_after_destroy)
subject.execute
end
end
context 'when not on a Geo primary node' do
it 'does not call replicator to update Geo' do
group.wiki.create_wiki_repository
expect(group.group_wiki_repository.replicator).not_to receive(:handle_after_destroy)
subject.execute
end
end
end end
...@@ -139,12 +139,60 @@ RSpec.describe PostReceive do ...@@ -139,12 +139,60 @@ RSpec.describe PostReceive do
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
it 'does not call Geo::RepositoryUpdatedService when running on a Geo primary node' do context 'when on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { true } before do
allow(Gitlab::Geo).to receive(:primary?) { true }
end
expect_next_instance_of(::Geo::RepositoryUpdatedService).never it 'does not call Geo::RepositoryUpdatedService' do
expect_next_instance_of(::Geo::RepositoryUpdatedService).never
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end
context 'when wiki is a project wiki' do
let(:wiki) { build(:project_wiki, project: project) }
it 'does not call replicator to update Geo' do
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator).never
described_class.new.perform(gl_repository, key_id, base64_changes)
end
end
context 'when group_wiki_repository does not exist' do
it 'does not call replicator to update Geo' do
expect(group.group_wiki_repository).to be_nil
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator).never
described_class.new.perform(gl_repository, key_id, base64_changes)
end
end
context 'when group_wiki_repository exists' do
it 'calls replicator to update Geo' do
wiki.create_wiki_repository
expect(group.group_wiki_repository).to be_present
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator) do |instance|
expect(instance).to receive(:handle_after_update)
end
described_class.new.perform(gl_repository, key_id, base64_changes)
end
end
end
context 'when not on a Geo primary node' do
it 'does not call replicator to update Geo' do
wiki.create_wiki_repository
expect(group.group_wiki_repository).to be_present
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator).never
described_class.new.perform(gl_repository, key_id, base64_changes)
end
end end
end end
end end
......
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