diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 914549bc..85d2338d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -108,6 +108,40 @@ jobs: ## If no one connects after 5 minutes, shut down server. wait-timeout-minutes: 5 + devel-tests: + strategy: + fail-fast: false + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v5 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + - name: Setup libvirt for Vagrant + uses: voxpupuli/setup-vagrant@v0 + - name: Install Ansible + run: pip install --upgrade ansible-core + - name: Setup environment + run: ./setup-environment + - name: Start VMs + run: | + ./forge vms start + - name: Configure repositories + run: | + ./forge setup-repositories + - name: Run deployment + run: | + ./forge deploy-dev --foreman-development-enabled-plugin foreman_ansible + - name: Setup upterm session + if: ${{ failure() }} + uses: owenthereal/action-upterm@v1 + with: + ## limits ssh access and adds the ssh public key for the user which triggered the workflow + limit-access-to-actor: true + ## If no one connects after 5 minutes, shut down server. + wait-timeout-minutes: 5 + # A dummy job that you can mark as a required check instead of each individual test test-suite: if: always() diff --git a/development/ansible.cfg b/development/ansible.cfg index 5aae890f..15225a2c 100644 --- a/development/ansible.cfg +++ b/development/ansible.cfg @@ -2,5 +2,5 @@ host_key_checking = False stdout_callback=debug stderr_callback=debug -roles_path = ./roles +roles_path = ./roles:../src/roles display_skipped_hosts = no diff --git a/development/playbooks/deploy-dev/deploy-dev.yaml b/development/playbooks/deploy-dev/deploy-dev.yaml new file mode 100644 index 00000000..dfa10cee --- /dev/null +++ b/development/playbooks/deploy-dev/deploy-dev.yaml @@ -0,0 +1,60 @@ +--- +- name: Deploy Foreman Development Environment + hosts: "{{ target_host if target_host is defined and target_host != '' else 'quadlet' }}" + become: true + vars_files: + - "../../../src/vars/defaults.yml" + - "../../../src/vars/{{ certificate_source }}_certificates.yml" + - "../../../src/vars/images.yml" + - "../../../src/vars/database.yml" + - "../../../src/vars/foreman.yml" + - "../../../src/vars/base.yaml" + vars: + httpd_foreman_backend: "http://localhost:3000" + roles: + - role: pre_install + - role: certificates + - role: postgresql + vars: + postgresql_databases: + - name: "{{ candlepin_database_name }}" + owner: "{{ candlepin_database_user }}" + - name: "{{ foreman_development_database_name }}" + owner: "{{ foreman_database_user }}" + - name: "{{ foreman_development_database_name }}_test" + owner: "{{ foreman_database_user }}" + - name: "{{ pulp_database_name }}" + owner: "{{ pulp_database_user }}" + postgresql_users: + - name: "{{ candlepin_database_user }}" + password: "{{ candlepin_database_password }}" + - name: "{{ foreman_database_user }}" + password: "{{ foreman_database_password }}" + role_attr_flags: SUPERUSER + - name: "{{ pulp_database_user }}" + password: "{{ pulp_database_password }}" + - role: redis + - role: candlepin + - role: httpd + - role: pulp + - role: foreman_development + post_tasks: + - name: Display development environment information + ansible.builtin.debug: + msg: | + Foreman development environment deployed successfully! + + Access URLs: + - Foreman UI: https://{{ foreman_development_url }} + - Direct Rails: http://localhost:3000 (when running) + + Credentials: + - Username: {{ foreman_development_admin_user }} + - Password: {{ foreman_development_admin_password }} + + Next steps: + - SSH into the system + when using Vagrant: vagrant ssh quadlet + when using a remote system: ssh {{ foreman_development_user }}@{{ ansible_facts['fqdn'] }} + - Navigate to {{ foreman_development_foreman_dir }} + - Run: bundle exec foreman start diff --git a/development/playbooks/deploy-dev/metadata.obsah.yaml b/development/playbooks/deploy-dev/metadata.obsah.yaml new file mode 100644 index 00000000..d4022466 --- /dev/null +++ b/development/playbooks/deploy-dev/metadata.obsah.yaml @@ -0,0 +1,18 @@ +--- +help: | + Deploy and manage Foreman development environment with git-based Foreman and containerized backend services. + +variables: + foreman_development_enabled_plugins: + help: Plugin to enable (can be used multiple times) + action: append + parameter: --foreman-development-enabled-plugin + target_host: + help: Target hostname or IP address for deployment + action: store + foreman_development_user: + help: Username for the development user account + action: store + foreman_development_github_username: + help: GitHub username to add as additional remote for git checkouts + action: store diff --git a/development/requirements.yml b/development/requirements.yml index b47a2162..e0ebc14f 100644 --- a/development/requirements.yml +++ b/development/requirements.yml @@ -1,7 +1,12 @@ --- collections: - ansible.posix + - community.crypto + - community.postgresql - community.general + - name: containers.podman + version: ">=1.16.4" - name: https://github.com/theforeman/forklift type: git + - name: theforeman.foreman - name: theforeman.operations diff --git a/development/roles/foreman_development/defaults/main.yaml b/development/roles/foreman_development/defaults/main.yaml new file mode 100644 index 00000000..5d33d764 --- /dev/null +++ b/development/roles/foreman_development/defaults/main.yaml @@ -0,0 +1,77 @@ +--- +foreman_development_user: "vagrant" +foreman_development_group: "{{ foreman_development_user }}" +foreman_development_deployment_dir: "/home/{{ foreman_development_user }}" +foreman_development_foreman_dir: "{{ foreman_development_deployment_dir }}/foreman" +foreman_development_cert_dir: "{{ foreman_development_deployment_dir }}/foreman-certs" + +foreman_development_ca_certificate: "{{ foreman_ca_certificate }}" +foreman_development_client_certificate: "{{ foreman_client_certificate }}" +foreman_development_client_key: "{{ foreman_client_key }}" + +foreman_development_admin_user: "admin" +foreman_development_admin_password: "changeme" + +foreman_development_git_repo: "https://github.com/theforeman/foreman.git" +foreman_development_git_revision: "develop" +foreman_development_github_username: "" + +foreman_development_rails_port: 3000 +foreman_development_rails_command: "puma -w 2 -p {{ foreman_development_rails_port }} --preload -b tcp://0.0.0.0" + +foreman_development_url: "http://{{ ansible_facts['fqdn'] }}:{{ foreman_development_rails_port }}" + +foreman_development_database_host: "localhost" +foreman_development_database_port: 5432 +foreman_development_database_name: "foreman_development" +foreman_development_database_user: "foreman" +foreman_development_database_password: "foreman" + +foreman_development_nodejs_stream: "22" + +foreman_development_plugin_registry: + katello: + name: "katello/katello" + settings_template: "katello.yaml.j2" + manage_repo: true + extra_gemfiles: + - "gemfile.d/test.rb" + foreman_remote_execution: + name: "theforeman/foreman_remote_execution" + manage_repo: true + foreman_ansible: + name: "theforeman/foreman_ansible" + settings_template: "foreman_ansible.yaml.j2" + manage_repo: true + foreman_rh_cloud: + name: "theforeman/foreman_rh_cloud" + manage_repo: true + foreman_discovery: + name: "theforeman/foreman_discovery" + manage_repo: true + foreman_openscap: + name: "theforeman/foreman_openscap" + manage_repo: true + foreman_bootdisk: + name: "theforeman/foreman_bootdisk" + manage_repo: true + +foreman_development_default_plugins: + - katello + - foreman_remote_execution + +foreman_development_enabled_plugins: [] + +foreman_development_packages: + - git + - ruby-devel + - npm + - postgresql-devel + - libxml2-devel + - libxslt-devel + - libcurl-devel + - gcc-c++ + - make + - rubygem-bundler + - rubygem-irb + - postgresql diff --git a/development/roles/foreman_development/tasks/main.yaml b/development/roles/foreman_development/tasks/main.yaml new file mode 100644 index 00000000..2a9ace8e --- /dev/null +++ b/development/roles/foreman_development/tasks/main.yaml @@ -0,0 +1,241 @@ +--- +- name: Enable nodejs module stream + ansible.builtin.command: + cmd: dnf module enable -y nodejs:{{ foreman_development_nodejs_stream | default('22') }} + register: foreman_development_nodejs_module_result + changed_when: "'CHANGED' in foreman_development_nodejs_module_result.stdout" + failed_when: + - foreman_development_nodejs_module_result.rc != 0 + - "'Nothing to do' not in foreman_development_nodejs_module_result.stdout" + - "'already enabled' not in foreman_development_nodejs_module_result.stdout" + +- name: Install nodejs from enabled module + ansible.builtin.package: + name: nodejs + state: present + +- name: Enable CodeReady Builder repository + community.general.rhsm_repository: + name: "codeready-builder-for-rhel-{{ ansible_distribution_major_version }}-{{ ansible_architecture }}-rpms" + state: enabled + when: ansible_distribution == 'RedHat' + +- name: Install development packages + ansible.builtin.package: + name: "{{ foreman_development_packages }}" + state: present + +- name: Disable firewall for development environment + ansible.builtin.systemd: + name: firewalld + state: stopped + enabled: false + failed_when: false + +- name: Create development user + ansible.builtin.user: + name: "{{ foreman_development_user }}" + home: "{{ foreman_development_deployment_dir }}" + create_home: true + groups: wheel + append: true + password: "{{ 'changeme' | password_hash('sha512') }}" + state: present + when: foreman_development_user != 'root' + +- name: Configure sudo access without password for development user + ansible.builtin.lineinfile: + path: /etc/sudoers.d/{{ foreman_development_user }} + line: "{{ foreman_development_user }} ALL=(ALL) NOPASSWD:ALL" + create: true + mode: '0440' + +- name: Create certificate directory + ansible.builtin.file: + path: "{{ foreman_development_cert_dir }}" + state: directory + owner: "{{ foreman_development_user }}" + group: "{{ foreman_development_group }}" + mode: "0775" + +- name: Copy certificates to development directory + ansible.builtin.copy: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + remote_src: true + owner: "{{ foreman_development_user }}" + group: "{{ foreman_development_group }}" + mode: "0640" + loop: + - src: "{{ foreman_development_ca_certificate }}" + dest: "{{ foreman_development_cert_dir }}/proxy_ca.pem" + - src: "{{ foreman_development_client_certificate }}" + dest: "{{ foreman_development_cert_dir }}/client_cert.pem" + - src: "{{ foreman_development_client_key }}" + dest: "{{ foreman_development_cert_dir }}/client_key.pem" + +- name: Clone Foreman repository + ansible.builtin.git: + repo: "{{ foreman_development_git_repo }}" + dest: "{{ foreman_development_foreman_dir }}" + version: "{{ foreman_development_git_revision }}" + force: true + become: true + become_user: "{{ foreman_development_user }}" + +- name: Add GitHub username as additional remote for Foreman + community.general.git_config: + name: "remote.{{ foreman_development_github_username }}.url" + scope: local + repo: "{{ foreman_development_foreman_dir }}" + value: "git@github.com:{{ foreman_development_github_username }}/foreman.git" + state: present + become: true + become_user: "{{ foreman_development_user }}" + when: foreman_development_github_username != "" + +- name: Create database configuration + ansible.builtin.template: + src: database.yml.j2 + dest: "{{ foreman_development_foreman_dir }}/config/database.yml" + owner: "{{ foreman_development_user }}" + group: "{{ foreman_development_group }}" + mode: "0644" + become: true + become_user: "{{ foreman_development_user }}" + +- name: Create development settings + ansible.builtin.template: + src: settings.yaml.j2 + dest: "{{ foreman_development_foreman_dir }}/config/settings.yaml" + owner: "{{ foreman_development_user }}" + group: "{{ foreman_development_group }}" + mode: "0644" + become: true + become_user: "{{ foreman_development_user }}" + +- name: Create environment file + ansible.builtin.template: + src: env.j2 + dest: "{{ foreman_development_foreman_dir }}/.env" + owner: "{{ foreman_development_user }}" + group: "{{ foreman_development_group }}" + mode: "0644" + become: true + become_user: "{{ foreman_development_user }}" + +- name: Create plugin settings directory + ansible.builtin.file: + path: "{{ foreman_development_foreman_dir }}/config/settings.plugins.d" + state: directory + owner: "{{ foreman_development_user }}" + group: "{{ foreman_development_group }}" + mode: "0755" + become: true + become_user: "{{ foreman_development_user }}" + +- name: Create bundler.d directory + ansible.builtin.file: + path: "{{ foreman_development_foreman_dir }}/bundler.d" + state: directory + owner: "{{ foreman_development_user }}" + group: "{{ foreman_development_group }}" + mode: "0755" + become: true + become_user: "{{ foreman_development_user }}" + +- name: Setup plugins + ansible.builtin.include_tasks: plugin.yaml + vars: + foreman_development_plugin_config: "{{ foreman_development_plugin_registry[plugin_item] }}" + foreman_development_plugin_name: "{{ foreman_development_plugin_config.name.split('/')[1] }}" + foreman_development_plugin_org: "{{ foreman_development_plugin_config.name.split('/')[0] }}" + foreman_development_plugin_repo_url: "https://github.com/{{ foreman_development_plugin_config.name }}.git" + foreman_development_plugin_manage_repo: "{{ foreman_development_plugin_config.manage_repo | default(true) }}" + foreman_development_plugin_settings_template: "{{ foreman_development_plugin_config.settings_template | default('') }}" + foreman_development_plugin_extra_gemfiles: "{{ foreman_development_plugin_config.extra_gemfiles | default([]) }}" + loop: "{{ foreman_development_default_plugins + foreman_development_enabled_plugins }}" + loop_control: + loop_var: plugin_item + +- name: Install Ruby dependencies + ansible.builtin.command: + cmd: bundle install --path .vendor --jobs 3 --without "libvirt:journald" + chdir: "{{ foreman_development_foreman_dir }}" + become: true + become_user: "{{ foreman_development_user }}" + environment: + PATH: "/usr/bin:/bin:/usr/local/bin" + changed_when: true + +- name: Install Node.js dependencies + ansible.builtin.command: + cmd: npm install + chdir: "{{ foreman_development_foreman_dir }}" + become: true + become_user: "{{ foreman_development_user }}" + changed_when: true + +- name: Run database migrations + ansible.builtin.command: + cmd: bundle exec rake db:migrate + chdir: "{{ foreman_development_foreman_dir }}" + become: true + become_user: "{{ foreman_development_user }}" + environment: + RAILS_ENV: development + changed_when: true + +- name: Seed database + ansible.builtin.command: + cmd: bundle exec rake db:seed + chdir: "{{ foreman_development_foreman_dir }}" + become: true + become_user: "{{ foreman_development_user }}" + environment: + RAILS_ENV: development + SEED_ADMIN_USER: "{{ foreman_development_admin_user }}" + SEED_ADMIN_PASSWORD: "{{ foreman_development_admin_password }}" + changed_when: true + +- name: Create Foreman development systemd service + ansible.builtin.template: + src: foreman-development.service.j2 + dest: /etc/systemd/system/foreman-development.service + owner: root + group: root + mode: "0644" + +- name: Reload systemd daemon + ansible.builtin.systemd: + daemon_reload: true + +- name: Enable and start Foreman development service + ansible.builtin.systemd: + name: foreman-development + enabled: true + state: started + +- name: Wait for Foreman development server to be accessible + ansible.builtin.uri: + url: '{{ foreman_development_url }}/api/v2/ping' + validate_certs: false + until: foreman_development_status.status == 200 + retries: 30 + delay: 5 + register: foreman_development_status + +- name: Configure Foreman Proxy for Pulp + theforeman.foreman.smart_proxy: + name: "{{ ansible_facts['fqdn'] }}-pulp" + url: "https://{{ ansible_facts['fqdn'] }}/pulp/api/v3/smart_proxy" + server_url: "{{ foreman_development_url }}" + username: "{{ foreman_development_admin_user }}" + password: "{{ foreman_development_admin_password }}" + validate_certs: false + +- name: Stop Foreman development service after smart proxy registration + ansible.builtin.systemd: + name: foreman-development + state: stopped + enabled: false diff --git a/development/roles/foreman_development/tasks/plugin.yaml b/development/roles/foreman_development/tasks/plugin.yaml new file mode 100644 index 00000000..5fb2215e --- /dev/null +++ b/development/roles/foreman_development/tasks/plugin.yaml @@ -0,0 +1,43 @@ +--- +- name: Clone plugin repository # noqa latest[git] + ansible.builtin.git: + repo: "{{ foreman_development_plugin_repo_url }}" + dest: "{{ foreman_development_deployment_dir }}/{{ foreman_development_plugin_name }}" + force: true + become: true + become_user: "{{ foreman_development_user }}" + when: foreman_development_plugin_manage_repo + +- name: Add GitHub username as additional remote for plugin + community.general.git_config: + name: "remote.{{ foreman_development_github_username }}.url" + scope: local + repo: "{{ foreman_development_deployment_dir }}/{{ foreman_development_plugin_name }}" + value: "git@github.com:{{ foreman_development_github_username }}/{{ foreman_development_plugin_name }}.git" + state: present + become: true + become_user: "{{ foreman_development_user }}" + when: + - foreman_development_plugin_manage_repo + - foreman_development_github_username != "" + +- name: Create plugin settings file + ansible.builtin.template: + src: "{{ foreman_development_plugin_settings_template }}" + dest: "{{ foreman_development_foreman_dir }}/config/settings.plugins.d/{{ foreman_development_plugin_name }}.yaml" + owner: "{{ foreman_development_user }}" + group: "{{ foreman_development_group }}" + mode: "0644" + become: true + become_user: "{{ foreman_development_user }}" + when: foreman_development_plugin_settings_template != "" + +- name: Create plugin bundler configuration + ansible.builtin.template: + src: plugin.local.rb.j2 + dest: "{{ foreman_development_foreman_dir }}/bundler.d/{{ foreman_development_plugin_name }}.local.rb" + owner: "{{ foreman_development_user }}" + group: "{{ foreman_development_group }}" + mode: "0644" + become: true + become_user: "{{ foreman_development_user }}" diff --git a/development/roles/foreman_development/templates/database.yml.j2 b/development/roles/foreman_development/templates/database.yml.j2 new file mode 100644 index 00000000..0f5698eb --- /dev/null +++ b/development/roles/foreman_development/templates/database.yml.j2 @@ -0,0 +1,29 @@ +development: + adapter: postgresql + database: {{ foreman_development_database_name }} + pool: 20 + username: {{ foreman_development_database_user }} + password: {{ foreman_development_database_password }} + host: localhost + encoding: UTF8 + template: template0 + +test: + adapter: postgresql + database: {{ foreman_development_database_name }}_test + pool: 20 + username: {{ foreman_development_database_user }} + password: {{ foreman_development_database_password }} + host: localhost + encoding: UTF8 + template: template0 + +production: + adapter: postgresql + database: {{ foreman_development_database_name }} + pool: 20 + username: {{ foreman_development_database_user }} + password: {{ foreman_development_database_password }} + host: localhost + encoding: UTF8 + template: template0 diff --git a/development/roles/foreman_development/templates/env.j2 b/development/roles/foreman_development/templates/env.j2 new file mode 100644 index 00000000..fccabcb6 --- /dev/null +++ b/development/roles/foreman_development/templates/env.j2 @@ -0,0 +1,4 @@ +BIND=0.0.0.0 +PORT={{ foreman_development_rails_port }} +RAILS_STARTUP='{{ foreman_development_rails_command }}' +REDUX_LOGGER=false diff --git a/development/roles/foreman_development/templates/foreman-development.service.j2 b/development/roles/foreman_development/templates/foreman-development.service.j2 new file mode 100644 index 00000000..83233e7b --- /dev/null +++ b/development/roles/foreman_development/templates/foreman-development.service.j2 @@ -0,0 +1,17 @@ +[Unit] +Description=Foreman Development Server +After=postgresql.service +Wants=postgresql.service + +[Service] +Type=simple +User={{ foreman_development_user }} +Group={{ foreman_development_group }} +WorkingDirectory={{ foreman_development_foreman_dir }} +Environment=RAILS_ENV=development +Environment=PATH=/usr/bin:/bin:/usr/local/bin +Environment=BUNDLE_PATH={{ foreman_development_foreman_dir }}/.vendor +ExecStart=/usr/bin/bundle exec {{ foreman_development_rails_command }} + +[Install] +WantedBy=multi-user.target diff --git a/development/roles/foreman_development/templates/foreman_ansible.yaml.j2 b/development/roles/foreman_development/templates/foreman_ansible.yaml.j2 new file mode 100644 index 00000000..8667d597 --- /dev/null +++ b/development/roles/foreman_development/templates/foreman_ansible.yaml.j2 @@ -0,0 +1,13 @@ +### File managed with Ansible ### +## Role: foreman_development + +:ansible: + :ansible_dir: /usr/share/foreman/.ansible + :ansible_ssh_private_key_file: ~/.ssh/id_rsa_foreman_proxy + :post_provision_timeout: 300 + :roles_path: + - /etc/ansible/roles + - /usr/share/ansible/roles + :collections_paths: + - /etc/ansible/collections + - /usr/share/ansible/collections diff --git a/development/roles/foreman_development/templates/katello.yaml.j2 b/development/roles/foreman_development/templates/katello.yaml.j2 new file mode 100644 index 00000000..5d9d585a --- /dev/null +++ b/development/roles/foreman_development/templates/katello.yaml.j2 @@ -0,0 +1,19 @@ +### File managed with Ansible ### +## Role: foreman_development + +:katello: + :rest_client_timeout: 3600 + :katello_applicability: true + + :candlepin: + :url: {{ candlepin_url | default('https://localhost:23443/candlepin') }} + :oauth_key: katello + :oauth_secret: {{ candlepin_oauth_secret }} + :ca_cert_file: {{ foreman_development_cert_dir }}/proxy_ca.pem + + :candlepin_events: + :ssl_cert_file: {{ foreman_development_cert_dir }}/client_cert.pem + :ssl_key_file: {{ foreman_development_cert_dir }}/client_key.pem + :ssl_ca_file: {{ foreman_development_cert_dir }}/proxy_ca.pem + + :katello_applicability: true diff --git a/development/roles/foreman_development/templates/plugin.local.rb.j2 b/development/roles/foreman_development/templates/plugin.local.rb.j2 new file mode 100644 index 00000000..f43000d8 --- /dev/null +++ b/development/roles/foreman_development/templates/plugin.local.rb.j2 @@ -0,0 +1,4 @@ +gemspec :path => '../{{ foreman_development_plugin_name }}', :development_group => '{{ foreman_development_plugin_name }}_dev', :name => '{{ foreman_development_plugin_name }}' +{% for gemfile in foreman_development_plugin_extra_gemfiles %} +eval_gemfile('{{ foreman_development_deployment_dir }}/{{ foreman_development_plugin_name }}/{{ gemfile }}') +{% endfor %} diff --git a/development/roles/foreman_development/templates/settings.yaml.j2 b/development/roles/foreman_development/templates/settings.yaml.j2 new file mode 100644 index 00000000..8a16de00 --- /dev/null +++ b/development/roles/foreman_development/templates/settings.yaml.j2 @@ -0,0 +1,48 @@ +#your default puppet server - can be overridden in the host level +#if none specified, plain "puppet" will be used. +#:puppet_server: puppet +:unattended: true +:login: true +:require_ssl: false +:locations_enabled: true +:organizations_enabled: true + +# The following values are used for providing default settings during db migrate +:oauth_active: true +:oauth_map_users: true +:oauth_consumer_key: {{ candlepin_oauth_key | default('katello') }} +:oauth_consumer_secret: {{ candlepin_oauth_secret }} + +# SSL settings +:ssl_ca_file: {{ foreman_development_cert_dir }}/proxy_ca.pem +:ssl_certificate: {{ foreman_development_cert_dir }}/client_cert.pem +:ssl_priv_key: {{ foreman_development_cert_dir }}/client_key.pem + +# Configure reverse proxy headers +:ssl_client_dn_env: HTTP_SSL_CLIENT_S_DN +:ssl_client_verify_env: HTTP_SSL_CLIENT_VERIFY +:ssl_client_cert_env: HTTP_SSL_CLIENT_CERT + +# Debug mode disables concatenation and preprocessing of assets. +:assets_debug: false + +# Rails Cache type +:rails_cache_store: + :type: redis + :urls: + - redis://localhost:6379/4 + :options: + :compress: true + :namespace: foreman + +# Individual logging types can be toggled on/off here +:loggers: + :audit: + :enabled: true + :level: error + :taxonomy: + :enabled: true + :level: error + :dynflow: + :enabled: true + :level: info diff --git a/docs/development-environment.md b/docs/development-environment.md new file mode 100644 index 00000000..b7406a5e --- /dev/null +++ b/docs/development-environment.md @@ -0,0 +1,122 @@ +# Foreman Development Environment + +This document describes how to set up and use the Foreman development environment that deploys Foreman source code directly on the VM while using containerized backend services. + +## Overview + +The development environment provides: +- Git-based Foreman installation (cloned from GitHub) +- Containerized backend services (PostgreSQL, Redis, Candlepin, Pulp, Apache HTTP Server) +- Plugin support with registry system +- Development-specific configurations +- Direct Rails server access for debugging + +## Prerequisites + +- A running EL9 virtual machine, and inventory that contains knowledge of the VM. For example, using `./forge vms start`. + - CentOS Stream 9 is recommended and tested + - Other EL9 variants should work too. Please report if they do not. +- Run `./setup-environment` and activate the virtual environment + +## Quick Start + +### Using Vagrant VMs (Default) + +1. **Start the development environment:** + ```bash + ./forge deploy-dev + ``` + +2. **Access the environment:** + - SSH into the VM: `vagrant ssh` + - Navigate to Foreman directory: `cd /home/vagrant/foreman` + - Start Rails server: `bundle exec foreman start` + +3. **Access URLs:** + - Foreman UI: `http://$(hostname -f):3000` (development server) + - Production-style UI: `https://$(hostname -f)` (via Apache proxy) + +### Deploying to a Remote Host + +You can deploy directly to a remote host using the `--target-host` parameter: + +```bash +# Deploy to a specific hostname or IP +./forge deploy-dev --target-host=my-server.example.com + +# Deploy to an IP address +./forge deploy-dev --target-host=192.168.1.100 +``` + +### SSH Authentication + +When deploying to remote hosts that require SSH password authentication: + +```bash +# Using environment variable +ANSIBLE_ASK_PASS=true ./forge deploy-dev --target-host=192.168.1.100 +``` + +## Plugin Management + +### Enabled Plugins (Default) + +- `katello` +- `foreman_remote_execution` + +### Plugin Registry + +The system includes a plugin registry with predefined configurations: +- `katello` - Katello subscription management +- `foreman_remote_execution` - Remote execution plugin +- `foreman_ansible` - Ansible integration +- `foreman_rh_cloud` - Red Hat Cloud integration +- `foreman_discovery` - Host discovery +- `foreman_openscap` - OpenSCAP compliance +- `foreman_bootdisk` - Boot disk creation + +### Enabling Additional Plugins + +#### At Deployment Time + +Use the `--foreman-development-enabled-plugin` parameter (can be used multiple times): + +```bash +# Enable specific plugins +./forge deploy-dev start --foreman-development-enabled-plugin katello --foreman-development-enabled-plugin foreman_ansible --foreman-development-enabled-plugin foreman_discovery + +# Enable single plugin +./forge deploy-dev start --foreman-development-enabled-plugin katello + +# Enable all available plugins +./forge deploy-dev start --foreman-development-enabled-plugin katello --foreman-development-enabled-plugin foreman_remote_execution --foreman-development-enabled-plugin foreman_ansible --foreman-development-enabled-plugin foreman_rh_cloud --foreman-development-enabled-plugin foreman_discovery --foreman-development-enabled-plugin foreman_openscap --foreman-development-enabled-plugin foreman_bootdisk +``` + +## Development Workflow + +### Initial Setup + +After deployment, the environment includes: +- Cloned Foreman repository +- Installed Ruby and Node.js dependencies +- Database migrations and seeding +- Plugin repositories and configurations +- Development-specific settings + +## Architecture + +### Service Integration + +The development environment integrates: +- **Apache HTTP Server**: Provides HTTPS proxy to the Rails development server +- **Backend Services**: All services (PostgreSQL, Redis, Candlepin, Pulp) run in containers +- **Rails Development Server**: Runs directly on the VM for live debugging and development +- **Pulp Smart Proxy Registration**: Automatically configures Pulp integration during deployment + +### Certificates + +Development certificates are copied to `/home/vagrant/foreman-certs/`: + +- `proxy_ca.pem` - CA certificate +- `client_cert.pem` - Client certificate +- `client_key.pem` - Client private key diff --git a/inventories/broker.py b/inventories/broker.py new file mode 100755 index 00000000..198df1da --- /dev/null +++ b/inventories/broker.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +import argparse +import json +import yaml +import os +import subprocess +import sys +from io import StringIO + + +def parse_args(): + parser = argparse.ArgumentParser(description="Broker inventory script") + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('--list', action='store_true') + group.add_argument('--host') + return parser.parse_args() + + +def get_running_hosts(): + cmd = ["broker", "inventory", "--details"] + + try: + output = subprocess.check_output(cmd, universal_newlines=True).rstrip() + except FileNotFoundError: + return + + hosts = yaml.safe_load(output) + return hosts.values() + + +def list_running_hosts(): + hosts = get_running_hosts() + variables = dict(get_configs(hosts)) + + return { + "_meta": { + "hostvars": variables + }, + "all": { + "hosts": list(variables.keys()) + }, + } + + +def get_configs(hosts): + if not hosts: + return + + for host in hosts: + if not host.get('hostname') or not host.get('ip'): + continue + + details = { + 'ansible_host': host['ip'], + 'ansible_port': '22', + 'ansible_user': 'root' + } + yield host['hostname'], details + + +def main(): + args = parse_args() + hosts = list_running_hosts() + + if args.list: + json.dump(hosts, sys.stdout) + elif args.host: + details = hosts['_meta']['hostvars'] + json.dump(details[args.host], sys.stdout) + + +if __name__ == '__main__': + main() diff --git a/src/playbooks/deploy/deploy.yaml b/src/playbooks/deploy/deploy.yaml index 59e14ae9..59a525a8 100644 --- a/src/playbooks/deploy/deploy.yaml +++ b/src/playbooks/deploy/deploy.yaml @@ -9,32 +9,7 @@ - "../../vars/images.yml" - "../../vars/database.yml" - "../../vars/foreman.yml" - vars: - certificates_hostnames: - - "{{ ansible_facts['fqdn'] }}" - - localhost - certificates_ca_password: "CHANGEME" - candlepin_keystore_password: "CHANGEME" - candlepin_oauth_secret: "CHANGEME" - candlepin_ca_key_password: "{{ ca_key_password }}" - candlepin_ca_key: "{{ ca_key }}" - candlepin_ca_certificate: "{{ ca_certificate }}" - candlepin_tomcat_key: "{{ localhost_key }}" - candlepin_tomcat_certificate: "{{ localhost_certificate }}" - candlepin_client_key: "{{ client_key }}" - candlepin_client_certificate: "{{ client_certificate }}" - foreman_ca_certificate: "{{ server_ca_certificate }}" - foreman_client_key: "{{ client_key }}" - foreman_client_certificate: "{{ client_certificate }}" - foreman_oauth_consumer_key: abcdefghijklmnopqrstuvwxyz123456 - foreman_oauth_consumer_secret: abcdefghijklmnopqrstuvwxyz123456 - foreman_url: "https://{{ ansible_facts['fqdn'] }}" - httpd_server_ca_certificate: "{{ server_ca_certificate }}" - httpd_client_ca_certificate: "{{ client_ca_certificate }}" - httpd_server_certificate: "{{ server_certificate }}" - httpd_server_key: "{{ server_key }}" - pulp_content_origin: "https://{{ ansible_facts['fqdn'] }}" - pulp_pulp_url: "https://{{ ansible_facts['fqdn'] }}" + - "../../vars/base.yaml" roles: - role: pre_install - role: checks diff --git a/src/requirements.txt b/src/requirements.txt index 0ee29be6..bdd36b72 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -1,2 +1,3 @@ obsah >= 1.4 +passlib requests diff --git a/src/roles/postgresql/tasks/main.yml b/src/roles/postgresql/tasks/main.yml index ba504298..2ca991b6 100644 --- a/src/roles/postgresql/tasks/main.yml +++ b/src/roles/postgresql/tasks/main.yml @@ -70,6 +70,7 @@ login_user: postgres login_password: "{{ postgresql_admin_password }}" login_host: localhost + role_attr_flags: "{{ item.role_attr_flags | default(omit) }}" state: present loop: "{{ postgresql_users }}" no_log: true diff --git a/src/vars/base.yaml b/src/vars/base.yaml new file mode 100644 index 00000000..5ad8d2f7 --- /dev/null +++ b/src/vars/base.yaml @@ -0,0 +1,31 @@ +--- +certificates_hostnames: + - "{{ ansible_facts['fqdn'] }}" + - localhost + +certificates_ca_password: "CHANGEME" +candlepin_keystore_password: "CHANGEME" +candlepin_oauth_secret: "CHANGEME" + +candlepin_ca_key_password: "{{ ca_key_password }}" +candlepin_ca_key: "{{ ca_key }}" +candlepin_ca_certificate: "{{ ca_certificate }}" +candlepin_tomcat_key: "{{ localhost_key }}" +candlepin_tomcat_certificate: "{{ localhost_certificate }}" +candlepin_client_key: "{{ client_key }}" +candlepin_client_certificate: "{{ client_certificate }}" + +foreman_ca_certificate: "{{ server_ca_certificate }}" +foreman_client_key: "{{ client_key }}" +foreman_client_certificate: "{{ client_certificate }}" +foreman_oauth_consumer_key: abcdefghijklmnopqrstuvwxyz123456 +foreman_oauth_consumer_secret: abcdefghijklmnopqrstuvwxyz123456 +foreman_url: "https://{{ ansible_facts['fqdn'] }}" + +httpd_server_ca_certificate: "{{ server_ca_certificate }}" +httpd_client_ca_certificate: "{{ client_ca_certificate }}" +httpd_server_certificate: "{{ server_certificate }}" +httpd_server_key: "{{ server_key }}" + +pulp_content_origin: "https://{{ ansible_facts['fqdn'] }}" +pulp_pulp_url: "https://{{ ansible_facts['fqdn'] }}"