From 641db335df0efa2e0440ca8b49a3b5c58bd636a0 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Fri, 5 Jan 2018 00:16:59 +0100 Subject: [PATCH 01/20] Create CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..3a2ed8d5 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@thoteam.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ From 38c3536655a7ca4310fe5e85580c33721a66b60f Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Mon, 15 Jan 2018 14:12:59 +0100 Subject: [PATCH 02/20] Details on write_policy allowed values for hosted repositories --- README.md | 4 ++-- defaults/main.yml | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index f2fecd47..70a1bf20 100644 --- a/README.md +++ b/README.md @@ -343,7 +343,7 @@ Maven [proxy repositories](https://books.sonatype.com/nexus-book/3.0/reference/m nexus_repos_maven_hosted: - name: private-release version_policy: release - write_policy: allow_once + write_policy: allow_once # one of "allow", "allow_once" or "deny" ``` Maven [hosted repositories](https://books.sonatype.com/nexus-book/3.0/reference/maven.html#_hosting_maven_repositories) configuration. @@ -366,7 +366,7 @@ All three repository types are combined with the following default values : strict_content_validation: true version_policy: release # release, snapshot or mixed layout_policy: strict # strict or permissive - write_policy: allow_once # allow_once or allow + write_policy: allow_once # one of "allow", "allow_once" or "deny" ``` Docker, Pypi, Raw, Rubygems, Bower, NPM, Git-LFS and yum repository types: diff --git a/defaults/main.yml b/defaults/main.yml index 1e47140c..2b84bd24 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -198,7 +198,7 @@ nexus_repos_maven_proxy: nexus_repos_maven_hosted: - name: private-release version_policy: release - write_policy: allow_once + write_policy: allow_once # one of "allow", "allow_once" or "deny" nexus_repos_maven_group: - name: public @@ -264,7 +264,7 @@ _nexus_repos_maven_defaults: strict_content_validation: true version_policy: release # release, snapshot or mixed layout_policy: strict # strict or permissive - write_policy: allow_once # allow_once or allow + write_policy: allow_once # one of "allow", "allow_once" or "deny" # pypi support ... _nexus_repos_pypi_defaults: @@ -272,12 +272,12 @@ _nexus_repos_pypi_defaults: strict_content_validation: true version_policy: release # release, snapshot or mixed layout_policy: strict # strict or permissive - write_policy: allow_once # allow_once or allow + write_policy: allow_once # one of "allow", "allow_once" or "deny" nexus_repos_pypi_hosted: - name: pypi-internal version_policy: release - write_policy: allow + write_policy: allow # one of "allow", "allow_once" or "deny" nexus_repos_pypi_group: - name: pypi-all @@ -296,7 +296,7 @@ _nexus_repos_raw_defaults: strict_content_validation: true version_policy: release # release, snapshot or mixed layout_policy: strict # strict or permissive - write_policy: allow_once # allow_once or allow + write_policy: allow_once # one of "allow", "allow_once" or "deny" nexus_repos_raw_proxy: - name: ubuntu-archive @@ -305,7 +305,7 @@ nexus_repos_raw_proxy: nexus_repos_raw_hosted: - name: raw-internal version_policy: release - write_policy: allow_once + write_policy: allow_once # one of "allow", "allow_once" or "deny" nexus_repos_raw_group: - name: raw-all @@ -320,7 +320,7 @@ _nexus_repos_docker_defaults: strict_content_validation: true version_policy: release # release, snapshot or mixed layout_policy: strict # strict or permissive - write_policy: allow_once # allow_once or allow + write_policy: allow_once # one of "allow", "allow_once" or "deny" nexus_repos_docker_hosted: - name: docker-hosted @@ -347,7 +347,7 @@ nexus_repos_docker_group: _nexus_repos_rubygems_defaults: blob_store: "{{ nexus_blob_names.ruby.blob }}" strict_content_validation: true - write_policy: allow_once # allow_once or allow + write_policy: allow_once # one of "allow", "allow_once" or "deny" nexus_repos_rubygems_hosted: - name: rubygems-hosted @@ -369,7 +369,7 @@ nexus_repos_rubygems_proxy: _nexus_repos_bower_defaults: blob_store: "{{ nexus_blob_names.bower.blob }}" strict_content_validation: true - write_policy: allow_once # allow_once or allow + write_policy: allow_once # one of "allow", "allow_once" or "deny" nexus_repos_bower_hosted: - name: bower-internal @@ -391,7 +391,7 @@ nexus_repos_bower_proxy: _nexus_repos_npm_defaults: blob_store: "{{ nexus_blob_names.npm.blob }}" strict_content_validation: true - write_policy: allow_once # allow_once or allow + write_policy: allow_once # one of "allow", "allow_once" or "deny" nexus_repos_npm_hosted: - name: npm-internal @@ -412,7 +412,7 @@ nexus_repos_npm_proxy: _nexus_repos_nuget_defaults: blob_store: "{{ nexus_blob_names.nuget.blob }}" strict_content_validation: true - write_policy: allow_once # allow_once or allow + write_policy: allow_once # one of "allow", "allow_once" or "deny" nexus_repos_nuget_hosted: - name: nuget-internal @@ -434,7 +434,7 @@ nexus_repos_nuget_proxy: _nexus_repos_gitlfs_defaults: blob_store: "{{ nexus_blob_names.gitlfs.blob }}" strict_content_validation: true - write_policy: allow # allow_once or allow + write_policy: allow # one of "allow", "allow_once" or "deny" nexus_repos_gitlfs_hosted: - name: gitlfs-internal From eab84dbad77dd060a10166356db88af5e11b0480 Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Tue, 16 Jan 2018 19:37:37 -0500 Subject: [PATCH 03/20] Updating tasks without deleting them first --- files/groovy/create_task.groovy | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/files/groovy/create_task.groovy b/files/groovy/create_task.groovy index 9eb574ed..9a6dd127 100644 --- a/files/groovy/create_task.groovy +++ b/files/groovy/create_task.groovy @@ -12,12 +12,15 @@ TaskInfo existingTask = taskScheduler.listsTasks().find { TaskInfo taskInfo -> taskInfo.name == parsed_args.name } -if (existingTask && !existingTask.remove()) { - throw new RuntimeException("Could not remove currently running task : " + parsed_args.name) +if (existingTask && existingTask.getCurrentState().getRunState() != null) { + log.info("Could not update currently running task : " + parsed_args.name) + return } TaskConfiguration taskConfiguration = taskScheduler.createTaskConfigurationInstance(parsed_args.typeId) +if (existingTask) { taskConfiguration.setId(existingTask.getId()) } taskConfiguration.setName(parsed_args.name) +taskConfiguration.setEnabled(parsed_args.enabled) parsed_args.taskProperties.each { key, value -> taskConfiguration.setString(key, value) } From de3a21b5643b49726261cba82339f0babf6b9ea5 Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Tue, 16 Jan 2018 20:35:43 -0500 Subject: [PATCH 04/20] Remove custom enabled boolean --- files/groovy/create_task.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/files/groovy/create_task.groovy b/files/groovy/create_task.groovy index 9a6dd127..241c0103 100644 --- a/files/groovy/create_task.groovy +++ b/files/groovy/create_task.groovy @@ -20,7 +20,6 @@ if (existingTask && existingTask.getCurrentState().getRunState() != null) { TaskConfiguration taskConfiguration = taskScheduler.createTaskConfigurationInstance(parsed_args.typeId) if (existingTask) { taskConfiguration.setId(existingTask.getId()) } taskConfiguration.setName(parsed_args.name) -taskConfiguration.setEnabled(parsed_args.enabled) parsed_args.taskProperties.each { key, value -> taskConfiguration.setString(key, value) } From ad79ed286f592df9fd43e81a2fe75a5d0aebee7b Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 17 Jan 2018 18:10:20 +0100 Subject: [PATCH 05/20] Add notification for Ansible Galaxy --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 99231fe8..549dce13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,3 +12,5 @@ install: - pip install -r requirements.txt script: - ./tests/test_molecule.sh +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ From 3bfac43694ce6978bad9b11fa4cd837f94d88ea4 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Thu, 4 Jan 2018 22:41:39 +0100 Subject: [PATCH 06/20] Change pattern for backup directory name - Use a 4 digit year - Use hours, minutes and seconds to allow several backups a day --- templates/backup.groovy.j2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/backup.groovy.j2 b/templates/backup.groovy.j2 index f1aca891..49ffcf76 100644 --- a/templates/backup.groovy.j2 +++ b/templates/backup.groovy.j2 @@ -23,7 +23,7 @@ nexusBackupLogFilePath = "{{ nexus_backup_log }}" nexusBackupDirPath = "{{ nexus_backup_dir }}" nexusDataDirPath = "{{ nexus_data_dir }}" -backupDateString = LocalDateTime.now().format(DateTimeFormatter.ofPattern('YY-MM-dd')) +backupDateString = LocalDateTime.now().format(DateTimeFormatter.ofPattern('YYYY-MM-dd-HH-mm-ss')) CurrentBackupDirPath = nexusBackupDirPath+'/blob-backup-'+backupDateString backupLog = new File(nexusBackupLogFilePath) @@ -55,4 +55,4 @@ try { tempBackupTask.remove() } catch (Exception e) { backupLog << e.toString() -} \ No newline at end of file +} From 6e8f28c332484ab5cab437447ad1a6fc32478cb7 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Fri, 12 Jan 2018 10:42:17 +0100 Subject: [PATCH 07/20] Rework restore script --- tasks/nexus-restore.yml | 9 +++++++++ templates/nexus-blob-restore.sh.j2 | 16 +++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/tasks/nexus-restore.yml b/tasks/nexus-restore.yml index 0f8e384c..8bfe866e 100644 --- a/tasks/nexus-restore.yml +++ b/tasks/nexus-restore.yml @@ -1,4 +1,13 @@ --- +- name: Make sure nexus is stopped + debug: + msg: "trigger nexus stop" + changed_when: true + notify: + - nexus-service-stop + +- meta: flush_handlers + - name: "Run restoration script" shell: "nexus-blob-restore.sh {{ nexus_restore_point }} 2>&1 | tee -a {{ nexus_restore_log }}" tags: diff --git a/templates/nexus-blob-restore.sh.j2 b/templates/nexus-blob-restore.sh.j2 index 58a01d8c..501688f2 100644 --- a/templates/nexus-blob-restore.sh.j2 +++ b/templates/nexus-blob-restore.sh.j2 @@ -1,19 +1,25 @@ #! /bin/bash - +#{{ansible_managed}} set -x -if [ "x$1" = "x" ]; then MDATE='$(date +%y-%m-%d)'; else MDATE =$1; fi +if [ "x$1" = "x" ]; then + echo "Restore script is expecting a restore point as parameter" + echo "None provided. exiting" + exit 1 +fi # Generated with Ansible vars -MDATE=$1 ## Should be %y-%m-%d format +MDATE=$1 ## Should be %Y-%m-%d-%H-%M-%S format blob_dir="blob-backup-${MDATE}" backup_dir={{ nexus_backup_dir }} data_dir={{ nexus_data_dir }} blob_prefix={{ nexus_blob_prefix |d('blob-') }} systemctl stop nexus -if [ $? != 0 ]; then - echo "Error code: $? Failed to stop nexus service" +return_status=$? +if [ $return_status != 0 ]; then + echo "Error code: $return_status Failed to stop nexus service" + exit $return_status else rm -rf ${data_dir}/db/* rm -rf ${data_dir}/blobs/* From 47008c6c4a894fa24cefcd119dd0779ae4e02415 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Fri, 12 Jan 2018 10:42:52 +0100 Subject: [PATCH 08/20] Update doc --- README.md | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 70a1bf20..a0bee069 100644 --- a/README.md +++ b/README.md @@ -442,27 +442,20 @@ These are all false unless you override them from playbook / group_var / cli, th ``` Backup will not be configured unless you switch `nexus_backup_configure` to `true`. -In this case, a scheduled script task will be configured in nexus to run every day -at time specified by `nexus_backup_cron` (defaults to 9pm). +In this case, a scheduled script task will be configured in nexus to run +at interval specified by `nexus_backup_cron` (defaults to 21:00 every day). See [the groovy template for this task](templates/backup.groovy.j2) for details. This scheduled task is independent from the other `nexus_scheduled_tasks` you declare in your playbook -Note that `nexus_backup_log` must be writable by the nexus user or the backup -task will fail +Note that `nexus_backup_log` _must be writable_ by the nexus user or the **backup +task will fail** #### Restore procedure - -Run your playbook with parameter `-e nexus_restore_point=` -(e.g. 17-12-17 for 17th of December 2017) +Run your playbook with parameter `-e nexus_restore_point=` +(e.g. 2017-12-17-21-00-00 for 17th of December 2017 at 21h00m00s) #### Current limitations -* Due to the initial chosen naming convention for restore points, -backups can only be ran once a day (this will be fixed in a future release - see #19). -Running more than once a day will work without errors but will: - * overwrite the last blobstore copy in the current daily backup dir - * multiply the instances of nexus db backup files in the daily backup dir - which might later confuse the restore script. * There is no rotation for backups. All of them will be kept unless you implement a rotation/cleanup by yourself. This might be added as an enhancement in a future release * Blobstore copies are made directly from nexus by the script scheduled task. From 191f8c5e56403000de6026e29c021faf1477db34 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Tue, 30 Jan 2018 08:42:54 +0100 Subject: [PATCH 09/20] Add backup config to selinux molecule scenario --- molecule/selinux/playbook.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/molecule/selinux/playbook.yml b/molecule/selinux/playbook.yml index 5bf5c521..b442a209 100644 --- a/molecule/selinux/playbook.yml +++ b/molecule/selinux/playbook.yml @@ -12,3 +12,5 @@ httpd_copy_ssl_files: false httpd_ssl_cert_file_location: "{{ default_cert }}" httpd_ssl_cert_key_location: "{{ default_key }}" + + nexus_backup_configure: true From 6b08ab588702586d0deeea404fb91fae856990ed Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 31 Jan 2018 08:05:56 +0100 Subject: [PATCH 10/20] Identation in .travis.yml introduded in an other branch --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 549dce13..cb2d49fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,4 +13,4 @@ install: script: - ./tests/test_molecule.sh notifications: - webhooks: https://galaxy.ansible.com/api/v1/notifications/ + webhooks: https://galaxy.ansible.com/api/v1/notifications/ From 6331cb1f855e831929be198025ac65cd4b6ddcb5 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 31 Jan 2018 08:41:51 +0100 Subject: [PATCH 11/20] Move backup configuration options together in defaults --- defaults/main.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 2b84bd24..ad787598 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -2,7 +2,6 @@ nexus_version: '3.7.1-02' nexus_package: "nexus-{{ nexus_version }}-unix.tar.gz" nexus_download_dir: '/tmp' -nexus_backup_dir: '/var/nexus-backup' nexus_os_group: 'nexus' nexus_os_user: 'nexus' nexus_os_max_filedescriptors: 65536 # nexus > 3.5.x issues a warning on lower value. Next versions might not boot at all @@ -11,8 +10,16 @@ nexus_data_dir: '/var/nexus' nexus_timezone: 'UTC' # java timezone nexus_tmp_dir: '/tmp/nexus' nexus_script_dir: '{{ nexus_installation_dir }}/nexus-{{ nexus_version }}/etc/scripts' + + +# Nexus Backup +nexus_backup_dir: '/var/nexus-backup' nexus_restore_log: '{{ nexus_backup_dir }}/nexus-restore.log' nexus_backup_log: '{{ nexus_backup_dir }}/nexus-backup.log' +# Shall we configure backup ? +nexus_backup_configure: false +# Backup time cron expression +nexus_backup_cron: "* 0 21 * * ?" # See cron expression in nexus create task GUI # Nexus restore procedure: # run ansible-playbook example.yml -e "nexus_restore_point=(# date of choice -> %y-%m-%d #)" @@ -206,14 +213,6 @@ nexus_repos_maven_group: - central - jboss -######## -# Nexus Backup -# Shall we configure backup ? -nexus_backup_configure: false -# Backup time cron expression -# Current limitation: can only be ran once a day -nexus_backup_cron: "* 0 21 * * ?" # See cron expression in nexus create task GUI - # Scheduled tasks # Note: these are tasks you define by yourself (default: none) # If you used `nexus_backup_configure: true` above you will see a scheduled task for this From 05862b25a49cd2271efa3628f3bdadb250a070be Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 31 Jan 2018 08:44:43 +0100 Subject: [PATCH 12/20] Update backup name format in defaults (was already done in README.md) --- defaults/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index ad787598..7a53818a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -22,8 +22,8 @@ nexus_backup_configure: false nexus_backup_cron: "* 0 21 * * ?" # See cron expression in nexus create task GUI # Nexus restore procedure: -# run ansible-playbook example.yml -e "nexus_restore_point=(# date of choice -> %y-%m-%d #)" -# nexus_restore_point: '17-02-22' # Example format +# run ansible-playbook example.yml -e "nexus_restore_point=(# date of choice -> %Y-%m-%d-%H-%M-%S #)" +# nexus_restore_point: '2017-02-22-01-30-32' # Example format # Nexus purge procedure: # run ansible-playbook example.yml -e "purge=true" From b75e4416bd0509ab7b54d5837f0577cc745d6bb3 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 31 Jan 2018 08:58:44 +0100 Subject: [PATCH 13/20] Add variables and doc for backup rotation (implementation to come) --- README.md | 14 +++++++++----- defaults/main.yml | 3 +++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a0bee069..2f82f34c 100644 --- a/README.md +++ b/README.md @@ -439,15 +439,21 @@ These are all false unless you override them from playbook / group_var / cli, th nexus_backup_dir: '/var/nexus-backup' nexus_backup_log: '{{ nexus_backup_dir }}/nexus-backup.log' nexus_restore_log: '{{ nexus_backup_dir }}/nexus-restore.log' + nexus_backup_rotate: false + nexus_backup_keep_rotations: 4 # Keep 4 backup rotation by default (current + last 3) ``` -Backup will not be configured unless you switch `nexus_backup_configure` to `true`. +Backup will not be configured unless you switch `nexus_backup_configure: true`. In this case, a scheduled script task will be configured in nexus to run at interval specified by `nexus_backup_cron` (defaults to 21:00 every day). See [the groovy template for this task](templates/backup.groovy.j2) for details. This scheduled task is independent from the other `nexus_scheduled_tasks` you declare in your playbook +If you want to rotate backups, set `nexus_backup_rotate: true` and adjust +the number of rotations you would like to keep with `nexus_backup_keep_rotations` +(defaults to 4) + Note that `nexus_backup_log` _must be writable_ by the nexus user or the **backup task will fail** @@ -455,10 +461,8 @@ task will fail** Run your playbook with parameter `-e nexus_restore_point=` (e.g. 2017-12-17-21-00-00 for 17th of December 2017 at 21h00m00s) -#### Current limitations -* There is no rotation for backups. All of them will be kept unless you implement -a rotation/cleanup by yourself. This might be added as an enhancement in a future release -* Blobstore copies are made directly from nexus by the script scheduled task. +#### Possible limitations +Blobstore copies are made directly from nexus by the script scheduled task. This has only been tested on rather small blobstores (less than 50Go) and should be used with caution and tested carefully on larger installations before moving to production. In any case, you are free to implement your own backup scenario diff --git a/defaults/main.yml b/defaults/main.yml index 7a53818a..f309fc00 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -20,6 +20,9 @@ nexus_backup_log: '{{ nexus_backup_dir }}/nexus-backup.log' nexus_backup_configure: false # Backup time cron expression nexus_backup_cron: "* 0 21 * * ?" # See cron expression in nexus create task GUI +# Shall we rotate backups ? No effect if nexus_backup_configure is false +nexus_backup_rotate: false +nexus_backup_keep_rotations: 4 # Keep 4 backup rotation by default (current + last 3) # Nexus restore procedure: # run ansible-playbook example.yml -e "nexus_restore_point=(# date of choice -> %Y-%m-%d-%H-%M-%S #)" From 622b31f657c6889ec9c7115497556a23e1c2ed78 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 7 Feb 2018 00:34:46 +0100 Subject: [PATCH 14/20] Implementation of backup rotation --- templates/backup.groovy.j2 | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/templates/backup.groovy.j2 b/templates/backup.groovy.j2 index 49ffcf76..4fadd7cf 100644 --- a/templates/backup.groovy.j2 +++ b/templates/backup.groovy.j2 @@ -7,6 +7,7 @@ import org.sonatype.nexus.scheduling.TaskInfo import org.sonatype.nexus.scheduling.schedule.Schedule import java.util.concurrent.TimeUnit + /** * This groovy script is meant to be included in a schedulled task in nexus. * It will perform a full backup of your installation with the following steps. @@ -16,12 +17,15 @@ import java.util.concurrent.TimeUnit * 4- Copy all blobstores from /blobs to /blob-backup- * 5- Eventually wait for the nexus temporary db-backup task to complete * 6- Delete the nexus temporary db-backup task + * 7- If is true, rotate backup dirs keeping last backups */ nexusBackupLogFilePath = "{{ nexus_backup_log }}" nexusBackupDirPath = "{{ nexus_backup_dir }}" nexusDataDirPath = "{{ nexus_data_dir }}" +nexusBackupRotate = Boolean.valueOf("{{ nexus_backup_rotate }}") +nexusBackupKeepRotations = "{{ nexus_backup_keep_rotations }}".toInteger() backupDateString = LocalDateTime.now().format(DateTimeFormatter.ofPattern('YYYY-MM-dd-HH-mm-ss')) CurrentBackupDirPath = nexusBackupDirPath+'/blob-backup-'+backupDateString @@ -53,6 +57,29 @@ try { } backupLog << "Remove temporary task\n" tempBackupTask.remove() + + if (nexusBackupRotate) { + backupLog << "Rotating backups keeping last "+nexusBackupKeepRotations.toString()+" Backups\n" + backupDirs = [] + backupCounter = 0 + backupPattern = ~/blob-backup-.*/ + new File(nexusBackupDirPath).eachDirMatch(backupPattern) { dir -> + backupDirs << dir + } + backupDirs.sort{ it.name }.reverse().each { dir -> + backupCounter++ + if (backupCounter > nexusBackupKeepRotations) { + backupLog << "Deleting backup "+ dir.name.toString() + "\n" + dir.deleteDir() + } + } + if (backupCounter > nexusBackupKeepRotations) { + backupDeleted = backupCounter - nexusBackupKeepRotations + backupLog << "Deleted a total of "+ backupDeleted + " backup directories\n" + } else { + backupLog << "There where no backup directories to delete\n" + } + } } catch (Exception e) { backupLog << e.toString() } From 110311a94395dbe7866126f0d8f683e054a4c91b Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 7 Feb 2018 00:51:01 +0100 Subject: [PATCH 15/20] Bump nexus version to 3.8 --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index f309fc00..b75ef0a0 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,5 +1,5 @@ --- -nexus_version: '3.7.1-02' +nexus_version: '3.8.0-02' nexus_package: "nexus-{{ nexus_version }}-unix.tar.gz" nexus_download_dir: '/tmp' nexus_os_group: 'nexus' From 666bd654cbab8288674ec77d1b0503cfd0fe9483 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 7 Feb 2018 08:19:36 +0100 Subject: [PATCH 16/20] Set rest api endpoint depending on nexus version --- tasks/call_script.yml | 2 +- tasks/declare_script_each.yml | 4 ++-- tasks/nexus_install.yml | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tasks/call_script.yml b/tasks/call_script.yml index 6cb1d571..1edcb9ca 100644 --- a/tasks/call_script.yml +++ b/tasks/call_script.yml @@ -1,7 +1,7 @@ --- - name: Calling Groovy script {{ script_name }} uri: - url: "http://localhost:{{ nexus_default_port }}{{ nexus_default_context_path }}service/siesta/rest/v1/script/{{ script_name }}/run" + url: "http://localhost:{{ nexus_default_port }}{{ nexus_default_context_path }}{{ nexus_rest_api_endpoint }}/{{ script_name }}/run" user: 'admin' password: "{{ current_nexus_admin_password }}" headers: diff --git a/tasks/declare_script_each.yml b/tasks/declare_script_each.yml index 5bd23f26..16b231a7 100644 --- a/tasks/declare_script_each.yml +++ b/tasks/declare_script_each.yml @@ -1,7 +1,7 @@ --- - name: Removing (potential) previously declared Groovy script {{ item }} uri: - url: "http://localhost:{{ nexus_default_port }}{{ nexus_default_context_path }}service/siesta/rest/v1/script/{{ item }}" + url: "http://localhost:{{ nexus_default_port }}{{ nexus_default_context_path }}{{ nexus_rest_api_endpoint }}/{{ item }}" user: 'admin' password: "{{ current_nexus_admin_password }}" method: DELETE @@ -10,7 +10,7 @@ - name: Declaring Groovy script {{ item }} uri: - url: "http://localhost:{{ nexus_default_port }}{{ nexus_default_context_path }}service/siesta/rest/v1/script" + url: "http://localhost:{{ nexus_default_port }}{{ nexus_default_context_path }}{{ nexus_rest_api_endpoint }}" user: 'admin' password: "{{ current_nexus_admin_password }}" body_format: json diff --git a/tasks/nexus_install.yml b/tasks/nexus_install.yml index 85511d47..5f291bb0 100644 --- a/tasks/nexus_install.yml +++ b/tasks/nexus_install.yml @@ -77,6 +77,16 @@ - "{{ nexus_installation_dir }}/nexus-latest/etc/scripts" when: nexus_version >= '3.1.0' +- name: Get rest API endpoint (v < 3.8.0) + set_fact: + nexus_rest_api_endpoint: "service/siesta/rest/v1/script" + when: nexus_version < '3.8.0' + +- name: Get rest API endpoint (v >= 3.8.0) + set_fact: + nexus_rest_api_endpoint: "service/rest/v1/script" + when: nexus_version >='3.8.0' + - name: Allow nexus to create first-time install configuration files in {{ nexus_installation_dir }}/nexus-latest/etc file: path: "{{ item }}" From f010258de264224283d37eee81cadfc0891e6133 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 7 Feb 2018 08:36:27 +0100 Subject: [PATCH 17/20] Add reference to mod_proxy_http in documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f82f34c..25762700 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ We would like to thank the original authors for the work done. - For more information see [nexus3 system requirements](https://help.sonatype.com/display/NXRM3/System+Requirements) - Apache HTTPD (optional) - Used to setup a SSL reverse-proxy - - The following modules must be enabled in your configuration: mod_ssl, mod_rewrite, mod_proxy, mod_headers. + - The following modules must be enabled in your configuration: mod_ssl, mod_rewrite, mod_proxy, mod_proxy_http, mod_headers. (see [Dependencies](#dependencies) section below for matching roles on galaxy) From 0c76400b938b8b62ca133ba7a7b87f448989a9d6 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 7 Feb 2018 09:01:38 +0100 Subject: [PATCH 18/20] Put sctructure in place for new doc --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 25762700..12e4b35b 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ All configuration can be updated by re-running the role, except for the [blobsto * [Scheduled tasks](#scheduled-tasks) * [Backups](#backups) * [Restore procedure](#restore-procedure) - * [Current limitations:](#current-limitations) + * [Possible limitations](#possible-limitations) * [Dependencies](#dependencies) * [Example Playbook](#example-playbook) * [Development, Contribution and Testing](#development-contribution-and-testing) @@ -34,6 +34,8 @@ All configuration can be updated by re-running the role, except for the [blobsto * [Testing](#testing) * [Groovy syntax](#groovy-syntax) * [Full role testing with molecule](#full-role-testing-with-molecule) + * [Molecule default scenario](#molecule-default-scenario) + * [Molecule selinux scenario](#molecule-selinux-scenario) * [Testing everything](#testing-everything) * [License](#license) * [Author Information](#author-information) @@ -597,6 +599,7 @@ If you wish to contribute: - Create a branch in your own repo with a meaningfull name. We suggest the following naming convention: - feature_ for features - fix_ for bug fixes + - docfix_ for documentation only fixes - If starting an important feature change, open a pull request early describing what you want to do so we can discuss it if needed. This will prevent you from doing a lot of hard work on a lot of code for changes that we cannot finally merge. - If there are build error on your pull request, have a look at the travis log and fix the relevant errors. @@ -620,6 +623,8 @@ You will need the groovy package installed locally to run this test. #### Full role testing with molecule +##### Molecule default scenario + The role is tested on travis with [molecule](https://pypi.python.org/pypi/molecule). You can run these tests locally. The best way to achieve this is through a python virtualenv. You can find some more details in [requirements.txt](requirements.txt). ```bash # Note: the following path should be outside the working dir @@ -634,6 +639,8 @@ To speed up tests, molecule uses automated docker build images on docker hub: - https://hub.docker.com/r/thoteam/ansible-ubuntu16.04-apache-java/ - https://hub.docker.com/r/thoteam/ansible-centos7-apache-java/ +##### Molecule selinux scenario + #### Testing everything As a convenience, we provide a script to run all test as once: ```bash From 7ea23f56c3b5f163187e969c4a47b23151fcbcf3 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 7 Feb 2018 20:50:53 +0100 Subject: [PATCH 19/20] Firt 'fast and dirty' doc for molecule selinux scenario + some fixes --- README.md | 111 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 12e4b35b..0fcbcb0c 100644 --- a/README.md +++ b/README.md @@ -5,40 +5,42 @@ This role installs and configures Nexus Repository Manager OSS version 3.x. All configuration can be updated by re-running the role, except for the [blobstores](https://books.sonatype.com/nexus-book/3.0/reference/admin.html#admin-repository-blobstores)-related settings, which are immutable in nexus. ## Table of Contents -(Toc created with [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)) - -* [History / Credits](#history--credits) -* [Requirements](#requirements) -* [Role Variables](#role-variables) - * [General variables](#general-variables) - * [Download dir for nexus package](#download-dir-for-nexus-package) - * [Nexus port and context path](#nexus-port-and-context-path) - * [Nexus OS user and group](#nexus-os-user-and-group) - * [Nexus instance directories](#nexus-instance-directories) - * [Admin password](#admin-password) - * [Default anonymous access](#default-anonymous-access) - * [Public hostname](#public-hostname) - * [Branding capabalities](#branding-capabalities) - * [Reverse proxy setup](#reverse-proxy-setup) - * [LDAP configuration](#ldap-configuration) - * [Privileges, roles and users](#privileges-roles-and-users) - * [Blobstores and repositories](#blobstores-and-repositories) - * [Scheduled tasks](#scheduled-tasks) - * [Backups](#backups) - * [Restore procedure](#restore-procedure) - * [Possible limitations](#possible-limitations) -* [Dependencies](#dependencies) -* [Example Playbook](#example-playbook) -* [Development, Contribution and Testing](#development-contribution-and-testing) - * [Contributions](#contributions) - * [Testing](#testing) - * [Groovy syntax](#groovy-syntax) - * [Full role testing with molecule](#full-role-testing-with-molecule) - * [Molecule default scenario](#molecule-default-scenario) - * [Molecule selinux scenario](#molecule-selinux-scenario) - * [Testing everything](#testing-everything) -* [License](#license) -* [Author Information](#author-information) + + * [Ansible Role: Nexus 3 OSS](#ansible-role-nexus-3-oss) + * [Table of Contents](#table-of-contents) + * [History / Credits](#history--credits) + * [Requirements](#requirements) + * [Role Variables](#role-variables) + * [General variables](#general-variables) + * [Download dir for nexus package](#download-dir-for-nexus-package) + * [Nexus port and context path](#nexus-port-and-context-path) + * [Nexus OS user and group](#nexus-os-user-and-group) + * [Nexus instance directories](#nexus-instance-directories) + * [Admin password](#admin-password) + * [Default anonymous access](#default-anonymous-access) + * [Public hostname](#public-hostname) + * [Branding capabalities](#branding-capabalities) + * [Reverse proxy setup](#reverse-proxy-setup) + * [LDAP configuration](#ldap-configuration) + * [Privileges, roles and users](#privileges-roles-and-users) + * [Blobstores and repositories](#blobstores-and-repositories) + * [Scheduled tasks](#scheduled-tasks) + * [Backups](#backups) + * [Restore procedure](#restore-procedure) + * [Possible limitations](#possible-limitations) + * [Dependencies](#dependencies) + * [Example Playbook](#example-playbook) + * [Development, Contribution and Testing](#development-contribution-and-testing) + * [Contributions](#contributions) + * [Testing](#testing) + * [Groovy syntax](#groovy-syntax) + * [Molecule default scenario](#molecule-default-scenario) + * [Testing everything](#testing-everything) + * [Molecule selinux scenario](#molecule-selinux-scenario) + * [License](#license) + * [Author Information](#author-information) + +Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)git s ## History / Credits @@ -596,7 +598,7 @@ All contributions to this role are welcome, either for bugfixes, new features or If you wish to contribute: - Fork the repo under your own name/organisation through github interface -- Create a branch in your own repo with a meaningfull name. We suggest the following naming convention: +- Create a branch **from the dev branch** in your own repo with a meaningfull name. We suggest the following naming convention: - feature_ for features - fix_ for bug fixes - docfix_ for documentation only fixes @@ -608,7 +610,7 @@ Moreover, if you have time to devote for code review, merge for realeases, etc.. ### Testing -This role includes tests and CI integration through travis. For build time sake, not all tests are run on travis. Currently, only molecule deployment tests are ran automatically on every merge request creation/upate. +This role includes tests and CI integration through travis. For build time sake, not all tests are run on travis. Currently, only default molecule deployment tests are ran automatically on every merge request creation/upate. #### Groovy syntax @@ -621,9 +623,7 @@ If you submit changes to groovy files, please run the groovy syntax check locall You will need the groovy package installed locally to run this test. -#### Full role testing with molecule - -##### Molecule default scenario +#### Molecule default scenario The role is tested on travis with [molecule](https://pypi.python.org/pypi/molecule). You can run these tests locally. The best way to achieve this is through a python virtualenv. You can find some more details in [requirements.txt](requirements.txt). ```bash @@ -636,17 +636,40 @@ deactivate ``` To speed up tests, molecule uses automated docker build images on docker hub: -- https://hub.docker.com/r/thoteam/ansible-ubuntu16.04-apache-java/ -- https://hub.docker.com/r/thoteam/ansible-centos7-apache-java/ - -##### Molecule selinux scenario +* https://hub.docker.com/r/thoteam/ansible-ubuntu16.04-apache-java/ +* https://hub.docker.com/r/thoteam/ansible-centos7-apache-java/ #### Testing everything -As a convenience, we provide a script to run all test as once: +As a convenience, we provide a script to run all test at once (including the default molecule scenario) ```bash ./tests/test_all.sh ``` +##### Molecule selinux scenario + +We included a second molecule `selinux` scenario. This one is not run on travis but can be used locally to: +* test selinux integration (on centos). +* run test and access the running vms under VirtualBox on you local machine. + +If you which to use this scenario you will need +* VirtualBox +* Vagrant +* molecule + +A typical workflow runs like this: +* `molecule create -s selinux`. Once this is complete, you will see two vagrant vms (centos7 and debian-stretch) in your VirtualBox console. +These Vagrant box are taken from http://vagrant.thoteam.com +* `molecule converge -s selinux` will run the [scenario test playbook](molecule/selinux/playbook.yml) against the two vms. +You can pass additionnal variables to ansible on the command line to override playbook or default vars +(e.g. `molecule converge -s selinux -- -e nexus_backup_rotate=true`). You can converge as many times as you want. +* To access the nexus gui on each machine, right click the vm in VirtualBox console, click settings. In the Network settings +for Adapter 1, click advanced, then Port Forwarding. Choose an available Host Port linked to Host IP 127.0.0.1 forwarding +to port 443 on the guest. +* You can now access the gui with https://localhost:. You will need to add a security exception for the +self signed ssl certificate. If you did not change it with a command line var above, the default role admin password is "changeme" +* When you're happy with your testing, you can recycle the used space with `molecule destroy -s selinux` + + ## License GNU GPLv3 From 21594dde31638b596855ff281a5bd2130793d9c0 Mon Sep 17 00:00:00 2001 From: Olivier Clavel Date: Wed, 7 Feb 2018 23:06:17 +0100 Subject: [PATCH 20/20] Document required security realm for ldap + other possible needed realms --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 0fcbcb0c..501c3119 100644 --- a/README.md +++ b/README.md @@ -166,13 +166,18 @@ Use already existing SSL certificates on the server file system for the https re Set httpd default admin email address ### LDAP configuration + +Ldap connections and security realm are disabled by default + ```yaml + nexus_ldap_realm: false ldap_connections: [] ``` [LDAP connection(s)](https://books.sonatype.com/nexus-book/3.0/reference/security.html#ldap) setup, each item goes as follow : ```yaml + nexus_ldap_realm: true - ldap_name: 'My Company LDAP' # used as a key to update the ldap config ldap_protocol: 'ldaps' # ldap or ldaps ldap_hostname: 'ldap.mycompany.com' @@ -200,6 +205,7 @@ Set httpd default admin email address Example LDAP config for anonymous authentication (anonymous bind), this is also the "minimal" config : ```yaml + nexus_ldap_realm: true - ldap_name: 'Simplest LDAP config' ldap_protocol: 'ldaps' ldap_hostname: 'annuaire.mycompany.com' @@ -214,6 +220,7 @@ Example LDAP config for anonymous authentication (anonymous bind), this is also Example LDAP config for simple authentication (using a DSA account) : ```yaml + nexus_ldap_realm: true - ldap_name: 'LDAP config with DSA' ldap_protocol: 'ldaps' ldap_hostname: 'annuaire.mycompany.com' @@ -233,6 +240,7 @@ Example LDAP config for simple authentication (using a DSA account) : Example LDAP config for simple authentication (using a DSA account) + groups mapped as roles : ```yaml + nexus_ldap_realm: true - ldap_name: 'LDAP config with DSA' ldap_protocol: 'ldaps' ldap_hostname: 'annuaire.mycompany.com' @@ -389,6 +397,15 @@ see `defaults/main.yml` for these options: These are all false unless you override them from playbook / group_var / cli, these all utilize the same mechanism as maven. +Note that you might need to enable certain security realms if you want to use other repository types than maven. These are +false by default + +```yaml +nexus_nuget_api_key_realm: false +nexus_npm_bearer_token_realm: false +nexus_docker_bearer_token_realm: false # required for docker anonymous access +``` + ### Scheduled tasks ```yaml nexus_scheduled_tasks: []