diff --git a/readme.md b/readme.md index 3864695..64a4182 100644 --- a/readme.md +++ b/readme.md @@ -43,3 +43,4 @@ * [8.5. Тестирование Roles](/src/homework/08-ansible/8.5) * [8.6. Создание собственных modules](/src/homework/08-ansible/8.6) * [9.1. Жизненный цикл ПО](/src/homework/09-ci/9.1) +* [9.3. CI\CD](/src/homework/09-ci/9.3) diff --git a/src/homework/09-ci/9.3/example/.gitignore b/src/homework/09-ci/9.3/example/.gitignore new file mode 100644 index 0000000..22646a4 --- /dev/null +++ b/src/homework/09-ci/9.3/example/.gitignore @@ -0,0 +1 @@ +/.scannerwork/ diff --git a/src/homework/09-ci/9.3/example/fail.py b/src/homework/09-ci/9.3/example/fail.py new file mode 100644 index 0000000..cbe3b95 --- /dev/null +++ b/src/homework/09-ci/9.3/example/fail.py @@ -0,0 +1,12 @@ +def increment(index): + newIndex = index+1 + return newIndex +def get_square(numb): + return numb*numb +def print_numb(numb): + print("Number is {}".format(numb)) + +index = 0 +while (index < 10): + index = increment(index) + print(get_square(index)) diff --git a/src/homework/09-ci/9.3/img/nexus_main.png b/src/homework/09-ci/9.3/img/nexus_main.png new file mode 100644 index 0000000..9280c6c Binary files /dev/null and b/src/homework/09-ci/9.3/img/nexus_main.png differ diff --git a/src/homework/09-ci/9.3/img/nexus_maven_upload.png b/src/homework/09-ci/9.3/img/nexus_maven_upload.png new file mode 100644 index 0000000..f3dc3ba Binary files /dev/null and b/src/homework/09-ci/9.3/img/nexus_maven_upload.png differ diff --git a/src/homework/09-ci/9.3/img/nexus_maven_upload_success.png b/src/homework/09-ci/9.3/img/nexus_maven_upload_success.png new file mode 100644 index 0000000..ce8461b Binary files /dev/null and b/src/homework/09-ci/9.3/img/nexus_maven_upload_success.png differ diff --git a/src/homework/09-ci/9.3/img/sonar_main.png b/src/homework/09-ci/9.3/img/sonar_main.png new file mode 100644 index 0000000..e6e5025 Binary files /dev/null and b/src/homework/09-ci/9.3/img/sonar_main.png differ diff --git a/src/homework/09-ci/9.3/img/sonar_project_analysis.png b/src/homework/09-ci/9.3/img/sonar_project_analysis.png new file mode 100644 index 0000000..098863a Binary files /dev/null and b/src/homework/09-ci/9.3/img/sonar_project_analysis.png differ diff --git a/src/homework/09-ci/9.3/img/sonar_project_analysis_fix.png b/src/homework/09-ci/9.3/img/sonar_project_analysis_fix.png new file mode 100644 index 0000000..496dc22 Binary files /dev/null and b/src/homework/09-ci/9.3/img/sonar_project_analysis_fix.png differ diff --git a/src/homework/09-ci/9.3/infrastructure/.gitignore b/src/homework/09-ci/9.3/infrastructure/.gitignore new file mode 100644 index 0000000..aa04836 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/.gitignore @@ -0,0 +1,3 @@ +files/*.pub +roles/* +inventory/hosts.yml diff --git a/src/homework/09-ci/9.3/infrastructure/files/CentOS-Base.repo b/src/homework/09-ci/9.3/infrastructure/files/CentOS-Base.repo new file mode 100644 index 0000000..e4ae95b --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/files/CentOS-Base.repo @@ -0,0 +1,47 @@ +# CentOS-Base.repo +# +# The mirror system uses the connecting IP address of the client and the +# update status of each mirror to pick mirrors that are updated to and +# geographically close to the client. You should use this for CentOS updates +# unless you are manually picking other mirrors. +# +# If the mirrorlist= does not work for you, as a fall back you can try the +# remarked out baseurl= line instead. +# +# + +[base] +name=CentOS-$releasever - Base +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra +#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/ +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 + +exclude=postgresql* + +#released updates +[updates] +name=CentOS-$releasever - Updates +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra +#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/ +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 + +exclude=postgresql* + +#additional packages that may be useful +[extras] +name=CentOS-$releasever - Extras +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra +#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/ +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 + +#additional packages that extend functionality of existing packages +[centosplus] +name=CentOS-$releasever - Plus +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra +#baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/ +gpgcheck=1 +enabled=0 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 diff --git a/src/homework/09-ci/9.3/infrastructure/files/pg_hba.conf b/src/homework/09-ci/9.3/infrastructure/files/pg_hba.conf new file mode 100644 index 0000000..b5c361a --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/files/pg_hba.conf @@ -0,0 +1,89 @@ +# PostgreSQL Client Authentication Configuration File +# =================================================== +# +# Refer to the "Client Authentication" section in the PostgreSQL +# documentation for a complete description of this file. A short +# synopsis follows. +# +# This file controls: which hosts are allowed to connect, how clients +# are authenticated, which PostgreSQL user names they can use, which +# databases they can access. Records take one of these forms: +# +# local DATABASE USER METHOD [OPTIONS] +# host DATABASE USER ADDRESS METHOD [OPTIONS] +# hostssl DATABASE USER ADDRESS METHOD [OPTIONS] +# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] +# +# (The uppercase items must be replaced by actual values.) +# +# The first field is the connection type: "local" is a Unix-domain +# socket, "host" is either a plain or SSL-encrypted TCP/IP socket, +# "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a +# plain TCP/IP socket. +# +# DATABASE can be "all", "sameuser", "samerole", "replication", a +# database name, or a comma-separated list thereof. The "all" +# keyword does not match "replication". Access to replication +# must be enabled in a separate record (see example below). +# +# USER can be "all", a user name, a group name prefixed with "+", or a +# comma-separated list thereof. In both the DATABASE and USER fields +# you can also write a file name prefixed with "@" to include names +# from a separate file. +# +# ADDRESS specifies the set of hosts the record matches. It can be a +# host name, or it is made up of an IP address and a CIDR mask that is +# an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that +# specifies the number of significant bits in the mask. A host name +# that starts with a dot (.) matches a suffix of the actual host name. +# Alternatively, you can write an IP address and netmask in separate +# columns to specify the set of hosts. Instead of a CIDR-address, you +# can write "samehost" to match any of the server's own IP addresses, +# or "samenet" to match any address in any subnet that the server is +# directly connected to. +# +# METHOD can be "trust", "reject", "md5", "password", "scram-sha-256", +# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert". +# Note that "password" sends passwords in clear text; "md5" or +# "scram-sha-256" are preferred since they send encrypted passwords. +# +# OPTIONS are a set of options for the authentication in the format +# NAME=VALUE. The available options depend on the different +# authentication methods -- refer to the "Client Authentication" +# section in the documentation for a list of which options are +# available for which authentication methods. +# +# Database and user names containing spaces, commas, quotes and other +# special characters must be quoted. Quoting one of the keywords +# "all", "sameuser", "samerole" or "replication" makes the name lose +# its special character, and just match a database or username with +# that name. +# +# This file is read on server startup and when the server receives a +# SIGHUP signal. If you edit the file on a running system, you have to +# SIGHUP the server for the changes to take effect, run "pg_ctl reload", +# or execute "SELECT pg_reload_conf()". +# +# Put your actual configuration here +# ---------------------------------- +# +# If you want to allow non-local connections, you need to add more +# "host" records. In that case you will also need to make PostgreSQL +# listen on a non-local interface via the listen_addresses +# configuration parameter, or via the -i or -h command line switches. + + + +# TYPE DATABASE USER ADDRESS METHOD + +# "local" is for Unix domain socket connections only +local all all trust +# IPv4 local connections: +host all all 127.0.0.1/32 md5 +# IPv6 local connections: +host all all ::1/128 md5 +# Allow replication connections from localhost, by a user with the +# replication privilege. +local replication all trust +host replication all 127.0.0.1/32 md5 +host replication all ::1/128 md5 diff --git a/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/all.yml b/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/all.yml new file mode 100644 index 0000000..84d57ec --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/all.yml @@ -0,0 +1,8 @@ +--- +jdk_url: https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_linux-x64_bin.tar.gz +jdk_distr_name: openjdk-11+28_linux-x64_bin.tar.gz +jdk_folder: "{{ jdk_distr_name.split('-')[:2] | join('-') }}" +java_home: "/opt/jdk/{{ jdk_folder }}" +sonarqube_db_name: sonar +sonarqube_db_user: sonar +sonarqube_db_password: sonar diff --git a/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/nexus.yml b/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/nexus.yml new file mode 100644 index 0000000..aef5969 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/nexus.yml @@ -0,0 +1,22 @@ +--- +nexus_user_group: nexus +nexus_user_name: nexus +nexus_directory_data: "/home/{{ nexus_user_name }}/sonatype-work/nexus3" +nexus_directory_home: "/home/{{ nexus_user_name }}/nexus" +nexus_directory_log: "/home/{{ nexus_user_name }}/log" +nexus_directory_package: "/home/{{ nexus_user_name }}/pkg" +nexus_directory_tmp: "/home/{{ nexus_user_name }}/tmp" +nexus_version: 3.14.0-04 +nexus_download_url: https://download.sonatype.com/nexus/3 +nexus_service_enabled: true +nexus_ulimit: 65536 +nexus_context_path: / +nexus_host: 0.0.0.0 +nexus_port: 8081 +nexus_port_check_timeout: 600 +nexus_edition: nexus-oss-edition +nexus_features: nexus-oss-feature +nexus_java_heap_size: 1200M +nexus_java_max_direct_memory: 2G +nexus_service_start_on_boot: true +nexus_configuration_disk_free_space_limit: ~ diff --git a/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/postgres.yml b/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/postgres.yml new file mode 100644 index 0000000..3b41b26 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/postgres.yml @@ -0,0 +1,2 @@ +--- +postgresql_version: 11 diff --git a/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/sonarqube.yml b/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/sonarqube.yml new file mode 100644 index 0000000..6740f28 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/inventory/group_vars/sonarqube.yml @@ -0,0 +1,6 @@ +--- +sonar_version: 9.1.0.47736 +sonar_download_url: "https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-{{ sonar_version }}.zip" +sonar_version_directory: "sonarqube-{{ sonar_version }}" +sonar_db_port: "5432" +sonar_web_context: '' diff --git a/src/homework/09-ci/9.3/infrastructure/inventory/hosts.yml.example b/src/homework/09-ci/9.3/infrastructure/inventory/hosts.yml.example new file mode 100644 index 0000000..d6f0643 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/inventory/hosts.yml.example @@ -0,0 +1,20 @@ +--- +all: + hosts: + sonar-01: + ansible_host: + nexus-01: + ansible_host: + children: + sonarqube: + hosts: + sonar-01: + nexus: + hosts: + nexus-01: + postgres: + hosts: + sonar-01: + vars: + ansible_connection_type: paramiko + ansible_user: diff --git a/src/homework/09-ci/9.3/infrastructure/site.yml b/src/homework/09-ci/9.3/infrastructure/site.yml new file mode 100644 index 0000000..26c1879 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/site.yml @@ -0,0 +1,382 @@ +--- +- name: Get OpenJDK installed + hosts: sonarqube + pre_tasks: + - name: install unzip + become: true + yum: + name: unzip + state: present + tasks: + - name: Upload .tar.gz file conaining binaries from remote storage + get_url: + url: "{{ jdk_url }}" + dest: "/tmp/jdk-{{ jdk_distr_name }}" + mode: 0755 + register: download_java_remote_binaries + until: download_java_remote_binaries is succeeded + + - name: Ensure installation dir exists + become: true + file: + state: directory + path: "{{ java_home }}" + mode: 0755 + + - name: Extract java in the installation directory + become: true + unarchive: + copy: false + src: "/tmp/jdk-{{ jdk_distr_name }}" + dest: "{{ java_home }}" + extra_opts: [--strip-components=1] + creates: "{{ java_home }}/bin/java" + + - name: Export environment variables + become: true + template: + src: jdk.sh.j2 + dest: /etc/profile.d/jdk.sh + owner: root + group: root + mode: 0644 + +- name: Get PostgreSQL installed + hosts: postgres + become: true + tasks: + - name: Change repo file + copy: + src: CentOS-Base.repo + dest: /etc/yum.repos.d/CentOS-Base.repo + mode: 0644 + owner: root + group: root + + - name: Install PostgreSQL repos + yum: + name: https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm + state: present + validate_certs: false + + - name: Install PostgreSQL + yum: + name: "postgresql{{ postgresql_version }}-server" + state: present + + - name: Init template1 DB + command: /usr/pgsql-11/bin/postgresql-11-setup initdb + failed_when: false + + - name: Start pgsql service + systemd: + name: "postgresql-{{ postgresql_version }}" + state: started + enabled: true + + - name: Create user in system + user: + name: "{{ sonarqube_db_user }}" + - name: Create user for Sonar in PostgreSQL + become_user: postgres + command: "createuser -s -e {{ sonarqube_db_user }}" + failed_when: false + + - name: Change password for Sonar user in PostgreSQL + become_user: postgres + command: "psql -c \"ALTER USER sonar WITH ENCRYPTED password '{{ sonarqube_db_password }}';\"" + + - name: Create Sonar DB + become_user: postgres + command: "createdb {{ sonarqube_db_name }}" + failed_when: false + + - name: Copy pg_hba.conf + copy: + src: pg_hba.conf + dest: /var/lib/pgsql/11/data/pg_hba.conf + mode: 0600 + owner: postgres + group: postgres + +- name: Prepare Sonar host + hosts: sonarqube + become: true + tasks: + - name: Create group in system + group: + name: "{{ sonarqube_db_user }}" + state: present + + - name: Create user in system + user: + name: "{{ sonarqube_db_user }}" + group: "{{ sonarqube_db_user }}" + + - name: "Set up ssh key to access for managed node" + authorized_key: + user: "{{ sonarqube_db_user }}" + state: present + key: "{{ lookup('file', 'id_rsa.pub') }}" + + - name: "Allow group to have passwordless sudo" + lineinfile: + dest: /etc/sudoers + state: present + regexp: '^%{{ sonarqube_db_user }}' + line: '%{{ sonarqube_db_user }} ALL=(ALL) NOPASSWD: ALL' + validate: 'visudo -cf %s' + + - name: Increase Virtual Memory + lineinfile: + dest: /etc/sysctl.conf + state: present + regexp: '^vm.max_map_count' + line: 'vm.max_map_count=262144' + - name: Reboot VM + reboot: + +- name: Get Sonarqube installed + hosts: sonarqube + vars: + ansible_user: "{{ sonarqube_db_user }}" + tasks: + - name: Get distrib ZIP + get_url: + url: "{{ sonar_download_url }}" + dest: "/tmp/{{ sonar_version_directory }}.zip" + validate_certs: false + + - name: Unzip Sonar + become: true + unarchive: + src: "/tmp/{{ sonar_version_directory }}.zip" + dest: /usr/local/ + copy: false + owner: "{{ sonarqube_db_user }}" + group: "{{ sonarqube_db_user }}" + creates: /usr/local/sonar/COPYING + + - name: Move Sonar into place. + become: true + copy: + src: /usr/local/{{ sonar_version_directory }}/ + dest: /usr/local/sonar/ + owner: "{{ sonarqube_db_user }}" + group: "{{ sonarqube_db_user }}" + remote_src: true + + - name: Configure SonarQube JDBC settings for PostgreSQL. + lineinfile: + dest: /usr/local/sonar/conf/sonar.properties + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + with_items: + - regexp: "^sonar.jdbc.username" + line: "sonar.jdbc.username={{ sonarqube_db_user }}" + - regexp: "^sonar.jdbc.password" + line: "sonar.jdbc.password={{ sonarqube_db_password }}" + - regexp: "^sonar.jdbc.url" + line: "sonar.jdbc.url=jdbc:postgresql://localhost:{{ sonar_db_port }}/{{ sonarqube_db_name }}?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance" + - regexp: "^sonar.web.context" + line: "sonar.web.context={{ sonar_web_context }}" + + - name: Generate wrapper.conf + template: + src: wrapper.conf.j2 + dest: /usr/local/sonar/conf/wrapper.conf + mode: 0644 + + - name: Symlink sonar bin. + become: true + file: + src: /usr/local/sonar/bin/linux-x86-64/sonar.sh + dest: /usr/bin/sonar + state: link + register: sonar_symlink + + - name: Copy SonarQube systemd unit file into place (for systemd systems). + become: true + template: + src: sonar.unit.j2 + dest: /etc/systemd/system/sonar.service + owner: root + group: root + mode: 0755 + + - name: Ensure Sonar is running and set to start on boot. + become: true + service: + name: sonar + state: restarted + enabled: true + + - name: Allow Sonar time to build on first start. + pause: + seconds: 180 + when: sonar_symlink.changed + tags: ['skip_ansible_lint'] + + - name: Make sure Sonar is responding on the configured port. + wait_for: + port: 9000 + delay: 3 + timeout: 300 +- name: Get Nexus installed + hosts: nexus + pre_tasks: + - name: Create Nexus group + become: true + group: + name: "{{ nexus_user_group }}" + state: present + - name: Create Nexus user + become: true + user: + name: "{{ nexus_user_name }}" + - name: Install JDK + become: true + package: + name: [java-1.8.0-openjdk, java-1.8.0-openjdk-devel] + state: present + tasks: + - name: Create Nexus directories + become: true + file: + group: "{{ nexus_user_group }}" + owner: "{{ nexus_user_name }}" + path: "{{ item }}" + state: directory + with_items: + - "{{ nexus_directory_log }}" + - "{{ nexus_directory_data }}" + - "{{ nexus_directory_data }}/etc" + - "{{ nexus_directory_package }}" + - "{{ nexus_directory_tmp }}" + + - name: Download Nexus + become: true + become_user: "{{ nexus_user_name }}" + get_url: + dest: "{{ nexus_directory_package }}/nexus-{{ nexus_version }}.tar.gz" + url: "{{ nexus_download_url }}/nexus-{{ nexus_version }}-unix.tar.gz" + validate_certs: false + + - name: Unpack Nexus + become: true + become_user: "{{ nexus_user_name }}" + unarchive: + copy: no + creates: "{{ nexus_directory_package }}/nexus-{{ nexus_version }}" + dest: "{{ nexus_directory_package }}" + src: "{{ nexus_directory_package }}/nexus-{{ nexus_version }}.tar.gz" + + - name: Link to Nexus Directory + become: true + become_user: "{{ nexus_user_name }}" + file: + dest: "{{ nexus_directory_home }}" + src: "{{ nexus_directory_package }}/nexus-{{ nexus_version }}" + state: link + + - name: Add NEXUS_HOME for Nexus user + become: true + become_user: "{{ nexus_user_name }}" + lineinfile: + create: yes + dest: "/home/{{ nexus_user_name }}/.bashrc" + insertafter: EOF + line: "export NEXUS_HOME={{ nexus_directory_home }}" + + - name: Add run_as_user to Nexus.rc + become: true + become_user: "{{ nexus_user_name }}" + lineinfile: + create: yes + dest: "{{ nexus_directory_home }}/bin/nexus.rc" + insertafter: EOF + line: "run_as_user=\"{{ nexus_user_name }}\"" + regexp: "^run_as_user" + + - name: Raise nofile limit for Nexus user + become: true + pam_limits: + domain: "{{ nexus_user_name }}" + limit_type: "-" + limit_item: nofile + value: "{{ nexus_ulimit }}" + + - name: Create Nexus service for SystemD + become: true + template: + dest: /lib/systemd/system/nexus.service + mode: 0644 + src: nexus.systemd.j2 + + - name: Ensure Nexus service is enabled for SystemD + become: true + systemd: + daemon_reload: yes + enabled: yes + name: nexus + when: + - nexus_service_enabled + + - name: Create Nexus vmoptions + become: true + become_user: "{{ nexus_user_name }}" + template: + dest: "{{ nexus_directory_home }}/bin/nexus.vmoptions" + src: nexus.vmoptions.j2 + register: nexus_config_changed + + - name: Create Nexus properties + become: true + become_user: "{{ nexus_user_name }}" + template: + dest: "{{ nexus_directory_data }}/etc/nexus.properties" + src: nexus.properties.j2 + register: nexus_config_changed + + - name: Lower Nexus disk space threshold + become: true + become_user: "{{ nexus_user_name }}" + lineinfile: + backrefs: yes + dest: "{{ nexus_directory_home }}/etc/karaf/system.properties" + insertafter: EOF + line: "storage.diskCache.diskFreeSpaceLimit={{ nexus_configuration_disk_free_space_limit }}" + regexp: ^storage\.diskCache\.diskFreeSpaceLimit + when: nexus_configuration_disk_free_space_limit is not none + register: nexus_config_changed + + - name: Start Nexus service if enabled + become: true + service: + enabled: yes + name: nexus + state: started + when: + - nexus_service_start_on_boot + - not nexus_config_changed.changed + tags: + - skip_ansible_lint + + - name: Ensure Nexus service is restarted + become: true + service: + name: nexus + state: restarted + when: + - nexus_service_start_on_boot + - nexus_config_changed.changed + tags: + - skip_ansible_lint + + - name: Wait for Nexus port if started + wait_for: + port: "{{ nexus_port }}" + state: started + timeout: "{{ nexus_port_check_timeout }}" + when: + - nexus_service_start_on_boot diff --git a/src/homework/09-ci/9.3/infrastructure/templates/jdk.sh.j2 b/src/homework/09-ci/9.3/infrastructure/templates/jdk.sh.j2 new file mode 100644 index 0000000..d04385d --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/templates/jdk.sh.j2 @@ -0,0 +1,5 @@ +# Warning: This file is Ansible Managed, manual changes will be overwritten on next playbook run. +#!/usr/bin/env bash + +export JAVA_HOME={{ java_home }} +export PATH=$PATH:$JAVA_HOME/bin diff --git a/src/homework/09-ci/9.3/infrastructure/templates/nexus.properties.j2 b/src/homework/09-ci/9.3/infrastructure/templates/nexus.properties.j2 new file mode 100644 index 0000000..2b95258 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/templates/nexus.properties.j2 @@ -0,0 +1,12 @@ +# +# + +# Jetty section +application-host={{ nexus_host }} +application-port={{ nexus_port }} +nexus-context-path={{ nexus_context_path }} + +# Nexus section +nexus-edition={{ nexus_edition }} +nexus-features=\ + {{ nexus_features }} diff --git a/src/homework/09-ci/9.3/infrastructure/templates/nexus.systemd.j2 b/src/homework/09-ci/9.3/infrastructure/templates/nexus.systemd.j2 new file mode 100644 index 0000000..1483c14 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/templates/nexus.systemd.j2 @@ -0,0 +1,15 @@ +[Unit] +Description=nexus service +After=network.target + +[Service] +Type=forking +User={{ nexus_user_name }} +Group={{ nexus_user_group }} +LimitNOFILE={{ nexus_ulimit }} +ExecStart={{ nexus_directory_home }}/bin/nexus start +ExecStop={{ nexus_directory_home }}/bin/nexus stop +Restart=on-abort + +[Install] +WantedBy=multi-user.target diff --git a/src/homework/09-ci/9.3/infrastructure/templates/nexus.vmoptions.j2 b/src/homework/09-ci/9.3/infrastructure/templates/nexus.vmoptions.j2 new file mode 100644 index 0000000..d3efba3 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/templates/nexus.vmoptions.j2 @@ -0,0 +1,16 @@ +-Xms{{ nexus_java_heap_size }} +-Xmx{{ nexus_java_heap_size }} +-XX:MaxDirectMemorySize={{ nexus_java_max_direct_memory }} +-XX:+UnlockDiagnosticVMOptions +-XX:+UnsyncloadClass +-XX:+LogVMOutput +-XX:LogFile={{ nexus_directory_log }}/jvm.log +-XX:-OmitStackTraceInFastThrow +-Djava.net.preferIPv4Stack=true +-Dkaraf.home=. +-Dkaraf.base=. +-Dkaraf.etc=etc/karaf +-Djava.util.logging.config.file=etc/karaf/java.util.logging.properties +-Dkaraf.data={{ nexus_directory_data }} +-Djava.io.tmpdir={{ nexus_directory_tmp }} +-Dkaraf.startLocalConsole=false diff --git a/src/homework/09-ci/9.3/infrastructure/templates/sonar.unit.j2 b/src/homework/09-ci/9.3/infrastructure/templates/sonar.unit.j2 new file mode 100644 index 0000000..fb48c80 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/templates/sonar.unit.j2 @@ -0,0 +1,22 @@ +[Unit] +Description=SonarQube +After=network.target network-online.target +Wants=network-online.target + +[Service] +LimitNOFILE=131072 +LimitNPROC=8192 +User={{ sonarqube_db_user }} +Group={{ sonarqube_db_user }} +ExecStart=/usr/bin/sonar start +ExecStop=/usr/bin/sonar stop +ExecReload=/usr/bin/sonar restart +PIDFile=/usr/local/sonar/bin/linux-x86-64/./SonarQube.pid +Type=simple +PermissionsStartOnly=true +TimeoutStartSec=5 +Restart=always +SuccessExitStatus=143 + +[Install] +WantedBy=multi-user.target diff --git a/src/homework/09-ci/9.3/infrastructure/templates/wrapper.conf.j2 b/src/homework/09-ci/9.3/infrastructure/templates/wrapper.conf.j2 new file mode 100644 index 0000000..bb271c1 --- /dev/null +++ b/src/homework/09-ci/9.3/infrastructure/templates/wrapper.conf.j2 @@ -0,0 +1,98 @@ +# Path to JVM executable. By default it must be available in PATH. +# Can be an absolute path, for example: +wrapper.java.command={{ java_home }}/bin/java + + +# +# DO NOT EDIT THE FOLLOWING SECTIONS +# + + +#******************************************************************** +# Wrapper Java +#******************************************************************** +wrapper.java.additional.1=-Dsonar.wrapped=true +wrapper.java.additional.2=-Djava.awt.headless=true +# extra args needed by hazelcast +wrapper.java.additional.3=--add-exports=java.base/jdk.internal.ref=ALL-UNNAMED +wrapper.java.additional.4=--add-opens=java.base/java.lang=ALL-UNNAMED +wrapper.java.additional.5=--add-opens=java.base/java.nio=ALL-UNNAMED +wrapper.java.additional.6=--add-opens=java.base/sun.nio.ch=ALL-UNNAMED +wrapper.java.additional.7=--add-opens=java.management/sun.management=ALL-UNNAMED +wrapper.java.additional.8=--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED + +wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp +wrapper.java.classpath.1=../../lib/sonar-application-9.1.0.47736.jar +wrapper.java.classpath.2=../../lib/jsw/wrapper-3.2.3.jar +wrapper.java.classpath.3=../../lib/sonar-shutdowner-9.1.0.47736.jar +wrapper.java.library.path.1=./lib +wrapper.app.parameter.1=org.sonar.application.App +wrapper.java.initmemory=8 +wrapper.java.maxmemory=32 + +#******************************************************************** +# Wrapper Logs +#******************************************************************** + +wrapper.console.format=PM +wrapper.console.loglevel=INFO +wrapper.logfile.format=M +wrapper.logfile.loglevel=INFO +wrapper.logfile.rollmode=DATE +wrapper.logfile=../../logs/sonar.YYYYMMDD.log + +# Maximum size that the log file will be allowed to grow to before +# the log is rolled. Size is specified in bytes. The default value +# of 0, disables log rolling. May abbreviate with the 'k' (kb) or +# 'm' (mb) suffix. For example: 10m = 10 megabytes. +#wrapper.logfile.maxsize=0 + +# Maximum number of rolled log files which will be allowed before old +# files are deleted. The default value of 0 implies no limit. +wrapper.logfile.maxfiles=7 + +# Log Level for sys/event log output. (See docs for log levels) +wrapper.syslog.loglevel=NONE + +#******************************************************************** +# Wrapper Windows Properties +#******************************************************************** +# Title to use when running as a console +wrapper.console.title=SonarQube + +# Disallow start of multiple instances of an application at the same time on Windows +wrapper.single_invocation=true + +#******************************************************************** +# Wrapper Windows NT/2000/XP Service Properties +#******************************************************************** +# WARNING - Do not modify any of these properties when an application +# using this configuration file has been installed as a service. +# Please uninstall the service before modifying this section. The +# service can then be reinstalled. + +# Name of the service +wrapper.ntservice.name=SonarQube + +# Display name of the service +wrapper.ntservice.displayname=SonarQube + +# Description of the service +wrapper.ntservice.description=SonarQube + +# Service dependencies. Add dependencies as needed starting from 1 +wrapper.ntservice.dependency.1= + +# Mode in which the service is installed. AUTO_START or DEMAND_START +wrapper.ntservice.starttype=AUTO_START + +# Allow the service to interact with the desktop. +wrapper.ntservice.interactive=false + +#******************************************************************** +# Forking Properties +#******************************************************************** +wrapper.disable_restarts=TRUE +wrapper.ping.timeout=0 +wrapper.shutdown.timeout=0 +wrapper.jvm_exit.timeout=0 diff --git a/src/homework/09-ci/9.3/mvn/.gitignore b/src/homework/09-ci/9.3/mvn/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/src/homework/09-ci/9.3/mvn/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/src/homework/09-ci/9.3/mvn/pom.xml b/src/homework/09-ci/9.3/mvn/pom.xml new file mode 100644 index 0000000..57640c2 --- /dev/null +++ b/src/homework/09-ci/9.3/mvn/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + com.netology.app + simple-app + 1.0-SNAPSHOT + + + my-repo + maven-releases + http://localhost:8081/repository/maven-releases/ + + + + + netology + java + 8_282 + distrib + tar.gz + + + diff --git a/src/homework/09-ci/9.3/readme.md b/src/homework/09-ci/9.3/readme.md new file mode 100644 index 0000000..5ef8cbc --- /dev/null +++ b/src/homework/09-ci/9.3/readme.md @@ -0,0 +1,240 @@ +Выполнение [домашнего задания](https://github.com/netology-code/mnt-homeworks/blob/MNT-13/09-ci-03-cicd/README.md) +по теме "9.3. CI\CD". + +## Q/A + +### Задание 1 + +> Подготовка к выполнению +> 1. Создаём 2 VM в yandex cloud со следующими параметрами: 2CPU 4RAM Centos7(остальное по минимальным требованиям) +> 2. Прописываем в [inventory](./infrastructure/inventory/hosts.yml) [playbook'a](./infrastructure/site.yml) созданные хосты +> 3. Добавляем в [files](./infrastructure/files/) файл со своим публичным ключом (id_rsa.pub). Если ключ называется иначе - найдите таску в плейбуке, которая использует id_rsa.pub имя и исправьте на своё +> 4. Запускаем playbook, ожидаем успешного завершения + +```shell +ansible-playbook -i inventory/hosts.yml site.yml +``` + + +```text +<...> +PLAY RECAP ***************************************************************************************************************** +nexus-01 : ok=17 changed=15 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 +sonar-01 : ok=35 changed=27 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +> 5. Проверяем готовность Sonarqube через [браузер](http://localhost:9000) +> 6. Заходим под admin\admin, меняем пароль на свой + +![sonar_main](./img/sonar_main.png) + +> 7. Проверяем готовность Nexus через [бразуер](http://localhost:8081) +> 8. Подключаемся под admin\admin123, меняем пароль, сохраняем анонимный доступ + +![sonar_main](./img/nexus_main.png) + +### Задание 2 + +> Знакомство с SonarQube + +> 1. Создаём новый проект, название произвольное +> 2. Скачиваем пакет sonar-scanner, который нам предлагает скачать сам sonarqube + +Для скачивания пакета актуальной версии на текущий момент: + +```shell +curl https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.7.0.2747-linux.zip -o sonar-scanner-cli-4.7.0.2747-linux.zip +``` + +Затем нужно распаковать архив в любую директорию: + +```shell +unzip sonar-scanner-cli-4.7.0.2747-linux.zip -d ~/.local/share/ +``` + +Внутри распакованной директории будет находиться директория `bin`, которую и нужно добавить в `$PATH`. + +> 3. Делаем так, чтобы binary был доступен через вызов в shell (или меняем переменную PATH или любой другой удобный вам способ) +> 4. Проверяем `sonar-scanner --version` + +```shell +sonar-scanner --version +``` + +```text +INFO: Scanner configuration file: ~/.local/share/sonar-scanner/conf/sonar-scanner.properties +INFO: Project root configuration file: NONE +INFO: SonarScanner 4.7.0.2747 +INFO: Java 11.0.14.1 Eclipse Adoptium (64-bit) +INFO: Linux 5.10.102.1-microsoft-standard-WSL2 amd64 +``` + +> 5. Запускаем анализатор против кода из директории [example](./example) с дополнительным ключом `-Dsonar.coverage.exclusions=fail.py` + +```shell +sonar-scanner \ + -Dsonar.projectKey=sao \ + -Dsonar.sources=. \ + -Dsonar.host.url=http://:9000 \ + -Dsonar.login= \ + -Dsonar.coverage.exclusions=fail.py +``` + +```text +<...> +INFO: ------------------------------------------------------------------------ +INFO: EXECUTION SUCCESS +INFO: ------------------------------------------------------------------------ +INFO: Total time: 34.848s +INFO: Final Memory: 8M/37M +INFO: ------------------------------------------------------------------------ +``` + +> 6. Смотрим результат в интерфейсе + +![sonar_project_analysis](./img/sonar_project_analysis.png) + +> 7. Исправляем ошибки, которые он выявил(включая warnings) + +Исправляем функцию, чтобы она выглядела следующим образом: + +```python +def increment(index): + newIndex = index+1 + return newIndex +``` + +И убираем из функции `print_numb` конструкцию `pass`. + +> 8. Запускаем анализатор повторно - проверяем, что QG пройдены успешно +> 9. Делаем скриншот успешного прохождения анализа, прикладываем к решению ДЗ + +![sonar_project_analysis_fix](./img/sonar_project_analysis_fix.png) + +### Задание 3 + +> Знакомство с Nexus +> 1. В репозиторий `maven-releases` загружаем артефакт с GAV параметрами: +> 1. groupId: netology +> 2. artifactId: java +> 3. version: 8_282 +> 4. classifier: distrib +> 5. type: tar.gz + +![nexus_maven_upload](./img/nexus_maven_upload.png) + +> 2. В него же загружаем такой же артефакт, но с version: 8_102 +> 3. Проверяем, что все файлы загрузились успешно + +![nexus_maven_upload_success](./img/nexus_maven_upload_success.png) + +> 4. В ответе присылаем файл `maven-metadata.xml` для этого артефекта + +```xml + + netology + java + + 8_282 + 8_282 + + 8_102 + 8_282 + + 20220824033600 + + +``` + +### Задание 4 + +> Знакомство с Maven +> +> Подготовка к выполнению +> 1. Скачиваем дистрибутив с [maven](https://maven.apache.org/download.cgi) +> 2. Разархивируем, делаем так, чтобы binary был доступен через вызов в shell (или меняем переменную PATH или любой другой удобный вам способ) + +Делать нужно по аналогии с `sonar-scanner` из [Задания 2](#задание-2) + +> 3. Удаляем из `apache-maven-/conf/settings.xml` упоминание о правиле, отвергающем http соединение( раздел `mirrors->id`: `my-repository-http-blocker`) +> 4. Проверяем `mvn --version` + +```shell +mvn --version +``` + +```text +Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63) +Maven home: ~/downloads/apache-maven-3.8.6 +Java version: 11.0.16, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64 +Default locale: en, platform encoding: UTF-8 +OS name: "linux", version: "5.10.102.1-microsoft-standard-wsl2", arch: "amd64", family: "unix" +``` + +> 5. Забираем директорию [mvn](./mvn) с pom + +> Основная часть +> 1. Меняем в `pom.xml` блок с зависимостями под наш артефакт из первого пункта задания для Nexus (java с версией 8_282) +> 2. Запускаем команду `mvn package` в директории с `pom.xml`, ожидаем успешного окончания + +```shell +mvn package +``` + +```text +[INFO] Building jar: ./mvn/target/simple-app-1.0-SNAPSHOT.jar +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 29.857 s +[INFO] Finished at: 2022-08-24T10:51:41+07:00 +[INFO] ------------------------------------------------------------------------ +``` + +> 3. Проверяем директорию `~/.m2/repository/`, находим наш артефакт + +```shell +ls -la ~/.m2/repository/netology/java/8_282 +``` + +```text +total 24 +drwxr-xr-x 2 dannc dannc 4096 Aug 24 10:51 . +drwxr-xr-x 3 dannc dannc 4096 Aug 24 10:51 .. +-rw-r--r-- 1 dannc dannc 176 Aug 24 10:51 _remote.repositories +-rw-r--r-- 1 dannc dannc 258 Aug 24 10:51 java-8_282-distrib.tar.gz +-rw-r--r-- 1 dannc dannc 40 Aug 24 10:51 java-8_282-distrib.tar.gz.sha1 +-rw-r--r-- 1 dannc dannc 397 Aug 24 10:51 java-8_282.pom.lastUpdated +``` + +> 4. В ответе присылаем исправленный файл `pom.xml` + +```xml + + 4.0.0 + + com.netology.app + simple-app + 1.0-SNAPSHOT + + + my-repo + maven-releases + http://nexus-01:8081/repository/maven-releases/ + + + + + netology + java + 8_282 + distrib + tar.gz + + + +```