Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4203215d54
commit
073ebdcae8
|
@ -339,8 +339,8 @@ Graphql/AuthorizeTypes:
|
|||
Graphql/JSONType:
|
||||
Enabled: true
|
||||
Include:
|
||||
- 'app/graphql/types/**/*'
|
||||
- 'ee/app/graphql/types/**/*'
|
||||
- 'app/graphql/**/*'
|
||||
- 'ee/app/graphql/**/*'
|
||||
Exclude:
|
||||
- 'spec/**/*.rb'
|
||||
- 'ee/spec/**/*.rb'
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
<script>
|
||||
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { last } from 'lodash';
|
||||
import { __ } from '~/locale';
|
||||
import getJiraImportDetailsQuery from '../queries/get_jira_import_details.query.graphql';
|
||||
import getJiraUserMappingMutation from '../queries/get_jira_user_mapping.mutation.graphql';
|
||||
import initiateJiraImportMutation from '../queries/initiate_jira_import.mutation.graphql';
|
||||
import { addInProgressImportToStore } from '../utils/cache_update';
|
||||
import { isInProgress, extractJiraProjectsOptions } from '../utils/jira_import_utils';
|
||||
import JiraImportForm from './jira_import_form.vue';
|
||||
import JiraImportProgress from './jira_import_progress.vue';
|
||||
|
@ -52,9 +48,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
isSubmitting: false,
|
||||
jiraImportDetails: {},
|
||||
userMappings: [],
|
||||
errorMessage: '',
|
||||
showAlert: false,
|
||||
};
|
||||
|
@ -78,70 +72,7 @@ export default {
|
|||
},
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.isJiraConfigured) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: getJiraUserMappingMutation,
|
||||
variables: {
|
||||
input: {
|
||||
projectPath: this.projectPath,
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(({ data }) => {
|
||||
if (data.jiraImportUsers.errors.length) {
|
||||
this.setAlertMessage(data.jiraImportUsers.errors.join('. '));
|
||||
} else {
|
||||
this.userMappings = data.jiraImportUsers.jiraUsers;
|
||||
}
|
||||
})
|
||||
.catch(() => this.setAlertMessage(__('There was an error retrieving the Jira users.')));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initiateJiraImport(project) {
|
||||
this.isSubmitting = true;
|
||||
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: initiateJiraImportMutation,
|
||||
variables: {
|
||||
input: {
|
||||
jiraProjectKey: project,
|
||||
projectPath: this.projectPath,
|
||||
usersMapping: this.userMappings.map(({ gitlabId, jiraAccountId }) => ({
|
||||
gitlabId,
|
||||
jiraAccountId,
|
||||
})),
|
||||
},
|
||||
},
|
||||
update: (store, { data }) =>
|
||||
addInProgressImportToStore(store, data.jiraImportStart, this.projectPath),
|
||||
})
|
||||
.then(({ data }) => {
|
||||
if (data.jiraImportStart.errors.length) {
|
||||
this.setAlertMessage(data.jiraImportStart.errors.join('. '));
|
||||
} else {
|
||||
this.selectedProject = undefined;
|
||||
}
|
||||
})
|
||||
.catch(() => this.setAlertMessage(__('There was an error importing the Jira project.')))
|
||||
.finally(() => {
|
||||
this.isSubmitting = false;
|
||||
});
|
||||
},
|
||||
updateMapping(jiraAccountId, gitlabId, gitlabUsername) {
|
||||
this.userMappings = this.userMappings.map(userMapping =>
|
||||
userMapping.jiraAccountId === jiraAccountId
|
||||
? {
|
||||
...userMapping,
|
||||
gitlabId,
|
||||
gitlabUsername,
|
||||
}
|
||||
: userMapping,
|
||||
);
|
||||
},
|
||||
setAlertMessage(message) {
|
||||
this.errorMessage = message;
|
||||
this.showAlert = true;
|
||||
|
@ -175,14 +106,12 @@ export default {
|
|||
/>
|
||||
<jira-import-form
|
||||
v-else
|
||||
:is-submitting="isSubmitting"
|
||||
:issues-path="issuesPath"
|
||||
:jira-imports="jiraImportDetails.imports"
|
||||
:jira-projects="jiraImportDetails.projects"
|
||||
:project-id="projectId"
|
||||
:user-mappings="userMappings"
|
||||
@initiateJiraImport="initiateJiraImport"
|
||||
@updateMapping="updateMapping"
|
||||
:project-path="projectPath"
|
||||
@error="setAlertMessage"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -16,6 +16,10 @@ import {
|
|||
} from '@gitlab/ui';
|
||||
import { debounce } from 'lodash';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { __ } from '~/locale';
|
||||
import getJiraUserMappingMutation from '../queries/get_jira_user_mapping.mutation.graphql';
|
||||
import initiateJiraImportMutation from '../queries/initiate_jira_import.mutation.graphql';
|
||||
import { addInProgressImportToStore } from '../utils/cache_update';
|
||||
import {
|
||||
debounceWait,
|
||||
dropdownLabel,
|
||||
|
@ -47,10 +51,6 @@ export default {
|
|||
tableConfig,
|
||||
userMappingMessage,
|
||||
props: {
|
||||
isSubmitting: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
issuesPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
@ -67,17 +67,19 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
userMappings: {
|
||||
type: Array,
|
||||
projectPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isFetching: false,
|
||||
isSubmitting: false,
|
||||
searchTerm: '',
|
||||
selectedProject: undefined,
|
||||
selectState: null,
|
||||
userMappings: [],
|
||||
users: [],
|
||||
};
|
||||
},
|
||||
|
@ -106,6 +108,24 @@ export default {
|
|||
}, debounceWait),
|
||||
},
|
||||
mounted() {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: getJiraUserMappingMutation,
|
||||
variables: {
|
||||
input: {
|
||||
projectPath: this.projectPath,
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(({ data }) => {
|
||||
if (data.jiraImportUsers.errors.length) {
|
||||
this.$emit('error', data.jiraImportUsers.errors.join('. '));
|
||||
} else {
|
||||
this.userMappings = data.jiraImportUsers.jiraUsers;
|
||||
}
|
||||
})
|
||||
.catch(() => this.$emit('error', __('There was an error retrieving the Jira users.')));
|
||||
|
||||
this.searchUsers()
|
||||
.then(data => {
|
||||
this.initialUsers = data;
|
||||
|
@ -138,13 +158,54 @@ export default {
|
|||
},
|
||||
initiateJiraImport(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (this.selectedProject) {
|
||||
this.hideValidationError();
|
||||
this.$emit('initiateJiraImport', this.selectedProject);
|
||||
|
||||
this.isSubmitting = true;
|
||||
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: initiateJiraImportMutation,
|
||||
variables: {
|
||||
input: {
|
||||
jiraProjectKey: this.selectedProject,
|
||||
projectPath: this.projectPath,
|
||||
usersMapping: this.userMappings.map(({ gitlabId, jiraAccountId }) => ({
|
||||
gitlabId,
|
||||
jiraAccountId,
|
||||
})),
|
||||
},
|
||||
},
|
||||
update: (store, { data }) =>
|
||||
addInProgressImportToStore(store, data.jiraImportStart, this.projectPath),
|
||||
})
|
||||
.then(({ data }) => {
|
||||
if (data.jiraImportStart.errors.length) {
|
||||
this.$emit('error', data.jiraImportStart.errors.join('. '));
|
||||
} else {
|
||||
this.selectedProject = undefined;
|
||||
}
|
||||
})
|
||||
.catch(() => this.$emit('error', __('There was an error importing the Jira project.')))
|
||||
.finally(() => {
|
||||
this.isSubmitting = false;
|
||||
});
|
||||
} else {
|
||||
this.showValidationError();
|
||||
}
|
||||
},
|
||||
updateMapping(jiraAccountId, gitlabId, gitlabUsername) {
|
||||
this.userMappings = this.userMappings.map(userMapping =>
|
||||
userMapping.jiraAccountId === jiraAccountId
|
||||
? {
|
||||
...userMapping,
|
||||
gitlabId,
|
||||
gitlabUsername,
|
||||
}
|
||||
: userMapping,
|
||||
);
|
||||
},
|
||||
hideValidationError() {
|
||||
this.selectState = null;
|
||||
},
|
||||
|
@ -227,7 +288,7 @@ export default {
|
|||
v-for="user in users"
|
||||
v-else
|
||||
:key="user.id"
|
||||
@click="$emit('updateMapping', data.item.jiraAccountId, user.id, user.username)"
|
||||
@click="updateMapping(data.item.jiraAccountId, user.id, user.username)"
|
||||
>
|
||||
{{ user.username }} ({{ user.name }})
|
||||
</gl-new-dropdown-item>
|
||||
|
|
|
@ -156,6 +156,9 @@ function deferredInitialisation() {
|
|||
});
|
||||
|
||||
loadAwardsHandler();
|
||||
|
||||
// Adding a helper class to activate animations only after all is rendered
|
||||
setTimeout(() => $body.addClass('page-initialised'), 1000);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
.content-wrapper {
|
||||
width: 100%;
|
||||
transition: padding $sidebar-transition-duration;
|
||||
|
||||
.container-fluid {
|
||||
padding: 0 $gl-padding;
|
||||
|
@ -13,6 +12,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.page-initialised .content-wrapper {
|
||||
transition: padding $sidebar-transition-duration;
|
||||
}
|
||||
|
||||
.nav-header-btn {
|
||||
padding: 10px $gl-sidebar-padding;
|
||||
color: inherit;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDeleteOriginalIndexAtToReindexingTasks < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
add_column :elastic_reindexing_tasks, :delete_original_index_at, :datetime_with_timezone
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_column :elastic_reindexing_tasks, :delete_original_index_at
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
867cea94f966c1ad3d9e02f7fa5b641ceac5a71667426330c2c96d6181164f66
|
|
@ -11353,6 +11353,7 @@ CREATE TABLE public.elastic_reindexing_tasks (
|
|||
elastic_task text,
|
||||
error_message text,
|
||||
documents_count_target integer,
|
||||
delete_original_index_at timestamp with time zone,
|
||||
CONSTRAINT check_04151aca42 CHECK ((char_length(index_name_from) <= 255)),
|
||||
CONSTRAINT check_7f64acda8e CHECK ((char_length(error_message) <= 255)),
|
||||
CONSTRAINT check_85ebff7124 CHECK ((char_length(index_name_to) <= 255)),
|
||||
|
|
|
@ -37,8 +37,7 @@ recover. See below for more details.
|
|||
The following guide assumes that:
|
||||
|
||||
- You are using Omnibus and therefore you are using PostgreSQL 11 or later
|
||||
which includes the [`pg_basebackup` tool](https://www.postgresql.org/docs/11/app-pgbasebackup.html) and improved
|
||||
[Foreign Data Wrapper](https://www.postgresql.org/docs/11/postgres-fdw.html) support.
|
||||
which includes the [`pg_basebackup` tool](https://www.postgresql.org/docs/11/app-pgbasebackup.html).
|
||||
- You have a **primary** node already set up (the GitLab server you are
|
||||
replicating from), running Omnibus' PostgreSQL (or equivalent version), and
|
||||
you have a new **secondary** server set up with the same versions of the OS,
|
||||
|
@ -346,10 +345,10 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
|
|||
Ensure that the contents of `~gitlab-psql/data/server.crt` on the **primary** node
|
||||
match the contents of `~gitlab-psql/.postgresql/root.crt` on the **secondary** node.
|
||||
|
||||
1. Configure PostgreSQL to enable FDW support:
|
||||
1. Configure PostgreSQL:
|
||||
|
||||
This step is similar to how we configured the **primary** instance.
|
||||
We need to enable this, to enable FDW support, even if using a single node.
|
||||
We need to enable this, even if using a single node.
|
||||
|
||||
Edit `/etc/gitlab/gitlab.rb` and add the following, replacing the IP
|
||||
addresses with addresses appropriate to your network configuration:
|
||||
|
@ -375,11 +374,6 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
|
|||
postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
|
||||
gitlab_rails['db_password'] = '<your_password_here>'
|
||||
|
||||
##
|
||||
## Enable FDW support for the Geo Tracking Database (improves performance)
|
||||
##
|
||||
geo_secondary['db_fdw'] = true
|
||||
```
|
||||
|
||||
For external PostgreSQL instances, see [additional instructions](external_database.md).
|
||||
If you bring a former **primary** node back online to serve as a **secondary** node, then you also need to remove `roles ['geo_primary_role']` or `geo_primary_role['enable'] = true`.
|
||||
|
@ -390,15 +384,12 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
|
|||
gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
1. Restart PostgreSQL for the IP change to take effect and reconfigure again:
|
||||
1. Restart PostgreSQL for the IP change to take effect:
|
||||
|
||||
```shell
|
||||
gitlab-ctl restart postgresql
|
||||
gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
This last reconfigure will provision the FDW configuration and enable it.
|
||||
|
||||
### Step 3. Initiate the replication process
|
||||
|
||||
Below we provide a script that connects the database on the **secondary** node to
|
||||
|
@ -473,48 +464,6 @@ high-availability configuration with a cluster of nodes supporting a Geo
|
|||
**primary** node and another cluster of nodes supporting a Geo **secondary** node. For more
|
||||
information, see [High Availability with Omnibus GitLab](../../postgresql/replication_and_failover.md).
|
||||
|
||||
For a Geo **secondary** node to work properly with PgBouncer in front of the database,
|
||||
it will need a separate read-only user to make [PostgreSQL FDW queries](https://www.postgresql.org/docs/11/postgres-fdw.html)
|
||||
work:
|
||||
|
||||
1. On the **primary** Geo database, enter the PostgreSQL on the console as an
|
||||
admin user. If you are using an Omnibus-managed database, log onto the **primary**
|
||||
node that is running the PostgreSQL database (the default Omnibus database name is `gitlabhq_production`):
|
||||
|
||||
```shell
|
||||
sudo \
|
||||
-u gitlab-psql /opt/gitlab/embedded/bin/psql \
|
||||
-h /var/opt/gitlab/postgresql gitlabhq_production
|
||||
```
|
||||
|
||||
1. Then create the read-only user:
|
||||
|
||||
```sql
|
||||
-- NOTE: Use the password defined earlier
|
||||
CREATE USER gitlab_geo_fdw WITH password 'mypassword';
|
||||
GRANT CONNECT ON DATABASE gitlabhq_production to gitlab_geo_fdw;
|
||||
GRANT USAGE ON SCHEMA public TO gitlab_geo_fdw;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA public TO gitlab_geo_fdw;
|
||||
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO gitlab_geo_fdw;
|
||||
|
||||
-- Tables created by "gitlab" should be made read-only for "gitlab_geo_fdw"
|
||||
-- automatically.
|
||||
ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON TABLES TO gitlab_geo_fdw;
|
||||
ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON SEQUENCES TO gitlab_geo_fdw;
|
||||
```
|
||||
|
||||
1. On the **secondary** nodes, change `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
geo_postgresql['fdw_external_user'] = 'gitlab_geo_fdw'
|
||||
```
|
||||
|
||||
1. Save the file and reconfigure GitLab for the changes to be applied:
|
||||
|
||||
```shell
|
||||
gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Read the [troubleshooting document](troubleshooting.md).
|
||||
|
|
|
@ -183,9 +183,6 @@ to grant additional roles to your tracking database user (by default, this is
|
|||
- Amazon RDS requires the [`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles) role.
|
||||
- Azure Database for PostgreSQL requires the [`azure_pg_admin`](https://docs.microsoft.com/en-us/azure/postgresql/howto-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql) role.
|
||||
|
||||
The tracking database requires an [FDW](https://www.postgresql.org/docs/11/postgres-fdw.html)
|
||||
connection with the **secondary** replica database for improved performance.
|
||||
|
||||
If you have an external database ready to be used as the tracking database,
|
||||
follow the instructions below to use it:
|
||||
|
||||
|
@ -224,7 +221,6 @@ the tracking database on port 5432.
|
|||
|
||||
geo_secondary['db_host'] = '<tracking_database_host>'
|
||||
geo_secondary['db_port'] = <tracking_database_port> # change to the correct port
|
||||
geo_secondary['db_fdw'] = true # enable FDW
|
||||
geo_postgresql['enable'] = false # don't use internal managed instance
|
||||
```
|
||||
|
||||
|
@ -236,48 +232,3 @@ the tracking database on port 5432.
|
|||
gitlab-rake geo:db:create
|
||||
gitlab-rake geo:db:migrate
|
||||
```
|
||||
|
||||
1. Configure the [PostgreSQL FDW](https://www.postgresql.org/docs/11/postgres-fdw.html)
|
||||
connection and credentials:
|
||||
|
||||
Save the script below in a file, ex. `/tmp/geo_fdw.sh` and modify the connection
|
||||
parameters to match your environment. Execute it to set up the FDW connection.
|
||||
|
||||
```shell
|
||||
#!/bin/bash
|
||||
|
||||
# Secondary Database connection params:
|
||||
DB_HOST="<public_ip_or_vpc_private_ip>"
|
||||
DB_NAME="gitlabhq_production"
|
||||
DB_USER="gitlab"
|
||||
DB_PASS="<your_password_here>"
|
||||
DB_PORT="5432"
|
||||
|
||||
# Tracking Database connection params:
|
||||
GEO_DB_HOST="<public_ip_or_vpc_private_ip>"
|
||||
GEO_DB_NAME="gitlabhq_geo_production"
|
||||
GEO_DB_USER="gitlab_geo"
|
||||
GEO_DB_PORT="5432"
|
||||
|
||||
query_exec () {
|
||||
gitlab-psql -h $GEO_DB_HOST -U $GEO_DB_USER -d $GEO_DB_NAME -p $GEO_DB_PORT -c "${1}"
|
||||
}
|
||||
|
||||
query_exec "CREATE EXTENSION postgres_fdw;"
|
||||
query_exec "CREATE SERVER gitlab_secondary FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '${DB_HOST}', dbname '${DB_NAME}', port '${DB_PORT}');"
|
||||
query_exec "CREATE USER MAPPING FOR ${GEO_DB_USER} SERVER gitlab_secondary OPTIONS (user '${DB_USER}', password '${DB_PASS}');"
|
||||
query_exec "CREATE SCHEMA gitlab_secondary;"
|
||||
query_exec "GRANT USAGE ON FOREIGN SERVER gitlab_secondary TO ${GEO_DB_USER};"
|
||||
```
|
||||
|
||||
NOTE: **Note:**
|
||||
The script template above uses `gitlab-psql` as it's intended to be executed from the Geo machine,
|
||||
but you can change it to `psql` and run it from any machine that has access to the database. We also recommend using
|
||||
`psql` for AWS RDS.
|
||||
|
||||
1. Save the file and [restart GitLab](../../restart_gitlab.md#omnibus-gitlab-restart)
|
||||
1. Populate the FDW tables:
|
||||
|
||||
```shell
|
||||
gitlab-rake geo:db:refresh_foreign_tables
|
||||
```
|
||||
|
|
|
@ -117,7 +117,7 @@ The following are required to run Geo:
|
|||
The following operating systems are known to ship with a current version of OpenSSH:
|
||||
- [CentOS](https://www.centos.org) 7.4+
|
||||
- [Ubuntu](https://ubuntu.com) 16.04+
|
||||
- PostgreSQL 11+ with [FDW](https://www.postgresql.org/docs/11/postgres-fdw.html) support and [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
|
||||
- PostgreSQL 11+ with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
|
||||
- Git 2.9+
|
||||
- All nodes must run the same GitLab version.
|
||||
|
||||
|
@ -166,7 +166,6 @@ The tracking database instance is used as metadata to control what needs to be u
|
|||
- Fetch changes from a repository that has recently been updated.
|
||||
|
||||
Because the replicated database instance is read-only, we need this additional database instance for each **secondary** node.
|
||||
The tracking database requires the `postgres_fdw` extension.
|
||||
|
||||
### Geo Log Cursor
|
||||
|
||||
|
|
|
@ -260,10 +260,8 @@ Configure the tracking database.
|
|||
geo_postgresql['sql_user_password'] = '<tracking_database_password_md5_hash>'
|
||||
|
||||
##
|
||||
## Configure FDW connection to the replica database
|
||||
## Configure PostgreSQL connection to the replica database
|
||||
##
|
||||
geo_secondary['db_fdw'] = true
|
||||
geo_postgresql['fdw_external_password'] = '<replica_database_password_plaintext>'
|
||||
geo_postgresql['md5_auth_cidr_addresses'] = ['<replica_database_ip>/32']
|
||||
gitlab_rails['db_host'] = '<replica_database_ip>'
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ Here is a list of steps you should take to attempt to fix problem:
|
|||
|
||||
- Perform [basic troubleshooting](#basic-troubleshooting).
|
||||
- Fix any [replication errors](#fixing-replication-errors).
|
||||
- Fix any [Foreign Data Wrapper](#fixing-foreign-data-wrapper-errors) errors.
|
||||
- Fix any [common](#fixing-common-errors) errors.
|
||||
|
||||
## Basic troubleshooting
|
||||
|
@ -64,8 +63,6 @@ This machine's Geo node name matches a database record ... yes, found a secondar
|
|||
GitLab Geo secondary database is correctly configured ... yes
|
||||
Database replication enabled? ... yes
|
||||
Database replication working? ... yes
|
||||
GitLab Geo tracking database is configured to use Foreign Data Wrapper? ... yes
|
||||
GitLab Geo tracking database Foreign Data Wrapper schema is up-to-date? ... yes
|
||||
GitLab Geo HTTP(S) connectivity ...
|
||||
* Can connect to the primary node ... yes
|
||||
HTTP/HTTPS repository cloning is enabled ... yes
|
||||
|
@ -255,7 +252,6 @@ sudo gitlab-rake gitlab:geo:check
|
|||
When performing a PostgreSQL major version (9 > 10) update this is expected. Follow:
|
||||
|
||||
- [initiate-the-replication-process](database.md#step-3-initiate-the-replication-process)
|
||||
- [Geo database has an outdated FDW remote schema](troubleshooting.md#geo-database-has-an-outdated-fdw-remote-schema-error)
|
||||
|
||||
## Fixing replication errors
|
||||
|
||||
|
@ -508,12 +504,6 @@ to start again from scratch, there are a few steps that can help you:
|
|||
gitlab-ctl start
|
||||
```
|
||||
|
||||
1. Refresh Foreign Data Wrapper tables
|
||||
|
||||
```shell
|
||||
gitlab-rake geo:db:refresh_foreign_tables
|
||||
```
|
||||
|
||||
## Fixing errors during a PostgreSQL upgrade or downgrade
|
||||
|
||||
### Message: `ERROR: psql: FATAL: role "gitlab-consul" does not exist`
|
||||
|
@ -572,24 +562,6 @@ Then reconfigure GitLab:
|
|||
sudo gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
### Message: `ActiveRecord::StatementInvalid: PG::SqlclientUnableToEstablishSqlconnection: ERROR: could not connect to server "gitlab_secondary"`
|
||||
|
||||
When
|
||||
[upgrading PostgreSQL on a Geo instance](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance), or when downgrading, you
|
||||
might encounter the following error:
|
||||
|
||||
```plaintext
|
||||
$ sudo gitlab-rake geo:db:refresh_foreign_tables
|
||||
|
||||
Refreshing foreign tables for FDW: gitlab_secondary ... rake aborted!
|
||||
ActiveRecord::StatementInvalid: PG::SqlclientUnableToEstablishSqlconnection: ERROR: could not connect to server "gitlab_secondary"
|
||||
DETAIL: SSL error: certificate verify failed
|
||||
FATAL: no pg_hba.conf entry for host "10.138.0.59", user "gitlab", database "gitlabhq_production", SSL off
|
||||
```
|
||||
|
||||
You may need to `gitlab-ctl restart` the read-replica DB node for its PostgreSQL
|
||||
server to recognize recent changes.
|
||||
|
||||
## Fixing errors during a failover or when promoting a secondary to a primary node
|
||||
|
||||
The following are possible errors that might be encountered during failover or
|
||||
|
@ -702,231 +674,6 @@ sudo /opt/gitlab/embedded/bin/gitlab-pg-ctl promote
|
|||
|
||||
GitLab 12.9 and later are [unaffected by this error](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5147).
|
||||
|
||||
## Fixing Foreign Data Wrapper errors
|
||||
|
||||
This section documents ways to fix potential Foreign Data Wrapper errors.
|
||||
|
||||
### "Foreign Data Wrapper (FDW) is not configured" error
|
||||
|
||||
When setting up Geo, you might see this warning in the `gitlab-rake
|
||||
gitlab:geo:check` output:
|
||||
|
||||
```plaintext
|
||||
GitLab Geo tracking database Foreign Data Wrapper schema is up-to-date? ... foreign data wrapper is not configured
|
||||
```
|
||||
|
||||
There are a few key points to remember:
|
||||
|
||||
1. The FDW settings are configured on the Geo **tracking** database.
|
||||
1. The configured foreign server enables a login to the Geo
|
||||
**secondary**, read-only database.
|
||||
|
||||
By default, the Geo secondary and tracking database are running on the
|
||||
same host on different ports. That is, 5432 and 5431 respectively.
|
||||
|
||||
#### Checking configuration
|
||||
|
||||
NOTE: **Note:**
|
||||
The following steps are for Omnibus installs only. Using Geo with source-based installs was **deprecated** in GitLab 11.5.
|
||||
|
||||
To check the configuration:
|
||||
|
||||
1. SSH into an app node in the **secondary**:
|
||||
|
||||
```shell
|
||||
sudo -i
|
||||
```
|
||||
|
||||
Note: An app node is any machine running at least one of the following services:
|
||||
|
||||
- `puma`
|
||||
- `unicorn`
|
||||
- `sidekiq`
|
||||
- `geo-logcursor`
|
||||
|
||||
1. Enter the database console:
|
||||
|
||||
If the tracking database is running on the same node:
|
||||
|
||||
```shell
|
||||
gitlab-geo-psql
|
||||
```
|
||||
|
||||
Or, if the tracking database is running on a different node, you must specify
|
||||
the user and host when entering the database console:
|
||||
|
||||
```shell
|
||||
gitlab-geo-psql -U gitlab_geo -h <IP of tracking database>
|
||||
```
|
||||
|
||||
You will be prompted for the password of the `gitlab_geo` user. You can find
|
||||
it in plaintext in `/etc/gitlab/gitlab.rb` at:
|
||||
|
||||
```ruby
|
||||
geo_secondary['db_password'] = '<geo_tracking_db_password>'
|
||||
```
|
||||
|
||||
This password is normally set on the tracking database during
|
||||
[Step 3: Configure the tracking database on the secondary node](multiple_servers.md#step-3-configure-the-tracking-database-on-the-secondary-node),
|
||||
and it is set on the app nodes during
|
||||
[Step 4: Configure the frontend application servers on the secondary node](multiple_servers.md#step-4-configure-the-frontend-application-servers-on-the-secondary-node).
|
||||
|
||||
1. Check whether any tables are present with the following statement:
|
||||
|
||||
```sql
|
||||
SELECT * from information_schema.foreign_tables;
|
||||
```
|
||||
|
||||
If everything is working, you should see something like this:
|
||||
|
||||
```plaintext
|
||||
gitlabhq_geo_production=# SELECT * from information_schema.foreign_tables;
|
||||
foreign_table_catalog | foreign_table_schema | foreign_table_name | foreign_server_catalog | foreign_server_name
|
||||
-------------------------+----------------------+-------------------------------------------------+-------------------------+---------------------
|
||||
gitlabhq_geo_production | gitlab_secondary | abuse_reports | gitlabhq_geo_production | gitlab_secondary
|
||||
gitlabhq_geo_production | gitlab_secondary | appearances | gitlabhq_geo_production | gitlab_secondary
|
||||
gitlabhq_geo_production | gitlab_secondary | application_setting_terms | gitlabhq_geo_production | gitlab_secondary
|
||||
gitlabhq_geo_production | gitlab_secondary | application_settings | gitlabhq_geo_production | gitlab_secondary
|
||||
<snip>
|
||||
```
|
||||
|
||||
However, if the query returns with `0 rows`, then continue onto the next steps.
|
||||
|
||||
1. Check that the foreign server mapping is correct via `\des+`. The
|
||||
results should look something like this:
|
||||
|
||||
```plaintext
|
||||
gitlabhq_geo_production=# \des+
|
||||
List of foreign servers
|
||||
-[ RECORD 1 ]--------+------------------------------------------------------------
|
||||
Name | gitlab_secondary
|
||||
Owner | gitlab-psql
|
||||
Foreign-data wrapper | postgres_fdw
|
||||
Access privileges | "gitlab-psql"=U/"gitlab-psql" +
|
||||
| gitlab_geo=U/"gitlab-psql"
|
||||
Type |
|
||||
Version |
|
||||
FDW Options | (host '0.0.0.0', port '5432', dbname 'gitlabhq_production')
|
||||
Description |
|
||||
```
|
||||
|
||||
NOTE: **Note:**
|
||||
Pay particular attention to the host and port under
|
||||
FDW options. That configuration should point to the Geo secondary
|
||||
database.
|
||||
|
||||
If you need to experiment with changing the host or password, the
|
||||
following queries demonstrate how:
|
||||
|
||||
```sql
|
||||
ALTER SERVER gitlab_secondary OPTIONS (SET host '<my_new_host>');
|
||||
ALTER SERVER gitlab_secondary OPTIONS (SET port 5432);
|
||||
```
|
||||
|
||||
If you change the host and/or port, you will also have to adjust the
|
||||
following settings in `/etc/gitlab/gitlab.rb` and run `gitlab-ctl
|
||||
reconfigure`:
|
||||
|
||||
- `gitlab_rails['db_host']`
|
||||
- `gitlab_rails['db_port']`
|
||||
|
||||
1. Check that the user mapping is configured properly via `\deu+`:
|
||||
|
||||
```plaintext
|
||||
gitlabhq_geo_production=# \deu+
|
||||
List of user mappings
|
||||
Server | User name | FDW Options
|
||||
------------------+------------+--------------------------------------------------------------------------------
|
||||
gitlab_secondary | gitlab_geo | ("user" 'gitlab', password 'YOUR-PASSWORD-HERE')
|
||||
(1 row)
|
||||
```
|
||||
|
||||
Make sure the password is correct. You can test that logins work by running `psql`:
|
||||
|
||||
```shell
|
||||
# Connect to the tracking database as the `gitlab_geo` user
|
||||
sudo \
|
||||
-u git /opt/gitlab/embedded/bin/psql \
|
||||
-h /var/opt/gitlab/geo-postgresql \
|
||||
-p 5431 \
|
||||
-U gitlab_geo \
|
||||
-W \
|
||||
-d gitlabhq_geo_production
|
||||
```
|
||||
|
||||
If you need to correct the password, the following query shows how:
|
||||
|
||||
```sql
|
||||
ALTER USER MAPPING FOR gitlab_geo SERVER gitlab_secondary OPTIONS (SET password '<my_new_password>');
|
||||
```
|
||||
|
||||
If you change the user or password, you will also have to adjust the
|
||||
following settings in `/etc/gitlab/gitlab.rb` and run `gitlab-ctl
|
||||
reconfigure`:
|
||||
|
||||
- `gitlab_rails['db_username']`
|
||||
- `gitlab_rails['db_password']`
|
||||
|
||||
If you are using [PgBouncer in front of the secondary
|
||||
database](database.md#pgbouncer-support-optional), be sure to update
|
||||
the following settings:
|
||||
|
||||
- `geo_postgresql['fdw_external_user']`
|
||||
- `geo_postgresql['fdw_external_password']`
|
||||
|
||||
#### Manual reload of FDW schema
|
||||
|
||||
If you're still unable to get FDW working, you may want to try a manual
|
||||
reload of the FDW schema. To manually reload the FDW schema:
|
||||
|
||||
1. On the node running the Geo tracking database, enter the PostgreSQL console via
|
||||
the `gitlab_geo` user:
|
||||
|
||||
```shell
|
||||
sudo \
|
||||
-u git /opt/gitlab/embedded/bin/psql \
|
||||
-h /var/opt/gitlab/geo-postgresql \
|
||||
-p 5431 \
|
||||
-U gitlab_geo \
|
||||
-W \
|
||||
-d gitlabhq_geo_production
|
||||
```
|
||||
|
||||
Be sure to adjust the port and hostname for your configuration. You
|
||||
may be asked to enter a password.
|
||||
|
||||
1. Reload the schema via:
|
||||
|
||||
```sql
|
||||
DROP SCHEMA IF EXISTS gitlab_secondary CASCADE;
|
||||
CREATE SCHEMA gitlab_secondary;
|
||||
GRANT USAGE ON FOREIGN SERVER gitlab_secondary TO gitlab_geo;
|
||||
IMPORT FOREIGN SCHEMA public FROM SERVER gitlab_secondary INTO gitlab_secondary;
|
||||
```
|
||||
|
||||
1. Test that queries work:
|
||||
|
||||
```sql
|
||||
SELECT * from information_schema.foreign_tables;
|
||||
SELECT * FROM gitlab_secondary.projects limit 1;
|
||||
```
|
||||
|
||||
### "Geo database has an outdated FDW remote schema" error
|
||||
|
||||
GitLab can error with a `Geo database has an outdated FDW remote schema` message.
|
||||
|
||||
For example:
|
||||
|
||||
```plaintext
|
||||
Geo database has an outdated FDW remote schema. It contains 229 of 236 expected tables. Please refer to Geo Troubleshooting.
|
||||
```
|
||||
|
||||
To resolve this, run the following command on the **secondary**:
|
||||
|
||||
```shell
|
||||
sudo gitlab-rake geo:db:refresh_foreign_tables
|
||||
```
|
||||
|
||||
## Expired artifacts
|
||||
|
||||
If you notice for some reason there are more artifacts on the Geo
|
||||
|
@ -1005,13 +752,6 @@ If you are using Omnibus GitLab installation, something might have failed during
|
|||
- Run `sudo gitlab-ctl reconfigure`.
|
||||
- Manually trigger the database migration by running: `sudo gitlab-rake geo:db:migrate` as root on the **secondary** node.
|
||||
|
||||
### Geo database is not configured to use Foreign Data Wrapper
|
||||
|
||||
This error means the Geo Tracking Database doesn't have the FDW server and credentials
|
||||
configured.
|
||||
|
||||
See ["Foreign Data Wrapper (FDW) is not configured" error?](#foreign-data-wrapper-fdw-is-not-configured-error).
|
||||
|
||||
### GitLab indicates that more than 100% of repositories were synced
|
||||
|
||||
This can be caused by orphaned records in the project registry. You can clear them
|
||||
|
|
|
@ -11,6 +11,19 @@ Check this document if it includes instructions for the version you are updating
|
|||
These steps go together with the [general steps](updating_the_geo_nodes.md#general-update-steps)
|
||||
for updating Geo nodes.
|
||||
|
||||
## Updating to GitLab 13.3
|
||||
|
||||
In GitLab 13.3, Geo removed the PostgreSQL [Foreign Data Wrapper](https://www.postgresql.org/docs/11/postgres-fdw.html) dependency for the tracking database.
|
||||
|
||||
The FDW server, user, and the extension will be removed during the upgrade process on each **secondary** node. The GitLab settings related to the FDW in the `/etc/gitlab/gitlab.rb` have been deprecated and can be safely removed.
|
||||
|
||||
There are some scenarios like using an external PostgreSQL instance for the tracking database where the FDW settings must be removed manually. Enter the PostgreSQL console of that instance and remove them:
|
||||
|
||||
```shell
|
||||
DROP SERVER gitlab_secondary CASCADE;
|
||||
DROP EXTENSION IF EXISTS postgres_fdw;
|
||||
```
|
||||
|
||||
## Updating to GitLab 13.0
|
||||
|
||||
Upgrading to GitLab 13.0 requires GitLab 12.10 to already be using PostgreSQL
|
||||
|
|
|
@ -58,7 +58,6 @@ This section is for links to information elsewhere in the GitLab documentation.
|
|||
- Support for MySQL was removed in GitLab 12.1; [migrate to PostgreSQL](../../update/mysql_to_postgresql.md)
|
||||
- required extension `pg_trgm`
|
||||
- required extension `btree_gist`
|
||||
- required extension `postgres_fdw` for Geo
|
||||
|
||||
- Errors like this in the `production/sidekiq` log; see: [Set default_transaction_isolation into read committed](https://docs.gitlab.com/omnibus/settings/database.html#set-default_transaction_isolation-into-read-committed):
|
||||
|
||||
|
@ -85,7 +84,7 @@ This section is for links to information elsewhere in the GitLab documentation.
|
|||
PANIC: could not write to file ‘pg_xlog/xlogtemp.123’: No space left on device
|
||||
```
|
||||
|
||||
- [Checking Geo configuration](../geo/replication/troubleshooting.md#checking-configuration) including
|
||||
- [Checking Geo configuration](../geo/replication/troubleshooting.md) including
|
||||
- reconfiguring hosts/ports
|
||||
- checking and fixing user/password mappings
|
||||
|
||||
|
|
|
@ -720,7 +720,7 @@ POST /projects/:id/issues
|
|||
| `title` | string | yes | The title of an issue |
|
||||
| `description` | string | no | The description of an issue. Limited to 1,048,576 characters. |
|
||||
| `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. |
|
||||
| `assignee_ids` | integer array | no | The ID of a user to assign issue |
|
||||
| `assignee_ids` | integer array | no | The ID of the user(s) to assign the issue to. |
|
||||
| `milestone_id` | integer | no | The global ID of a milestone to assign issue |
|
||||
| `labels` | string | no | Comma-separated label names for an issue |
|
||||
| `created_at` | string | no | Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` (requires admin or project/group owner rights) |
|
||||
|
|
|
@ -209,121 +209,12 @@ To migrate the tracking database, run:
|
|||
bundle exec rake geo:db:migrate
|
||||
```
|
||||
|
||||
### Foreign Data Wrapper
|
||||
|
||||
> Introduced in GitLab 10.1.
|
||||
|
||||
Foreign Data Wrapper ([FDW](#fdw)) is used by the [Geo Log Cursor](#geo-log-cursor) and improves
|
||||
the performance of many synchronization operations.
|
||||
|
||||
FDW is a PostgreSQL extension ([`postgres_fdw`](https://www.postgresql.org/docs/11/postgres-fdw.html)) that is enabled within
|
||||
the Geo Tracking Database (on a **secondary** node), which allows it
|
||||
to connect to the read-only database replica and perform queries and filter
|
||||
data from both instances.
|
||||
|
||||
This persistent connection is configured as an FDW server
|
||||
named `gitlab_secondary`. This configuration exists within the database's user
|
||||
context only. To access the `gitlab_secondary`, GitLab needs to use the
|
||||
same database user that had previously been configured.
|
||||
|
||||
The Geo Tracking Database accesses the read-only database replica via FDW as a regular user,
|
||||
limited by its own restrictions. The credentials are configured as a
|
||||
`USER MAPPING` associated with the `SERVER` mapped previously
|
||||
(`gitlab_secondary`).
|
||||
|
||||
FDW configuration and credentials definition are managed automatically by the
|
||||
Omnibus GitLab `gitlab-ctl reconfigure` command.
|
||||
|
||||
#### Refreshing the Foreign Tables
|
||||
|
||||
Whenever a new Geo node is configured or the database schema changes on the
|
||||
**primary** node, you must refresh the foreign tables on the **secondary** node
|
||||
by running the following:
|
||||
|
||||
```shell
|
||||
bundle exec rake geo:db:refresh_foreign_tables
|
||||
```
|
||||
|
||||
Failure to do this will prevent the **secondary** node from
|
||||
functioning properly. The **secondary** node will generate error
|
||||
messages, as the following PostgreSQL error:
|
||||
|
||||
```sql
|
||||
ERROR: relation "gitlab_secondary.ci_job_artifacts" does not exist at character 323
|
||||
STATEMENT: SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
||||
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
|
||||
FROM pg_attribute a LEFT JOIN pg_attrdef d
|
||||
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
||||
WHERE a.attrelid = '"gitlab_secondary"."ci_job_artifacts"'::regclass
|
||||
AND a.attnum > 0 AND NOT a.attisdropped
|
||||
ORDER BY a.attnum
|
||||
```
|
||||
|
||||
#### Accessing data from a Foreign Table
|
||||
|
||||
At the SQL level, all you have to do is `SELECT` data from `gitlab_secondary.*`.
|
||||
|
||||
Here's an example of how to access all projects from the Geo Tracking Database's FDW:
|
||||
|
||||
```sql
|
||||
SELECT * FROM gitlab_secondary.projects;
|
||||
```
|
||||
|
||||
As a more real-world example, this is how you filter for unarchived projects
|
||||
on the Tracking Database:
|
||||
|
||||
```sql
|
||||
SELECT project_registry.*
|
||||
FROM project_registry
|
||||
JOIN gitlab_secondary.projects
|
||||
ON (project_registry.project_id = gitlab_secondary.projects.id
|
||||
AND gitlab_secondary.projects.archived IS FALSE)
|
||||
```
|
||||
|
||||
At the ActiveRecord level, we have additional Models that represent the
|
||||
foreign tables. They must be mapped in a slightly different way, and they are read-only.
|
||||
|
||||
Check the existing FDW models in `ee/app/models/geo/fdw` for reference.
|
||||
|
||||
From a developer's perspective, it's no different than creating a model that
|
||||
represents a Database View.
|
||||
|
||||
With the examples above, you can access the projects with:
|
||||
|
||||
```ruby
|
||||
Geo::Fdw::Project.all
|
||||
```
|
||||
|
||||
and to access the `ProjectRegistry` filtering by unarchived projects:
|
||||
|
||||
```ruby
|
||||
# We have to use Arel here:
|
||||
project_registry_table = Geo::ProjectRegistry.arel_table
|
||||
fdw_project_table = Geo::Fdw::Project.arel_table
|
||||
|
||||
project_registry_table.join(fdw_project_table)
|
||||
.on(project_registry_table[:project_id].eq(fdw_project_table[:id]))
|
||||
.where((fdw_project_table[:archived]).eq(true)) # if you append `.to_sql` you can check generated query
|
||||
```
|
||||
|
||||
## Finders
|
||||
|
||||
Geo uses [Finders](https://gitlab.com/gitlab-org/gitlab/tree/master/app/finders),
|
||||
which are classes take care of the heavy lifting of looking up
|
||||
projects/attachments/etc. in the tracking database and main database.
|
||||
|
||||
### Finders Performance
|
||||
|
||||
The Finders need to compare data from the main database with data in
|
||||
the tracking database. For example, counting the number of synced
|
||||
projects normally involves retrieving the project IDs from one
|
||||
database and checking their state in the other database. This is slow
|
||||
and requires a lot of memory.
|
||||
|
||||
To overcome this, the Finders use [FDW](#fdw), or Foreign Data
|
||||
Wrappers. This allows a regular `JOIN` between the main database and
|
||||
the tracking database.
|
||||
|
||||
## Redis
|
||||
|
||||
Redis on the **secondary** node works the same as on the **primary**
|
||||
|
@ -397,12 +288,6 @@ migration do not need to run on the secondary nodes.
|
|||
A database on each Geo **secondary** node that keeps state for the node
|
||||
on which it resides. Read more in [Using the Tracking database](#using-the-tracking-database).
|
||||
|
||||
### FDW
|
||||
|
||||
Foreign Data Wrapper, or FDW, is a feature built-in in PostgreSQL. It
|
||||
allows data to be queried from different data sources. In Geo, it's
|
||||
used to query data from different PostgreSQL instances.
|
||||
|
||||
## Geo Event Log
|
||||
|
||||
The Geo **primary** stores events in the `geo_event_log` table. Each
|
||||
|
|
|
@ -156,10 +156,6 @@ If you're using [GitLab Geo](../administration/geo/replication/index.md):
|
|||
- We strongly recommend running Omnibus-managed instances as they are actively
|
||||
developed and tested. We aim to be compatible with most external (not managed
|
||||
by Omnibus) databases (for example, [AWS Relational Database Service (RDS)](https://aws.amazon.com/rds/)) but we don't guarantee compatibility.
|
||||
- You must also ensure the `postgres_fdw` extension is loaded into every
|
||||
GitLab database. This extension
|
||||
[can be enabled](https://www.postgresql.org/docs/11/sql-createextension.html)
|
||||
using a PostgreSQL super user.
|
||||
|
||||
## Puma settings
|
||||
|
||||
|
|
|
@ -548,13 +548,17 @@ To trigger the re-index from `primary` index:
|
|||
|
||||
### Trigger the reindex via the Elasticsearch administration
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34069) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34069) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
|
||||
> - A scheduled index deletion and the ability to cancel it was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38914) in GitLab Starter 13.3.
|
||||
|
||||
Under **Admin Area > Integration > Elasticsearch zero-downtime reindexing**, click on **Trigger cluster reindexing**.
|
||||
|
||||
NOTE: **Note:**
|
||||
Reindexing can be a lengthy process depending on the size of your Elasticsearch cluster.
|
||||
|
||||
CAUTION: **Caution:**
|
||||
After the reindexing is completed, the original index will be scheduled to be deleted after 14 days. You can cancel this action by pressing the cancel button.
|
||||
|
||||
While the reindexing is running, you will be able to follow its progress under that same section.
|
||||
|
||||
## GitLab Elasticsearch Rake tasks
|
||||
|
|
|
@ -4319,6 +4319,9 @@ msgstr ""
|
|||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancel index deletion"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancel running"
|
||||
msgstr ""
|
||||
|
||||
|
@ -13010,6 +13013,9 @@ msgstr ""
|
|||
msgid "Index all projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "Index deletion is canceled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Indicates whether this runner can pick jobs without tags"
|
||||
msgstr ""
|
||||
|
||||
|
@ -26265,6 +26271,9 @@ msgstr ""
|
|||
msgid "Until"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
|
||||
msgstr ""
|
||||
|
||||
msgid "Unverified"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -1,21 +1,26 @@
|
|||
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import AxiosMockAdapter from 'axios-mock-adapter';
|
||||
import Vue from 'vue';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import JiraImportApp from '~/jira_import/components/jira_import_app.vue';
|
||||
import JiraImportForm from '~/jira_import/components/jira_import_form.vue';
|
||||
import JiraImportProgress from '~/jira_import/components/jira_import_progress.vue';
|
||||
import JiraImportSetup from '~/jira_import/components/jira_import_setup.vue';
|
||||
import initiateJiraImportMutation from '~/jira_import/queries/initiate_jira_import.mutation.graphql';
|
||||
import getJiraUserMappingMutation from '~/jira_import/queries/get_jira_user_mapping.mutation.graphql';
|
||||
import { imports, issuesPath, jiraIntegrationPath, jiraProjects, userMappings } from '../mock_data';
|
||||
import {
|
||||
imports,
|
||||
issuesPath,
|
||||
jiraIntegrationPath,
|
||||
jiraProjects,
|
||||
projectId,
|
||||
projectPath,
|
||||
} from '../mock_data';
|
||||
|
||||
describe('JiraImportApp', () => {
|
||||
let axiosMock;
|
||||
let mutateSpy;
|
||||
let wrapper;
|
||||
|
||||
const inProgressIllustration = 'in-progress-illustration.svg';
|
||||
|
||||
const setupIllustration = 'setup-illustration.svg';
|
||||
|
||||
const getFormComponent = () => wrapper.find(JiraImportForm);
|
||||
|
||||
const getProgressComponent = () => wrapper.find(JiraImportProgress);
|
||||
|
@ -32,22 +37,19 @@ describe('JiraImportApp', () => {
|
|||
showAlert = false,
|
||||
isInProgress = false,
|
||||
loading = false,
|
||||
mutate = mutateSpy,
|
||||
} = {}) =>
|
||||
shallowMount(JiraImportApp, {
|
||||
propsData: {
|
||||
inProgressIllustration: 'in-progress-illustration.svg',
|
||||
inProgressIllustration,
|
||||
isJiraConfigured,
|
||||
issuesPath,
|
||||
jiraIntegrationPath,
|
||||
projectId: '5',
|
||||
projectPath: 'gitlab-org/gitlab-test',
|
||||
setupIllustration: 'setup-illustration.svg',
|
||||
projectId,
|
||||
projectPath,
|
||||
setupIllustration,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isSubmitting: false,
|
||||
userMappings,
|
||||
errorMessage,
|
||||
showAlert,
|
||||
jiraImportDetails: {
|
||||
|
@ -61,26 +63,11 @@ describe('JiraImportApp', () => {
|
|||
mocks: {
|
||||
$apollo: {
|
||||
loading,
|
||||
mutate,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
axiosMock = new AxiosMockAdapter(axios);
|
||||
mutateSpy = jest.fn(() =>
|
||||
Promise.resolve({
|
||||
data: {
|
||||
jiraImportStart: { errors: [] },
|
||||
jiraImportUsers: { jiraUsers: [], errors: [] },
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
axiosMock.restore();
|
||||
mutateSpy.mockRestore();
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
@ -173,72 +160,79 @@ describe('JiraImportApp', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('import in progress screen', () => {
|
||||
describe('import setup component', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = mountComponent({ isJiraConfigured: false });
|
||||
});
|
||||
|
||||
it('receives the illustration', () => {
|
||||
expect(getSetupComponent().props('illustration')).toBe(setupIllustration);
|
||||
});
|
||||
|
||||
it('receives the path to the Jira integration page', () => {
|
||||
expect(getSetupComponent().props('jiraIntegrationPath')).toBe(jiraIntegrationPath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('import in progress component', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = mountComponent({ isInProgress: true });
|
||||
});
|
||||
|
||||
it('shows the illustration', () => {
|
||||
expect(getProgressComponent().props('illustration')).toBe('in-progress-illustration.svg');
|
||||
it('receives the illustration', () => {
|
||||
expect(getProgressComponent().props('illustration')).toBe(inProgressIllustration);
|
||||
});
|
||||
|
||||
it('shows the name of the most recent import initiator', () => {
|
||||
it('receives the name of the most recent import initiator', () => {
|
||||
expect(getProgressComponent().props('importInitiator')).toBe('Jane Doe');
|
||||
});
|
||||
|
||||
it('shows the name of the most recent imported project', () => {
|
||||
it('receives the name of the most recent imported project', () => {
|
||||
expect(getProgressComponent().props('importProject')).toBe('MTG');
|
||||
});
|
||||
|
||||
it('shows the time of the most recent import', () => {
|
||||
it('receives the time of the most recent import', () => {
|
||||
expect(getProgressComponent().props('importTime')).toBe('2020-04-09T16:17:18+00:00');
|
||||
});
|
||||
|
||||
it('has the path to the issues page', () => {
|
||||
it('receives the path to the issues page', () => {
|
||||
expect(getProgressComponent().props('issuesPath')).toBe('gitlab-org/gitlab-test/-/issues');
|
||||
});
|
||||
});
|
||||
|
||||
describe('initiating a Jira import', () => {
|
||||
it('calls the mutation with the expected arguments', () => {
|
||||
describe('import form component', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = mountComponent();
|
||||
|
||||
const mutationArguments = {
|
||||
mutation: initiateJiraImportMutation,
|
||||
variables: {
|
||||
input: {
|
||||
jiraProjectKey: 'MTG',
|
||||
projectPath: 'gitlab-org/gitlab-test',
|
||||
usersMapping: [
|
||||
{
|
||||
jiraAccountId: 'aei23f98f-q23fj98qfj',
|
||||
gitlabId: 15,
|
||||
},
|
||||
{
|
||||
jiraAccountId: 'fu39y8t34w-rq3u289t3h4i',
|
||||
gitlabId: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
getFormComponent().vm.$emit('initiateJiraImport', 'MTG');
|
||||
|
||||
expect(mutateSpy).toHaveBeenCalledWith(expect.objectContaining(mutationArguments));
|
||||
});
|
||||
|
||||
describe('when there is an error', () => {
|
||||
beforeEach(() => {
|
||||
const mutate = jest.fn(() => Promise.reject());
|
||||
wrapper = mountComponent({ mutate });
|
||||
it('receives the illustration', () => {
|
||||
expect(getFormComponent().props('issuesPath')).toBe(issuesPath);
|
||||
});
|
||||
|
||||
getFormComponent().vm.$emit('initiateJiraImport', 'MTG');
|
||||
});
|
||||
it('receives the name of the most recent import initiator', () => {
|
||||
expect(getFormComponent().props('jiraImports')).toEqual(imports);
|
||||
});
|
||||
|
||||
it('shows alert message with error message', async () => {
|
||||
expect(getAlert().text()).toBe('There was an error importing the Jira project.');
|
||||
});
|
||||
it('receives the name of the most recent imported project', () => {
|
||||
expect(getFormComponent().props('jiraProjects')).toEqual(jiraProjects);
|
||||
});
|
||||
|
||||
it('receives the project ID', () => {
|
||||
expect(getFormComponent().props('projectId')).toBe(projectId);
|
||||
});
|
||||
|
||||
it('receives the project path', () => {
|
||||
expect(getFormComponent().props('projectPath')).toBe(projectPath);
|
||||
});
|
||||
|
||||
it('shows an alert when it emits an error', async () => {
|
||||
expect(getAlert().exists()).toBe(false);
|
||||
|
||||
getFormComponent().vm.$emit('error', 'There was an error');
|
||||
|
||||
await Vue.nextTick();
|
||||
|
||||
expect(getAlert().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -259,40 +253,4 @@ describe('JiraImportApp', () => {
|
|||
expect(getAlert().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('on mount GraphQL user mapping mutation', () => {
|
||||
it('is called with the expected arguments', () => {
|
||||
wrapper = mountComponent();
|
||||
|
||||
const mutationArguments = {
|
||||
mutation: getJiraUserMappingMutation,
|
||||
variables: {
|
||||
input: {
|
||||
projectPath: 'gitlab-org/gitlab-test',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(mutateSpy).toHaveBeenCalledWith(expect.objectContaining(mutationArguments));
|
||||
});
|
||||
|
||||
describe('when Jira is not configured', () => {
|
||||
it('is not called', () => {
|
||||
wrapper = mountComponent({ isJiraConfigured: false });
|
||||
|
||||
expect(mutateSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there is an error when called', () => {
|
||||
beforeEach(() => {
|
||||
const mutate = jest.fn(() => Promise.reject());
|
||||
wrapper = mountComponent({ mutate });
|
||||
});
|
||||
|
||||
it('shows error message', () => {
|
||||
expect(getAlert().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,15 +4,20 @@ import { mount, shallowMount } from '@vue/test-utils';
|
|||
import AxiosMockAdapter from 'axios-mock-adapter';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import JiraImportForm from '~/jira_import/components/jira_import_form.vue';
|
||||
import getJiraUserMappingMutation from '~/jira_import/queries/get_jira_user_mapping.mutation.graphql';
|
||||
import initiateJiraImportMutation from '~/jira_import/queries/initiate_jira_import.mutation.graphql';
|
||||
import {
|
||||
imports,
|
||||
issuesPath,
|
||||
jiraProjects,
|
||||
projectId,
|
||||
projectPath,
|
||||
userMappings as defaultUserMappings,
|
||||
} from '../mock_data';
|
||||
|
||||
describe('JiraImportForm', () => {
|
||||
let axiosMock;
|
||||
let mutateSpy;
|
||||
let wrapper;
|
||||
|
||||
const currentUsername = 'mrgitlab';
|
||||
|
@ -35,35 +40,53 @@ describe('JiraImportForm', () => {
|
|||
|
||||
const mountComponent = ({
|
||||
isSubmitting = false,
|
||||
loading = false,
|
||||
mutate = mutateSpy,
|
||||
selectedProject = 'MTG',
|
||||
userMappings = defaultUserMappings,
|
||||
mountFunction = shallowMount,
|
||||
} = {}) =>
|
||||
mountFunction(JiraImportForm, {
|
||||
propsData: {
|
||||
isSubmitting,
|
||||
issuesPath,
|
||||
jiraImports: imports,
|
||||
jiraProjects,
|
||||
projectId: '5',
|
||||
userMappings,
|
||||
projectId,
|
||||
projectPath,
|
||||
},
|
||||
data: () => ({
|
||||
isFetching: false,
|
||||
isSubmitting,
|
||||
searchTerm: '',
|
||||
selectedProject,
|
||||
selectState: null,
|
||||
users: [],
|
||||
userMappings,
|
||||
}),
|
||||
mocks: {
|
||||
$apollo: {
|
||||
loading,
|
||||
mutate,
|
||||
},
|
||||
},
|
||||
currentUsername,
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
axiosMock = new AxiosMockAdapter(axios);
|
||||
mutateSpy = jest.fn(() =>
|
||||
Promise.resolve({
|
||||
data: {
|
||||
jiraImportStart: { errors: [] },
|
||||
jiraImportUsers: { jiraUsers: [], errors: [] },
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
axiosMock.restore();
|
||||
mutateSpy.mockRestore();
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
@ -238,15 +261,61 @@ describe('JiraImportForm', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('form', () => {
|
||||
it('emits an "initiateJiraImport" event with the selected dropdown value when submitted', () => {
|
||||
const selectedProject = 'MTG';
|
||||
describe('submitting the form', () => {
|
||||
it('initiates the Jira import mutation with the expected arguments', () => {
|
||||
wrapper = mountComponent();
|
||||
|
||||
wrapper = mountComponent({ selectedProject });
|
||||
const mutationArguments = {
|
||||
mutation: initiateJiraImportMutation,
|
||||
variables: {
|
||||
input: {
|
||||
jiraProjectKey: 'MTG',
|
||||
projectPath,
|
||||
usersMapping: [
|
||||
{
|
||||
jiraAccountId: 'aei23f98f-q23fj98qfj',
|
||||
gitlabId: 15,
|
||||
},
|
||||
{
|
||||
jiraAccountId: 'fu39y8t34w-rq3u289t3h4i',
|
||||
gitlabId: undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
wrapper.find('form').trigger('submit');
|
||||
|
||||
expect(wrapper.emitted('initiateJiraImport')[0]).toEqual([selectedProject]);
|
||||
expect(mutateSpy).toHaveBeenCalledWith(expect.objectContaining(mutationArguments));
|
||||
});
|
||||
});
|
||||
|
||||
describe('on mount GraphQL user mapping mutation', () => {
|
||||
it('is called with the expected arguments', () => {
|
||||
wrapper = mountComponent();
|
||||
|
||||
const mutationArguments = {
|
||||
mutation: getJiraUserMappingMutation,
|
||||
variables: {
|
||||
input: {
|
||||
projectPath,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(mutateSpy).toHaveBeenCalledWith(expect.objectContaining(mutationArguments));
|
||||
});
|
||||
|
||||
describe('when there is an error when called', () => {
|
||||
beforeEach(() => {
|
||||
const mutate = jest.fn(() => Promise.reject());
|
||||
wrapper = mountComponent({ mutate });
|
||||
});
|
||||
|
||||
it('shows error message', () => {
|
||||
expect(getAlert().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,6 +3,16 @@ import { IMPORT_STATE } from '~/jira_import/utils/jira_import_utils';
|
|||
|
||||
export const fullPath = 'gitlab-org/gitlab-test';
|
||||
|
||||
export const issuesPath = 'gitlab-org/gitlab-test/-/issues';
|
||||
|
||||
export const illustration = 'illustration.svg';
|
||||
|
||||
export const jiraIntegrationPath = 'gitlab-org/gitlab-test/-/services/jira/edit';
|
||||
|
||||
export const projectId = '5';
|
||||
|
||||
export const projectPath = 'gitlab-org/gitlab-test';
|
||||
|
||||
export const queryDetails = {
|
||||
query: getJiraImportDetailsQuery,
|
||||
variables: {
|
||||
|
@ -71,12 +81,6 @@ export const jiraImportMutationResponse = {
|
|||
},
|
||||
};
|
||||
|
||||
export const issuesPath = 'gitlab-org/gitlab-test/-/issues';
|
||||
|
||||
export const jiraIntegrationPath = 'gitlab-org/gitlab-test/-/services/jira/edit';
|
||||
|
||||
export const illustration = 'illustration.svg';
|
||||
|
||||
export const jiraProjects = [
|
||||
{ text: 'My Jira Project (MJP)', value: 'MJP' },
|
||||
{ text: 'My Second Jira Project (MSJP)', value: 'MSJP' },
|
||||
|
|
Loading…
Reference in New Issue