├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ └── user-story.md └── pull-request-template.md ├── .gitignore ├── .zuul.yaml ├── LICENSE ├── README.md ├── Vagrantfile ├── ci ├── mbbox-osdk-playbook.yml ├── roles │ └── openshift-osdk │ │ ├── defaults │ │ └── main.yml │ │ ├── files │ │ ├── .bashrc │ │ └── motd │ │ └── tasks │ │ ├── main.yml │ │ └── operator-sdk.yml ├── test-cluster.yml ├── test-default.yml ├── test-docs.yml └── test-local.yml ├── component ├── components ├── identity │ ├── README.md │ └── kube.yaml ├── kerberos │ ├── 0-service.yaml │ ├── 1-configmap.yaml │ ├── 2-deployment.yaml │ └── README.md ├── psql │ ├── 0-secret.yaml │ ├── 1-pvc.yaml │ ├── 2-deployment.yaml │ └── 3-service.yaml └── rabbitmq │ ├── 0-secret.yaml │ ├── 1-app.secret.yaml │ ├── 2-pvc.yaml │ ├── 3-service.yaml │ ├── 4-deployment.yaml │ ├── README.md │ └── playbook.yml ├── docs ├── Makefile ├── make.bat └── source │ ├── _static │ └── .gitkeep │ ├── conf.py │ ├── contributing.rst │ ├── deployment-guide.rst │ ├── index.rst │ └── user-guide │ ├── index.rst │ ├── koji-builder.rst │ ├── koji-hub.rst │ ├── kojira.rst │ ├── mbox.rst │ ├── mbs-backend.rst │ └── mbs-frontend.rst ├── example.yml ├── images ├── identity │ ├── Dockerfile │ ├── cfgprofile │ └── start.sh ├── kerberos │ └── Dockerfile ├── koji-builder │ ├── Dockerfile │ └── entrypoint.sh ├── koji-hub │ ├── Dockerfile │ ├── entrypoint.sh │ ├── readiness.sh │ └── service.yaml ├── kojira │ ├── Dockerfile │ └── entrypoint.sh ├── mbs-backend │ ├── Dockerfile │ ├── entrypoint.sh │ └── mbs-scheduler.py └── mbs-frontend │ ├── Dockerfile │ ├── entrypoint.sh │ └── mbs.wsgi ├── main.py └── mbox-operator ├── .yamllint ├── Dockerfile ├── Makefile ├── PROJECT ├── config ├── crd │ ├── bases │ │ ├── apps.fedoraproject.org_mbkojibuilders.yaml │ │ ├── apps.fedoraproject.org_mbkojihubs.yaml │ │ ├── apps.fedoraproject.org_mbkojiras.yaml │ │ ├── apps.fedoraproject.org_mbmbsbackends.yaml │ │ ├── apps.fedoraproject.org_mbmbsfrontends.yaml │ │ └── apps.fedoraproject.org_mboxes.yaml │ └── kustomization.yaml ├── default │ ├── kustomization.yaml │ └── manager_auth_proxy_patch.yaml ├── manager │ ├── kustomization.yaml │ └── manager.yaml ├── prometheus │ ├── kustomization.yaml │ └── monitor.yaml ├── rbac │ ├── auth_proxy_client_clusterrole.yaml │ ├── auth_proxy_role.yaml │ ├── auth_proxy_role_binding.yaml │ ├── auth_proxy_service.yaml │ ├── kustomization.yaml │ ├── leader_election_role.yaml │ ├── leader_election_role_binding.yaml │ ├── mbkojibuilder_editor_role.yaml │ ├── mbkojibuilder_viewer_role.yaml │ ├── mbkojihub_editor_role.yaml │ ├── mbkojihub_viewer_role.yaml │ ├── mbkojira_editor_role.yaml │ ├── mbkojira_viewer_role.yaml │ ├── mbmbsbackend_editor_role.yaml │ ├── mbmbsbackend_viewer_role.yaml │ ├── mbmbsfrontend_editor_role.yaml │ ├── mbmbsfrontend_viewer_role.yaml │ ├── mbox_editor_role.yaml │ ├── mbox_viewer_role.yaml │ ├── role.yaml │ ├── role_binding.yaml │ └── service_account.yaml ├── samples │ ├── apps_v1alpha1_mbkojibuilder.yaml │ ├── apps_v1alpha1_mbkojihub.yaml │ ├── apps_v1alpha1_mbkojira.yaml │ ├── apps_v1alpha1_mbmbsbackend.yaml │ ├── apps_v1alpha1_mbmbsfrontend.yaml │ ├── apps_v1alpha1_mbox.yaml │ └── kustomization.yaml ├── scorecard │ ├── bases │ │ └── config.yaml │ ├── kustomization.yaml │ └── patches │ │ ├── basic.config.yaml │ │ └── olm.config.yaml └── testing │ ├── debug_logs_patch.yaml │ ├── kustomization.yaml │ ├── manager_image.yaml │ └── pull_policy │ ├── Always.yaml │ ├── IfNotPresent.yaml │ └── Never.yaml ├── molecule ├── default │ ├── converge.yml │ ├── create.yml │ ├── destroy.yml │ ├── kustomize.yml │ ├── molecule.yml │ ├── prepare.yml │ ├── tasks │ │ ├── mbkojibuilder_test.yml │ │ ├── mbkojihub_test.yml │ │ ├── mbkojira_test.yml │ │ ├── mbmbsbackend_test.yml │ │ ├── mbmbsfrontend_test.yml │ │ └── mbox_test.yml │ └── verify.yml ├── kind │ ├── converge.yml │ ├── create.yml │ ├── destroy.yml │ └── molecule.yml └── test-local │ ├── converge.yml │ ├── destroy.yml │ ├── molecule.yml │ └── prepare.yml ├── playbooks └── .keep ├── requirements.yml ├── roles ├── koji-builder │ ├── defaults │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── cert.yml │ │ └── main.yml │ └── templates │ │ ├── configmap.yml.j2 │ │ └── deployment.yml.j2 ├── koji-hub │ ├── defaults │ │ └── main.yml │ ├── tasks │ │ ├── cert.yml │ │ ├── main.yml │ │ └── pvc.yml │ └── templates │ │ ├── cert-secret.yml.j2 │ │ ├── configmap.yml.j2 │ │ ├── deployment.yml.j2 │ │ ├── ingress.yml.j2 │ │ ├── kojiadmin.conf.j2 │ │ ├── openshift-route.yml.j2 │ │ ├── pvc.yml.j2 │ │ └── service.yml.j2 ├── koji-lib │ ├── library │ │ ├── koji_host.py │ │ └── koji_user.py │ └── tasks │ │ └── main.yml ├── kojira │ ├── defaults │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── cert.yml │ │ └── main.yml │ └── templates │ │ ├── kojira.configmap.yaml.j2 │ │ └── kojira.deployment.yaml.j2 ├── mbox │ ├── README.md │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── cert.yml │ │ └── main.yml │ ├── templates │ │ └── mbs.configmap.yaml.j2 │ └── vars │ │ └── main.yml ├── mbs-backend │ ├── defaults │ │ └── main.yml │ ├── tasks │ │ ├── cert.yml │ │ └── main.yml │ └── templates │ │ ├── deployment.yaml.j2 │ │ └── mbs-configmap.yaml.j2 └── mbs-frontend │ ├── defaults │ └── main.yml │ ├── tasks │ ├── cert.yml │ └── main.yml │ └── templates │ ├── deployment.yaml.j2 │ ├── ingress.yml.j2 │ ├── mbs-configmap.yaml.j2 │ ├── mbs-frontend.configmap.yaml.j2 │ └── service.yml.j2 └── watches.yaml /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Report a bug for mbbox 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Expected Behavior 11 | 12 | 13 | ## Actual Behavior 14 | 15 | 16 | ## Steps to Reproduce the Problem 17 | 18 | * -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/user-story.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: User Story 3 | about: Create an user story for mbbox 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | # Description 10 | 11 | ## Acceptance Criteria 12 | -------------------------------------------------------------------------------- /.github/pull-request-template.md: -------------------------------------------------------------------------------- 1 | 4 | Fixes # 5 | 6 | 9 | ## Proposed Changes 10 | 11 | * 12 | 13 | 16 | ## Verification Steps 17 | 18 | * 19 | 20 | 23 | ## Additional Notes 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | state/ 2 | mbox/__pycache__ 3 | openshift.local.clusterup/ 4 | .vagrant/ 5 | docs/build 6 | -------------------------------------------------------------------------------- /.zuul.yaml: -------------------------------------------------------------------------------- 1 | # Disaled until we have a real CI kubernetes cluster 2 | # - job: 3 | # name: test-cluster 4 | # run: ci/test-cluster.yml 5 | # nodeset: fedora-30-vm-medium 6 | - job: 7 | name: test-local 8 | run: ci/test-local.yml 9 | nodeset: fedora-30-vm-medium 10 | - job: 11 | name: test-docs 12 | run: ci/test-docs.yml 13 | nodeset: fedora-30-vm 14 | - job: 15 | name: test-lint 16 | run: ci/test-default.yml 17 | nodeset: fedora-30-vm 18 | - project: 19 | check: 20 | jobs: 21 | # - test-cluster 22 | - test-local 23 | - test-docs 24 | - test-lint 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Patrick Uiterwijk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Documentation Status](https://readthedocs.org/projects/mbbox-operator/badge/?version=latest)](https://mbbox-operator.readthedocs.io/en/latest/?badge=latest) 2 | 3 | # mbox 4 | Module Building in a Box 5 | 6 | This repository contains a Kubernetes operator for deployment of buildsystem that can be used for Fedora/RHEL Modular packages, based on [Koji](https://pagure.io/koji/) and [Module Build Service](https://pagure.io/fm-orchestrator/). 7 | 8 | The intention is for it to be trivially simple to get started with both, but also allow the same setup to be used for a production setup. 9 | 10 | Full documentation can be found at: https://mbbox-operator.readthedocs.io/en/latest/ 11 | 12 | ## Development environment 13 | This project uses vagrant as development environment. To use the vagrant you need to have installed [`vagrant`](https://www.vagrantup.com/), [`vagrant_sshfs`](https://github.com/dustymabe/vagrant-sshfs) and [`libvirt`](https://libvirt.org/). 14 | 15 | ### Operator SDK vagrant box 16 | To setup the development environment run `vagrant up` in root folder. 17 | 18 | To recreate the environment run `vagrant destroy && vagrant up`. `vagrant provision` will not work in most cases because of the various OpenShift commands ran by the ansible provisioning script. 19 | 20 | To enter the running vagrant box use `vagrant ssh`. 21 | 22 | The box is set to use `docker` with [quay.io](https://quay.io) registry. For this to work properly you need to login to your quay.io account using `docker login quay.io`. 23 | 24 | Follow MOTD (Message Of The Day) for more information. 25 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | require 'etc' 5 | 6 | VAGRANTFILE_API_VERSION = "2" 7 | 8 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 9 | config.vm.box = "fedora/33-cloud-base" 10 | 11 | # Forward traffic on the host to the development server on the guest 12 | # config.vm.network "forwarded_port", guest: 5000, host: 5000 13 | # RabbitMQ 14 | config.vm.network "forwarded_port", guest: 15672, host: 15672 15 | 16 | if Vagrant.has_plugin?("vagrant-hostmanager") 17 | config.hostmanager.enabled = true 18 | config.hostmanager.manage_host = true 19 | end 20 | 21 | # Vagrant can share the source directory using rsync, NFS, or SSHFS (with the vagrant-sshfs 22 | # plugin). By default it rsyncs the current working directory to /vagrant. 23 | # 24 | # If you would prefer to use NFS to share the directory uncomment this and configure NFS 25 | # config.vm.synced_folder ".", "/vagrant", type: "nfs", nfs_version: 4, nfs_udp: false 26 | config.vm.synced_folder ".", "/vagrant", disabled: true 27 | config.vm.synced_folder ".", "/home/vagrant/devel", type: "sshfs" 28 | 29 | # To cache update packages (which is helpful if frequently doing `vagrant destroy && vagrant up`) 30 | # you can create a local directory and share it to the guest's DNF cache. The directory needs to 31 | # exist, so create it before you uncomment the line below. 32 | # 33 | # config.vm.synced_folder ".dnf-cache", "/var/cache/dnf", type: "sshfs", sshfs_opts_append: "-o nonempty" 34 | 35 | # Comment this line if you would like to disable the automatic update during provisioning 36 | config.vm.provision "shell", inline: "sudo dnf upgrade -y" 37 | 38 | # Create the "mbbox" OperatorSDK box 39 | config.vm.define "mbbox_osdk", autostart: true do |mbbox_osdk| 40 | mbbox_osdk.vm.host_name = "mbbox-osdk.example.com" 41 | # bootstrap and run with ansible 42 | mbbox_osdk.vm.provision "ansible" do |ansible| 43 | ansible.playbook = "ci/mbbox-osdk-playbook.yml" 44 | ansible.raw_arguments = ["-e", "ansible_python_interpreter=/usr/bin/python3"] 45 | end 46 | 47 | mbbox_osdk.vm.provider :libvirt do |domain| 48 | # Season to taste 49 | domain.cpus = Etc.nprocessors 50 | domain.cpu_mode = "host-passthrough" 51 | domain.graphics_type = "spice" 52 | domain.memory = 4096 53 | domain.video_type = "qxl" 54 | 55 | # Uncomment the following line if you would like to enable libvirt's unsafe cache 56 | # mode. It is called unsafe for a reason, as it causes the virtual host to ignore all 57 | # fsync() calls from the guest. Only do this if you are comfortable with the possibility of 58 | # your development guest becoming corrupted (in which case you should only need to do a 59 | # vagrant destroy and vagrant up to get a new one). 60 | # 61 | # domain.volume_cache = "unsafe" 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /ci/mbbox-osdk-playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: true 4 | become_method: sudo 5 | vars: 6 | roles: 7 | - openshift-osdk 8 | -------------------------------------------------------------------------------- /ci/roles/openshift-osdk/defaults/main.yml: -------------------------------------------------------------------------------- 1 | minikube_version: '1.15.1-0' 2 | operator_sdk_version: '1.2.0' 3 | kustomize_version: '3.8.7' 4 | dev_username: vagrant 5 | -------------------------------------------------------------------------------- /ci/roles/openshift-osdk/files/.bashrc: -------------------------------------------------------------------------------- 1 | # .bashrc 2 | 3 | # Source global definitions 4 | if [ -f /etc/bashrc ]; then 5 | . /etc/bashrc 6 | fi 7 | 8 | # User specific environment 9 | if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]] 10 | then 11 | PATH="$HOME/.local/bin:$HOME/bin:$PATH" 12 | fi 13 | 14 | export PATH 15 | 16 | # Uncomment the following line if you don't like systemctl's auto-paging feature: 17 | # export SYSTEMD_PAGER= 18 | 19 | # User specific aliases and functions 20 | 21 | #alias minikube='sudo minikube' 22 | #alias oc='sudo oc' 23 | #alias docker='sudo docker' 24 | #alias operator_sdk='sudo operator-sdk' 25 | -------------------------------------------------------------------------------- /ci/roles/openshift-osdk/files/motd: -------------------------------------------------------------------------------- 1 | 2 | Welcome to the mbbox development environment! 3 | 4 | Here are some tips: 5 | 6 | * The code is located at ~/devel/ 7 | 8 | * Dev environment is set for the development of ansible based operator for OpenShift, for more info look at https://docs.openshift.com/container-platform/4.3/operators/operator_sdk/osdk-ansible.html 9 | 10 | * To test the operator in the containerized kubernetes cluster 11 | # This command runs automated E2E (end to end) tests in the containerized kubernetes cluster 12 | $ molecule test -s test-local 13 | 14 | * To deploy and run the mbox operator in the local kubernetes cluster: 15 | # First you need to start the minikube cluster and enable the ingress addon 16 | $ minikube start 17 | $ minikube addons enable ingress 18 | 19 | # To prevent issues in docker network setup of minikube 20 | $ minikube ssh 21 | $ sudo ip link set docker0 promisc on 22 | 23 | # Build the image and upload it to quay (optional) (you need to be in ~/devel/mbox-operator) 24 | # This needs to be done every time you made a change to the operator code 25 | # You may also need to update the IMG variable in mbox-operator/Makefile 26 | $ docker build -t quay.io/username/mbbox-operator:tag . 27 | $ docker push quay.io/username/mbbox-operator:tag 28 | 29 | # Create the mbbox-operator requirements to the local kubernetes cluster 30 | # This needs to be done only once unless there was a change in any of those resources 31 | $ make install 32 | 33 | # Deploy the operator 34 | $ make deploy 35 | 36 | # Deploy rabbitmq and postgreSQL (you need to be in the ~/devel directory) 37 | $ kubectl apply -f components/rabbitmq -n default 38 | $ kubectl apply -f components/psql -n default 39 | 40 | # Deploy the operator CRDs (you need to be in ~/devel/mbox-operator) 41 | $ kustomize build config/samples | kubectl apply -f - 42 | 43 | Congratulations! MBBox is now running inside 'default' namespace. 44 | 45 | * To destroy the minikube cluster 46 | $ minikube delete 47 | 48 | * To debug kubernetes deployment here are a few tips 49 | $ kubectl get all - help you see what is currently in kubernetes cluster 50 | $ kubectl describe pod/ - will give you some overview 51 | $ kubectl logs pod/ - will show you logs of the pod 52 | 53 | Happy hacking! 54 | 55 | -------------------------------------------------------------------------------- /ci/roles/openshift-osdk/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install helpful development packages 3 | dnf: 4 | name: [ 5 | fpaste, 6 | git, 7 | htop, 8 | make, 9 | python3-black, 10 | python3-sphinx, 11 | tmux, 12 | vim-enhanced, 13 | ] 14 | state: present 15 | 16 | # Add various helpful configuration files 17 | - name: Install the message of the day 18 | copy: src=motd dest=/etc/motd 19 | 20 | - name: Copy bashrc 21 | copy: src=.bashrc dest=/home/vagrant/.bashrc 22 | 23 | - name: Configure Cgroups v1 for docker in grub.cfg 24 | replace: 25 | path: /etc/default/grub 26 | regexp: '^(GRUB_CMDLINE_LINUX="[^"]+)' 27 | replace: '\1 systemd.unified_cgroup_hierarchy=0' 28 | 29 | - name: Generate the new grub configuration with cgroups v1 30 | command: grub2-mkconfig -o /boot/grub2/grub.cfg 31 | 32 | - name: Reboot the machine 33 | reboot: 34 | 35 | - import_tasks: operator-sdk.yml 36 | -------------------------------------------------------------------------------- /ci/roles/openshift-osdk/tasks/operator-sdk.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Operator SDK system dependencies 3 | dnf: 4 | name: [ 5 | ansible, 6 | ansible-lint, 7 | docker, 8 | kubernetes, 9 | kubernetes-client, 10 | python-flake8, 11 | python-molecule, 12 | python-molecule-docker, 13 | python-openshift 14 | ] 15 | state: present 16 | 17 | - name: Install Python dependencies 18 | pip: 19 | name: 20 | - kubernetes < 12.0.0 21 | 22 | - name: Create docker group 23 | group: 24 | name: docker 25 | state: present 26 | become: yes 27 | 28 | - name: Ensure user is added to docker group 29 | user: 30 | name: "{{ dev_username }}" 31 | groups: ['docker'] 32 | append: yes 33 | become: yes 34 | 35 | - name: Reset ssh connection to allow user changes to affect 'current login user' 36 | meta: reset_connection 37 | 38 | - name: Start docker 39 | systemd: 40 | state: restarted 41 | daemon_reload: yes 42 | name: docker 43 | 44 | # I don't like to do this, but the manually installed minikube needs to many SELinux changes 45 | - name: Set SELinux to permissive 46 | selinux: 47 | policy: targeted 48 | state: permissive 49 | 50 | # Install minikube 51 | - name: Download minikube 52 | get_url: 53 | url: https://storage.googleapis.com/minikube/releases/latest/minikube-{{minikube_version}}.x86_64.rpm 54 | dest: /tmp/ 55 | 56 | - name: Install minikube 57 | dnf: 58 | name: /tmp/minikube-{{minikube_version}}.x86_64.rpm 59 | state: present 60 | disable_gpg_check: true 61 | 62 | - name: Set minikube default driver to docker 63 | command: minikube config set vm-driver docker 64 | become: yes 65 | become_user: "{{ dev_username }}" 66 | 67 | # Install kustomize 68 | - name: Retrieve kustomize 69 | get_url: 70 | url: https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh 71 | dest: /tmp/install_kustomize.sh 72 | 73 | - name: Create kustomize binary 74 | command: bash /tmp/install_kustomize.sh {{ kustomize_version }} 75 | args: 76 | chdir: /tmp/ 77 | creates: /tmp/kustomize 78 | 79 | - name: Move kustomize binary to correct location 80 | copy: 81 | src: /tmp/kustomize 82 | dest: /usr/local/bin/kustomize 83 | mode: '0755' 84 | remote_src: yes 85 | 86 | # "Install" the operator SDK 87 | - name: Retrieve operator-sdk binary 88 | get_url: 89 | url: https://github.com/operator-framework/operator-sdk/releases/download/v{{operator_sdk_version}}/operator-sdk-v{{operator_sdk_version}}-x86_64-linux-gnu 90 | dest: /tmp/ 91 | 92 | - name: Move operator-sdk binary to correct location 93 | copy: 94 | src: /tmp/operator-sdk-v{{operator_sdk_version}}-x86_64-linux-gnu 95 | dest: /usr/local/bin/operator-sdk 96 | mode: '0755' 97 | remote_src: yes 98 | -------------------------------------------------------------------------------- /ci/test-cluster.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | become: true 3 | tasks: 4 | - name: Add Vagrant user and home-dir 5 | user: 6 | name: vagrant 7 | - hosts: all 8 | become: true 9 | become_method: sudo 10 | vars: 11 | roles: 12 | - openshift-osdk 13 | 14 | - hosts: all 15 | tasks: 16 | - name: Download kustomize 17 | get_url: 18 | url: https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh 19 | dest: /usr/bin/install_kustomize.sh 20 | mode: '0755' 21 | become: true 22 | - name: 23 | command: ./install_kustomize.sh 24 | args: 25 | chdir: /usr/bin 26 | become: true 27 | - name: Run molecule test-cluster 28 | command: molecule test 29 | args: 30 | chdir: "{{ansible_user_dir}}/{{zuul.project.src_dir}}/mbox-operator" 31 | become: true 32 | environment: 33 | OPERATOR_IMAGE: "quay.io/fedora/mbox-operator:latest" 34 | MOLECULE_PROJECT_DIRECTORY: "{{ansible_user_dir}}/{{zuul.project.src_dir}}/mbox-operator" 35 | OPERATOR_PULL_POLICY: Always 36 | K8S_AUTH_KUBECONFIG: /tmp/molecule/kind-test-local/kubeconfig 37 | KUBECONFIG: /tmp/molecule/kind-test-local/kubeconfig 38 | ANSIBLE_ROLES_PATH: ${MOLECULE_PROJECT_DIRECTORY}/roles 39 | KIND_PORT: '10443' 40 | -------------------------------------------------------------------------------- /ci/test-default.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: Install dependencies 4 | become: true 5 | dnf: 6 | name: 7 | - yamllint 8 | state: latest 9 | - name: Run molecule test (the default only runs lint) 10 | command: chdir={{ansible_user_dir}}/{{zuul.project.src_dir}}/mbox-operator yamllint roles/ 11 | -------------------------------------------------------------------------------- /ci/test-docs.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: install dependencies 4 | pip: 5 | name: sphinx 6 | extra_args: --user 7 | - name: Build html documentation 8 | command: "make html SPHINXOPTS='-W'" 9 | args: 10 | chdir: "{{ansible_user_dir}}/{{zuul.project.src_dir}}/docs" 11 | -------------------------------------------------------------------------------- /ci/test-local.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: List project directory on the test system 4 | command: ls -al {{ansible_user_dir}}/{{zuul.project.src_dir}} 5 | - name: Install git, pip and moby 6 | become: true 7 | package: 8 | name: ['git', 'moby-engine', 'python3-pip', 'conntrack-tools'] 9 | state: present 10 | 11 | - name: Ensure user is added to docker group 12 | user: 13 | name: "zuul-worker" 14 | groups: ['docker'] 15 | append: yes 16 | become: yes 17 | 18 | - name: Reset ssh connection to allow user changes to affect 'current login user' 19 | meta: reset_connection 20 | 21 | - name: Start docker 22 | become: true 23 | systemd: 24 | state: restarted 25 | daemon_reload: yes 26 | name: docker 27 | - name: Install libraries through pip 28 | become: true 29 | pip: 30 | name: 31 | - 'ansible' 32 | - 'molecule' 33 | - 'openshift' 34 | - 'kubernetes==11.0.0' # fixed version due to bugs with the latest version 35 | - 'docker' 36 | - 'jmespath' 37 | - 'yamllint' 38 | - 'molecule-docker' 39 | - name: Download kustomize 40 | get_url: 41 | url: https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh 42 | dest: /usr/bin/install_kustomize.sh 43 | mode: '0755' 44 | become: true 45 | - name: 46 | command: ./install_kustomize.sh 47 | args: 48 | chdir: /usr/bin 49 | become: true 50 | - name: Run molecule 51 | become: true 52 | shell: | 53 | OPERATOR_IMAGE="apps.fedoraproject.org/mbox-operator:testing" \ 54 | KUBECONFIG="/tmp/molecule/kind-test-local/kubeconfig" 55 | molecule test -s test-local 56 | args: 57 | chdir: "{{ansible_user_dir}}/{{zuul.project.src_dir}}/mbox-operator" 58 | -------------------------------------------------------------------------------- /component: -------------------------------------------------------------------------------- 1 | - Koji-builder 2 | - imagefactory 3 | - oz 4 | - livemediacreate 5 | - mock 6 | - Ipsilon 7 | - OpenIDC Extensions 8 | - MBS 9 | - ODCS 10 | 11 | 12 | External, configure: 13 | - Git 14 | - Lookaside 15 | 16 | 17 | Parameters: 18 | GIT_BASEURL 19 | LOOKASIDE_BASEURL 20 | REALM 21 | 22 | Expects: 23 | PV 24 | -------------------------------------------------------------------------------- /components/identity/README.md: -------------------------------------------------------------------------------- 1 | # Identity Deployment 2 | 3 | An identity kubernetes deployment for development purposes. 4 | 5 | It requires two secrets in order to work: 6 | 7 | HTTPD CA cert secret: 8 | 9 | ```yaml 10 | apiVersion: v1 11 | kind: Secret 12 | metadata: 13 | name: service-ca 14 | labels: 15 | app: identity 16 | data: 17 | cert: fillme 18 | ``` 19 | 20 | HTTPD certificate and key: 21 | 22 | ``` 23 | apiVersion: v1 24 | kind: Secret 25 | metadata: 26 | name: service-cert 27 | labels: 28 | app: identity 29 | data: 30 | tls.crt: fillme 31 | tls.key: fillme 32 | --- 33 | ``` -------------------------------------------------------------------------------- /components/identity/kube.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: identity-postgres 5 | labels: 6 | app: identity-postgres 7 | data: 8 | POSTGRES_HOST: cG9zdGdyZXNxbA== #postgresql 9 | POSTGRES_DB: bWJveGRi #mboxdb 10 | POSTGRES_USER: bWJveA== #koji 11 | POSTGRES_PASS: bWJveA== #mbox 12 | --- 13 | apiVersion: v1 14 | kind: Service 15 | metadata: 16 | name: identity 17 | labels: 18 | app: identity 19 | service: identity 20 | spec: 21 | ports: 22 | - name: web 23 | port: 8443 24 | targetPort: 8443 25 | selector: 26 | deploymentconfig: identity 27 | --- 28 | apiVersion: v1 29 | kind: PersistentVolumeClaim 30 | metadata: 31 | name: idenity-httpd 32 | spec: 33 | accessModes: 34 | - ReadWriteMany 35 | resources: 36 | requests: 37 | storage: 10Gi 38 | --- 39 | apiVersion: v1 40 | kind: ConfigMap 41 | metadata: 42 | name: identity-configmap 43 | data: 44 | httpd.conf: |- 45 | ServerRoot "/httpdir" 46 | PidFile "/httpdir/httpd.pid" 47 | LoadModule authn_file_module modules/mod_authn_file.so 48 | LoadModule authn_anon_module modules/mod_authn_anon.so 49 | LoadModule authz_user_module modules/mod_authz_user.so 50 | LoadModule authz_host_module modules/mod_authz_host.so 51 | LoadModule include_module modules/mod_include.so 52 | LoadModule log_config_module modules/mod_log_config.so 53 | LoadModule env_module modules/mod_env.so 54 | LoadModule ext_filter_module modules/mod_ext_filter.so 55 | LoadModule expires_module modules/mod_expires.so 56 | LoadModule headers_module modules/mod_headers.so 57 | LoadModule mime_module modules/mod_mime.so 58 | LoadModule status_module modules/mod_status.so 59 | LoadModule dir_module modules/mod_dir.so 60 | LoadModule alias_module modules/mod_alias.so 61 | LoadModule rewrite_module modules/mod_rewrite.so 62 | LoadModule version_module modules/mod_version.so 63 | LoadModule wsgi_module modules/mod_wsgi_python3.so 64 | LoadModule authn_core_module modules/mod_authn_core.so 65 | LoadModule authz_core_module modules/mod_authz_core.so 66 | LoadModule unixd_module modules/mod_unixd.so 67 | LoadModule mpm_event_module modules/mod_mpm_event.so 68 | LoadModule ssl_module modules/mod_ssl.so 69 | ServerName identity 70 | StartServers 20 71 | ServerLimit 100 72 | MaxRequestsPerChild 2000 73 | MaxRequestWorkers 100 74 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 75 | CustomLog /dev/stdout combined 76 | ErrorLog /dev/stderr 77 | LogLevel debug 78 | TypesConfig /etc/mime.types 79 | AddDefaultCharset UTF-8 80 | CoreDumpDirectory /tmp 81 | Listen 0.0.0.0:8443 https 82 | SSLEngine on 83 | SSLProtocol TLSv1.2 84 | 85 | SSLCertificateFile /etc/servicecert/tls.crt 86 | SSLCertificateKeyFile /etc/servicecert/tls.key 87 | SSLCertificateChainFile /etc/cacert/cert 88 | 89 | Include /etc/ipsilon/httpd/*.conf 90 | --- 91 | apiVersion: apps/v1 92 | kind: Deployment 93 | metadata: 94 | name: identity 95 | spec: 96 | replicas: 1 97 | selector: 98 | matchLabels: 99 | app: identity 100 | template: 101 | metadata: 102 | labels: 103 | app: identity 104 | spec: 105 | containers: 106 | - name: identity 107 | image: quay.io/fedora/identity:latest 108 | imagePullPolicy: Always 109 | #uncomment to debug pod 110 | #command: 111 | # - sleep 112 | # - infinity 113 | ports: 114 | - containerPort: 8443 115 | envFrom: 116 | - secretRef: 117 | name: identity-postgres 118 | volumeMounts: 119 | - name: identity-httpd 120 | mountPath: /httpdir 121 | - name: identity-config 122 | mountPath: /etc/ipsilon-cfg/httpd 123 | - name: service-cert 124 | mountPath: /etc/servicecert 125 | - name: service-ca 126 | mountPath: /etc/cacert 127 | volumes: 128 | - name: identity-httpd 129 | persistentVolumeClaim: 130 | claimName: idenity-httpd 131 | - name: identity-config 132 | configMap: 133 | name: identity-configmap 134 | - name: service-cert 135 | secret: 136 | secretName: service-cert 137 | - name: service-ca 138 | secret: 139 | secretName: service-ca 140 | -------------------------------------------------------------------------------- /components/kerberos/0-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: kerberos 5 | labels: 6 | app: kerberos 7 | service: kerberos 8 | spec: 9 | ports: 10 | - name: "kdc" 11 | port: 88 12 | targetPort: 88 13 | protocol: TCP 14 | - name: "kadmin" 15 | port: 749 16 | targetPort: 749 17 | protocol: TCP 18 | selector: 19 | app: kerberos 20 | -------------------------------------------------------------------------------- /components/kerberos/1-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: kerberos-configmap 5 | data: 6 | krb5.conf: |- 7 | [logging] 8 | default = FILE:/var/log/krb5libs.log 9 | kdc = FILE:/var/log/krb5kdc.log 10 | admin_server = FILE:/var/log/kadmind.log 11 | 12 | [libdefaults] 13 | ticket_lifetime = 24000 14 | default_realm = KERBEROS 15 | 16 | [realms] 17 | KERBEROS = { 18 | kdc = kerberos:88 19 | admin_server = kerberos:749 20 | default_domain = kerberos 21 | } 22 | 23 | [domain_realm] 24 | .kerberos = KERBEROS 25 | kerberos = KERBEROS 26 | 27 | [kdc] 28 | profile = /etc/kerberos/kdc.conf 29 | 30 | [pam] 31 | debug = false 32 | ticket_lifetime = 36000 33 | renew_lifetime = 36000 34 | forwardable = true 35 | krb4_convert = false 36 | 37 | kdc.conf: |- 38 | [kdcdefaults] 39 | kdc_ports = 88 40 | acl_file = /etc/kerberos/kadm5.acl 41 | dict_file = /usr/dict/words 42 | admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab 43 | 44 | [realms] 45 | KERBEROS = { 46 | database_name = /var/kerberos/krb5kdc/principal 47 | admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab 48 | kadmind_port = 749 49 | acl_file = /etc/kerberos/kadm5.acl 50 | dict_file = /usr/dict/words 51 | } 52 | 53 | kadm5.acl: |- 54 | */admin@KERBEROS * 55 | 56 | start.sh: |- 57 | #!/bin/sh 58 | 59 | # Create kerberos database 60 | expect -c " 61 | spawn kdb5_util create -s 62 | expect \"Enter KDC database master key:\" 63 | send \"admin\n\" 64 | expect \"Re-enter KDC database master key to verify:\" 65 | send \"admin\n\" 66 | expect eof 67 | exit 68 | " 69 | 70 | # Start services 71 | /usr/sbin/krb5kdc 72 | /usr/sbin/kadmind 73 | 74 | # Create principals and add them to keytab 75 | expect -c " 76 | spawn kadmin.local 77 | # Create principal host 78 | expect \"kadmin.local:\" 79 | send \"addprinc host/kerberos\n\" 80 | expect \"Enter password for principal 'host/kerberos@KERBEROS':\" 81 | send \"admin\n\" 82 | expect \"Re-enter password for principal 'host/kerberos@KERBEROS':\" 83 | send \"admin\n\" 84 | expect \"Principal 'host/kerberos@KERBEROS' created.\" 85 | 86 | # Create principal root 87 | expect \"kadmin.local:\" 88 | send \"addprinc root\n\" 89 | expect \"Enter password for principal 'root@KERBEROS':\" 90 | send \"admin\n\" 91 | expect \"Re-enter password for principal 'root@KERBEROS':\" 92 | send \"admin\n\" 93 | expect \"Principal 'root@KERBEROS' created.\" 94 | 95 | # Create principal root/admin 96 | expect \"kadmin.local:\" 97 | send \"addprinc root/admin\n\" 98 | expect \"Enter password for principal 'root/admin@KERBEROS':\" 99 | send \"admin\n\" 100 | expect \"Re-enter password for principal 'root/admin@KERBEROS':\" 101 | send \"admin\n\" 102 | expect \"Principal 'root/admin@KERBEROS' created.\" 103 | 104 | # Add the host to keytab 105 | expect \"kadmin.local:\" 106 | send \"ktadd -k /etc/krb5.keytab host/kerberos\n\" 107 | expect \"Entry for principal host/kerberos with kvno 2, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab.\" 108 | expect \"Entry for principal host/kerberos with kvno 2, encryption type Triple DES cbc mode raw added to keytab WRFILE:/etc/krb5.keytab.\" 109 | expect \"kadmin.local:\" 110 | send \"exit\n\" 111 | expect eof 112 | exit 113 | " 114 | 115 | # Keep the eye on the log 116 | tail -f /var/log/krb5kdc.log 117 | -------------------------------------------------------------------------------- /components/kerberos/2-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: kerberos 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: kerberos 10 | template: 11 | metadata: 12 | labels: 13 | app: kerberos 14 | spec: 15 | containers: 16 | - name: kerberos 17 | image: quay.io/fedora/kerberos:latest 18 | env: 19 | - name: KRB5_CONFIG 20 | value: "/etc/kerberos/krb5.conf" 21 | command: ["bash"] 22 | args: ["/etc/kerberos/start.sh"] 23 | imagePullPolicy: Always 24 | ports: 25 | - containerPort: 88 26 | - containerPort: 749 27 | volumeMounts: 28 | - name: config-volume 29 | mountPath: /etc/kerberos 30 | readOnly: true 31 | volumes: 32 | - name: config-volume 33 | configMap: 34 | name: kerberos-configmap 35 | - name: kdc-config-volume 36 | configMap: 37 | name: kerberos-kdc-configmap 38 | -------------------------------------------------------------------------------- /components/kerberos/README.md: -------------------------------------------------------------------------------- 1 | # Kerberos deployment 2 | 3 | A kerberos kubernetes deployment for development purposes. 4 | 5 | It can be deployed by running `kubectl apply -f .` 6 | -------------------------------------------------------------------------------- /components/psql/0-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: postgres 5 | labels: 6 | app: postgres 7 | data: 8 | POSTGRES_HOST: cG9zdGdyZXNxbA== #postgresql 9 | POSTGRES_DB: bWJveGRi #mboxdb 10 | POSTGRES_USER: a29qaQ== #koji 11 | POSTGRES_PASSWORD: bWJveA== #mbox 12 | -------------------------------------------------------------------------------- /components/psql/1-pvc.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: postgres 5 | labels: 6 | app: postgres 7 | spec: 8 | accessModes: 9 | - ReadWriteMany 10 | resources: 11 | requests: 12 | storage: 5Gi 13 | -------------------------------------------------------------------------------- /components/psql/2-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: postgres 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: postgres 10 | template: 11 | metadata: 12 | labels: 13 | app: postgres 14 | spec: 15 | containers: 16 | - name: postgres 17 | image: postgres:10.4 18 | imagePullPolicy: Always 19 | ports: 20 | - containerPort: 5432 21 | envFrom: 22 | - secretRef: 23 | name: postgres 24 | volumeMounts: 25 | - mountPath: /var/lib/postgresql 26 | name: postgredb 27 | volumes: 28 | - name: postgredb 29 | persistentVolumeClaim: 30 | claimName: postgres 31 | -------------------------------------------------------------------------------- /components/psql/3-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: postgresql 5 | labels: 6 | app: postgres 7 | spec: 8 | type: NodePort 9 | ports: 10 | - port: 5432 11 | selector: 12 | app: postgres 13 | -------------------------------------------------------------------------------- /components/rabbitmq/0-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: rabbitmq-ssl 5 | labels: 6 | app: rabbitmq 7 | data: 8 | RABBITMQ_SSL_CACERTFILE: L2V0Yy9wa2kvY2EtdHJ1c3Qvc291cmNlL2FuY2hvcnMvY2E= #/etc/pki/ca-trust/source/anchors/ca 9 | RABBITMQ_SSL_CERTFILE: L2V0Yy9wa2kvY2EtdHJ1c3Qvc291cmNlL2FuY2hvcnMvY2VydA== #/etc/pki/ca-trust/source/anchors/cert 10 | RABBITMQ_SSL_KEYFILE: L2V0Yy9wa2kvY2EtdHJ1c3Qvc291cmNlL2FuY2hvcnMva2V5 #/etc/pki/ca-trust/source/anchors/key 11 | RABBITMQ_SSL_VERIFY: dmVyaWZ5X25vbmU= #false -------------------------------------------------------------------------------- /components/rabbitmq/1-app.secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: rabbitmq-certs 5 | data: 6 | ca: |- 7 | Y2hhbmdlbWU= 8 | cert: |- 9 | Y2hhbmdlbWU= 10 | key: |- 11 | Y2hhbmdlbWU= 12 | --- 13 | apiVersion: v1 14 | kind: Secret 15 | metadata: 16 | name: koji-hub-msg 17 | data: 18 | koji.ca: |- 19 | Y2hhbmdlbWU= 20 | koji.crt: |- 21 | Y2hhbmdlbWU= 22 | koji.key: |- 23 | Y2hhbmdlbWU= 24 | 25 | -------------------------------------------------------------------------------- /components/rabbitmq/2-pvc.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: rabbitmq-data 5 | labels: 6 | app: rabbitmq 7 | spec: 8 | accessModes: 9 | - ReadWriteMany 10 | resources: 11 | requests: 12 | storage: 2Gi -------------------------------------------------------------------------------- /components/rabbitmq/3-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: rabbitmq 5 | labels: 6 | app: rabbitmq 7 | spec: 8 | type: NodePort 9 | ports: 10 | - port: 15672 11 | selector: 12 | app: rabbitmq -------------------------------------------------------------------------------- /components/rabbitmq/4-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: rabbitmq 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: rabbitmq 10 | template: 11 | metadata: 12 | labels: 13 | app: rabbitmq 14 | spec: 15 | containers: 16 | - name: rabbitmq 17 | image: rabbitmq:3.8 18 | imagePullPolicy: IfNotPresent 19 | ports: 20 | - containerPort: 15672 21 | env: 22 | - name: RABBITMQ_ERLANG_COOKIE 23 | value: mbox 24 | - name: RABBITMQ_NODENAME 25 | value: rabbitmq 26 | envFrom: 27 | - secretRef: 28 | name: rabbitmq-ssl 29 | volumeMounts: 30 | - mountPath: /var/lib/rabbitmq 31 | name: rabbitmq-data 32 | - name: rabbitmq-certs 33 | mountPath: /etc/pki/ca-trust/source/anchors 34 | readOnly: true 35 | volumes: 36 | - name: rabbitmq-data 37 | persistentVolumeClaim: 38 | claimName: rabbitmq-data 39 | - name: rabbitmq-certs 40 | configMap: 41 | name: rabbitmq-certs -------------------------------------------------------------------------------- /components/rabbitmq/README.md: -------------------------------------------------------------------------------- 1 | # RabbitMQ Certificates 2 | 3 | ## Generator 4 | 5 | Generate CA, server and client certificates by running: 6 | 7 | ```sh 8 | git clone https://github.com/michaelklishin/tls-gen tls-gen 9 | cd tls-gen/basic 10 | # private key password 11 | make PASSWORD=mbox 12 | make verify 13 | make info 14 | ``` 15 | 16 | Certificate files will be created in `tls-gen/basic/result/`. 17 | 18 | Copy the contents of CA, certificate and key (.key file) into the secret for both server and client configmaps. 19 | 20 | RabbitMQ can now be deployed by running `kubectl apply -f .` 21 | 22 | -------------------------------------------------------------------------------- /components/rabbitmq/playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | vars: 5 | namespace: mbbox 6 | key_size: 4096 7 | rabbitmq_host: "rabbitmq" 8 | rabbitmq_username: mbbox 9 | tasks: 10 | - name: tmp_dir.create 11 | tempfile: 12 | state: directory 13 | suffix: mbbox 14 | register: tmp_dir 15 | - name: tmp_dir.var 16 | set_fact: 17 | cert_dir: "{{ tmp_dir.path }}" 18 | 19 | - name: ca.key 20 | openssl_privatekey: 21 | path: "{{ cert_dir }}/ca_key.pem" 22 | size: "{{ key_size|int }}" 23 | - name: ca.csr 24 | openssl_csr: 25 | path: "{{ cert_dir }}/ca_req.pem" 26 | privatekey_path: "{{ cert_dir }}/ca_key.pem" 27 | common_name: "{{ rabbitmq_host }}" 28 | create_subject_key_identifier: true 29 | key_usage: 30 | - cRLSign 31 | - dataEncipherment 32 | - digitalSignature 33 | - keyCertSign 34 | - keyEncipherment 35 | - nonRepudiation 36 | basic_constraints: 37 | - 'CA:TRUE' 38 | - name: ca.crt 39 | openssl_certificate: 40 | path: "{{ cert_dir }}/ca_cert.pem" 41 | privatekey_path: "{{ cert_dir }}/ca_key.pem" 42 | csr_path: "{{ cert_dir }}/ca_req.pem" 43 | provider: selfsigned 44 | 45 | - name: server.key 46 | openssl_privatekey: 47 | path: "{{ cert_dir }}/server_key.pem" 48 | size: "{{ key_size|int }}" 49 | - name: server.csr 50 | openssl_csr: 51 | path: "{{ cert_dir }}/server_req.pem" 52 | privatekey_path: "{{ cert_dir }}/server_key.pem" 53 | common_name: "{{ rabbitmq_host }}" 54 | subject_alt_name: 55 | - "DNS:{{ rabbitmq_host }}" 56 | - "DNS:{{ rabbitmq_host }}.{{ namespace }}.svc" 57 | - "DNS:{{ rabbitmq_host }}.{{ namespace }}.svc.cluster" 58 | - name: server.crt 59 | openssl_certificate: 60 | path: "{{ cert_dir }}/server_cert.pem" 61 | csr_path: "{{ cert_dir }}/server_req.pem" 62 | ownca_path: "{{ cert_dir }}/ca_cert.pem" 63 | ownca_privatekey_path: "{{ cert_dir }}/ca_key.pem" 64 | provider: ownca 65 | 66 | - name: client.key 67 | openssl_privatekey: 68 | path: "{{ cert_dir }}/client_key.pem" 69 | size: "{{ key_size|int }}" 70 | - name: client.csr 71 | openssl_csr: 72 | path: "{{ cert_dir }}/client_req.pem" 73 | privatekey_path: "{{ cert_dir }}/client_key.pem" 74 | common_name: "{{ rabbitmq_username }}" 75 | - name: client.crt 76 | openssl_certificate: 77 | path: "{{ cert_dir }}/client_cert.pem" 78 | csr_path: "{{ cert_dir }}/client_req.pem" 79 | ownca_path: "{{ cert_dir }}/ca_cert.pem" 80 | ownca_privatekey_path: "{{ cert_dir }}/ca_key.pem" 81 | provider: ownca 82 | 83 | - name: k8s.rabbitmq.configmap(name=rabbitmq-certs) 84 | k8s: 85 | definition: 86 | apiVersion: v1 87 | kind: ConfigMap 88 | metadata: 89 | name: rabbitmq-certs 90 | namespace: "{{ namespace }}" 91 | data: 92 | ca: "{{ lookup('file', cert_dir + '/ca_cert.pem') }}" 93 | cert: "{{ lookup('file', cert_dir + '/server_cert.pem') }}" 94 | key: "{{ lookup('file', cert_dir + '/server_key.pem') }}" 95 | 96 | - name: k8s.rabbitmq.configmap(name=koji-hub-msg) 97 | k8s: 98 | definition: 99 | apiVersion: v1 100 | kind: ConfigMap 101 | metadata: 102 | name: koji-hub-msg 103 | namespace: "{{ namespace }}" 104 | data: 105 | ca: "{{ lookup('file', cert_dir + '/ca_cert.pem') }}" 106 | cert: "{{ lookup('file', cert_dir + '/client_cert.pem') }}" 107 | key: "{{ lookup('file', cert_dir + '/client_key.pem') }}" 108 | 109 | - name: k8s.rabbitmq 110 | k8s: 111 | definition: "{{ lookup('file', './' + item) }}" 112 | namespace: "{{ namespace }}" 113 | wait: true 114 | with_items: 115 | - 0-secret.yaml 116 | - 2-pvc.yaml 117 | - 4-deployment.yaml 118 | - 3-service.yaml 119 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @make clean 21 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 22 | 23 | 24 | .PHONY: clean 25 | clean: 26 | rm -rf $(BUILDDIR)/* 27 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/source/_static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/mbbox/bc7cbdb74fd9ec0071617bbcf15f32f0e44935ac/docs/source/_static/.gitkeep -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'mbox-operator' 21 | copyright = '2019, Red Hat, Inc. and others' 22 | author = 'Red Hat, Inc. and others' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = '0.0.1' 26 | 27 | 28 | # -- General configuration --------------------------------------------------- 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | "sphinx.ext.autosummary", 35 | "sphinx.ext.doctest", 36 | "sphinx.ext.intersphinx", 37 | "sphinx.ext.viewcode", 38 | "sphinx.ext.napoleon" 39 | ] 40 | 41 | autosummary_generate = True 42 | 43 | # Add any paths that contain templates here, relative to this directory. 44 | templates_path = ['_templates'] 45 | 46 | # source_suffix = ['.rst', '.md'] 47 | source_suffix = ".rst" 48 | 49 | # The master toctree document. 50 | master_doc = "index" 51 | 52 | 53 | # List of patterns, relative to source directory, that match files and 54 | # directories to ignore when looking for source files. 55 | # This pattern also affects html_static_path and html_extra_path. 56 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 57 | 58 | 59 | # -- Options for HTML output ------------------------------------------------- 60 | 61 | # The theme to use for HTML and HTML Help pages. See the documentation for 62 | # a list of builtin themes. 63 | # 64 | html_theme = 'alabaster' 65 | 66 | html_theme_options = { 67 | "logo_name": True, 68 | "github_user": "fedora-infra", 69 | "github_repo": "mbbox", 70 | "page_width": "1040px", 71 | } 72 | 73 | # Add any paths that contain custom static files (such as style sheets) here, 74 | # relative to this directory. They are copied after the builtin static files, 75 | # so a file named "default.css" will overwrite the builtin "default.css". 76 | html_static_path = ['_static'] -------------------------------------------------------------------------------- /docs/source/contributing.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Contributing 3 | ============ 4 | 5 | Mbox welcomes contributions! Our issue tracker is located on `GitHub `_. 6 | 7 | Guidelines 8 | =========== 9 | 10 | When you make a pull request, someone from the fedora organization 11 | will review your code. Please make sure you follow the guidelines below: 12 | 13 | Code Style 14 | ---------- 15 | 16 | Make sure your yaml code passes our yamllint rules. 17 | 18 | E2E Tests 19 | --------- 20 | 21 | Every change should be tested in molecule, which is the tool we use for E2E (end to end) testing. 22 | 23 | Tests can be run using either molecule or operator-sdk cli (which uses molecule as well). 24 | 25 | .. code-block:: bash 26 | 27 | molecule test -s test-local #local tests, no need for a cluster 28 | molecule test -s test-cluster #needs a remote cluster, minikube is enough 29 | 30 | Debugging Local Tests 31 | --------------------- 32 | 33 | If you encounter any error when running test you can debug the issue by connecting to local instance of kubernetes running in docker: 34 | 35 | .. code-block:: bash 36 | 37 | molecule converge -s test-local #runs local test without destroy sequence 38 | docker exec -it kind-test-local bash #get inside the container created in previous step 39 | kubectl config set-context --current --namespace=osdk-test #sets namespace to operator-sdk 40 | 41 | Here are few useful commands for debugging, for another commands look at `kubectl help`: 42 | 43 | .. code-block:: bash 44 | 45 | kubectl get all #returns all resources in the current namespace 46 | kubectl logs #shows logs for specific 47 | kubectl logs ansible #shows ansible logs for 48 | kubectl describe #shows detailed information about specific 49 | kubectl get ingress #returns all ingress resources, is not part of get all 50 | 51 | Troubleshooting 52 | --------------- 53 | 54 | During the development, we encountered some issues when debugging operator deployment. We will try to document them in this section, together with solutions. 55 | 56 | Issue: Timeout in reconciliation task 57 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 58 | 59 | This was caused by low space, because failing tests aren't removing docker volumes when they fails. To remove the volumes run following command `docker volume prune`. 60 | 61 | Issue: Can't reach service from the pod in minikube 62 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 63 | 64 | This issue is caused by network problem inside docker running minikube cluster. You can encounter this issue in vagrant when trying to access the service from pod which 65 | is linked to the service. 66 | 67 | To fix this just run the following: 68 | 69 | .. code-block:: bash 70 | 71 | minikube ssh 72 | sudo ip link set docker0 promisc on 73 | 74 | Environment 75 | =========== 76 | 77 | We are providing a full development environment in Vagrant but you can use your host machine as long as you meet the following requirements: 78 | 79 | * ansible >= 2.9 80 | * molecule >= 3 81 | * yamllint >= 1.20 82 | * python kubernetes and openshift libraries 83 | * operator-sdk >= 0.16 84 | * docker >= 19 85 | 86 | NOTE: make sure both ansible and molecule are system-wide installed using in the same python interpreter otherwise you may have issues running tests. 87 | 88 | Setting Up Vagrant Environment 89 | ------------------------------ 90 | 91 | To start the vagrant operator SDK box, run the following in project root: 92 | 93 | .. code-block:: bash 94 | 95 | vagrant up #starts the vagrant VM, it could take a while 96 | vagrant reload #this is needed to remount the sshfs mounts after reboot when cgroups are changed to V1 97 | vagrant ssh #connects you to the vagrant VM 98 | 99 | In vagrant VM you can find project folder in `~/devel`. 100 | To run the tests do `cd ~/devel/mbox-operator` and follow `E2E Tests`_ section. 101 | 102 | If you encounter any issue with `vagrant up` command, do `vagrant destroy` to be sure that there isn't any leftover from previous run. 103 | -------------------------------------------------------------------------------- /docs/source/deployment-guide.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | Deployment Guide 3 | ================ 4 | 5 | This guide describes manual deployment process of MBBox operator in OpenShift 4 and Kubernetes Cluster. 6 | 7 | Requirements 8 | ============ 9 | 10 | To be able to deploy MBBox operator manually you need to have admin rights to cluster. Otherwise you will not be able to deploy CRDs, roles, role bindings or service accounts. 11 | 12 | To be able to deploy just the CR files you only need admin rights to namespace where you want to deploy operator. 13 | 14 | Some commands require the usage of the "kustomize" CLI tool which an be found `here `_. 15 | 16 | Makefile 17 | ======== 18 | 19 | We have a `Makefile `_ for you ready to be used. 20 | 21 | Prepare MBBox deployment 22 | ======================== 23 | 24 | To prepare cluster for MBBox deployment you just need to run following commands with the Makefile mentioned earlier in this guide. 25 | 26 | .. code-block:: bash 27 | 28 | make install 29 | make deploy 30 | 31 | This will apply CRDs files for MBBox and create roles, role bindings, service accounts and deploy the mbbox operator. 32 | 33 | Create PVCs 34 | =========== 35 | 36 | For deployment of the MBBox operator you need to prepare 2 PVCs. In case you are allowed to create PVCs this could be configured in CR files for koji-hub and mbox itself and they will be generated automatically based on the configuration. Otherwise you need to create them manually beforehand. 37 | 38 | Most of the components are using Koji shared mount point. Check if the name of PVC is same in each component CR file otherwise the deployment will fail. 39 | 40 | Prepare PostgreSQL DB 41 | ===================== 42 | 43 | In case you have PostgreSQL DB running in cluster you can skip this step and just use the existing one. 44 | 45 | To deploy PostgreSQL DB you can use the one `prepared by us `__. You can change anything in those files, especially secret file. To deploy it run the following. 46 | 47 | .. code-block:: bash 48 | 49 | kubectl apply -f components/psql -n 50 | 51 | Prepare RabbitMQ server 52 | ======================= 53 | 54 | In case you have a running RabbitMQ server in your cluster, you can skip this step and just use the existing one. 55 | 56 | To deploy RabbitMQ you can use the one `prepared by us `__. You can change anything in those files, especially secret file. Refer to the `README.md` file for instructions about certificates. To deploy it run the following. 57 | 58 | .. code-block:: bash 59 | 60 | kubectl apply -f components/rabbitmq -n 61 | 62 | .. note:: 63 | Right now only Koji is emitting `Fedora messaging `_ messages, which needs the RabbitMQ server. 64 | 65 | CR Deployment 66 | ============= 67 | 68 | Before deploying CR check the variables configuration. Please refer to :ref:`user-guide-label` for information about variables. 69 | 70 | A full deployment needs to deploy a couple of CRs in order, `kustomize` can be used to achieve that: 71 | 72 | .. code-block:: bash 73 | 74 | kustomize build config/samples | kubectl apply -f - 75 | 76 | Delete Operator deployment 77 | ========================== 78 | 79 | To delete operator deployment simply run: 80 | 81 | .. code-block:: bash 82 | 83 | kustomize build config/samples | kubectl delete -f - 84 | make undeploy # This will delete the operator 85 | make uninstall # this will uninstall CRDs, roles, etc 86 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. mbox-operator documentation master file, created by 2 | sphinx-quickstart on Thu Apr 23 13:01:40 2020. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | mbox-operator 7 | ============= 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | user-guide/index 14 | deployment-guide 15 | contributing 16 | 17 | 18 | 19 | Module Building in a Box (MBBOX) Kubernetes Operator 20 | 21 | MBOX is a kubernetes operator used to set up a buildsystem that can be used for Fedora/RHEL Modular packages, based on Koji and Module Build Service. 22 | 23 | The intention is for it to be trivially simple to get started with both, but also allow the same setup to be used for a production setup. 24 | -------------------------------------------------------------------------------- /docs/source/user-guide/index.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | User Guide 3 | ========== 4 | 5 | .. _user-guide-label: 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | :caption: Contents: 10 | 11 | koji-hub 12 | koji-builder 13 | kojira 14 | mbs-backend 15 | mbs-frontend 16 | mbox 17 | -------------------------------------------------------------------------------- /example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | project_name: mbox 3 | template_dir: ./components 4 | state_dir: ./state 5 | ca: 6 | built_in: yes 7 | directory: na 8 | database: 9 | built_in: persistent 10 | storage: 11 | mnt_koji_volname: "" 12 | persistent_storage: yes 13 | koji_hub: 14 | public_hostname: koji.mbox.test 15 | admin_username: admin 16 | kojira: 17 | username: kojira 18 | builder: 19 | built_in: yes 20 | identity: 21 | built_in: yes 22 | public_hostname: identity.mbox.test 23 | etc_ipsilon_volname: "" 24 | mbs: 25 | public_hostname: mbs.mbox.test 26 | -------------------------------------------------------------------------------- /images/identity/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:31 2 | 3 | ENV PSQL_USER=mbox \ 4 | PSQL_PASS=mbox \ 5 | PSQL_HOST=postgre \ 6 | PSQL_DB=mbox-identity 7 | 8 | RUN dnf install -y ipsilon ipsilon-openidc python2-psycopg2 curl httpd mod_ssl python3-mod_wsgi 9 | 10 | COPY start.sh /etc/ipsilon-cfg/start.sh 11 | RUN chmod +x /etc/ipsilon-cfg/start.sh && \ 12 | chown -R 1001:root /etc/ipsilon-cfg 13 | RUN printf "def fix_user_dirs(*args, **kwargs):\n pass\n" >>/usr/lib/python3.7/site-packages/ipsilon/tools/files.py 14 | 15 | COPY cfgprofile /etc/ipsilon-cfg/cfgprofile 16 | RUN mkdir /etc/ipsilon/{httpd,ipsilon,data} && \ 17 | LOGFILE=/dev/stdout ipsilon-server-install --config-profile=/etc/ipsilon-cfg/cfgprofile 18 | 19 | EXPOSE 8443 20 | 21 | ENTRYPOINT /etc/ipsilon-cfg/start.sh -------------------------------------------------------------------------------- /images/identity/cfgprofile: -------------------------------------------------------------------------------- 1 | [globals] 2 | datadir = /etc/ipsilon/data 3 | httpdconfd = /etc/ipsilon/httpd 4 | confdir = /etc/ipsilon/ipsilon 5 | 6 | [arguments] 7 | ignored_database_url = postgresql://%(PSQL_USER):%(PSQL_PASS)@%(PSQL_HOST)/%(PSQL_DB) 8 | admin_user = admin 9 | gssapi = no 10 | ipa = no 11 | port = 8443 12 | testauth = yes 13 | openidc = yes 14 | hostname = identity.mbox.test 15 | server_debugging = True 16 | root_instance = yes 17 | instance = root 18 | pam = no -------------------------------------------------------------------------------- /images/identity/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -xe 3 | 4 | mkdir /httpdir/run || rm -rf /httpdir/run/* 5 | ln -s /etc/httpd/modules /httpdir/modules 6 | truncate --size=0 /httpdir/accesslog /httpdir/errorlog 7 | ulimit -c 0 8 | 9 | exec httpd -f /etc/ipsilon-cfg/httpd/httpd.conf -DFOREGROUND -DNO_DETACH -------------------------------------------------------------------------------- /images/kerberos/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:33 2 | 3 | RUN dnf install -y krb5-libs krb5-server krb5-workstation expect 4 | 5 | EXPOSE 88 6 | EXPOSE 749 -------------------------------------------------------------------------------- /images/koji-builder/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:8 2 | 3 | RUN yum install -y epel-release && \ 4 | yum install -y koji-builder 5 | 6 | COPY entrypoint.sh /entrypoint.sh 7 | RUN chmod +x /entrypoint.sh && \ 8 | chown 1001:root /entrypoint.sh 9 | 10 | ENV USER=1001 11 | 12 | ENTRYPOINT bash /entrypoint.sh 13 | 14 | USER 1001 -------------------------------------------------------------------------------- /images/koji-builder/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | update-ca-trust 4 | exec /usr/sbin/kojid --fg --force-lock --verbose 5 | -------------------------------------------------------------------------------- /images/koji-hub/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:8 2 | 3 | RUN yum install -y epel-release 4 | RUN yum install -y \ 5 | koji koji-hub koji-web koji-hub-plugins \ 6 | curl httpd mod_ssl postgresql fedora-messaging python3-mod_wsgi 7 | 8 | RUN curl https://pagure.io/fedora-infra/ansible/raw/master/f/roles/koji_hub/templates/fedmsg-koji-plugin.py -o /usr/lib/koji-hub-plugins/fedmsg-koji-plugin.py 9 | RUN rm -f /etc/kojiweb/web.conf && \ 10 | ln -s /etc/koji-hub/kojiweb.conf /etc/kojiweb/web.conf 11 | RUN chown -R 1001:root /etc/koji-hub && \ 12 | chown -R 1001:root /etc/pki/tls 13 | RUN mkdir -p /var/cache/kojihub && \ 14 | chown -R 1001:root /var/cache/kojihub 15 | 16 | COPY readiness.sh /readiness.sh 17 | COPY entrypoint.sh /entrypoint.sh 18 | 19 | RUN chmod +x /entrypoint.sh /readiness.sh && \ 20 | chown 1001:root /entrypoint.sh /readiness.sh 21 | 22 | ENV USER=1001 23 | 24 | EXPOSE 8443 25 | 26 | ENTRYPOINT bash /entrypoint.sh 27 | 28 | USER 1001 29 | -------------------------------------------------------------------------------- /images/koji-hub/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "${KOJI_HUB_CA_CERT_PATH}" == "" ]; then 4 | KOJI_HUB_CA_CERT_PATH="/etc/cacert/cert" 5 | fi 6 | 7 | ln -s ${KOJI_HUB_CA_CERT_PATH} /etc/pki/tls/certs/`openssl x509 -hash -noout -in ${KOJI_HUB_CA_CERT_PATH}`.0 8 | update-ca-trust 9 | 10 | if [ ! -f "/var/cache/kojihub/.dbschema" ]; then 11 | PGPASSWORD="${POSTGRES_PASSWORD}" psql \ 12 | -h ${POSTGRES_HOST} \ 13 | -U ${POSTGRES_USER} \ 14 | -W ${POSTGRES_DB} < /usr/share/doc/koji/docs/schema.sql 15 | 16 | touch /var/cache/kojihub/.dbschema 17 | fi 18 | 19 | mkdir -p /httpdir/run/ 20 | ln -s /usr/lib64/httpd/modules /httpdir/modules 21 | truncate --size=0 /httpdir/accesslog /httpdir/errorlog 22 | tail -qf /httpdir/accesslog /httpdir/errorlog & 23 | ulimit -c 0 24 | mkdir -p /mnt/koji/{packages,repos,work,scratch,repos-dist} 25 | exec httpd -f /etc/koji-hub/httpd.conf -DFOREGROUND -DNO_DETACH 26 | -------------------------------------------------------------------------------- /images/koji-hub/readiness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BODY='system.listMethods' 4 | 5 | res=$(curl \ 6 | -X POST \ 7 | -H 'Content-Type: text/xml' \ 8 | -d "$BODY" \ 9 | http://127.0.0.1:8080/kojihub/) 10 | 11 | if [ "$?" != '0' ] 12 | then 13 | exit 1 14 | fi 15 | 16 | if [ "$res" == '**' ] 17 | then 18 | echo $res 19 | exit 1 20 | fi 21 | 22 | echo $http_code 23 | 24 | exit 0 -------------------------------------------------------------------------------- /images/koji-hub/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: postgresql 5 | labels: 6 | app: postgres 7 | spec: 8 | type: NodePort 9 | ports: 10 | - port: 5432 11 | selector: 12 | app: postgres 13 | -------------------------------------------------------------------------------- /images/kojira/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:8 2 | 3 | RUN yum install -y epel-release 4 | RUN yum install -y koji-utils 5 | 6 | COPY entrypoint.sh /entrypoint.sh 7 | 8 | ENV USER=1001 9 | 10 | ENTRYPOINT /entrypoint.sh 11 | -------------------------------------------------------------------------------- /images/kojira/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec /usr/sbin/kojira --fg --verbose --force-lock 4 | -------------------------------------------------------------------------------- /images/mbs-backend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:33 2 | 3 | RUN yum install -y module-build-service python3-psycopg2 python3-fedmsg 4 | 5 | RUN mkdir /etc/mbs-backend && \ 6 | chown -R 1001:root /etc/mbs-backend 7 | 8 | COPY entrypoint.sh /entrypoint.sh 9 | COPY mbs-scheduler.py /etc/mbs-backend/mbs-scheduler.py 10 | 11 | ENV USER=1001 12 | 13 | ENTRYPOINT /entrypoint.sh 14 | -------------------------------------------------------------------------------- /images/mbs-backend/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Start the fedmsg-hub 4 | echo "Starting fedmsg-hub" 5 | exec /usr/bin/fedmsg-hub-3 6 | 7 | -------------------------------------------------------------------------------- /images/mbs-backend/mbs-scheduler.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | def str2bool(v): 4 | return v.lower() in ['true', 't', '1', 'yes', 'y'] 5 | 6 | 7 | config = { 8 | 'mbsconsumer': str2bool(os.environ.get('MBS_CONSUMER', 'true')), 9 | 'mbspoller': str2bool(os.environ.get('MBS_POLLER', 'true')), 10 | } 11 | -------------------------------------------------------------------------------- /images/mbs-frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:33 2 | 3 | RUN yum install -y module-build-service python3-psycopg2 httpd python3-mod_wsgi mod_ssl 4 | 5 | COPY entrypoint.sh /entrypoint.sh 6 | COPY mbs.wsgi /mbs.wsgi 7 | RUN chmod +x /entrypoint.sh 8 | 9 | ENV USER=1001 10 | EXPOSE 8443 11 | 12 | ENTRYPOINT /entrypoint.sh 13 | -------------------------------------------------------------------------------- /images/mbs-frontend/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | update-ca-trust 4 | mkdir -p /httpdir/run 5 | ln -s /usr/lib64/httpd/modules /httpdir/modules 6 | truncate --size=0 /httpdir/accesslog /httpdir/errorlog 7 | tail -qf /httpdir/accesslog /httpdir/errorlog & 8 | ulimit -c 0 9 | exec httpd -f /etc/mbs-frontend/httpd.conf -DFOREGROUND -DNO_DETACH 10 | -------------------------------------------------------------------------------- /images/mbs-frontend/mbs.wsgi: -------------------------------------------------------------------------------- 1 | import logging 2 | logging.basicConfig(level=logging.DEBUG) 3 | from module_build_service import app as application -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import logging 4 | 5 | import mbox.ca 6 | import mbox.state 7 | 8 | 9 | def parse_args(): 10 | parser = argparse.ArgumentParser(description="Modular Builder in a Box") 11 | parser.add_argument("config_file", default="./mbox.yml", 12 | help="Configuration file path") 13 | parser.add_argument("--debug", action='store_true', default=False, 14 | help='Enable debugging') 15 | parser.add_argument("--force-update", action='append', default=[], 16 | help="Force this component to be updated") 17 | # TODO 18 | return parser.parse_known_args() 19 | 20 | 21 | def main(): 22 | args, extra = parse_args() 23 | if args.debug: 24 | logging.basicConfig(level=logging.DEBUG) 25 | else: 26 | logging.basicConfig(level=logging.INFO) 27 | logger = logging.getLogger("main") 28 | 29 | logger.debug("Initializing objects") 30 | state = mbox.state.State( 31 | config_file=args.config_file, 32 | print_oc_output=args.debug, 33 | ) 34 | 35 | logger.debug("Running OC test") 36 | state.oc_test() 37 | 38 | if len(extra) > 0 and extra[0] == 'koji': 39 | out = state.client.run_koji_command(capture=False, *extra[1:]) 40 | print("Retcode: %s" % out.returncode) 41 | print("Stdout: %s" % out.stdout) 42 | print("Stderr: %s" % out.stderr) 43 | return 44 | 45 | state.build_all() 46 | state.ensure_all( 47 | forced=args.force_update, 48 | ) 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /mbox-operator/.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | # Based on ansible-lint config 3 | extends: default 4 | 5 | rules: 6 | braces: 7 | max-spaces-inside: 1 8 | level: error 9 | brackets: 10 | max-spaces-inside: 1 11 | level: error 12 | colons: 13 | max-spaces-after: -1 14 | level: error 15 | commas: 16 | max-spaces-after: -1 17 | level: error 18 | comments: disable 19 | comments-indentation: disable 20 | document-start: disable 21 | empty-lines: 22 | max: 3 23 | level: error 24 | hyphens: 25 | level: error 26 | indentation: disable 27 | key-duplicates: enable 28 | line-length: disable 29 | new-line-at-end-of-file: disable 30 | new-lines: 31 | type: unix 32 | trailing-spaces: disable 33 | truthy: disable 34 | -------------------------------------------------------------------------------- /mbox-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/operator-framework/ansible-operator:v1.0.1 2 | 3 | USER root 4 | RUN dnf install gcc libpq libpq-devel python3-devel krb5-devel -y 5 | RUN pip3.6 install psycopg2 koji 6 | USER ${USER_ID} 7 | 8 | COPY requirements.yml ${HOME}/requirements.yml 9 | RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ 10 | && chmod -R ug+rwx ${HOME}/.ansible 11 | 12 | COPY watches.yaml ${HOME}/watches.yaml 13 | COPY roles/ ${HOME}/roles/ 14 | COPY playbooks/ ${HOME}/playbooks/ 15 | -------------------------------------------------------------------------------- /mbox-operator/Makefile: -------------------------------------------------------------------------------- 1 | # Container image to use 2 | IMG = quay.io/fedora/mbox-operator:latest 3 | # Current Operator version 4 | VERSION ?= 0.0.1 5 | # Default bundle image tag 6 | BUNDLE_IMG ?= controller-bundle:$(VERSION) 7 | # Options for 'bundle-build' 8 | ifneq ($(origin CHANNELS), undefined) 9 | BUNDLE_CHANNELS := --channels=$(CHANNELS) 10 | endif 11 | ifneq ($(origin DEFAULT_CHANNEL), undefined) 12 | BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) 13 | endif 14 | BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) 15 | 16 | # Image URL to use all building/pushing image targets 17 | IMG ?= controller:latest 18 | 19 | all: docker-build 20 | 21 | # Run against the configured Kubernetes cluster in ~/.kube/config 22 | run: ansible-operator 23 | $(ANSIBLE_OPERATOR) run 24 | 25 | # Install CRDs into a cluster 26 | install: kustomize 27 | $(KUSTOMIZE) build config/crd | kubectl apply -f - 28 | 29 | # Uninstall CRDs from a cluster 30 | uninstall: kustomize 31 | $(KUSTOMIZE) build config/crd | kubectl delete -f - 32 | 33 | # Deploy controller in the configured Kubernetes cluster in ~/.kube/config 34 | deploy: kustomize 35 | cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} 36 | $(KUSTOMIZE) build config/default | kubectl apply -f - 37 | 38 | # Undeploy controller in the configured Kubernetes cluster in ~/.kube/config 39 | undeploy: kustomize 40 | $(KUSTOMIZE) build config/default | kubectl delete -f - 41 | 42 | # Build the docker image 43 | docker-build: 44 | docker build . -t ${IMG} 45 | 46 | # Push the docker image 47 | docker-push: 48 | docker push ${IMG} 49 | 50 | PATH := $(PATH):$(PWD)/bin 51 | SHELL := env PATH=$(PATH) /bin/sh 52 | OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') 53 | ARCH = $(shell uname -m | sed 's/x86_64/amd64/') 54 | OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') 55 | ARCHOPER = $(shell uname -m ) 56 | 57 | kustomize: 58 | ifeq (, $(shell which kustomize 2>/dev/null)) 59 | @{ \ 60 | set -e ;\ 61 | mkdir -p bin ;\ 62 | curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ 63 | } 64 | KUSTOMIZE=$(realpath ./bin/kustomize) 65 | else 66 | KUSTOMIZE=$(shell which kustomize) 67 | endif 68 | 69 | ansible-operator: 70 | ifeq (, $(shell which ansible-operator 2>/dev/null)) 71 | @{ \ 72 | set -e ;\ 73 | mkdir -p bin ;\ 74 | curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.0.1/ansible-operator-v1.0.1-$(ARCHOPER)-$(OSOPER) ;\ 75 | mv ansible-operator-v1.0.1-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ 76 | chmod +x ./bin/ansible-operator ;\ 77 | } 78 | ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator) 79 | else 80 | ANSIBLE_OPERATOR=$(shell which ansible-operator) 81 | endif 82 | 83 | # Generate bundle manifests and metadata, then validate generated files. 84 | .PHONY: bundle 85 | bundle: kustomize 86 | operator-sdk generate kustomize manifests -q 87 | cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) 88 | $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) 89 | operator-sdk bundle validate ./bundle 90 | 91 | # Build the bundle image. 92 | .PHONY: bundle-build 93 | bundle-build: 94 | docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . 95 | -------------------------------------------------------------------------------- /mbox-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: fedoraproject.org 2 | layout: ansible.sdk.operatorframework.io/v1 3 | projectName: mbox-operator 4 | resources: 5 | - group: apps 6 | kind: MBKojiBuilder 7 | version: v1alpha1 8 | - group: apps 9 | kind: MBKojiHub 10 | version: v1alpha1 11 | - group: apps 12 | kind: MBKojira 13 | version: v1alpha1 14 | - group: apps 15 | kind: MBMbsBackend 16 | version: v1alpha1 17 | - group: apps 18 | kind: MBMbsFrontend 19 | version: v1alpha1 20 | - group: apps 21 | kind: Mbox 22 | version: v1alpha1 23 | version: 3-alpha 24 | -------------------------------------------------------------------------------- /mbox-operator/config/crd/bases/apps.fedoraproject.org_mbkojibuilders.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: mbkojibuilders.apps.fedoraproject.org 6 | spec: 7 | group: apps.fedoraproject.org 8 | names: 9 | kind: MBKojiBuilder 10 | listKind: MBKojiBuilderList 11 | plural: mbkojibuilders 12 | singular: mbkojibuilder 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: MBKojiBuilder is the Schema for the mbkojibuilders API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of MBKojiBuilder 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of MBKojiBuilder 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /mbox-operator/config/crd/bases/apps.fedoraproject.org_mbkojihubs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: mbkojihubs.apps.fedoraproject.org 6 | spec: 7 | group: apps.fedoraproject.org 8 | names: 9 | kind: MBKojiHub 10 | listKind: MBKojiHubList 11 | plural: mbkojihubs 12 | singular: mbkojihub 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: MBKojiHub is the Schema for the mbkojihubs API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of MBKojiHub 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of MBKojiHub 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /mbox-operator/config/crd/bases/apps.fedoraproject.org_mbkojiras.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: mbkojiras.apps.fedoraproject.org 6 | spec: 7 | group: apps.fedoraproject.org 8 | names: 9 | kind: MBKojira 10 | listKind: MBKojiraList 11 | plural: mbkojiras 12 | singular: mbkojira 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: MBKojira is the Schema for the mbkojiras API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of MBKojira 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of MBKojira 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /mbox-operator/config/crd/bases/apps.fedoraproject.org_mbmbsbackends.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: mbmbsbackends.apps.fedoraproject.org 6 | spec: 7 | group: apps.fedoraproject.org 8 | names: 9 | kind: MBMbsBackend 10 | listKind: MBMbsBackendList 11 | plural: mbmbsbackends 12 | singular: mbmbsbackend 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: MBMbsBackend is the Schema for the mbmbsbackends API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of MBMbsBackend 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of MBMbsBackend 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /mbox-operator/config/crd/bases/apps.fedoraproject.org_mbmbsfrontends.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: mbmbsfrontends.apps.fedoraproject.org 6 | spec: 7 | group: apps.fedoraproject.org 8 | names: 9 | kind: MBMbsFrontend 10 | listKind: MBMbsFrontendList 11 | plural: mbmbsfrontends 12 | singular: mbmbsfrontend 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: MBMbsFrontend is the Schema for the mbmbsfrontends API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of MBMbsFrontend 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of MBMbsFrontend 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /mbox-operator/config/crd/bases/apps.fedoraproject.org_mboxes.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: mboxes.apps.fedoraproject.org 6 | spec: 7 | group: apps.fedoraproject.org 8 | names: 9 | kind: Mbox 10 | listKind: MboxList 11 | plural: mboxes 12 | singular: mbox 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: Mbox is the Schema for the mboxes API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of Mbox 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of Mbox 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /mbox-operator/config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/apps.fedoraproject.org_mbkojihubs.yaml 6 | - bases/apps.fedoraproject.org_mbkojibuilders.yaml 7 | - bases/apps.fedoraproject.org_mbkojiras.yaml 8 | - bases/apps.fedoraproject.org_mbmbsbackends.yaml 9 | - bases/apps.fedoraproject.org_mbmbsfrontends.yaml 10 | - bases/apps.fedoraproject.org_mboxes.yaml 11 | # +kubebuilder:scaffold:crdkustomizeresource 12 | -------------------------------------------------------------------------------- /mbox-operator/config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: mbox-operator-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: mbox-operator- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../crd 17 | - ../rbac 18 | - ../manager 19 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 20 | #- ../prometheus 21 | 22 | patchesStrategicMerge: 23 | # Protect the /metrics endpoint by putting it behind auth. 24 | # If you want your controller-manager to expose the /metrics 25 | # endpoint w/o any authn/z, please comment the following line. 26 | - manager_auth_proxy_patch.yaml 27 | -------------------------------------------------------------------------------- /mbox-operator/config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: kube-rbac-proxy 13 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 14 | args: 15 | - "--secure-listen-address=0.0.0.0:8443" 16 | - "--upstream=http://127.0.0.1:8080/" 17 | - "--logtostderr=true" 18 | - "--v=10" 19 | ports: 20 | - containerPort: 8443 21 | name: https 22 | - name: manager 23 | args: 24 | - "--metrics-addr=127.0.0.1:8080" 25 | - "--enable-leader-election" 26 | - "--leader-election-id=mbox-operator" 27 | -------------------------------------------------------------------------------- /mbox-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | images: 6 | - name: controller 7 | newName: quay.io/fedora/mbox-operator 8 | newTag: latest 9 | -------------------------------------------------------------------------------- /mbox-operator/config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: system 7 | --- 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | metadata: 11 | name: controller-manager 12 | namespace: system 13 | labels: 14 | control-plane: controller-manager 15 | spec: 16 | selector: 17 | matchLabels: 18 | control-plane: controller-manager 19 | replicas: 1 20 | template: 21 | metadata: 22 | labels: 23 | control-plane: controller-manager 24 | spec: 25 | containers: 26 | - name: manager 27 | args: 28 | - "--enable-leader-election" 29 | - "--leader-election-id=mbox-operator" 30 | image: controller:latest 31 | terminationGracePeriodSeconds: 10 32 | -------------------------------------------------------------------------------- /mbox-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /mbox-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | selector: 15 | matchLabels: 16 | control-plane: controller-manager 17 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - role.yaml 3 | - role_binding.yaml 4 | - leader_election_role.yaml 5 | - leader_election_role_binding.yaml 6 | # Comment the following 4 lines if you want to disable 7 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 8 | # which protects your /metrics endpoint. 9 | - auth_proxy_service.yaml 10 | - auth_proxy_role.yaml 11 | - auth_proxy_role_binding.yaml 12 | - auth_proxy_client_clusterrole.yaml 13 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - events 23 | verbs: 24 | - create 25 | - patch 26 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbkojibuilder_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit mbkojibuilders. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbkojibuilder-editor-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbkojibuilders 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - apps.fedoraproject.org 21 | resources: 22 | - mbkojibuilders/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbkojibuilder_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view mbkojibuilders. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbkojibuilder-viewer-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbkojibuilders 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - apps.fedoraproject.org 17 | resources: 18 | - mbkojibuilders/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbkojihub_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit mbkojihubs. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbkojihub-editor-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbkojihubs 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - apps.fedoraproject.org 21 | resources: 22 | - mbkojihubs/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbkojihub_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view mbkojihubs. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbkojihub-viewer-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbkojihubs 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - apps.fedoraproject.org 17 | resources: 18 | - mbkojihubs/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbkojira_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit mbkojiras. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbkojira-editor-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbkojiras 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - apps.fedoraproject.org 21 | resources: 22 | - mbkojiras/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbkojira_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view mbkojiras. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbkojira-viewer-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbkojiras 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - apps.fedoraproject.org 17 | resources: 18 | - mbkojiras/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbmbsbackend_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit mbmbsbackends. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbmbsbackend-editor-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbmbsbackends 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - apps.fedoraproject.org 21 | resources: 22 | - mbmbsbackends/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbmbsbackend_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view mbmbsbackends. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbmbsbackend-viewer-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbmbsbackends 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - apps.fedoraproject.org 17 | resources: 18 | - mbmbsbackends/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbmbsfrontend_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit mbmbsfrontends. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbmbsfrontend-editor-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbmbsfrontends 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - apps.fedoraproject.org 21 | resources: 22 | - mbmbsfrontends/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbmbsfrontend_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view mbmbsfrontends. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbmbsfrontend-viewer-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mbmbsfrontends 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - apps.fedoraproject.org 17 | resources: 18 | - mbmbsfrontends/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbox_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit mboxes. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbox-editor-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mboxes 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - apps.fedoraproject.org 21 | resources: 22 | - mboxes/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/mbox_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view mboxes. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: mbox-viewer-role 6 | rules: 7 | - apiGroups: 8 | - apps.fedoraproject.org 9 | resources: 10 | - mboxes 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - apps.fedoraproject.org 17 | resources: 18 | - mboxes/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: manager-role 6 | rules: 7 | ## 8 | ## Base operator rules 9 | ## 10 | - apiGroups: 11 | - route.openshift.io 12 | resources: 13 | - routes 14 | verbs: 15 | - '*' 16 | - apiGroups: 17 | - networking.k8s.io 18 | resources: 19 | - ingresses 20 | verbs: 21 | - '*' 22 | - apiGroups: 23 | - "" 24 | resources: 25 | - secrets 26 | - configmaps 27 | - services 28 | - services/finalizers 29 | - pods 30 | - pods/exec 31 | - pods/log 32 | - endpoints 33 | - persistentvolumeclaims 34 | - events 35 | verbs: 36 | - create 37 | - delete 38 | - get 39 | - list 40 | - patch 41 | - update 42 | - watch 43 | - apiGroups: 44 | - apps 45 | resources: 46 | - deployments 47 | - daemonsets 48 | - replicasets 49 | - statefulsets 50 | verbs: 51 | - create 52 | - delete 53 | - get 54 | - list 55 | - patch 56 | - update 57 | - watch 58 | ## 59 | ## Rules for apps.fedoraproject.org/v1alpha1, Kind: MBKojiBuilder 60 | ## 61 | - apiGroups: 62 | - apps.fedoraproject.org 63 | resources: 64 | - mbkojibuilders 65 | - mbkojibuilders/status 66 | - mbkojibuilders/finalizers 67 | verbs: 68 | - create 69 | - delete 70 | - get 71 | - list 72 | - patch 73 | - update 74 | - watch 75 | ## 76 | ## Rules for apps.fedoraproject.org/v1alpha1, Kind: MBKojiHub 77 | ## 78 | - apiGroups: 79 | - apps.fedoraproject.org 80 | resources: 81 | - mbkojihubs 82 | - mbkojihubs/status 83 | - mbkojihubs/finalizers 84 | verbs: 85 | - create 86 | - delete 87 | - get 88 | - list 89 | - patch 90 | - update 91 | - watch 92 | ## 93 | ## Rules for apps.fedoraproject.org/v1alpha1, Kind: MBKojira 94 | ## 95 | - apiGroups: 96 | - apps.fedoraproject.org 97 | resources: 98 | - mbkojiras 99 | - mbkojiras/status 100 | - mbkojiras/finalizers 101 | verbs: 102 | - create 103 | - delete 104 | - get 105 | - list 106 | - patch 107 | - update 108 | - watch 109 | ## 110 | ## Rules for apps.fedoraproject.org/v1alpha1, Kind: MBMbsBackend 111 | ## 112 | - apiGroups: 113 | - apps.fedoraproject.org 114 | resources: 115 | - mbmbsbackends 116 | - mbmbsbackends/status 117 | - mbmbsbackends/finalizers 118 | verbs: 119 | - create 120 | - delete 121 | - get 122 | - list 123 | - patch 124 | - update 125 | - watch 126 | ## 127 | ## Rules for apps.fedoraproject.org/v1alpha1, Kind: MBMbsFrontend 128 | ## 129 | - apiGroups: 130 | - apps.fedoraproject.org 131 | resources: 132 | - mbmbsfrontends 133 | - mbmbsfrontends/status 134 | - mbmbsfrontends/finalizers 135 | verbs: 136 | - create 137 | - delete 138 | - get 139 | - list 140 | - patch 141 | - update 142 | - watch 143 | ## 144 | ## Rules for apps.fedoraproject.org/v1alpha1, Kind: Mbox 145 | ## 146 | - apiGroups: 147 | - apps.fedoraproject.org 148 | resources: 149 | - mboxes 150 | - mboxes/status 151 | - mboxes/finalizers 152 | verbs: 153 | - create 154 | - delete 155 | - get 156 | - list 157 | - patch 158 | - update 159 | - watch 160 | # +kubebuilder:scaffold:rules 161 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: manager-rolebinding 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: manager-role 10 | subjects: 11 | - kind: ServiceAccount 12 | name: default 13 | namespace: system 14 | -------------------------------------------------------------------------------- /mbox-operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: mbox-operator 5 | -------------------------------------------------------------------------------- /mbox-operator/config/samples/apps_v1alpha1_mbkojibuilder.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps.fedoraproject.org/v1alpha1 2 | kind: MBKojiBuilder 3 | metadata: 4 | name: mb-koji-builder 5 | spec: 6 | image: quay.io/fedora/koji-builder:latest 7 | replicas: 1 8 | configmap: koji-builder-configmap 9 | cacert_secret: koji-hub-ca-cert 10 | client_cert_secret: koji-builder-client-cert 11 | koji_hub_user: 'koji-builder.mbox.dev' 12 | koji_hub_host: 'koji-hub' 13 | koji_hub_port: 8443 14 | max_jobs: 5 15 | vendor: MBox 16 | host_archs: 17 | - x86_64 18 | host_channels: 19 | - default 20 | - createrepo 21 | host_name: mbbox.default 22 | ssl_verify: false 23 | shared_pvc: koji-hub-mnt-pvc 24 | # mbox: example-mbox #uncomment to retrieve pvc and cert config from a mbox cr 25 | -------------------------------------------------------------------------------- /mbox-operator/config/samples/apps_v1alpha1_mbkojihub.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps.fedoraproject.org/v1alpha1 2 | kind: MBKojiHub 3 | metadata: 4 | name: mb-koji-hub 5 | labels: 6 | app: mb-koji-hub 7 | spec: 8 | image: quay.io/fedora/koji-hub:latest 9 | replicas: 1 10 | persistent: true 11 | host: koji.mbox.dev # change it to match the external web url/route of koji-hub 12 | configmap: koji-hub 13 | ca_cert_secret: koji-hub-ca-cert 14 | service_cert_secret: koji-hub-service-cert 15 | postgres_secret: postgres 16 | http_enabled: true 17 | https_enabled: true 18 | topic_prefix: mbox_dev 19 | fedora_messaging_url: amqps://koji:something@rabbitmq 20 | messaging_cert_secret: koji-hub-msg 21 | ingress_backend: nginx # default 22 | # ingress_backend: openshift 23 | httpd_pvc_name: koji-hub-httpd-pvc 24 | httpd_pvc_size: 1Gi 25 | mnt_pvc_name: koji-hub-mnt-pvc 26 | mnt_pvc_size: 10Gi 27 | web_client_cert_secret: koji-hub-web-client-cert 28 | web_client_username: kojiweb 29 | admin_client_cert: koji-hub-admin-cert 30 | admin_username: kojiadmin 31 | # mbox: example-mbox #uncomment to retrieve pvc and cert config from a mbox cr 32 | -------------------------------------------------------------------------------- /mbox-operator/config/samples/apps_v1alpha1_mbkojira.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps.fedoraproject.org/v1alpha1 2 | kind: MBKojira 3 | metadata: 4 | name: mb-kojira 5 | labels: 6 | app: mb-kojira 7 | spec: 8 | replicas: 1 9 | image: quay.io/fedora/kojira:latest 10 | configmap: kojira-config 11 | hub_username: kojira 12 | hub_host: koji-hub:8443 13 | src: 'no' 14 | max_repo_tasks: 15 15 | repo_tasks_limit: 15 16 | cacert_secret: koji-hub-ca-cert 17 | client_cert_secret: kojira-client-cert 18 | shared_pvc: koji-hub-mnt-pvc 19 | admin_secret: koji-hub-admin-cert 20 | # mbox: example-mbox #uncomment to retrieve pvc and cert config from a mbox cr 21 | -------------------------------------------------------------------------------- /mbox-operator/config/samples/apps_v1alpha1_mbmbsbackend.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps.fedoraproject.org/v1alpha1 2 | kind: MBMbsBackend 3 | metadata: 4 | name: example-mb-mbs-backend 5 | spec: 6 | replicas: 1 7 | image: quay.io/fedora/mbs-backend:latest 8 | hub_username: mbs 9 | cacert_secret: koji-hub-ca-cert 10 | client_cert_secret: mbs-client-cert 11 | postgres_secret: postgres 12 | configmap: mbs-configmap 13 | fedora_versions: ['32'] 14 | hub_host: 'koji-hub:8443' 15 | messaging_system: 'fedmsg' 16 | topic_prefix: 'org.fedoraproject.dev' 17 | scm_url: 'git+https://src.fedoraproject.org/modules/' 18 | rpms_default_repository: 'git+https://src.fedoraproject.org/rpms/' 19 | rpms_default_cache: 'https://src.fedoraproject.org/repo/pkgs/' 20 | modules_default_repository: 'git+https://src.fedoraproject.org/modules/' 21 | pdc_url: 'https://pdc.stg.fedoraproject.org/rest_api/v1' 22 | oidc_required_scope: 'https://mbs.fedoraproject.org/oidc/submit-build' 23 | shared_pvc: 'koji-hub-mnt-pvc' 24 | # mbox: example-mbox #uncomment to retrieve pvc and cert config from a mbox cr 25 | -------------------------------------------------------------------------------- /mbox-operator/config/samples/apps_v1alpha1_mbmbsfrontend.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps.fedoraproject.org/v1alpha1 2 | kind: MBMbsFrontend 3 | metadata: 4 | name: mb-mbs-frontend 5 | labels: 6 | app: mb-mbs-frontend 7 | spec: 8 | replicas: 1 9 | image: quay.io/fedora/mbs-frontend:latest 10 | configmap: mbs-frontend-configmap 11 | https_enabled: true 12 | postgres_secret: postgres 13 | mbs_configmap: mbs-configmap 14 | fedora_versions: ['32'] 15 | messaging_system: 'fedmsg' 16 | topic_prefix: 'org.fedoraproject.dev' 17 | scm_url: 'git+https://src.fedoraproject.org/modules/' 18 | rpms_default_repository: 'git+https://src.fedoraproject.org/rpms/' 19 | rpms_default_cache: 'https://src.fedoraproject.org/repo/pkgs/' 20 | modules_default_repository: 'git+https://src.fedoraproject.org/modules/' 21 | pdc_url: 'https://pdc.stg.fedoraproject.org/rest_api/v1' 22 | oidc_required_scope: 'https://mbs.fedoraproject.org/oidc/submit-build' 23 | 24 | ca_cert_secret: koji-hub-ca-cert 25 | koji_hub_host: 'koji-hub:8443' 26 | host: 'mbs.mbox.dev' 27 | client_cert_secret: mbs-frontend-client-cert 28 | service_cert_secret: mbs-frontend-service-cert 29 | service_name: 'mbs' 30 | ingress_backend: 'nginx' 31 | # mbox: example-mbox #uncomment to retrieve pvc and cert config from a mbox cr 32 | -------------------------------------------------------------------------------- /mbox-operator/config/samples/apps_v1alpha1_mbox.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps.fedoraproject.org/v1alpha1 2 | kind: Mbox 3 | metadata: 4 | name: example-mbox 5 | spec: 6 | psql_secret_name: postgres 7 | koji_pvc_name: mbox-koji-mnt 8 | koji_pvc_size: 10Gi 9 | root_ca_secret_name: mbox-koji-root-ca 10 | koji_hub_host: koji-hub:8443 11 | mq_topic_prefix: 'org.fedoraproject.dev' 12 | mbs: 13 | configmap: mbs-configmap 14 | fedora_versions: 15 | - '32' 16 | scm_repo_url: 'git+https://src.fedoraproject.org/modules/' 17 | rpm_repo_url: 'git+https://src.fedoraproject.org/rpms/' 18 | pkg_repo_url: 'https://src.fedoraproject.org/repo/pkgs/' 19 | pdc_url: 'https://pdc.stg.fedoraproject.org/rest_api/v1' 20 | oidc_required_scope: 'https://mbs.fedoraproject.org/oidc/submit-build' 21 | backend_config_messaging: fedmsg 22 | topic_prefix: 'org.fedoraproject.dev' 23 | -------------------------------------------------------------------------------- /mbox-operator/config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples you want in your CSV to this file as resources ## 2 | resources: 3 | - apps_v1alpha1_mbkojihub.yaml 4 | - apps_v1alpha1_mbkojibuilder.yaml 5 | - apps_v1alpha1_mbkojira.yaml 6 | - apps_v1alpha1_mbmbsbackend.yaml 7 | - apps_v1alpha1_mbmbsfrontend.yaml 8 | - apps_v1alpha1_mbox.yaml 9 | # +kubebuilder:scaffold:manifestskustomizesamples 10 | -------------------------------------------------------------------------------- /mbox-operator/config/scorecard/bases/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: [] 8 | -------------------------------------------------------------------------------- /mbox-operator/config/scorecard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - bases/config.yaml 3 | patchesJson6902: 4 | - path: patches/basic.config.yaml 5 | target: 6 | group: scorecard.operatorframework.io 7 | version: v1alpha3 8 | kind: Configuration 9 | name: config 10 | - path: patches/olm.config.yaml 11 | target: 12 | group: scorecard.operatorframework.io 13 | version: v1alpha3 14 | kind: Configuration 15 | name: config 16 | # +kubebuilder:scaffold:patchesJson6902 17 | -------------------------------------------------------------------------------- /mbox-operator/config/scorecard/patches/basic.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - basic-check-spec 7 | image: quay.io/operator-framework/scorecard-test:v1.0.1 8 | labels: 9 | suite: basic 10 | test: basic-check-spec-test 11 | -------------------------------------------------------------------------------- /mbox-operator/config/scorecard/patches/olm.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - olm-bundle-validation 7 | image: quay.io/operator-framework/scorecard-test:v1.0.1 8 | labels: 9 | suite: olm 10 | test: olm-bundle-validation-test 11 | - op: add 12 | path: /stages/0/tests/- 13 | value: 14 | entrypoint: 15 | - scorecard-test 16 | - olm-crds-have-validation 17 | image: quay.io/operator-framework/scorecard-test:v1.0.1 18 | labels: 19 | suite: olm 20 | test: olm-crds-have-validation-test 21 | - op: add 22 | path: /stages/0/tests/- 23 | value: 24 | entrypoint: 25 | - scorecard-test 26 | - olm-crds-have-resources 27 | image: quay.io/operator-framework/scorecard-test:v1.0.1 28 | labels: 29 | suite: olm 30 | test: olm-crds-have-resources-test 31 | - op: add 32 | path: /stages/0/tests/- 33 | value: 34 | entrypoint: 35 | - scorecard-test 36 | - olm-spec-descriptors 37 | image: quay.io/operator-framework/scorecard-test:v1.0.1 38 | labels: 39 | suite: olm 40 | test: olm-spec-descriptors-test 41 | - op: add 42 | path: /stages/0/tests/- 43 | value: 44 | entrypoint: 45 | - scorecard-test 46 | - olm-status-descriptors 47 | image: quay.io/operator-framework/scorecard-test:v1.0.1 48 | labels: 49 | suite: olm 50 | test: olm-status-descriptors-test 51 | -------------------------------------------------------------------------------- /mbox-operator/config/testing/debug_logs_patch.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | env: 13 | - name: ANSIBLE_DEBUG_LOGS 14 | value: "TRUE" 15 | -------------------------------------------------------------------------------- /mbox-operator/config/testing/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: osdk-test 3 | 4 | namePrefix: osdk- 5 | 6 | # Labels to add to all resources and selectors. 7 | #commonLabels: 8 | # someName: someValue 9 | 10 | # - pull_policy/IfNotPresent.yaml 11 | patchesStrategicMerge: 12 | - manager_image.yaml 13 | - debug_logs_patch.yaml 14 | - ../default/manager_auth_proxy_patch.yaml 15 | 16 | apiVersion: kustomize.config.k8s.io/v1beta1 17 | kind: Kustomization 18 | resources: 19 | - ../crd 20 | - ../rbac 21 | - ../manager 22 | images: 23 | - name: testing 24 | newName: apps.fedoraproject.org/mbox-operator 25 | newTag: testing 26 | -------------------------------------------------------------------------------- /mbox-operator/config/testing/manager_image.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | image: testing 13 | -------------------------------------------------------------------------------- /mbox-operator/config/testing/pull_policy/Always.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | imagePullPolicy: Always 13 | -------------------------------------------------------------------------------- /mbox-operator/config/testing/pull_policy/IfNotPresent.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | imagePullPolicy: IfNotPresent 13 | -------------------------------------------------------------------------------- /mbox-operator/config/testing/pull_policy/Never.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | imagePullPolicy: Never 13 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: localhost 4 | connection: local 5 | gather_facts: no 6 | collections: 7 | - community.kubernetes 8 | - operator_sdk.util 9 | 10 | tasks: 11 | - name: Create Namespace 12 | k8s: 13 | api_version: v1 14 | kind: Namespace 15 | name: '{{ namespace }}' 16 | wait: true 17 | 18 | - name: Deploy postgres 19 | k8s: 20 | src: "{{ components_dir }}/psql/{{ item }}" 21 | namespace: "{{ namespace }}" 22 | state: present 23 | wait: true 24 | with_items: 25 | - 0-secret.yaml 26 | - 1-pvc.yaml 27 | - 2-deployment.yaml 28 | - 3-service.yaml 29 | 30 | - name: Deploy kerberos 31 | k8s: 32 | src: "{{ components_dir }}/kerberos/{{ item }}" 33 | namespace: "{{ namespace }}" 34 | state: present 35 | wait: true 36 | with_items: 37 | - 0-service.yaml 38 | - 1-configmap.yaml 39 | - 2-deployment.yaml 40 | 41 | - name: Create RabbitMQ ConfigMap 42 | k8s: 43 | src: "{{ components_dir }}/rabbitmq/1-app.secret.yaml" 44 | namespace: "{{ namespace }}" 45 | state: present 46 | wait: true 47 | 48 | - import_tasks: kustomize.yml 49 | vars: 50 | state: present 51 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | tasks: [] 7 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/destroy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Destroy 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | collections: 7 | - community.kubernetes 8 | 9 | tasks: 10 | - import_tasks: kustomize.yml 11 | vars: 12 | state: absent 13 | 14 | - name: Destroy Namespace 15 | k8s: 16 | api_version: v1 17 | kind: Namespace 18 | name: '{{ namespace }}' 19 | state: absent 20 | 21 | - name: Unset pull policy 22 | command: '{{ kustomize }} edit remove patch --path pull_policy/{{ operator_pull_policy }}.yaml' 23 | args: 24 | chdir: '{{ config_dir }}/testing' 25 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/kustomize.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Build kustomize testing overlay 3 | # load_restrictor must be set to none so we can load patch files from the default overlay 4 | command: '{{ kustomize }} build --load_restrictor none .' 5 | args: 6 | chdir: '{{ config_dir }}/testing' 7 | register: resources 8 | changed_when: false 9 | 10 | - name: Set resources to {{ state }} 11 | debug: 12 | var: item 13 | loop: '{{resources.stdout_lines }}' 14 | 15 | - name: Set resources to {{ state }} 16 | k8s: 17 | definition: '{{ item }}' 18 | state: '{{ state }}' 19 | wait: yes 20 | loop: '{{ resources.stdout | from_yaml_all | list }}' 21 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: delegated 6 | lint: | 7 | set -e 8 | yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . 9 | platforms: 10 | - name: cluster 11 | groups: 12 | - k8s 13 | provisioner: 14 | name: ansible 15 | lint: | 16 | set -e 17 | ansible-lint 18 | inventory: 19 | group_vars: 20 | all: 21 | namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} 22 | host_vars: 23 | localhost: 24 | ansible_python_interpreter: '{{ ansible_playbook_python }}' 25 | config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config 26 | samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples 27 | components_dir: ${MOLECULE_PROJECT_DIRECTORY}/../components 28 | operator_image: ${OPERATOR_IMAGE:-""} 29 | operator_pull_policy: ${OPERATOR_PULL_POLICY:-"Always"} 30 | kustomize: ${KUSTOMIZE_PATH:-kustomize} 31 | env: 32 | K8S_AUTH_KUBECONFIG: ${KUBECONFIG:-"~/.kube/config"} 33 | verifier: 34 | name: ansible 35 | lint: | 36 | set -e 37 | ansible-lint 38 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | 7 | tasks: 8 | - name: Ensure operator image is set 9 | fail: 10 | msg: | 11 | You must specify the OPERATOR_IMAGE environment variable in order to run the 12 | 'default' scenario 13 | when: not operator_image 14 | 15 | - name: Set testing image 16 | command: '{{ kustomize }} edit set image testing={{ operator_image }}' 17 | args: 18 | chdir: '{{ config_dir }}/testing' 19 | 20 | - name: Set pull policy 21 | command: '{{ kustomize }} edit add patch --path pull_policy/{{ operator_pull_policy }}.yaml' 22 | args: 23 | chdir: '{{ config_dir }}/testing' 24 | 25 | - name: Set testing namespace 26 | command: '{{ kustomize }} edit set namespace {{ namespace }}' 27 | args: 28 | chdir: '{{ config_dir }}/testing' 29 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/tasks/mbkojibuilder_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create the apps.fedoraproject.org/v1alpha1.MBKojiBuilder 3 | k8s: 4 | state: present 5 | namespace: '{{ namespace }}' 6 | definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" 7 | wait: yes 8 | wait_timeout: 300 9 | wait_condition: 10 | type: Running 11 | reason: Successful 12 | status: "True" 13 | vars: 14 | cr_file: 'apps_v1alpha1_mbkojibuilder.yaml' 15 | 16 | - block: 17 | - name: 'TEST: kojibuilder.configmap' 18 | k8s_info: 19 | api_version: v1 20 | kind: ConfigMap 21 | namespace: "{{ namespace }}" 22 | name: koji-builder-configmap 23 | register: koji_configmap 24 | - assert: 25 | that: 26 | - koji_configmap.resources|length == 1 27 | - koji_configmap.resources[0].metadata.labels['app'] == 'koji-builder' 28 | - "'kojid.conf' in koji_configmap.resources[0].data" 29 | 30 | - block: 31 | - name: 'TEST: kojibuilder.secret.client-cert' 32 | k8s_info: 33 | api_version: v1 34 | kind: Secret 35 | namespace: "{{ namespace }}" 36 | name: koji-builder-client-cert 37 | register: kojibuilder_client_secrets 38 | - assert: 39 | that: 40 | - kojibuilder_client_secrets.resources|length == 1 41 | - kojibuilder_client_secrets.resources[0].metadata.labels['app'] == 'koji-builder' 42 | - "'tls.crt' in kojibuilder_client_secrets.resources[0].data" 43 | - "'tls.key' in kojibuilder_client_secrets.resources[0].data" 44 | 45 | - block: 46 | - name: 'TEST: kojibuilder.pod deployment' 47 | k8s_info: 48 | api_version: v1 49 | kind: Pod 50 | namespace: "{{ namespace }}" 51 | label_selectors: 52 | - app = koji-builder 53 | register: pods 54 | - assert: 55 | that: 56 | - pods.resources|length == 1 57 | - pods.resources[0].metadata.labels['app'] == 'koji-builder' 58 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/tasks/mbkojihub_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create the apps.fedoraproject.org/v1alpha1.MBKojiHub 3 | k8s: 4 | state: present 5 | namespace: '{{ namespace }}' 6 | definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" 7 | wait: yes 8 | wait_timeout: 300 9 | wait_condition: 10 | type: Running 11 | reason: Successful 12 | status: "True" 13 | vars: 14 | cr_file: 'apps_v1alpha1_mbkojihub.yaml' 15 | 16 | - block: 17 | - name: 'TEST: koji_hub.configmap' 18 | k8s_info: 19 | api_version: v1 20 | kind: ConfigMap 21 | namespace: "{{ namespace }}" 22 | name: koji-hub 23 | register: koji_configmap 24 | - assert: 25 | that: 26 | - koji_configmap.resources|length == 1 27 | - koji_configmap.resources[0].metadata.labels['app'] == 'koji-hub' 28 | - "'httpd.conf' in koji_configmap.resources[0].data" 29 | - "'hub.conf' in koji_configmap.resources[0].data" 30 | - "'kojiweb.conf' in koji_configmap.resources[0].data" 31 | - "'fedora-messaging.toml' in koji_configmap.resources[0].data" 32 | 33 | - block: 34 | - name: 'TEST: kojihub.secret.koji-hub-ca-cert' 35 | k8s_info: 36 | api_version: v1 37 | kind: Secret 38 | namespace: "{{ namespace }}" 39 | name: koji-hub-ca-cert 40 | register: kojihub_secrets 41 | - assert: 42 | that: 43 | - kojihub_secrets.resources|length == 1 44 | - kojihub_secrets.resources[0].metadata.labels['app'] == 'koji-hub' 45 | - "'cert' in kojihub_secrets.resources[0].data" 46 | 47 | - block: 48 | - name: 'TEST: kojihub.secret.koji-hub-service-cert' 49 | k8s_info: 50 | api_version: v1 51 | kind: Secret 52 | namespace: "{{ namespace }}" 53 | name: koji-hub-service-cert 54 | register: kojihub_secrets 55 | - assert: 56 | that: 57 | - kojihub_secrets.resources|length == 1 58 | - kojihub_secrets.resources[0].metadata.labels['app'] == 'koji-hub' 59 | - "'tls.crt' in kojihub_secrets.resources[0].data" 60 | - "'tls.key' in kojihub_secrets.resources[0].data" 61 | 62 | - block: 63 | - name: 'TEST: kojihub.secret.koji-hub-web-client-cert' 64 | k8s_info: 65 | api_version: v1 66 | kind: Secret 67 | namespace: "{{ namespace }}" 68 | name: koji-hub-web-client-cert 69 | register: kojihub_secrets 70 | - assert: 71 | that: 72 | - kojihub_secrets.resources|length == 1 73 | - kojihub_secrets.resources[0].metadata.labels['app'] == 'koji-hub' 74 | - "'client.pem' in kojihub_secrets.resources[0].data" 75 | 76 | - block: 77 | - name: 'TEST: kojihub.pvcs' 78 | k8s_info: 79 | api_version: v1 80 | kind: PersistentVolumeClaim 81 | namespace: "{{ namespace }}" 82 | name: koji-hub-mnt-pvc 83 | register: kojihub_pvcs 84 | - assert: 85 | that: 86 | - kojihub_pvcs.resources|length == 1 87 | - kojihub_pvcs.resources[0].metadata.labels['app'] == 'koji-hub' 88 | - "'ReadWriteMany' in kojihub_pvcs.resources[0].spec.accessModes" 89 | - "kojihub_pvcs.resources[0].spec.resources.requests.storage == '10Gi'" 90 | - k8s_info: 91 | api_version: v1 92 | kind: PersistentVolumeClaim 93 | namespace: "{{ namespace }}" 94 | name: koji-hub-httpd-pvc 95 | register: kojihub_pvcs 96 | - assert: 97 | that: 98 | - kojihub_pvcs.resources|length == 1 99 | - kojihub_pvcs.resources[0].metadata.labels['app'] == 'koji-hub' 100 | - "'ReadWriteOnce' in kojihub_pvcs.resources[0].spec.accessModes" 101 | - "kojihub_pvcs.resources[0].spec.resources.requests.storage == '1Gi'" 102 | 103 | - block: 104 | - name: 'TEST: kojihub.service' 105 | k8s_info: 106 | api_version: v1 107 | kind: Service 108 | namespace: "{{ namespace }}" 109 | name: koji-hub 110 | register: kojihub_ingress 111 | - assert: 112 | that: 113 | - kojihub_ingress.resources|length == 1 114 | - kojihub_ingress.resources[0].metadata.labels['app'] == 'koji-hub' 115 | 116 | - block: 117 | - name: 'TEST: kojihub.ingress.http' 118 | k8s_info: 119 | api_version: networking.k8s.io/v1beta1 120 | kind: Ingress 121 | namespace: "{{ namespace }}" 122 | name: koji-hub-http 123 | register: kojihub_ingress 124 | - assert: 125 | that: 126 | - kojihub_ingress.resources|length == 1 127 | - kojihub_ingress.resources[0].metadata.labels['app'] == 'koji-hub' 128 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/tasks/mbkojira_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create the apps.fedoraproject.org/v1alpha1.MBKojira 3 | k8s: 4 | state: present 5 | namespace: '{{ namespace }}' 6 | definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" 7 | wait: yes 8 | wait_timeout: 300 9 | wait_condition: 10 | type: Running 11 | reason: Successful 12 | status: "True" 13 | vars: 14 | cr_file: 'apps_v1alpha1_mbkojira.yaml' 15 | 16 | - block: 17 | - name: 'TEST: kojira.configmap' 18 | k8s_info: 19 | api_version: v1 20 | kind: ConfigMap 21 | namespace: "{{ namespace }}" 22 | name: kojira-config 23 | register: kojira_configmap 24 | - assert: 25 | that: 26 | - kojira_configmap.resources|length == 1 27 | - kojira_configmap.resources[0].metadata.labels['app'] == 'kojira' 28 | - "'kojira.conf' in kojira_configmap.resources[0].data" 29 | 30 | - block: 31 | - name: 'TEST: kojira.secret.client-cert' 32 | k8s_info: 33 | api_version: v1 34 | kind: Secret 35 | namespace: "{{ namespace }}" 36 | name: kojira-client-cert 37 | register: kojira_client_secrets 38 | - assert: 39 | that: 40 | - kojira_client_secrets.resources|length == 1 41 | - kojira_client_secrets.resources[0].metadata.labels['app'] == 'kojira' 42 | - "'client.pem' in kojira_client_secrets.resources[0].data" 43 | 44 | - block: 45 | - name: 'TEST: kojira.deployment' 46 | k8s_info: 47 | api_version: v1 48 | kind: Deployment 49 | namespace: "{{ namespace }}" 50 | name: kojira 51 | register: kojira_deployments 52 | - k8s_info: 53 | api_version: v1 54 | kind: Pod 55 | namespace: "{{ namespace }}" 56 | label_selectors: 57 | - app = kojira 58 | register: kojira_pods 59 | - assert: 60 | that: 61 | - kojira_deployments.resources|length == 1 62 | - kojira_deployments.resources[0].metadata.labels['app'] == 'kojira' 63 | - assert: 64 | that: 65 | - kojira_pods.resources|length == 1 66 | - kojira_pods.resources[0].metadata.labels['app'] == 'kojira' 67 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/tasks/mbmbsbackend_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create the apps.fedoraproject.org/v1alpha1.MBMbsBackend 3 | k8s: 4 | state: present 5 | namespace: '{{ namespace }}' 6 | definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" 7 | wait: yes 8 | wait_timeout: 300 9 | wait_condition: 10 | type: Running 11 | reason: Successful 12 | status: "True" 13 | vars: 14 | cr_file: 'apps_v1alpha1_mbmbsbackend.yaml' 15 | 16 | - block: 17 | - name: 'TEST: mbs-backend.mbs-configmap' 18 | k8s_info: 19 | api_version: v1 20 | kind: ConfigMap 21 | namespace: "{{ namespace }}" 22 | name: mbs-configmap 23 | register: mbs_configmap 24 | - assert: 25 | that: 26 | - mbs_configmap.resources|length == 1 27 | - "'default_module_f32.yml' in mbs_configmap.resources[0].data" 28 | - "'koji.conf' in mbs_configmap.resources[0].data" 29 | - "'config.py' in mbs_configmap.resources[0].data" 30 | 31 | - block: 32 | - name: 'TEST: mbs-backend.secret.client-cert' 33 | k8s_info: 34 | api_version: v1 35 | kind: Secret 36 | namespace: "{{ namespace }}" 37 | name: mbs-client-cert 38 | register: mbs_client_secrets 39 | - assert: 40 | that: 41 | - mbs_client_secrets.resources|length == 1 42 | - mbs_client_secrets.resources[0].metadata.labels['app'] == 'mbs-backend' 43 | - "'client.pem' in mbs_client_secrets.resources[0].data" 44 | 45 | - block: 46 | - name: 'TEST: mbs-backend.deployment' 47 | k8s_info: 48 | api_version: v1 49 | kind: Pod 50 | namespace: "{{ namespace }}" 51 | label_selectors: 52 | - app = mbs-backend 53 | register: mbs_backend_pods 54 | - assert: 55 | that: 56 | - mbs_backend_pods.resources|length == 1 57 | - mbs_backend_pods.resources[0].metadata.labels['app'] == 'mbs-backend' 58 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/tasks/mbmbsfrontend_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create the apps.fedoraproject.org/v1alpha1.MBMbsFrontend 3 | k8s: 4 | state: present 5 | namespace: '{{ namespace }}' 6 | definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" 7 | wait: yes 8 | wait_timeout: 300 9 | wait_condition: 10 | type: Running 11 | reason: Successful 12 | status: "True" 13 | vars: 14 | cr_file: 'apps_v1alpha1_mbmbsfrontend.yaml' 15 | 16 | - block: 17 | - name: 'TEST: mbs-frontend.configmap' 18 | k8s_info: 19 | api_version: v1 20 | kind: ConfigMap 21 | namespace: "{{ namespace }}" 22 | name: mbs-frontend-configmap 23 | register: mbs_configmap 24 | - assert: 25 | that: 26 | - mbs_configmap.resources|length == 1 27 | - mbs_configmap.resources[0].metadata.labels['app'] == 'mbs-frontend' 28 | - "'httpd.conf' in mbs_configmap.resources[0].data" 29 | 30 | - block: 31 | - name: 'TEST: mbs-frontend.mbs-configmap' 32 | k8s_info: 33 | api_version: v1 34 | kind: ConfigMap 35 | namespace: "{{ namespace }}" 36 | name: mbs-configmap 37 | register: mbs_configmap 38 | - assert: 39 | that: 40 | - mbs_configmap.resources|length == 1 41 | - "'default_module_f32.yml' in mbs_configmap.resources[0].data" 42 | - "'koji.conf' in mbs_configmap.resources[0].data" 43 | - "'config.py' in mbs_configmap.resources[0].data" 44 | 45 | - block: 46 | - name: 'TEST: mbs-frontend.secret.client-cert' 47 | k8s_info: 48 | api_version: v1 49 | kind: Secret 50 | namespace: "{{ namespace }}" 51 | name: mbs-frontend-client-cert 52 | register: mbsfrontend_client_secrets 53 | - assert: 54 | that: 55 | - mbsfrontend_client_secrets.resources|length == 1 56 | - mbsfrontend_client_secrets.resources[0].metadata.labels['app'] == 'mbs-frontend' 57 | - "'tls.crt' in mbsfrontend_client_secrets.resources[0].data" 58 | - "'tls.key' in mbsfrontend_client_secrets.resources[0].data" 59 | - "'tls.pem' in mbsfrontend_client_secrets.resources[0].data" 60 | 61 | - block: 62 | - name: 'TEST: mbs-frontend.secret.mbs-frontend-service-cert' 63 | k8s_info: 64 | api_version: v1 65 | kind: Secret 66 | namespace: "{{ namespace }}" 67 | name: mbs-frontend-service-cert 68 | register: mbsfrontend_secrets 69 | - assert: 70 | that: 71 | - mbsfrontend_secrets.resources|length == 1 72 | - mbsfrontend_secrets.resources[0].metadata.labels['app'] == 'mbs-frontend' 73 | - "'tls.crt' in mbsfrontend_secrets.resources[0].data" 74 | - "'tls.key' in mbsfrontend_secrets.resources[0].data" 75 | 76 | - block: 77 | - name: 'TEST: mbs-frontend.deployment' 78 | k8s_info: 79 | api_version: v1 80 | kind: Pod 81 | namespace: "{{ namespace }}" 82 | label_selectors: 83 | - app = mbs-frontend 84 | register: mbs_frontend_pods 85 | - assert: 86 | that: 87 | - mbs_frontend_pods.resources|length == 1 88 | - mbs_frontend_pods.resources[0].metadata.labels['app'] == 'mbs-frontend' 89 | 90 | - block: 91 | - name: 'TEST: mbs-frontend.service' 92 | k8s_info: 93 | api_version: v1 94 | kind: Service 95 | namespace: "{{ namespace }}" 96 | name: mbs 97 | register: mbsfrontend_service 98 | - assert: 99 | that: 100 | - mbsfrontend_service.resources|length == 1 101 | - mbsfrontend_service.resources[0].metadata.labels['app'] == 'mbs-frontend' 102 | 103 | - block: 104 | - name: 'TEST: mbs-frontend.ingress.http' 105 | k8s_info: 106 | api_version: networking.k8s.io/v1beta1 107 | kind: Ingress 108 | namespace: "{{ namespace }}" 109 | name: mbs-frontend-http 110 | register: mbsfrontend_ingress 111 | - assert: 112 | that: 113 | - mbsfrontend_ingress.resources|length == 1 114 | - mbsfrontend_ingress.resources[0].metadata.labels['app'] == 'mbs-frontend' 115 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/tasks/mbox_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create the apps.fedoraproject.org/v1alpha1.Mbox 3 | k8s: 4 | state: present 5 | namespace: '{{ namespace }}' 6 | definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" 7 | wait: yes 8 | wait_timeout: 300 9 | wait_condition: 10 | type: Running 11 | reason: Successful 12 | status: "True" 13 | vars: 14 | cr_file: 'apps_v1alpha1_mbox.yaml' 15 | 16 | - block: 17 | - name: mbox.secret.root_ca 18 | k8s_info: 19 | api_version: v1 20 | kind: Secret 21 | namespace: "{{ namespace }}" 22 | name: mbox-koji-root-ca 23 | register: k8s_secrets 24 | - assert: 25 | that: 26 | - k8s_secrets.resources|length == 1 27 | - k8s_secrets.resources[0].metadata.labels['app'] == 'mbox' 28 | - "'ca_req.pem' in k8s_secrets.resources[0].data" 29 | - "'ca_cert.pem' in k8s_secrets.resources[0].data" 30 | - "'ca_key.pem' in k8s_secrets.resources[0].data" 31 | 32 | - block: 33 | - name: mbox.secret.root_ca 34 | k8s_info: 35 | api_version: v1 36 | kind: ConfigMap 37 | namespace: "{{ namespace }}" 38 | name: mbs-configmap 39 | register: k8s_cms 40 | - assert: 41 | that: 42 | - k8s_cms.resources|length == 1 43 | -------------------------------------------------------------------------------- /mbox-operator/molecule/default/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Verify 3 | hosts: localhost 4 | connection: local 5 | gather_facts: no 6 | collections: 7 | - community.kubernetes 8 | 9 | vars: 10 | ctrl_label: control-plane=controller-manager 11 | 12 | tasks: 13 | - block: 14 | - name: Import all test files from tasks/ 15 | include_tasks: 'tasks/{{ item }}_test.yml' 16 | with_items: 17 | - mbkojihub 18 | - mbkojibuilder 19 | - mbkojira 20 | - mbmbsbackend 21 | - mbmbsfrontend 22 | - mbox 23 | rescue: 24 | - name: Retrieve relevant resources 25 | k8s_info: 26 | api_version: '{{ item.api_version }}' 27 | kind: '{{ item.kind }}' 28 | namespace: '{{ namespace }}' 29 | loop: 30 | - api_version: v1 31 | kind: Pod 32 | - api_version: apps/v1 33 | kind: Deployment 34 | - api_version: v1 35 | kind: Secret 36 | - api_version: v1 37 | kind: ConfigMap 38 | register: debug_resources 39 | 40 | - name: Retrieve Pod logs 41 | shell: "kubectl logs {{ item.metadata.name }} -c manager -n {{ namespace }}" 42 | loop: "{{ q('k8s', api_version='v1', kind='Pod', namespace=namespace, label_selector=ctrl_label) }}" 43 | register: debug_logs 44 | 45 | - name: Output gathered resources 46 | debug: 47 | var: debug_resources 48 | 49 | - name: Output gathered logs 50 | debug: 51 | var: debug_logs 52 | # loop: '{{ debug_logs.stdout_lines }}' 53 | 54 | - name: Re-emit failure 55 | vars: 56 | failed_task: 57 | result: '{{ ansible_failed_result }}' 58 | fail: 59 | msg: '{{ failed_task }}' 60 | -------------------------------------------------------------------------------- /mbox-operator/molecule/kind/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: localhost 4 | connection: local 5 | gather_facts: no 6 | tasks: 7 | - name: Build operator image 8 | docker_image: 9 | build: 10 | path: '{{ project_dir }}' 11 | pull: no 12 | name: '{{ operator_image }}' 13 | tag: latest 14 | push: no 15 | source: build 16 | force_source: yes 17 | 18 | - name: Load image into kind cluster 19 | command: kind load docker-image --name osdk-test '{{ operator_image }}' 20 | register: result 21 | changed_when: '"not yet present" in result.stdout' 22 | 23 | - import_playbook: ../default/converge.yml 24 | -------------------------------------------------------------------------------- /mbox-operator/molecule/kind/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | tasks: 7 | - name: Create test kind cluster 8 | command: kind create cluster --name osdk-test --kubeconfig {{ kubeconfig }} 9 | -------------------------------------------------------------------------------- /mbox-operator/molecule/kind/destroy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Destroy 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | collections: 7 | - community.kubernetes 8 | 9 | tasks: 10 | - name: Destroy test kind cluster 11 | command: kind delete cluster --name osdk-test --kubeconfig {{ kubeconfig }} 12 | 13 | - name: Unset pull policy 14 | command: '{{ kustomize }} edit remove patch pull_policy/{{ operator_pull_policy }}.yaml' 15 | args: 16 | chdir: '{{ config_dir }}/testing' 17 | -------------------------------------------------------------------------------- /mbox-operator/molecule/kind/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: delegated 6 | lint: | 7 | set -e 8 | yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . 9 | platforms: 10 | - name: cluster 11 | groups: 12 | - k8s 13 | provisioner: 14 | name: ansible 15 | playbooks: 16 | prepare: ../default/prepare.yml 17 | verify: ../default/verify.yml 18 | lint: | 19 | set -e 20 | ansible-lint 21 | inventory: 22 | group_vars: 23 | all: 24 | namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} 25 | host_vars: 26 | localhost: 27 | ansible_python_interpreter: '{{ ansible_playbook_python }}' 28 | config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config 29 | samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples 30 | components_dir: ${MOLECULE_PROJECT_DIRECTORY}/../components 31 | project_dir: ${MOLECULE_PROJECT_DIRECTORY} 32 | operator_image: testing-operator 33 | operator_pull_policy: "Never" 34 | kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" 35 | kustomize: ${KUSTOMIZE_PATH:-kustomize} 36 | env: 37 | K8S_AUTH_KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig 38 | KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig 39 | verifier: 40 | name: ansible 41 | lint: | 42 | set -e 43 | ansible-lint 44 | -------------------------------------------------------------------------------- /mbox-operator/molecule/test-local/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Build Operator in Kubernetes docker container 3 | hosts: k8s 4 | gather_facts: false 5 | vars: 6 | image_name: "{{ operator_image }}" 7 | dockerfile_path: /build/Dockerfile 8 | tasks: 9 | # using command so we don't need to install any dependencies 10 | - name: Get existing image hash 11 | command: docker images -q {{ image_name }} 12 | register: prev_hash 13 | changed_when: false 14 | 15 | - name: Build Operator Image 16 | command: docker build -f {{ dockerfile_path }} -t {{ image_name }} /build 17 | register: build_cmd 18 | changed_when: not prev_hash.stdout or (prev_hash.stdout and prev_hash.stdout not in ''.join(build_cmd.stdout_lines[-2:])) 19 | 20 | 21 | - import_playbook: '{{ playbook_dir }}/../default/converge.yml' 22 | -------------------------------------------------------------------------------- /mbox-operator/molecule/test-local/destroy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Destroy 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | no_log: "{{ molecule_no_log }}" 7 | tasks: 8 | - name: Destroy molecule instance(s) 9 | docker_container: 10 | name: "{{ item.name }}" 11 | docker_host: "{{ item.docker_host | default(lookup('env', 'DOCKER_HOST') or 'unix://var/run/docker.sock') }}" 12 | cacert_path: "{{ item.cacert_path | default((lookup('env', 'DOCKER_CERT_PATH') + '/ca.pem') if lookup('env', 'DOCKER_CERT_PATH') else omit) }}" 13 | cert_path: "{{ item.cert_path | default((lookup('env', 'DOCKER_CERT_PATH') + '/cert.pem') if lookup('env', 'DOCKER_CERT_PATH') else omit) }}" 14 | key_path: "{{ item.key_path | default((lookup('env', 'DOCKER_CERT_PATH') + '/key.pem') if lookup('env', 'DOCKER_CERT_PATH') else omit) }}" 15 | tls_verify: "{{ item.tls_verify | default(lookup('env', 'DOCKER_TLS_VERIFY')) or false }}" 16 | state: absent 17 | force_kill: "{{ item.force_kill | default(true) }}" 18 | keep_volumes: "{{ item.keep_volumes | default(true) }}" 19 | container_default_behavior: "{{ item.container_default_behavior | default('compatibility' if ansible_version.full is version_compare('2.10', '>=') else omit) }}" 20 | register: server 21 | with_items: "{{ molecule_yml.platforms }}" 22 | async: 7200 23 | poll: 0 24 | 25 | - name: Wait for instance(s) deletion to complete 26 | async_status: 27 | jid: "{{ item.ansible_job_id }}" 28 | register: docker_jobs 29 | until: docker_jobs.finished 30 | retries: 300 31 | with_items: "{{ server.results }}" 32 | 33 | - name: Prune everything 34 | docker_prune: 35 | containers: yes 36 | images: yes 37 | networks: yes 38 | volumes: yes 39 | 40 | - name: Unset pull policy 41 | command: '{{ kustomize }} edit remove patch --path pull_policy/{{ operator_pull_policy }}.yaml' 42 | args: 43 | chdir: '{{ config_dir }}/testing' 44 | -------------------------------------------------------------------------------- /mbox-operator/molecule/test-local/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | lint: | 7 | yamllint roles/ 8 | platforms: 9 | - name: kind-test-local 10 | groups: 11 | - k8s 12 | image: bsycorp/kind:latest-1.16 13 | privileged: true 14 | override_command: false 15 | exposed_ports: 16 | - 8443/tcp 17 | - 10080/tcp 18 | published_ports: 19 | - 0.0.0.0:${TEST_CLUSTER_PORT:-10443}:8443/tcp 20 | pre_build_image: true 21 | volumes: 22 | - ${MOLECULE_PROJECT_DIRECTORY}:/build:Z 23 | provisioner: 24 | name: ansible 25 | log: true 26 | lint: | 27 | ansible-lint . 28 | inventory: 29 | group_vars: 30 | all: 31 | namespace: ${TEST_NAMESPACE:-osdk-test} 32 | operator_image: apps.fedoraproject.org/mbox-operator:testing 33 | host_vars: 34 | localhost: 35 | ansible_python_interpreter: '{{ ansible_playbook_python }}' 36 | config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config 37 | samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples 38 | components_dir: ${MOLECULE_PROJECT_DIRECTORY}/../components 39 | operator_image: ${OPERATOR_IMAGE:-"apps.fedoraproject.org/mbox-operator:testing"} 40 | operator_pull_policy: ${OPERATOR_PULL_POLICY:-"IfNotPresent"} 41 | kustomize: ${KUSTOMIZE_PATH:-kustomize} 42 | kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" 43 | env: 44 | K8S_AUTH_KUBECONFIG: /tmp/molecule/kind-test-local/kubeconfig 45 | KUBECONFIG: /tmp/molecule/kind-test-local/kubeconfig 46 | ANSIBLE_ROLES_PATH: ${MOLECULE_PROJECT_DIRECTORY}/roles 47 | KIND_PORT: '${TEST_CLUSTER_PORT:-10443}' 48 | playbooks: 49 | destroy: destroy.yml 50 | verify: ../default/verify.yml 51 | scenario: 52 | name: test-local 53 | test_sequence: 54 | - lint 55 | - destroy 56 | - dependency 57 | - syntax 58 | - create 59 | - prepare 60 | - converge 61 | - verify 62 | - destroy 63 | verifier: 64 | name: ansible 65 | lint: | 66 | flake8 67 | -------------------------------------------------------------------------------- /mbox-operator/molecule/test-local/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare 3 | hosts: k8s 4 | gather_facts: false 5 | vars: 6 | kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" 7 | tasks: 8 | - name: delete the kubeconfig if present 9 | file: 10 | path: '{{ kubeconfig }}' 11 | state: absent 12 | delegate_to: localhost 13 | 14 | - name: Fetch the kubeconfig 15 | fetch: 16 | dest: '{{ kubeconfig }}' 17 | flat: true 18 | src: /root/.kube/config 19 | 20 | - name: Change the kubeconfig port to the proper value 21 | replace: 22 | regexp: 'server: http(s?):\/\/([0-9\.]+|localhost):[0-9]+' 23 | replace: "server: https://localhost:{{ lookup('env', 'KIND_PORT') }}" 24 | path: '{{ kubeconfig }}' 25 | delegate_to: localhost 26 | 27 | - name: Wait for the Kubernetes API to become available (this could take a minute) 28 | uri: 29 | url: "https://localhost:8443/readyz" 30 | status_code: 200 31 | validate_certs: false 32 | register: result 33 | until: (result.status|default(-1)) == 200 34 | retries: 60 35 | delay: 5 36 | 37 | - import_playbook: '{{ playbook_dir }}/../default/prepare.yml' 38 | -------------------------------------------------------------------------------- /mbox-operator/playbooks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/mbbox/bc7cbdb74fd9ec0071617bbcf15f32f0e44935ac/mbox-operator/playbooks/.keep -------------------------------------------------------------------------------- /mbox-operator/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | collections: 3 | - name: community.kubernetes 4 | version: "<1.0.0" 5 | - operator_sdk.util 6 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-builder/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for koji-builder 3 | koji_builder_image: "{{ image|default('quay.io/fedora/koji-builder:latest') }}" 4 | koji_builder_replicas: "{{ replicas|default(1) }}" 5 | 6 | koji_builder_configmap: "{{ configmap|default('koji-builder-configmap') }}" 7 | koji_builder_cacert_secret: "{{ cacert_secret|default('koji-builder-ca-cert') }}" 8 | koji_builder_client_cert_secret: "{{ client_cert_secret|default('koji-builder-client-cert') }}" 9 | koji_builder_hub_user: "{{ koji_hub_user|default('koji-builder.mbox.dev') }}" 10 | 11 | koji_builder_koji_hub_host: "{{ koji_hub_host|default('koji-hub') }}" 12 | koji_builder_koji_hub_port: "{{ koji_hub_port|default(8443) }}" 13 | koji_builder_maxjobs: "{{ max_jobs|default(5) }}" 14 | koji_builder_vendor: "{{ vendor|default('MBox') }}" 15 | 16 | koji_builder_admin_secret: "{{ admin_secret | default('koji-hub-admin-cert') }}" 17 | 18 | koji_builder_host_archs: "{{ host_archs | default(['x86_64']) }}" 19 | koji_builder_host_channels: "{{ host_channels | default(['default', 'createrepo']) }}" 20 | koji_builder_host_name: "{{ host_name | default('koji-hub:8443') }}" 21 | koji_builder_ssl_verify: "{{ ssl_verify | default(true) }}" 22 | 23 | koji_builder_shared_pvc: "{{ shared_pvc | default('koji-hub-mnt-pvc') }}" 24 | koji_builder_mbox: "{{ mbox | default('') }}" 25 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-builder/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - role: koji-lib 3 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-builder/tasks/cert.yml: -------------------------------------------------------------------------------- 1 | - name: create temporary cert directory 2 | tempfile: 3 | state: directory 4 | prefix: kojibuilder 5 | suffix: cert 6 | register: cert_dir 7 | 8 | - name: create temporary koji directory 9 | tempfile: 10 | state: directory 11 | prefix: kojibuilder 12 | suffix: koji 13 | register: koji_dir 14 | 15 | - block: 16 | - set_fact: 17 | koji_builder_cacert_secret: "{{ k8s_mboxes.resources[0].spec.root_ca_secret_name }}" 18 | when: koji_builder_mbox|length > 0 19 | 20 | - name: Check for koji-builder client secret existence 21 | k8s_info: 22 | api_version: v1 23 | kind: Secret 24 | name: "{{ koji_builder_client_cert_secret }}" 25 | namespace: "{{ meta.namespace }}" 26 | register: clientcert_query 27 | 28 | - name: Retrieve ca secret 29 | block: 30 | - k8s_info: 31 | api_version: v1 32 | kind: Secret 33 | name: "{{ koji_builder_cacert_secret }}" 34 | namespace: "{{ meta.namespace }}" 35 | register: k8s_secrets 36 | - fail: 37 | msg: "Secret {{ koji_builder_cacert_secret }} not found." 38 | when: k8s_secrets.resources|length == 0 39 | - set_fact: 40 | ca: "{{ k8s_secrets.resources[0] }}" 41 | - copy: 42 | content: "{{ ca.data.cert | b64decode }}" 43 | dest: "{{ cert_dir.path }}/ca_cert.pem" 44 | - copy: 45 | content: "{{ ca.data.key | b64decode }}" 46 | dest: "{{ cert_dir.path }}/ca_key.pem" 47 | when: clientcert_query.resources|length == 0 48 | - copy: 49 | content: "{{ ca.data.cert | b64decode }}" 50 | dest: "{{ koji_dir.path }}/ca.pem" 51 | 52 | - name: Client certificate creation 53 | block: 54 | - openssl_privatekey: 55 | path: "{{ cert_dir.path }}/client_key.pem" 56 | size: 4096 57 | - openssl_csr: 58 | path: "{{ cert_dir.path }}/client_req.pem" 59 | privatekey_path: "{{ cert_dir.path }}/client_key.pem" 60 | common_name: "{{ koji_builder_host_name }}" 61 | - openssl_certificate: 62 | path: "{{ cert_dir.path }}/client_cert.pem" 63 | csr_path: "{{ cert_dir.path }}/client_req.pem" 64 | ownca_path: "{{ cert_dir.path }}/ca_cert.pem" 65 | ownca_privatekey_path: "{{ cert_dir.path }}/ca_key.pem" 66 | provider: ownca 67 | when: clientcert_query.resources|length == 0 68 | 69 | - name: Kubernetes client certificate secret creation 70 | block: 71 | - k8s: 72 | definition: 73 | apiVersion: v1 74 | kind: Secret 75 | metadata: 76 | name: "{{ koji_builder_client_cert_secret }}" 77 | namespace: "{{ meta.namespace }}" 78 | labels: 79 | app: koji-builder 80 | data: 81 | tls.crt: "{{ lookup('file', cert_dir.path + '/client_cert.pem') | b64encode }}" 82 | tls.key: "{{ lookup('file', cert_dir.path + '/client_key.pem') | b64encode }}" 83 | tls.pem: "{{ (lookup('file', cert_dir.path + '/client_key.pem') + '\n' + lookup('file', cert_dir.path + '/client_cert.pem')) | b64encode }}" 84 | type: kubernetes.io/tls 85 | when: clientcert_query.resources|length == 0 86 | 87 | - name: cleanup 88 | file: 89 | path: "{{ cert_dir.path }}" 90 | state: absent 91 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-builder/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - set_fact: 3 | koji_builder_koji_hub_url: "https://{{ koji_builder_koji_hub_host }}.{{ meta.namespace }}.svc:{{ koji_builder_koji_hub_port }}" 4 | - block: 5 | - name: retrieve mbox resource 6 | k8s_info: 7 | api_version: apps.fedoraproject.org/v1alpha1 8 | kind: Mbox 9 | namespace: "{{ meta.namespace }}" 10 | name: "{{ koji_builder_mbox }}" 11 | register: k8s_mboxes 12 | - fail: 13 | msg: "Failed to find mbox {{ koji_builder_mbox }} in namespace {{ meta.namespace }}" 14 | when: k8s_mboxes.resources|length == 0 15 | when: koji_builder_mbox|length > 0 16 | 17 | - block: 18 | - name: Ensure koji-builder configmap is updated 19 | template: 20 | src: configmap.yml.j2 21 | dest: /tmp/configmap.yml 22 | - k8s: 23 | state: present 24 | src: /tmp/configmap.yml 25 | wait: true 26 | namespace: "{{ meta.namespace }}" 27 | - file: 28 | path: /tmp/configmap.yml 29 | state: absent 30 | 31 | - include_tasks: cert.yml 32 | 33 | - block: 34 | - name: retrieve and set shared pvc name var 35 | k8s_info: 36 | api_version: apps.fedoraproject.org/v1alpha1 37 | kind: Mbox 38 | namespace: "{{ meta.namespace }}" 39 | name: "{{ koji_builder_mbox }}" 40 | register: k8s_mboxes 41 | - fail: 42 | msg: "Failed to find mbox {{ koji_builder_mbox }} in namespace {{ meta.namespace }}" 43 | when: k8s_mboxes.resources|length == 0 44 | - set_fact: 45 | koji_builder_pvc_name: "{{ k8s_mboxes.resources[0].spec.koji_pvc_name }}" 46 | when: koji_builder_mbox|length > 0 47 | 48 | - block: 49 | - name: add default koji host 50 | k8s_info: 51 | api_version: v1 52 | kind: Secret 53 | namespace: "{{ meta.namespace }}" 54 | name: "{{ koji_builder_admin_secret }}" 55 | register: k8s_res 56 | - fail: 57 | msg: "Secret not found: {{ koji_builder_admin_secret }}" 58 | when: k8s_res.resources|length == 0 59 | - set_fact: 60 | koji_admin_secret: "{{ k8s_res.resources[0] | from_yaml }}" 61 | - copy: 62 | content: "{{ koji_admin_secret.data['client.pem'] | b64decode }}" 63 | dest: "{{ koji_dir.path }}/admin.pem" 64 | - koji_host: 65 | server: "{{ koji_builder_koji_hub_url }}/kojihub" 66 | host: "{{ koji_builder_host_name }}" 67 | archs: "{{ koji_builder_host_archs }}" 68 | channels: "{{ koji_builder_host_channels }}" 69 | ssl_auth: 70 | cert: "{{ koji_dir.path }}/admin.pem" 71 | serverca: "{{ koji_dir.path }}/ca.pem" 72 | verify: "{{ koji_builder_ssl_verify }}" 73 | - file: 74 | state: absent 75 | path: "{{ koji_dir.path }}" 76 | 77 | - block: 78 | - name: Apply koji-builder deployment 79 | template: 80 | src: deployment.yml.j2 81 | dest: /tmp/deployment.yml 82 | - k8s: 83 | state: present 84 | src: /tmp/deployment.yml 85 | wait: true 86 | namespace: "{{ meta.namespace }}" 87 | - file: 88 | path: /tmp/deployment.yml 89 | state: absent 90 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-builder/templates/configmap.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ koji_builder_configmap }} 5 | labels: 6 | app: koji-builder 7 | data: 8 | kojid.conf: |- 9 | [kojid] 10 | maxjobs={{ koji_builder_maxjobs }} 11 | use_createrepo_c=True 12 | topurl = {{ koji_builder_koji_hub_url }}/pkgs 13 | vendor={{ koji_builder_vendor }} 14 | packager={{ koji_builder_vendor }} 15 | distribution={{ koji_builder_vendor }} 16 | mockhost=redhat-linux-gnu 17 | server={{ koji_builder_koji_hub_url }}/kojihub 18 | build_arch_can_fail = True 19 | plugins= 20 | 21 | ; Configuration authentication 22 | serverca = /etc/cacert/cert 23 | cert=/etc/clientcert/tls.pem 24 | 25 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-builder/templates/deployment.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: koji-builder 5 | labels: 6 | app: koji-builder 7 | spec: 8 | replicas: {{ koji_builder_replicas|int }} 9 | selector: 10 | matchLabels: 11 | app: koji-builder 12 | template: 13 | metadata: 14 | labels: 15 | app: koji-builder 16 | spec: 17 | containers: 18 | - name: koji-builder 19 | image: {{ koji_builder_image }} 20 | resources: {} 21 | livenessProbe: 22 | exec: 23 | command: 24 | - pgrep 25 | - kojid 26 | initialDelaySeconds: 5 27 | periodSeconds: 15 28 | volumeMounts: 29 | - name: config-volume 30 | mountPath: /etc/kojid 31 | readOnly: true 32 | - name: cacert-volume 33 | mountPath: /etc/cacert 34 | readOnly: true 35 | - name: client-cert-volume 36 | mountPath: /etc/clientcert 37 | readOnly: true 38 | - name: koji-builder-mnt 39 | mountPath: /mnt/koji 40 | volumes: 41 | - name: config-volume 42 | configMap: 43 | name: "{{ koji_builder_configmap }}" 44 | - name: cacert-volume 45 | secret: 46 | secretName: "{{ koji_builder_cacert_secret }}" 47 | - name: client-cert-volume 48 | secret: 49 | secretName: "{{ koji_builder_client_cert_secret }}" 50 | - name: koji-builder-mnt 51 | persistentVolumeClaim: 52 | claimName: "{{ koji_builder_shared_pvc }}" 53 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-hub/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for koji-hub 3 | koji_hub_image: "{{ image | default('quay.io/fedora/koji-hub:latest') }}" 4 | koji_hub_replicas: "{{ replicas | default(1) }}" 5 | 6 | koji_hub_postgres_secret: "{{ postgres_secret | default('postgres') }}" 7 | 8 | koji_hub_configmap: "{{ configmap | default('koji-hub-configmap') }}" 9 | koji_hub_ca_cert_secret: "{{ ca_cert_secret | default('koji-hub-ca-cert') }}" 10 | koji_hub_service_cert_secret: "{{ service_cert_secret | default('koji-hub-service-cert') }}" 11 | koji_hub_messaging_cert_secret: "{{ messaging_cert_secret | default('koji-hub-msg') }}" 12 | 13 | koji_hub_httpd_pvc_name: "{{ httpd_pvc_name | default('koji-hub-httpd-pvc') }}" 14 | koji_hub_httpd_pvc_size: "{{ httpd_pvc_size | default('1Gi') }}" 15 | 16 | koji_hub_mnt_pvc_name: "{{ mnt_pvc_name | default('koji-hub-mnt-pvc') }}" 17 | koji_hub_mnt_pvc_size: "{{ mnt_pvc_size | default('10Gi') }}" 18 | 19 | koji_hub_http_port: "{{ http_port | default('8080') }}" 20 | koji_hub_https_port: "{{ https_port | default('8443') }}" 21 | koji_hub_svc_name: "{{ svc_name | default('koji-hub') }}" 22 | koji_hub_http_enabled: "{{ http_enabled | default(false) }}" 23 | koji_hub_https_enabled: "{{ https_enabled | default(true) }}" 24 | koji_hub_host: "{{ host | default('kojihub.mbox.dev') }}" 25 | 26 | koji_hub_ingress_backend: "{{ ingress_backend | default('nginx') }}" 27 | 28 | koji_hub_admin_client_cert: "{{ admin_client_cert | default('koji-hub-admin-cert') }}" 29 | koji_hub_admin_username: "{{ admin_username | default('kojiadmin') }}" 30 | 31 | koji_mbox: "{{ mbox | default('') }}" 32 | 33 | koji_hub_web_client_cert: "{{ web_client_cert | default('koji-hub-web-client-cert') }}" 34 | koji_hub_web_client_username: "{{ web_client_username | default('kojiweb') }}" 35 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-hub/tasks/pvc.yml: -------------------------------------------------------------------------------- 1 | - name: Ensure PVC is present and PV is bound 2 | template: 3 | src: pvc.yml.j2 4 | dest: /tmp/pvc.yml 5 | 6 | - k8s: 7 | state: present 8 | src: /tmp/pvc.yml 9 | wait: true 10 | namespace: "{{ pvc_namespace }}" 11 | 12 | - file: 13 | path: /tmp/pvc.yml 14 | state: absent 15 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-hub/templates/cert-secret.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ cert_name }} 5 | labels: 6 | app: koji-hub 7 | data: 8 | {{ cert_key_name }}: {{ cert_data | b64encode }} 9 | {% if pk_key_name is defined %} 10 | {{ pk_key_name }}: {{ key_data | b64encode }} 11 | {% endif %} 12 | {% if ca_name is defined %} 13 | {{ ca_name }}: {{ ca_data | b64encode }} 14 | {% endif %} 15 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-hub/templates/deployment.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: koji-hub 5 | labels: 6 | app: koji-hub 7 | spec: 8 | replicas: {{ koji_hub_replicas|int }} 9 | selector: 10 | matchLabels: 11 | app: koji-hub 12 | template: 13 | metadata: 14 | labels: 15 | app: koji-hub 16 | spec: 17 | containers: 18 | - name: koji-hub 19 | image: "{{ koji_hub_image }}" 20 | livenessProbe: 21 | tcpSocket: 22 | port: {{ koji_hub_http_port }} 23 | readinessProbe: 24 | exec: 25 | command: 26 | - /readiness.sh 27 | initialDelaySeconds: 5 28 | periodSeconds: 15 29 | ports: 30 | - containerPort: {{ koji_hub_http_port }} 31 | - containerPort: {{ koji_hub_https_port }} 32 | envFrom: 33 | - secretRef: 34 | name: {{ koji_hub_postgres_secret }} 35 | volumeMounts: 36 | - name: config-volume 37 | mountPath: /etc/koji-hub 38 | readOnly: true 39 | - name: cacert-volume 40 | mountPath: /etc/cacert 41 | readOnly: true 42 | - name: webcert-volume 43 | mountPath: /etc/webcert 44 | readOnly: true 45 | - name: service-cert-volume 46 | mountPath: /etc/servicecert 47 | readOnly: true 48 | - name: koji-hub-httpd 49 | mountPath: /httpdir 50 | - name: koji-hub-mnt 51 | mountPath: /mnt/koji 52 | - name: koji-hub-msg 53 | mountPath: /etc/msgcert 54 | volumes: 55 | - name: cacert-volume 56 | secret: 57 | secretName: "{{ koji_hub_ca_cert_secret }}" 58 | - name: service-cert-volume 59 | secret: 60 | secretName: "{{ koji_hub_service_cert_secret }}" 61 | - name: webcert-volume 62 | secret: 63 | secretName: "{{ koji_hub_web_client_cert }}" 64 | - name: config-volume 65 | configMap: 66 | name: "{{ koji_hub_configmap }}" 67 | - name: koji-hub-httpd 68 | persistentVolumeClaim: 69 | claimName: "{{ koji_hub_httpd_pvc_name }}" 70 | - name: koji-hub-mnt 71 | persistentVolumeClaim: 72 | claimName: "{{ koji_hub_mnt_pvc_name }}" 73 | - name: koji-hub-msg 74 | secretName: 75 | name: {{ koji_hub_messaging_cert_secret }} 76 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-hub/templates/ingress.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: {{ koji_hub_ingress_name }} 5 | labels: 6 | app: koji-hub 7 | {% if koji_hub_ingress_backend == 'nginx' %} 8 | annotations: 9 | kubernetes.io/ingress.class: nginx 10 | kubernetes.io/ingress.allow-http: "false" 11 | nginx.ingress.kubernetes.io/ssl-passthrough: "true" 12 | nginx.ingress.kubernetes.io/force-ssl-redirect: "true" 13 | nginx.ingress.kubernetes.io/secure-backends: "true" 14 | {% endif %} 15 | spec: 16 | {% if koji_hub_https_enabled %} 17 | tls: 18 | - hosts: 19 | - {{ koji_hub_host }} 20 | secretName: {{ koji_hub_service_cert_secret }} 21 | {% endif %} 22 | rules: 23 | - http: 24 | paths: 25 | - path: /kojihub 26 | pathType: Prefix 27 | backend: 28 | serviceName: {{ koji_hub_ingress_svc }} 29 | servicePort: {{ koji_hub_http_port }} 30 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-hub/templates/kojiadmin.conf.j2: -------------------------------------------------------------------------------- 1 | [kojiadmin] 2 | weburl = https://{{ koji_hub_svc_name }}:{{ koji_hub_https_port }}/koji 3 | topurl = https://{{ koji_hub_svc_name }}:{{ koji_hub_https_port }} 4 | server = https://{{ koji_hub_svc_name }}:{{ koji_hub_https_port }}/kojihub 5 | ;auth 6 | cert = {{ kojiadmin_cert_path }} 7 | serverca = {{ kojiadmin_ca_cert_path }} 8 | authtype = ssl 9 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-hub/templates/openshift-route.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: route.openshift.io/v1 2 | kind: Route 3 | metadata: 4 | name: "{{ koji_hub_route_name }}" 5 | labels: 6 | app: koji-hub 7 | service: koji-hub 8 | spec: 9 | to: 10 | kind: Service 11 | name: "{{ koji_hub_route_svc }}" 12 | weight: 100 13 | port: 14 | targetPort: https 15 | tls: 16 | termination: passthrough 17 | insecureEdgeTerminationPolicy: None 18 | wildcardPolicy: None -------------------------------------------------------------------------------- /mbox-operator/roles/koji-hub/templates/pvc.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: {{ pvc_name }} 5 | labels: 6 | app: koji-hub 7 | spec: 8 | accessModes: 9 | - {{ pvc_mode }} 10 | resources: 11 | requests: 12 | storage: {{ pvc_size }} 13 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-hub/templates/service.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ koji_hub_svc_name }} 5 | labels: 6 | app: koji-hub 7 | service: {{ koji_hub_svc_name }} 8 | spec: 9 | selector: 10 | app: koji-hub 11 | ports: 12 | {% if koji_hub_http_enabled %} 13 | - name: http 14 | port: {{ koji_hub_http_port }} 15 | targetPort: {{ koji_hub_http_port }} 16 | {% endif %} 17 | {% if koji_hub_https_enabled %} 18 | - name: https 19 | port: {{ koji_hub_https_port }} 20 | targetPort: {{ koji_hub_https_port }} 21 | {% endif %} 22 | -------------------------------------------------------------------------------- /mbox-operator/roles/koji-lib/tasks/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/mbbox/bc7cbdb74fd9ec0071617bbcf15f32f0e44935ac/mbox-operator/roles/koji-lib/tasks/main.yml -------------------------------------------------------------------------------- /mbox-operator/roles/kojira/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for kojira 3 | kojira_replicas: "{{ replicas | default(1) }}" 4 | kojira_image: "{{ image | default('quay.io/fedora/kojira:latest') }}" 5 | kojira_configmap: "{{ configmap | default('kojira-config') }}" 6 | kojira_hub_username: "{{ hub_username | default('kojira') }}" 7 | kojira_hub_host: "{{ hub_host | default('koji-hub:8443') }}" 8 | kojira_src: "{{ src | default('no') }}" 9 | kojira_max_repo_tasks: "{{ max_repo_tasks | default(15) }}" 10 | kojira_repo_tasks_limit: "{{ repo_tasks_limit | default(15) }}" 11 | 12 | kojira_admin_secret: "{{ admin_secret | default('kojira-admin-cert') }}" 13 | kojira_cacert_secret: "{{ cacert_secret|default('kojira-ca-cert') }}" 14 | kojira_client_cert_secret: "{{ client_cert_secret|default('kojira-client-cert') }}" 15 | 16 | kojira_shared_pvc: "{{ shared_pvc | default('koji-hub-mnt-pvc') }}" 17 | 18 | kojira_builder_mbox: "{{ mbox | default('') }}" 19 | -------------------------------------------------------------------------------- /mbox-operator/roles/kojira/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - role: koji-lib 3 | -------------------------------------------------------------------------------- /mbox-operator/roles/kojira/tasks/cert.yml: -------------------------------------------------------------------------------- 1 | - name: create temporary cert directory 2 | tempfile: 3 | state: directory 4 | prefix: kojira 5 | suffix: cert 6 | register: cert_dir 7 | 8 | - name: create temporary koji directory 9 | tempfile: 10 | state: directory 11 | prefix: kojira 12 | suffix: koji 13 | register: koji_dir 14 | 15 | - block: 16 | - set_fact: 17 | kojira_cacert_secret: "{{ k8s_mboxes.resources[0].spec.root_ca_secret_name }}" 18 | when: kojira_builder_mbox|length > 0 19 | 20 | - k8s_info: 21 | api_version: v1 22 | kind: Secret 23 | name: "{{ kojira_client_cert_secret }}" 24 | namespace: "{{ meta.namespace }}" 25 | register: clientcert_query 26 | 27 | - name: Retrieve ca secret 28 | block: 29 | - k8s_info: 30 | api_version: v1 31 | kind: Secret 32 | name: "{{ kojira_cacert_secret }}" 33 | namespace: "{{ meta.namespace }}" 34 | register: k8s_secrets 35 | - fail: 36 | msg: "Secret {{ kojira_cacert_secret }} not found." 37 | when: k8s_secrets.resources|length == 0 38 | - set_fact: 39 | ca: "{{ k8s_secrets.resources[0] }}" 40 | - copy: 41 | content: "{{ ca.data.cert | b64decode }}" 42 | dest: "{{ cert_dir.path }}/ca_cert.pem" 43 | - copy: 44 | content: "{{ ca.data.key | b64decode }}" 45 | dest: "{{ cert_dir.path }}/ca_key.pem" 46 | when: clientcert_query.resources|length == 0 47 | - copy: 48 | content: "{{ ca.data.cert | b64decode }}" 49 | dest: "{{ koji_dir.path }}/ca.pem" 50 | 51 | - name: Client certificate creation 52 | block: 53 | - openssl_privatekey: 54 | path: "{{ cert_dir.path }}/client_key.pem" 55 | size: 4096 56 | - openssl_csr: 57 | path: "{{ cert_dir.path }}/client_req.pem" 58 | privatekey_path: "{{ cert_dir.path }}/client_key.pem" 59 | common_name: "{{ kojira_hub_username }}" 60 | - openssl_certificate: 61 | path: "{{ cert_dir.path }}/client_cert.pem" 62 | csr_path: "{{ cert_dir.path }}/client_req.pem" 63 | ownca_path: "{{ cert_dir.path }}/ca_cert.pem" 64 | ownca_privatekey_path: "{{ cert_dir.path }}/ca_key.pem" 65 | provider: ownca 66 | when: clientcert_query.resources|length == 0 67 | 68 | - name: Kubernetes client certificate secret creation 69 | block: 70 | - k8s: 71 | definition: 72 | apiVersion: v1 73 | kind: Secret 74 | metadata: 75 | name: "{{ kojira_client_cert_secret }}" 76 | namespace: "{{ meta.namespace }}" 77 | labels: 78 | app: kojira 79 | data: 80 | client.pem: "{{ (lookup('file', cert_dir.path + '/client_key.pem') + '\n' + lookup('file', cert_dir.path + '/client_cert.pem')) | b64encode }}" 81 | when: clientcert_query.resources|length == 0 82 | 83 | - name: cleanup 84 | file: 85 | path: "{{ cert_dir.path }}" 86 | state: absent 87 | -------------------------------------------------------------------------------- /mbox-operator/roles/kojira/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create temporary kojira directory 3 | tempfile: 4 | state: directory 5 | prefix: kojira 6 | suffix: deploy 7 | register: kojira_dir 8 | 9 | - block: 10 | - name: retrieve mbox resource 11 | k8s_info: 12 | api_version: apps.fedoraproject.org/v1alpha1 13 | kind: Mbox 14 | namespace: "{{ meta.namespace }}" 15 | name: "{{ kojira_builder_mbox }}" 16 | register: k8s_mboxes 17 | - fail: 18 | msg: "Failed to find mbox {{ kojira_builder_mbox }} in namespace {{ meta.namespace }}" 19 | when: k8s_mboxes.resources|length == 0 20 | when: kojira_builder_mbox|length > 0 21 | 22 | - include_tasks: cert.yml 23 | 24 | - block: 25 | - name: ensure kojira configmap 26 | template: 27 | src: kojira.configmap.yaml.j2 28 | dest: "{{ kojira_dir.path }}/kojira.configmap.yaml" 29 | - k8s: 30 | state: present 31 | wait: true 32 | namespace: "{{ meta.namespace }}" 33 | src: "{{ kojira_dir.path }}/kojira.configmap.yaml" 34 | 35 | - block: 36 | - name: retrieve and set shared pvc name var 37 | k8s_info: 38 | api_version: apps.fedoraproject.org/v1alpha1 39 | kind: Mbox 40 | namespace: "{{ meta.namespace }}" 41 | name: "{{ kojira_builder_mbox }}" 42 | register: k8s_mboxes 43 | - fail: 44 | msg: "Failed to find mbox {{ kojira_builder_mbox }} in namespace {{ meta.namespace }}" 45 | when: k8s_mboxes.resources|length == 0 46 | - set_fact: 47 | kojira_shared_pvc: "{{ k8s_mboxes.resources[0].spec.koji_pvc_name }}" 48 | when: kojira_builder_mbox|length > 0 49 | 50 | - block: 51 | - name: ensure kojira deployment 52 | template: 53 | src: kojira.deployment.yaml.j2 54 | dest: "{{ kojira_dir.path }}/kojira.deployment.yaml" 55 | - k8s: 56 | state: present 57 | wait: true 58 | namespace: "{{ meta.namespace }}" 59 | src: "{{ kojira_dir.path }}/kojira.deployment.yaml" 60 | 61 | - block: 62 | - name: setup kojira user 63 | k8s_info: 64 | api_version: v1 65 | kind: Secret 66 | namespace: "{{ meta.namespace }}" 67 | name: "{{ kojira_admin_secret }}" 68 | register: k8s_res 69 | - fail: 70 | msg: "Secret not found: {{ kojira_admin_secret }}" 71 | when: k8s_res.resources|length == 0 72 | - set_fact: 73 | koji_admin_secret: "{{ k8s_res.resources[0] | from_yaml }}" 74 | - copy: 75 | content: "{{ koji_admin_secret.data['client.pem'] | b64decode }}" 76 | dest: "{{ kojira_dir.path }}/admin.pem" 77 | # 78 | - k8s_info: 79 | api_version: v1 80 | kind: Secret 81 | namespace: "{{ meta.namespace }}" 82 | name: "{{ kojira_cacert_secret }}" 83 | register: k8s_res1 84 | - fail: 85 | msg: "Secret not found: koji-hub-ca-cert" 86 | when: k8s_res1.resources|length == 0 87 | - set_fact: 88 | koji_ca_secret: "{{ k8s_res1.resources[0] | from_yaml }}" 89 | - copy: 90 | content: "{{ koji_ca_secret.data['cert'] | b64decode }}" 91 | dest: "{{ kojira_dir.path }}/ca.pem" 92 | # 93 | - koji_user: 94 | server: "https://{{ kojira_hub_host }}/kojihub" 95 | username: "{{ kojira_hub_username }}" 96 | permissions: 97 | - repo 98 | ssl_auth: 99 | cert: "{{ kojira_dir.path }}/admin.pem" 100 | serverca: "{{ kojira_dir.path }}/ca.pem" 101 | verify: false 102 | - file: 103 | state: absent 104 | path: "{{ koji_dir.path }}" 105 | 106 | 107 | - name: cleanup 108 | file: 109 | path: "{{ kojira_dir.path }}" 110 | state: absent 111 | -------------------------------------------------------------------------------- /mbox-operator/roles/kojira/templates/kojira.configmap.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ kojira_configmap }} 5 | labels: 6 | app: kojira 7 | data: 8 | kojira.conf: |- 9 | [kojira] 10 | ; Configuration authentication 11 | serverca = /etc/cacert/cert 12 | user={{ kojira_hub_username }} 13 | cert=/etc/clientcert/client.pem 14 | 15 | server=https://{{ kojira_hub_host }}/kojihub 16 | with_src={{ kojira_src }} 17 | max_repo_tasks={{ kojira_max_repo_tasks }} 18 | repo_tasks_limit={{ kojira_repo_tasks_limit }} 19 | logfile=/dev/stdout 20 | -------------------------------------------------------------------------------- /mbox-operator/roles/kojira/templates/kojira.deployment.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: kojira 5 | labels: 6 | app: kojira 7 | spec: 8 | replicas: {{ kojira_replicas|int }} 9 | selector: 10 | matchLabels: 11 | app: kojira 12 | template: 13 | metadata: 14 | labels: 15 | app: kojira 16 | spec: 17 | containers: 18 | - name: kojira 19 | image: "{{ kojira_image }}" 20 | resources: {} 21 | livenessProbe: 22 | exec: 23 | command: 24 | - pgrep 25 | - kojira 26 | initialDelaySeconds: 5 27 | periodSeconds: 15 28 | volumeMounts: 29 | - name: config-volume 30 | mountPath: /etc/kojira 31 | readOnly: true 32 | - name: cacert-volume 33 | mountPath: /etc/cacert 34 | readOnly: true 35 | - name: client-cert-volume 36 | mountPath: /etc/clientcert 37 | readOnly: true 38 | - name: koji-shared 39 | mountPath: /mnt/koji 40 | volumes: 41 | - name: config-volume 42 | configMap: 43 | name: "{{ kojira_configmap }}" 44 | - name: cacert-volume 45 | secret: 46 | secretName: "{{ kojira_cacert_secret }}" 47 | - name: client-cert-volume 48 | secret: 49 | secretName: "{{ kojira_client_cert_secret }}" 50 | - name: koji-shared 51 | persistentVolumeClaim: 52 | claimName: "{{ kojira_shared_pvc }}" 53 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbox/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ========= 3 | 4 | This role deploys mbbox - only usable in the operator-sdk context. 5 | 6 | 7 | License 8 | ------- 9 | 10 | MIT -------------------------------------------------------------------------------- /mbox-operator/roles/mbox/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for mbox 3 | mbox_psql_secret_name: "{{ psql_secret_name | default('postgres') }}" 4 | mbox_koji_pvc_name: "{{ koji_pvc_name | default('mbox-koji-mnt') }}" 5 | mbox_koji_pvc_size: "{{ koji_pvc_size | default('10Gi') }}" 6 | mbox_root_ca_secret_name: "{{ root_ca_secret_name | default('mbox-root-ca') }}" 7 | mbox_koji_hub_host: "{{ koji_hub_host | default('koji-hub:8443') }}" 8 | mbox_mbs: "{{ mbs | default({}) }}" 9 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbox/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for mbox 3 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbox/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: CPE Team 3 | description: Mbox Operator 4 | company: Red Hat 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Some suggested licenses: 11 | # - BSD (default) 12 | # - MIT 13 | # - GPLv2 14 | # - GPLv3 15 | # - Apache 16 | # - CC-BY 17 | license: MIT 18 | 19 | min_ansible_version: 2.9 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # Optionally specify the branch Galaxy will use when accessing the GitHub 25 | # repo for this role. During role install, if no tags are available, 26 | # Galaxy will use this branch. During import Galaxy will access files on 27 | # this branch. If Travis integration is configured, only notifications for this 28 | # branch will be accepted. Otherwise, in all cases, the repo's default branch 29 | # (usually master) will be used. 30 | # github_branch: 31 | 32 | # 33 | # Provide a list of supported platforms, and for each platform a list of versions. 34 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 35 | # To view available platforms and versions (or releases), visit: 36 | # https://galaxy.ansible.com/api/v1/platforms/ 37 | # 38 | # platforms: 39 | # - name: Fedora 40 | # versions: 41 | # - all 42 | # - 25 43 | # - name: SomePlatform 44 | # versions: 45 | # - all 46 | # - 1.0 47 | # - 7 48 | # - 99.99 49 | 50 | galaxy_tags: [] 51 | # List tags for your role here, one per line. A tag is a keyword that describes 52 | # and categorizes the role. Users find roles by searching for tags. Be sure to 53 | # remove the '[]' above, if you add tags to this list. 54 | # 55 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 56 | # Maximum 20 tags per role. 57 | 58 | dependencies: [] 59 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 60 | # if you add dependencies to this list. 61 | collections: 62 | - operator_sdk.util 63 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbox/tasks/cert.yml: -------------------------------------------------------------------------------- 1 | - block: 2 | - name: create temporary cert directory 3 | set_fact: 4 | mbox_cert_dir: "{{ mbox_dir.path }}/certs" 5 | - file: 6 | path: "{{ mbox_cert_dir }}" 7 | state: directory 8 | 9 | - k8s_info: 10 | api_version: v1 11 | kind: Secret 12 | namespace: "{{ meta.namespace }}" 13 | name: "{{ mbox_root_ca_secret_name }}" 14 | register: k8s_secrets 15 | 16 | - block: 17 | - name: validate existing cert 18 | set_fact: 19 | k8s_mbox_secret: "{{ k8s_secrets.resources[0] | from_yaml }}" 20 | - fail: 21 | msg: "ca_req.pem key not found in {{ mbox_root_ca_secret_name }} secret" 22 | when: "not 'ca_req.pem' in k8s_mbox_secret.data" 23 | - fail: 24 | msg: "ca_cert.pem key not found in {{ mbox_root_ca_secret_name }} secret" 25 | when: "not 'ca_cert.pem' in k8s_mbox_secret.data" 26 | - fail: 27 | msg: "ca_key.pem key not found in {{ mbox_root_ca_secret_name }} secret" 28 | when: "not 'ca_key.pem' in k8s_mbox_secret.data" 29 | when: k8s_secrets.resources|length == 1 30 | 31 | - block: 32 | - name: create self signed cert 33 | openssl_privatekey: 34 | path: "{{ mbox_cert_dir }}/ca_key.pem" 35 | size: 4096 36 | - openssl_csr: 37 | path: "{{ mbox_cert_dir }}/ca_req.pem" 38 | privatekey_path: "{{ mbox_cert_dir }}/ca_key.pem" 39 | common_name: "{{ mbox_koji_hub_host }}" 40 | create_subject_key_identifier: true 41 | key_usage: 42 | - cRLSign 43 | - dataEncipherment 44 | - digitalSignature 45 | - keyCertSign 46 | - keyEncipherment 47 | - nonRepudiation 48 | basic_constraints: 49 | - 'CA:TRUE' 50 | - openssl_certificate: 51 | path: "{{ mbox_cert_dir }}/ca_cert.pem" 52 | privatekey_path: "{{ mbox_cert_dir }}/ca_key.pem" 53 | csr_path: "{{ mbox_cert_dir }}/ca_req.pem" 54 | provider: selfsigned 55 | - set_fact: 56 | ca_req: "{{ lookup('file', mbox_cert_dir + '/ca_req.pem') }}" 57 | ca_cert: "{{ lookup('file', mbox_cert_dir + '/ca_cert.pem') }}" 58 | ca_key: "{{ lookup('file', mbox_cert_dir + '/ca_key.pem') }}" 59 | - k8s: 60 | wait: true 61 | state: present 62 | definition: 63 | apiVersion: v1 64 | kind: Secret 65 | metadata: 66 | name: "{{ mbox_root_ca_secret_name }}" 67 | namespace: "{{ meta.namespace }}" 68 | labels: 69 | app: mbox 70 | data: 71 | ca_req.pem: "{{ lookup('file', mbox_cert_dir + '/ca_req.pem') | b64encode }}" 72 | ca_cert.pem: "{{ lookup('file', mbox_cert_dir + '/ca_cert.pem') | b64encode }}" 73 | ca_key.pem: "{{ lookup('file', mbox_cert_dir + '/ca_key.pem') | b64encode }}" 74 | when: k8s_secrets.resources|length == 0 75 | 76 | - name: delete temporary cert directory 77 | file: 78 | path: "{{ mbox_cert_dir }}" 79 | state: absent 80 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbox/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: mbox.tmpdir.create 3 | tempfile: 4 | state: directory 5 | prefix: mbox 6 | suffix: deploy 7 | register: mbox_dir 8 | 9 | - include_tasks: cert.yml 10 | 11 | - block: 12 | - name: mbox.secret.psql.read 13 | k8s_info: 14 | api_version: v1 15 | kind: Secret 16 | namespace: "{{ meta.namespace }}" 17 | name: "{{ mbox_psql_secret_name }}" 18 | register: k8s_psql_secrets 19 | - fail: 20 | msg: "Secret {{ mbox_psql_secret_name }} not found in namespace {{ meta.namespace }}" 21 | when: k8s_psql_secrets.resources|length == 0 22 | 23 | - block: 24 | - name: mbox.pvc 25 | k8s_info: 26 | api_version: v1 27 | kind: PersistentVolumeClaim 28 | namespace: "{{ meta.namespace }}" 29 | name: "{{ mbox_koji_pvc_name }}" 30 | register: k8s_mbox_pvc_query 31 | - k8s: 32 | state: present 33 | wait: true 34 | definition: 35 | apiVersion: v1 36 | kind: PersistentVolumeClaim 37 | metadata: 38 | namespace: "{{ meta.namespace }}" 39 | name: "{{ mbox_koji_pvc_name }}" 40 | labels: 41 | app: mbox 42 | spec: 43 | accessModes: 44 | - ReadWriteMany 45 | resources: 46 | requests: 47 | storage: "{{ mbox_koji_pvc_size }}" 48 | selector: 49 | matchLabels: 50 | app: mbox 51 | when: k8s_mbox_pvc_query.resources|length == 0 52 | 53 | - block: 54 | - name: mbox.mbs.configmap.create 55 | k8s_info: 56 | api_version: v1 57 | kind: Configmap 58 | namespace: "{{ meta.namespace }}" 59 | name: "{{ mbox_mbs.configmap }}" 60 | register: k8s_mbs_cm 61 | - template: 62 | src: mbs.configmap.yaml.j2 63 | dest: "{{ mbox_dir.path }}/mbs.configmap.yaml" 64 | vars: 65 | mbs_configmap: "{{ mbox_mbs.configmap }}" 66 | mbs_fedora_versions: "{{ mbox_mbs.fedora_versions }}" 67 | mbs_hub_host: "{{ mbox_koji_hub_host }}" 68 | mbs_messaging_system: "{{ mbox_mbs.backend_config_messaging }}" 69 | mbs_topic_prefix: "{{ mbox_mbs.topic_prefix }}" 70 | mbs_scm_url: "{{ mbox_mbs.scm_repo_url }}" 71 | mbs_rpms_default_repository: "{{ mbox_mbs.rpm_repo_url }}" 72 | mbs_rpms_default_cache: "{{ mbox_mbs.pkg_repo_url }}" 73 | mbs_modules_default_repository: "{{ mbox_mbs.scm_repo_url }}" 74 | mbs_psql_user: "{{ k8s_psql_secrets.resources[0].data.POSTGRES_USER | b64decode }}" 75 | mbs_psql_pass: "{{ k8s_psql_secrets.resources[0].data.POSTGRES_PASSWORD | b64decode }}" 76 | mbs_psql_hostname: "{{ k8s_psql_secrets.resources[0].data.POSTGRES_HOST | b64decode }}" 77 | mbs_psql_db_name: "{{ k8s_psql_secrets.resources[0].data.POSTGRES_DB | b64decode }}" 78 | mbs_pdc_url: "{{ mbox_mbs.pdc_url }}" 79 | mbs_oidc_required_scope: "{{ mbox_mbs.oidc_required_scope }}" 80 | when: k8s_mbs_cm.resources|length == 0 81 | - k8s: 82 | src: "{{ mbox_dir.path }}/mbs.configmap.yaml" 83 | wait: true 84 | state: present 85 | namespace: "{{ meta.namespace }}" 86 | when: k8s_mbs_cm.resources|length == 0 87 | when: mbox_mbs|length > 0 88 | 89 | - name: mbs.tmp_dir.delete 90 | file: 91 | path: "{{ mbox_dir.path }}" 92 | state: absent 93 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbox/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for mbox 3 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-backend/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for mbs-backend 3 | mbs_backend_replicas: "{{ replicas | default(1) }}" 4 | mbs_backend_image: "{{ image | default('quay.io/fedora/mbs-backend:latest') }}" 5 | mbs_backend_hub_username: "{{ hub_username | default('mbs') }}" 6 | mbs_backend_cacert_secret: "{{ cacert_secret|default('mbs-ca-cert') }}" 7 | mbs_backend_client_cert_secret: "{{ client_cert_secret|default('mbs-client-cert') }}" 8 | 9 | mbs_backend_postgres_secret: "{{ postgres_secret | default('postgres') }}" 10 | mbs_configmap: "{{ configmap | default('mbs-configmap') }}" 11 | mbs_fedora_versions: "{{ fedora_versions | default(['32']) }}" 12 | mbs_hub_host: "{{ hub_host | default('koji-hub:8443') }}" 13 | mbs_messaging_system: "{{ messaging_system | default('fedmsg') }}" 14 | mbs_topic_prefix: "{{ topic_prefix | default('org.fedoraproject.dev') }}" 15 | mbs_scm_url: "{{ scm_url | default('git+https://src.fedoraproject.org/modules/') }}" 16 | mbs_rpms_default_repository: "{{ rpms_default_repository|default('git+https://src.fedoraproject.org/rpms/') }}" 17 | mbs_rpms_default_cache: "{{ rpms_default_cache|default('https://src.fedoraproject.org/repo/pkgs/') }}" 18 | mbs_modules_default_repository: "{{ modules_default_repository|default('git+https://src.fedoraproject.org/modules/') }}" 19 | mbs_pdc_url: "{{ pdc_url|default('https://pdc.stg.fedoraproject.org/rest_api/v1') }}" 20 | mbs_oidc_required_scope: "{{ oidc_required_scope|default('https://mbs.fedoraproject.org/oidc/submit-build') }}" 21 | 22 | mbs_backend_shared_pvc: "{{ shared_pvc | default('koji-hub-mnt-pvc') }}" 23 | mbs_backend_mbox: "{{ mbox | default('') }}" 24 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-backend/tasks/cert.yml: -------------------------------------------------------------------------------- 1 | - name: ensure cert dir exists 2 | file: 3 | path: "{{ mbs_dir.path }}/certs" 4 | state: directory 5 | 6 | - block: 7 | - set_fact: 8 | mbs_backend_cacert_secret: "{{ k8s_mboxes.resources[0].spec.root_ca_secret_name }}" 9 | when: mbs_backend_mbox|length > 0 10 | 11 | - name: retrieve ca secret 12 | block: 13 | - k8s_info: 14 | api_version: v1 15 | kind: Secret 16 | name: "{{ mbs_backend_cacert_secret }}" 17 | namespace: "{{ meta.namespace }}" 18 | register: k8s_secrets 19 | - fail: 20 | msg: "Secret {{ mbs_backend_cacert_secret }} not found." 21 | when: k8s_secrets.resources|length == 0 22 | - set_fact: 23 | ca: "{{ k8s_secrets.resources[0] }}" 24 | - copy: 25 | content: "{{ ca.data.cert | b64decode }}" 26 | dest: "{{ mbs_dir.path }}/certs/ca_cert.pem" 27 | - copy: 28 | content: "{{ ca.data.key | b64decode }}" 29 | dest: "{{ mbs_dir.path }}/certs/ca_key.pem" 30 | - copy: 31 | content: "{{ ca.data.cert | b64decode }}" 32 | dest: "{{ mbs_dir.path }}/certs/ca.pem" 33 | 34 | - name: client certificate creation 35 | block: 36 | - openssl_privatekey: 37 | path: "{{ mbs_dir.path }}/certs/client_key.pem" 38 | size: 4096 39 | - openssl_csr: 40 | path: "{{ mbs_dir.path }}/certs/client_req.pem" 41 | privatekey_path: "{{ mbs_dir.path }}/certs/client_key.pem" 42 | common_name: "{{ mbs_backend_hub_username }}" 43 | - openssl_certificate: 44 | path: "{{ mbs_dir.path }}/certs/client_cert.pem" 45 | csr_path: "{{ mbs_dir.path }}/certs/client_req.pem" 46 | ownca_path: "{{ mbs_dir.path }}/certs/ca_cert.pem" 47 | ownca_privatekey_path: "{{ mbs_dir.path }}/certs/ca_key.pem" 48 | provider: ownca 49 | 50 | - name: kubernetes client certificate secret creation 51 | block: 52 | - k8s_info: 53 | api_version: v1 54 | kind: Secret 55 | name: "{{ mbs_backend_client_cert_secret }}" 56 | namespace: "{{ meta.namespace }}" 57 | register: clientcert_query 58 | - k8s: 59 | definition: 60 | apiVersion: v1 61 | kind: Secret 62 | metadata: 63 | name: "{{ mbs_backend_client_cert_secret }}" 64 | namespace: "{{ meta.namespace }}" 65 | labels: 66 | app: mbs-backend 67 | data: 68 | client.pem: "{{ (lookup('file', mbs_dir.path + '/certs/client_key.pem') + '\n' + lookup('file', mbs_dir.path + '/certs/client_cert.pem')) | b64encode }}" 69 | when: clientcert_query.resources|length == 0 70 | 71 | - name: cert dir cleanup 72 | file: 73 | path: "{{ mbs_dir.path }}/certs" 74 | state: absent 75 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-backend/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - block: 3 | - name: retrieve mbox resource 4 | k8s_info: 5 | api_version: apps.fedoraproject.org/v1alpha1 6 | kind: Mbox 7 | namespace: "{{ meta.namespace }}" 8 | name: "{{ mbs_backend_mbox }}" 9 | register: k8s_mboxes 10 | - fail: 11 | msg: "Failed to find mbox {{ mbs_backend_mbox }} in namespace {{ meta.namespace }}" 12 | when: k8s_mboxes.resources|length == 0 13 | when: mbs_backend_mbox|length > 0 14 | 15 | - set_fact: 16 | mbs_backend_postgres_secret: "{{ k8s_mboxes.resources[0].spec.psql_secret_name }}" 17 | mbs_configmap: "{{ k8s_mboxes.resources[0].spec.mbs.configmap }}" 18 | when: mbs_backend_mbox|length > 0 19 | 20 | - block: 21 | - name: Retrieve postgresql secret 22 | k8s_info: 23 | api_version: v1 24 | kind: Secret 25 | namespace: "{{ meta.namespace }}" 26 | name: "{{ mbs_backend_postgres_secret }}" 27 | register: k8s_psql_secrets 28 | - fail: 29 | msg: "Secret {{ mbs_backend_postgres_secret }} not found in namespace {{ meta.namespace }}" 30 | when: k8s_psql_secrets.resources|length == 0 31 | - set_fact: 32 | psql_secret: "{{ k8s_psql_secrets.resources[0] }}" 33 | 34 | - name: create temporary component directory 35 | tempfile: 36 | state: directory 37 | prefix: mbs 38 | suffix: backend 39 | register: mbs_dir 40 | 41 | - name: check if mbs-configmap exists 42 | k8s_info: 43 | api_version: v1 44 | kind: ConfigMap 45 | namespace: "{{ meta.namespace }}" 46 | name: "{{ mbs_configmap }}" 47 | register: k8s_mbs_cm 48 | 49 | - block: 50 | - name: ensure mbs configmap 51 | template: 52 | src: mbs-configmap.yaml.j2 53 | dest: "{{ mbs_dir.path }}/mbs-configmap.yaml" 54 | vars: 55 | mbs_psql_hostname: "{{ psql_secret.data.POSTGRES_HOST | b64decode }}" 56 | mbs_psql_db_name: "{{ psql_secret.data.POSTGRES_DB | b64decode }}" 57 | mbs_psql_user: "{{ psql_secret.data.POSTGRES_USER | b64decode }}" 58 | mbs_psql_pass: "{{ psql_secret.data.POSTGRES_PASSWORD | b64decode }}" 59 | - k8s: 60 | state: present 61 | wait: true 62 | namespace: "{{ meta.namespace }}" 63 | src: "{{ mbs_dir.path }}/mbs-configmap.yaml" 64 | when: k8s_mbs_cm.resources|length == 0 65 | 66 | - include_tasks: cert.yml 67 | 68 | - block: 69 | - name: retrieve and set shared pvc name var 70 | k8s_info: 71 | api_version: apps.fedoraproject.org/v1alpha1 72 | kind: Mbox 73 | namespace: "{{ meta.namespace }}" 74 | name: "{{ mbs_backend_mbox }}" 75 | register: k8s_mboxes 76 | - fail: 77 | msg: "Failed to find mbox {{ mbs_backend_mbox }} in namespace {{ meta.namespace }}" 78 | when: k8s_mboxes.resources|length == 0 79 | - set_fact: 80 | mbs_backend_shared_pvc: "{{ k8s_mboxes.resources[0].spec.koji_pvc_name }}" 81 | when: mbs_backend_mbox|length > 0 82 | 83 | - block: 84 | - name: ensure mbs-backend deployment 85 | template: 86 | src: deployment.yaml.j2 87 | dest: "{{ mbs_dir.path }}/deployment.yaml" 88 | - k8s: 89 | src: "{{ mbs_dir.path }}/deployment.yaml" 90 | state: present 91 | namespace: "{{ meta.namespace }}" 92 | wait: true 93 | 94 | - name: delete temporary component directory 95 | file: 96 | path: "{{ mbs_dir.path }}" 97 | state: absent 98 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-backend/templates/deployment.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: mbs-backend 5 | labels: 6 | app: mbs-backend 7 | spec: 8 | replicas: {{ mbs_backend_replicas|int }} 9 | selector: 10 | matchLabels: 11 | app: mbs-backend 12 | template: 13 | metadata: 14 | labels: 15 | app: mbs-backend 16 | spec: 17 | containers: 18 | - name: mbs-backend 19 | image: "{{ mbs_backend_image }}" 20 | resources: {} 21 | livenessProbe: 22 | exec: 23 | command: 24 | - pgrep 25 | - fedmsg-hub-3 26 | initialDelaySeconds: 5 27 | periodSeconds: 15 28 | volumeMounts: 29 | - name: config-volume 30 | mountPath: /etc/module-build-service 31 | readOnly: true 32 | - name: cacert-volume 33 | mountPath: /etc/cacert 34 | readOnly: true 35 | - name: client-cert-volume 36 | mountPath: /etc/clientcert 37 | readOnly: true 38 | - name: koji-shared 39 | mountPath: /mnt/koji 40 | volumes: 41 | - name: config-volume 42 | configMap: 43 | name: "{{ mbs_configmap }}" 44 | - name: cacert-volume 45 | secret: 46 | secretName: "{{ mbs_backend_cacert_secret }}" 47 | - name: client-cert-volume 48 | secret: 49 | secretName: "{{ mbs_backend_client_cert_secret }}" 50 | - name: koji-shared 51 | persistentVolumeClaim: 52 | claimName: "{{ mbs_backend_shared_pvc }}" 53 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-frontend/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for mbs-frontend 3 | mbs_frontend_replicas: "{{ replicas | default(1) }}" 4 | mbs_frontend_image: "{{ image | default('quay.io/fedora/mbs-frontend:latest') }}" 5 | 6 | mbs_frontend_configmap: "{{ configmap|default('mbs-frontend-configmap') }}" 7 | 8 | mbs_frontend_ca_cert_secret: "{{ ca_cert_secret|default('koji-hub-ca-cert') }}" 9 | mbs_frontend_koji_hub_host: "{{ koji_hub_host|default('koji-hub:8443') }}" 10 | mbs_frontend_postgres_secret: "{{ postgres_secret | default('postgres') }}" 11 | mbs_frontend_host: "{{ host|default('mbs.mbox.dev') }}" 12 | mbs_frontend_client_cert_secret: "{{ client_cert_secret|default('mbs-frontend-client-cert') }}" 13 | mbs_frontend_service_cert_secret: "{{ service_cert_secret|default('mbs-frontend-service-cert') }}" 14 | 15 | mbs_frontend_https_enabled: "{{ https_enabled|default(true) }}" 16 | mbs_frontend_http_port: "{{ http_port|default(8080) }}" 17 | mbs_frontend_https_port: "{{ https_port|default(8443) }}" 18 | 19 | mbs_frontend_svc_name: "{{ service_name|default('mbs') }}" 20 | mbs_frontend_ingress_backend: "{{ ingress_backend|default('nginx') }}" 21 | 22 | mbs_configmap: "{{ mbs_configmap|default('mbs-configmap') }}" 23 | mbs_fedora_versions: "{{ fedora_versions|default(['32']) }}" 24 | mbs_messaging_system: "{{ messaging_sytem|default('fedmsg') }}" 25 | mbs_topic_prefix: "{{ topic_prefix|default('org.fedoraproject.dev') }}" 26 | mbs_scm_url: "{{ scm_url|default('git+https://src.fedoraproject.org/modules/') }}" 27 | mbs_rpms_default_repository: "{{ rpms_default_repository|default('git+https://src.fedoraproject.org/rpms/') }}" 28 | mbs_rpms_default_cache: "{{ rpms_default_cache|default('https://src.fedoraproject.org/repo/pkgs/') }}" 29 | mbs_modules_default_repository: "{{ modules_default_repository|default('git+https://src.fedoraproject.org/modules/') }}" 30 | mbs_pdc_url: "{{ pdc_url|default('https://pdc.stg.fedoraproject.org/rest_api/v1') }}" 31 | mbs_oidc_required_scope: "{{ oidc_required_scope|default('https://mbs.fedoraproject.org/oidc/submit-build') }}" 32 | mbs_frontend_mbox: "{{ mbox | default('') }}" 33 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-frontend/tasks/cert.yml: -------------------------------------------------------------------------------- 1 | - name: create temporary cert directory 2 | tempfile: 3 | state: directory 4 | prefix: mbsfrontend 5 | suffix: cert 6 | register: cert_dir 7 | 8 | - block: 9 | - set_fact: 10 | mbs_frontend_ca_cert_secret: "{{ k8s_mboxes.resources[0].spec.root_ca_secret_name }}" 11 | when: mbs_frontend_mbox|length > 0 12 | 13 | - name: retrieve ca secret 14 | block: 15 | - k8s_info: 16 | api_version: v1 17 | kind: Secret 18 | name: "{{ mbs_frontend_ca_cert_secret }}" 19 | namespace: "{{ meta.namespace }}" 20 | register: k8s_secrets 21 | - fail: 22 | msg: "Secret {{ mbs_frontend_ca_cert_secret }} not found." 23 | when: k8s_secrets.resources|length == 0 24 | - set_fact: 25 | ca: "{{ k8s_secrets.resources[0] }}" 26 | - copy: 27 | content: "{{ ca.data.cert | b64decode }}" 28 | dest: "{{ cert_dir.path }}/ca_cert.pem" 29 | - copy: 30 | content: "{{ ca.data.key | b64decode }}" 31 | dest: "{{ cert_dir.path }}/ca_key.pem" 32 | - copy: 33 | content: "{{ ca.data.cert | b64decode }}" 34 | dest: "{{ cert_dir.path }}/ca.pem" 35 | 36 | - name: client certificate creation 37 | block: 38 | - openssl_privatekey: 39 | path: "{{ cert_dir.path }}/client_key.pem" 40 | size: 4096 41 | - openssl_csr: 42 | path: "{{ cert_dir.path }}/client_req.pem" 43 | privatekey_path: "{{ cert_dir.path }}/client_key.pem" 44 | common_name: "{{ mbs_frontend_koji_hub_host }}" 45 | - openssl_certificate: 46 | path: "{{ cert_dir.path }}/client_cert.pem" 47 | csr_path: "{{ cert_dir.path }}/client_req.pem" 48 | ownca_path: "{{ cert_dir.path }}/ca_cert.pem" 49 | ownca_privatekey_path: "{{ cert_dir.path }}/ca_key.pem" 50 | provider: ownca 51 | 52 | - name: server certificate creation 53 | block: 54 | - openssl_privatekey: 55 | path: "{{ cert_dir.path }}/server_key.pem" 56 | size: 4096 57 | - openssl_csr: 58 | path: "{{ cert_dir.path }}/server_req.pem" 59 | privatekey_path: "{{ cert_dir.path }}/server_key.pem" 60 | common_name: "{{ mbs_frontend_host }}" 61 | - openssl_certificate: 62 | path: "{{ cert_dir.path }}/server_cert.pem" 63 | csr_path: "{{ cert_dir.path }}/server_req.pem" 64 | ownca_path: "{{ cert_dir.path }}/ca_cert.pem" 65 | ownca_privatekey_path: "{{ cert_dir.path }}/ca_key.pem" 66 | provider: ownca 67 | 68 | - name: kubernetes client certificate secret creation 69 | block: 70 | - k8s_info: 71 | api_version: v1 72 | kind: Secret 73 | name: "{{ mbs_frontend_client_cert_secret }}" 74 | namespace: "{{ meta.namespace }}" 75 | register: clientcert_query 76 | - k8s: 77 | definition: 78 | apiVersion: v1 79 | kind: Secret 80 | metadata: 81 | name: "{{ mbs_frontend_client_cert_secret }}" 82 | namespace: "{{ meta.namespace }}" 83 | labels: 84 | app: mbs-frontend 85 | data: 86 | tls.crt: "{{ lookup('file', cert_dir.path + '/client_cert.pem') | b64encode }}" 87 | tls.key: "{{ lookup('file', cert_dir.path + '/client_key.pem') | b64encode }}" 88 | tls.pem: "{{ (lookup('file', cert_dir.path + '/client_key.pem') + '\n' + lookup('file', cert_dir.path + '/client_cert.pem')) | b64encode }}" 89 | type: kubernetes.io/tls 90 | when: clientcert_query.resources|length == 0 91 | 92 | - name: kubernetes server certificate secret creation 93 | block: 94 | - k8s_info: 95 | api_version: v1 96 | kind: Secret 97 | name: "{{ mbs_frontend_service_cert_secret }}" 98 | namespace: "{{ meta.namespace }}" 99 | register: servicecert_query 100 | - k8s: 101 | definition: 102 | apiVersion: v1 103 | kind: Secret 104 | metadata: 105 | name: "{{ mbs_frontend_service_cert_secret }}" 106 | namespace: "{{ meta.namespace }}" 107 | labels: 108 | app: mbs-frontend 109 | data: 110 | tls.crt: "{{ lookup('file', cert_dir.path + '/server_cert.pem') | b64encode }}" 111 | tls.key: "{{ lookup('file', cert_dir.path + '/server_key.pem') | b64encode }}" 112 | type: kubernetes.io/tls 113 | when: servicecert_query.resources|length == 0 114 | 115 | - name: cleanup 116 | file: 117 | path: "{{ cert_dir.path }}" 118 | state: absent 119 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-frontend/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - block: 3 | - name: retrieve mbox resource 4 | k8s_info: 5 | api_version: apps.fedoraproject.org/v1alpha1 6 | kind: Mbox 7 | namespace: "{{ meta.namespace }}" 8 | name: "{{ mbs_frontend_mbox }}" 9 | register: k8s_mboxes 10 | - fail: 11 | msg: "Failed to find mbox {{ mbs_frontend_mbox }} in namespace {{ meta.namespace }}" 12 | when: k8s_mboxes.resources|length == 0 13 | when: mbs_frontend_mbox|length > 0 14 | 15 | - set_fact: 16 | mbs_frontend_postgres_secret: "{{ k8s_mboxes.resources[0].spec.psql_secret_name }}" 17 | mbs_configmap: "{{ k8s_mboxes.resources[0].spec.mbs.configmap }}" 18 | when: mbs_frontend_mbox|length > 0 19 | 20 | - block: 21 | - name: retrieve postgresql secret 22 | k8s_info: 23 | api_version: v1 24 | kind: Secret 25 | namespace: "{{ meta.namespace }}" 26 | name: "{{ mbs_frontend_postgres_secret }}" 27 | register: k8s_psql_secrets 28 | - fail: 29 | msg: "Secret {{ mbs_frontend_postgres_secret }} not found in namespace {{ meta.namespace }}" 30 | when: k8s_psql_secrets.resources|length == 0 31 | - set_fact: 32 | psql_secret: "{{ k8s_psql_secrets.resources[0] }}" 33 | 34 | - name: create temporary mbs-frontend directory 35 | tempfile: 36 | state: directory 37 | prefix: mbs-frontend 38 | suffix: deploy 39 | register: mbs_frontend_dir 40 | 41 | - block: 42 | - name: ensure mbs-frontend configmap 43 | template: 44 | src: mbs-frontend.configmap.yaml.j2 45 | dest: "{{ mbs_frontend_dir.path }}/mbs-frontend.configmap.yaml" 46 | - k8s: 47 | state: present 48 | wait: true 49 | namespace: "{{ meta.namespace }}" 50 | src: "{{ mbs_frontend_dir.path }}/mbs-frontend.configmap.yaml" 51 | 52 | - name: check if mbs-configmap exists 53 | k8s_info: 54 | api_version: v1 55 | kind: ConfigMap 56 | namespace: "{{ meta.namespace }}" 57 | name: "{{ mbs_configmap }}" 58 | register: k8s_mbs_cm 59 | 60 | - block: 61 | - name: ensure mbs configmap 62 | template: 63 | src: mbs-configmap.yaml.j2 64 | dest: "{{ mbs_frontend_dir.path }}/mbs-configmap.yaml" 65 | vars: 66 | mbs_hub_host: "{{ mbs_frontend_koji_hub_host }}" 67 | mbs_psql_hostname: "{{ psql_secret.data.POSTGRES_HOST | b64decode }}" 68 | mbs_psql_db_name: "{{ psql_secret.data.POSTGRES_DB | b64decode }}" 69 | mbs_psql_user: "{{ psql_secret.data.POSTGRES_USER | b64decode }}" 70 | mbs_psql_pass: "{{ psql_secret.data.POSTGRES_PASSWORD | b64decode }}" 71 | - k8s: 72 | state: present 73 | wait: true 74 | namespace: "{{ meta.namespace }}" 75 | src: "{{ mbs_frontend_dir.path }}/mbs-configmap.yaml" 76 | when: k8s_mbs_cm.resources|length == 0 77 | 78 | - include_tasks: cert.yml 79 | 80 | - block: 81 | - name: ensure mbs-frontend deployment 82 | template: 83 | src: deployment.yaml.j2 84 | dest: "{{ mbs_frontend_dir.path }}/deployment.yaml" 85 | - k8s: 86 | src: "{{ mbs_frontend_dir.path }}/deployment.yaml" 87 | state: present 88 | namespace: "{{ meta.namespace }}" 89 | wait: true 90 | 91 | - name: delete temporary component directory 92 | file: 93 | path: "{{ mbs_frontend_dir.path }}" 94 | state: absent 95 | 96 | - block: 97 | - name: apply mbs-frontend http service and ingress 98 | template: 99 | src: service.yml.j2 100 | dest: /tmp/service.yml 101 | - k8s: 102 | state: present 103 | src: /tmp/service.yml 104 | wait: true 105 | namespace: "{{ meta.namespace }}" 106 | - template: 107 | src: ingress.yml.j2 108 | dest: /tmp/ingress.yml 109 | vars: 110 | mbs_frontend_ingress_name: mbs-frontend-http 111 | - k8s: 112 | state: present 113 | src: /tmp/ingress.yml 114 | wait: true 115 | namespace: "{{ meta.namespace }}" 116 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-frontend/templates/deployment.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: mbs-frontend 5 | labels: 6 | app: mbs-frontend 7 | spec: 8 | replicas: {{ mbs_frontend_replicas|int }} 9 | selector: 10 | matchLabels: 11 | app: mbs-frontend 12 | template: 13 | metadata: 14 | labels: 15 | app: mbs-frontend 16 | spec: 17 | containers: 18 | - name: mbs-frontend 19 | image: "{{ mbs_frontend_image }}" 20 | ports: 21 | - containerPort: 8443 22 | resources: {} 23 | livenessProbe: 24 | exec: 25 | command: 26 | - pgrep 27 | - httpd 28 | readinessProbe: 29 | tcpSocket: 30 | port: 8443 31 | initialDelaySeconds: 5 32 | periodSeconds: 15 33 | volumeMounts: 34 | - name: config-volume 35 | mountPath: /etc/module-build-service 36 | readOnly: true 37 | - name: frontend-config-volume 38 | mountPath: /etc/mbs-frontend 39 | readOnly: true 40 | - name: mbs-frontend-httpd 41 | mountPath: /httpdir 42 | - name: cacert-volume 43 | mountPath: /etc/cacert 44 | readOnly: true 45 | - name: service-cert-volume 46 | mountPath: /etc/servicecert 47 | readOnly: true 48 | volumes: 49 | - name: config-volume 50 | configMap: 51 | name: "{{ mbs_configmap }}" 52 | - name: frontend-config-volume 53 | configMap: 54 | name: "{{ mbs_frontend_configmap }}" 55 | - name: mbs-frontend-httpd 56 | emptyDir: {} 57 | - name: cacert-volume 58 | secret: 59 | secretName: "{{ mbs_frontend_client_cert_secret }}" 60 | - name: service-cert-volume 61 | secret: 62 | secretName: "{{ mbs_frontend_service_cert_secret }}" 63 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-frontend/templates/ingress.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: {{ mbs_frontend_ingress_name }} 5 | labels: 6 | app: mbs-frontend 7 | {% if mbs_frontend_ingress_backend == 'nginx' %} 8 | annotations: 9 | kubernetes.io/ingress.class: nginx 10 | kubernetes.io/ingress.allow-http: "false" 11 | nginx.ingress.kubernetes.io/ssl-passthrough: "true" 12 | nginx.ingress.kubernetes.io/force-ssl-redirect: "true" 13 | nginx.ingress.kubernetes.io/secure-backends: "true" 14 | {% endif %} 15 | spec: 16 | {% if mbs_frontend_https_enabled %} 17 | tls: 18 | - hosts: 19 | - {{ mbs_frontend_host }} 20 | secretName: {{ mbs_frontend_service_cert_secret }} 21 | {% endif %} 22 | rules: 23 | - http: 24 | paths: 25 | - path: /mbs 26 | pathType: Prefix 27 | backend: 28 | serviceName: {{ mbs_frontend_svc_name }} 29 | servicePort: {{ mbs_frontend_http_port }} 30 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-frontend/templates/mbs-frontend.configmap.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ mbs_frontend_configmap }} 5 | labels: 6 | app: mbs-frontend 7 | data: 8 | httpd.conf: |- 9 | ServerName "{{ mbs_frontend_host }}" 10 | ServerRoot "/httpdir" 11 | PidFile "/httpdir/httpd.pid" 12 | LoadModule authn_file_module modules/mod_authn_file.so 13 | LoadModule authn_anon_module modules/mod_authn_anon.so 14 | LoadModule authz_user_module modules/mod_authz_user.so 15 | LoadModule authz_host_module modules/mod_authz_host.so 16 | LoadModule include_module modules/mod_include.so 17 | LoadModule log_config_module modules/mod_log_config.so 18 | LoadModule env_module modules/mod_env.so 19 | LoadModule ext_filter_module modules/mod_ext_filter.so 20 | LoadModule expires_module modules/mod_expires.so 21 | LoadModule headers_module modules/mod_headers.so 22 | LoadModule mime_module modules/mod_mime.so 23 | LoadModule status_module modules/mod_status.so 24 | LoadModule dir_module modules/mod_dir.so 25 | LoadModule alias_module modules/mod_alias.so 26 | LoadModule rewrite_module modules/mod_rewrite.so 27 | LoadModule version_module modules/mod_version.so 28 | LoadModule wsgi_module modules/mod_wsgi_python3.so 29 | LoadModule authn_core_module modules/mod_authn_core.so 30 | LoadModule authz_core_module modules/mod_authz_core.so 31 | LoadModule unixd_module modules/mod_unixd.so 32 | LoadModule mpm_event_module modules/mod_mpm_event.so 33 | LoadModule ssl_module modules/mod_ssl.so 34 | StartServers 20 35 | ServerLimit 100 36 | MaxRequestsPerChild 2000 37 | MaxRequestWorkers 100 38 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 39 | CustomLog /httpdir/accesslog combined 40 | ErrorLog /httpdir/errorlog 41 | LogLevel debug 42 | TypesConfig /etc/mime.types 43 | AddDefaultCharset UTF-8 44 | CoreDumpDirectory /tmp 45 | {% if mbs_frontend_https_enabled %} 46 | Listen 0.0.0.0:{{ mbs_frontend_https_port }} https 47 | 48 | 49 | ServerName "{{ mbs_frontend_host }}" 50 | TypesConfig /etc/mime.types 51 | AddDefaultCharset UTF-8 52 | SSLEngine on 53 | SSLProtocol TLSv1.2 54 | 55 | {% else %} 56 | Listen 0.0.0.0:{{ mbs_frontend_http_port }} http 57 | 58 | 59 | ServerName "{{ mbs_frontend_host }}" 60 | TypesConfig /etc/mime.types 61 | AddDefaultCharset UTF-8 62 | 63 | {% endif %} 64 | 65 | WSGIDaemonProcess mbs_frontend display-name=mbs_frontend processes=2 threads=2 maximum-requests=1000 home=/httpdir 66 | WSGIApplicationGroup %{GLOBAL} 67 | WSGISocketPrefix run/wsgi 68 | WSGIRestrictStdout Off 69 | WSGIRestrictSignal Off 70 | WSGIPythonOptimize 1 71 | 72 | WSGIScriptAlias / /mbs.wsgi 73 | 74 | Require all granted 75 | 76 | 77 | RewriteEngine on 78 | RewriteRule ^(|/+)$ /module-build-service/1/module-builds/ [L,R=302] 79 | 80 | SSLCertificateFile /etc/servicecert/tls.crt 81 | SSLCertificateKeyFile /etc/servicecert/tls.key 82 | SSLCertificateChainFile /etc/cacert/tls.crt 83 | -------------------------------------------------------------------------------- /mbox-operator/roles/mbs-frontend/templates/service.yml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ mbs_frontend_svc_name }} 5 | labels: 6 | app: mbs-frontend 7 | service: {{ mbs_frontend_svc_name }} 8 | spec: 9 | selector: 10 | app: mbs-frontend 11 | ports: 12 | {% if mbs_frontend_https_enabled %} 13 | - name: https 14 | port: {{ mbs_frontend_https_port }} 15 | targetPort: {{ mbs_frontend_https_port }} 16 | {% else %} 17 | - name: http 18 | port: {{ mbs_frontend_http_port }} 19 | targetPort: {{ mbs_frontend_http_port }} 20 | {% endif %} 21 | -------------------------------------------------------------------------------- /mbox-operator/watches.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Use the 'create api' subcommand to add watches to this file. 3 | - version: v1alpha1 4 | group: apps.fedoraproject.org 5 | kind: MBKojiBuilder 6 | role: koji-builder 7 | vars: 8 | meta: '{{ ansible_operator_meta }}' 9 | 10 | - version: v1alpha1 11 | group: apps.fedoraproject.org 12 | kind: MBKojiHub 13 | role: koji-hub 14 | vars: 15 | meta: '{{ ansible_operator_meta }}' 16 | 17 | - version: v1alpha1 18 | group: apps.fedoraproject.org 19 | kind: MBKojira 20 | role: kojira 21 | vars: 22 | meta: '{{ ansible_operator_meta }}' 23 | 24 | - version: v1alpha1 25 | group: apps.fedoraproject.org 26 | kind: MBMbsBackend 27 | role: mbs-backend 28 | vars: 29 | meta: '{{ ansible_operator_meta }}' 30 | 31 | - version: v1alpha1 32 | group: apps.fedoraproject.org 33 | kind: MBMbsFrontend 34 | role: mbs-frontend 35 | vars: 36 | meta: '{{ ansible_operator_meta }}' 37 | 38 | - version: v1alpha1 39 | group: apps.fedoraproject.org 40 | kind: Mbox 41 | role: mbox 42 | vars: 43 | meta: '{{ ansible_operator_meta }}' 44 | # +kubebuilder:scaffold:watch 45 | --------------------------------------------------------------------------------