From 335ca9c71ee50600a6116f6678700e095629ba72 Mon Sep 17 00:00:00 2001 From: Gildas Fargeas Date: Fri, 21 Feb 2025 16:54:41 +0900 Subject: [PATCH] initial commit --- .gitignore | 1 + NERD_Debian_Exercise.pkr.hcl | 149 ++++++++++++++++++ README.md | 132 ++++++++++++++++ http/preseed.cfg | 47 ++++++ puppet/Puppetfile | 8 + puppet/modules/nerd/templates/daemon.json.erb | 13 ++ .../templates/jenkins/Dockerfile.agent.erb | 4 + .../templates/jenkins/Dockerfile.server.erb | 6 + .../templates/jenkins/docker-compose.yml.erb | 49 ++++++ .../nerd/templates/jenkins/plugins.txt | 115 ++++++++++++++ puppet/site.pp | 129 +++++++++++++++ scripts/bootstrap.sh | 6 + 12 files changed, 659 insertions(+) create mode 100644 .gitignore create mode 100644 NERD_Debian_Exercise.pkr.hcl create mode 100644 README.md create mode 100644 http/preseed.cfg create mode 100644 puppet/Puppetfile create mode 100644 puppet/modules/nerd/templates/daemon.json.erb create mode 100644 puppet/modules/nerd/templates/jenkins/Dockerfile.agent.erb create mode 100644 puppet/modules/nerd/templates/jenkins/Dockerfile.server.erb create mode 100644 puppet/modules/nerd/templates/jenkins/docker-compose.yml.erb create mode 100644 puppet/modules/nerd/templates/jenkins/plugins.txt create mode 100644 puppet/site.pp create mode 100755 scripts/bootstrap.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d874ad6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.tar diff --git a/NERD_Debian_Exercise.pkr.hcl b/NERD_Debian_Exercise.pkr.hcl new file mode 100644 index 0000000..a478138 --- /dev/null +++ b/NERD_Debian_Exercise.pkr.hcl @@ -0,0 +1,149 @@ +# file: NERD_Debian_Exercise.pkr.hcl + +packer { + required_plugins { + vmware = { + version = ">= 1.1.0" + source = "github.com/hashicorp/vmware" + } + virtualbox = { + version = ">= 1.1.1" + source = "github.com/hashicorp/virtualbox" + } + qemu = { + version = ">= 1.1.1" + source = "github.com/hashicorp/qemu" + } + } +} + +variable "no_proxy" { + type = string + default = "${env("no_proxy")}" +} + +locals { + name = "NERD-Debian-Exercise" + version = "TIMESTAMP" + build_directory = "build" + boot_command = ["install preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg debian-installer=en_US.UTF-8 auto locale=en_US.UTF-8 kbd-chooser/method=us keyboard-configuration/xkb-keymap=us netcfg/get_hostname={{ .Name }} netcfg/get_domain=solve.me fb=false debconf/frontend=noninteractive console-setup/ask_detect=false console-keymaps-at/keymap=us grub-installer/bootdev=default "] + build_timestamp = "timestamp()" + http_directory = "${path.root}/http" + ssh_user = "nerd" + ssh_password = "dvop2025" + cpus = "4" + disk_size = "16384" + memory = "1024" + iso_checksum = "04396d12b0f377958a070c38a923c227832fa3b3e18ddc013936ecf492e9fbb3" + iso_name = "debian-12.8.0-amd64-netinst.iso" + mirror = "http://cdimage.debian.org/cdimage/archive" + mirror_directory = "12.8.0/amd64/iso-cd" +} + +source "virtualbox-iso" "primary" { + boot_command = "${local.boot_command}" + boot_wait = "5s" + cpus = "${local.cpus}" + disk_size = "${local.disk_size}" + guest_additions_path = "VBoxGuestAdditions_{{ .Version }}.iso" + guest_additions_url = "" + guest_os_type = "Debian_64" + hard_drive_interface = "sata" + http_directory = "${local.http_directory}" + iso_checksum = "${local.iso_checksum}" + iso_url = "${local.mirror}/${local.mirror_directory}/${local.iso_name}" + memory = "${local.memory}" + output_directory = "${local.build_directory}/packer-${local.name}-virtualbox" + ssh_password = "${local.ssh_password}" + ssh_port = 22 + ssh_timeout = "10000s" + ssh_username = "${local.ssh_user}" + virtualbox_version_file = ".vbox_version" + vm_name = "${local.name}" +} + +source "vmware-iso" "primary" { + boot_command = "${local.boot_command}" + boot_wait = "5s" + cpus = "${local.cpus}" + disk_size = "${local.disk_size}" + guest_os_type = "debian12-64" + http_directory = "${local.http_directory}" + iso_checksum = "${local.iso_checksum}" + iso_url = "${local.mirror}/${local.mirror_directory}/${local.iso_name}" + memory = "${local.memory}" + output_directory = "${local.build_directory}/packer-${local.name}-vmware" + ssh_password = "${local.ssh_password}" + ssh_port = 22 + ssh_timeout = "10000s" + ssh_username = "${local.ssh_user}" + vm_name = "${local.name}" +} + +source "qemu" "primary" { + # This source was not tested. + iso_url = "${local.mirror}/${local.mirror_directory}/${local.iso_name}" + iso_checksum = "${local.iso_checksum}" + output_directory = "${local.build_directory}/packer-${local.name}-qemu" + disk_size = "${local.disk_size}" + cpus = "${local.cpus}" + memory = "${local.memory}" + format = "qcow2" + # accelerator = "kvm" + http_directory = "${local.http_directory}" + ssh_username = "${local.ssh_user}" + ssh_password = "${local.ssh_password}" + ssh_timeout = "10000s" + vm_name = "${local.name}" + net_device = "virtio-net" + disk_interface = "virtio" + boot_wait = "5s" + boot_command = "${local.boot_command}" + use_default_display = true +} + +source "null" "local" { + communicator = "none" +} +source "null" "wsl" { + communicator = "none" +} + +build { + sources = ["source.virtualbox-iso.primary", "source.vmware-iso.primary", "source.qemu.primary", "source.null.local", "source.null.wsl"] + provisioner "file" { + only = ["virtualbox-iso.primary", "vmware-iso.primary", "qemu.primary"] + source = "${path.root}/scripts/bootstrap.sh" + destination = "/home/${local.ssh_user}/bootstrap.sh" + } + provisioner "shell" { + only = ["virtualbox-iso.primary", "vmware-iso.primary", "qemu.primary"] + inline = [ + "echo '${local.ssh_password}' | sudo -S -E bash -x /home/${local.ssh_user}/bootstrap.sh ${source.name} ${source.type} /etc/facter/facts.d/nerd_packer.json" + ] + } + provisioner "shell-local" { + only = ["null.local", "null.wsl"] + inline = [ + "sudo bash -xc './scripts/bootstrap.sh ${source.name} ${source.type} /etc/facter/facts.d/nerd_packer.json'" + ] + } + provisioner "file" { + only = ["virtualbox-iso.primary", "vmware-iso.primary", "qemu.primary"] + source = "${path.root}/puppet" + destination = "/home/${local.ssh_user}/" + } + provisioner "shell" { + only = ["virtualbox-iso.primary", "vmware-iso.primary", "qemu.primary"] + inline = [ + "echo '${local.ssh_password}' | sudo -S -E bash -xc 'r10k puppetfile install --puppetfile=/home/${local.ssh_user}/puppet/Puppetfile --moduledir=/home/${local.ssh_user}/puppet/modules; puppet apply /home/${local.ssh_user}/puppet/site.pp --modulepath /home/${local.ssh_user}/puppet/modules; puppet apply /home/${local.ssh_user}/puppet/site.pp --modulepath /home/${local.ssh_user}/puppet/modules'" + ] + } + provisioner "shell-local" { + only = ["null.local", "null.wsl"] + inline = [ + "sudo -S -E bash -xc 'r10k puppetfile install --puppetfile=puppet/Puppetfile --moduledir=puppet/modules; puppet apply puppet/site.pp --modulepath puppet/modules; puppet apply puppet/site.pp --modulepath puppet/modules'" + ] + } +} + diff --git a/README.md b/README.md new file mode 100644 index 0000000..9187048 --- /dev/null +++ b/README.md @@ -0,0 +1,132 @@ +# NERD PSDVOP2025 Exercise + +## Context + +As a NERD DevOps engineer, you are asked by a fellow developer to help restore the behavior of a **Continuous Integration Service** that was building and testing a C++ project **`around early 2019`**. \ +The goal is to ensure the job could run again in similar conditions. + +The service you will be investigating is a fresh Jenkins instance containing a job that was imported from a backup. + +Unfortunately, when a fresh instance of Jenkins with the plugins list updated, the project's job that was imported from a backup of the original Jenkins instance could not be run out-of-the box... + +The exercise consists of the following steps: + +* build a virtual machine with the given [instructions](#building-the-virtual-machine). +* launch the VM, access the mentioned service, observe and explore... +* and solve the [questions](#questions)! + +Consider each of those steps has part of the exercise. Some steps have not been detailed extensively *on purpose*. + +To avoid installing too many required components on your environment, the service is bundled inside a VM that you'll have to build and run yourself. +_This will take about 10min depending on your settings (you can also [skip the VM part and provision the exercise locally](#provision-the-exercise-locally))_ + +## Software Requirements + +The following software requirements have been selected to ensure a minimal residual footprint on your system: + +* [Hashicorp packer](https://www.packer.io/) +* One of these hypervisors: + * [Oracle VM Virtualbox](https://www.virtualbox.org/) + * [VMware Workstation Pro](https://www.vmware.com/products/desktop-hypervisor/workstation-and-fusion#product-overview) + +This exercise was built on the following recommended configurations and validated (with exceptions in *italic*): + +Debian Linux (sid/trixie 2025-02) | Microsoft Windows 11 23H2 +------------------------------------|------------------------------ + Hashicorp Packer 1.11.2 | Hashicorp Packer 1.11.2 + Oracle VM VirtualBox 7.0.20 | Oracle VM VirtualBox 7.1.6 + VMware Workstation 17.6.2 | *VMWare was **not tested** but should work oob* + *n/a* | Local provisionning on WLS2 Debian 12 + *QEMU was **not tested*** | *QEMU was **not tested*** + +## Architecture + +Here are some pieces of information you need to get the service built and running: + +* you're given a **Packer** manifest and files that will build a ready-to-use VM (see below section [Building The Virtual Machine](#building-the-virtual-machine)) + + * the VM can be connected to with an SSH client + * the VM exposes a **Jenkins** Server on its port 80 + * the VM is provisionned using a mix of **Packer** hcl2 directives and [Puppet](#details-about-the-provisioning-mechanism) manifest + +* the service running inside the VM consists of 3 **Docker** containers: + * a proxy server based on Nginx with a pretty minimal configuration that runs oob on the port 80 of the VM. + * a **Jenkins** server used to orchestrate the build and test of the project source code + * you've been told that the generated test binary might not run perfectly. + * a **Jenkins** agent used to build and run the project that connects automatically to the **Jenkins** Server. + +## Building The Virtual Machine + +Depending on the hypervisor you selected (VirtualBox or VMWare, no need to build both), use the appropriate build source for your packer build command : + +``` +packer build -only="SOURCE_TYPE.SOURCE_NAME" NERD_Debian_Exercise.pkr.hcl +``` + +This will build a VM in the `build` directory that you will be able to import and run in your selected hypervisor. + +### Note about Packer and Firewall configuration + +Packer spawns a HTTP server to be able to serve the preseed file to the **Debian** VM. Keep this in mind as Firewall rules on your **Windows** or **Linux** system might block this feature. + +### Note about Packer and VMware Workstation on Windows + +Packer seems to have an issue with VMware network configuration detection leading to an early failure.\ +This looks like Packer requires the presence of the `netmap.conf` to proceed and potentially, your VMware Workstation installation folder may not contain it. \ +Regenerating it is not that hard as you just have to go to `Edit` -> `Virtual Network Editor` -> `Change Settings` and just click `OK`. \ +This appears to do the trick for Packer. + +### Details about the provisioning mechanism + +Even if packer is provisoning components, the system is mainly provisioned using a **Puppet** manifest and modules that are deployed and called within the Packer build step. \ +If you are comfortable with the matter of provisioning, you'll find all the **Puppet** manifest code in the _puppet_ directory. + +## Provision the exercise locally + +**DISCLAIMER: This approach alters the software/user environment of the guest running packer.** + +If you already have a dedicated testbed running a Debian-based Linux (chroot, wsl, aws, rancher, qemu...), you can skip the VM building part, install only Packer and only provision Packer using the following command line + +``` +packer build -only="null.local" NERD_Debian_Exercise.pkr.hcl +# or if you run in a WSL2 vanilla environment (Docker must not run on the host though) +packer build -only="null.wsl" NERD_Debian_Exercise.pkr.hcl +``` + +Keep in mind that the process will install some packages and will try and start a Docker daemon so if you are on WSL2 on Windows, this may interfere with your local Docker Daemon (managing the Docker service might need some tweaking in the puppet manifest as well). + +## Questions + +1. When is the last time the `test_app` job ran ? + +_Give the full date_ + +2. When building the job again, can you describe and explain what is going differently than the previous run ? + +_Explain in a few lines_ + +3. Now that you have assessed the situation, make the necessary modifications to make sure the Job environment and/or Job executable behaves in the same manner as it was before. + +_Explain in a few lines the steps you took and provide a package (git repository / patch files) containing your modifications and a note explaining your changes._ + +4. Describe another solution to make the Job environment and/or Job executable behave in the same manner as it was before. + +_Explain in a few lines and compare it against your first solution._ + +5. Now that everything is running as expected, it is time to suggest a production rollout for this service. Please suggest changes to the service to ensure a secure, production-ready deployment to be accessed by a team of developers. The suggestions are not limited in scope, but should focus on security, performance and reliability. + +_Explain in a few lines._ + +### Notes + +* For questions 3 and 4, **there is more than one way to get things done** and what's important here is for you to make sure your decisions are **explained** and **justified**. +* Your goal is to provide the components that will ensure the service runs in the best conditions. +* Changes should be documented as commits in the provided git repository (in the `puppet` directory) and delivered as the repository itself or patches; providing a VM, docker layer or a link to prebuilt containers should not be necessary. +* Consider keeping the puppet modules `archive`, `docker` and `stdlib` as-is as these are commonly found modules but there should be no need to modify them (except for update if deemed necesssary) +* **Puppet** module `nerd` content can be changed to suit changes in the deployed software environment. This includes but is not limited to: + * Dockerfile templates, compose files + * source code files +* Note that the Jenkins server instance Dockerfile template was succesfully bumped beforehand and runs a more recent version than the original one. The nginx and agent Dockerfile templates _were not modified since 2019_ and started without any issue. + * The Jenkins server configuration can also be modified to suit your recommendations; Don't forget to provide us the patches/changes. + +[[Back to top]](#nerd-psdvop2025-exercise) diff --git a/http/preseed.cfg b/http/preseed.cfg new file mode 100644 index 0000000..f0bb5bc --- /dev/null +++ b/http/preseed.cfg @@ -0,0 +1,47 @@ +choose-mirror-bin mirror/http/proxy string +d-i apt-setup/use_mirror boolean true +d-i base-installer/kernel/override-image string linux-server +d-i clock-setup/utc boolean true +d-i clock-setup/utc-auto boolean true +d-i finish-install/reboot_in_progress note +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean true +d-i keymap select en +d-i mirror/country string manual +d-i mirror/http/directory string /debian +d-i mirror/http/hostname string httpredir.debian.org +d-i mirror/http/proxy string +d-i partman-auto-lvm/guided_size string max +d-i partman-auto/choose_recipe select atomic +d-i partman-auto/method string lvm +d-i partman-lvm/confirm boolean true +d-i partman-lvm/confirm_nooverwrite boolean true +d-i partman-lvm/device_remove_lvm boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +d-i partman/confirm_write_new_label boolean true +d-i passwd/root-login boolean false +d-i passwd/root-password-again password dvop2025 +d-i passwd/root-password password dvop2025 +d-i passwd/user-fullname string Nerd Exercise User +d-i passwd/user-uid string 1000 +d-i passwd/user-password password dvop2025 +d-i passwd/user-password-again password dvop2025 +d-i passwd/username string nerd +d-i pkgsel/include string sudo bzip2 acpid cryptsetup zlib1g-dev wget curl dkms fuse make nfs-common net-tools cifs-utils rsync +d-i pkgsel/install-language-support boolean false +d-i pkgsel/update-policy select none +d-i pkgsel/upgrade select none +# Prevent packaged version of VirtualBox Guest Additions being installed: +d-i preseed/early_command string sed -i \ + '/in-target/idiscover(){/sbin/discover|grep -v VirtualBox;}' \ + /usr/lib/pre-pkgsel.d/20install-hwpackages +d-i time/zone string UTC +d-i user-setup/allow-password-weak boolean true +d-i user-setup/encrypt-home boolean false +d-i preseed/late_command string sed -i '/^deb cdrom:/s/^/#/' /target/etc/apt/sources.list +apt-cdrom-setup apt-setup/cdrom/set-first boolean false +apt-mirror-setup apt-setup/use_mirror boolean true +popularity-contest popularity-contest/participate boolean false +tasksel tasksel/first multiselect standard, ssh-server \ No newline at end of file diff --git a/puppet/Puppetfile b/puppet/Puppetfile new file mode 100644 index 0000000..3e10d0f --- /dev/null +++ b/puppet/Puppetfile @@ -0,0 +1,8 @@ +forge 'forge.puppetlabs.com' +mod 'puppetlabs-stdlib', '9.7.0' +mod 'puppetlabs-docker', '10.1.0' +mod 'puppetlabs-apt', '9.4.0' +mod 'puppetlabs-powershell', '6.0.2' +mod 'puppetlabs-reboot', '5.1.0' +mod 'puppet-archive', '7.1.0' +mod 'nerd', :local => true diff --git a/puppet/modules/nerd/templates/daemon.json.erb b/puppet/modules/nerd/templates/daemon.json.erb new file mode 100644 index 0000000..de97505 --- /dev/null +++ b/puppet/modules/nerd/templates/daemon.json.erb @@ -0,0 +1,13 @@ +{ + <%= @docker_config_host %> + "log-driver": "json-file", + "log-opts": { + "max-size": "10m", + "max-file": "3" + }, + "userland-proxy": false, + "default-address-pools": [{ + "base": "172.16.0.0/16", + "size": 26 + }] +} diff --git a/puppet/modules/nerd/templates/jenkins/Dockerfile.agent.erb b/puppet/modules/nerd/templates/jenkins/Dockerfile.agent.erb new file mode 100644 index 0000000..afcbd1d --- /dev/null +++ b/puppet/modules/nerd/templates/jenkins/Dockerfile.agent.erb @@ -0,0 +1,4 @@ +FROM jenkins/agent:latest +USER root +RUN apt update && apt install -y curl cmake build-essential +USER jenkins \ No newline at end of file diff --git a/puppet/modules/nerd/templates/jenkins/Dockerfile.server.erb b/puppet/modules/nerd/templates/jenkins/Dockerfile.server.erb new file mode 100644 index 0000000..71c80e7 --- /dev/null +++ b/puppet/modules/nerd/templates/jenkins/Dockerfile.server.erb @@ -0,0 +1,6 @@ +FROM jenkins/jenkins:2.479.3-lts +USER jenkins +ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false +COPY --chown=jenkins:jenkins plugins.txt /usr/share/jenkins/ref/plugins.txt +RUN jenkins-plugin-cli -f /usr/share/jenkins/ref/plugins.txt --latest false + diff --git a/puppet/modules/nerd/templates/jenkins/docker-compose.yml.erb b/puppet/modules/nerd/templates/jenkins/docker-compose.yml.erb new file mode 100644 index 0000000..491ee36 --- /dev/null +++ b/puppet/modules/nerd/templates/jenkins/docker-compose.yml.erb @@ -0,0 +1,49 @@ +version: "3.5" +networks: + default: + internal: false + ipam: + config: + - subnet: 172.16.10.0/26 +services: + nginx: + image: nginx:alpine + ports: + - 80:80 + volumes: + - /srv/docker/proxy/nginx-conf:/etc/nginx/conf.d:ro + - /srv/docker/proxy/nginx-logs:/var/log/nginx + restart: always + jenkins_server: + build: ../jenkins_server + container_name: server + hostname: server + restart: unless-stopped + expose: + - "8080" + - "50000" + volumes: + - /srv/docker/jenkins_server/home:/var/jenkins_home + - /srv/docker/jenkins_server/logs:/var/jenkins_home/logs + - /srv/docker/jenkins_server/tmp:/var/jenkins_home/tmp + - repos:/srv/scm + env_file: + - /srv/docker/jenkins_server/jenkins.env + jenkins_agent: + build: ../jenkins_agent + container_name: agent + hostname: agent + restart: unless-stopped + command: java -jar /usr/share/jenkins/agent.jar -jnlpUrl http://server:8080/computer/jenkins%5Fagent/jenkins-agent.jnlp + volumes: + - /srv/docker/jenkins_agent/data:/home/jenkins/agent + - repos:/srv/scm + +volumes: + repos: + driver: local + driver_opts: + type: 'none' + o: 'bind' + device: '/srv/scm' + diff --git a/puppet/modules/nerd/templates/jenkins/plugins.txt b/puppet/modules/nerd/templates/jenkins/plugins.txt new file mode 100644 index 0000000..31060cf --- /dev/null +++ b/puppet/modules/nerd/templates/jenkins/plugins.txt @@ -0,0 +1,115 @@ +antisamy-markup-formatter:162.v0e6ec0fcfcf6 +apache-httpcomponents-client-4-api:4.5.14-208.v438351942757 +asm-api:9.7.1-97.v4cc844130d97 +authentication-tokens:1.119.v50285141b_7e1 +blueocean-autofavorite:1.2.5 +blueocean-bitbucket-pipeline:1.27.16 +blueocean-commons:1.27.16 +blueocean-config:1.27.16 +blueocean-core-js:1.27.16 +blueocean-dashboard:1.27.16 +blueocean-display-url:2.4.3 +blueocean-events:1.27.16 +blueocean-git-pipeline:1.27.16 +blueocean-github-pipeline:1.27.16 +blueocean-i18n:1.27.16 +blueocean-jwt:1.27.16 +blueocean-personalization:1.27.16 +blueocean-pipeline-api-impl:1.27.16 +blueocean-pipeline-editor:1.27.16 +blueocean-pipeline-scm-api:1.27.16 +blueocean-rest-impl:1.27.16 +blueocean-rest:1.27.16 +blueocean-web:1.27.16 +blueocean:1.27.16 +bootstrap5-api:5.3.3-1 +bouncycastle-api:2.30.1.80-256.vf98926042a_9b_ +branch-api:2.1208.vf528356feca_4 +caffeine-api:3.1.8-133.v17b_1ff2e0599 +checks-api:2.2.1 +cloudbees-bitbucket-branch-source:934.4.0 +cloudbees-folder:6.980.v5a_cc0cb_25881 +command-launcher:118.v72741845c17a_ +commons-compress-api:1.26.1-2 +commons-lang3-api:3.17.0-84.vb_b_938040b_078 +commons-text-api:1.13.0-153.v91dcd89e2a_22 +configuration-as-code:1929.v036b_5a_e1f123 +credentials-binding:687.v619cb_15e923f +credentials:1405.vb_cda_74a_f8974 +display-url-api:2.209.v582ed814ff2f +durable-task:581.v299a_5609d767 +echarts-api:5.5.1-5 +eddsa-api:0.3.0-4.v84c6f0f4969e +favorite:2.225.v68765b_b_a_1fa_3 +font-awesome-api:6.6.0-2 +git-client:6.1.1 +git-parameter:0.10.0 +git:5.7.0 +github-api:1.321-478.vc9ce627ce001 +github-branch-source:1810.v913311241fa_9 +github:1.41.0 +gson-api:2.11.0-109.v1ef91dd0829a_ +handy-uri-templates-2-api:2.1.8-30.v7e777411b_148 +htmlpublisher:1.37 +instance-identity:201.vd2a_b_5a_468a_a_6 +ionicons-api:74.v93d5eb_813d5f +jackson2-api:2.17.0-379.v02de8ec9f64c +jakarta-activation-api:2.1.3-1 +jakarta-mail-api:2.1.3-1 +javax-activation-api:1.2.0-7 +javax-mail-api:1.6.2-10 +jaxb:2.3.9-1 +jdk-tool:83.v417146707a_3d +jenkins-design-language:1.27.16 +jjwt-api:0.11.5-112.ve82dfb_224b_a_d +joda-time-api:2.13.0-93.v9934da_29b_a_e9 +jquery:1.12.4-3 +jquery3-api:3.7.1-2 +jsch:0.2.16-86.v42e010d9484b_ +json-api:20250107-125.v28b_a_ffa_eb_f01 +json-path-api:2.9.0-138.vc943da_d833b_6 +junit:1312.v1a_235a_b_94a_31 +mailer:489.vd4b_25144138f +matrix-auth:3.2.4 +matrix-project:845.vffd7fa_f27555 +mina-sshd-api-common:2.14.0-143.v2b_362fc39576 +mina-sshd-api-core:2.14.0-143.v2b_362fc39576 +okhttp-api:4.11.0-183.va_87fc7a_89810 +pipeline-build-step:551.v178956c49ef8 +pipeline-graph-analysis:216.vfd8b_ece330ca_ +pipeline-groovy-lib:749.v70084559234a_ +pipeline-input-step:508.v584c0e9a_2177 +pipeline-milestone-step:119.vdfdc43fc3b_9a_ +pipeline-model-api:2.2221.vc657003fb_d93 +pipeline-model-definition:2.2221.vc657003fb_d93 +pipeline-model-extensions:2.2221.vc657003fb_d93 +pipeline-rest-api:2.34 +pipeline-stage-step:312.v8cd10304c27a_ +pipeline-stage-tags-metadata:2.2221.vc657003fb_d93 +pipeline-utility-steps:2.18.0 +plain-credentials:183.va_de8f1dd5a_2b_ +plugin-util-api:5.1.0 +prism-api:1.29.0-18 +pubsub-light:1.18 +scm-api:703.v72ff4b_259600 +script-security:1369.v9b_98a_4e95b_2d +snakeyaml-api:2.3-123.v13484c65210a_ +sse-gateway:1.27 +ssh-credentials:349.vb_8b_6b_9709f5b_ +sshd:3.330.vc866a_8389b_58 +structs:338.v848422169819 +theme-manager:278.v2e3c063e42cc +token-macro:400.v35420b_922dcb_ +trilead-api:2.147.vb_73cc728a_32e +variant:70.va_d9f17f859e0 +versioncolumn:320.v6b_b_814ca_01f7 +workflow-aggregator:600.vb_57cdd26fdd7 +workflow-api:1363.v03f731255494 +workflow-basic-steps:1079.vce64b_a_929c5a_ +workflow-cps:4014.vcd7dc51d8b_30 +workflow-durable-task-step:1405.v1fcd4a_d00096 +workflow-job:1498.v33a_0c6f3a_4b_4 +workflow-multibranch:800.v5f0a_a_660950e +workflow-scm-step:427.v4ca_6512e7df1 +workflow-step-api:686.v603d058a_e148 +workflow-support:944.v5a_859593b_98a_ \ No newline at end of file diff --git a/puppet/site.pp b/puppet/site.pp new file mode 100644 index 0000000..430ad0a --- /dev/null +++ b/puppet/site.pp @@ -0,0 +1,129 @@ + +############################################################################### +# Puppet standalone manifest to be applied to setup Exercise environment +############################################################################### +# No need to filter by hostname here. +node default { + include ::stdlib + # This will install all docker stack with default value + # FIXME Debian on WSL will be an issue due to systemd being chosen as default service provider. + include 'docker' + + # enforce custom root password + user { 'root': + password => pw_hash('secret_root_password', 'SHA-512', stdlib::fqdn_rand_string(10)) + } + # enforce custom user password + user { 'nerd': + password => pw_hash('secret_nerd_password', 'SHA-512', stdlib::fqdn_rand_string(10)) + } + # enforce directory layout for clarity + file {[ + '/srv/docker', '/srv/scm', + '/srv/docker/proxy', '/srv/docker/proxy/nginx-conf' + ]: + ensure => directory + } + # enforce more directory layout for clarity + # those are likely to be written by the docker execution. + file {[ + '/srv/docker/jenkins_server', '/srv/docker/jenkins_server/home', + '/srv/docker/jenkins_server/logs', '/srv/docker/jenkins_server/tmp', + '/srv/docker/jenkins_agent', '/srv/docker/jenkins_agent/data' + ]: + ensure => directory, + owner => 1000, + group => 1000 + } + + ############################################################################# + ## Below Directives are required to setup the exercise environment. + ## You can look into the archives or into the deployed content but + ## MODIFY THE ARCHIVES CONTENT or the exercise might environment might + ## be compromised. + archive { '/var/local/jenkins_home.tar': + source => 'puppet:///modules/nerd/jenkins_home.tar', + extract => true, + extract_path => '/srv/docker/jenkins_server/home', + creates => '/srv/docker/jenkins_server/home/config.xml' + } + ## Above Directives are meant to setup the exercise environment. + ############################################################################# + + ############################################################################# + ## This archive contains the source code repository that will be used in + ## the Jenkins job both in the Server and Agent instances + ## This archive contains a bare repository that can be changed is needed + archive { '/var/local/repos.tar': + source => 'puppet:///modules/nerd/repos.tar', + extract => true, + extract_path => '/srv/scm', + creates => '/srv/scm/test_app' + } + ############################################################################# + + # simple http proxypass + file {'/srv/docker/proxy/nginx-conf/nginx-conf.conf': + content => @("U_NGINX"/$) + server { + listen 80; + server_name _; + access_log /var/log/nginx/access.log main; + error_log /var/log/nginx/error.log info; + + # skip favicon.ico + location = /favicon.ico { + access_log off; + return 204; + } + location / { + proxy_pass http://server:8080; + proxy_set_header Host \$http_host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_buffering off; + tcp_nodelay on; + } + } + |-U_NGINX + } + + # Jenkins Server Dockerfile + file {'/srv/docker/jenkins_server/Dockerfile': + content => template('nerd/jenkins/Dockerfile.server.erb'), + notify => Docker_compose['jenkins_stack'] + } + -> file {'/srv/docker/jenkins_server/plugins.txt': + content => template('nerd/jenkins/plugins.txt'), + notify => Docker_compose['jenkins_stack'] + } + -> file {'/srv/docker/jenkins_server/jenkins.env': + content => @("env"/$L) + TZ=Europe/Paris + LC_ALL=C.UTF-8 + JAVA_OPTS=-Djenkins.install.runSetupWizard=false + JENKINS_SLAVE_AGENT_PORT=50000 + JENKINS_OPTS=-Dhudson.plugins.git.GitSCM.ALLOW_LOCAL_CHECKOUT=true + | env + , + mode => '0400', + require => File['/srv/docker/jenkins_server'], + notify => Docker_compose['jenkins_stack'] + } + # Jenkins Agent Dockerfile + file {'/srv/docker/jenkins_agent/Dockerfile': + content => template('nerd/jenkins/Dockerfile.agent.erb'), + notify => Docker_compose['jenkins_stack'] + } + + # Jenkins Stack Compose file + file {'/srv/docker/proxy/docker-compose.yml': + content => template('nerd/jenkins/docker-compose.yml.erb'), + require => [File['/srv/docker/proxy']] + } + # Launch the stack + docker_compose { 'jenkins_stack': + ensure => present, + compose_files => ['/srv/docker/proxy/docker-compose.yml'] + } +} diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100755 index 0000000..b1f60c6 --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +export DEBIAN_FRONTEND=noninteractive +/usr/bin/apt-get update && /usr/bin/apt-get install -y puppet r10k +mkdir -p /etc/facter/facts.d +echo "{\"packer\":{\"source_name\":\"${1}\", \"source_type\":\"${2}\"}}" > $3 \ No newline at end of file