├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── gitlab-del-projects-container-build.yaml │ ├── gitlab-del-projects-release.yaml │ ├── lint-test.yaml │ ├── prune-ocp-projects-container-build.yaml │ ├── prune-ocp-projects-release.yaml │ └── release.yaml ├── README.md ├── charts ├── cluster-descheduler │ ├── Chart.yaml │ ├── templates │ │ ├── clusterrole.yaml │ │ ├── clusterrolebinding.yaml │ │ ├── configmap.yaml │ │ ├── cronjob.yaml │ │ └── serviceaccount.yaml │ └── values.yaml ├── cronjob-aws-ocp-snap │ ├── Chart.yaml │ ├── templates │ │ ├── buildconfig.yaml │ │ ├── clusterrole.yaml │ │ ├── clusterrolebinding.yaml │ │ ├── cronjob.yaml │ │ ├── imagestream.yaml │ │ ├── secret.yaml │ │ └── serviceaccount.yaml │ └── values.yaml ├── cronjob-etcd-backup │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── templates │ │ ├── ClusterRole.yml │ │ ├── ClusterRoleBinding.yml │ │ ├── CronJob.yml │ │ ├── NOTES.txt │ │ ├── PersistentVolumeClaim.yml │ │ ├── ServiceAccount.yml │ │ ├── _helpers.tpl │ │ └── tests │ │ │ └── test-cronjob.yaml │ └── values.yaml ├── cronjob-git-sync │ ├── Chart.yaml │ ├── templates │ │ ├── cronjob.yaml │ │ └── secret.yaml │ └── values.yaml ├── cronjob-gitlab-delete-projects │ ├── Chart.yaml │ ├── README.md │ ├── templates │ │ ├── cronjob.yaml │ │ └── secret.yaml │ └── values.yaml ├── cronjob-ldap-group-sync-secure │ ├── Chart.yaml │ ├── templates │ │ ├── clusterrole.yaml │ │ ├── clusterrolebinding.yaml │ │ ├── configmap.yaml │ │ ├── cronjob.yaml │ │ ├── secret.yaml │ │ └── serviceaccount.yaml │ └── values.yaml ├── cronjob-ldap-group-sync │ ├── Chart.yaml │ ├── templates │ │ ├── clusterrole.yaml │ │ ├── clusterrolebinding.yaml │ │ ├── configmap.yaml │ │ ├── cronjob.yaml │ │ ├── secret.yaml │ │ └── serviceaccount.yaml │ └── values.yaml ├── cronjob-prune-builds-deployments │ ├── Chart.yaml │ ├── templates │ │ ├── clusterrolebinding.yaml │ │ ├── cronjob.yaml │ │ └── serviceaccount.yaml │ └── values.yaml ├── cronjob-prune-images │ ├── Chart.yaml │ ├── templates │ │ ├── clusterrolebinding.yaml │ │ ├── cronjob.yaml │ │ └── serviceaccount.yaml │ └── values.yaml ├── cronjob-prune-projects │ ├── Chart.yaml │ ├── templates │ │ ├── buildconfig.yaml │ │ ├── clusterrolebinding.yaml │ │ ├── cronjob.yaml │ │ ├── imagestream.yaml │ │ └── serviceaccount.yaml │ └── values.yaml └── cronjob-prune-tekton-pipelinerun │ ├── Chart.yaml │ ├── README.md │ ├── templates │ ├── clusterrolebinding.yaml │ ├── cronjob.yaml │ └── serviceaccount.yaml │ └── values.yaml ├── images ├── README.md ├── aws-ocp-snap │ ├── Dockerfile │ └── include │ │ └── create_snapshot.sh ├── gitlab-delete-stale-projects │ ├── Dockerfile │ ├── README.md │ └── gitlab-cleanup.py └── prune-ocp-projects │ ├── Dockerfile │ ├── README.md │ ├── buildah.sh │ └── include │ └── prune-ocp-projects.sh └── jobs ├── README.md ├── cluster-descheduler.yml ├── cronjob-aws-ocp-snap.yaml ├── cronjob-git-sync.yml ├── cronjob-ldap-group-sync-secure.yml ├── cronjob-ldap-group-sync.yml ├── cronjob-prune-builds-deployments.yml ├── cronjob-prune-images.yml ├── cronjob-prune-projects-build.yaml └── cronjob-prune-projects.yaml /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | #### What is this PR About? 2 | Describe the contents of the PR 3 | 4 | #### How do we test this? 5 | Provide commands/steps to test this PR. 6 | 7 | cc: @redhat-cop/casl 8 | -------------------------------------------------------------------------------- /.github/workflows/gitlab-del-projects-container-build.yaml: -------------------------------------------------------------------------------- 1 | name: Gitlab Delete Projects Container 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - images/gitlab-delete-stale-projects/** 9 | - .github/workflows/gitlab-del-projects-container-build.yaml 10 | 11 | jobs: 12 | build-gitlab-delete-project: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: echo var 17 | run: | 18 | echo version name is: ${{ github.event.repository.name }} 19 | echo repository is: ${{ github.repository }} 20 | - name: Login quay.io 21 | run: echo ${{ secrets.QUAY_PASSWORD }} | docker login quay.io -u ${{ secrets.QUAY_USERNAME }} --password-stdin 22 | - name: Build Container 23 | run: docker build images/gitlab-delete-stale-projects -t quay.io/redhat-cop/gitlab-cleanup:${{ github.sha }} 24 | - name: Push Container 25 | run: docker push quay.io/redhat-cop/gitlab-cleanup:${{ github.sha }} 26 | - name: Tag Latest 27 | run: docker tag quay.io/redhat-cop/gitlab-cleanup:${{ github.sha }} quay.io/redhat-cop/gitlab-cleanup:master 28 | - name: Push branch tag 29 | run: docker push quay.io/redhat-cop/gitlab-cleanup:master 30 | -------------------------------------------------------------------------------- /.github/workflows/gitlab-del-projects-release.yaml: -------------------------------------------------------------------------------- 1 | name: Gitlab Delete Projects Release Tag 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | release: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: tag with release version 13 | uses: tinact/docker.image-retag@1.0.2 14 | with: 15 | image_name: redhat-cop/gitlab-cleanup 16 | image_old_tag: master 17 | image_new_tag: ${{ github.event.release.tag_name }} 18 | registry: quay.io 19 | registry_username: ${{ secrets.QUAY_USERNAME }} 20 | registry_password: ${{ secrets.QUAY_PASSWORD }} 21 | - name: tag with latest 22 | uses: tinact/docker.image-retag@1.0.2 23 | with: 24 | image_name: redhat-cop/gitlab-cleanup 25 | image_old_tag: master 26 | registry: quay.io 27 | registry_username: ${{ secrets.QUAY_USERNAME }} 28 | registry_password: ${{ secrets.QUAY_PASSWORD }} 29 | -------------------------------------------------------------------------------- /.github/workflows/lint-test.yaml: -------------------------------------------------------------------------------- 1 | name: Lint and Test Charts 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'charts/**' 7 | 8 | jobs: 9 | lint-test: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | 15 | - name: Fetch history 16 | run: git fetch --prune --unshallow 17 | 18 | - name: Set up Helm 19 | uses: azure/setup-helm@v2.1 20 | with: 21 | version: v3.5.1 22 | 23 | - uses: actions/setup-python@v4 24 | with: 25 | python-version: 3.7 26 | 27 | - name: Run chart-testing (lint) 28 | id: lint 29 | uses: helm/chart-testing-action@v2.2.1 30 | 31 | - name: Run chart-testing (list-changed) 32 | id: list-changed 33 | run: | 34 | changed=$(ct list-changed) 35 | if [[ -n "$changed" ]]; then 36 | echo "::set-output name=changed::true" 37 | fi 38 | 39 | - name: Run chart-testing (lint) 40 | run: ct lint -------------------------------------------------------------------------------- /.github/workflows/prune-ocp-projects-container-build.yaml: -------------------------------------------------------------------------------- 1 | name: OpenShift Container Platform Prune Projects Container 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - images/prune-ocp-projects/** 9 | - .github/workflows/prune-ocp-projects-container-build.yaml 10 | 11 | jobs: 12 | build-prune-ocp-projects: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: echo var 17 | run: | 18 | echo version name is: ${{ github.event.repository.name }} 19 | echo repository is: ${{ github.repository }} 20 | - name: Login quay.io 21 | run: echo ${{ secrets.QUAY_PASSWORD }} | docker login quay.io -u ${{ secrets.QUAY_USERNAME }} --password-stdin 22 | - name: Build Container 23 | run: docker build images/prune-ocp-projects -t quay.io/redhat-cop/prune-ocp-projects:${{ github.sha }} 24 | - name: Push Container 25 | run: docker push quay.io/redhat-cop/prune-ocp-projects:${{ github.sha }} 26 | - name: Tag Latest 27 | run: docker tag quay.io/redhat-cop/prune-ocp-projects:${{ github.sha }} quay.io/redhat-cop/prune-ocp-projects:master 28 | - name: Push branch tag 29 | run: docker push quay.io/redhat-cop/prune-ocp-projects:master 30 | -------------------------------------------------------------------------------- /.github/workflows/prune-ocp-projects-release.yaml: -------------------------------------------------------------------------------- 1 | name: Prune OpenShift Container Platform Projects Release Tag 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | release: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: tag with release version 13 | uses: tinact/docker.image-retag@1.0.2 14 | with: 15 | image_name: redhat-cop/prune-ocp-projects 16 | image_old_tag: master 17 | image_new_tag: ${{ github.event.release.tag_name }} 18 | registry: quay.io 19 | registry_username: ${{ secrets.QUAY_USERNAME }} 20 | registry_password: ${{ secrets.QUAY_PASSWORD }} 21 | - name: tag with latest 22 | uses: tinact/docker.image-retag@1.0.2 23 | with: 24 | image_name: redhat-cop/prune-ocp-projects 25 | image_old_tag: master 26 | registry: quay.io 27 | registry_username: ${{ secrets.QUAY_USERNAME }} 28 | registry_password: ${{ secrets.QUAY_PASSWORD }} 29 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release Charts 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - 'charts/**' 9 | 10 | jobs: 11 | release: 12 | concurrency: staging_environment 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Configure Git 21 | run: | 22 | git config user.name "$GITHUB_ACTOR" 23 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 24 | 25 | - name: Install Helm 26 | uses: azure/setup-helm@v2.1 27 | with: 28 | version: latest 29 | 30 | - name: Add dependency chart repos 31 | run: | 32 | helm repo add stable https://charts.helm.sh/stable 33 | helm repo add incubator https://charts.helm.sh/incubator 34 | 35 | - name: Run chart-releaser 36 | uses: helm/chart-releaser-action@v1.4.0 37 | env: 38 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenShift Management 2 | 3 | ## Status 4 | 5 | ![Gitlab Delete Projects Release Tag](https://github.com/redhat-cop/openshift-management/workflows/Gitlab%20Delete%20Projects%20Release%20Tag/badge.svg)
6 | 7 | 8 | ## General Information 9 | This repo contains a set of general _good practice_ jobs that can be used as a starting point for operationalizing an OpenShift Container Platform cluster. This repo breaks down into several categories: 10 | 11 | - **jobs** - a set of _jobs_ (including _CronJob_) templates for common tasks **deprecated** 12 | - **charts** - a set of Helm Charts for common tasks **new** 13 | - **images** - utility images for common tasks 14 | -------------------------------------------------------------------------------- /charts/cluster-descheduler/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | description: Descheduler to remove pods violating usage thresholds, affinity violations and duplicate pod placements 3 | name: cluster-descheduler 4 | tags: management,descheduler 5 | version: 0.0.3 6 | maintainers: 7 | - name: redhat-cop 8 | -------------------------------------------------------------------------------- /charts/cluster-descheduler/templates/clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | template: cluster-scheduler 6 | name: descheduler-role 7 | rules: 8 | - apiGroups: 9 | - "" 10 | resources: 11 | - nodes 12 | verbs: 13 | - get 14 | - watch 15 | - list 16 | - apiGroups: 17 | - "" 18 | resources: 19 | - pods 20 | verbs: 21 | - get 22 | - watch 23 | - list 24 | - delete 25 | - apiGroups: 26 | - "" 27 | resources: 28 | - pods/eviction 29 | verbs: 30 | - create 31 | -------------------------------------------------------------------------------- /charts/cluster-descheduler/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | template: cluster-descheduler 6 | name: descheduler-binding 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | kind: ClusterRole 10 | name: descheduler-role 11 | subjects: 12 | - kind: ServiceAccount 13 | name: descheduler-sa 14 | namespace: {{ .Values.namespace }} 15 | -------------------------------------------------------------------------------- /charts/cluster-descheduler/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | policy.yaml: | 4 | apiVersion: descheduler/v1alpha1 5 | kind: DeschedulerPolicy 6 | strategies: 7 | RemoveDuplicates: 8 | enabled: {{ .Values.remove_dups }} 9 | LowNodeUtilization: 10 | enabled: {{ .Values.enable_utilization }} 11 | params: 12 | nodeResourceUtilizationThresholds: 13 | thresholds: 14 | cpu: {{ .Values.min_cpu }} 15 | memory: {{ .Values.min_mem }} 16 | pods: {{ .Values.min_pods }} 17 | targetThresholds: 18 | cpu: {{ .Values.max_cpu }} 19 | memory: {{ .Values.max_mem }} 20 | pods: {{ .Values.max_pods }} 21 | numberOfNodes: {{ .Values.node_threshold }} 22 | RemovePodsViolatingInterPodAntiAffinity: 23 | enabled: {{ .Values.enable_affinity_violation }} 24 | kind: ConfigMap 25 | metadata: 26 | labels: 27 | template: cluster-descheduler 28 | name: descheduler-policy-configmap 29 | namespace: {{ .Values.namespace }} 30 | -------------------------------------------------------------------------------- /charts/cluster-descheduler/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | labels: 5 | template: cluster-descheduler 6 | name: descheduler-job 7 | namespace: {{ .Values.namespace }} 8 | spec: 9 | concurrencyPolicy: Forbid 10 | failedJobsHistoryLimit: "1" 11 | jobTemplate: 12 | spec: 13 | completions: 1 14 | parallelism: 1 15 | template: 16 | metadata: 17 | annotations: 18 | scheduler.alpha.kubernetes.io/critical-pod: "true" 19 | name: descheduler-pod 20 | spec: 21 | containers: 22 | - command: 23 | - /bin/sh 24 | - -ec 25 | - | 26 | /bin/descheduler --policy-config-file /policy-dir/policy.yaml 27 | image: {{ .Values.image }}:{{ .Values.image_tag }} 28 | name: descheduler 29 | volumeMounts: 30 | - mountPath: /policy-dir 31 | name: policy-volume 32 | restartPolicy: Never 33 | serviceAccountName: descheduler-sa 34 | volumes: 35 | - configMap: 36 | name: descheduler-policy-configmap 37 | name: policy-volume 38 | schedule: {{ .Values.schedule | quote }} 39 | successfulJobsHistoryLimit: "1" 40 | -------------------------------------------------------------------------------- /charts/cluster-descheduler/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | template: cluster-descheduler 6 | name: descheduler-sa 7 | namespace: {{ .Values.namespace }} 8 | -------------------------------------------------------------------------------- /charts/cluster-descheduler/values.yaml: -------------------------------------------------------------------------------- 1 | enable_affinity_violation: "False" 2 | enable_utilization: "False" 3 | image: registry.access.redhat.com/openshift3/ose-descheduler 4 | image_tag: v3.11 5 | max_cpu: "0" 6 | max_mem: "0" 7 | max_pods: "0" 8 | min_cpu: "0" 9 | min_mem: "0" 10 | min_pods: "0" 11 | namespace: cluster-ops 12 | node_threshold: "0" 13 | remove_dups: "False" 14 | schedule: '@hourly' 15 | -------------------------------------------------------------------------------- /charts/cronjob-aws-ocp-snap/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: cronjob-aws-ocp-snap 3 | version: 0.0.2 4 | maintainers: 5 | - name: redhat-cop 6 | -------------------------------------------------------------------------------- /charts/cronjob-aws-ocp-snap/templates/buildconfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: build.openshift.io/v1 2 | kind: BuildConfig 3 | metadata: 4 | annotations: 5 | description: Defines how to build the application 6 | labels: 7 | template: cronjob-aws-ocp-snap 8 | name: {{ .Values.name }} 9 | spec: 10 | completionDeadlineSeconds: 1800 11 | output: 12 | to: 13 | kind: ImageStreamTag 14 | name: {{ .Values.name }}:latest 15 | runPolicy: Serial 16 | source: 17 | contextDir: /images/cronjob-aws-ocp-snap 18 | git: 19 | uri: https://github.com/redhat-cop/openshift-management.git 20 | type: Git 21 | strategy: 22 | dockerStrategy: 23 | from: 24 | kind: DockerImage 25 | name: centos:7 26 | type: Docker 27 | triggers: 28 | - type: ConfigChange 29 | -------------------------------------------------------------------------------- /charts/cronjob-aws-ocp-snap/templates/clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | template: cronjob-aws-ocp-snap 6 | name: pvc-reader 7 | rules: 8 | - apiGroups: 9 | - "" 10 | resources: 11 | - persistentvolumes 12 | verbs: 13 | - get 14 | - list 15 | - watch 16 | - apiGroups: 17 | - storage.k8s.io 18 | resources: 19 | - storageclasses 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | - apiGroups: 25 | - "" 26 | resources: 27 | - events 28 | - persistentvolumeclaims 29 | verbs: 30 | - get 31 | - list 32 | - watch 33 | -------------------------------------------------------------------------------- /charts/cronjob-aws-ocp-snap/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | template: cronjob-aws-ocp-snap 6 | name: {{ .Values.namespace }}-pvc-reader 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | name: pvc-reader 10 | kind: ClusterRole 11 | subjects: 12 | - kind: ServiceAccount 13 | name: {{ .Values.job_service_account }} 14 | namespace: {{ .Values.namespace }} 15 | -------------------------------------------------------------------------------- /charts/cronjob-aws-ocp-snap/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | labels: 5 | template: cronjob-aws-ocp-snap 6 | name: {{ .Values.job_name }} 7 | spec: 8 | concurrencyPolicy: Forbid 9 | failedJobsHistoryLimit: {{ .Values.failed_jobs_history_limit }} 10 | jobTemplate: 11 | spec: 12 | template: 13 | spec: 14 | activeDeadlineSeconds: 500 15 | containers: 16 | - command: 17 | - /bin/bash 18 | - -c 19 | - /usr/local/bin/create_snapshot.sh {{ .Values.nspace }} {{ .Values.vol }} 20 | env: 21 | - name: AWS_ACCESS_KEY_ID 22 | valueFrom: 23 | secretKeyRef: 24 | key: key_id 25 | name: aws-secret 26 | - name: AWS_SECRET_ACCESS_KEY 27 | valueFrom: 28 | secretKeyRef: 29 | key: access_key 30 | name: aws-secret 31 | - name: AWS_DEFAULT_REGION 32 | valueFrom: 33 | secretKeyRef: 34 | key: region 35 | name: aws-secret 36 | image: docker-registry.default.svc:5000/{{ .Values.namespace }}/{{ .Values.name }}:latest 37 | name: {{ .Values.job_name }} 38 | dnsPolicy: ClusterFirst 39 | restartPolicy: Never 40 | serviceAccount: {{ .Values.job_service_account }} 41 | serviceAccountName: {{ .Values.job_service_account }} 42 | terminationGracePeriodSeconds: 30 43 | schedule: "{{ .Values.schedule }}" 44 | successfulJobsHistoryLimit: {{ .Values.success_jobs_history_limit }} 45 | -------------------------------------------------------------------------------- /charts/cronjob-aws-ocp-snap/templates/imagestream.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: image.openshift.io/v1 2 | kind: ImageStream 3 | metadata: 4 | annotations: 5 | description: Keeps track of changes in the application image 6 | labels: 7 | template: cronjob-aws-ocp-snap 8 | name: {{ .Values.name }} 9 | -------------------------------------------------------------------------------- /charts/cronjob-aws-ocp-snap/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | labels: 5 | template: cronjob-aws-ocp-snap 6 | name: aws-secret 7 | stringData: 8 | access_key: {{ .Values.aws_secret_access_key }} 9 | key_id: {{ .Values.aws_access_key_id }} 10 | region: {{ .Values.aws_region }} 11 | -------------------------------------------------------------------------------- /charts/cronjob-aws-ocp-snap/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | template: cronjob-aws-ocp-snap 6 | name: {{ .Values.job_service_account }} 7 | -------------------------------------------------------------------------------- /charts/cronjob-aws-ocp-snap/values.yaml: -------------------------------------------------------------------------------- 1 | aws_access_key_id: PLEASE_CHANGE_ME_WITH_VALID_VALUE 2 | aws_region: PLEASE_CHANGE_ME_WITH_VALID_VALUE 3 | aws_secret_access_key: PLEASE_CHANGE_ME_WITH_VALID_VALUE 4 | failed_jobs_history_limit: "5" 5 | job_name: cronjob-ebs-snaphost 6 | job_service_account: ebs-snap-creator 7 | name: cronjob-aws-ocp-snap 8 | namespace: cluster-ops 9 | nspace: PLEASE_CHANGE_ME_WITH_VALID_VALUE 10 | schedule: '@daily' 11 | success_jobs_history_limit: "5" 12 | vol: PLEASE_CHANGE_ME_WITH_VALID_VALUE 13 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: cronjob-etcd-backup 3 | description: Deploys a CronJob for creating automated backups of ETCD and storing them on a PersistentVolume 4 | type: application 5 | version: 1.0.1 6 | maintainers: 7 | - name: redhat-cop 8 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/README.md: -------------------------------------------------------------------------------- 1 | # cronjob-etcd-backup 2 | 3 | Creates a CronJob that creates etcd backups on a schedule and stores them on a PersistentVolume. 4 | 5 | This essentially automates the [officially documented etcd backup process](https://docs.openshift.com/container-platform/4.10/backup_and_restore/control_plane_backup_and_restore/backing-up-etcd.html) with the additional step 6 | that the etcd backup is moved to external storage via a PVC. 7 | 8 | > :exclamation: **uses privileged** see [Permissions](#permissions) 9 | 10 | ## Use 11 | 12 | ### Manual 13 | Installs and tests the helm chart 14 | ```bash 15 | helm upgrade --install cronjob-etcd-backup ./cronjob-etcd-backup --namespace openshift-etcd-backup --create-namespace 16 | helm test cronjob-etcd-backup 17 | ``` 18 | 19 | ### ArgoCD 20 | There innumerable different ways and opinions on doing GitOps, and even within ArgoCD there 21 | are many ways. Here is a start if you don't already have an opinion. 22 | 23 | ```yaml 24 | apiVersion: argoproj.io/v1alpha1 25 | kind: Application 26 | metadata: 27 | name: openshift-etcd-backup 28 | spec: 29 | destination: 30 | name: '' 31 | namespace: openshift-etcd-backup 32 | server: 'https://kubernetes.default.svc' 33 | source: 34 | path: charts/cronjob-etcd-backup 35 | repoURL: 'https://github.com/redhat-cop/openshift-management.git' 36 | targetRevision: master 37 | helm: 38 | values: | 39 | pvcStorage: 100Gi 40 | pvcStorageClassName: 41 | cronJobSchedule: '5 0 * * *' 42 | cronJobDaysToKeepPersistentETCDBackups: 5 43 | project: default 44 | syncPolicy: 45 | automated: 46 | prune: true 47 | selfHeal: true 48 | syncOptions: 49 | - CreateNamespace=true 50 | ``` 51 | 52 | ## Permissions 53 | Yes, this chart uses the `privileged` security context, but it is not out of laziness, it is 54 | out of necessity. To be able to run the `cluster-backup.sh` script on a control node you not only 55 | need to be able to mount the host file system but you need to be able to sudo. 56 | 57 | While the [officially documented etcd backup process](https://docs.openshift.com/container-platform/4.10/backup_and_restore/control_plane_backup_and_restore/backing-up-etcd.html) 58 | has you manually create a debug pod for a control node to accomplish this, if you are automating this 59 | process then the container created by the CronJob has to have the same permissions a debug pod 60 | for a control node would have. So this is no more permissions then would be used doing this the 61 | documented manual way, its just giving it to the "robot". 62 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/templates/ClusterRole.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # NOTE: To be able to run the ETCD backup commands need to be able to sudo, 3 | # hence the need for privileged. 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | kind: ClusterRole 6 | metadata: 7 | name: {{ include "cronjob-etcd-backup.fullname" . }} 8 | labels: 9 | {{- include "cronjob-etcd-backup.labels" . | nindent 4 }} 10 | rules: 11 | - verbs: 12 | - use 13 | apiGroups: 14 | - security.openshift.io 15 | resources: 16 | - securitycontextconstraints 17 | resourceNames: 18 | - privileged 19 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/templates/ClusterRoleBinding.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: ClusterRoleBinding 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | metadata: 5 | name: {{ include "cronjob-etcd-backup.fullname" . }} 6 | labels: 7 | {{- include "cronjob-etcd-backup.labels" . | nindent 4 }} 8 | subjects: 9 | - kind: ServiceAccount 10 | name: {{ include "cronjob-etcd-backup.fullname" . }} 11 | namespace: {{ .Release.Namespace }} 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: ClusterRole 15 | name: {{ include "cronjob-etcd-backup.fullname" . }} 16 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/templates/CronJob.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: CronJob 3 | apiVersion: batch/v1 4 | metadata: 5 | name: {{ include "cronjob-etcd-backup.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "cronjob-etcd-backup.labels" . | nindent 4 }} 9 | spec: 10 | schedule: "{{ .Values.cronJobSchedule }}" 11 | concurrencyPolicy: Forbid 12 | suspend: false 13 | jobTemplate: 14 | metadata: 15 | labels: 16 | {{- include "cronjob-etcd-backup.labels" . | nindent 8 }} 17 | spec: 18 | backoffLimit: 0 19 | template: 20 | metadata: 21 | labels: 22 | {{- include "cronjob-etcd-backup.labels" . | nindent 12 }} 23 | spec: 24 | nodeSelector: 25 | node-role.kubernetes.io/master: '' 26 | restartPolicy: Never 27 | activeDeadlineSeconds: 500 28 | serviceAccountName: {{ include "cronjob-etcd-backup.fullname" . }} 29 | hostPID: true 30 | hostNetwork: true 31 | enableServiceLinks: true 32 | schedulerName: default-scheduler 33 | terminationGracePeriodSeconds: 30 34 | securityContext: {} 35 | containers: 36 | - resources: {} 37 | terminationMessagePath: /dev/termination-log 38 | name: {{ include "cronjob-etcd-backup.fullname" . }} 39 | command: 40 | - /bin/bash 41 | - '-c' 42 | - >- 43 | echo -e '\n\n---\nCreate etcd backup local to master\n' && 44 | chroot /host /usr/local/bin/cluster-backup.sh /home/core/backup/ && 45 | echo -e '\n\n---\nCleanup old local etcd backups\n' && 46 | chroot /host find /home/core/backup/ -type f -mmin +"2" -delete && 47 | echo -e '\n\n---\nCopy etcd backup to persistent volume\n' && 48 | mkdir -pv /mnt/backup/$(date "+%F_%H%M%S") && 49 | cp -v /host/home/core/backup/* /mnt/backup/$(date "+%F_%H%M%S") && 50 | echo -e "\n\n---\nDelete persistent ETCD backups older then ${DAYS_TO_KEEP_PERSISTENT_ETCD_BACKUPS} days\n" && 51 | find /mnt/backup/* -type d -mtime +${DAYS_TO_KEEP_PERSISTENT_ETCD_BACKUPS} -exec rm -rv {} \; && 52 | echo -e '\n\n---\nList all etc backups\n' && 53 | ls -al /mnt/backup/* 54 | env: 55 | - name: DAYS_TO_KEEP_PERSISTENT_ETCD_BACKUPS 56 | value: "{{ .Values.cronJobDaysToKeepPersistentETCDBackups }}" 57 | securityContext: 58 | privileged: true 59 | runAsUser: 0 60 | capabilities: 61 | add: 62 | - SYS_CHROOT 63 | imagePullPolicy: Always 64 | volumeMounts: 65 | - name: backup 66 | mountPath: /mnt/backup 67 | - name: host 68 | mountPath: /host 69 | terminationMessagePolicy: File 70 | image: {{ .Values.cronJobImage }} 71 | volumes: 72 | - name: backup 73 | persistentVolumeClaim: 74 | claimName: {{ include "cronjob-etcd-backup.fullname" . }} 75 | - name: host 76 | hostPath: 77 | path: / 78 | type: Directory 79 | dnsPolicy: ClusterFirst 80 | tolerations: 81 | - key: node-role.kubernetes.io/master 82 | successfulJobsHistoryLimit: {{ .Values.cronJobSuccessfulJobsHistoryLimit }} 83 | failedJobsHistoryLimit: {{ .Values.cronJobFailedJobsHistoryLimit }} 84 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | etcd is now being automatically backed up on schedule: {{ .Values.cronJobSchedule }} 2 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/templates/PersistentVolumeClaim.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: PersistentVolumeClaim 3 | apiVersion: v1 4 | metadata: 5 | name: {{ include "cronjob-etcd-backup.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "cronjob-etcd-backup.labels" . | nindent 4 }} 9 | spec: 10 | accessModes: 11 | - ReadWriteOnce 12 | resources: 13 | requests: 14 | storage: {{ .Values.pvcStorage }} 15 | {{ if .Values.pvcStorageClassName }} 16 | storageClassName: {{ .Values.pvcStorageClassName }} 17 | {{ end }} 18 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/templates/ServiceAccount.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: ServiceAccount 3 | apiVersion: v1 4 | metadata: 5 | name: {{ include "cronjob-etcd-backup.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{- include "cronjob-etcd-backup.labels" . | nindent 4 }} -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "cronjob-etcd-backup.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "cronjob-etcd-backup.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "cronjob-etcd-backup.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "cronjob-etcd-backup.labels" -}} 37 | app.kubernetes.io/name: {{ template "cronjob-etcd-backup.name" . }} 38 | app.kubernetes.io/component: cronjob 39 | app.kubernetes.io/part-of: {{ .Values.partOf }} 40 | app.kubernetes.io/managed-by: {{ .Release.Service }} 41 | app.kubernetes.io/instance: {{ .Release.Name }} 42 | helm.sh/chart: {{ include "cronjob-etcd-backup.chart" . }} 43 | {{- end }} 44 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/templates/tests/test-cronjob.yaml: -------------------------------------------------------------------------------- 1 | 2 | {{- define "cronjob-etcd-backup.helmTestCronJobServiceAccountName" -}} 3 | {{- printf "helm-test-cronjob-%s" (include "cronjob-etcd-backup.fullname" .) | trunc 63 | trimSuffix "-" }} 4 | {{- end }} 5 | 6 | --- 7 | apiVersion: v1 8 | kind: Pod 9 | metadata: 10 | name: "{{ include "cronjob-etcd-backup.fullname" . }}-test-cronjob" 11 | labels: 12 | {{- include "cronjob-etcd-backup.labels" . | nindent 4 }} 13 | annotations: 14 | "helm.sh/hook": test 15 | spec: 16 | serviceAccountName: {{ include "cronjob-etcd-backup.helmTestCronJobServiceAccountName" . }} 17 | automountServiceAccountToken: true 18 | containers: 19 | - name: wget 20 | image: registry.redhat.io/openshift4/ose-cli 21 | command: 22 | - /bin/bash 23 | - -ec 24 | - | 25 | NAMESPACE="{{ .Release.Namespace }}" 26 | CRONJOB_NAME="{{ include "cronjob-etcd-backup.fullname" . }}" 27 | JOB_NAME="test-${CRONJOB_NAME}-{{ .Release.Revision }}" 28 | TEST_TIMEOUT="{{ .Values.testCronJobTimeout }}" 29 | 30 | echo "Create Test Job from CronJob" 31 | oc create job ${JOB_NAME} --from=cronjob/${CRONJOB_NAME} --namespace ${NAMESPACE} 32 | 33 | echo "Wait for Test Job to complete successfully" 34 | oc wait --for=condition=complete job/${JOB_NAME} --namespace ${NAMESPACE} --timeout ${TEST_TIMEOUT} 35 | restartPolicy: Never 36 | 37 | --- 38 | apiVersion: v1 39 | kind: ServiceAccount 40 | metadata: 41 | name: {{ include "cronjob-etcd-backup.helmTestCronJobServiceAccountName" . }} 42 | labels: 43 | {{- include "cronjob-etcd-backup.labels" . | nindent 4 }} 44 | 45 | --- 46 | apiVersion: rbac.authorization.k8s.io/v1 47 | kind: RoleBinding 48 | metadata: 49 | name: {{ include "cronjob-etcd-backup.helmTestCronJobServiceAccountName" . }} 50 | labels: 51 | {{- include "cronjob-etcd-backup.labels" . | nindent 4 }} 52 | roleRef: 53 | apiGroup: rbac.authorization.k8s.io 54 | kind: ClusterRole 55 | name: edit 56 | subjects: 57 | - kind: ServiceAccount 58 | name: {{ include "cronjob-etcd-backup.helmTestCronJobServiceAccountName" . }} 59 | namespace: {{ .Release.Namespace }} 60 | -------------------------------------------------------------------------------- /charts/cronjob-etcd-backup/values.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | partOf: cluster-operations 3 | 4 | pvcStorage: 100Gi 5 | pvcStorageClassName: 6 | 7 | cronJobSchedule: '5 0 * * *' 8 | cronJobSuccessfulJobsHistoryLimit: 5 9 | cronJobFailedJobsHistoryLimit: 5 10 | cronJobImage: registry.redhat.io/openshift4/ose-cli 11 | 12 | cronJobDaysToKeepPersistentETCDBackups: 5 13 | 14 | testCronJobTimeout: 120s 15 | -------------------------------------------------------------------------------- /charts/cronjob-git-sync/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | description: Scheduled Task to Perform Git Repo Synchronization 3 | name: cronjob-git-sync 4 | tags: management,cronjob,git,sync 5 | version: 0.0.2 6 | maintainers: 7 | - name: redhat-cop 8 | -------------------------------------------------------------------------------- /charts/cronjob-git-sync/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | labels: 5 | template: cronjob-git-sync 6 | name: {{ .Values.job_name }} 7 | spec: 8 | concurrencyPolicy: Forbid 9 | failedJobsHistoryLimit: {{ .Values.failed_jobs_history_limit }} 10 | jobTemplate: 11 | spec: 12 | template: 13 | spec: 14 | activeDeadlineSeconds: 500 15 | containers: 16 | - command: 17 | - /bin/bash 18 | - -c 19 | - | 20 | mkdir ~/.ssh 21 | chmod 700 ~/.ssh 22 | printf 'host {{ .Values.git_host }}\n PreferredAuthentications publickey\n IdentitiesOnly yes\n HostName {{ .Values.git_host }}\n IdentityFile /etc/secret-volume/ssh-privatekey\n User git\n' >> ~/.ssh/config 23 | printf 'host {{ .Values.git_sync_host }}\n PreferredAuthentications publickey\n IdentitiesOnly yes\n HostName {{ .Values.git_sync_host }}\n IdentityFile /etc/secret-volume/ssh-privatekey\n User git\n' >> ~/.ssh/config 24 | chmod 400 ~/.ssh/config 25 | ssh-keyscan -p {{ .Values.git_sync_port }} -H {{ .Values.git_sync_host }} >> ~/.ssh/known_hosts 26 | ssh-keyscan -p {{ .Values.git_port }} -H {{ .Values.git_host }} >> ~/.ssh/known_hosts 27 | USER_ID=$(id -u) 28 | GROUP_ID=$(id -g) 29 | echo "gitsync:x:${USER_ID}:${GROUP_ID}:Git Sync User:${HOME}:/sbin/nologin" > ~/passwd 30 | echo "root:x:${GROUP_ID}:" > ~/group 31 | LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=~/passwd NSS_WRAPPER_GROUP=~/group git clone ssh://git@{{ .Values.git_host }}:{{ .Values.git_port }}/{{ .Values.git_repo }} /tmp/temp 32 | cd /tmp/temp 33 | for branch in $(git branch -a | grep remotes | grep -v HEAD | grep -v master); do git branch --track ${branch#remotes/origin/} $branch; done 34 | LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=~/passwd NSS_WRAPPER_GROUP=~/group git remote add backup ssh://git@{{ .Values.git_sync_host }}:{{ .Values.git_sync_port }}/{{ .Values.git_sync_repo }} 35 | LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=~/passwd NSS_WRAPPER_GROUP=~/group git push -f --all backup 36 | env: 37 | - name: GIT_COMMITTER_NAME 38 | value: hello 39 | - name: GIT_COMMITTER_EMAIL 40 | value: hello@world.com 41 | image: {{ .Values.image }}:{{ .Values.image_tag }} 42 | name: {{ .Values.job_name }} 43 | volumeMounts: 44 | - mountPath: /etc/secret-volume 45 | name: secret-volume 46 | readOnly: true 47 | dnsPolicy: ClusterFirst 48 | restartPolicy: Never 49 | terminationGracePeriodSeconds: 30 50 | volumes: 51 | - name: secret-volume 52 | secret: 53 | secretName: {{ .Values.ssh_key_secret_name }} 54 | schedule: {{ .Values.schedule | quote }} 55 | successfulJobsHistoryLimit: {{ .Values.success_jobs_history_limit }} 56 | -------------------------------------------------------------------------------- /charts/cronjob-git-sync/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | ssh-privatekey: {{ .Values.git_private_key }} 4 | kind: Secret 5 | metadata: 6 | labels: 7 | template: cronjob-git-sync 8 | name: {{ .Values.ssh_key_secret_name }} 9 | type: Opaque 10 | -------------------------------------------------------------------------------- /charts/cronjob-git-sync/values.yaml: -------------------------------------------------------------------------------- 1 | failed_jobs_history_limit: "5" 2 | git_host: '# TODO: must define a default value for .git_host' 3 | git_port: "22" 4 | git_private_key: '# TODO: must define a default value for .git_private_key' 5 | git_repo: '# TODO: must define a default value for .git_repo' 6 | git_sync_host: '# TODO: must define a default value for .git_sync_host' 7 | git_sync_port: "22" 8 | git_sync_repo: '# TODO: must define a default value for .git_sync_repo' 9 | image: registry.access.redhat.com/openshift3/python-33-rhel7 10 | image_tag: latest 11 | job_name: cronjob-git-sync 12 | schedule: '@hourly' 13 | ssh_key_secret_name: ssh-key-secret 14 | success_jobs_history_limit: "5" 15 | -------------------------------------------------------------------------------- /charts/cronjob-gitlab-delete-projects/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: gitlab-cleanup 3 | description: A Helm chart to clean up stale gitlab groups and projects 4 | type: application 5 | version: 0.1.1 6 | appVersion: v0.1.0 7 | maintainers: 8 | - name: redhat-cop 9 | -------------------------------------------------------------------------------- /charts/cronjob-gitlab-delete-projects/README.md: -------------------------------------------------------------------------------- 1 | ![Gitlab Delete Projects Container](https://github.com/redhat-cop/openshift-management/workflows/Gitlab%20Delete%20Projects%20Container/badge.svg) 2 | 3 | # Gitlab Delete Projects Job 4 | 5 | A cronjob that enables OpenShift to delete Gitlab projects that have become stale by checking the age of a repo. This also deletes groups that have no projects. Provide the job a top level group and it will search all projects under it and delete stale ones based on last activity and also remove empty groups. 6 | 7 | The cronjob will not delete in the follow cases: 8 | 9 | 1. A group with the text `DO_NOT_DELETE` in the description will not delete the group, any subgroup and projects in the group and subgroups. 10 | 2. A project wit the text `DO_NOT_DELETE` in the description or a tag `DO_NOT_DELETE` in the tag list. 11 | 12 | **Caution:** this jobs performs hard deletes. The actual deletion policy is influenced by overarching settings in Gitlab. 13 | 14 | ## Notification / Hook 15 | 16 | This job has the ability to notify applications via a webhook. Specify the url to post to and the value of the secret header `x-notification-token` for the request to be invoked. 17 | 18 | The json payload will look like 19 | 20 | ``` 21 | { 22 | "event_name": "project_deleted", # or group_deleted 23 | "group_id": 1424, # only set if group was deleted 24 | "project" { ...} # the full gitlab project structure, only set if project was deleted 25 | } 26 | ``` 27 | 28 | ## Using This Chart 29 | 30 | This chart is geared toward Helm 3. 31 | 32 | 1. Clone the target repo 33 | 34 | ``` 35 | git clone https://github.com/redhat-cop/openshift-management.git 36 | ``` 37 | 38 | 2. Change into ths job's directory 39 | 40 | ``` 41 | cd openshift-management/charts/cronjob-gitlab-delete-projects 42 | ``` 43 | 44 | 3. Deploy using the follow Helm command: 45 | 46 | ``` 47 | helm template . \ 48 | --set env.secret.name=my-openshift-secret-ref \ 49 | --set env.gitlabApiUrl=https//my.gitlab.base.com \ 50 | --set env.secret.personalAccessToken=bot-token-value \ 51 | --set env.parentGroupId=-1 \ 52 | | oc apply -f - -n target-namespace 53 | ``` 54 | 55 | The following variables maybe configured. 56 | 57 | | Variable | Used by | Usage | Default | 58 | |---|---|--|--| 59 | | `image.name` | cronjob | The name of the image | `quay.io/redhat-cop/gitlab-cleanup` | 60 | | `image.tag` | cronjob | The tag of the image | `latest` | 61 | | `cron.schedule` | cronjob | The cron schedule | `"1 0 * * *"` | 62 | | `cron.historyLimit` | cronjob | The amount of job runs to retain. | `5` | 63 | | `generateSecret` | secret | If true, then helm will generate the secret with values set at `env.secret.xxx`. | `false` | 64 | | `env.deleteAfterInHours` | cronjob | The job will delete itetms that are older than this amount of time. | `100 years` | 65 | | `env.dryRun` | cronjob | If true, then this job will not perform the deletes. Good for tetsting. | `true` | 66 | | `env.logLevel` | cronjob | Set the application log level. | `INFO` | 67 | | `env.secret.name` | cronjob, secret | A reference to an opaque secret that is deployed in the same namespace. Can be generated if necessary. | `secret-gitlab-info` | 68 | | `env.gitlabApiUrl` | cronjob | The url of the gitlab instance | 69 | | `env.secret.personalAccessToken` | secret | The personal access token for the user accessing gitlab. Bot recommended | 70 | | `env.parentGroupId` | cronjob | Group ID of the GitLab (sub)group to look for projects to delete. | 71 | | `env.secret.notificationToken` | secret | The access token for the notification application | 72 | | `env.notificationUrl` | cronjob | The url to notify when a delete has occurred. Disabled during a dry run unless the token is set to `DRYRUN` | 73 | -------------------------------------------------------------------------------- /charts/cronjob-gitlab-delete-projects/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | labels: 5 | app: {{ .Values.name }} 6 | name: {{ .Values.name }} 7 | spec: 8 | schedule: "{{ .Values.cron.schedule }}" 9 | concurrencyPolicy: "Forbid" 10 | successfulJobsHistoryLimit: {{ .Values.cron.historyLimit }} 11 | jobTemplate: 12 | spec: 13 | template: 14 | spec: 15 | containers: 16 | - image: {{ .Values.image.name }}:{{ .Values.image.tag }} 17 | env: 18 | - name: LOG_LEVEL 19 | value: "{{ .Values.env.logLevel }}" 20 | - name: DELETE_AFTER_HOURS 21 | value: "{{ .Values.env.deleteAfterInHours }}" 22 | - name: DRY_RUN 23 | value: "{{ .Values.env.dryRun }}" 24 | - name: GITLAB_API_URL 25 | value: "{{ .Values.env.gitlabApiUrl }}" 26 | - name: PARENT_GROUP_ID 27 | value: "{{ .Values.env.parentGroupId }}" 28 | - name: NOTIFICATION_URL 29 | value: "{{ .Values.env.notificationUrl }}" 30 | - name: GIT_TOKEN 31 | valueFrom: 32 | secretKeyRef: 33 | key: GITLAB_PERSONAL_ACCESS_TOKEN 34 | name: {{ .Values.env.secret.name }} 35 | - name: NOTIFICATION_TOKEN 36 | valueFrom: 37 | secretKeyRef: 38 | key: NOTIFICATION_TOKEN 39 | name: {{ .Values.env.secret.name }} 40 | imagePullPolicy: Always 41 | name: {{ .Values.name }} 42 | resources: {} 43 | terminationMessagePath: /dev/termination-log 44 | terminationMessagePolicy: File 45 | restartPolicy: OnFailure 46 | status: {} 47 | -------------------------------------------------------------------------------- /charts/cronjob-gitlab-delete-projects/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.generateSecret }} 2 | apiVersion: v1 3 | stringData: 4 | GITLAB_PERSONAL_ACCESS_TOKEN: {{ .Values.env.secret.personalAccessToken }} 5 | NOTIFICATION_TOKEN: {{ .Values.env.secret.notificationToken }} 6 | kind: Secret 7 | metadata: 8 | name: {{ .Values.env.secret.name }} 9 | type: Opaque 10 | {{- end }} 11 | -------------------------------------------------------------------------------- /charts/cronjob-gitlab-delete-projects/values.yaml: -------------------------------------------------------------------------------- 1 | name: gitlab-cleanup 2 | 3 | image: 4 | name: "quay.io/redhat-cop/gitlab-cleanup" 5 | tag: "master" # This is intended to be overridden by the parent Helm chart. 6 | 7 | generateSecret: false # set true if you want to create the secret data file. 8 | 9 | env: 10 | secret: 11 | name: secret-gitlab-info # cronjob references this secret 12 | personalAccessToken: xxxx # real value needed if generateSecret=true 13 | notificationToken: yyyy # real value needed if generateSecret=true 14 | gitlabApiUrl: http://gitlab.ca 15 | parentGroupId: 6 # top level group to search 16 | deleteAfterInHours: 876000 # 1 year 17 | dryRun: TRUE # set this to false to delete something 18 | logLevel: DEBUG 19 | 20 | cron: 21 | schedule: "1 0 * * *" 22 | historyLimit: 5 23 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync-secure/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | description: Scheduled Task to Perform LDAP Group Synchronization 3 | name: cronjob-ldap-group-sync-secure 4 | tags: management,cronjob,ldap,group,sync 5 | version: 0.0.2 6 | maintainers: 7 | - name: redhat-cop 8 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync-secure/templates/clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | template: cronjob-ldap-group-sync-secure 6 | name: ldap-group-syncer 7 | namespace: {{ .Values.namespace }} 8 | rules: 9 | - apiGroups: 10 | - "" 11 | - user.openshift.io 12 | resources: 13 | - groups 14 | verbs: 15 | - get 16 | - list 17 | - create 18 | - update 19 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync-secure/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | groupNames: null 3 | kind: ClusterRoleBinding 4 | metadata: 5 | labels: 6 | template: cronjob-ldap-group-sync-secure 7 | name: {{ .Values.namespace }}-ldap-group-syncers 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | name: ldap-group-syncer 11 | kind: ClusterRole 12 | subjects: 13 | - kind: ServiceAccount 14 | name: {{ .Values.job_service_account }} 15 | namespace: {{ .Values.namespace }} 16 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync-secure/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | ldap-group-sync.yaml: | 4 | kind: "LDAPSyncConfig" 5 | apiVersion: "v1" 6 | url: "{{ .Values.ldap_url }}" 7 | insecure: false 8 | bindDN: "{{ .Values.ldap_bind_dn }}" 9 | bindPassword: 10 | file: "/ldap-sync/secrets/bind_password" 11 | ca: "/ldap-sync/ca/ldap-ca.crt" 12 | rfc2307: 13 | groupsQuery: 14 | baseDN: "{{ .Values.ldap_groups_search_base }}" 15 | scope: "sub" 16 | derefAliases: "never" 17 | filter: "{{ .Values.ldap_groups_filter }}" 18 | pageSize: 0 19 | groupUIDAttribute: "{{ .Values.ldap_group_uid_attribute }}" 20 | groupNameAttributes: {{ .Values.ldap_group_name_attributes }} 21 | groupMembershipAttributes: {{ .Values.ldap_group_membership_attributes }} 22 | usersQuery: 23 | baseDN: "{{ .Values.ldap_users_search_base }}" 24 | scope: "sub" 25 | derefAliases: "never" 26 | pageSize: 0 27 | userNameAttributes: {{ .Values.ldap_user_name_attributes }} 28 | userUIDAttribute: "{{ .Values.ldap_user_uid_attribute }}" 29 | tolerateMemberNotFoundErrors: true 30 | tolerateMemberOutOfScopeErrors: true 31 | whitelist.txt: {{ .Values.ldap_groups_whitelist | quote }} 32 | kind: ConfigMap 33 | metadata: 34 | labels: 35 | template: cronjob-ldap-group-sync-secure 36 | name: {{ .Values.ldap_sync_configmap }} 37 | namespace: {{ .Values.namespace }} 38 | --- 39 | apiVersion: v1 40 | data: 41 | ldap-ca.crt: {{ .Values.ldap_ca_cert }} 42 | kind: ConfigMap 43 | metadata: 44 | labels: 45 | template: cronjob-ldap-group-sync-secure 46 | name: {{ .Values.ldap_sync_ca_configmap }} 47 | namespace: {{ .Values.namespace }} 48 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync-secure/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | labels: 5 | template: cronjob-ldap-group-sync-secure 6 | name: {{ .Values.job_name }} 7 | namespace: {{ .Values.namespace }} 8 | spec: 9 | concurrencyPolicy: Forbid 10 | failedJobsHistoryLimit: {{ .Values.failed_jobs_history_limit }} 11 | jobTemplate: 12 | spec: 13 | backoffLimit: 0 14 | template: 15 | spec: 16 | activeDeadlineSeconds: 500 17 | containers: 18 | - command: 19 | - /bin/bash 20 | - -c 21 | - oc adm groups sync --confirm --sync-config=/ldap-sync/config/ldap-group-sync.yaml 22 | $([ -s /ldap-sync/config/whitelist.txt ] && echo --whitelist=/ldap-sync/config/whitelist.txt) 23 | image: {{ .Values.image }}:{{ .Values.image_tag }} 24 | name: {{ .Values.job_name }} 25 | volumeMounts: 26 | - mountPath: /ldap-sync/config 27 | name: ldap-sync-config 28 | - mountPath: /ldap-sync/ca 29 | name: ldap-sync-ca 30 | - mountPath: /ldap-sync/secrets 31 | name: ldap-bind-password 32 | dnsPolicy: ClusterFirst 33 | restartPolicy: Never 34 | serviceAccount: {{ .Values.job_service_account }} 35 | serviceAccountName: {{ .Values.job_service_account }} 36 | terminationGracePeriodSeconds: 30 37 | volumes: 38 | - configMap: 39 | name: {{ .Values.ldap_sync_configmap }} 40 | name: ldap-sync-config 41 | - configMap: 42 | name: {{ .Values.ldap_sync_ca_configmap }} 43 | name: ldap-sync-ca 44 | - name: ldap-bind-password 45 | secret: 46 | secretName: {{ .Values.ldap_bind_password_secret }} 47 | schedule: {{ .Values.schedule | quote }} 48 | successfulJobsHistoryLimit: {{ .Values.success_jobs_history_limit }} 49 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync-secure/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | labels: 5 | template: cronjob-ldap-group-sync-secure 6 | name: {{ .Values.ldap_bind_password_secret }} 7 | namespace: {{ .Values.namespace }} 8 | stringData: 9 | bind_password: {{ .Values.ldap_bind_password }} 10 | type: Opaque 11 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync-secure/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | template: cronjob-ldap-group-sync-secure 6 | name: {{ .Values.job_service_account }} 7 | namespace: {{ .Values.namespace }} 8 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync-secure/values.yaml: -------------------------------------------------------------------------------- 1 | failed_jobs_history_limit: "5" 2 | image: registry.access.redhat.com/openshift3/ose-cli 3 | image_tag: v3.11 4 | job_name: cronjob-ldap-group-sync 5 | job_service_account: ldap-group-syncer 6 | ldap_bind_dn: '# TODO: must define a default value for .ldap_bind_dn' 7 | ldap_bind_password: '# TODO: must define a default value for .ldap_bind_password' 8 | ldap_bind_password_secret: ldap-bind-password 9 | ldap_ca_cert: '# TODO: must define a default value for .ldap_ca_cert' 10 | ldap_group_membership_attributes: '["member"]' 11 | ldap_group_name_attributes: '["cn"]' 12 | ldap_group_uid_attribute: ipaUniqueID 13 | ldap_groups_filter: (&(objectclass=ipausergroup)(memberOf=cn=openshift-users,cn=groups,cn=accounts,dc=myorg,dc=example,dc=com)) 14 | ldap_groups_search_base: cn=groups,cn=accounts,dc=myorg,dc=example,dc=com 15 | ldap_groups_whitelist: '# TODO: must define a default value for .ldap_groups_whitelist' 16 | ldap_sync_ca_configmap: ldap-group-sync-ca 17 | ldap_sync_configmap: ldap-group-sync 18 | ldap_url: '# TODO: must define a default value for .ldap_url' 19 | ldap_user_name_attributes: '["uid"]' 20 | ldap_user_uid_attribute: dn 21 | ldap_users_search_base: cn=users,cn=accounts,dc=myorg,dc=example,dc=com 22 | namespace: cluster-ops 23 | schedule: '@hourly' 24 | success_jobs_history_limit: "5" 25 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | description: Scheduled Task to Perform LDAP Group Synchronization 3 | name: cronjob-ldap-group-sync 4 | tags: management,cronjob,ldap,group,sync 5 | version: 0.0.2 6 | maintainers: 7 | - name: redhat-cop 8 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync/templates/clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | template: cronjob-ldap-group-sync 6 | name: ldap-group-syncer 7 | namespace: {{ .Values.namespace }} 8 | rules: 9 | - apiGroups: 10 | - "" 11 | - user.openshift.io 12 | resources: 13 | - groups 14 | verbs: 15 | - get 16 | - list 17 | - create 18 | - update 19 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | groupNames: null 3 | kind: ClusterRoleBinding 4 | metadata: 5 | labels: 6 | template: cronjob-ldap-group-sync 7 | name: {{ .Values.namespace }}-ldap-group-syncers 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | name: ldap-group-syncer 11 | kind: ClusterRole 12 | subjects: 13 | - kind: ServiceAccount 14 | name: {{ .Values.job_service_account }} 15 | namespace: {{ .Values.namespace }} 16 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | ldap-group-sync.yaml: | 4 | kind: "LDAPSyncConfig" 5 | apiVersion: "v1" 6 | url: "{{ .Values.ldap_url }}" 7 | insecure: true 8 | bindDN: "{{ .Values.ldap_bind_dn }}" 9 | bindPassword: 10 | file: "/etc/secrets/bind_password" 11 | rfc2307: 12 | groupsQuery: 13 | baseDN: "{{ .Values.ldap_groups_search_base }}" 14 | scope: "sub" 15 | derefAliases: "never" 16 | filter: "{{ .Values.ldap_groups_filter }}" 17 | pageSize: 0 18 | groupUIDAttribute: "{{ .Values.ldap_group_uid_attribute }}" 19 | groupNameAttributes: {{ .Values.ldap_group_name_attributes }} 20 | groupMembershipAttributes: {{ .Values.ldap_group_membership_attributes }} 21 | usersQuery: 22 | baseDN: "{{ .Values.ldap_users_search_base }}" 23 | scope: "sub" 24 | derefAliases: "never" 25 | pageSize: 0 26 | userNameAttributes: {{ .Values.ldap_user_name_attributes }} 27 | userUIDAttribute: "{{ .Values.ldap_user_uid_attribute }}" 28 | tolerateMemberNotFoundErrors: true 29 | tolerateMemberOutOfScopeErrors: true 30 | whitelist.txt: {{ .Values.ldap_groups_whitelist | quote }} 31 | kind: ConfigMap 32 | metadata: 33 | labels: 34 | template: cronjob-ldap-group-sync 35 | name: ldap-config 36 | namespace: {{ .Values.namespace }} 37 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | labels: 5 | template: cronjob-ldap-group-sync 6 | name: {{ .Values.job_name }} 7 | namespace: {{ .Values.namespace }} 8 | spec: 9 | concurrencyPolicy: Forbid 10 | failedJobsHistoryLimit: {{ .Values.failed_jobs_history_limit }} 11 | jobTemplate: 12 | spec: 13 | backoffLimit: 0 14 | template: 15 | spec: 16 | activeDeadlineSeconds: 500 17 | containers: 18 | - command: 19 | - /bin/bash 20 | - -c 21 | - oc adm groups sync --sync-config=/etc/config/ldap-group-sync.yaml --confirm 22 | $([ -s /etc/config/whitelist.txt ] && echo --whitelist=/etc/config/whitelist.txt) 23 | image: {{ .Values.image }}:{{ .Values.image_tag }} 24 | name: {{ .Values.job_name }} 25 | volumeMounts: 26 | - mountPath: /etc/config 27 | name: ldap-sync-volume 28 | - mountPath: /etc/secrets 29 | name: ldap-bind-password 30 | dnsPolicy: ClusterFirst 31 | restartPolicy: Never 32 | serviceAccount: {{ .Values.job_service_account }} 33 | serviceAccountName: {{ .Values.job_service_account }} 34 | terminationGracePeriodSeconds: 30 35 | volumes: 36 | - configMap: 37 | name: ldap-config 38 | name: ldap-sync-volume 39 | - name: ldap-bind-password 40 | secret: 41 | secretName: {{ .Values.ldap_bind_password_secret }} 42 | schedule: {{ .Values.schedule | quote }} 43 | successfulJobsHistoryLimit: {{ .Values.success_jobs_history_limit }} 44 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | labels: 5 | template: cronjob-ldap-group-sync 6 | name: {{ .Values.ldap_bind_password_secret }} 7 | namespace: {{ .Values.namespace }} 8 | stringData: 9 | bind_password: {{ .Values.ldap_bind_password }} 10 | type: Opaque 11 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | template: cronjob-ldap-group-sync 6 | name: {{ .Values.job_service_account }} 7 | namespace: {{ .Values.namespace }} 8 | -------------------------------------------------------------------------------- /charts/cronjob-ldap-group-sync/values.yaml: -------------------------------------------------------------------------------- 1 | failed_jobs_history_limit: "5" 2 | image: registry.access.redhat.com/openshift3/ose-cli 3 | image_tag: v3.11 4 | job_name: cronjob-ldap-group-sync 5 | job_service_account: ldap-group-syncer 6 | ldap_bind_dn: '# TODO: must define a default value for .ldap_bind_dn' 7 | ldap_bind_password: '# TODO: must define a default value for .ldap_bind_password' 8 | ldap_bind_password_secret: ldap-bind-password 9 | ldap_group_membership_attributes: '["member"]' 10 | ldap_group_name_attributes: '["cn"]' 11 | ldap_group_uid_attribute: ipaUniqueID 12 | ldap_groups_filter: (&(objectclass=ipausergroup)(memberOf=cn=openshift-users,cn=groups,cn=accounts,dc=myorg,dc=example,dc=com)) 13 | ldap_groups_search_base: cn=groups,cn=accounts,dc=myorg,dc=example,dc=com 14 | ldap_groups_whitelist: '# TODO: must define a default value for .ldap_groups_whitelist' 15 | ldap_url: '# TODO: must define a default value for .ldap_url' 16 | ldap_user_name_attributes: '["uid"]' 17 | ldap_user_uid_attribute: dn 18 | ldap_users_search_base: cn=users,cn=accounts,dc=myorg,dc=example,dc=com 19 | namespace: cluster-ops 20 | schedule: '@hourly' 21 | success_jobs_history_limit: "5" 22 | -------------------------------------------------------------------------------- /charts/cronjob-prune-builds-deployments/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | description: Scheduled Task to Prune Builds or Deployments 3 | name: cronjob-prune-builds-deployments 4 | tags: management,cronjob,prune,builds,deployments 5 | version: 0.0.2 6 | maintainers: 7 | - name: redhat-cop 8 | -------------------------------------------------------------------------------- /charts/cronjob-prune-builds-deployments/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | template: cronjob-prune-builds-deployments 6 | name: {{ .Values.namespace }}-{{ .Values.prune_type }}-pruners 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | name: cluster-admin 10 | kind: ClusterRole 11 | subjects: 12 | - kind: ServiceAccount 13 | name: {{ .Values.prune_type }}-{{ .Values.job_service_account }} 14 | namespace: {{ .Values.namespace }} 15 | -------------------------------------------------------------------------------- /charts/cronjob-prune-builds-deployments/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | labels: 5 | template: cronjob-prune-builds-deployments 6 | name: {{ .Values.job_name }}-{{ .Values.prune_type }} 7 | spec: 8 | concurrencyPolicy: Forbid 9 | failedJobsHistoryLimit: {{ .Values.failed_jobs_history_limit }} 10 | jobTemplate: 11 | spec: 12 | template: 13 | spec: 14 | activeDeadlineSeconds: 500 15 | containers: 16 | - command: 17 | - /bin/bash 18 | - -c 19 | - oc adm prune {{ .Values.prune_type }} --keep-complete=$KEEP_COMPLETE --keep-failed=$KEEP_FAILED 20 | --keep-younger-than=$KEEP_YOUNGER_THAN --orphans=$PRUNE_ORPHANS --confirm 21 | env: 22 | - name: KEEP_COMPLETE 23 | value: "{{ .Values.keep_complete }}" 24 | - name: KEEP_FAILED 25 | value: "{{ .Values.keep_failed }}" 26 | - name: KEEP_YOUNGER_THAN 27 | value: "{{ .Values.keep_younger_than }}" 28 | - name: PRUNE_ORPHANS 29 | value: "{{ .Values.prune_orphans }}" 30 | image: {{ .Values.image }}:{{ .Values.image_tag }} 31 | name: {{ .Values.job_name }}-{{ .Values.prune_type }} 32 | dnsPolicy: ClusterFirst 33 | restartPolicy: Never 34 | serviceAccount: {{ .Values.prune_type }}-{{ .Values.job_service_account }} 35 | serviceAccountName: {{ .Values.prune_type }}-{{ .Values.job_service_account }} 36 | terminationGracePeriodSeconds: 30 37 | schedule: "{{ .Values.schedule }}" 38 | successfulJobsHistoryLimit: {{ .Values.success_jobs_history_limit }} 39 | -------------------------------------------------------------------------------- /charts/cronjob-prune-builds-deployments/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | template: cronjob-prune-builds-deployments 6 | name: {{ .Values.prune_type }}-{{ .Values.job_service_account }} 7 | -------------------------------------------------------------------------------- /charts/cronjob-prune-builds-deployments/values.yaml: -------------------------------------------------------------------------------- 1 | failed_jobs_history_limit: "5" 2 | image: quay.io/openshift/origin-cli 3 | image_tag: 4.5 4 | job_name: cronjob-prune-resources 5 | job_service_account: pruner 6 | keep_complete: "5" 7 | keep_failed: "1" 8 | keep_younger_than: 60m 9 | namespace: cluster-ops 10 | prune_orphans: "true" 11 | prune_type: builds 12 | schedule: 0 0 * * * 13 | success_jobs_history_limit: "5" 14 | -------------------------------------------------------------------------------- /charts/cronjob-prune-images/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | description: Scheduled Task to Prune Images from Internal Docker Registry 3 | name: cronjob-prune-images 4 | tags: management,cronjob,prune,images 5 | version: 0.0.2 6 | maintainers: 7 | - name: redhat-cop 8 | -------------------------------------------------------------------------------- /charts/cronjob-prune-images/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | template: cronjob-prune-images 6 | name: {{ .Values.namespace }}-image-pruners 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | name: cluster-admin 10 | kind: ClusterRole 11 | subjects: 12 | - kind: ServiceAccount 13 | name: {{ .Values.job_service_account }} 14 | namespace: {{ .Values.namespace }} 15 | -------------------------------------------------------------------------------- /charts/cronjob-prune-images/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | labels: 5 | template: cronjob-prune-images 6 | name: {{ .Values.job_name }} 7 | spec: 8 | concurrencyPolicy: Forbid 9 | failedJobsHistoryLimit: {{ .Values.failed_jobs_history_limit }} 10 | jobTemplate: 11 | spec: 12 | template: 13 | spec: 14 | activeDeadlineSeconds: 500 15 | containers: 16 | - command: 17 | - /bin/bash 18 | - -c 19 | - oc adm prune images --certificate-authority=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt 20 | --keep-tag-revisions=$IMAGE_PRUNE_KEEP_TAG_REVISIONS --keep-younger-than=$IMAGE_PRUNE_KEEP_YOUNGER_THAN --confirm 21 | env: 22 | - name: IMAGE_PRUNE_KEEP_TAG_REVISIONS 23 | value: "{{ .Values.image_prune_keep_tag_revisions }}" 24 | - name: IMAGE_PRUNE_KEEP_YOUNGER_THAN 25 | value: "{{ .Values.image_prune_keep_younger_than }}" 26 | image: {{ .Values.image }}:{{ .Values.image_tag }} 27 | name: {{ .Values.job_name }} 28 | dnsPolicy: ClusterFirst 29 | restartPolicy: Never 30 | serviceAccount: {{ .Values.job_service_account }} 31 | serviceAccountName: {{ .Values.job_service_account }} 32 | terminationGracePeriodSeconds: 30 33 | schedule: "{{ .Values.schedule }}" 34 | successfulJobsHistoryLimit: {{ .Values.success_jobs_history_limit }} 35 | -------------------------------------------------------------------------------- /charts/cronjob-prune-images/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | template: cronjob-prune-images 6 | name: {{ .Values.job_service_account }} 7 | -------------------------------------------------------------------------------- /charts/cronjob-prune-images/values.yaml: -------------------------------------------------------------------------------- 1 | failed_jobs_history_limit: "5" 2 | image: quay.io/openshift/origin-cli 3 | image_prune_keep_tag_revisions: "3" 4 | image_prune_keep_younger_than: 1h0m0s 5 | image_tag: 4.4 6 | job_name: cronjob-prune-images 7 | job_service_account: image-pruner 8 | namespace: cluster-ops 9 | schedule: "0 0 * * *" 10 | success_jobs_history_limit: "5" 11 | -------------------------------------------------------------------------------- /charts/cronjob-prune-projects/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: cronjob-prune-projects 3 | version: 0.0.2 4 | maintainers: 5 | - name: redhat-cop 6 | -------------------------------------------------------------------------------- /charts/cronjob-prune-projects/templates/buildconfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: build.openshift.io/v1 2 | kind: BuildConfig 3 | metadata: 4 | annotations: 5 | description: Defines how to build the application 6 | labels: 7 | template: cronjob-prune-projects 8 | name: {{ .Values.name }} 9 | spec: 10 | completionDeadlineSeconds: 1800 11 | output: 12 | to: 13 | kind: ImageStreamTag 14 | name: {{ .Values.name }}:{{ .Values.tag }} 15 | runPolicy: Serial 16 | source: 17 | contextDir: {{ .Values.context_dir }} 18 | git: 19 | ref: {{ .Values.source_repository_ref }} 20 | uri: {{ .Values.source_repository_url }} 21 | type: Git 22 | strategy: 23 | dockerStrategy: 24 | from: 25 | kind: DockerImage 26 | name: {{ .Values.base_image }} 27 | type: Docker 28 | triggers: 29 | - type: ConfigChange 30 | -------------------------------------------------------------------------------- /charts/cronjob-prune-projects/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | template: cronjob-prune-projects 6 | name: {{ .Values.namespace }}-project-pruners 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | name: cluster-admin 10 | kind: ClusterRole 11 | subjects: 12 | - kind: ServiceAccount 13 | name: {{ .Values.job_service_account }} 14 | namespace: {{ .Values.namespace }} 15 | -------------------------------------------------------------------------------- /charts/cronjob-prune-projects/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | labels: 5 | template: cronjob-prune-projects 6 | name: {{ .Values.job_name }} 7 | spec: 8 | concurrencyPolicy: Forbid 9 | failedJobsHistoryLimit: {{ .Values.failed_jobs_history_limit }} 10 | jobTemplate: 11 | spec: 12 | template: 13 | spec: 14 | activeDeadlineSeconds: 500 15 | containers: 16 | - command: 17 | - /bin/bash 18 | - -c 19 | - /usr/local/bin/prune-ocp-projects.sh 20 | env: 21 | - name: PROJECT_EXCLUDE_USER 22 | value: "{{ .Values.project_exclude_user }}" 23 | - name: PROJECT_EXCLUDE_SYSTEM 24 | value: "{{ .Values.namespace }} {{ .Values.project_exclude_system }}" 25 | - name: TIMESTAMP_HOURS_AGO 26 | value: "{{ .Values.timestamp_hours_ago }}" 27 | image: {{ .Values.name }}:{{ .Values.tag }} 28 | name: {{ .Values.job_name }} 29 | dnsPolicy: ClusterFirst 30 | restartPolicy: Never 31 | serviceAccount: {{ .Values.job_service_account }} 32 | serviceAccountName: {{ .Values.job_service_account }} 33 | terminationGracePeriodSeconds: 30 34 | schedule: "{{ .Values.schedule }}" 35 | successfulJobsHistoryLimit: {{ .Values.success_jobs_history_limit }} 36 | -------------------------------------------------------------------------------- /charts/cronjob-prune-projects/templates/imagestream.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: image.openshift.io/v1 2 | kind: ImageStream 3 | metadata: 4 | annotations: 5 | description: Keeps track of changes in the application image 6 | labels: 7 | template: cronjob-prune-projects 8 | name: {{ .Values.name }} 9 | spec: 10 | lookupPolicy: 11 | local: true 12 | -------------------------------------------------------------------------------- /charts/cronjob-prune-projects/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | template: cronjob-prune-projects 6 | name: {{ .Values.job_service_account }} 7 | -------------------------------------------------------------------------------- /charts/cronjob-prune-projects/values.yaml: -------------------------------------------------------------------------------- 1 | base_image: centos:7 2 | context_dir: images/prune-ocp-projects 3 | failed_jobs_history_limit: "5" 4 | job_name: cronjob-prune-projects 5 | job_service_account: project-pruner 6 | name: prune-ocp-projects 7 | namespace: cluster-ops 8 | project_exclude_system: cluster-ops 9 | project_exclude_user: '# TODO: must define a default value for .project_exclude_user' 10 | schedule: '@hourly' 11 | source_repository_ref: master 12 | source_repository_url: https://github.com/redhat-cop/openshift-management 13 | success_jobs_history_limit: "5" 14 | tag: latest 15 | timestamp_hours_ago: -12hours 16 | -------------------------------------------------------------------------------- /charts/cronjob-prune-tekton-pipelinerun/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | description: Scheduled task to prune pipelinerun from tekton 3 | name: cronjob-prune-tekton-pipelinerun 4 | tags: management,cronjob,prune,tekton,pipelinerun 5 | version: 0.0.2 6 | maintainers: 7 | - name: redhat-cop 8 | -------------------------------------------------------------------------------- /charts/cronjob-prune-tekton-pipelinerun/README.md: -------------------------------------------------------------------------------- 1 | # Delete Tekton Pipelinruns Job 2 | 3 | A cronjob that enables OpenShift to delete Tekton Pipelineruns that have completed. The job will delete Pipelineruns above `NUM_TO_KEEP` in all namespaces (`^kube|^openshift|^default` are excluded). Individual pipelines can also be deleted through `PIPELINES` (use the following format: `"ns1/pipeline1 ns1/pipeline2 ns2/pipeline1"`). 4 | 5 | ## Using This Chart 6 | 7 | This chart is geared toward Helm 3. 8 | 9 | 1. Clone the target repo 10 | 11 | ``` 12 | git clone https://github.com/redhat-cop/openshift-management.git 13 | ``` 14 | 15 | 2. Change into ths job's directory 16 | 17 | ``` 18 | cd openshift-management/charts/cronjob-prune-tekton-pipelinerun 19 | ``` 20 | 21 | 3. Deploy using the follow Helm command: 22 | 23 | ``` 24 | helm template prune-tekton-pipelinerun . \ 25 | --set namespace=prune-jobs \ 26 | --set num_to_keep=5 \ 27 | --set pipelines="ns1/pipeline1 ns2/pipeline1" 28 | | oc apply -f - -n target-namespace 29 | ``` 30 | 31 | The following variables maybe configured. 32 | 33 | | Variable | Used by | Usage | Default | 34 | |---|---|--|--| 35 | | `namespace` | cronjob | The namespace where to install | `labs-ci-cd` | 36 | | `job_name` | cronjob | The name of the cronjob| `cronjob-prune-tekton-pipelinerun` | 37 | | `schedule` | cronjob | The cron schedule | `"*/30 * * * *"` | 38 | | `num_to_keep` | cronjob | The number of pipelineruns to retain (per pipeline). | `10` | 39 | | `pipelines` | cronjob | If set, then only these pipelines will be pruned. Should use format `namespace1/pipeline1`. Multiple pipelines are supported, use space delimited pipelines. | `""` | 40 | | `failed_jobs_history_limit` | cronjob | The number of failed jobs to keep. | `5` | 41 | | `success_jobs_history_limit` | cronjob | The number of successful jobs to keep. | `5` | 42 | | `image` | cronjob | The container image to use for the cronjob. | `quay.io/openshift/origin-cli` | 43 | | `image_tag` | cronjob | The container image tag to use for the cronjob. | `4.7` | 44 | -------------------------------------------------------------------------------- /charts/cronjob-prune-tekton-pipelinerun/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | template: cronjob-prune-tekton-pipelinerun 6 | name: {{ .Values.namespace }}-tekton-pipelinerun-pruners 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | name: cluster-admin 10 | kind: ClusterRole 11 | subjects: 12 | - kind: ServiceAccount 13 | name: {{ .Values.job_service_account }} 14 | namespace: {{ .Values.namespace }} -------------------------------------------------------------------------------- /charts/cronjob-prune-tekton-pipelinerun/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: batch/v1 3 | kind: CronJob 4 | metadata: 5 | labels: 6 | template: cronjob-prune-tekton-pipelinerun 7 | name: {{ .Values.job_name }} 8 | spec: 9 | schedule: {{ .Values.schedule | quote }} 10 | successfulJobsHistoryLimit: {{ .Values.success_jobs_history_limit }} 11 | concurrencyPolicy: Forbid 12 | jobTemplate: 13 | spec: 14 | template: 15 | spec: 16 | restartPolicy: OnFailure 17 | serviceAccount: cleaner 18 | containers: 19 | - name: kubectl 20 | image: {{ .Values.image }}:{{ .Values.image_tag }} 21 | env: 22 | - name: PIPELINES 23 | value: {{ .Values.pipelines | quote }} 24 | - name: NUM_TO_KEEP 25 | value: {{ .Values.num_to_keep | quote }} 26 | command: 27 | - /bin/bash 28 | - -c 29 | - | 30 | PIPELINES=${PIPELINES:-$(kubectl get pipeline -A -ojsonpath='{range .items[*]}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{end}'|grep -vE '^default|^kube|^openshift')} 31 | for pipeline in $PIPELINES 32 | do 33 | NS=$(echo $pipeline | awk -F/ '{print $1}') 34 | PL_LABEL=$(echo $pipeline | awk -F/ '{print $2}') 35 | TO_DELETE=$(kubectl get pipelinerun -n $NS -l tekton.dev/pipeline=$PL_LABEL --ignore-not-found -o jsonpath='{range .items[?(@.status.completionTime)]}{.status.completionTime}{" "}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{end}' | sort | head -n -${NUM_TO_KEEP} | awk -F/ '{print $2}') 36 | test -n "$TO_DELETE" && kubectl delete pipelinerun ${TO_DELETE} -n ${NS} || true 37 | done 38 | serviceAccount: {{ .Values.job_service_account }} 39 | serviceAccountName: {{ .Values.job_service_account }} 40 | terminationGracePeriodSeconds: 60 41 | -------------------------------------------------------------------------------- /charts/cronjob-prune-tekton-pipelinerun/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | template: cronjob-prune-tekton-pipelinerun 7 | name: {{ .Values.job_service_account }} -------------------------------------------------------------------------------- /charts/cronjob-prune-tekton-pipelinerun/values.yaml: -------------------------------------------------------------------------------- 1 | namespace: labs-ci-cd 2 | job_name: cronjob-prune-tekton-pipelinerun 3 | job_service_account: tekton-pruner 4 | pipelines: '' 5 | num_to_keep: "10" 6 | failed_jobs_history_limit: "5" 7 | schedule: "*/30 * * * *" 8 | success_jobs_history_limit: "5" 9 | image: quay.io/openshift/origin-cli 10 | image_tag: 4.7 11 | -------------------------------------------------------------------------------- /images/README.md: -------------------------------------------------------------------------------- 1 | # Images 2 | 3 | This directory contains a collection of utility images for OpenShift tasks. 4 | 5 | ## Prune Openshift projects 6 | 7 | The [prune-ocp-projects](prune-ocp-projects) declaratively prunes projects based on creation date. Projects can be excluded from being pruned by annotating the project or by excluding it based on name. 8 | -------------------------------------------------------------------------------- /images/aws-ocp-snap/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7 2 | 3 | MAINTAINER Marcos Entenza 4 | 5 | LABEL io.k8s.description="AWS EBS snaphot manager for OCP" \ 6 | io.k8s.display-name="AWS EBS snaphot manager for OCP" 7 | 8 | ENV PATH=$PATH:/usr/local/bin 9 | ENV AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} 10 | ENV AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} 11 | ENV AWS_DEFAULT_REGION=${AWS_REGION} 12 | ENV NSPACE=${NSPACE} 13 | ENV VOL=${VOL} 14 | 15 | ADD include/create_snapshot.sh /usr/local/bin/ 16 | 17 | RUN rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm && \ 18 | rm -fr /var/cache/yum/* && \ 19 | yum clean all && \ 20 | INSTALL_PKGS="python2-pip wget" && \ 21 | yum install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \ 22 | rpm -V $INSTALL_PKGS && \ 23 | yum clean all && \ 24 | pip install --upgrade pip && \ 25 | pip install awscli && \ 26 | curl https://mirror.openshift.com/pub/openshift-v3/clients/3.9.19/linux/oc.tar.gz | tar -C /usr/local/bin/ -xzf - && \ 27 | chmod +x /usr/local/bin/create_snapshot.sh 28 | 29 | 30 | CMD [ "/usr/local/bin/create_snapshot.sh", "${NSPACE}", "${VOL}" ] 31 | -------------------------------------------------------------------------------- /images/aws-ocp-snap/include/create_snapshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | NAMESPACE=$1 4 | VOLUME=$2 5 | 6 | TMPFILE=$(mktemp /tmp/tmp.XXXXXXXXXXXXX) 7 | CHKFILE=$(mktemp /tmp/chk.XXXXXXXXXXXXX) 8 | 9 | if [ -z "$NAMESPACE" -o "$NAMESPACE" = " " ]; then 10 | echo "A Namepace must be provided or select ALL" 11 | exit 2 12 | fi 13 | case "$NAMESPACE" in 14 | "ALL") 15 | oc get pv --no-headers 2> $CHKFILE 16 | RESULT=$? 17 | NOVOL=$(grep "No resources" $CHKFILE | wc -l) 18 | if [ ! $RESULT -eq 0 ] || [ $NOVOL -gt 0 ]; then 19 | echo "Error while getting EBS volumes information" 20 | exit 0 21 | else 22 | oc get pv -o=custom-columns=NAME:.spec.awsElasticBlockStore.volumeID --no-headers | cut -d "/" -f 4 > $TMPFILE 23 | while read vol 24 | do 25 | echo "Creating snapshot for EBS volume " $vol 26 | aws ec2 create-snapshot --volume-id $vol --description "Automted Snapshot by aws-ocp-snap" 27 | done < $TMPFILE 28 | fi 29 | ;; 30 | *) 31 | if [ -z "$VOLUME" -o "$VOLUME" = " " ]; then 32 | echo "A Volume must be provided or select ALL" 33 | exit 2 34 | fi 35 | case "$VOLUME" in 36 | "ALL") 37 | oc get pvc --no-headers -n $NAMESPACE 2> $CHKFILE 38 | RESULT=$? 39 | NOVOL=$(grep "No resources" $CHKFILE | wc -l) 40 | if [ ! $RESULT -eq 0 ] || [ $NOVOL -gt 0 ]; then 41 | echo "Error while getting EBS volumes information" 42 | exit 2 43 | else 44 | oc get pv $(oc get pvc -n $NAMESPACE -o=custom-columns=NAME:.spec.volumeName --no-headers) -o=custom-columns=NAME:.spec.awsElasticBlockStore.volumeID --no-headers | cut -d "/" -f 4 > $TMPFILE 45 | while read vol 46 | do 47 | echo "Creating snapshot for EBS volume " $vol 48 | aws ec2 create-snapshot --volume-id $vol --description "Automted Snapshot by aws-ocp-snap" 49 | done < $TMPFILE 50 | fi 51 | ;; 52 | *) 53 | oc get pvc --no-headers $VOLUME -n $NAMESPACE &>/dev/null 54 | if [ ! $? -eq 0 ]; then 55 | echo "Error while getting EBS volumes information" 56 | exit 2 57 | else 58 | oc get pv $(oc get pvc $VOLUME -n $NAMESPACE -o=custom-columns=NAME:.spec.volumeName --no-headers) -o=custom-columns=NAME:.spec.awsElasticBlockStore.volumeID --no-headers | cut -d "/" -f 4 59 | NOVOL=$(grep "No resources found" $TMPFILE | wc -l) 60 | if [ $NOVOL -gt 0 ];then 61 | echo "There are no presistent volumes configured" 62 | exit 1 63 | else 64 | while read vol 65 | do 66 | echo "Creating snapshot for EBS volume " $vol 67 | aws ec2 create-snapshot --volume-id $vol --description "Automted Snapshot by aws-ocp-snap" 68 | done < $TMPFILE 69 | fi 70 | fi 71 | ;; 72 | esac 73 | ;; 74 | esac 75 | -------------------------------------------------------------------------------- /images/gitlab-delete-stale-projects/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.access.redhat.com/ubi8/ubi 2 | 3 | LABEL maintainer="Red Hat Services" 4 | 5 | # Update image 6 | RUN dnf update -y && rm -rf /var/cache/yum 7 | 8 | RUN dnf install -y python3; yum clean all 9 | 10 | RUN python3 -m pip install requests 11 | 12 | ENV LOG_LEVEL=INFO 13 | ENV DRY_RUN=TRUE 14 | 15 | USER root 16 | RUN yum install -y python3-pip 17 | USER 1001 18 | 19 | ADD gitlab-cleanup.py . 20 | 21 | CMD ["python3", "gitlab-cleanup.py"] 22 | -------------------------------------------------------------------------------- /images/gitlab-delete-stale-projects/README.md: -------------------------------------------------------------------------------- 1 | # Gitlab Delete Projects Image 2 | 3 | ## Development 4 | 5 | The container can be built and run locally 6 | 7 | To build: 8 | 9 | ``` 10 | docker build . -t gitlab-clean 11 | ``` 12 | 13 | To run: 14 | 15 | ``` 16 | docker run -e DRY_RUN=true -e PARENT_GROUP_ID=-10 -e GIT_TOKEN=xxxxx -e GITLAB_API_URL=https://gitlab.com -e DELETE_AFTER_HOURS=240000 -e LOG_LEVEL=DEBUG gitlab-clean 17 | ``` 18 | 19 | See the [chart doc](../../charts/cronjob-gitlab-delete-projects/README.md) for more configuration information. -------------------------------------------------------------------------------- /images/gitlab-delete-stale-projects/gitlab-cleanup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import requests 4 | import datetime 5 | import logging 6 | import math 7 | 8 | currentTime = datetime.datetime.now() 9 | 10 | logging.basicConfig(level="INFO") 11 | logger = logging.getLogger("com.redhat.labs") 12 | logger.setLevel(os.environ.get('LOG_LEVEL', 'INFO')) 13 | 14 | gitlab_api_url = '/api/v4' 15 | git_base_url = os.environ.get('GITLAB_API_URL') 16 | git_token = os.environ.get('GIT_TOKEN') 17 | parent_group_id = os.environ.get('PARENT_GROUP_ID') 18 | delete_after_hours_string = os.environ.get('DELETE_AFTER_HOURS') 19 | delete_after_hours = 2147483647 # default but line above must be set and is enforced 20 | notification_url = os.environ.get('NOTIFICATION_URL') 21 | notification_token = os.environ.get('NOTIFICATION_TOKEN') 22 | dry_run = os.environ.get('DRY_RUN').lower() == 'true' 23 | 24 | def check_env_vars(): 25 | if parent_group_id is None: 26 | raise ValueError('Parent Group (PARENT_GROUP_ID) is required') 27 | if not parent_group_id.isnumeric(): 28 | raise ValueError('Parent Group (PARENT_GROUP_ID) has an invalid value of ' + parent_group) 29 | if not git_token: 30 | raise ValueError('Git Token (GIT_TOKEN) is required') 31 | if not git_base_url: 32 | raise ValueError('Git Url base url (GITLAB_API_URL) is required (eg. https://gitlab.com)') 33 | if not delete_after_hours_string: 34 | raise ValueError('You must set a time period to delete projects (DELETE_AFTER_HOURS)') 35 | if not delete_after_hours_string.isnumeric(): 36 | raise ValueError('You must set a time period to delete projects (DELETE_AFTER_HOURS)') 37 | 38 | logger.info(f"Notification URL {notification_url}") 39 | logger.info(f"Notification Token {notification_token.translate('*'*256)}") 40 | 41 | # clean groups and projects at our below this level of the group hierarchy 42 | # uses a staleness time measure to decide whether to delete 43 | # if a group has no projects or subgroups it should also be deleted 44 | # careful - recursion in use 45 | def clean_group(group_id, group_name): 46 | # let's us know if the group represented by group_id was deleted. This is the return value 47 | cleanGroupDeleted = False 48 | 49 | logger.debug(f'clean group {group_id} - {group_name}') 50 | 51 | subgroups = find_subgroups(group_id) 52 | subgroup_count = len(subgroups) 53 | 54 | for subgroup in subgroups: 55 | if 'DO_NOT_DELETE' in subgroup['description']: 56 | logger.info(f"Group {subgroup['name']} with subgroups and projects are not eligible for deletion") 57 | else: 58 | deleted = clean_group(subgroup['id'], subgroup['name']) 59 | logger.debug(f"subgroup {subgroup['name']}") 60 | if deleted: 61 | subgroup_count -= 1 62 | 63 | projects = find_projects(group_id) 64 | all_projects_deleted = True 65 | for project in projects: 66 | if is_project_stale(project): 67 | delete_project(project) 68 | else: 69 | all_projects_deleted = False 70 | 71 | if subgroup_count == 0 and all_projects_deleted: 72 | cleanGroupDeleted = delete_group(group_id, group_name) 73 | 74 | logger.debug(f'clean group {group_id} finished') 75 | return cleanGroupDeleted 76 | 77 | # end clean_group 78 | 79 | # returns a list of subgroups for the super group_id 80 | def find_subgroups(group_id): 81 | logger.debug(f'find subgroups {group_id}') 82 | 83 | response = requests.get( 84 | f'{git_base_url}{gitlab_api_url}/groups/{group_id}/subgroups', 85 | headers={"PRIVATE-TOKEN": git_token, 'Content-Type': 'application/json'}, 86 | ) 87 | 88 | if response.status_code == 200: 89 | return json.loads(response.text); 90 | if response.status_code == 401: 91 | raise ValueError('Git Token is not valid') 92 | 93 | return [] 94 | # end find_groups 95 | 96 | def find_projects(group_id): 97 | logger.debug(f'find projects {group_id}') 98 | 99 | response = requests.get( 100 | f'{git_base_url}{gitlab_api_url}/groups/{group_id}/projects', 101 | headers={"PRIVATE-TOKEN": git_token, 'Content-Type': 'application/json'}, 102 | ) 103 | projects = json.loads(response.text) 104 | 105 | logger.debug(f'project count = {len(projects)}') 106 | return projects 107 | # end find_projects 108 | 109 | def delete_group(group_id, group_name): 110 | logger.info(f'delete group {group_id} {group_name} dry-run {dry_run}') 111 | if(group_name == 'PARENT'): 112 | return False; 113 | 114 | if not dry_run: 115 | response = requests.delete( 116 | f'{git_base_url}{gitlab_api_url}/groups/{group_id}', 117 | headers={"PRIVATE-TOKEN": git_token}, 118 | ) 119 | 120 | if response.status_code != 202: 121 | logger.error(f"Failed to delete group {group_id} code {response.status}") 122 | return False; 123 | 124 | logger.warn(f"deleted group {group_id}") 125 | 126 | notifyGroup(group_id) 127 | return True; 128 | # end delete_group 129 | 130 | def delete_project(project): 131 | project_id = project['id'] 132 | logger.info(f"delete project {project_id} { project['name']} dry-run {dry_run}") 133 | 134 | if not dry_run: 135 | response = requests.delete( 136 | f"{git_base_url}{gitlab_api_url}/projects/{project_id}", 137 | headers={"PRIVATE-TOKEN": git_token}, 138 | ) 139 | 140 | if response.status_code != 202: 141 | logger.error(f"Failed to delete project {project_id} { project['name']} code {response.status}") 142 | return False; 143 | 144 | logger.warn(f"deleted project {project_id} { project['name']} ") 145 | 146 | notifyProject(project) 147 | return True 148 | #end delete_project 149 | 150 | # a job is considered stale if the amount of time that has occurred since its last activity is greater than the threshold amount of hours set in the env 151 | def is_project_stale(project): 152 | shouldDelete = False 153 | 154 | logger.debug(f"is_project stale {project['path_with_namespace']}") 155 | 156 | doNotDeleteInDesc = project['description'] is not None and 'DO_NOT_DELETE' in project['description'] 157 | 158 | if doNotDeleteInDesc or 'DO_NOT_DELETE' in project['tag_list']: 159 | logger.info(f"Project {project['path_with_namespace']} is not eligible for deletion") 160 | return shouldDelete 161 | 162 | lastActivity = datetime.datetime.strptime(project['last_activity_at'], '%Y-%m-%dT%H:%M:%S.%fZ') 163 | passedTime = currentTime - lastActivity 164 | elapsed_hours = passedTime.total_seconds() / 3600 165 | logger.debug(f"Last Activity {lastActivity:%b %d %Y} : Total Hours = { int(elapsed_hours) } (threshold = {delete_after_hours}) - {project['path_with_namespace']}") 166 | 167 | if elapsed_hours > delete_after_hours: 168 | logger.info(f"Stale repository found. Last Activity {lastActivity:%b %d %Y} : Total Hours = { int(elapsed_hours) } (threshold = {delete_after_hours}) - {project['path_with_namespace']}") 169 | shouldDelete = True 170 | 171 | return shouldDelete 172 | # end is_project_stale 173 | 174 | def notifyProject(project): 175 | notify(project, None) 176 | 177 | def notifyGroup(group_id): 178 | notify(None, group_id) 179 | 180 | def notify(project, group_id): 181 | 182 | if not notification_url or not notification_token: 183 | logger.debug("Notifications not configured") 184 | return False 185 | 186 | if dry_run and notification_token != 'DRYRUN': 187 | logger.debug('Notification not sent during dry run. Set token to DRYRUN to enable dry run notifications'); 188 | return False 189 | 190 | try: 191 | resp = requests.post( 192 | notification_url, headers={"x-notification-token": notification_token, 'Content-type': 'application/json'}, 193 | json={"event_name": "project_deleted" if project is not None else "group_deleted", "project": project, "group_id": group_id} 194 | ) 195 | logger.info(f"Notification status_code {resp.status_code}"); 196 | except: 197 | logger.error(f"Notification error smothered {notification_url}") 198 | 199 | check_env_vars() 200 | 201 | if(dry_run): 202 | logger.info('In dry-run mode. No deletes will occur') 203 | 204 | delete_after_hours = int(delete_after_hours_string) 205 | logger.info("Delete projects after %i hours", delete_after_hours) 206 | 207 | clean_group(parent_group_id, "PARENT") 208 | 209 | logger.info("Gitlab clean up complete") 210 | -------------------------------------------------------------------------------- /images/prune-ocp-projects/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.access.redhat.com/ubi8/ubi 2 | 3 | LABEL io.k8s.description="OCP Project Pruner" \ 4 | io.k8s.display-name="OCP Project Pruner" 5 | 6 | ENV PATH=$PATH:/usr/local/bin 7 | 8 | ADD include/prune-ocp-projects.sh /usr/local/bin/ 9 | 10 | RUN curl https://mirror.openshift.com/pub/openshift-v4/clients/oc/4.4/linux/oc.tar.gz | tar -C /usr/local/bin/ -xzf - && \ 11 | chmod +x /usr/local/bin/prune-ocp-projects.sh 12 | 13 | CMD [ "/usr/local/bin/prune-ocp-projects.sh" ] 14 | -------------------------------------------------------------------------------- /images/prune-ocp-projects/README.md: -------------------------------------------------------------------------------- 1 | # Prune OCP projects 2 | 3 | Use this image to prune Openshift projects 4 | 5 | - Based on UBI 8 6 | - Uses oc client 4.4 7 | 8 | ## Build image 9 | 10 | ### Dockerfile 11 | ``` 12 | docker build -t prune-ocp-projects . 13 | ``` 14 | 15 | ### Buildah 16 | ``` 17 | ./buildah.sh 18 | ``` 19 | or 20 | ``` 21 | buildah build -t prune-ocp-projects . 22 | ``` 23 | -------------------------------------------------------------------------------- /images/prune-ocp-projects/buildah.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | 5 | # Create the container 6 | container=$(buildah from registry.access.redhat.com/ubi8/ubi) 7 | buildah config --label io.k8s.description="OCP Project Pruner" --label io.k8s.display-name="OCP Project Pruner" --env PATH='$PATH:/usr/local/bin' $container 8 | buildah add $container include/prune-ocp-projects.sh /usr/local/bin/ 9 | buildah run $container -- bash -c 'curl -L https://mirror.openshift.com/pub/openshift-v4/clients/oc/4.4/linux/oc.tar.gz | tar -C /usr/local/bin -xzf -' 10 | buildah config --cmd /usr/local/bin/prune-ocp-projects.sh $container 11 | 12 | buildah commit $container prune-ocp-projects:latest 13 | -------------------------------------------------------------------------------- /images/prune-ocp-projects/include/prune-ocp-projects.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Make sure to declare these two environment variables to prevent projects to be deleted 4 | # The values should be set as a quoted list of projects - i.e: 5 | # 'default openshift openshift-infra' 6 | #PROJECT_EXCLUDE_SYSTEM 7 | #PROJECT_EXCLUDE_USER 8 | 9 | # Also make sure to declare the TIMESTAMP_HOURS_AGO environment variable with the 10 | # number of hours "old" a project has to be for deletion - i.e.: '-2hours', '-24hours', etc 11 | #TIMESTAMP_HOURS_AGO='-12hours' 12 | 13 | # Alternatively, make sure the namespace (not the project) is annotated with 14 | # do-not-auto-prune: true 15 | # i.e.: 16 | # > oc annotate namespace do-not-auto-prune=true 17 | 18 | # Use an indexed array to keep track of existing projects 19 | declare -A projects 20 | 21 | for project in `oc get project -o=custom-columns=NAME:.metadata.name --no-headers`; 22 | do 23 | projects["${project}"]="found" 24 | done 25 | 26 | # Eliminate the "System projects" 27 | for project in "${!projects[@]}"; 28 | do 29 | if [[ "$project" == "openshift"* || "$project" == "kube"* || "$project" == "default" ]]; 30 | then 31 | unset projects["${project}"] 32 | fi 33 | done 34 | 35 | # Eliminate the "User-System projects" 36 | if [ -n "${PROJECT_EXCLUDE_SYSTEM}" ]; 37 | then 38 | for project in ${PROJECT_EXCLUDE_SYSTEM}; 39 | do 40 | unset projects["${project}"] 41 | done 42 | fi 43 | 44 | # Eliminate the "User projects" 45 | if [ -n "${PROJECT_EXCLUDE_USER}" ]; 46 | then 47 | for project in ${PROJECT_EXCLUDE_USER}; 48 | do 49 | unset projects["${project}"] 50 | done 51 | fi 52 | 53 | # Capture the timestamp for each project and only delete projects older 54 | # than the set number of hours 55 | # ... or, if the annotation 'do-not-auto-prune' is set to true, skip this project 56 | for project in "${!projects[@]}"; 57 | do 58 | doNotAutoPrune=`oc get project ${project} -o=custom-columns=prune:.metadata.annotations.do-not-auto-prune --no-headers` 59 | if [ "${doNotAutoPrune,,}" = "true" ]; 60 | then 61 | continue; 62 | fi 63 | 64 | purgetime=`date -d "${TIMESTAMP_HOURS_AGO}" +%s` 65 | temp=`oc get project ${project} -o=custom-columns=time:.metadata.creationTimestamp --no-headers` 66 | projects[${project}]=`date -d "${temp}" +%s` 67 | 68 | if [ ${purgetime} -gt ${projects[${project}]} ]; 69 | then 70 | echo "Deleting project ${project}" 71 | oc delete project ${project} 72 | fi 73 | done 74 | -------------------------------------------------------------------------------- /jobs/README.md: -------------------------------------------------------------------------------- 1 | # Jobs 2 | 3 | This directory contains a collection of [jobs](https://docs.openshift.com/container-platform/3.11/dev_guide/jobs.html) and [Cron jobs](https://docs.openshift.com/container-platform/3.11/dev_guide/cron_jobs.html). 4 | 5 | The rest of this document describes the specific configurations that are applicable to the execution of certain jobs contained within this directory. 6 | 7 | ## Git Backup 8 | 9 | The [cronjob-git-sync.yml](cronjob-git-sync.yml) backs up one repository to another repository with all of it's branches on a regular basis. 10 | 11 | Prior to instantiating the template, the following must be completed: 12 | 13 | 1. Two repositories created. 14 | 15 | 2. [SSH key created](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/) and put into base64 form for the `GIT_PRIVATE_KEY` param. Which can be done using: 16 | 17 | ```bash 18 | cat | base64 19 | ``` 20 | 21 | 3. The repository that will be pushed to, needs to have the public key added. 22 | 23 | 4. Instantiate the template 24 | 25 | ```bash 26 | oc process --param-file=params -f | oc create -f- 27 | ``` 28 | 29 | where the parameters file might look like this: 30 | 31 | ```text 32 | GIT_PRIVATE_KEY=GIANTENCODEDSTRINGHERE 33 | GIT_HOST=github.com 34 | GIT_REPO=pcarney8/example.git 35 | GIT_SYNC_HOST=gitlab.com 36 | GIT_SYNC_PORT=2222 37 | GIT_SYNC_REPO=pcarney8/example-backup.git 38 | SCHEDULE=*/5 * * * * 39 | JOB_NAME=example-backup-job 40 | ``` 41 | 42 | ## Pruning Resources 43 | 44 | The [cronjob-prune-images.yml](cronjob-prune-images.yml) facilitates [image pruning](https://docs.openshift.com/container-platform/3.11/admin_guide/pruning_resources.html#pruning-images) of the integrated docker registry while the [cronjob-prune-builds-deployments.yml](cronjob-prune-builds-deployments.yml) facilitates pruning [builds](https://docs.openshift.com/container-platform/3.11/admin_guide/pruning_resources.html#pruning-builds) and [deployments](https://docs.openshift.com/container-platform/3.11/admin_guide/pruning_resources.html#pruning-deployments) on a regular basis. 45 | 46 | To instantiate the template, run the following. 47 | 48 | 1. Create a project in which to host your jobs. 49 | 50 | ```bash 51 | oc new-project 52 | ``` 53 | 54 | 2. Instantiate the template 55 | 56 | ```bash 57 | oc process -f \ 58 | -p NAMESPACE="" 59 | -p JOB_SERVICE_ACCOUNT=pruner | oc create -f- 60 | ``` 61 | 62 | **Note:** *Some templates require additional parameters to be specified. Be sure to review each specific template contents prior to instantiation.* 63 | 64 | ## LDAP Group Synchronization 65 | 66 | The [cronjob-ldap-group-sync.yml](cronjob-ldap-group-sync.yml) and [cronjob-ldap-group-sync-secure.yml](cronjob-ldap-group-sync-secure.yml) templates facilitate routine [LDAP Group Synchronization](https://docs.openshift.com/container-platform/3.11/install_config/syncing_groups_with_ldap.html), synchronizing groups defined in an LDAP directory with OpenShift's internal group storage facility. 67 | 68 | These template makes several assumptions about your LDAP architecture and intentions of your group sync process, and is meant to showcase common use cases seen in the field. It will likely need further updating to accommodate other sync strategies or LDAP architectures. 69 | 70 | In this case, we use a top level group to designate all users and groups that will have access to OpenShift. We then create child groups to designate users who should have certain capabilities in OpenShift. A sample tree structure might look like: 71 | 72 | ```yaml 73 | openshift-users 74 | - cluster-admins 75 | * bob 76 | - app-team-a-devs 77 | * alice 78 | * suzie 79 | ``` 80 | 81 | We'll build a filter to return these groups in LDAP. Something like: 82 | 83 | ```text 84 | (&(objectclass=ipausergroup)(memberOf=cn=openshift-users,cn=groups,cn=accounts,dc=myorg,dc=example,dc=com)) 85 | ``` 86 | 87 | ### Cron Job Setup 88 | 89 | The `cronjob-ldap-group-sync.yml` template creates several objects in OpenShift. 90 | 91 | * A custom `ClusterRole` that defines the proper permissions to do a group sync 92 | * A `ServiceAccount` we will use to run the group sync 93 | * A `ClusterRoleBinding` that maps the `ServiceAccount` to the `ClusterRole` 94 | * A `ConfigMap` containing the `LDAPSyncConfig` [configuration file](https://docs.openshift.com/container-platform/latest/install_config/syncing_groups_with_ldap.html#configuring-ldap-sync) and optional whitelist configuration. 95 | * A `Secret` containing the LDAP bind password 96 | * A `CronJob` to run the LDAP Sync on a schedule 97 | 98 | To instantiate the template, run the following. 99 | 100 | 1. Create a project in which to host your jobs. 101 | 102 | ```bash 103 | oc new-project 104 | ``` 105 | 106 | 2. Instantiate the template 107 | 108 | ```bash 109 | oc process -f cronjob-ldap-group-sync.yml \ 110 | -p NAMESPACE="" 111 | -p LDAP_URL="ldap://idm-2.etl.rht-labs.com:389" \ 112 | -p LDAP_BIND_DN="uid=ldap-user,cn=users,cn=accounts,dc=myorg,dc=example,dc=com" \ 113 | -p LDAP_BIND_PASSWORD="password1" \ 114 | -p LDAP_GROUPS_SEARCH_BASE="cn=groups,cn=accounts,dc=myorg,dc=example,dc=com" \ 115 | -p LDAP_GROUPS_FILTER="(&(objectclass=ipausergroup)(memberOf=cn=ose_users,cn=groups,cn=accounts,dc=myorg,dc=example,dc=com))" \ 116 | -p LDAP_USERS_SEARCH_BASE="cn=users,cn=accounts,dc=myorg,dc=example,dc=com" \ 117 | | oc create -f- 118 | ``` 119 | 120 | ### Secure Cron Job Setup 121 | 122 | The `cronjob-ldap-group-sync-secure.yml` template uses TLS security and creates the additional object in OpenShift: 123 | 124 | * A `ConfigMap` containing the TLS certificate bundle for validating the LDAP server identity 125 | 126 | To instantiate the secure ldap group sync template, add the `LDAP_CA_CERT` parameter: 127 | 128 | ```bash 129 | oc process -f cronjob-ldap-group-sync-secure.yml \ 130 | -p NAMESPACE="" 131 | -p LDAP_URL="ldaps://idm-2.etl.rht-labs.com:636" \ 132 | -p LDAP_BIND_DN="uid=ldap-user,cn=users,cn=accounts,dc=myorg,dc=example,dc=com" \ 133 | -p LDAP_BIND_PASSWORD="password1" \ 134 | -p LDAP_CA_CERT="$(cat /path/to/ldap-ca.crt)" \ 135 | -p LDAP_GROUPS_SEARCH_BASE="cn=groups,cn=accounts,dc=myorg,dc=example,dc=com" \ 136 | -p LDAP_GROUPS_FILTER="(&(objectclass=ipausergroup)(memberOf=cn=ose_users,cn=groups,cn=accounts,dc=myorg,dc=example,dc=com))" \ 137 | -p LDAP_USERS_SEARCH_BASE="cn=users,cn=accounts,dc=myorg,dc=example,dc=com" \ 138 | | oc create -f- 139 | ``` 140 | 141 | ### Cleanup 142 | 143 | You can clean up the objects created by the template with the following command. 144 | 145 | ```bash 146 | oc delete cronjob,configmap,clusterrole,clusterrolebinding,sa,secret -l template=cronjob-ldap-group-sync 147 | ``` 148 | 149 | ## AWS EBS backed PVs snapshots 150 | 151 | The [cronjob-aws-ocp-snap.yaml](cronjob-aws-ocp-snap.yaml) facilitates [aws snapshots](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-creating-snapshot.html) for the Persistent Volumes created on OCP which use EBS as the backend storage. 152 | 153 | ### Setup 154 | 155 | The `cronjob-aws-ocp-snap.yaml` template creates several objects in OpenShift. 156 | 157 | * A custom `BuildConfig` that will create the required container to run the job from 158 | * A custom `ClusterRole` that defines the proper permissions to query PVCs in the Cluster 159 | * A `ServiceAccount` we will use with 'aws cli' to perform the snapshots 160 | * A `ClusterRoleBinding` that maps the `ServiceAccount` to the `ClusterRole` 161 | * A `CronJob` to run the snapshots on a schedule 162 | * A `Secret` to store the 'aws cli' required credentials and config to connect to your AWS account 163 | 164 | To instantiate the template, run the following. 165 | 166 | 1. Create a project in which to host your jobs. 167 | 168 | ```bash 169 | oc new-project 170 | ``` 171 | 172 | 2. Instantiate the template 173 | 174 | ```bash 175 | oc process -f cronjob-aws-ocp-snap.yaml \ 176 | -p NAMESPACE="" \ 177 | -p AWS_ACCESS_KEY_ID="AWS Access Key ID" \ 178 | -p AWS_SECRET_ACCESS_KEY="WS Secret Access Key ID" \ 179 | -p AWS_REGION="AWS Region where EBS objects reside" \ 180 | -p NSPACE="Namespace where Persistent Volumes are defined (can be ALL)" \ 181 | -p VOL="Persistent Volume Claim name (can be ALL)" \ 182 | | oc create -f- 183 | ``` 184 | -------------------------------------------------------------------------------- /jobs/cluster-descheduler.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | metadata: 4 | name: cluster-descheduler 5 | annotations: 6 | description: "Descheduler to remove pods violating usage thresholds, affinity violations and dupliacate pod placements" 7 | iconClass: icon-shadowman 8 | tags: management,descheduler 9 | objects: 10 | - kind: ClusterRole 11 | apiVersion: rbac.authorization.k8s.io/v1beta1 12 | metadata: 13 | name: descheduler-role 14 | labels: 15 | template: cluster-scheduler 16 | rules: 17 | - apiGroups: [""] 18 | resources: ["nodes"] 19 | verbs: ["get", "watch", "list"] 20 | - apiGroups: [""] 21 | resources: ["pods"] 22 | verbs: ["get", "watch", "list", "delete"] 23 | - apiGroups: [""] 24 | resources: ["pods/eviction"] 25 | verbs: ["create"] 26 | - kind: ServiceAccount 27 | apiVersion: v1 28 | metadata: 29 | name: descheduler-sa 30 | namespace: "${NAMESPACE}" 31 | labels: 32 | template: cluster-descheduler 33 | - kind: ClusterRoleBinding 34 | apiVersion: rbac.authorization.k8s.io/v1beta1 35 | metadata: 36 | name: descheduler-binding 37 | labels: 38 | template: cluster-descheduler 39 | roleRef: 40 | apiGroup: rbac.authorization.k8s.io 41 | kind: ClusterRole 42 | name: descheduler-role 43 | subjects: 44 | - kind: ServiceAccount 45 | name: descheduler-sa 46 | namespace: "${NAMESPACE}" 47 | - kind: ConfigMap 48 | apiVersion: v1 49 | data: 50 | policy.yaml: | 51 | apiVersion: descheduler/v1alpha1 52 | kind: DeschedulerPolicy 53 | strategies: 54 | RemoveDuplicates: 55 | enabled: ${REMOVE_DUPS} 56 | LowNodeUtilization: 57 | enabled: ${ENABLE_UTILIZATION} 58 | params: 59 | nodeResourceUtilizationThresholds: 60 | thresholds: 61 | cpu: ${MIN_CPU} 62 | memory: ${MIN_MEM} 63 | pods: ${MIN_PODS} 64 | targetThresholds: 65 | cpu: ${MAX_CPU} 66 | memory: ${MAX_MEM} 67 | pods: ${MAX_PODS} 68 | numberOfNodes: ${NODE_THRESHOLD} 69 | RemovePodsViolatingInterPodAntiAffinity: 70 | enabled: ${ENABLE_AFFINITY_VIOLATION} 71 | metadata: 72 | name: descheduler-policy-configmap 73 | namespace: "${NAMESPACE}" 74 | labels: 75 | template: cluster-descheduler 76 | - kind: CronJob 77 | apiVersion: batch/v1beta1 78 | metadata: 79 | name: descheduler-job 80 | namespace: "${NAMESPACE}" 81 | labels: 82 | template: cluster-descheduler 83 | spec: 84 | schedule: "${SCHEDULE}" 85 | concurrencyPolicy: "Forbid" 86 | successfulJobsHistoryLimit: "1" 87 | failedJobsHistoryLimit: "1" 88 | jobTemplate: 89 | spec: 90 | completions: 1 91 | parallelism: 1 92 | template: 93 | metadata: 94 | name: descheduler-pod 95 | annotations: 96 | scheduler.alpha.kubernetes.io/critical-pod: "true" 97 | spec: 98 | containers: 99 | - name: descheduler 100 | image: "${IMAGE}:${IMAGE_TAG}" 101 | volumeMounts: 102 | - mountPath: /policy-dir 103 | name: policy-volume 104 | command: 105 | - "/bin/sh" 106 | - "-ec" 107 | - | 108 | /bin/descheduler --policy-config-file /policy-dir/policy.yaml 109 | restartPolicy: Never 110 | serviceAccountName: descheduler-sa 111 | volumes: 112 | - name: policy-volume 113 | configMap: 114 | name: descheduler-policy-configmap 115 | startingDeadlineSeconds: ${{STARTING_DEADLINE_SECONDS}} 116 | parameters: 117 | - name: "SCHEDULE" 118 | displayName: "Cron Schedule" 119 | description: "Cron Schedule to Execute the Job" 120 | value: "@hourly" 121 | - name: NAMESPACE 122 | displayName: Namespace 123 | description: namespace to deploy descheduler 124 | value: "kube-system" 125 | - name: MIN_CPU 126 | displayName: 127 | description: 128 | value: "0" 129 | - name: MIN_MEM 130 | displayName: 131 | description: 132 | value: "0" 133 | - name: MAX_CPU 134 | displayName: 135 | description: 136 | value: "0" 137 | - name: MAX_MEM 138 | displayName: 139 | description: 140 | value: "0" 141 | - name: MIN_PODS 142 | displayName: 143 | description: 144 | value: "0" 145 | - name: MAX_PODS 146 | displayName: 147 | description: 148 | value: "0" 149 | - name: ENABLE_AFFINITY_VIOLATION 150 | displayName: 151 | description: enable descheduling of pods that are violating pod affinities 152 | value: "False" 153 | - name: ENABLE_UTILIZATION 154 | displayName: 155 | description: enable descheduling of pods that are violating utilization specs 156 | value: "False" 157 | - name: REMOVE_DUPS 158 | displayName: 159 | description: enable descheduling of application pods that are scheduled on the same node 160 | value: "False" 161 | - name: NODE_THRESHOLD 162 | displayName: 163 | description: 164 | value: "0" 165 | - name: "IMAGE" 166 | displayName: "Image" 167 | description: "Image to use for the container." 168 | required: true 169 | value: "registry.access.redhat.com/openshift3/ose-descheduler" 170 | - name: "IMAGE_TAG" 171 | displayName: "Image Tag" 172 | description: "Image Tag to use for the container." 173 | required: true 174 | value: "v3.11" 175 | - name: STARTING_DEADLINE_SECONDS 176 | description: Set the startingDeadlineSeconds for the cronjob 177 | required: false 178 | value: "60" 179 | -------------------------------------------------------------------------------- /jobs/cronjob-aws-ocp-snap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | metadata: 4 | name: aws-ocp-snap 5 | objects: 6 | - apiVersion: v1 7 | kind: ImageStream 8 | metadata: 9 | annotations: 10 | description: Keeps track of changes in the application image 11 | name: ${NAME} 12 | labels: 13 | template: aws-ocp-snap 14 | - apiVersion: v1 15 | kind: BuildConfig 16 | metadata: 17 | annotations: 18 | description: Defines how to build the application 19 | name: ${NAME} 20 | labels: 21 | template: aws-ocp-snap 22 | spec: 23 | completionDeadlineSeconds: "1800" 24 | output: 25 | to: 26 | kind: ImageStreamTag 27 | name: ${NAME}:latest 28 | runPolicy: Serial 29 | source: 30 | git: 31 | uri: https://github.com/redhat-cop/openshift-management.git 32 | contextDir: /images/aws-ocp-snap 33 | strategy: 34 | dockerStrategy: 35 | from: 36 | kind: DockerImage 37 | name: centos:7 38 | type: Docker 39 | triggers: 40 | - type: ConfigChange 41 | - apiVersion: v1 42 | kind: Secret 43 | metadata: 44 | name: aws-secret 45 | labels: 46 | template: aws-ocp-snap 47 | stringData: 48 | key_id: ${AWS_ACCESS_KEY_ID} 49 | access_key: ${AWS_SECRET_ACCESS_KEY} 50 | region: ${AWS_REGION} 51 | - apiVersion: batch/v2alpha1 52 | kind: CronJob 53 | metadata: 54 | name: "${JOB_NAME}" 55 | labels: 56 | template: aws-ocp-snap 57 | spec: 58 | schedule: "${SCHEDULE}" 59 | concurrencyPolicy: Forbid 60 | successfulJobsHistoryLimit: "${SUCCESS_JOBS_HISTORY_LIMIT}" 61 | failedJobsHistoryLimit: "${FAILED_JOBS_HISTORY_LIMIT}" 62 | jobTemplate: 63 | spec: 64 | template: 65 | spec: 66 | containers: 67 | - name: "${JOB_NAME}" 68 | image: docker-registry.default.svc:5000/${NAMESPACE}/${NAME}:latest 69 | command: 70 | - "/bin/bash" 71 | - "-c" 72 | - "/usr/local/bin/create_snapshot.sh ${NSPACE} ${VOL}" 73 | env: 74 | - name: AWS_ACCESS_KEY_ID 75 | valueFrom: 76 | secretKeyRef: 77 | name: aws-secret 78 | key: key_id 79 | - name: AWS_SECRET_ACCESS_KEY 80 | valueFrom: 81 | secretKeyRef: 82 | name: aws-secret 83 | key: access_key 84 | - name: AWS_DEFAULT_REGION 85 | valueFrom: 86 | secretKeyRef: 87 | name: aws-secret 88 | key: region 89 | restartPolicy: Never 90 | terminationGracePeriodSeconds: 30 91 | activeDeadlineSeconds: 500 92 | dnsPolicy: ClusterFirst 93 | serviceAccountName: "${JOB_SERVICE_ACCOUNT}" 94 | serviceAccount: "${JOB_SERVICE_ACCOUNT}" 95 | startingDeadlineSeconds: ${{STARTING_DEADLINE_SECONDS}} 96 | - apiVersion: v1 97 | kind: ClusterRole 98 | metadata: 99 | name: pvc-reader 100 | labels: 101 | template: aws-ocp-snap 102 | rules: 103 | - apiGroups: 104 | - "" 105 | resources: 106 | - persistentvolumes 107 | verbs: 108 | - get 109 | - list 110 | - watch 111 | - apiGroups: 112 | - storage.k8s.io 113 | resources: 114 | - storageclasses 115 | verbs: 116 | - get 117 | - list 118 | - watch 119 | - apiGroups: 120 | - "" 121 | resources: 122 | - events 123 | - persistentvolumeclaims 124 | verbs: 125 | - get 126 | - list 127 | - watch 128 | - apiVersion: v1 129 | kind: ClusterRoleBinding 130 | metadata: 131 | name: system:pvc-reader 132 | labels: 133 | template: aws-ocp-snap 134 | roleRef: 135 | name: pvc-reader 136 | subjects: 137 | - kind: ServiceAccount 138 | name: ${JOB_SERVICE_ACCOUNT} 139 | userNames: 140 | - system:serviceaccount:${NAMESPACE}:${JOB_SERVICE_ACCOUNT} 141 | - apiVersion: v1 142 | kind: ServiceAccount 143 | metadata: 144 | name: ${JOB_SERVICE_ACCOUNT} 145 | labels: 146 | template: aws-ocp-snap 147 | parameters: 148 | - description: The name assigned to all of the frontend objects defined in this template. 149 | displayName: Name 150 | name: NAME 151 | required: true 152 | value: aws-ocp-snap 153 | - name: JOB_NAME 154 | displayName: Job Name 155 | description: Name of the Scheduled Job to Create. 156 | value: cronjob-ebs-snaphost 157 | required: true 158 | - name: SCHEDULE 159 | displayName: Cron Schedule 160 | description: Cron Schedule to Execute the Job 161 | value: "@daily" 162 | required: true 163 | - name: SUCCESS_JOBS_HISTORY_LIMIT 164 | displayName: Successful Job History Limit 165 | description: The number of successful jobs that will be retained 166 | value: '5' 167 | required: true 168 | - name: FAILED_JOBS_HISTORY_LIMIT 169 | displayName: Failed Job History Limit 170 | description: The number of failed jobs that will be retained 171 | value: '5' 172 | required: true 173 | - name: NAMESPACE 174 | displayName: "Namespace where this is deployed" 175 | description: "Namespace where this is deployed." 176 | value: "cluster-maintenance" 177 | required: true 178 | - name: AWS_ACCESS_KEY_ID 179 | displayName: AWS Access Key ID 180 | description: AWS Access Key ID to be used to create the snapshots 181 | value: "" 182 | required: true 183 | - name: AWS_SECRET_ACCESS_KEY 184 | displayName: AWS Secret Access Key ID 185 | description: AWS Secret Access Key ID to be used to create the snapshots 186 | value: "" 187 | required: true 188 | - name: AWS_REGION 189 | displayName: AWS Region 190 | description: AWS Region where EBS objects reside 191 | value: "" 192 | required: true 193 | - name: NSPACE 194 | displayName: Namespace where Persistent Volumes are defined 195 | description: Namespace where Persistent Volumes are defined (can be ALL) 196 | value: "" 197 | required: true 198 | - name: VOL 199 | displayName: Persistent Volume Claim name 200 | description: Persistent Volume Claim name (can be ALL) 201 | value: "" 202 | required: true 203 | - name: JOB_SERVICE_ACCOUNT 204 | displayName: "Service Account Name" 205 | description: "Name of the Service Account To Exeucte the Job As." 206 | value: "ebs-snap-creator" 207 | required: true 208 | - name: STARTING_DEADLINE_SECONDS 209 | description: Set the startingDeadlineSeconds for the cronjob 210 | required: false 211 | value: "60" 212 | -------------------------------------------------------------------------------- /jobs/cronjob-git-sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: "Template" 3 | apiVersion: "v1" 4 | metadata: 5 | name: "cronjob-git-sync" 6 | annotations: 7 | description: "Scheduled Task to Perform Git Repo Synchronization" 8 | iconClass: "icon-shadowman" 9 | tags: "management,cronjob,git,sync" 10 | objects: 11 | - kind: Secret 12 | apiVersion: "v1" 13 | metadata: 14 | name: "${SSH_KEY_SECRET_NAME}" 15 | type: Opaque 16 | data: 17 | ssh-privatekey: ${GIT_PRIVATE_KEY} 18 | - kind: "CronJob" 19 | apiVersion: "batch/v1beta1" 20 | metadata: 21 | name: "${JOB_NAME}" 22 | labels: 23 | template: "cronjob-git-sync" 24 | spec: 25 | schedule: "${SCHEDULE}" 26 | concurrencyPolicy: "Forbid" 27 | successfulJobsHistoryLimit: "${{SUCCESS_JOBS_HISTORY_LIMIT}}" 28 | failedJobsHistoryLimit: "${{FAILED_JOBS_HISTORY_LIMIT}}" 29 | jobTemplate: 30 | spec: 31 | template: 32 | spec: 33 | volumes: 34 | - name: secret-volume 35 | secret: 36 | secretName: "${SSH_KEY_SECRET_NAME}" 37 | containers: 38 | - name: "${JOB_NAME}" 39 | image: "${IMAGE}:${IMAGE_TAG}" 40 | env: 41 | - name: GIT_COMMITTER_NAME 42 | value: hello 43 | - name: GIT_COMMITTER_EMAIL 44 | value: hello@world.com 45 | command: 46 | - "/bin/bash" 47 | - "-c" 48 | - | 49 | mkdir ~/.ssh 50 | chmod 700 ~/.ssh 51 | printf 'host ${GIT_HOST}\n PreferredAuthentications publickey\n IdentitiesOnly yes\n HostName ${GIT_HOST}\n IdentityFile /etc/secret-volume/ssh-privatekey\n User git\n' >> ~/.ssh/config 52 | printf 'host ${GIT_SYNC_HOST}\n PreferredAuthentications publickey\n IdentitiesOnly yes\n HostName ${GIT_SYNC_HOST}\n IdentityFile /etc/secret-volume/ssh-privatekey\n User git\n' >> ~/.ssh/config 53 | chmod 400 ~/.ssh/config 54 | ssh-keyscan -p ${GIT_SYNC_PORT} -H ${GIT_SYNC_HOST} >> ~/.ssh/known_hosts 55 | ssh-keyscan -p ${GIT_PORT} -H ${GIT_HOST} >> ~/.ssh/known_hosts 56 | USER_ID=$(id -u) 57 | GROUP_ID=$(id -g) 58 | echo "gitsync:x:${USER_ID}:${GROUP_ID}:Git Sync User:${HOME}:/sbin/nologin" > ~/passwd 59 | echo "root:x:${GROUP_ID}:" > ~/group 60 | LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=~/passwd NSS_WRAPPER_GROUP=~/group git clone ssh://git@${GIT_HOST}:${GIT_PORT}/${GIT_REPO} /tmp/temp 61 | cd /tmp/temp 62 | for branch in $(git branch -a | grep remotes | grep -v HEAD | grep -v master); do git branch --track ${branch#remotes/origin/} $branch; done 63 | LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=~/passwd NSS_WRAPPER_GROUP=~/group git remote add backup ssh://git@${GIT_SYNC_HOST}:${GIT_SYNC_PORT}/${GIT_SYNC_REPO} 64 | LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=~/passwd NSS_WRAPPER_GROUP=~/group git push -f --all backup 65 | volumeMounts: 66 | - name: secret-volume 67 | readOnly: true 68 | mountPath: "/etc/secret-volume" 69 | restartPolicy: "Never" 70 | terminationGracePeriodSeconds: 30 71 | activeDeadlineSeconds: 500 72 | dnsPolicy: "ClusterFirst" 73 | startingDeadlineSeconds: ${{STARTING_DEADLINE_SECONDS}} 74 | parameters: 75 | - name: "JOB_NAME" 76 | displayName: "Job Name" 77 | description: "Name of the Scheduled Job to Create." 78 | value: "cronjob-git-sync" 79 | required: true 80 | - name: "SCHEDULE" 81 | displayName: "Cron Schedule" 82 | description: "Cron Schedule to Execute the Job" 83 | value: "@hourly" 84 | required: true 85 | - name: "SUCCESS_JOBS_HISTORY_LIMIT" 86 | displayName: "Successful Job History Limit" 87 | description: "The number of successful jobs that will be retained" 88 | value: "5" 89 | required: true 90 | - name: "FAILED_JOBS_HISTORY_LIMIT" 91 | displayName: "Failed Job History Limit" 92 | description: "The number of failed jobs that will be retained" 93 | value: "5" 94 | required: true 95 | - name: "GIT_HOST" 96 | displayName: "Git server host name" 97 | description: "Git server host name" 98 | required: true 99 | - name: "GIT_PORT" 100 | displayName: "Port of the main git server" 101 | description: "Port of the main git server, NEED TO MAKE SURE THIS MATCHES THE PROTOCOL" 102 | required: true 103 | value: "22" 104 | - name: "GIT_REPO" 105 | displayName: "Git server repo path" 106 | description: "Git server repo path, i.e. userName/repo-name.git" 107 | required: true 108 | - name: "GIT_SYNC_HOST" 109 | displayName: "Git backup server host name of the server to be synced to" 110 | description: "Git backup server host name of the server to be synced to, used to add to known hosts" 111 | required: true 112 | - name: "GIT_SYNC_PORT" 113 | displayName: "Port of the server to be synced to" 114 | description: "Port of the server to be synced to, used to add to known hosts" 115 | required: true 116 | value: "22" 117 | - name: "GIT_SYNC_REPO" 118 | displayName: "Git backup server repo path" 119 | description: "Git backup server repo path, i.e. userName/repo-name.git" 120 | required: true 121 | - name: "GIT_PRIVATE_KEY" 122 | displayName: "SSH private key for the Git server to be synced to" 123 | description: "SSH private key for the Git server to be synced to, NOTE: no passphrase! and make sure it is encoded! You can do this by manually adding via the UI and then go to the secret and click 'Edit YAML', this will show the encoded secret under 'data: ssh-privatekey:' you don't need to include the '>-'" 124 | required: true 125 | - name: "SSH_KEY_SECRET_NAME" 126 | displayName: "Name of the ssh key secret" 127 | description: "Name of the ssh key secret" 128 | required: true 129 | value: "ssh-key-secret" 130 | - name: "IMAGE" 131 | displayName: "Image" 132 | description: "Image to use for the container." 133 | required: true 134 | value: "registry.access.redhat.com/openshift3/python-33-rhel7" 135 | - name: "IMAGE_TAG" 136 | displayName: "Image Tag" 137 | description: "Image Tag to use for the container." 138 | required: true 139 | value: "latest" 140 | - name: STARTING_DEADLINE_SECONDS 141 | description: Set the startingDeadlineSeconds for the cronjob 142 | required: false 143 | value: "60" 144 | labels: 145 | template: "cronjob-git-sync" 146 | -------------------------------------------------------------------------------- /jobs/cronjob-ldap-group-sync-secure.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: "Template" 3 | apiVersion: "v1" 4 | metadata: 5 | name: "cronjob-ldap-group-sync-secure" 6 | annotations: 7 | description: "Scheduled Task to Perform LDAP Group Synchronization" 8 | iconClass: "icon-shadowman" 9 | tags: "management,cronjob,ldap,group,sync" 10 | labels: 11 | template: "cronjob-ldap-group-sync-secure" 12 | 13 | parameters: 14 | - name: "NAMESPACE" 15 | displayName: "Namespace" 16 | description: "Name of the Namespace where to deploy the Scheduled Job" 17 | value: "openshift-cluster-ops" 18 | required: true 19 | - name: "JOB_NAME" 20 | displayName: "Job Name" 21 | description: "Name of the Scheduled Job to Create." 22 | value: "cronjob-ldap-group-sync" 23 | required: true 24 | - name: "SCHEDULE" 25 | displayName: "Cron Schedule" 26 | description: "Cron Schedule to Execute the Job" 27 | value: "@hourly" 28 | required: true 29 | - name: "JOB_SERVICE_ACCOUNT" 30 | displayName: "Service Account Name" 31 | description: "Name of the Service Account To Exeucte the Job As." 32 | value: "ldap-group-syncer" 33 | required: true 34 | - name: "SUCCESS_JOBS_HISTORY_LIMIT" 35 | displayName: "Successful Job History Limit" 36 | description: "The number of successful jobs that will be retained" 37 | value: "5" 38 | required: true 39 | - name: "FAILED_JOBS_HISTORY_LIMIT" 40 | displayName: "Failed Job History Limit" 41 | description: "The number of failed jobs that will be retained" 42 | value: "5" 43 | required: true 44 | - name: "LDAP_URL" 45 | displayName: "LDAP Server URL" 46 | description: "URL of you LDAP server" 47 | required: true 48 | - name: "LDAP_BIND_DN" 49 | displayName: "LDAP Bind User's DN" 50 | description: "The Full DN for the user you wish to use to authenticate to LDAP" 51 | required: true 52 | - name: "LDAP_BIND_PASSWORD" 53 | displayName: "LDAP Bind User's password" 54 | description: "Password for the LDAP_BIND_DN user" 55 | required: true 56 | - name: "LDAP_BIND_PASSWORD_SECRET" 57 | displayName: "LDAP Bind Password Secret" 58 | description: "The name for the secret in which to store the bind password" 59 | value: "ldap-bind-password" 60 | required: true 61 | - name: "LDAP_CA_CERT" 62 | displayName: "LDAP CA Certificate" 63 | description: "The LDAP TLS Certificate Authority Certificate Bundle" 64 | required: true 65 | - name: "LDAP_GROUPS_SEARCH_BASE" 66 | displayName: "Group search query" 67 | description: "Location in LDAP tree where you will find groups" 68 | required: true 69 | value: "cn=groups,cn=accounts,dc=myorg,dc=example,dc=com" 70 | - name: "LDAP_GROUPS_FILTER" 71 | displayName: "Group Filter" 72 | description: "LDAP Filter to use when deciding which groups to sync into OpenShift" 73 | required: true 74 | value: "(&(objectclass=ipausergroup)(memberOf=cn=openshift-users,cn=groups,cn=accounts,dc=myorg,dc=example,dc=com))" 75 | - name: "LDAP_GROUP_NAME_ATTRIBUTES" 76 | displayName: "Group name attributes" 77 | description: "The attribute list to use to discover the name for the group." 78 | required: true 79 | value: >- 80 | ["cn"] 81 | - name: "LDAP_GROUP_MEMBERSHIP_ATTRIBUTES" 82 | displayName: "Group membership attributes" 83 | required: true 84 | value: >- 85 | ["member"] 86 | - name: "LDAP_GROUP_UID_ATTRIBUTE" 87 | displayName: "Group UID Attribute" 88 | description: "The attribute that uniquely identifies a group on the LDAP server." 89 | required: true 90 | value: "ipaUniqueID" 91 | - name: "LDAP_GROUPS_WHITELIST" 92 | displayName: "LDAP sync whitelist" 93 | description: "File content for groups sync --whitelist option" 94 | value: "" 95 | - name: "LDAP_SYNC_CONFIGMAP" 96 | displayName: "LDAP sync config map" 97 | description: "Name for the config map storing the group sync config" 98 | value: "ldap-group-sync" 99 | - name: "LDAP_SYNC_CA_CONFIGMAP" 100 | displayName: "LDAP sync certificate authority config map" 101 | description: "Name for the config map storing the TLS certificate authority" 102 | value: "ldap-group-sync-ca" 103 | - name: "LDAP_USER_NAME_ATTRIBUTES" 104 | displayName: "User name attributes" 105 | description: "JSON list of attributes to use to discover the user name for group membership" 106 | required: true 107 | value: >- 108 | ["uid"] 109 | - name: "LDAP_USER_UID_ATTRIBUTE" 110 | displayName: "User UID attribute" 111 | description: "The attribute that uniquely identifies a user on the LDAP server." 112 | required: true 113 | value: "dn" 114 | - name: "LDAP_USERS_SEARCH_BASE" 115 | displayName: "User search query" 116 | description: "Location in LDAP tree where you will find users" 117 | required: true 118 | value: "cn=users,cn=accounts,dc=myorg,dc=example,dc=com" 119 | - name: "IMAGE" 120 | displayName: "Image" 121 | description: "Image to use for the container." 122 | required: true 123 | value: "registry.access.redhat.com/openshift3/ose-cli" 124 | - name: "IMAGE_TAG" 125 | displayName: "Image Tag" 126 | description: "Image Tag to use for the container." 127 | required: true 128 | value: "v3.11" 129 | - name: STARTING_DEADLINE_SECONDS 130 | description: Set the startingDeadlineSeconds for the cronjob 131 | required: false 132 | value: "60" 133 | 134 | objects: 135 | - kind: "ConfigMap" 136 | apiVersion: "v1" 137 | metadata: 138 | name: "${LDAP_SYNC_CONFIGMAP}" 139 | namespace: "${NAMESPACE}" 140 | labels: 141 | template: "cronjob-ldap-group-sync" 142 | data: 143 | ldap-group-sync.yaml: | 144 | kind: "LDAPSyncConfig" 145 | apiVersion: "v1" 146 | url: "${LDAP_URL}" 147 | insecure: false 148 | bindDN: "${LDAP_BIND_DN}" 149 | bindPassword: 150 | file: "/ldap-sync/secrets/bind_password" 151 | ca: "/ldap-sync/ca/ldap-ca.crt" 152 | rfc2307: 153 | groupsQuery: 154 | baseDN: "${LDAP_GROUPS_SEARCH_BASE}" 155 | scope: "sub" 156 | derefAliases: "never" 157 | filter: "${LDAP_GROUPS_FILTER}" 158 | pageSize: 0 159 | groupUIDAttribute: "${LDAP_GROUP_UID_ATTRIBUTE}" 160 | groupNameAttributes: ${LDAP_GROUP_NAME_ATTRIBUTES} 161 | groupMembershipAttributes: ${LDAP_GROUP_MEMBERSHIP_ATTRIBUTES} 162 | usersQuery: 163 | baseDN: "${LDAP_USERS_SEARCH_BASE}" 164 | scope: "sub" 165 | derefAliases: "never" 166 | pageSize: 0 167 | userNameAttributes: ${LDAP_USER_NAME_ATTRIBUTES} 168 | userUIDAttribute: "${LDAP_USER_UID_ATTRIBUTE}" 169 | tolerateMemberNotFoundErrors: true 170 | tolerateMemberOutOfScopeErrors: true 171 | whitelist.txt: "${LDAP_GROUPS_WHITELIST}" 172 | 173 | - kind: "ConfigMap" 174 | apiVersion: "v1" 175 | metadata: 176 | name: "${LDAP_SYNC_CA_CONFIGMAP}" 177 | namespace: "${NAMESPACE}" 178 | labels: 179 | template: "cronjob-ldap-group-sync" 180 | data: 181 | ldap-ca.crt: "${LDAP_CA_CERT}" 182 | 183 | - kind: "Secret" 184 | apiVersion: "v1" 185 | metadata: 186 | name: "${LDAP_BIND_PASSWORD_SECRET}" 187 | namespace: "${NAMESPACE}" 188 | labels: 189 | template: "cronjob-ldap-group-sync" 190 | type: "Opaque" 191 | stringData: 192 | bind_password: "${LDAP_BIND_PASSWORD}" 193 | 194 | - kind: "CronJob" 195 | apiVersion: "batch/v1beta1" 196 | metadata: 197 | name: "${JOB_NAME}" 198 | namespace: "${NAMESPACE}" 199 | labels: 200 | template: "cronjob-ldap-group-sync" 201 | spec: 202 | schedule: "${SCHEDULE}" 203 | concurrencyPolicy: "Forbid" 204 | successfulJobsHistoryLimit: "${{SUCCESS_JOBS_HISTORY_LIMIT}}" 205 | failedJobsHistoryLimit: "${{FAILED_JOBS_HISTORY_LIMIT}}" 206 | jobTemplate: 207 | spec: 208 | backoffLimit: 0 209 | template: 210 | spec: 211 | containers: 212 | - name: "${JOB_NAME}" 213 | image: "${IMAGE}:${IMAGE_TAG}" 214 | command: 215 | - "/bin/bash" 216 | - "-c" 217 | - oc adm groups sync --confirm 218 | --sync-config=/ldap-sync/config/ldap-group-sync.yaml 219 | $([ -s /ldap-sync/config/whitelist.txt ] && echo --whitelist=/ldap-sync/config/whitelist.txt) 220 | volumeMounts: 221 | - mountPath: "/ldap-sync/config" 222 | name: "ldap-sync-config" 223 | - mountPath: "/ldap-sync/ca" 224 | name: "ldap-sync-ca" 225 | - mountPath: "/ldap-sync/secrets" 226 | name: "ldap-bind-password" 227 | volumes: 228 | - name: "ldap-sync-config" 229 | configMap: 230 | name: "${LDAP_SYNC_CONFIGMAP}" 231 | - name: "ldap-sync-ca" 232 | configMap: 233 | name: "${LDAP_SYNC_CA_CONFIGMAP}" 234 | - name: "ldap-bind-password" 235 | secret: 236 | secretName: "${LDAP_BIND_PASSWORD_SECRET}" 237 | restartPolicy: "Never" 238 | terminationGracePeriodSeconds: 30 239 | activeDeadlineSeconds: 500 240 | dnsPolicy: "ClusterFirst" 241 | serviceAccountName: "${JOB_SERVICE_ACCOUNT}" 242 | serviceAccount: "${JOB_SERVICE_ACCOUNT}" 243 | startingDeadlineSeconds: ${{STARTING_DEADLINE_SECONDS}} 244 | 245 | - kind: "ClusterRole" 246 | apiVersion: "v1" 247 | metadata: 248 | name: "ldap-group-syncer" 249 | namespace: "${NAMESPACE}" 250 | labels: 251 | template: "cronjob-ldap-group-sync" 252 | rules: 253 | - apiGroups: 254 | - "" 255 | - "user.openshift.io" 256 | resources: 257 | - "groups" 258 | verbs: 259 | - "get" 260 | - "list" 261 | - "create" 262 | - "update" 263 | 264 | - kind: "ClusterRoleBinding" 265 | apiVersion: "v1" 266 | groupNames: null 267 | metadata: 268 | name: "system:ldap-group-syncers" 269 | roleRef: 270 | name: "ldap-group-syncer" 271 | subjects: 272 | - kind: "ServiceAccount" 273 | name: "${JOB_SERVICE_ACCOUNT}" 274 | userNames: 275 | - "system:serviceaccount:${NAMESPACE}:${JOB_SERVICE_ACCOUNT}" 276 | 277 | - kind: "ServiceAccount" 278 | apiVersion: "v1" 279 | metadata: 280 | name: "${JOB_SERVICE_ACCOUNT}" 281 | namespace: "${NAMESPACE}" 282 | labels: 283 | template: "cronjob-ldap-group-sync" 284 | -------------------------------------------------------------------------------- /jobs/cronjob-ldap-group-sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: "Template" 3 | apiVersion: "v1" 4 | metadata: 5 | name: "cronjob-ldap-group-sync" 6 | annotations: 7 | description: "Scheduled Task to Perform LDAP Group Synchronization" 8 | iconClass: "icon-shadowman" 9 | tags: "management,cronjob,ldap,group,sync" 10 | labels: 11 | template: "cronjob-ldap-group-sync" 12 | 13 | objects: 14 | - kind: "ConfigMap" 15 | apiVersion: "v1" 16 | metadata: 17 | name: "${LDAP_CONFIG}" 18 | namespace: "${NAMESPACE}" 19 | labels: 20 | template: "cronjob-ldap-group-sync" 21 | data: 22 | ldap-group-sync.yaml: | 23 | kind: "LDAPSyncConfig" 24 | apiVersion: "v1" 25 | url: "${LDAP_URL}" 26 | insecure: true 27 | bindDN: "${LDAP_BIND_DN}" 28 | bindPassword: 29 | file: "/etc/secrets/bind_password" 30 | rfc2307: 31 | groupsQuery: 32 | baseDN: "${LDAP_GROUPS_SEARCH_BASE}" 33 | scope: "sub" 34 | derefAliases: "never" 35 | filter: "${LDAP_GROUPS_FILTER}" 36 | pageSize: 0 37 | groupUIDAttribute: "${LDAP_GROUP_UID_ATTRIBUTE}" 38 | groupNameAttributes: ${LDAP_GROUP_NAME_ATTRIBUTES} 39 | groupMembershipAttributes: ${LDAP_GROUP_MEMBERSHIP_ATTRIBUTES} 40 | usersQuery: 41 | baseDN: "${LDAP_USERS_SEARCH_BASE}" 42 | scope: "sub" 43 | derefAliases: "never" 44 | pageSize: 0 45 | userNameAttributes: ${LDAP_USER_NAME_ATTRIBUTES} 46 | userUIDAttribute: "${LDAP_USER_UID_ATTRIBUTE}" 47 | tolerateMemberNotFoundErrors: true 48 | tolerateMemberOutOfScopeErrors: true 49 | whitelist.txt: "${LDAP_GROUPS_WHITELIST}" 50 | 51 | - kind: "Secret" 52 | apiVersion: "v1" 53 | metadata: 54 | name: "${LDAP_BIND_PASSWORD_SECRET}" 55 | namespace: "${NAMESPACE}" 56 | labels: 57 | template: "cronjob-ldap-group-sync" 58 | type: "Opaque" 59 | stringData: 60 | bind_password: "${LDAP_BIND_PASSWORD}" 61 | 62 | - kind: "CronJob" 63 | apiVersion: "batch/v1beta1" 64 | metadata: 65 | name: "${JOB_NAME}" 66 | namespace: "${NAMESPACE}" 67 | labels: 68 | template: "cronjob-ldap-group-sync" 69 | spec: 70 | schedule: "${SCHEDULE}" 71 | concurrencyPolicy: "Forbid" 72 | successfulJobsHistoryLimit: "${{SUCCESS_JOBS_HISTORY_LIMIT}}" 73 | failedJobsHistoryLimit: "${{FAILED_JOBS_HISTORY_LIMIT}}" 74 | jobTemplate: 75 | spec: 76 | backoffLimit: 0 77 | template: 78 | spec: 79 | containers: 80 | - name: "${JOB_NAME}" 81 | image: "${IMAGE}:${IMAGE_TAG}" 82 | command: 83 | - "/bin/bash" 84 | - "-c" 85 | - oc adm groups sync --sync-config=/etc/config/ldap-group-sync.yaml --confirm 86 | $([ -s /etc/config/whitelist.txt ] && echo --whitelist=/etc/config/whitelist.txt) 87 | volumeMounts: 88 | - mountPath: "/etc/config" 89 | name: "ldap-sync-volume" 90 | - mountPath: "/etc/secrets" 91 | name: "ldap-bind-password" 92 | volumes: 93 | - name: "ldap-sync-volume" 94 | configMap: 95 | name: "${LDAP_CONFIG}" 96 | - name: "ldap-bind-password" 97 | secret: 98 | secretName: "${LDAP_BIND_PASSWORD_SECRET}" 99 | restartPolicy: "Never" 100 | terminationGracePeriodSeconds: 30 101 | activeDeadlineSeconds: 500 102 | dnsPolicy: "ClusterFirst" 103 | serviceAccountName: "${JOB_SERVICE_ACCOUNT}" 104 | serviceAccount: "${JOB_SERVICE_ACCOUNT}" 105 | startingDeadlineSeconds: ${{STARTING_DEADLINE_SECONDS}} 106 | 107 | - kind: "ClusterRole" 108 | apiVersion: "v1" 109 | metadata: 110 | name: "ldap-group-syncer" 111 | namespace: "${NAMESPACE}" 112 | labels: 113 | template: "cronjob-ldap-group-sync" 114 | rules: 115 | - apiGroups: 116 | - "" 117 | - "user.openshift.io" 118 | resources: 119 | - "groups" 120 | verbs: 121 | - "get" 122 | - "list" 123 | - "create" 124 | - "update" 125 | 126 | - kind: "ClusterRoleBinding" 127 | apiVersion: "v1" 128 | groupNames: null 129 | metadata: 130 | name: "system:ldap-group-syncers" 131 | roleRef: 132 | name: "ldap-group-syncer" 133 | subjects: 134 | - kind: "ServiceAccount" 135 | name: "${JOB_SERVICE_ACCOUNT}" 136 | userNames: 137 | - "system:serviceaccount:${NAMESPACE}:${JOB_SERVICE_ACCOUNT}" 138 | 139 | - kind: "ServiceAccount" 140 | apiVersion: "v1" 141 | metadata: 142 | name: "${JOB_SERVICE_ACCOUNT}" 143 | namespace: "${NAMESPACE}" 144 | labels: 145 | template: "cronjob-ldap-group-sync" 146 | 147 | parameters: 148 | - name: "NAMESPACE" 149 | displayName: "Namespace" 150 | description: "Name of the Namespace where to deploy the Scheduled Job" 151 | value: "openshift-cluster-ops" 152 | required: true 153 | - name: "JOB_NAME" 154 | displayName: "Job Name" 155 | description: "Name of the Scheduled Job to Create." 156 | value: "cronjob-ldap-group-sync" 157 | required: true 158 | - name: "SCHEDULE" 159 | displayName: "Cron Schedule" 160 | description: "Cron Schedule to Execute the Job" 161 | value: "@hourly" 162 | required: true 163 | - name: "JOB_SERVICE_ACCOUNT" 164 | displayName: "Service Account Name" 165 | description: "Name of the Service Account To Exeucte the Job As." 166 | value: "ldap-group-syncer" 167 | required: true 168 | - name: "SUCCESS_JOBS_HISTORY_LIMIT" 169 | displayName: "Successful Job History Limit" 170 | description: "The number of successful jobs that will be retained" 171 | value: "5" 172 | required: true 173 | - name: "FAILED_JOBS_HISTORY_LIMIT" 174 | displayName: "Failed Job History Limit" 175 | description: "The number of failed jobs that will be retained" 176 | value: "5" 177 | required: true 178 | - name: "LDAP_URL" 179 | displayName: "LDAP Server URL" 180 | description: "URL of you LDAP server" 181 | required: true 182 | - name: "LDAP_BIND_DN" 183 | displayName: "LDAP Bind User's DN" 184 | description: "The Full DN for the user you wish to use to authenticate to LDAP" 185 | required: true 186 | - name: "LDAP_BIND_PASSWORD" 187 | displayName: "LDAP Bind User's password" 188 | description: "Password for the LDAP_BIND_DN user" 189 | required: true 190 | - name: "LDAP_BIND_PASSWORD_SECRET" 191 | displayName: "LDAP Bind Password Secret" 192 | description: "The name for the secret in which to store the bind password" 193 | value: "ldap-bind-password" 194 | required: true 195 | - name: "LDAP_GROUPS_SEARCH_BASE" 196 | displayName: "Group search query" 197 | description: "Location in LDAP tree where you will find groups" 198 | required: true 199 | value: "cn=groups,cn=accounts,dc=myorg,dc=example,dc=com" 200 | - name: "LDAP_GROUPS_FILTER" 201 | displayName: "Group Filter" 202 | description: "LDAP Filter to use when deciding which groups to sync into OpenShift" 203 | required: true 204 | value: "(&(objectclass=ipausergroup)(memberOf=cn=openshift-users,cn=groups,cn=accounts,dc=myorg,dc=example,dc=com))" 205 | - name: "LDAP_GROUP_NAME_ATTRIBUTES" 206 | displayName: "Group name attributes" 207 | description: "The attribute list to use to discover the name for the group." 208 | required: true 209 | value: >- 210 | ["cn"] 211 | - name: "LDAP_GROUP_MEMBERSHIP_ATTRIBUTES" 212 | displayName: "Group membership attributes" 213 | value: >- 214 | ["member"] 215 | - name: "LDAP_GROUP_UID_ATTRIBUTE" 216 | displayName: "Group UID Attribute" 217 | description: "The attribute that uniquely identifies a group on the LDAP server." 218 | required: true 219 | value: "ipaUniqueID" 220 | - name: "LDAP_GROUPS_WHITELIST" 221 | displayName: "LDAP sync whitelist" 222 | description: "File content for groups sync --whitelist option" 223 | value: "" 224 | - name: "LDAP_USER_NAME_ATTRIBUTES" 225 | displayName: "User name attributes" 226 | description: "JSON list of attributes to use to discover the user name for group membership" 227 | required: true 228 | value: >- 229 | ["uid"] 230 | - name: "LDAP_USER_UID_ATTRIBUTE" 231 | displayName: "User UID attribute" 232 | description: "The attribute that uniquely identifies a user on the LDAP server." 233 | required: true 234 | value: "dn" 235 | - name: "LDAP_USERS_SEARCH_BASE" 236 | displayName: "User search query" 237 | description: "Location in LDAP tree where you will find users" 238 | required: true 239 | value: "cn=users,cn=accounts,dc=myorg,dc=example,dc=com" 240 | - name: "IMAGE" 241 | displayName: "Image" 242 | description: "Image to use for the container." 243 | required: true 244 | value: "registry.access.redhat.com/openshift3/ose-cli" 245 | - name: "IMAGE_TAG" 246 | displayName: "Image Tag" 247 | description: "Image Tag to use for the container." 248 | required: true 249 | value: "v3.11" 250 | - name: "STARTING_DEADLINE_SECONDS" 251 | description: "Set the startingDeadlineSeconds for the cronjob" 252 | required: false 253 | value: "60" 254 | - name: "LDAP_CONFIG" 255 | displayName: "LDAP Config" 256 | description: "The name for the ConfigMap in which to store the LDAP Configuration" 257 | value: "ldap-config" 258 | required: true 259 | -------------------------------------------------------------------------------- /jobs/cronjob-prune-builds-deployments.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Template 3 | apiVersion: v1 4 | metadata: 5 | name: cronjob-prune-builds-deployments 6 | annotations: 7 | description: Scheduled Task to Prune Builds or Deployments 8 | iconClass: icon-shadowman 9 | tags: management,cronjob,prune,builds,deployments 10 | objects: 11 | - kind: CronJob 12 | apiVersion: batch/v1beta1 13 | metadata: 14 | name: "${JOB_NAME}-${PRUNE_TYPE}" 15 | spec: 16 | schedule: "${SCHEDULE}" 17 | concurrencyPolicy: Forbid 18 | successfulJobsHistoryLimit: "${{SUCCESS_JOBS_HISTORY_LIMIT}}" 19 | failedJobsHistoryLimit: "${{FAILED_JOBS_HISTORY_LIMIT}}" 20 | jobTemplate: 21 | spec: 22 | template: 23 | spec: 24 | containers: 25 | - name: "${JOB_NAME}-${PRUNE_TYPE}" 26 | image: "${IMAGE}:${IMAGE_TAG}" 27 | command: 28 | - "/bin/bash" 29 | - "-c" 30 | - oc adm prune ${PRUNE_TYPE} --keep-complete=$KEEP_COMPLETE --keep-failed=$KEEP_FAILED 31 | --keep-younger-than=$KEEP_YOUNGER_THAN --orphans=$PRUNE_ORPHANS --confirm 32 | env: 33 | - name: KEEP_COMPLETE 34 | value: "${KEEP_COMPLETE}" 35 | - name: KEEP_FAILED 36 | value: "${KEEP_FAILED}" 37 | - name: KEEP_YOUNGER_THAN 38 | value: "${KEEP_YOUNGER_THAN}" 39 | - name: PRUNE_ORPHANS 40 | value: "${PRUNE_ORPHANS}" 41 | restartPolicy: Never 42 | terminationGracePeriodSeconds: 30 43 | activeDeadlineSeconds: 500 44 | dnsPolicy: ClusterFirst 45 | serviceAccountName: "${JOB_SERVICE_ACCOUNT}" 46 | serviceAccount: "${JOB_SERVICE_ACCOUNT}" 47 | startingDeadlineSeconds: ${{STARTING_DEADLINE_SECONDS}} 48 | - kind: ClusterRoleBinding 49 | apiVersion: v1 50 | metadata: 51 | name: system:build-pruners 52 | labels: 53 | template: "cronjob-prune-builds" 54 | roleRef: 55 | name: cluster-admin 56 | subjects: 57 | - kind: ServiceAccount 58 | name: ${JOB_SERVICE_ACCOUNT} 59 | userNames: 60 | - system:serviceaccount:${NAMESPACE}:${JOB_SERVICE_ACCOUNT} 61 | - kind: ServiceAccount 62 | apiVersion: v1 63 | metadata: 64 | name: ${JOB_SERVICE_ACCOUNT} 65 | labels: 66 | template: "cronjob-prune-builds" 67 | parameters: 68 | - name: JOB_NAME 69 | displayName: Job Name 70 | description: Name of the Scheduled Job to Create. 71 | value: cronjob-prune-resources 72 | required: true 73 | - name: SCHEDULE 74 | displayName: Cron Schedule 75 | description: Cron Schedule to Execute the Job 76 | value: 0 0 * * * 77 | required: true 78 | - name: JOB_SERVICE_ACCOUNT 79 | displayName: Service Account Name 80 | description: Name of the Service Account To Exeucte the Job As. 81 | value: pruner 82 | required: true 83 | - name: PRUNE_TYPE 84 | displayName: Type of pruning action (builds|deployments) 85 | description: Type of pruning action that will be performed. Must specify 'builds' 86 | or 'deployments' 87 | value: '' 88 | required: true 89 | - name: KEEP_COMPLETE 90 | displayName: Number of Completed Items 91 | description: Number of completed items that will not be considered for pruning. 92 | value: '5' 93 | required: true 94 | - name: KEEP_FAILED 95 | displayName: Number of Failed Items 96 | description: Number of failed items that will not be considered for pruning. 97 | value: '1' 98 | required: true 99 | - name: KEEP_YOUNGER_THAN 100 | displayName: Minimum Age of the resource 101 | description: The minimum age of the resource for it to be considered a candidate 102 | for pruning 103 | value: 60m 104 | required: true 105 | - name: PRUNE_ORPHANS 106 | displayName: Prune orphan resources 107 | description: Prune builds or deployments where their associated BuildConfig or DeploymentConfig 108 | no longer exists 109 | value: 'true' 110 | required: true 111 | - name: SUCCESS_JOBS_HISTORY_LIMIT 112 | displayName: Successful Job History Limit 113 | description: The number of successful jobs that will be retained 114 | value: '5' 115 | required: true 116 | - name: FAILED_JOBS_HISTORY_LIMIT 117 | displayName: Failed Job History Limit 118 | description: The number of failed jobs that will be retained 119 | value: '5' 120 | required: true 121 | - name: "NAMESPACE" 122 | displayName: "Namespace where this is deployed" 123 | description: "Namespace where this is deployed." 124 | value: "cluster-ops" 125 | required: true 126 | - name: "IMAGE" 127 | displayName: "Image" 128 | description: "Image to use for the container." 129 | required: true 130 | value: "quay.io/openshift/origin-cli" 131 | - name: "IMAGE_TAG" 132 | displayName: "Image Tag" 133 | description: "Image Tag to use for the container." 134 | required: true 135 | value: "4.4" 136 | - name: STARTING_DEADLINE_SECONDS 137 | description: Set the startingDeadlineSeconds for the cronjob 138 | required: false 139 | value: "60" 140 | labels: 141 | template: cronjob-prune-builds-deployments 142 | -------------------------------------------------------------------------------- /jobs/cronjob-prune-images.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Template 3 | apiVersion: v1 4 | metadata: 5 | name: cronjob-prune-images 6 | annotations: 7 | description: Scheduled Task to Prune Images from Internal Docker Registry 8 | iconClass: icon-shadowman 9 | tags: management,cronjob,prune,images 10 | objects: 11 | - kind: CronJob 12 | apiVersion: batch/v1beta1 13 | metadata: 14 | name: "${JOB_NAME}" 15 | spec: 16 | schedule: "${SCHEDULE}" 17 | concurrencyPolicy: Forbid 18 | successfulJobsHistoryLimit: "${{SUCCESS_JOBS_HISTORY_LIMIT}}" 19 | failedJobsHistoryLimit: "${{FAILED_JOBS_HISTORY_LIMIT}}" 20 | jobTemplate: 21 | spec: 22 | template: 23 | spec: 24 | containers: 25 | - name: "${JOB_NAME}" 26 | image: "${IMAGE}:${IMAGE_TAG}" 27 | command: 28 | - "/bin/bash" 29 | - "-c" 30 | - oc adm prune images --certificate-authority=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt 31 | --keep-tag-revisions=$IMAGE_PRUNE_KEEP_TAG_REVISIONS --keep-younger-than=$IMAGE_PRUNE_KEEP_YOUNGER_THAN --confirm 32 | env: 33 | - name: IMAGE_PRUNE_KEEP_TAG_REVISIONS 34 | value: "${IMAGE_PRUNE_KEEP_TAG_REVISIONS}" 35 | - name: IMAGE_PRUNE_KEEP_YOUNGER_THAN 36 | value: "${IMAGE_PRUNE_KEEP_YOUNGER_THAN}" 37 | restartPolicy: Never 38 | terminationGracePeriodSeconds: 30 39 | activeDeadlineSeconds: 500 40 | dnsPolicy: ClusterFirst 41 | serviceAccountName: "${JOB_SERVICE_ACCOUNT}" 42 | serviceAccount: "${JOB_SERVICE_ACCOUNT}" 43 | startingDeadlineSeconds: ${{STARTING_DEADLINE_SECONDS}} 44 | - kind: ClusterRoleBinding 45 | apiVersion: v1 46 | metadata: 47 | name: system:image-pruners 48 | labels: 49 | template: "cronjob-prune-images" 50 | roleRef: 51 | name: cluster-admin 52 | subjects: 53 | - kind: ServiceAccount 54 | name: ${JOB_SERVICE_ACCOUNT} 55 | userNames: 56 | - system:serviceaccount:${NAMESPACE}:${JOB_SERVICE_ACCOUNT} 57 | - kind: ServiceAccount 58 | apiVersion: v1 59 | metadata: 60 | name: ${JOB_SERVICE_ACCOUNT} 61 | labels: 62 | template: "cronjob-prune-images" 63 | parameters: 64 | - name: JOB_NAME 65 | displayName: Job Name 66 | description: Name of the Scheduled Job to Create. 67 | value: cronjob-prune-images 68 | required: true 69 | - name: SCHEDULE 70 | displayName: Cron Schedule 71 | description: Cron Schedule to Execute the Job 72 | value: 0 0 * * * 73 | required: true 74 | - name: JOB_SERVICE_ACCOUNT 75 | displayName: Service Account Name 76 | description: Name of the Service Account To Exeucte the Job As. 77 | value: pruner 78 | required: true 79 | - name: IMAGE_PRUNE_KEEP_TAG_REVISIONS 80 | displayName: Number of Tag Revisions 81 | description: Specify the number of image revisions for a tag in an image stream 82 | that will be preserved. 83 | value: '3' 84 | required: true 85 | - name: IMAGE_PRUNE_KEEP_YOUNGER_THAN 86 | displayName: Minimum Age of an Image 87 | description: The minimum age of an image for it to be considered a candidate for 88 | pruning 89 | value: 1h0m0s 90 | required: true 91 | - name: SUCCESS_JOBS_HISTORY_LIMIT 92 | displayName: Successful Job History Limit 93 | description: The number of successful jobs that will be retained 94 | value: '5' 95 | required: true 96 | - name: FAILED_JOBS_HISTORY_LIMIT 97 | displayName: Failed Job History Limit 98 | description: The number of failed jobs that will be retained 99 | value: '5' 100 | required: true 101 | - name: "NAMESPACE" 102 | displayName: "Namespace where this is deployed" 103 | description: "Namespace where this is deployed." 104 | value: "cluster-ops" 105 | required: true 106 | - name: "IMAGE" 107 | displayName: "Image" 108 | description: "Image to use for the container." 109 | required: true 110 | value: "quay.io/openshift/origin-cli" 111 | - name: "IMAGE_TAG" 112 | displayName: "Image Tag" 113 | description: "Image Tag to use for the container." 114 | required: true 115 | value: "4.4" 116 | - name: STARTING_DEADLINE_SECONDS 117 | description: Set the startingDeadlineSeconds for the cronjob 118 | required: false 119 | value: "60" 120 | 121 | labels: 122 | template: cronjob-prune-images 123 | -------------------------------------------------------------------------------- /jobs/cronjob-prune-projects-build.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Template 4 | metadata: 5 | name: cronjob-prune-projects 6 | objects: 7 | - kind: ImageStream 8 | apiVersion: v1 9 | metadata: 10 | annotations: 11 | description: Keeps track of changes in the application image 12 | name: ${NAME} 13 | labels: 14 | template: cronjob-prune-projects 15 | spec: 16 | lookupPolicy: 17 | local: true 18 | - kind: BuildConfig 19 | apiVersion: v1 20 | metadata: 21 | annotations: 22 | description: Defines how to build the application 23 | name: ${NAME} 24 | labels: 25 | template: cronjob-prune-projects 26 | spec: 27 | completionDeadlineSeconds: 1800 28 | output: 29 | to: 30 | kind: ImageStreamTag 31 | name: ${NAME}:${TAG} 32 | runPolicy: Serial 33 | source: 34 | git: 35 | uri: "${SOURCE_REPOSITORY_URL}" 36 | ref: "${SOURCE_REPOSITORY_REF}" 37 | contextDir: "${CONTEXT_DIR}" 38 | strategy: 39 | dockerStrategy: 40 | from: 41 | kind: DockerImage 42 | name: "${BASE_IMAGE}" 43 | type: Docker 44 | triggers: 45 | - type: ConfigChange 46 | parameters: 47 | - description: The name assigned to all of the frontend objects defined in this template. 48 | displayName: Name 49 | name: NAME 50 | required: true 51 | value: prune-ocp-projects 52 | - description: Git branch/tag reference 53 | name: SOURCE_REPOSITORY_REF 54 | value: master 55 | - description: Git source URL for application 56 | name: SOURCE_REPOSITORY_URL 57 | required: true 58 | value: https://github.com/redhat-cop/openshift-management 59 | - description: Path within Git repository to build; empty for root of repository 60 | name: CONTEXT_DIR 61 | value: "images/prune-ocp-projects" 62 | - description: Base image for the buils 63 | name: BASE_IMAGE 64 | required: true 65 | value: "centos:7" 66 | - description: The tag for the iamge 67 | displayName: Image Tag 68 | name: TAG 69 | required: true 70 | value: latest 71 | -------------------------------------------------------------------------------- /jobs/cronjob-prune-projects.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Template 4 | metadata: 5 | name: cronjob-prune-projects 6 | objects: 7 | - kind: CronJob 8 | apiVersion: batch/v1beta1 9 | metadata: 10 | name: "${JOB_NAME}" 11 | labels: 12 | template: cronjob-prune-projects 13 | spec: 14 | schedule: "${SCHEDULE}" 15 | concurrencyPolicy: Forbid 16 | successfulJobsHistoryLimit: "${{SUCCESS_JOBS_HISTORY_LIMIT}}" 17 | failedJobsHistoryLimit: "${{FAILED_JOBS_HISTORY_LIMIT}}" 18 | jobTemplate: 19 | spec: 20 | template: 21 | spec: 22 | containers: 23 | - name: "${JOB_NAME}" 24 | image: "${IMAGE_PROJECT_PRUNER}:${TAG}" 25 | command: 26 | - "/bin/bash" 27 | - "-c" 28 | - "/usr/local/bin/prune-ocp-projects.sh" 29 | env: 30 | - name: PROJECT_EXCLUDE_USER 31 | value: "${PROJECT_EXCLUDE_USER}" 32 | - name: PROJECT_EXCLUDE_SYSTEM 33 | value: "${NAMESPACE} ${PROJECT_EXCLUDE_SYSTEM}" 34 | - name: TIMESTAMP_HOURS_AGO 35 | value: "${TIMESTAMP_HOURS_AGO}" 36 | restartPolicy: Never 37 | terminationGracePeriodSeconds: 30 38 | activeDeadlineSeconds: 500 39 | dnsPolicy: ClusterFirst 40 | serviceAccountName: "${JOB_SERVICE_ACCOUNT}" 41 | serviceAccount: "${JOB_SERVICE_ACCOUNT}" 42 | startingDeadlineSeconds: ${{STARTING_DEADLINE_SECONDS}} 43 | - kind: ClusterRoleBinding 44 | apiVersion: v1 45 | metadata: 46 | name: system:project-pruners 47 | labels: 48 | template: cronjob-prune-projects 49 | roleRef: 50 | name: cluster-admin 51 | subjects: 52 | - kind: ServiceAccount 53 | name: ${JOB_SERVICE_ACCOUNT} 54 | userNames: 55 | - system:serviceaccount:${NAMESPACE}:${JOB_SERVICE_ACCOUNT} 56 | - kind: ServiceAccount 57 | apiVersion: v1 58 | metadata: 59 | name: ${JOB_SERVICE_ACCOUNT} 60 | labels: 61 | template: cronjob-prune-projects 62 | parameters: 63 | - description: The name assigned to all of the frontend objects defined in this template. 64 | displayName: Name 65 | name: NAME 66 | required: true 67 | value: prune-ocp-projects 68 | - name: JOB_NAME 69 | displayName: Job Name 70 | description: Name of the Scheduled Job to Create. 71 | value: cronjob-prune-projects 72 | required: true 73 | - name: SCHEDULE 74 | displayName: Cron Schedule 75 | description: Cron Schedule to Execute the Job 76 | value: "@hourly" 77 | required: true 78 | - name: SUCCESS_JOBS_HISTORY_LIMIT 79 | displayName: Successful Job History Limit 80 | description: The number of successful jobs that will be retained 81 | value: '5' 82 | required: true 83 | - name: FAILED_JOBS_HISTORY_LIMIT 84 | displayName: Failed Job History Limit 85 | description: The number of failed jobs that will be retained 86 | value: '5' 87 | required: true 88 | - name: NAMESPACE 89 | displayName: "Namespace where this is deployed" 90 | description: "Namespace where this is deployed." 91 | value: "cluster-maintenance" 92 | required: true 93 | - name: PROJECT_EXCLUDE_SYSTEM 94 | displayName: System projects to exclude from the Prune Job 95 | description: System projects that should not be deleted 96 | value: cluster-maintenance 97 | required: true 98 | - name: PROJECT_EXCLUDE_USER 99 | displayName: User defined projects to exclude from the Prune Job 100 | description: User projects that should not be deleted 101 | required: true 102 | - name: TIMESTAMP_HOURS_AGO 103 | displayName: Prune projects older than X hours 104 | description: The number of hours "old" the project needs to be - i.e. '-2hours' 105 | value: '-12hours' 106 | required: true 107 | - name: JOB_SERVICE_ACCOUNT 108 | displayName: "Service Account Name" 109 | description: "Name of the Service Account To Execute the Job As." 110 | value: "pruner" 111 | required: true 112 | - description: The Image name 113 | displayName: Image Name 114 | name: IMAGE_PROJECT_PRUNER 115 | required: true 116 | value: quay.io/redhat-cop/prune-ocp-projects 117 | - description: The tag for the iamge 118 | displayName: Image Tag 119 | name: TAG 120 | required: true 121 | value: latest 122 | - name: STARTING_DEADLINE_SECONDS 123 | description: Set the startingDeadlineSeconds for the cronjob 124 | required: false 125 | value: "60" 126 | --------------------------------------------------------------------------------