├── .applier ├── group_vars │ └── seed-hosts.yml └── hosts ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── stale.yml └── workflows │ └── mvn.yaml ├── .gitignore ├── .openshift └── templates │ └── build-pipelines.j2 ├── .travis └── check-missing.sh ├── LICENSE ├── OWNERS ├── README.md ├── TESTING.md ├── _test └── setup.sh ├── galaxy-requirements.yml ├── jenkins-s2i ├── configuration │ └── org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml ├── jenkins-s2i.yml └── plugins.txt ├── meta └── main.yml ├── pom.xml ├── requirements.yml ├── roles ├── configure-jenkins │ ├── defaults │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── link-secret │ └── tasks │ │ └── main.yml └── process-tests │ ├── defaults │ └── main.yml │ └── tasks │ └── main.yml ├── src └── org │ └── redhatcop │ └── util │ ├── Notifications.txt │ └── notifications.groovy ├── test ├── Jenkinsfile-applier ├── Jenkinsfile-applier-fail-missingsecret ├── Jenkinsfile-applyTemplate ├── Jenkinsfile-applyTemplate-viahttp ├── Jenkinsfile-applyTemplate-withparams ├── Jenkinsfile-binaryBuild ├── Jenkinsfile-binaryBuild-fail-missingbuildconfig ├── Jenkinsfile-buildAndTag ├── Jenkinsfile-clusterCredentials ├── Jenkinsfile-clusterCredentials-fail-missingsecret ├── Jenkinsfile-configMap ├── Jenkinsfile-configMap-fail-missingconfigmap ├── Jenkinsfile-crossClusterPromote ├── Jenkinsfile-crossClusterPromote-fail-missingsecret ├── Jenkinsfile-patchBuildConfigOutputLabels ├── Jenkinsfile-rollback ├── Jenkinsfile-rollback-fail-missingdc ├── Jenkinsfile-rollout ├── Jenkinsfile-rollout-deployment ├── Jenkinsfile-rollout-fail-loghistory ├── Jenkinsfile-rollout-fail-missingdc ├── Jenkinsfile-sonarqubeStaticAnalysis ├── Jenkinsfile-tagAndDeploy ├── Jenkinsfile-tagImage ├── Jenkinsfile-verifyDeployment ├── Jenkinsfile-verifyDeployment-fail-viacrashloop ├── Jenkinsfile-verifyService ├── Jenkinsfile-verifyService-fail-nopods ├── create-pipeline-library.groovy ├── create-sonarqube-installation.groovy ├── disabled-imageMirror └── org │ └── redhatcop │ └── util │ ├── end-to-end │ ├── Jenkinsfile │ ├── README.md │ ├── files │ │ ├── params │ │ │ ├── build │ │ │ ├── deploy-dev │ │ │ ├── deploy-test │ │ │ ├── jenkins-deployment │ │ │ └── jenkins-s2i │ │ ├── projects.yml │ │ └── templates │ │ │ ├── build.yml │ │ │ └── deployment.yml │ └── inventory │ │ ├── group_vars │ │ └── seed-hosts.yml │ │ └── hosts │ ├── rocketchat │ ├── Jenkinsfile │ ├── README.md │ ├── files │ │ ├── params │ │ │ ├── jenkins-deployment.params │ │ │ ├── jenkins-s2i.params │ │ │ └── notifications-build.params │ │ ├── projects.yml │ │ ├── rocketchat-secret.yml │ │ └── templates │ │ │ └── build-template.yml │ └── inventory │ │ ├── group_vars │ │ └── seed-hosts.yml │ │ └── hosts │ └── rollback │ ├── Jenkinsfile │ ├── README.md │ ├── files │ ├── params │ │ ├── build │ │ ├── deploy │ │ ├── jenkins-deployment │ │ └── jenkins-s2i │ ├── projects.yml │ └── templates │ │ ├── build.yml │ │ └── deployment.yml │ └── inventory │ ├── group_vars │ └── seed-hosts.yml │ └── hosts └── vars ├── applier.groovy ├── applier.txt ├── applyTemplate.groovy ├── applyTemplate.txt ├── binaryBuild.groovy ├── binaryBuild.txt ├── buildAndTag.groovy ├── buildAndTag.txt ├── clusterCredentials.groovy ├── clusterCredentials.txt ├── configMap.groovy ├── configMap.txt ├── crossClusterPromote.groovy ├── crossClusterPromote.txt ├── imageMirror.groovy ├── imageMirror.txt ├── patchBuildConfigOutputLabels.groovy ├── patchBuildConfigOutputLabels.txt ├── rollback.groovy ├── rollback.txt ├── rollout.groovy ├── rollout.txt ├── sonarqubeStaticAnalysis.groovy ├── sonarqubeStaticAnalysis.txt ├── tagAndDeploy.groovy ├── tagAndDeploy.txt ├── tagImage.groovy ├── tagImage.txt ├── verifyDeployment.groovy ├── verifyDeployment.txt ├── verifyService.groovy └── verifyService.txt /.applier/group_vars/seed-hosts.yml: -------------------------------------------------------------------------------- 1 | --- 2 | namespace: pipelinelib-testing 3 | repository_url: https://github.com/redhat-cop/pipeline-library.git 4 | repo_ref: master 5 | clone_dir: /tmp/redhat-cop/pipeline-library/master 6 | templates_repo_ref: v1.4.13 7 | 8 | secretdata_auth: "openshift1:{{ oc_token }}" 9 | secretdata: 10 | dockercfg_json: '{"auths": { "{{ internal_registry_url.split("/")[0] }}": {"username": "openshift1", "password": "{{ oc_token }}", "auth": "{{ secretdata_auth | b64encode }}", "email": "unused"}}}' 11 | 12 | secrets: '{ 13 | "{{ namespace }}": { 14 | "local-registry-generic": { 15 | "username": "openshift1", 16 | "token": "{{ oc_token }}", 17 | "registry": "{{ internal_registry_url.split("/")[0] }}" 18 | }, 19 | "my-token": { 20 | "username": "openshift1", 21 | "password": "{{ oc_token }}" 22 | } 23 | } 24 | }' 25 | 26 | jenkins: 27 | deploy: 28 | MEMORY_REQUEST: 2Gi 29 | MEMORY_LIMIT: 3Gi 30 | CPU_REQUEST: 2 31 | CPU_LIMIT: 3 32 | imagestreams: 33 | ansible: 34 | IMAGE_STREAM_ROLE: jenkins-slave 35 | IMAGE_STREAM_NAME: jenkins-slave-ansible 36 | IMAGE_STREAM_TAG_FROM_KIND: DockerImage 37 | IMAGE_STREAM_TAG_FROM_NAME: quay.io/redhat-cop/jenkins-slave-ansible:v1.15 38 | IMAGE_STREAM_NAMESPACE: "{{ namespace }}" 39 | imagemgmt: 40 | IMAGE_STREAM_ROLE: jenkins-slave 41 | IMAGE_STREAM_NAME: jenkins-slave-image-mgmt 42 | IMAGE_STREAM_TAG_FROM_KIND: DockerImage 43 | IMAGE_STREAM_TAG_FROM_NAME: siamaksade/jenkins-slave-skopeo-centos7 44 | IMAGE_STREAM_NAMESPACE: "{{ namespace }}" 45 | secrets: 46 | localregistrydockercfg: 47 | NAME: local-registry 48 | DOCKER_CONFIG: "{{ secretdata.dockercfg_json | to_json | b64encode }}" 49 | tests: 50 | files: "{{ lookup('fileglob', '{{ inventory_dir }}/../test/Jenkinsfile-*', wantlist=true) }}" 51 | 52 | openshift_cluster_content: 53 | - galaxy_requirements: 54 | - "{{ inventory_dir }}/../galaxy-requirements.yml" 55 | - object: Environment Setup 56 | content: 57 | - name: Create Projects 58 | template: "https://raw.githubusercontent.com/redhat-cop/openshift-templates/{{ templates_repo_ref }}/project-requests/create-project.yml" 59 | action: create 60 | params_from_vars: 61 | NAMESPACE: "{{ namespace }}" 62 | NAMESPACE_DESCRIPTION: "{{ namespace }}" 63 | NAMESPACE_DISPLAY_NAME: "{{ namespace }}" 64 | tags: 65 | - project 66 | - object: jenkins-imagestreams 67 | content: 68 | - name: jenkins-slave-ansible 69 | template: "https://raw.githubusercontent.com/redhat-cop/openshift-templates/{{ templates_repo_ref }}/imagestreams/imagestream-generic.yml" 70 | params_from_vars: "{{ jenkins.imagestreams.ansible }}" 71 | namespace: "{{ namespace }}" 72 | tags: 73 | - jenkins-imagestreams 74 | - name: jenkins-slave-image-mgmt 75 | template: "https://raw.githubusercontent.com/redhat-cop/openshift-templates/{{ templates_repo_ref }}/imagestreams/imagestream-generic.yml" 76 | params_from_vars: "{{ jenkins.imagestreams.imagemgmt }}" 77 | namespace: "{{ namespace }}" 78 | tags: 79 | - jenkins-imagestreams 80 | - object: jenkins-secrets 81 | content: 82 | - name: local-registry-dockercfg 83 | template: "https://raw.githubusercontent.com/redhat-cop/openshift-templates/{{ templates_repo_ref }}/secrets/secret-docker-cfg.yml" 84 | params_from_vars: "{{ jenkins.secrets.localregistrydockercfg }}" 85 | namespace: "{{ namespace }}" 86 | tags: 87 | - jenkins-secrets 88 | - name: generic 89 | file: "https://raw.githubusercontent.com/redhat-cop/openshift-templates/{{ templates_repo_ref }}/secrets/dynamic-opaque-jinja.j2" 90 | namespace: "{{ namespace }}" 91 | post_steps: 92 | - role: casl-ansible/roles/openshift-labels 93 | vars: 94 | label: "credential.sync.jenkins.openshift.io=true" 95 | target_object: "secret" 96 | target_name: "my-token" 97 | target_namespace: "{{ namespace }}" 98 | tags: 99 | - jenkins-secrets 100 | - object: jenkins 101 | content: 102 | - name: jenkins 103 | template: "https://raw.githubusercontent.com/redhat-cop/openshift-templates/{{ templates_repo_ref }}/jenkins/jenkins-ephemeral-template.yml" 104 | params_from_vars: "{{ jenkins.deploy }}" 105 | namespace: "{{ namespace }}" 106 | pre_steps: 107 | - role: pipeline-library/roles/process-tests 108 | post_steps: 109 | - role: casl-ansible/roles/openshift-replicas-ready 110 | vars: 111 | type: deploymentconfig 112 | resource: jenkins 113 | - role: casl-ansible/roles/openshift-route-status 114 | vars: 115 | target_namespace: "{{ namespace }}" 116 | route: jenkins 117 | protocol: https 118 | status: 200 119 | retries: 10 120 | delay: 30 121 | validate_certificates: no 122 | headers: 123 | Authorization: "Bearer {{ oc_token }}" 124 | - role: pipeline-library/roles/configure-jenkins 125 | - role: pipeline-library/roles/link-secret 126 | vars: 127 | sa_name: "jenkins" 128 | secret_name: "local-registry" 129 | - role: pipeline-library/roles/link-secret 130 | vars: 131 | sa_name: "jenkins" 132 | secret_name: "local-registry-generic" 133 | tags: 134 | - jenkins 135 | - object: test-pipelines 136 | content: 137 | - name: Deploy test pipelines 138 | file: "{{ inventory_dir }}/../.openshift/templates/build-pipelines.j2" 139 | namespace: "{{ namespace }}" 140 | tags: 141 | - test-pipelines 142 | -------------------------------------------------------------------------------- /.applier/hosts: -------------------------------------------------------------------------------- 1 | [seed-hosts] 2 | localhost ansible_connection=local 3 | -------------------------------------------------------------------------------- /.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/day-in-the-life 8 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | ## Configuration for probot-stale - https://github.com/probot/stale 2 | # 3 | ## Number of days of inactivity before an Issue or Pull Request becomes stale 4 | #daysUntilStale: 60 5 | ## Number of days of inactivity before a stale Issue or Pull Request is closed. 6 | ## Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 7 | #daysUntilClose: 7 8 | ## Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 9 | #exemptLabels: 10 | # - pinned 11 | # - security 12 | # - "[Status] Maybe Later" 13 | ## Label to use when marking as stale 14 | #staleLabel: wontfix 15 | ## Comment to post when marking as stale. Set to `false` to disable 16 | #markComment: > 17 | # This issue has been automatically marked as stale because it has not had 18 | # recent activity. It will be closed if no further activity occurs. Thank you 19 | # for your contributions. 20 | ## Comment to post when removing the stale label. Set to `false` to disable 21 | #unmarkComment: false 22 | ## Comment to post when closing a stale Issue or Pull Request. Set to `false` to disable 23 | #closeComment: false 24 | ## Limit the number of actions per hour, from 1-30. Default is 30 25 | #limitPerRun: 30 26 | ## Limit to only `issues` or `pulls` 27 | ## only: issues 28 | ## 29 | ## Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': 30 | ## pulls: 31 | ## daysUntilStale: 30 32 | ## markComment: > 33 | ## This pull request has been automatically marked as stale because it has not had 34 | ## recent activity. It will be closed if no further activity occurs. Thank you 35 | ## for your contributions. 36 | ## issues: 37 | ## exemptLabels: 38 | ## - confirmed -------------------------------------------------------------------------------- /.github/workflows/mvn.yaml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven 5 | 6 | on: [push, pull_request] 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | 15 | - name: Set up JDK 1.8 16 | uses: actions/setup-java@v1 17 | with: 18 | java-version: 1.8 19 | 20 | - uses: actions/cache@v1 21 | with: 22 | path: ~/.m2/repository 23 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} 24 | restore-keys: | 25 | ${{ runner.os }}-maven- 26 | 27 | - name: Build with Maven 28 | run: mvn -B clean install -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | deps/ 2 | .DS_Store 3 | **/galaxy/ 4 | 5 | ### Eclipse template 6 | .metadata 7 | bin/ 8 | tmp/ 9 | *.tmp 10 | *.bak 11 | *.swp 12 | *~.nib 13 | local.properties 14 | .settings/ 15 | .loadpath 16 | .recommenders 17 | 18 | ### JetBrains template 19 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 20 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 21 | 22 | # User-specific stuff: 23 | .idea/ 24 | .idea/**/workspace.xml 25 | .idea/**/tasks.xml 26 | .idea/dictionaries 27 | 28 | # Sensitive or high-churn files: 29 | .idea/**/dataSources/ 30 | .idea/**/dataSources.ids 31 | .idea/**/dataSources.xml 32 | .idea/**/dataSources.local.xml 33 | .idea/**/sqlDataSources.xml 34 | .idea/**/dynamic.xml 35 | .idea/**/uiDesigner.xml 36 | 37 | ## File-based project format: 38 | *.iws 39 | *.iml 40 | 41 | ### Maven template 42 | target/ 43 | pom.xml.tag 44 | pom.xml.releaseBackup 45 | pom.xml.versionsBackup 46 | pom.xml.next 47 | release.properties 48 | dependency-reduced-pom.xml 49 | buildNumber.properties 50 | .mvn/timing.properties 51 | .classpath 52 | .project 53 | -------------------------------------------------------------------------------- /.openshift/templates/build-pipelines.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # https://github.com/redhat-cop/openshift-templates/blob/v1.4.14/jenkins-pipelines/jenkins-pipeline-template-no-ocp-triggers.yml 3 | apiVersion: v1 4 | kind: List 5 | items: 6 | {% for current in jenkins_test_files %} 7 | {% set jenkinsfile = current.path | basename %} 8 | - apiVersion: v1 9 | kind: BuildConfig 10 | metadata: 11 | labels: 12 | build: "{{ jenkinsfile }}" 13 | name: "{{ jenkinsfile }}" 14 | type: "pipeline" 15 | name: "{{ jenkinsfile | lower }}" 16 | spec: 17 | runPolicy: "Serial" 18 | source: 19 | contextDir: "test" 20 | git: 21 | ref: "{{ repo_ref }}" 22 | uri: "{{ repository_url }}" 23 | type: Git 24 | strategy: 25 | jenkinsPipelineStrategy: 26 | jenkinsfile: |- 27 | {{ current.content | indent(10, True) }} 28 | type: JenkinsPipeline 29 | {% endfor %} -------------------------------------------------------------------------------- /.travis/check-missing.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Checking for missing docs and tests" 4 | 5 | find vars -type f -name "*.groovy" -exec bash -c '[ -f vars/$(basename {} .groovy).txt ] || echo "Missing vars/$(basename {} .groovy).txt" >> fail.tmp' \; 6 | find vars -type f -name "*.groovy" ! -path "vars/imageMirror.groovy" -exec bash -c '[ -f test/Jenkinsfile-$(basename {} .groovy) ] || echo "Missing test/Jenkinsfile-$(basename {} .groovy)" >> fail.tmp' \; 7 | 8 | if [ -f fail.tmp ]; then 9 | echo "Found:" 10 | 11 | cat fail.tmp 12 | exit 1 13 | fi -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | reviewers: 4 | - etsauer 5 | - oybed 6 | - pabrahamsson 7 | - sabre1041 8 | - springdo 9 | approvers: 10 | - etsauer 11 | - garethahealy 12 | - oybed 13 | - pabrahamsson 14 | - sabre1041 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Java CI with Maven](https://github.com/redhat-cop/pipeline-library/workflows/Java%20CI%20with%20Maven/badge.svg) 2 | [![License](https://img.shields.io/hexpm/l/plug.svg?maxAge=2592000)]() 3 | 4 | # OpenShift Pipeline Library 5 | 6 | ## What This Repo Is 7 | 8 | This is a shared library of Jenkins Pipeline functionality we've developed and use frequently within the CoP. This repo can be imported into a jenkins server (following [this doc](https://jenkins.io/doc/book/pipeline/shared-libraries/#using-libraries)) and used to add functionality to Pipeline scripts. 9 | 10 | You can include this repo in your Jenkins Pipeline by defining following at beginning of your Jenkinsfile: 11 | 12 | ``` 13 | library identifier: "pipeline-library@master", retriever: modernSCM( 14 | [$class: "GitSCMSource", 15 | remote: "https://github.com/redhat-cop/pipeline-library.git"]) 16 | ``` 17 | 18 | Included in this library: 19 | 20 | * [org.redhatcop.util.Notifications](./src/org/redhatcop/util/Notifications.txt) - A build status notification system for chat-ops 21 | * [vars](./vars/) - Many small Jenkins functions for OpenShift 22 | 23 | 24 | Please see https://github.com/redhat-cop/container-pipelines or https://github.com/redhat-cop/containers-quickstarts for related content. 25 | 26 | ## Other Resources 27 | 28 | * https://jenkins.io/doc/book/pipeline/shared-libraries/ 29 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | ## Automated 3 | We currently use openshift-applier for deployment and test as per: 4 | 5 | ```bash 6 | ./_test/setup.sh applier && ./_test/setup.sh test 7 | ``` 8 | 9 | The scripts also support passing in the project, git repo and git branch as per: 10 | ```bash 11 | ./_test/setup.sh applier pipelinelib-testing garethahealy/pipeline-library master && ./_test/setup.sh test 12 | ``` 13 | 14 | ## Manual 15 | The below steps can be used to test each pipeline lib method. If you are testing a PR or your local branch, you need to change the following: 16 | - test/create-pipeline-library.groovy - to point to your git repo, instead of https://github.com/redhat-cop/pipeline-library.git 17 | - test/Jenkinsfile-* - the branch for the Jenkinsfile needs to match the branch of the changes 18 | 19 | For convenience, the below commands can automate the above. NOTE: the below presumes the remote url is https based. 20 | ```bash 21 | sed -i "s|https://github.com/redhat-cop/pipeline-library.git|$(git config --get remote.origin.url)|g" test/create-pipeline-library.groovy 22 | find test -type f -name "Jenkinsfile*" -exec sed -i "s/pipeline-library@master/pipeline-library@$(git rev-parse --abbrev-ref HEAD)/g" {} \; 23 | ``` 24 | 25 | ### Create projects 26 | ```bash 27 | oc new-project pipelinelib-testing 28 | ``` 29 | 30 | ### Import additional image streams for slaves 31 | ```bash 32 | oc import-image jenkins-slave-ansible --from=quay.io/redhat-cop/jenkins-slave-ansible:v1.15 --confirm 33 | oc label imagestream jenkins-slave-ansible role=jenkins-slave 34 | 35 | oc import-image jenkins-slave-image-mgmt --from=siamaksade/jenkins-slave-skopeo-centos7 --confirm 36 | oc label imagestream jenkins-slave-image-mgmt role=jenkins-slave 37 | ``` 38 | 39 | // NOTE: The below image is not released into quay yet, thats why we are using the above 40 | // oc import-image jenkins-slave-image-mgmt --from=quay.io/redhat-cop/jenkins-slave-image-mgmt --confirm 41 | // oc label imagestream jenkins-slave-image-mgmt role=jenkins-slave 42 | 43 | ### Create BuildConfigs 44 | ```bash 45 | find test -type f -name "Jenkinsfile-*" -exec bash -c '\ 46 | oc process -f https://raw.githubusercontent.com/redhat-cop/openshift-templates/v1.4.9/jenkins-pipelines/jenkins-pipeline-template-no-ocp-triggers.yml \ 47 | -p NAME=$(basename {} | tr 'A-Z' 'a-z') \ 48 | -p PIPELINE_FILENAME=$(basename {}) \ 49 | -p PIPELINE_CONTEXT_DIR=test \ 50 | -p PIPELINE_SOURCE_REPOSITORY_URL=$(git config --get remote.origin.url) \ 51 | -p PIPELINE_SOURCE_REPOSITORY_REF=$(git rev-parse --abbrev-ref HEAD)' \; | oc apply -f - 52 | ``` 53 | 54 | ### Deploy Jenkins 55 | ```bash 56 | oc process -p MEMORY_REQUEST=2Gi -p MEMORY_LIMIT=3Gi -f https://raw.githubusercontent.com/redhat-cop/openshift-templates/v1.4.9/jenkins/jenkins-persistent-template.yml | oc apply -f - 57 | oc patch dc jenkins -p '{"apiVersion":"apps.openshift.io/v1","kind":"DeploymentConfig","metadata":{"name":"jenkins"},"spec":{"template":{"spec":{"containers":[{"name":"jenkins","resources":{"limits":{"cpu":"3"},"requests":{"cpu":"2"}}}]}}}}' 58 | oc rollout status dc/jenkins --watch=true 59 | ``` 60 | 61 | ### Create global pipeline lib 62 | ```bash 63 | curl --header "Authorization: Bearer $(oc whoami --show-token)" --data-urlencode "script=$(< test/create-pipeline-library.groovy)" https://$(oc get route jenkins -o jsonpath={.spec.host})/scriptText 64 | ``` 65 | 66 | ### Install plugins 67 | ```bash 68 | curl -X POST -d "" --header "Authorization: Bearer $(oc whoami --show-token)" --header "Content-Type: text/xml" https://$(oc get route jenkins -o jsonpath={.spec.host})/pluginManager/installNecessaryPlugins 69 | curl -X POST -d "" --header "Authorization: Bearer $(oc whoami --show-token)" --header "Content-Type: text/xml" https://$(oc get route jenkins -o jsonpath={.spec.host})/pluginManager/installNecessaryPlugins 70 | ``` 71 | 72 | ### Create username/password and dockercfg secrets 73 | ```bash 74 | oc create secret generic my-token --from-literal=username=openshift1 --from-literal=password=$(oc whoami --show-token) 75 | oc label secret my-token credential.sync.jenkins.openshift.io=true 76 | 77 | oc create secret generic --from-literal=registry=$(oc get is jenkins -n openshift -o jsonpath={.status.dockerImageRepository} | cut -d '/' -f1 | xargs) --from-literal=username=openshift1 --from-literal=token=$(oc whoami --show-token) local-registry-generic 78 | oc secrets link --for=mount jenkins local-registry-generic 79 | 80 | oc create secret docker-registry --docker-server=$(oc get is jenkins -n openshift -o jsonpath={.status.dockerImageRepository} | cut -d '/' -f1 | xargs) --docker-username=openshift1 --docker-password=$(oc whoami --show-token) --docker-email=unused local-registry 81 | oc secrets link --for=mount jenkins local-registry 82 | ``` 83 | 84 | ### Start all BuildConfigs 85 | ```bash 86 | find test -type f -name "Jenkinsfile-*" -exec bash -c 'oc start-build $(basename {} | tr 'A-Z' 'a-z')-pipeline' \; 87 | ``` 88 | 89 | ### Cleanup 90 | ```bash 91 | oc delete project pipelinelib-testing{,-promotion-testing,-build-s2i-executable,-sonarqube} 92 | ``` -------------------------------------------------------------------------------- /_test/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | trap "exit 1" TERM 3 | export TOP_PID=$$ 4 | NAMESPACE="${2:-pipelinelib-testing}" 5 | CI_REPO_SLUG="${3:-redhat-cop/pipeline-library}" 6 | CI_BRANCH="${4:-master}" 7 | CLONE_DIR="/tmp/${CI_REPO_SLUG}/${CI_BRANCH}" 8 | 9 | clone() { 10 | rm -rf ${CLONE_DIR} 11 | git clone -b ${CI_BRANCH} "https://github.com/${CI_REPO_SLUG}.git" ${CLONE_DIR} 12 | } 13 | 14 | applier() { 15 | pushd ${CLONE_DIR} 16 | 17 | echo "${CI_BRANCH}" 18 | echo "${CI_REPO_SLUG}" 19 | 20 | sed -i "7s|.*|- src: https://github.com/${CI_REPO_SLUG}.git|" galaxy-requirements.yml 21 | sed -i "9s/.*/ version: ${CI_BRANCH}/g" galaxy-requirements.yml 22 | 23 | ansible-galaxy install -r requirements.yml -p galaxy --force 24 | ansible-playbook -i .applier/ galaxy/openshift-applier/playbooks/openshift-cluster-seed.yml \ 25 | -e namespace=${NAMESPACE} \ 26 | -e repo_ref=${CI_BRANCH} \ 27 | -e repository_url=https://github.com/${CI_REPO_SLUG}.git \ 28 | -e clone_dir=${CLONE_DIR} \ 29 | -e oc_token="$(oc whoami --show-token)" \ 30 | -e internal_registry_url="$(oc get is jenkins -n openshift -o jsonpath={.status.dockerImageRepository})" 31 | 32 | popd 33 | } 34 | 35 | test() { 36 | # Make sure we're logged in, and we've found at least one build to test. 37 | oc status > /dev/null || echo "Please log in before running tests." || exit 1 38 | if [ $(oc get bc -l type=pipeline -n ${NAMESPACE} --no-headers | grep -c .) -lt 1 ]; then 39 | echo "Did not find any builds, make sure you've passed the proper arguments." 40 | exit 1 41 | fi 42 | 43 | echo "Ensure all Builds are executed..." 44 | for pipeline in $(oc get bc -l type=pipeline -n ${NAMESPACE} -o jsonpath='{.items[*].metadata.name}'); do 45 | oc start-build ${pipeline} -n ${NAMESPACE} 46 | done 47 | 48 | echo "Waiting for all builds to start..." 49 | while [[ "$(get_build_phases "New")" -ne 0 || $(get_build_phases "Pending") -ne 0 ]]; do 50 | echo -ne "New Builds: $(get_build_phases "New"), Pending Builds: $(get_build_phases "Pending")$([ "$TRAVIS" != "true" ] && echo "\r" || echo "\n")" 51 | sleep 1 52 | done 53 | 54 | echo "Waiting for all builds to complete..." 55 | while [ $(get_build_phases "Running") -ne 0 ]; do 56 | echo -ne "Running Builds: $(get_build_phases "Running")$([ "$TRAVIS" != "true" ] && echo "\r" || echo "\n")" 57 | sleep 1 58 | done 59 | 60 | download_jenkins_logs_for_failed "$(ls --ignore=*fail* ${CLONE_DIR}/test/ | grep "Jenkinsfile" | tr 'A-Z' 'a-z' | xargs)" "Complete" 61 | download_jenkins_logs_for_failed "$(ls ${CLONE_DIR}/test/Jenkinsfile-*-fail-* | xargs -n 1 basename | tr 'A-Z' 'a-z' | xargs)" "Failed" 62 | 63 | logcount=$(ls *.log | wc -l) 64 | if [[ $logcount -gt 0 ]]; then 65 | echo "Tests Completed Unsuccessfully. See logs above." 66 | exit 1 67 | else 68 | echo "Tests Completed Successfully!" 69 | fi 70 | } 71 | 72 | get_build_phases() { 73 | phase=$1 74 | result=$(retry 5 oc get builds -l type=pipeline -o jsonpath="{.items[?(@.status.phase==\"${phase}\")].metadata.name}" -n $NAMESPACE) || kill -s TERM $TOP_PID 75 | echo ${result} | wc -w 76 | } 77 | 78 | get_build_phase_for() { 79 | name=$1 80 | result=$(retry 5 oc get builds ${name} -o jsonpath="{.status.phase}" -n $NAMESPACE) || kill -s TERM $TOP_PID 81 | echo ${result} 82 | } 83 | 84 | get_buildnumber_for() { 85 | name=$1 86 | result=$(retry 5 oc get buildconfigs ${name} -o jsonpath="{.status.lastVersion}" -n $NAMESPACE) || kill -s TERM $TOP_PID 87 | echo ${result} 88 | } 89 | 90 | download_jenkins_logs_for_failed() { 91 | jobs=$1 92 | expectedphase=$2 93 | 94 | echo "Checking jobs which should have an expected phase of ${expectedphase}..." 95 | 96 | jenkins_url=$(oc get route jenkins -n ${NAMESPACE} -o jsonpath='{ .spec.host }') 97 | token=$(oc whoami --show-token) 98 | 99 | for pipeline in ${jobs}; do 100 | build_number=$(get_buildnumber_for ${pipeline}) 101 | build="${pipeline}-${build_number}" 102 | 103 | phase=$(get_build_phase_for ${build}) 104 | if [[ "${expectedphase}" != "${phase}" ]]; then 105 | echo "" 106 | echo "Downloading Jenkins logs for ${build} as phase (${phase}) does not match expected (${expectedphase})..." 107 | curl -k -sS -H "Authorization: Bearer ${token}" "https://${jenkins_url}/blue/rest/organizations/jenkins/pipelines/${NAMESPACE}/pipelines/${NAMESPACE}-${pipeline}/runs/${build_number}/log/?start=0&download=true" -o "${pipeline}.log" 108 | 109 | echo "## START LOGS: ${build}" 110 | cat "${pipeline}.log" 111 | echo "## END LOGS: ${build}" 112 | fi 113 | done 114 | } 115 | 116 | function retry { 117 | local retries=$1 118 | shift 119 | 120 | local count=0 121 | until "$@"; do 122 | exit=$? 123 | wait=$((2 ** $count)) 124 | count=$(($count + 1)) 125 | if [ $count -lt $retries ]; then 126 | echo "Retry $count/$retries exited $exit, retrying in $wait seconds..." 127 | sleep $wait 128 | else 129 | echo "Retry $count/$retries exited $exit, no more retries left." 130 | return $exit 131 | fi 132 | done 133 | return 0 134 | } 135 | 136 | # Process arguments 137 | case $1 in 138 | applier) 139 | clone 140 | applier 141 | ;; 142 | test) 143 | test 144 | ;; 145 | *) 146 | echo "Not an option" 147 | exit 1 148 | esac 149 | -------------------------------------------------------------------------------- /galaxy-requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - src: https://github.com/redhat-cop/casl-ansible.git 3 | scm: git 4 | version: v3.11.6 5 | name: casl-ansible 6 | 7 | - src: https://github.com/redhat-cop/pipeline-library.git 8 | scm: git 9 | version: master 10 | name: pipeline-library 11 | -------------------------------------------------------------------------------- /jenkins-s2i/configuration/org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | cop-library 6 | 7 | 8 | a568a19b-8f41-478b-b80f-28eeee157e05 9 | SAME 10 | etsauer 11 | pipeline-library 12 | * 13 | 14 | true 15 | true 16 | false 17 | false 18 | true 19 | false 20 | 21 | 22 | shared-lib 23 | false 24 | true 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /jenkins-s2i/jenkins-s2i.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Template 4 | labels: 5 | template: jenkins2-s2i 6 | group: jenkins2-s2i 7 | metadata: 8 | annotations: 9 | description: Creates the Jenkins2 image for CD Pipeline builds 10 | iconClass: icon-jenkins 11 | tags: instant-app,jenkins,cicd 12 | name: jenkins2-s2i 13 | parameters: 14 | - description: Custom Jenkins for CD Pipeline SCM location 15 | displayName: CD Jenkins Pipeline SCM URL 16 | name: JENKINS_GIT_URL 17 | required: true 18 | - description: Custom Jenkins for CD Pipeline SCM branch 19 | displayName: CD Jenkins Pipeline SCM branch 20 | name: JENKINS_GIT_BRANCH 21 | required: true 22 | value: 'master' 23 | - description: Context Directory inside of the Git repo 24 | displayName: Context Directory 25 | name: JENKINS_GIT_CONTEXT_DIR 26 | value: '' 27 | objects: 28 | # Jenkins2 29 | - apiVersion: v1 30 | kind: ImageStream 31 | metadata: 32 | labels: 33 | app: jenkins2-s2i 34 | template: jenkins2-s2i 35 | name: jenkins2-s2i 36 | - apiVersion: v1 37 | kind: BuildConfig 38 | metadata: 39 | labels: 40 | application: jenkins2-s2i 41 | template: jenkins2-s2i 42 | name: jenkins2-s2i 43 | spec: 44 | triggers: 45 | - type: "ConfigChange" 46 | output: 47 | to: 48 | kind: ImageStreamTag 49 | name: jenkins2-s2i:latest 50 | source: 51 | type: Git 52 | git: 53 | uri: "${JENKINS_GIT_URL}" 54 | ref: "${JENKINS_GIT_BRANCH}" 55 | contextDir: ${JENKINS_GIT_CONTEXT_DIR} 56 | strategy: 57 | sourceStrategy: 58 | from: 59 | kind: ImageStreamTag 60 | name: jenkins:latest 61 | namespace: openshift 62 | type: Source 63 | -------------------------------------------------------------------------------- /jenkins-s2i/plugins.txt: -------------------------------------------------------------------------------- 1 | http_request:1.8.21 2 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | org.redhatcop 7 | pipeline-library 8 | 1.7.0-SNAPSHOT 9 | 10 | 11 | UTF-8 12 | UTF-8 13 | 1.8 14 | ${java.version} 15 | ${java.version} 16 | 3.6.1 17 | 2.4.9 18 | 1.6.1 19 | 2.5.3 20 | 21 | 22 | 23 | scm:git:ssh://git@github.com:redhat-cop/pipeline-library.git 24 | scm:git:ssh://git@github.com:redhat-cop/pipeline-library.git 25 | https://github.com/redhat-cop/pipeline-library.git 26 | HEAD 27 | 28 | 29 | 30 | 31 | org.codehaus.groovy 32 | groovy-all 33 | 2.5.0 34 | pom 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.codehaus.gmavenplus 42 | gmavenplus-plugin 43 | 1.6.1 44 | 45 | 46 | 47 | addSources 48 | addTestSources 49 | compile 50 | compileTests 51 | 52 | 53 | 54 | 55 | true 56 | 57 | 58 | ${project.basedir}/src 59 | 60 | **/*.groovy 61 | 62 | 63 | 64 | ${project.basedir}/vars 65 | 66 | **/*.groovy 67 | 68 | 69 | 70 | 71 | 72 | ${project.basedir}/test/groovy 73 | 74 | **/*.groovy 75 | 76 | 77 | 78 | 79 | 80 | 81 | org.apache.maven.plugins 82 | maven-compiler-plugin 83 | 3.8.1 84 | 85 | 86 | org.apache.maven.plugins 87 | maven-source-plugin 88 | 2.4 89 | 90 | 91 | attach-sources 92 | 93 | jar-no-fork 94 | test-jar-no-fork 95 | 96 | 97 | 98 | 99 | 100 | exec-maven-plugin 101 | org.codehaus.mojo 102 | 1.6.0 103 | 104 | 105 | test-compile 106 | 107 | exec 108 | 109 | 110 | ${basedir}/.travis/check-missing.sh 111 | 112 | 113 | 114 | 115 | 116 | org.apache.maven.plugins 117 | maven-release-plugin 118 | ${maven.release.plugin.version} 119 | 120 | 121 | 122 | 123 | 124 | 125 | repo.jenkins-ci.org 126 | http://repo.jenkins-ci.org/public/ 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /requirements.yml: -------------------------------------------------------------------------------- 1 | # This is the Ansible Galaxy requirements file to pull in the correct roles 2 | # to support the operation of CASL provisioning/runs. 3 | 4 | # From 'openshift-applier' 5 | - name: openshift-applier 6 | scm: git 7 | src: https://github.com/redhat-cop/openshift-applier 8 | version: v2.1.2 9 | -------------------------------------------------------------------------------- /roles/configure-jenkins/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | delay: 5 4 | retries: 3 -------------------------------------------------------------------------------- /roles/configure-jenkins/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: "Lookup route url for jenkins" 4 | shell: "oc get route jenkins -n {{ namespace }} -o jsonpath='{ .spec.host }'" 5 | register: url 6 | 7 | - name: Create pipeline library 8 | uri: 9 | url: "https://{{ url.stdout }}/scriptText" 10 | method: POST 11 | body: "{{ 'script=' ~ lookup('file', '{{ clone_dir }}/test/create-pipeline-library.groovy') | urlencode }}" 12 | headers: 13 | Authorization: "Bearer {{ oc_token }}" 14 | validate_certs: no 15 | retries: "{{ retries|int }}" 16 | delay: "{{ delay|int }}" 17 | register: createlib_result 18 | until: createlib_result is not failed 19 | 20 | - name: Install plugins 21 | uri: 22 | url: "https://{{ url.stdout }}/pluginManager/installNecessaryPlugins" 23 | method: POST 24 | status_code: 25 | - 200 26 | - 302 27 | body: "" 28 | headers: 29 | Authorization: "Bearer {{ oc_token }}" 30 | Content-Type: text/xml 31 | validate_certs: no 32 | retries: "{{ retries|int }}" 33 | delay: "{{ delay|int }}" 34 | register: plugininstall_result 35 | until: plugininstall_result is not failed 36 | with_items: 37 | - sonar@2.10 38 | - openshift-client@1.0.32 39 | -------------------------------------------------------------------------------- /roles/link-secret/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Link secret to service account for mount 4 | command: "oc secrets link --for=mount {{ sa_name }} {{ secret_name }} -n {{ namespace }}" -------------------------------------------------------------------------------- /roles/process-tests/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | delay: 5 4 | retries: 3 -------------------------------------------------------------------------------- /roles/process-tests/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Update pipeline-library with correct git branch 4 | replace: 5 | path: "{{ clone_dir }}/test/create-pipeline-library.groovy" 6 | regexp: "https://github.com/redhat-cop/pipeline-library.git" 7 | replace: "{{ repository_url }}" 8 | 9 | - name: Update Jenkinsfile tests with correct git branch 10 | replace: 11 | path: "{{ item }}" 12 | regexp: "pipeline-library@master" 13 | replace: "pipeline-library@{{ repo_ref }}" 14 | with_fileglob: "{{ clone_dir }}/test/Jenkinsfile*" 15 | 16 | - name: Update Jenkinsfile tests with correct Jenkins credential name 17 | replace: 18 | path: "{{ item }}" 19 | regexp: "pipelinelib-testing-my-token" 20 | replace: "{{ namespace }}-my-token" 21 | with_fileglob: "{{ clone_dir }}/test/Jenkinsfile*" 22 | 23 | - name: Update Sonar Jenkinsfile with correct git repo/branch 24 | replace: 25 | path: "{{ item }}" 26 | regexp: "git clone https://github.com/redhat-cop/pipeline-library.git" 27 | replace: "git clone {{ repository_url }}; pushd pipeline-library; git checkout {{ repo_ref }}; popd" 28 | with_fileglob: "{{ clone_dir }}/test/Jenkinsfile-sonarqubeStaticAnalysis" 29 | 30 | - name: Load Jenkinsfile content into memory 31 | set_fact: 32 | jenkins_test_files: "{{ jenkins_test_files|default([]) + [{'path': item, 'content': lookup('file', '{{ item }}') }] }}" 33 | with_items: "{{ lookup('fileglob', '{{ clone_dir }}/test/Jenkinsfile-*', wantlist=true) }}" 34 | -------------------------------------------------------------------------------- /src/org/redhatcop/util/Notifications.txt: -------------------------------------------------------------------------------- 1 | # Notifications library 2 | 3 | Sends notifications on build status to rocketChat. 4 | 5 | This requires you to set up an [Incoming Webhook](https://rocket.chat/docs/administrator-guides/integrations/) in RocketChat. 6 | 7 | Sample usage: 8 | 9 | ``` 10 | @Library('cop-library') _ 11 | 12 | def rocketchat_url = 'https://rocket.example.com/hooks/[integration_id]/[integration_secret]' 13 | def n = new org.redhatcop.util.notifications() 14 | 15 | n.notifyBuild('STARTED', rocketchat_url) 16 | ``` 17 | -------------------------------------------------------------------------------- /src/org/redhatcop/util/notifications.groovy: -------------------------------------------------------------------------------- 1 | package org.redhatcop.util; 2 | 3 | def rocketChatSend(String url, String text, String emoji) { 4 | echo "Sending rocketchat message: {\"username\":\"Jenkins\",\"icon_emoji\":\"${emoji}\",\"text\": \"${text}\"}" 5 | 6 | // POST Message 7 | def response = httpRequest url: url, 8 | httpMode: 'POST', 9 | requestBody: "{\"username\":\"Jenkins\",\"icon_emoji\":\"${emoji}\",\"text\": \"${text}\"}" 10 | } 11 | 12 | def notifyBuild(String buildStatus = 'STARTED', String rocketChatUrl) { 13 | // build status of null means successful 14 | buildStatus = buildStatus ?: 'SUCCESSFUL' 15 | 16 | // Default values 17 | def colorName = 'RED' 18 | def colorCode = '#FF0000' 19 | def subject = "${buildStatus}: Job ${env.JOB_NAME} [${env.BUILD_NUMBER}]" 20 | def summary = "${subject} (${env.BUILD_URL})" 21 | def details = """

STARTED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]':

22 |

Check console output at "${env.JOB_NAME} [${env.BUILD_NUMBER}]"

""" 23 | 24 | // Override default values based on build status 25 | if (buildStatus == 'STARTED') { 26 | color = 'YELLOW' 27 | colorCode = '#FFFF00' 28 | status_icon = ':soon:' 29 | } else if (buildStatus == 'SUCCESSFUL') { 30 | color = 'GREEN' 31 | colorCode = '#00FF00' 32 | status_icon = ':white_check_mark:' 33 | } else { 34 | color = 'RED' 35 | colorCode = '#FF0000' 36 | status_icon = ':negative_squared_cross_mark:' 37 | } 38 | 39 | // Send notifications 40 | rocketChatSend(rocketChatUrl, summary, status_icon) 41 | echo "Sending RocketChat Notification: ${buildStatus}" 42 | 43 | } 44 | -------------------------------------------------------------------------------- /test/Jenkinsfile-applier: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def applierNamespace 5 | def testingNamespace 6 | 7 | node("jenkins-slave-ansible") { 8 | stage("SETUP: Clone containers-quickstarts") { 9 | testingNamespace = sh(script: "cat /var/run/secrets/kubernetes.io/serviceaccount/namespace", returnStdout: true) 10 | applierNamespace = testingNamespace + '-build-s2i-executable' 11 | 12 | sh "git clone https://github.com/redhat-cop/containers-quickstarts.git" 13 | 14 | openshift.logLevel(10) 15 | } 16 | 17 | stage("TEST: Run applier for 'build-s2i-executable'") { 18 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 19 | applier([ 20 | inventoryPath : ".applier/hosts", 21 | requirementsPath: "requirements.yml", 22 | ansibleRootDir : "${WORKSPACE}/containers-quickstarts/build-s2i-executable", 23 | applierPlaybook : "galaxy/openshift-applier/playbooks/openshift-cluster-seed.yml", 24 | playbookAdditionalArgs: "-e namespace=${applierNamespace}", 25 | clusterAPI : "https://kubernetes.default.svc", 26 | clusterToken : "${TOKEN}" 27 | ]) 28 | } 29 | } 30 | 31 | stage("ASSERT") { 32 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 33 | openshift.withCluster("https://kubernetes.default.svc", "${TOKEN}") { 34 | openshift.withProject(applierNamespace) { 35 | def buildConfig = openshift.selector("bc", "build-s2i-executable") 36 | assert buildConfig.exists() 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/Jenkinsfile-applier-fail-missingsecret: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("jenkins-slave-ansible") { 5 | stage("SETUP: Set logging to verbose") { 6 | openshift.logLevel(10) 7 | } 8 | 9 | stage("TEST: Run applier for 'build-s2i-executable' and fail") { 10 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 11 | applier([ 12 | inventoryPath : ".applier/hosts", 13 | requirementsPath: "requirements.yml", 14 | ansibleRootDir : "${WORKSPACE}/containers-quickstarts/build-s2i-executable", 15 | applierPlaybook : "galaxy/openshift-applier/playbooks/openshift-cluster-seed.yml", 16 | secretName : "doesnt-exist", 17 | ]) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/Jenkinsfile-applyTemplate: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create deployment files") { 6 | sh "curl -L -o cakephp-mysql.json https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json" 7 | 8 | openshift.logLevel(10) 9 | } 10 | 11 | stage("TEST: Can deploy via local file") { 12 | applyTemplate([ 13 | templateFile : "cakephp-mysql.json", 14 | loglevel: 3 15 | ]) 16 | } 17 | 18 | stage("ASSERT") { 19 | openshift.withCluster() { 20 | openshift.withProject() { 21 | def deployment = openshift.selector("dc", "cakephp-mysql-example") 22 | assert deployment.exists() 23 | 24 | //Scale down afterwards to lower quotas 25 | deployment.scale("--replicas=0") 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-applyTemplate-viahttp: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create deployment files") { 6 | def params = """ 7 | NAME=applytemplate-http 8 | DATABASE_SERVICE_NAME=applytemplate-http 9 | """ 10 | 11 | writeFile file: "params.txt", text: params 12 | 13 | openshift.logLevel(10) 14 | } 15 | 16 | stage("TEST: Can deploy via http") { 17 | applyTemplate([ 18 | templateFile : "https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json", 19 | parameterFile: "params.txt" 20 | ]) 21 | } 22 | 23 | stage("ASSERT") { 24 | openshift.withCluster() { 25 | openshift.withProject() { 26 | def deployment = openshift.selector("dc", "applytemplate-http") 27 | assert deployment.exists() 28 | 29 | //Scale down afterwards to lower quotas 30 | deployment.scale("--replicas=0") 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-applyTemplate-withparams: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create deployment files") { 6 | def params = """ 7 | NAME=applytemplate 8 | DATABASE_SERVICE_NAME=applytemplate 9 | """ 10 | 11 | writeFile file: "params.txt", text: params 12 | 13 | sh "curl -L -o cakephp-mysql.json https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json" 14 | 15 | openshift.logLevel(10) 16 | } 17 | 18 | stage("TEST: Can deploy via local file") { 19 | applyTemplate([ 20 | templateFile : "cakephp-mysql.json", 21 | parameterFile: "params.txt" 22 | ]) 23 | } 24 | 25 | stage("ASSERT") { 26 | openshift.withCluster() { 27 | openshift.withProject() { 28 | def deployment = openshift.selector("dc", "applytemplate") 29 | assert deployment.exists() 30 | 31 | //Scale down afterwards to lower quotas 32 | deployment.scale("--replicas=0") 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-binaryBuild: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def firstBuildVersion 5 | 6 | node("maven") { 7 | stage("SETUP: Create build files") { 8 | openshift.withCluster() { 9 | openshift.withProject() { 10 | def buildConfig = openshift.selector("bc", "sample-build-binary") 11 | if (!buildConfig.exists()) { 12 | openshift.apply("-f", "https://raw.githubusercontent.com/openshift/origin/v3.11.0/test/extended/testdata/builds/test-build.yaml") 13 | } 14 | 15 | def buildConfigObject = buildConfig.object() 16 | firstBuildVersion = buildConfigObject.status?.lastVersion 17 | } 18 | } 19 | 20 | dir("build") { 21 | dockerfile = """ 22 | FROM scratch 23 | COPY README.md / 24 | """ 25 | 26 | writeFile file: "README.md", text: "Test file" 27 | writeFile file: "Dockerfile", text: dockerfile 28 | } 29 | 30 | openshift.logLevel(10) 31 | } 32 | 33 | stage("TEST: Can build using from-file") { 34 | binaryBuild([ 35 | buildConfigName: "sample-build-binary", 36 | buildFromFlag : "--from-dir", 37 | buildFromPath : "${WORKSPACE}/build/" 38 | ]) 39 | } 40 | 41 | stage("ASSERT") { 42 | openshift.withCluster() { 43 | openshift.withProject() { 44 | def build = openshift.selector("build", "sample-build-binary-${firstBuildVersion + 1}") 45 | assert build.exists() 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-binaryBuild-fail-missingbuildconfig: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create build files") { 6 | dir("build") { 7 | dockerfile = """ 8 | FROM scratch 9 | COPY README.md / 10 | """ 11 | 12 | writeFile file: "README.md", text: "Test file" 13 | writeFile file: "Dockerfile", text: dockerfile 14 | } 15 | 16 | openshift.logLevel(10) 17 | } 18 | 19 | stage("TEST: Can build using from-file and fail") { 20 | binaryBuild([ 21 | buildConfigName: "doesnt-exist", 22 | buildFromFlag : "--from-dir", 23 | buildFromPath : "${WORKSPACE}/build/" 24 | ]) 25 | } 26 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-buildAndTag: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def dockerRegistry 5 | def firstBuildVersion 6 | def testingNamespace 7 | 8 | podTemplate(label: "jnlp", cloud: "openshift", inheritFrom: "jenkins-slave-image-mgmt", volumes: [ 9 | secretVolume(mountPath: "/var/run/secrets/kubernetes.io/dockerconfigjson", secretName: "local-registry") 10 | ]) { 11 | node("jnlp") { 12 | stage("SETUP: Create build files") { 13 | testingNamespace = sh(script: "cat /var/run/secrets/kubernetes.io/serviceaccount/namespace", returnStdout: true) 14 | 15 | openshift.withCluster() { 16 | openshift.withProject("openshift") { 17 | def imageStream = openshift.selector("is", "jenkins") 18 | dockerRegistry = sh(returnStdout: true, script: "echo '${imageStream.object().status.dockerImageRepository}' | cut -d '/' -f1").trim() 19 | } 20 | } 21 | 22 | openshift.withCluster() { 23 | openshift.withProject() { 24 | def buildConfig = openshift.selector("bc", "sample-build") 25 | if (!buildConfig.exists()) { 26 | openshift.apply("-f", "https://raw.githubusercontent.com/openshift/origin/v3.11.0/test/extended/testdata/builds/test-build.yaml") 27 | } 28 | 29 | try { 30 | def patch = '{"apiVersion":"build.openshift.io/v1","kind":"BuildConfig","metadata":{"name":"sample-build"},"spec":{"output":{"to":{"kind":"ImageStreamTag","name":"sample-build:latest"}}}}' 31 | openshift.patch(buildConfig.object(), "'" + patch + "'") 32 | } catch(ex) { 33 | echo "Ignoring patch error: ${ex}" 34 | } 35 | 36 | def buildConfigObject = buildConfig.object() 37 | firstBuildVersion = buildConfigObject.status?.lastVersion 38 | 39 | def imageStream = openshift.selector("is", "sample-build") 40 | if (!imageStream.exists()) { 41 | openshift.create("imagestream", "sample-build") 42 | } 43 | } 44 | } 45 | 46 | dir("target") { 47 | writeFile file: "HelloWorld.txt", text: "HelloWorld" 48 | } 49 | 50 | openshift.logLevel(10) 51 | } 52 | 53 | stage("TEST: Can build and tag") { 54 | buildAndTag([ 55 | imageName : "sample-build", 56 | fromFilePath : "${WORKSPACE}/target/", 57 | registryFQDN : "${dockerRegistry}", 58 | imageNamespace: "${testingNamespace}", 59 | imageVersion : "v2" 60 | ]) 61 | } 62 | 63 | stage("ASSERT") { 64 | openshift.withCluster() { 65 | openshift.withProject() { 66 | def build = openshift.selector("build", "sample-build-${firstBuildVersion + 1}") 67 | assert build.exists() 68 | 69 | def imageStream = openshift.selector("is", "sample-build") 70 | imageStream.untilEach(1) { 71 | return it.object().status?.tags?.size() == 2 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /test/Jenkinsfile-clusterCredentials: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def credentials 5 | 6 | node("maven") { 7 | stage("SETUP: Create secret") { 8 | def secret = """ 9 | kind: Secret 10 | apiVersion: v1 11 | metadata: 12 | name: cluster-credential 13 | type: Opaque 14 | stringData: 15 | api: openshift.com:8443 16 | token: YmxhaAo= 17 | """ 18 | 19 | writeFile file: "secret-example.yml", text: secret 20 | 21 | openshift.withCluster() { 22 | openshift.withProject() { 23 | openshift.apply("-f", "secret-example.yml") 24 | } 25 | } 26 | 27 | openshift.logLevel(10) 28 | } 29 | 30 | stage("TEST: Can get credential") { 31 | credentials = clusterCredentials([ 32 | secretName: "cluster-credential" 33 | ]) 34 | } 35 | 36 | stage("ASSERT") { 37 | assert credentials != null 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/Jenkinsfile-clusterCredentials-fail-missingsecret: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Set logging to verbose") { 6 | openshift.logLevel(10) 7 | } 8 | 9 | stage("TEST: Can get credential and fail") { 10 | credentials = clusterCredentials([ 11 | secretName: "doesnt-exist" 12 | ]) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/Jenkinsfile-configMap: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def configMapData 5 | 6 | node("maven") { 7 | stage("SETUP: Create configmap") { 8 | def configMap = """ 9 | apiVersion: v1 10 | kind: ConfigMap 11 | metadata: 12 | name: game-config 13 | data: 14 | game.properties: | 15 | enemies=aliens 16 | """ 17 | 18 | writeFile file: "configmap-example.yml", text: configMap 19 | 20 | openshift.withCluster() { 21 | openshift.withProject() { 22 | openshift.apply("-f", "configmap-example.yml") 23 | } 24 | } 25 | 26 | openshift.logLevel(10) 27 | } 28 | 29 | stage("TEST: Can get configmap data") { 30 | configMapData = configMap([ 31 | configMapName: "game-config" 32 | ]) 33 | } 34 | 35 | stage("ASSERT") { 36 | assert configMapData != null 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/Jenkinsfile-configMap-fail-missingconfigmap: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Set logging to verbose") { 6 | openshift.logLevel(10) 7 | } 8 | 9 | stage("TEST: Can get configmap data and fail") { 10 | configMapData = configMap([ 11 | configMapName: "doesnt-exist" 12 | ]) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/Jenkinsfile-crossClusterPromote: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def promotionNamespace 5 | def testingNamespace 6 | 7 | node("jenkins-slave-image-mgmt") { 8 | stage("SETUP: Check imagestream doesnt exist") { 9 | testingNamespace = sh(script: "cat /var/run/secrets/kubernetes.io/serviceaccount/namespace", returnStdout: true) 10 | promotionNamespace = testingNamespace + '-promotion-testing' 11 | 12 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 13 | openshift.withCluster("https://kubernetes.default.svc", "${TOKEN}") { 14 | try { 15 | openshift.newProject(promotionNamespace) 16 | } catch(ex) { 17 | echo "Ignoring new-project error: ${ex}" 18 | } 19 | 20 | openshift.withProject(promotionNamespace) { 21 | def imageStream = openshift.selector("is", "jenkins-slave-ansible") 22 | if (imageStream.exists()) { 23 | imageStream.delete() 24 | } 25 | } 26 | } 27 | } 28 | 29 | openshift.logLevel(10) 30 | } 31 | 32 | stage("TEST: Can promote image from one project to another") { 33 | crossClusterPromote([ 34 | sourceImageName : "jenkins-slave-ansible", 35 | sourceImagePath : "${testingNamespace}", 36 | destinationImagePath : "${promotionNamespace}", 37 | targetRegistryCredentials: "local-registry-generic" 38 | ]) 39 | } 40 | 41 | stage("ASSERT") { 42 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 43 | openshift.withCluster("https://kubernetes.default.svc", "${TOKEN}") { 44 | openshift.withProject(promotionNamespace) { 45 | def imageStream = openshift.selector("is", "jenkins-slave-ansible") 46 | assert imageStream.exists() 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/Jenkinsfile-crossClusterPromote-fail-missingsecret: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("jenkins-slave-image-mgmt") { 5 | stage("SETUP: Set logging to verbose") { 6 | openshift.logLevel(10) 7 | } 8 | 9 | stage("TEST: Can promote image from one project to another and fail") { 10 | crossClusterPromote([ 11 | sourceImageName : "jenkins-slave-ansible", 12 | sourceImagePath : "pipelinelib-testing", 13 | destinationImagePath : "pipelinelib-promotion-testing", 14 | targetRegistryCredentials: "doesnt-exist" 15 | ]) 16 | } 17 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-patchBuildConfigOutputLabels: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create build files") { 6 | openshift.withCluster() { 7 | openshift.withProject() { 8 | def buildConfig = openshift.selector("bc", "sample-verbose-build") 9 | if (!buildConfig.exists()) { 10 | openshift.apply("-f", "https://raw.githubusercontent.com/openshift/origin/v3.11.0/test/extended/testdata/builds/test-build.yaml") 11 | } 12 | } 13 | } 14 | 15 | openshift.logLevel(10) 16 | } 17 | 18 | stage("TEST: Can patch build config") { 19 | patchBuildConfigOutputLabels([ 20 | bcName : "sample-verbose-build", 21 | domainPrefix: "org.example" 22 | ]) 23 | } 24 | 25 | stage("ASSERT") { 26 | openshift.withCluster() { 27 | openshift.withProject() { 28 | def buildConfig = openshift.selector("bc", "sample-verbose-build") 29 | assert buildConfig.exists() 30 | 31 | def imageLabels = buildConfig.object().spec.output?.imageLabels 32 | assert imageLabels != null 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-rollback: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def firstDeploymentVersion 5 | 6 | node("maven") { 7 | stage("SETUP: Create deployment files") { 8 | openshift.withCluster() { 9 | openshift.withProject() { 10 | def model = openshift.process("https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json", "-p NAME=rollback", "-p DATABASE_SERVICE_NAME=rollback") 11 | openshift.apply(model) 12 | 13 | openshift.selector("bc", "rollback").startBuild("--wait") 14 | 15 | def deployment = openshift.selector("dc", "rollback") 16 | deployment.rollout().status("--watch=true") 17 | 18 | firstDeploymentVersion = deployment.object().status.latestVersion 19 | 20 | def patch = '{"apiVersion":"apps.openshift.io/v1","kind":"DeploymentConfig","metadata":{"name":"rollback"},"spec":{"template":{"metadata":{"labels":{"version":"v2"}}}}}' 21 | openshift.patch(deployment.object(), "'" + patch + "'") 22 | 23 | //Wait for v2 24 | deployment.rollout().status("--watch=true") 25 | } 26 | } 27 | 28 | openshift.logLevel(10) 29 | } 30 | 31 | stage("TEST: Can rollback to earlier version") { 32 | rollback([ 33 | resourceKindAndName: "dc/rollback" 34 | ]) 35 | } 36 | 37 | stage("ASSERT") { 38 | openshift.withCluster() { 39 | openshift.withProject() { 40 | def deployment = openshift.selector("dc", "rollback") 41 | deployment.rollout().status("--watch=true") 42 | 43 | def first = openshift.selector("rc", "rollback-${firstDeploymentVersion}") 44 | assert first.exists() 45 | assert first.object().spec.template.metadata.labels.version == null 46 | 47 | def second = openshift.selector("rc", "rollback-${firstDeploymentVersion + 1}") 48 | assert second.exists() 49 | assert second.object().spec.template.metadata.labels.version == "v2" 50 | 51 | def third = openshift.selector("rc", "rollback-${firstDeploymentVersion + 2}") 52 | assert third.exists() 53 | assert third.object().spec.template.metadata.labels.version == null 54 | 55 | //Scale down afterwards to lower quotas 56 | deployment.scale("--replicas=0") 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-rollback-fail-missingdc: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Set logging to verbose") { 6 | openshift.logLevel(10) 7 | } 8 | 9 | stage("TEST: Can rollback to earlier version and fail") { 10 | rollback([ 11 | resourceKindAndName: "dc/doesnt-exist" 12 | ]) 13 | } 14 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-rollout: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def firstDeploymentVersion 5 | 6 | node("maven") { 7 | stage("SETUP: Create deployment files") { 8 | openshift.withCluster() { 9 | openshift.withProject() { 10 | def model = openshift.process("https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json", "-p NAME=rollout", "-p DATABASE_SERVICE_NAME=rollout") 11 | openshift.apply(model) 12 | 13 | openshift.selector("bc", "rollout").startBuild("--wait") 14 | 15 | def deployment = openshift.selector("dc", "rollout") 16 | deployment.rollout().status("--watch=true") 17 | 18 | firstDeploymentVersion = deployment.object().status.latestVersion 19 | } 20 | } 21 | 22 | openshift.logLevel(10) 23 | } 24 | 25 | stage("TEST: Can rollout to latest version") { 26 | rollout([ 27 | resourceKindAndName: "dc/rollout" 28 | ]) 29 | } 30 | 31 | stage("ASSERT") { 32 | openshift.withCluster() { 33 | openshift.withProject() { 34 | def nextRcNumber = firstDeploymentVersion + 1 35 | 36 | def deployment = openshift.selector("dc", "rollout") 37 | assert deployment.object().status.latestVersion == nextRcNumber 38 | 39 | def rc = openshift.selector("rc", "rollout-${nextRcNumber}") 40 | assert rc.exists() 41 | 42 | //Scale down afterwards to lower quotas 43 | deployment.scale("--replicas=0") 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/Jenkinsfile-rollout-deployment: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create deployment files") { 6 | openshift.withCluster() { 7 | openshift.withProject() { 8 | openshift.apply("-f", "https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/all-in-one/guestbook-all-in-one.yaml") 9 | 10 | openshift.patch(openshift.selector("deployment", "redis-master").object(), "'{\"spec\":{\"replicas\":0}}'") 11 | openshift.patch(openshift.selector("deployment", "redis-slave").object(), "'{\"spec\":{\"replicas\":1}}'") 12 | openshift.patch(openshift.selector("deployment", "frontend").object(), "'{\"spec\":{\"replicas\":0}}'") 13 | } 14 | } 15 | 16 | openshift.logLevel(10) 17 | } 18 | 19 | stage("TEST: Can rollout a k8s deployment") { 20 | rollout([ 21 | resourceKindAndName: "deployment/redis-slave", 22 | latest: false 23 | ]) 24 | } 25 | 26 | stage("ASSERT") { 27 | openshift.withCluster() { 28 | openshift.withProject() { 29 | def deployment = openshift.selector("deployment", "redis-slave") 30 | assert deployment.object().status.availableReplicas == 1 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/Jenkinsfile-rollout-fail-loghistory: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create deployment files") { 6 | openshift.withCluster() { 7 | openshift.withProject() { 8 | def model = openshift.process("https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json", "-p NAME=rollout-fail-loghistory", "-p DATABASE_SERVICE_NAME=rollout-fail-loghistory") 9 | openshift.apply(model) 10 | 11 | openshift.patch(openshift.selector("dc", "rollout-fail-loghistory").object(), "'{\"spec\":{\"strategy\":{\"recreateParams\":{\"timeoutSeconds\":60}},\"template\":{\"spec\":{\"containers\":[{\"name\":\"mysql\",\"env\":null}]}}}}'") 12 | openshift.selector("dc", "rollout-fail-loghistory").rollout().cancel() 13 | 14 | //HACK: Wait for the deployment to stop 15 | sh "sleep 5" 16 | } 17 | } 18 | } 19 | 20 | stage("TEST: Can rollout to latest version and fail with history printed") { 21 | rollout([ 22 | deploymentConfigName: "rollout-fail-loghistory" 23 | ]) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/Jenkinsfile-rollout-fail-missingdc: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Set logging to verbose") { 6 | openshift.logLevel(10) 7 | } 8 | 9 | stage("TEST: Can rollout to latest version and fail") { 10 | rollout([ 11 | resourceKindAndName: "dc/doesnt-exist" 12 | ]) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/Jenkinsfile-sonarqubeStaticAnalysis: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def jenkinsUrl 5 | def sonarqubeNamespace 6 | 7 | node("jenkins-slave-ansible") { 8 | stage("SETUP: Deploy sonarqube via applier") { 9 | sonarqubeNamespace = sh(script: "cat /var/run/secrets/kubernetes.io/serviceaccount/namespace", returnStdout: true) + '-sonarqube' 10 | 11 | sh "git clone https://github.com/redhat-cop/containers-quickstarts.git" 12 | 13 | openshift.withCluster() { 14 | openshift.withProject() { 15 | def jenkinsRoute = openshift.selector("route", "jenkins") 16 | jenkinsUrl = "https://" + jenkinsRoute.object().spec?.host 17 | } 18 | } 19 | 20 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 21 | applier([ 22 | inventoryPath : ".applier/hosts", 23 | requirementsPath : "requirements.yml", 24 | ansibleRootDir : "${WORKSPACE}/containers-quickstarts/sonarqube", 25 | applierPlaybook : "galaxy/openshift-applier/playbooks/openshift-cluster-seed.yml", 26 | playbookAdditionalArgs: "-e jenkins_url=${jenkinsUrl} -e namespace=${sonarqubeNamespace}", 27 | clusterAPI : "https://kubernetes.default.svc", 28 | clusterToken : "${TOKEN}" 29 | ]) 30 | } 31 | 32 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 33 | openshift.withCluster("https://kubernetes.default.svc", "${TOKEN}") { 34 | openshift.withProject(sonarqubeNamespace) { 35 | def dbDeployment = openshift.selector("dc", "sonardb") 36 | dbDeployment.rollout().status("--watch=true") 37 | 38 | def sonarDeployment = openshift.selector("dc", "sonarqube") 39 | 40 | try { 41 | def patch = '{"apiVersion":"apps.openshift.io/v1","kind":"DeploymentConfig","metadata":{"name":"sonarqube"},"spec":{"template":{"spec":{"containers":[{"name":"sonarqube","livenessProbe":{"initialDelaySeconds":180},"readinessProbe":{"initialDelaySeconds":180}}]}}}}' 42 | openshift.patch(sonarDeployment.object(), "'" + patch + "'") 43 | } catch (ex) { 44 | echo "Ignoring patch error: ${ex}" 45 | } 46 | 47 | //Can be very flaky when following out.. 48 | retry(3) { 49 | try { 50 | sonarDeployment.rollout().status("--watch=true") 51 | } catch(ex) { 52 | sonarDeployment.rollout().latest() 53 | 54 | error "Ignoring rollout error: ${ex}" 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | 62 | stage("SETUP: Configure sonarqube") { 63 | sh """git clone https://github.com/redhat-cop/pipeline-library.git""" 64 | 65 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 66 | openshift.withCluster("https://kubernetes.default.svc", "${TOKEN}") { 67 | openshift.withProject(sonarqubeNamespace) { 68 | def route = openshift.selector("route", "sonarqube") 69 | def sonarUrl = "https://" + route.object().spec?.host 70 | 71 | writeFile file: "token.json", text: sh(returnStdout: true, script: "curl --insecure -L -X POST -u admin:admin ${sonarUrl}/api/user_tokens/generate?name=jenkins-b${env.BUILD_NUMBER}") 72 | def sonarqubeToken = readJSON file: "token.json" 73 | 74 | sh """ 75 | sed -i 's|def SONAR_URL|def SONAR_URL = "${sonarUrl}"|' ${WORKSPACE}/pipeline-library/test/create-sonarqube-installation.groovy 76 | sed -i 's|def SONAR_TOKEN|def SONAR_TOKEN = "${sonarqubeToken.token}"|' ${WORKSPACE}/pipeline-library/test/create-sonarqube-installation.groovy 77 | 78 | curl --insecure --header "Authorization: Bearer ${TOKEN}" --data-urlencode "script=\$(< ${WORKSPACE}/pipeline-library/test/create-sonarqube-installation.groovy)" ${jenkinsUrl}/scriptText 79 | """ 80 | } 81 | } 82 | } 83 | } 84 | } 85 | 86 | node("maven") { 87 | stage("TEST: Can run sonarqube static analysis") { 88 | sh """git clone https://github.com/redhat-cop/pipeline-library.git""" 89 | 90 | dir ("pipeline-library") { 91 | sonarqubeStaticAnalysis([ 92 | curlOptions: "--insecure" 93 | ]) 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /test/Jenkinsfile-tagAndDeploy: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def dockerRegistry 5 | def testingNamespace 6 | 7 | podTemplate(label: "jnlp", cloud: "openshift", inheritFrom: "jenkins-slave-image-mgmt", volumes: [ 8 | secretVolume(mountPath: "/var/run/secrets/kubernetes.io/dockerconfigjson", secretName: "local-registry") 9 | ]) { 10 | node("jnlp") { 11 | stage("SETUP: Create build/deployment files") { 12 | testingNamespace = sh(script: "cat /var/run/secrets/kubernetes.io/serviceaccount/namespace", returnStdout: true) 13 | openshift.withCluster() { 14 | openshift.withProject("openshift") { 15 | def imageStream = openshift.selector("is", "jenkins") 16 | dockerRegistry = sh(returnStdout: true, script: "echo '${imageStream.object().status.dockerImageRepository}' | cut -d '/' -f1").trim() 17 | } 18 | } 19 | 20 | openshift.withCluster() { 21 | openshift.withProject() { 22 | def model = openshift.process("https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json", "-p NAME=taganddeploy", "-p DATABASE_SERVICE_NAME=taganddeploy") 23 | openshift.apply(model) 24 | 25 | openshift.selector("bc", "taganddeploy").startBuild("--wait") 26 | 27 | def imageStream = openshift.selector("is", "taganddeploy") 28 | imageStream.untilEach(1) { 29 | return it.object().status?.tags?.size() > 0 30 | } 31 | 32 | def deployment = openshift.selector("dc", "taganddeploy") 33 | deployment.rollout().status("--watch=true") 34 | } 35 | } 36 | 37 | openshift.logLevel(10) 38 | } 39 | 40 | stage("TEST: Can tag and deploy") { 41 | tagAndDeploy([ 42 | registryFQDN : "${dockerRegistry}", 43 | imageNamespace : "${testingNamespace}", 44 | imageName : "taganddeploy", 45 | imageVersion : "latest", 46 | deployDestinationVersionTag : "v2", 47 | deployDestinationProjectName: "${testingNamespace}" 48 | ]) 49 | } 50 | 51 | stage("ASSERT") { 52 | openshift.withCluster() { 53 | openshift.withProject() { 54 | def imageStream = openshift.selector("is", "taganddeploy") 55 | imageStream.untilEach(1) { 56 | return it.object().status?.tags?.size() == 2 57 | } 58 | 59 | //Scale down afterwards to lower quotas 60 | def deployment = openshift.selector("dc", "taganddeploy") 61 | deployment.scale("--replicas=0") 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/Jenkinsfile-tagImage: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def testingNamespace 5 | 6 | node("maven") { 7 | stage("SETUP: Resolve namespace") { 8 | testingNamespace = sh(script: "cat /var/run/secrets/kubernetes.io/serviceaccount/namespace", returnStdout: true) 9 | } 10 | 11 | stage("TEST: Can tag image") { 12 | tagImage([ 13 | sourceImagePath: "openshift", 14 | sourceImageName: "jenkins", 15 | sourceImageTag : "2", 16 | toImagePath : "${testingNamespace}", 17 | toImageName : "tagimage", 18 | toImageTag : "2" 19 | ]) 20 | } 21 | 22 | stage("ASSERT") { 23 | openshift.withCluster() { 24 | openshift.withProject() { 25 | def imageStream = openshift.selector("is", "tagimage") 26 | imageStream.untilEach(1) { 27 | return it.object().status?.tags?.size() == 1 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/Jenkinsfile-verifyDeployment: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create deployment files") { 6 | openshift.withCluster() { 7 | openshift.withProject() { 8 | def model = openshift.process("https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json", "-p NAME=verifydeployment", "-p DATABASE_SERVICE_NAME=verifydeployment") 9 | openshift.apply(model) 10 | } 11 | } 12 | 13 | openshift.logLevel(10) 14 | } 15 | 16 | stage("TEST: Can verify deployment") { 17 | verifyDeployment([ 18 | targetApp: "verifydeployment" 19 | ]) 20 | } 21 | 22 | stage("ASSERT") { 23 | openshift.withCluster() { 24 | openshift.withProject() { 25 | def deployment = openshift.selector("dc", "verifydeployment") 26 | deployment.rollout().status("--watch=true") 27 | 28 | //Scale down afterwards to lower quotas 29 | deployment.scale("--replicas=0") 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-verifyDeployment-fail-viacrashloop: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create deployment files") { 6 | openshift.withCluster() { 7 | openshift.withProject() { 8 | def model = openshift.process("https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json", "-p NAME=verifydeployment-fail-viacrashloop", "-p DATABASE_SERVICE_NAME=verifydeployment-fail-viacrashloop") 9 | openshift.apply(model) 10 | 11 | openshift.patch(openshift.selector("dc", "verifydeployment-fail-viacrashloop").object(), "'{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"mysql\",\"env\":null}]}}}}'") 12 | 13 | //HACK: Wait for the deployment to be trigger 14 | sh "sleep 5" 15 | } 16 | } 17 | } 18 | 19 | stage("TEST: Can verify deployment and fail with due to crashloopbackoff") { 20 | verifyDeployment([ 21 | targetApp: "verifydeployment-fail-viacrashloop" 22 | ]) 23 | } 24 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-verifyService: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create deployment files") { 6 | openshift.withCluster() { 7 | openshift.withProject() { 8 | def model = openshift.process("https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json", "-p NAME=verifyservice", "-p DATABASE_SERVICE_NAME=verifyservice") 9 | openshift.apply(model) 10 | 11 | def deployment = openshift.selector("dc", "verifyservice") 12 | deployment.rollout().status("--watch=true") 13 | } 14 | } 15 | 16 | openshift.logLevel(10) 17 | } 18 | 19 | stage("TEST: Can verify service") { 20 | verifyService([ 21 | serviceName: "verifyservice" 22 | ]) 23 | } 24 | 25 | stage("ASSERT") { 26 | openshift.withCluster() { 27 | openshift.withProject() { 28 | def deployment = openshift.selector("dc", "verifyservice") 29 | 30 | sh "curl -L http://verifyservice:3306" 31 | 32 | //Scale down afterwards to lower quotas 33 | deployment.scale("--replicas=0") 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /test/Jenkinsfile-verifyService-fail-nopods: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | node("maven") { 5 | stage("SETUP: Create deployment files") { 6 | openshift.withCluster() { 7 | openshift.withProject() { 8 | def model = openshift.process("https://raw.githubusercontent.com/openshift/origin/v3.11.0/examples/quickstarts/cakephp-mysql.json", "-p NAME=verifyservice-fail-nopods", "-p DATABASE_SERVICE_NAME=verifyservice-fail-nopods") 9 | openshift.apply(model) 10 | 11 | def deployment = openshift.selector("dc", "verifyservice-fail-nopods") 12 | deployment.rollout().status("--watch=true") 13 | 14 | deployment.scale("--replicas=0") 15 | } 16 | } 17 | 18 | openshift.logLevel(10) 19 | } 20 | 21 | stage("TEST: Can verify service and fail due to no pods behind service") { 22 | verifyService([ 23 | serviceName: "verifyservice-fail-nopods" 24 | ]) 25 | } 26 | } -------------------------------------------------------------------------------- /test/create-pipeline-library.groovy: -------------------------------------------------------------------------------- 1 | import hudson.model.* 2 | import jenkins.model.* 3 | import jenkins.plugins.git.GitSCMSource 4 | import org.jenkinsci.plugins.workflow.libs.GlobalLibraries 5 | import org.jenkinsci.plugins.workflow.libs.LibraryConfiguration 6 | import org.jenkinsci.plugins.workflow.libs.SCMSourceRetriever 7 | 8 | final Jenkins jenkins = Jenkins.getInstance() 9 | 10 | GitSCMSource librarySource = new GitSCMSource("pipeline-library", "https://github.com/redhat-cop/pipeline-library.git", "", "*", "", true) 11 | 12 | LibraryConfiguration config = new LibraryConfiguration("pipeline-library", new SCMSourceRetriever(librarySource)) 13 | config.setAllowVersionOverride(true) 14 | config.setImplicit(false) 15 | config.setDefaultVersion("master") 16 | 17 | List configurations = new ArrayList() 18 | configurations.add(config) 19 | 20 | GlobalLibraries globalLibraries = GlobalLibraries.get() 21 | globalLibraries.setLibraries(configurations) 22 | 23 | jenkins.save() -------------------------------------------------------------------------------- /test/create-sonarqube-installation.groovy: -------------------------------------------------------------------------------- 1 | import jenkins.model.* 2 | import hudson.model.* 3 | import hudson.plugins.sonar.* 4 | import hudson.tools.* 5 | import hudson.util.Secret 6 | import com.cloudbees.plugins.credentials.impl.* 7 | import com.cloudbees.plugins.credentials.* 8 | import com.cloudbees.plugins.credentials.domains.* 9 | import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl 10 | 11 | def instance = Jenkins.getInstance() 12 | 13 | def SONAR_URL 14 | def SONAR_TOKEN 15 | 16 | def stringCredentials = new StringCredentialsImpl(CredentialsScope.GLOBAL, "sonartoken", null, Secret.fromString("${SONAR_TOKEN}")) 17 | 18 | SystemCredentialsProvider systemCredentialsProvider = SystemCredentialsProvider.getInstance() 19 | systemCredentialsProvider.getStore().addCredentials(Domain.global(), stringCredentials) 20 | systemCredentialsProvider.save() 21 | 22 | SonarInstallation sonarInstallation = new SonarInstallation("sonar", "${SONAR_URL}", "sonartoken", null, null, null, null, null, null) 23 | 24 | SonarGlobalConfiguration sonarGlobalConfiguration = instance.getDescriptor(SonarGlobalConfiguration.class) 25 | sonarGlobalConfiguration.setInstallations(sonarInstallation) 26 | sonarGlobalConfiguration.migrateCredentials() 27 | sonarGlobalConfiguration.save() 28 | 29 | instance.save() -------------------------------------------------------------------------------- /test/disabled-imageMirror: -------------------------------------------------------------------------------- 1 | #!groovy 2 | @Library(["pipeline-library@master"]) _ 3 | 4 | def dockerRegistry 5 | def promotionNamespace 6 | def testingNamespace 7 | 8 | node("maven") { 9 | stage("SETUP: Check imagestream doesnt exist") { 10 | openshift.withCluster() { 11 | testingNamespace = sh(script: "cat /var/run/secrets/kubernetes.io/serviceaccount/namespace", returnStdout: true) 12 | promotionNamespace = testingNamespace + '-promotion-testing' 13 | 14 | openshift.withProject("openshift") { 15 | def imageStream = openshift.selector("is", "jenkins") 16 | dockerRegistry = sh(returnStdout: true, script: "echo '${imageStream.object().status.dockerImageRepository}' | cut -d '/' -f1").trim() 17 | } 18 | } 19 | 20 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 21 | openshift.withCluster("https://kubernetes.default.svc", "${TOKEN}") { 22 | try { 23 | openshift.newProject(promotionNamespace) 24 | } catch(ex) { 25 | echo "Ignoring new-project error: ${ex}" 26 | } 27 | 28 | openshift.withProject(promotionNamespace) { 29 | def imageStream = openshift.selector("is", "jenkins-slave-image-mgmt") 30 | if (imageStream.exists()) { 31 | imageStream.delete() 32 | } 33 | } 34 | } 35 | } 36 | 37 | openshift.logLevel(10) 38 | } 39 | 40 | stage("TEST: Can promote image from one project to another") { 41 | imageMirror([ 42 | sourceSecret : "pipelinelib-testing-my-token", 43 | sourceRegistry : "https://${dockerRegistry}", 44 | destinationSecret : "pipelinelib-testing-my-token", 45 | destinationRegistry : "https://${dockerRegistry}", 46 | insecure : "true", 47 | sourceNamespace : "${testingNamespace}", 48 | destinationNamespace : "${promotionNamespace}", 49 | sourceImage : "jenkins-slave-image-mgmt", 50 | sourceImageVersion : "latest", 51 | destinationImageVersion: "latest" 52 | ]) 53 | } 54 | 55 | stage("ASSERT") { 56 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 57 | openshift.withCluster("https://kubernetes.default.svc", "${TOKEN}") { 58 | openshift.withProject(promotionNamespace) { 59 | def imageStream = openshift.selector("is", "jenkins-slave-image-mgmt") 60 | imageStream.untilEach(1) { 61 | return it.object().status?.tags?.size() == 1 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/Jenkinsfile: -------------------------------------------------------------------------------- 1 | library identifier: "pipeline-library@master", retriever: modernSCM( 2 | [$class: "GitSCMSource", 3 | remote: "https://github.com/redhat-cop/pipeline-library.git"]) 4 | 5 | pipeline { 6 | // Use Jenkins Maven slave 7 | // Jenkins will dynamically provision this as OpenShift Pod 8 | // All the stages and steps of this Pipeline will be executed on this Pod 9 | // After Pipeline completes the Pod is killed so every run will have clean 10 | // workspace 11 | agent { 12 | label 'maven' 13 | } 14 | 15 | // Pipeline Stages start here 16 | // Requeres at least one stage 17 | stages { 18 | 19 | // Checkout source code 20 | // This is required as Pipeline code is originally checkedout to 21 | // Jenkins Master but this will also pull this same code to this slave 22 | stage('Git Checkout') { 23 | steps { 24 | // Turn off Git's SSL cert check, uncomment if needed 25 | // sh 'git config --global http.sslVerify false' 26 | git url: "${SOURCE_CODE_URL}" 27 | } 28 | } 29 | 30 | // Run Maven build, skipping tests 31 | stage('Build'){ 32 | steps { 33 | sh "mvn clean install -q" 34 | } 35 | } 36 | 37 | // Build Container Image using the artifacts produced in previous stages 38 | stage('Build Container Image'){ 39 | steps { 40 | binaryBuild(projectName: "pipeline-library-dev", buildConfigName: "spring-rest", artifactsDirectoryName: "target") 41 | } 42 | } 43 | 44 | stage ('Verify Deployment to Dev') { 45 | steps { 46 | verifyDeployment(projectName: "pipeline-library-dev", targetApp: "spring-rest") 47 | } 48 | } 49 | 50 | stage('Promote image') { 51 | steps { 52 | tagImage(sourceImagePath: "pipeline-library-dev", sourceImageName: "spring-rest", toImagePath: "pipeline-library-test") 53 | } 54 | } 55 | 56 | stage ('Verify Deployment to test') { 57 | steps { 58 | verifyDeployment(projectName: "pipeline-library-test", targetApp: "spring-rest") 59 | } 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/README.md: -------------------------------------------------------------------------------- 1 | # Testing the generic vars 2 | 3 | This directory contains a test inventory for testing the generic vars -files in OpenShift. It requires [openshift-applier](https://github.com/redhat-cop/openshift-applier.git) to test. This can be pulled in via ansible-galaxy. 4 | 5 | ## Dependencies 6 | [redhat-openjdk-18/openjdk18-openshift](https://access.redhat.com/containers/?tab=overview#/registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift) is needed in the `openshift` project to build the test app. Add the image to your `openshift` project: `oc import-image openshift/openjdk18-openshift --from=registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift --confirm` 7 | 8 | ## Steps to test 9 | 10 | 1. Pull in dependencies at root of this git repository. 11 | ``` 12 | ansible-galaxy install -r requirements.yml -p deps 13 | ``` 14 | 2. Run ansible under the test directory. 15 | ``` 16 | ansible-playbook -i test/org/redhatcop/util/end-to-end/inventory/ deps/openshift-applier/playbooks/openshift-cluster-seed.yml 17 | ``` 18 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/files/params/build: -------------------------------------------------------------------------------- 1 | NAMESPACE=pipeline-library-dev 2 | PIPELINE_REPOSITORY_URL=https://github.com/redhat-cop/pipeline-library.git 3 | PIPELINE_REPOSITORY_REF=master 4 | CONTEXT_DIR=test/org/redhatcop/util/end-to-end -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/files/params/deploy-dev: -------------------------------------------------------------------------------- 1 | APPLICATION_NAME=spring-rest 2 | NAMESPACE=pipeline-library-dev 3 | SA_NAMESPACE=pipeline-library-dev 4 | READINESS_RESPONSE=status.:.UP 5 | READINESS_PATH=/health -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/files/params/deploy-test: -------------------------------------------------------------------------------- 1 | APPLICATION_NAME=spring-rest 2 | NAMESPACE=pipeline-library-test 3 | SA_NAMESPACE=pipeline-library-dev 4 | READINESS_RESPONSE=status.:.UP 5 | READINESS_PATH=/health -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/files/params/jenkins-deployment: -------------------------------------------------------------------------------- 1 | NAMESPACE=pipeline-library-dev 2 | JENKINS_IMAGE_STREAM_TAG=jenkins2-s2i:latest -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/files/params/jenkins-s2i: -------------------------------------------------------------------------------- 1 | JENKINS_GIT_URL=https://github.com/redhat-cop/pipeline-library.git 2 | JENKINS_GIT_BRANCH=master 3 | JENKINS_GIT_CONTEXT_DIR=jenkins-s2i/ 4 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/files/projects.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: List 3 | items: 4 | - kind: ProjectRequest 5 | apiVersion: v1 6 | metadata: 7 | name: pipeline-library-dev 8 | creationTimestam: null 9 | displayName: Pipeline Library Development Project 10 | - kind: ProjectRequest 11 | apiVersion: v1 12 | metadata: 13 | name: pipeline-library-test 14 | creationTimestam: null 15 | displayName: Pipeline Library Testing Project -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/files/templates/build.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | labels: 4 | template: generic-java-jenkins-pipeline 5 | metadata: 6 | annotations: 7 | description: Application template for JWS applications built using a Jenkins Pipeline 8 | iconClass: icon-tomcat 9 | tags: tomcat,tomcat8,java,jboss,xpaas,jenkins-ci 10 | version: 1.2.0 11 | name: generic-java-jenkins-pipeline 12 | objects: 13 | - kind: "BuildConfig" 14 | apiVersion: "v1" 15 | metadata: 16 | labels: 17 | application: ${APPLICATION_NAME} 18 | name: "${APPLICATION_NAME}-pipeline" 19 | namespace: "${NAMESPACE}" 20 | spec: 21 | source: 22 | type: Git 23 | git: 24 | uri: ${PIPELINE_REPOSITORY_URL} 25 | ref: ${PIPELINE_REPOSITORY_REF} 26 | contextDir: ${CONTEXT_DIR} 27 | triggers: 28 | - type: "GitHub" 29 | github: 30 | secret: ${GITHUB_WEBHOOK_SECRET} 31 | - type: "ConfigChange" 32 | strategy: 33 | type: "JenkinsPipeline" 34 | jenkinsPipelineStrategy: 35 | jenkinsfilePath: ${PIPELINE_SCRIPT} 36 | env: 37 | - name: SOURCE_CODE_URL 38 | value: ${SOURCE_CODE_URL} 39 | - name: SOURCE_CODE_BRANCH 40 | value: ${SOURCE_CODE_BRANCH} 41 | - apiVersion: v1 42 | kind: BuildConfig 43 | metadata: 44 | labels: 45 | application: ${APPLICATION_NAME} 46 | name: ${APPLICATION_NAME} 47 | namespace: "${NAMESPACE}" 48 | spec: 49 | output: 50 | to: 51 | kind: ImageStreamTag 52 | name: ${APPLICATION_NAME}:latest 53 | source: 54 | binary: {} 55 | type: Binary 56 | strategy: 57 | sourceStrategy: 58 | from: 59 | kind: ImageStreamTag 60 | name: ${IMAGE_STREAM_TAG_NAME} 61 | namespace: ${IMAGE_STREAM_NAMESPACE} 62 | type: Source 63 | parameters: 64 | - description: The name for the application. 65 | name: APPLICATION_NAME 66 | required: true 67 | value: spring-rest 68 | - description: The namespace to deploy into 69 | name: NAMESPACE 70 | required: true 71 | - description: Git source URI for application 72 | name: PIPELINE_REPOSITORY_URL 73 | required: true 74 | value: https://github.com/redhat-cop/pipeline-library.git 75 | - description: Git branch/tag reference 76 | name: PIPELINE_REPOSITORY_REF 77 | value: "master" 78 | - description: Path within Git project to build; empty for root project directory. 79 | name: CONTEXT_DIR 80 | value: 81 | - description: Path within Git project pointing to the pipeline run script 82 | name: PIPELINE_SCRIPT 83 | value: Jenkinsfile 84 | - description: Git source URI for application 85 | name: SOURCE_CODE_URL 86 | required: true 87 | value: https://github.com/redhat-cop/spring-rest.git 88 | - description: Git branch/tag reference 89 | name: SOURCE_CODE_REF 90 | value: "master" 91 | - description: GitHub trigger secret 92 | from: '[a-zA-Z0-9]{8}' 93 | generate: expression 94 | name: GITHUB_WEBHOOK_SECRET 95 | required: true 96 | - description: Generic build trigger secret 97 | from: '[a-zA-Z0-9]{8}' 98 | generate: expression 99 | name: GENERIC_WEBHOOK_SECRET 100 | required: true 101 | - description: Namespace in which the ImageStreams for Red Hat Middleware images are 102 | installed. These ImageStreams are normally installed in the openshift namespace. 103 | You should only need to modify this if you've installed the ImageStreams in a 104 | different namespace/project. 105 | name: IMAGE_STREAM_NAMESPACE 106 | required: true 107 | value: openshift 108 | - description: Image stream tag for the image you'd like to use to build the application 109 | name: IMAGE_STREAM_TAG_NAME 110 | required: true 111 | value: redhat-openjdk18-openshift:1.4 -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/files/templates/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | labels: 4 | template: basic-spring-boot 5 | metadata: 6 | annotations: 7 | description: Application template for JWS applications built using a Jenkins 8 | iconClass: icon-tomcat 9 | tags: java,spring 10 | version: 1.2.0 11 | name: basic-sprint-boot 12 | objects: 13 | - apiVersion: v1 14 | kind: Service 15 | metadata: 16 | annotations: 17 | description: The web server's http port. 18 | labels: 19 | application: ${APPLICATION_NAME} 20 | name: ${APPLICATION_NAME} 21 | namespace: ${NAMESPACE} 22 | spec: 23 | ports: 24 | - port: 8080 25 | targetPort: 8080 26 | selector: 27 | deploymentConfig: ${APPLICATION_NAME} 28 | - apiVersion: v1 29 | id: ${APPLICATION_NAME}-http 30 | kind: Route 31 | metadata: 32 | annotations: 33 | description: Route for application's http service. 34 | labels: 35 | application: ${APPLICATION_NAME} 36 | name: ${APPLICATION_NAME} 37 | namespace: ${NAMESPACE} 38 | spec: 39 | host: ${HOSTNAME_HTTP} 40 | to: 41 | name: ${APPLICATION_NAME} 42 | - apiVersion: v1 43 | kind: ImageStream 44 | metadata: 45 | labels: 46 | application: ${APPLICATION_NAME} 47 | name: ${APPLICATION_NAME} 48 | namespace: ${NAMESPACE} 49 | - apiVersion: v1 50 | kind: DeploymentConfig 51 | metadata: 52 | labels: 53 | application: ${APPLICATION_NAME} 54 | name: ${APPLICATION_NAME} 55 | namespace: ${NAMESPACE} 56 | spec: 57 | replicas: 1 58 | selector: 59 | deploymentConfig: ${APPLICATION_NAME} 60 | strategy: 61 | type: Recreate 62 | template: 63 | metadata: 64 | labels: 65 | application: ${APPLICATION_NAME} 66 | deploymentConfig: ${APPLICATION_NAME} 67 | name: ${APPLICATION_NAME} 68 | spec: 69 | containers: 70 | - env: 71 | - name: JWS_ADMIN_USERNAME 72 | value: ${JWS_ADMIN_USERNAME} 73 | - name: JWS_ADMIN_PASSWORD 74 | value: ${JWS_ADMIN_PASSWORD} 75 | image: ${APPLICATION_NAME} 76 | imagePullPolicy: Always 77 | name: ${APPLICATION_NAME} 78 | ports: 79 | - containerPort: 8778 80 | name: jolokia 81 | protocol: TCP 82 | - containerPort: 8080 83 | name: http 84 | protocol: TCP 85 | readinessProbe: 86 | exec: 87 | command: 88 | - /bin/bash 89 | - -c 90 | - curl -s 'http://localhost:8080${READINESS_PATH}' 91 | |grep -iq '${READINESS_RESPONSE}' 92 | terminationGracePeriodSeconds: 60 93 | triggers: 94 | - imageChangeParams: 95 | automatic: true 96 | containerNames: 97 | - ${APPLICATION_NAME} 98 | from: 99 | kind: ImageStreamTag 100 | name: ${APPLICATION_NAME}:latest 101 | type: ImageChange 102 | - type: ConfigChange 103 | - apiVersion: v1 104 | groupNames: null 105 | kind: RoleBinding 106 | metadata: 107 | creationTimestamp: null 108 | labels: 109 | template: basic-tomcat-template 110 | name: jenkins_edit 111 | namespace: ${NAMESPACE} 112 | roleRef: 113 | name: edit 114 | subjects: 115 | - kind: ServiceAccount 116 | name: ${SA_NAME} 117 | namespace: ${SA_NAMESPACE} 118 | userNames: 119 | - system:serviceaccount:${SA_NAMESPACE}:${SA_NAME} 120 | parameters: 121 | - description: The name for the application. 122 | name: APPLICATION_NAME 123 | required: true 124 | value: jws-app 125 | - description: The namespace to deploy into 126 | name: NAMESPACE 127 | required: true 128 | - description: Name of a service account that can deploy to this project 129 | name: SA_NAME 130 | required: true 131 | value: jenkins 132 | - description: Namespace of service account that can deploy to this project 133 | name: SA_NAMESPACE 134 | required: true 135 | - description: 'Custom hostname for http service route. Leave blank for default hostname, 136 | e.g.: -.' 137 | name: HOSTNAME_HTTP 138 | - description: 'URI to check for app health' 139 | name: READINESS_PATH 140 | required: true 141 | value: '/' 142 | - description: 'String value expected back from readiness check' 143 | name: READINESS_RESPONSE 144 | required: true 145 | value: 'Hello World!' -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/inventory/group_vars/seed-hosts.yml: -------------------------------------------------------------------------------- 1 | openshift_cluster_content: 2 | - object: rollback test 3 | content: 4 | - name: create project 5 | file: "{{ inventory_dir }}/../files/projects.yml" 6 | action: create 7 | - name: build jenkins image 8 | template: "{{ inventory_dir }}/../../../../../../jenkins-s2i/jenkins-s2i.yml" 9 | params: "{{ inventory_dir }}/../files/params/jenkins-s2i" 10 | namespace: pipeline-library-dev 11 | - name: deploy jenkins 12 | template: "openshift//jenkins-ephemeral" 13 | params: "{{ inventory_dir }}/../files/params/jenkins-deployment" 14 | namespace: pipeline-library-dev 15 | - name: test app build 16 | template: "{{ inventory_dir }}/../files/templates/build.yml" 17 | params: "{{ inventory_dir }}/../files/params/build" 18 | - name: test app deploy dev 19 | template: "{{ inventory_dir }}/../files/templates/deployment.yml" 20 | params: "{{ inventory_dir }}/../files/params/deploy-dev" 21 | - name: test app deploy test 22 | template: "{{ inventory_dir }}/../files/templates/deployment.yml" 23 | params: "{{ inventory_dir }}/../files/params/deploy-test" -------------------------------------------------------------------------------- /test/org/redhatcop/util/end-to-end/inventory/hosts: -------------------------------------------------------------------------------- 1 | [seed-hosts] 2 | localhost ansible_connection=local 3 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/Jenkinsfile: -------------------------------------------------------------------------------- 1 | /* 2 | Must create a secret in openshift project with the following: 3 | apiVersion: v1 4 | kind: Secret 5 | metadata: 6 | name: rocketchat-secret 7 | stringData: 8 | server: https://rocketchat.example.com 9 | key: somehookid 10 | secret: somehooksecret 11 | */ 12 | 13 | @Library('cop-library') _ 14 | 15 | podTemplate(label: 'slave-ruby', cloud: 'openshift', serviceAccount: "jenkins", containers: [ 16 | containerTemplate(name: 'jnlp', image: 'docker.io/redhatcop/jenkins-slave-ruby', privileged: false, alwaysPullImage: true, workingDir: '/tmp', args: '${computer.jnlpmac} ${computer.name}', ttyEnabled: false, 17 | envVars: [ 18 | secretEnvVar(key: 'ROCKETCHAT_SERVER', secretName: 'rocketchat-secret', secretKey: 'server'), 19 | secretEnvVar(key: 'ROCKETCHAT_KEY', secretName: 'rocketchat-secret', secretKey: 'key'), 20 | secretEnvVar(key: 'ROCKETCHAT_SECRET', secretName: 'rocketchat-secret', secretKey: 'secret') 21 | ] 22 | ) 23 | ]) { 24 | 25 | node ('slave-ruby') { 26 | rocketchat_url = "${env.ROCKETCHAT_SERVER}/hooks/${env.ROCKETCHAT_KEY}/${env.ROCKETCHAT_SECRET}" 27 | def n = new org.redhatcop.util.notifications() 28 | 29 | stage('Test Notifications') { 30 | n.notifyBuild('STARTED', rocketchat_url) 31 | n.notifyBuild('FAILED', rocketchat_url) 32 | n.notifyBuild('SUCCESSFUL', rocketchat_url) 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/README.md: -------------------------------------------------------------------------------- 1 | # Testing the org.redhatcop.util package 2 | 3 | This directory contains a test inventory for testing the `org.redhatcop.utils` package in OpenShift. It requires [casl-ansible](https://github.com/redhat-cop/casl-ansible.git) to test. This can be pulled in via ansible-galaxy. 4 | 5 | ## Steps to test 6 | 7 | 1. Must create a rocketchat [incoming webhook integration](https://rocket.chat/docs/administrator-guides/integrations/) 8 | 2. Update files/rocketchat-secret.yml to match the webhook integration you created. The secret should look like: 9 | ``` 10 | apiVersion: v1 11 | kind: Secret 12 | metadata: 13 | name: rocketchat-secret 14 | stringData: 15 | server: https://rocketchat.example.com 16 | key: somehookid 17 | secret: somehooksecret 18 | ``` 19 | Where the full rocketchat URL looks like `https://rocketchat.example.com/hooks/somehookid/somehooksecret`. 20 | 3. Pull in dependencies 21 | ``` 22 | ansible-galaxy install -r requirements.yml -p deps 23 | ``` 24 | 4. Run ansible. 25 | ``` 26 | ansible-playbook -i .test/org/redhatcop/util/inventory/ deps/casl-ansible/playbooks/openshift-cluster-seed.yml 27 | ``` 28 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/files/params/jenkins-deployment.params: -------------------------------------------------------------------------------- 1 | NAMESPACE=pipeline-library-test 2 | JENKINS_IMAGE_STREAM_TAG=jenkins2-s2i:latest 3 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/files/params/jenkins-s2i.params: -------------------------------------------------------------------------------- 1 | JENKINS_GIT_URL=https://github.com/redhat-cop/pipeline-library.git 2 | JENKINS_GIT_BRANCH=master 3 | JENKINS_GIT_CONTEXT_DIR=jenkins-s2i/ -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/files/params/notifications-build.params: -------------------------------------------------------------------------------- 1 | APPLICATION_NAME=notifications-test 2 | NAMESPACE=pipeline-library-test 3 | SOURCE_REPOSITORY_URL=https://github.com/redhat-cop/pipeline-library.git 4 | SOURCE_REPOSITORY_REF=master 5 | CONTEXT_DIR=test/org/redhatcop/util/rocketchat 6 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/files/projects.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: List 3 | items: 4 | - kind: ProjectRequest 5 | apiVersion: v1 6 | metadata: 7 | name: pipeline-library-test 8 | creationTimestam: null 9 | displayName: Pipeline Library Testing Project 10 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/files/rocketchat-secret.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: rocketchat-secret 5 | namespace: pipeline-library-test 6 | stringData: 7 | server: https://rocketchat.example.com 8 | key: somehookid 9 | secret: somehooksecret 10 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/files/templates/build-template.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | labels: 4 | template: pipeline-library-test 5 | metadata: 6 | annotations: 7 | description: Application template for testing pipelines 8 | tags: jenkins,pipeline 9 | version: 1.0.0 10 | name: pipeline-library-test 11 | objects: 12 | - kind: "BuildConfig" 13 | apiVersion: "v1" 14 | metadata: 15 | labels: 16 | application: ${APPLICATION_NAME} 17 | template: pipeline-library-test 18 | name: "${APPLICATION_NAME}-pipeline" 19 | namespace: "${NAMESPACE}" 20 | spec: 21 | source: 22 | type: Git 23 | git: 24 | uri: ${SOURCE_REPOSITORY_URL} 25 | ref: ${SOURCE_REPOSITORY_REF} 26 | contextDir: ${CONTEXT_DIR} 27 | triggers: 28 | - type: "GitHub" 29 | github: 30 | secret: ${GITHUB_WEBHOOK_SECRET} 31 | - type: "ConfigChange" 32 | strategy: 33 | type: "JenkinsPipeline" 34 | jenkinsPipelineStrategy: 35 | jenkinsfilePath: "Jenkinsfile" 36 | parameters: 37 | - description: The name for the application. 38 | name: APPLICATION_NAME 39 | required: true 40 | value: pipeline-test 41 | - description: The namespace to deploy into 42 | name: NAMESPACE 43 | required: true 44 | - description: Git source URI for application 45 | name: SOURCE_REPOSITORY_URL 46 | required: true 47 | value: https://github.com/redhat-cop/pipeline-library.git 48 | - description: Git branch/tag reference 49 | name: SOURCE_REPOSITORY_REF 50 | value: "master" 51 | - description: Path within Git project to build; empty for root project directory. 52 | name: CONTEXT_DIR 53 | value: 54 | - description: Path within Git project pointing to the pipeline run script 55 | name: PIPELINE_SCRIPT 56 | value: Jenkinsfile 57 | - description: GitHub trigger secret 58 | from: '[a-zA-Z0-9]{8}' 59 | generate: expression 60 | name: GITHUB_WEBHOOK_SECRET 61 | required: true -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/inventory/group_vars/seed-hosts.yml: -------------------------------------------------------------------------------- 1 | openshift_cluster_content: 2 | - object: notifications test 3 | content: 4 | - name: create project 5 | file: "{{ inventory_dir }}/../files/projects.yml" 6 | - name: create secret 7 | file: "{{ inventory_dir }}/../files/rocketchat-secret.yml" 8 | - name: build jenkins image 9 | template: "{{ inventory_dir }}/../../../../../../jenkins-s2i/jenkins-s2i.yml" 10 | params: "{{ inventory_dir }}/../files/params/jenkins-s2i.params" 11 | namespace: pipeline-library-test 12 | - name: deploy jenkins 13 | template: "openshift//jenkins-ephemeral" 14 | params: "{{ inventory_dir }}/../files/params/jenkins-deployment.params" 15 | namespace: pipeline-library-test 16 | - name: test pipeline build 17 | template: "{{ inventory_dir }}/../files/templates/build-template.yml" 18 | params: "{{ inventory_dir }}/../files/params/notifications-build.params" -------------------------------------------------------------------------------- /test/org/redhatcop/util/rocketchat/inventory/hosts: -------------------------------------------------------------------------------- 1 | [seed-hosts] 2 | localhost ansible_connection=local 3 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/Jenkinsfile: -------------------------------------------------------------------------------- 1 | 2 | @Library('cop-library') _ 3 | 4 | node ('maven') { 5 | stage('Code Build') { 6 | git url: "${SOURCE_CODE_URL}" 7 | sh "mvn clean install -q" 8 | } 9 | 10 | stage('Image Build') { 11 | echo 'Building Image from Jar File' 12 | sh """ 13 | set +x 14 | rm -rf oc-build && mkdir -p oc-build/deployments 15 | for t in \$(echo "jar;war;ear" | tr ";" "\\n"); do 16 | cp -rfv ./target/*.\$t oc-build/deployments/ 2> /dev/null || echo "No \$t files" 17 | done 18 | """ 19 | script { 20 | openshift.withCluster() { 21 | openshift.startBuild("spring-rest", "--from-dir=oc-build", "--wait", "--follow") 22 | } 23 | } 24 | } 25 | 26 | stage ('Verify Deployment to Dev') { 27 | script { 28 | openshift.withCluster() { 29 | def dcObj = openshift.selector('dc', "spring-rest").object() 30 | def podSelector = openshift.selector('pod', [deployment: "spring-rest-${dcObj.status.latestVersion}"]) 31 | podSelector.untilEach { 32 | echo "pod: ${it.name()}" 33 | return it.object().status.containerStatuses[0].ready 34 | } 35 | } 36 | } 37 | } 38 | 39 | stage('Test Rollback') { 40 | rollback(deploymentConfig: "dc/spring-rest") 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/README.md: -------------------------------------------------------------------------------- 1 | # Testing the org.redhatcop.util.rollback package 2 | 3 | This directory contains a test inventory for testing the `org.redhatcop.utils.rollback` package in OpenShift. It requires [casl-ansible](https://github.com/redhat-cop/casl-ansible.git) to test. This can be pulled in via ansible-galaxy. 4 | 5 | ## Dependencies 6 | [redhat-openjdk-18/openjdk18-openshift](https://access.redhat.com/containers/?tab=overview#/registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift) is needed in the `openshift` project to build the test app. Add the image to your `openshift` project: `oc import-image openshift/openjdk18-openshift --from=registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift --confirm` 7 | 8 | ## Steps to test 9 | 10 | 1. Pull in dependencies 11 | ``` 12 | ansible-galaxy install -r requirements.yml -p deps 13 | ``` 14 | 2. Run ansible. 15 | ``` 16 | ansible-playbook -i .test/org/redhatcop/util/rollback/inventory/ deps/casl-ansible/playbooks/openshift-cluster-seed.yml 17 | ``` 18 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/files/params/build: -------------------------------------------------------------------------------- 1 | NAMESPACE=pipeline-library-test 2 | PIPELINE_REPOSITORY_URL=https://github.com/Gl4di4torRr/pipeline-library.git 3 | PIPELINE_REPOSITORY_REF=rollback 4 | CONTEXT_DIR=test/org/redhatcop/util/rollback -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/files/params/deploy: -------------------------------------------------------------------------------- 1 | APPLICATION_NAME=spring-rest 2 | NAMESPACE=pipeline-library-test 3 | SA_NAMESPACE=pipeline-library-test 4 | READINESS_RESPONSE=status.:.UP 5 | READINESS_PATH=/health -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/files/params/jenkins-deployment: -------------------------------------------------------------------------------- 1 | NAMESPACE=pipeline-library-test 2 | JENKINS_IMAGE_STREAM_TAG=jenkins2-s2i:latest -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/files/params/jenkins-s2i: -------------------------------------------------------------------------------- 1 | JENKINS_GIT_URL=https://github.com/redhat-cop/pipeline-library.git 2 | JENKINS_GIT_BRANCH=master 3 | JENKINS_GIT_CONTEXT_DIR=jenkins-s2i/ 4 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/files/projects.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: List 3 | items: 4 | - kind: ProjectRequest 5 | apiVersion: v1 6 | metadata: 7 | name: pipeline-library-test 8 | creationTimestam: null 9 | displayName: Pipeline Library Testing Project -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/files/templates/build.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | labels: 4 | template: generic-java-jenkins-pipeline 5 | metadata: 6 | annotations: 7 | description: Application template for JWS applications built using a Jenkins Pipeline 8 | iconClass: icon-tomcat 9 | tags: tomcat,tomcat8,java,jboss,xpaas,jenkins-ci 10 | version: 1.2.0 11 | name: generic-java-jenkins-pipeline 12 | objects: 13 | - kind: "BuildConfig" 14 | apiVersion: "v1" 15 | metadata: 16 | labels: 17 | application: ${APPLICATION_NAME} 18 | name: "${APPLICATION_NAME}-pipeline" 19 | namespace: "${NAMESPACE}" 20 | spec: 21 | source: 22 | type: Git 23 | git: 24 | uri: ${PIPELINE_REPOSITORY_URL} 25 | ref: ${PIPELINE_REPOSITORY_REF} 26 | contextDir: ${CONTEXT_DIR} 27 | triggers: 28 | - type: "GitHub" 29 | github: 30 | secret: ${GITHUB_WEBHOOK_SECRET} 31 | - type: "ConfigChange" 32 | strategy: 33 | type: "JenkinsPipeline" 34 | jenkinsPipelineStrategy: 35 | jenkinsfilePath: ${PIPELINE_SCRIPT} 36 | env: 37 | - name: SOURCE_CODE_URL 38 | value: ${SOURCE_CODE_URL} 39 | - name: SOURCE_CODE_BRANCH 40 | value: ${SOURCE_CODE_BRANCH} 41 | - apiVersion: v1 42 | kind: BuildConfig 43 | metadata: 44 | labels: 45 | application: ${APPLICATION_NAME} 46 | name: ${APPLICATION_NAME} 47 | namespace: "${NAMESPACE}" 48 | spec: 49 | output: 50 | to: 51 | kind: ImageStreamTag 52 | name: ${APPLICATION_NAME}:latest 53 | source: 54 | binary: {} 55 | type: Binary 56 | strategy: 57 | sourceStrategy: 58 | from: 59 | kind: ImageStreamTag 60 | name: ${IMAGE_STREAM_TAG_NAME} 61 | namespace: ${IMAGE_STREAM_NAMESPACE} 62 | type: Source 63 | parameters: 64 | - description: The name for the application. 65 | name: APPLICATION_NAME 66 | required: true 67 | value: spring-rest 68 | - description: The namespace to deploy into 69 | name: NAMESPACE 70 | required: true 71 | - description: Git source URI for application 72 | name: PIPELINE_REPOSITORY_URL 73 | required: true 74 | value: https://github.com/redhat-cop/pipeline-library.git 75 | - description: Git branch/tag reference 76 | name: PIPELINE_REPOSITORY_REF 77 | value: "master" 78 | - description: Path within Git project to build; empty for root project directory. 79 | name: CONTEXT_DIR 80 | value: 81 | - description: Path within Git project pointing to the pipeline run script 82 | name: PIPELINE_SCRIPT 83 | value: Jenkinsfile 84 | - description: Git source URI for application 85 | name: SOURCE_CODE_URL 86 | required: true 87 | value: https://github.com/redhat-cop/spring-rest.git 88 | - description: Git branch/tag reference 89 | name: SOURCE_CODE_REF 90 | value: "master" 91 | - description: GitHub trigger secret 92 | from: '[a-zA-Z0-9]{8}' 93 | generate: expression 94 | name: GITHUB_WEBHOOK_SECRET 95 | required: true 96 | - description: Generic build trigger secret 97 | from: '[a-zA-Z0-9]{8}' 98 | generate: expression 99 | name: GENERIC_WEBHOOK_SECRET 100 | required: true 101 | - description: Namespace in which the ImageStreams for Red Hat Middleware images are 102 | installed. These ImageStreams are normally installed in the openshift namespace. 103 | You should only need to modify this if you've installed the ImageStreams in a 104 | different namespace/project. 105 | name: IMAGE_STREAM_NAMESPACE 106 | required: true 107 | value: openshift 108 | - description: Image stream tag for the image you'd like to use to build the application 109 | name: IMAGE_STREAM_TAG_NAME 110 | required: true 111 | value: openjdk18-openshift:latest -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/files/templates/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | labels: 4 | template: basic-spring-boot 5 | metadata: 6 | annotations: 7 | description: Application template for JWS applications built using a Jenkins Pipeline 8 | iconClass: icon-tomcat 9 | tags: java,spring 10 | version: 1.2.0 11 | name: basic-sprint-boot 12 | objects: 13 | - apiVersion: v1 14 | kind: Service 15 | metadata: 16 | annotations: 17 | description: The web server's http port. 18 | labels: 19 | application: ${APPLICATION_NAME} 20 | name: ${APPLICATION_NAME} 21 | namespace: ${NAMESPACE} 22 | spec: 23 | ports: 24 | - port: 8080 25 | targetPort: 8080 26 | selector: 27 | deploymentConfig: ${APPLICATION_NAME} 28 | - apiVersion: v1 29 | id: ${APPLICATION_NAME}-http 30 | kind: Route 31 | metadata: 32 | annotations: 33 | description: Route for application's http service. 34 | labels: 35 | application: ${APPLICATION_NAME} 36 | name: ${APPLICATION_NAME} 37 | namespace: ${NAMESPACE} 38 | spec: 39 | host: ${HOSTNAME_HTTP} 40 | to: 41 | name: ${APPLICATION_NAME} 42 | - apiVersion: v1 43 | kind: ImageStream 44 | metadata: 45 | labels: 46 | application: ${APPLICATION_NAME} 47 | name: ${APPLICATION_NAME} 48 | namespace: ${NAMESPACE} 49 | - apiVersion: v1 50 | kind: DeploymentConfig 51 | metadata: 52 | labels: 53 | application: ${APPLICATION_NAME} 54 | name: ${APPLICATION_NAME} 55 | namespace: ${NAMESPACE} 56 | spec: 57 | replicas: 1 58 | selector: 59 | deploymentConfig: ${APPLICATION_NAME} 60 | strategy: 61 | type: Recreate 62 | template: 63 | metadata: 64 | labels: 65 | application: ${APPLICATION_NAME} 66 | deploymentConfig: ${APPLICATION_NAME} 67 | name: ${APPLICATION_NAME} 68 | spec: 69 | containers: 70 | - env: 71 | - name: JWS_ADMIN_USERNAME 72 | value: ${JWS_ADMIN_USERNAME} 73 | - name: JWS_ADMIN_PASSWORD 74 | value: ${JWS_ADMIN_PASSWORD} 75 | image: ${APPLICATION_NAME} 76 | imagePullPolicy: Always 77 | name: ${APPLICATION_NAME} 78 | ports: 79 | - containerPort: 8778 80 | name: jolokia 81 | protocol: TCP 82 | - containerPort: 8080 83 | name: http 84 | protocol: TCP 85 | readinessProbe: 86 | exec: 87 | command: 88 | - /bin/bash 89 | - -c 90 | - curl -s 'http://localhost:8080${READINESS_PATH}' 91 | |grep -iq '${READINESS_RESPONSE}' 92 | terminationGracePeriodSeconds: 60 93 | triggers: 94 | - imageChangeParams: 95 | automatic: true 96 | containerNames: 97 | - ${APPLICATION_NAME} 98 | from: 99 | kind: ImageStreamTag 100 | name: ${APPLICATION_NAME}:latest 101 | type: ImageChange 102 | - type: ConfigChange 103 | - apiVersion: v1 104 | groupNames: null 105 | kind: RoleBinding 106 | metadata: 107 | creationTimestamp: null 108 | labels: 109 | template: basic-tomcat-template 110 | name: jenkins_edit 111 | namespace: ${NAMESPACE} 112 | roleRef: 113 | name: edit 114 | subjects: 115 | - kind: ServiceAccount 116 | name: ${SA_NAME} 117 | namespace: ${SA_NAMESPACE} 118 | userNames: 119 | - system:serviceaccount:${SA_NAMESPACE}:${SA_NAME} 120 | parameters: 121 | - description: The name for the application. 122 | name: APPLICATION_NAME 123 | required: true 124 | value: jws-app 125 | - description: The namespace to deploy into 126 | name: NAMESPACE 127 | required: true 128 | - description: Name of a service account that can deploy to this project 129 | name: SA_NAME 130 | required: true 131 | value: jenkins 132 | - description: Namespace of service account that can deploy to this project 133 | name: SA_NAMESPACE 134 | required: true 135 | - description: 'Custom hostname for http service route. Leave blank for default hostname, 136 | e.g.: -.' 137 | name: HOSTNAME_HTTP 138 | - description: 'URI to check for app health' 139 | name: READINESS_PATH 140 | required: true 141 | value: '/' 142 | - description: 'String value expected back from readiness check' 143 | name: READINESS_RESPONSE 144 | required: true 145 | value: 'Hello World!' -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/inventory/group_vars/seed-hosts.yml: -------------------------------------------------------------------------------- 1 | openshift_cluster_content: 2 | - object: rollback test 3 | content: 4 | - name: create project 5 | file: "{{ inventory_dir }}/../files/projects.yml" 6 | - name: build jenkins image 7 | template: "{{ inventory_dir }}/../../../../../../jenkins-s2i/jenkins-s2i.yml" 8 | params: "{{ inventory_dir }}/../files/params/jenkins-s2i" 9 | namespace: pipeline-library-test 10 | - name: deploy jenkins 11 | template: "openshift//jenkins-ephemeral" 12 | params: "{{ inventory_dir }}/../files/params/jenkins-deployment" 13 | namespace: pipeline-library-test 14 | - name: test pipeline deploy 15 | template: "{{ inventory_dir }}/../files/templates/deployment.yml" 16 | params: "{{ inventory_dir }}/../files/params/deploy" 17 | - name: test pipeline build 18 | template: "{{ inventory_dir }}/../files/templates/build.yml" 19 | params: "{{ inventory_dir }}/../files/params/build" 20 | -------------------------------------------------------------------------------- /test/org/redhatcop/util/rollback/inventory/hosts: -------------------------------------------------------------------------------- 1 | [seed-hosts] 2 | localhost ansible_connection=local 3 | -------------------------------------------------------------------------------- /vars/applier.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | // orginial from https://github.com/redhat-cop/pipeline-library/blob/master/vars/applier.groovy 4 | 5 | class ApplierInput implements Serializable { 6 | //Required 7 | String inventoryPath = '' 8 | String requirementsPath = '' 9 | String ansibleRootDir = '' 10 | String rolesPath = 'galaxy' 11 | String applierPlaybook = 'galaxy/openshift-applier/playbooks/openshift-cluster-seed.yml' 12 | 13 | //Optional 14 | String playbookAdditionalArgs = '' 15 | String secretName = '' 16 | 17 | //Optional - Platform 18 | String clusterAPI = '' 19 | String clusterToken = '' 20 | Integer loglevel = 0 21 | } 22 | 23 | def call(Map input) { 24 | call(new ApplierInput(input)) 25 | } 26 | 27 | def call(ApplierInput input) { 28 | assert input.inventoryPath?.trim() : "Param inventoryPath should be defined." 29 | assert input.requirementsPath?.trim() : "Param requirementsPath should be defined." 30 | assert input.ansibleRootDir?.trim() : "Param ansibleRootDir should be defined." 31 | assert input.rolesPath?.trim() : "Param rolesPath should be defined." 32 | assert input.applierPlaybook?.trim() : "Param applierPlaybook should be defined." 33 | 34 | openshift.loglevel(input.loglevel) 35 | 36 | def clusterAPI 37 | def clusterToken 38 | 39 | // if secretName is given then get cluster token from there 40 | // else use given clusterToken 41 | // useful to prevent loading the cluster token from secret over and over again 42 | // which can be a slow operation but also preserves backward compatibility in this function 43 | if(!input.secretName.allWhitespace) { 44 | openshift.withCluster() { 45 | def secretData = openshift.selector("secret/${input.secretName}").object().data 46 | def encodedToken = secretData.token 47 | 48 | clusterToken = sh(script:"set +x; echo ${encodedToken} | base64 --decode", returnStdout: true) 49 | clusterAPI = input.clusterAPI 50 | } 51 | } else { 52 | clusterAPI = input.clusterAPI 53 | clusterToken = input.clusterToken 54 | } 55 | 56 | openshift.withCluster(clusterAPI, clusterToken) { 57 | openshift.withProject() { 58 | openshift.raw("login") 59 | 60 | sh """ 61 | pushd ${input.ansibleRootDir} 62 | ansible-galaxy install --role-file=${input.requirementsPath} --roles-path=${input.rolesPath} 63 | ansible-playbook -i ${input.inventoryPath} ${input.applierPlaybook} ${input.playbookAdditionalArgs} 64 | popd 65 | """ 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /vars/applier.txt: -------------------------------------------------------------------------------- 1 | # applier 2 | 3 | ## Summary 4 | 5 | Applier executes [openshift-applier](https://github.com/redhat-cop/openshift-applier) templates on a specified cluster. 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | - Ansible 14 | 15 | ### Parameters 16 | 17 | The method supports the following parameters: 18 | ```groovy 19 | // applier.groovy#L6-L20 20 | 21 | //Required 22 | String inventoryPath = '' 23 | String requirementsPath = '' 24 | String ansibleRootDir = '' 25 | String rolesPath = 'galaxy' 26 | String applierPlaybook = 'galaxy/openshift-applier/playbooks/openshift-cluster-seed.yml' 27 | 28 | //Optional 29 | String playbookAdditionalArgs = '' 30 | String secretName = '' 31 | 32 | //Optional - Platform 33 | String clusterAPI = '' 34 | String clusterToken = '' 35 | Integer loglevel = 0 36 | ``` 37 | 38 | ### Example 39 | 40 | ```groovy 41 | // ../test/Jenkinsfile-applier#L11-L22 42 | 43 | stage("TEST: Run applier for 'build-s2i-executable'") { 44 | withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'pipelinelib-testing-my-token', usernameVariable: 'USERNAME', passwordVariable: 'TOKEN']]) { 45 | applier([ 46 | inventoryPath : ".applier/hosts", 47 | requirementsPath: "requirements.yml", 48 | ansibleRootDir : "${WORKSPACE}/containers-quickstarts/build-s2i-executable", 49 | applierPlaybook : "galaxy/openshift-applier/playbooks/openshift-cluster-seed.yml", 50 | clusterAPI : "https://kubernetes.default.svc", 51 | clusterToken : "${TOKEN}" 52 | ]) 53 | } 54 | } 55 | ``` 56 | 57 | ### Local vs Remote cluster support 58 | 59 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 60 | the ability to connect to a the local cluster, a cluster via URL/Token or using 61 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 62 | as setting the clusterAPI and clusterToken parameters. 63 | 64 | ### Secret Format 65 | 66 | This method supports using a secret (via secretName) which is used to login to the cluster that the applier will work against. Typically, 67 | a [service account token](https://docs.openshift.com/container-platform/3.11/dev_guide/service_accounts.html#using-a-service-accounts-credentials-externally) 68 | would be used within the secret. 69 | 70 | ```yaml 71 | --- 72 | kind: Template 73 | apiVersion: v1 74 | metadata: 75 | name: cluster-credential-secret 76 | annotations: 77 | openshift.io/display-name: Cluster Credential Secret 78 | objects: 79 | - apiVersion: v1 80 | kind: Secret 81 | metadata: 82 | name: "${NAME}" 83 | labels: 84 | credential.sync.jenkins.openshift.io: "true" 85 | type: Opaque 86 | data: 87 | api: "${API_B64}" 88 | token: "${TOKEN_B64}" 89 | parameters: 90 | - name: NAME 91 | displayName: Name 92 | description: The name of secret. 93 | required: true 94 | - name: API_B64 95 | displayName: API 96 | description: API url of the cluster the credential is for. 97 | required: true 98 | - name: TOKEN_B64 99 | displayName: Token 100 | description: Token to use when authenticating. 101 | required: true 102 | ``` -------------------------------------------------------------------------------- /vars/applyTemplate.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class ApplyTemplateInput implements Serializable { 4 | //Required 5 | String templateFile 6 | 7 | //Optional 8 | String parameterFile 9 | 10 | //Optional - Platform 11 | String clusterUrl = "" 12 | String clusterAPI = "" 13 | String clusterToken = "" 14 | String projectName = "" 15 | Integer loglevel = 0 16 | } 17 | 18 | def call(Map input) { 19 | call(new ApplyTemplateInput(input)) 20 | } 21 | 22 | def call(ApplyTemplateInput input) { 23 | assert input.templateFile?.trim() : "Param templateFile should be defined." 24 | 25 | openshift.loglevel(input.loglevel) 26 | 27 | if (input.clusterUrl?.trim().length() > 0) { 28 | error "clusterUrl is deprecated and will be removed in the next release. Please use 'clusterAPI'" 29 | } 30 | 31 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 32 | openshift.withProject(input.projectName) { 33 | def fileNameArg = input.templateFile.toLowerCase().startsWith("http") ? input.templateFile : "--filename=${input.templateFile}" 34 | def parameterFileArg = input.parameterFile?.trim()?.length() <= 0 ? "" : "--param-file=${input.parameterFile}" 35 | 36 | echo "Attempting to process template '${fileNameArg}' in ${openshift.project()}" 37 | 38 | def models = openshift.process(fileNameArg, parameterFileArg, "--ignore-unknown-parameters") 39 | 40 | echo "Processed template '${fileNameArg}' will instantiate ${models.size()} objects" 41 | 42 | def created = openshift.apply( models ) 43 | echo "Created: ${created.names()}" 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vars/applyTemplate.txt: -------------------------------------------------------------------------------- 1 | # applyTemplate 2 | 3 | ## Summary 4 | 5 | Process and apply an OpenShift [template](https://docs.openshift.com/container-platform/3.11/dev_guide/templates.html). 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | 14 | ### Parameters 15 | 16 | The method supports the following parameters: 17 | ```groovy 18 | // applyTemplate.groovy#L4-L15 19 | 20 | //Required 21 | String templateFile 22 | 23 | //Optional 24 | String parameterFile 25 | 26 | //Optional - Platform 27 | String clusterUrl = "" 28 | String clusterAPI = "" 29 | String clusterToken = "" 30 | String projectName = "" 31 | Integer loglevel = 0 32 | ``` 33 | 34 | ### Example 35 | 36 | ```groovy 37 | // ../test/Jenkinsfile-applyTemplate#L11-L16 38 | 39 | stage("TEST: Can deploy via local file") { 40 | applyTemplate([ 41 | templateFile : "cakephp-mysql.json" 42 | ]) 43 | } 44 | ``` 45 | 46 | ### Local vs Remote cluster support 47 | 48 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 49 | the ability to connect to a the local cluster, a cluster via URL/Token or using 50 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 51 | as setting the clusterAPI and clusterToken parameters. -------------------------------------------------------------------------------- /vars/binaryBuild.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class BinaryBuildInput implements Serializable { 4 | //Required 5 | String buildConfigName = "" 6 | String buildFromFlag = "--from-dir" 7 | String buildFromPath = "" 8 | 9 | //Optional - Platform 10 | String clusterAPI = "" 11 | String clusterToken = "" 12 | String projectName = "" 13 | Integer loglevel = 0 14 | } 15 | 16 | def call(Map input) { 17 | call(new BinaryBuildInput(input)) 18 | } 19 | 20 | def call(BinaryBuildInput input) { 21 | assert input.buildConfigName?.trim() : "Param buildConfigName should be defined." 22 | assert input.buildFromFlag?.trim() : "Param buildFromFlag should be defined." 23 | assert input.buildFromPath?.trim() : "Param buildFromPath should be defined." 24 | 25 | openshift.loglevel(input.loglevel) 26 | 27 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 28 | openshift.withProject(input.projectName) { 29 | echo "Attemping to start and follow 'buildconfig/${input.buildConfigName}' in ${openshift.project()}" 30 | 31 | def buildConfig = openshift.selector('bc', input.buildConfigName) 32 | def build = buildConfig.startBuild("${input.buildFromFlag}=${input.buildFromPath}", '--wait') 33 | build.logs('-f') 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vars/binaryBuild.txt: -------------------------------------------------------------------------------- 1 | # binaryBuild 2 | 3 | ## Summary 4 | 5 | Trigger a BuildConfig using the [binary build strategy](https://docs.openshift.com/container-platform/3.11/dev_guide/dev_tutorials/binary_builds.html). 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | 14 | ### Parameters 15 | 16 | The method supports the following parameters: 17 | ```groovy 18 | // binaryBuild.groovy#L4-L13 19 | 20 | //Required 21 | String buildConfigName = "" 22 | String buildFromFlag = "--from-dir" 23 | String buildFromPath = "" 24 | 25 | //Optional - Platform 26 | String clusterAPI = "" 27 | String clusterToken = "" 28 | String projectName = "" 29 | Integer loglevel = 0 30 | ``` 31 | 32 | ### Example 33 | 34 | ```groovy 35 | // ../test/Jenkinsfile-binaryBuild#L33-L39 36 | 37 | stage("TEST: Can build using from-file") { 38 | binaryBuild([ 39 | buildConfigName: "sample-build-binary", 40 | buildFromFlag : "--from-dir", 41 | buildFromPath : "${WORKSPACE}/build/" 42 | ]) 43 | } 44 | ``` 45 | 46 | ### Local vs Remote cluster support 47 | 48 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 49 | the ability to connect to a the local cluster, a cluster via URL/Token or using 50 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 51 | as setting the clusterAPI and clusterToken parameters. -------------------------------------------------------------------------------- /vars/buildAndTag.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class BuildAndTagInput implements Serializable { 4 | //Required 5 | String imageName = '' 6 | String imageNamespace = '' 7 | String imageVersion = '' 8 | String registryFQDN = '' 9 | 10 | //Optional 11 | String fromFilePath = "" 12 | String tagDestinationTLSVerify = "true" 13 | String tagSourceTLSVerify = "true" 14 | String tagAuthFile = "/var/run/secrets/kubernetes.io/dockerconfigjson/.dockerconfigjson" 15 | String tagDestinationCertDir = "/run/secrets/kubernetes.io/serviceaccount/" 16 | String tagSourceCertDir = "/run/secrets/kubernetes.io/serviceaccount/" 17 | 18 | //Optional - Platform 19 | String clusterAPI = "" 20 | String clusterToken = "" 21 | String buildProjectName = "" 22 | Integer loglevel = 0 23 | } 24 | 25 | def call(Map input) { 26 | call(new BuildAndTagInput(input)) 27 | } 28 | 29 | def call(BuildAndTagInput input) { 30 | assert input.imageName?.trim() : "Param imageName should be defined." 31 | assert input.imageNamespace?.trim() : "Param imageNamespace should be defined." 32 | assert input.imageVersion?.trim() : "Param imageVersion should be defined." 33 | assert input.registryFQDN?.trim() : "Param registryFQDN should be defined." 34 | 35 | binaryBuild([ 36 | clusterAPI : input.clusterAPI, 37 | clusterToken : input.clusterToken, 38 | projectName : input.buildProjectName, 39 | buildConfigName: input.imageName, 40 | buildFromPath : input.fromFilePath, 41 | loglevel: input.loglevel 42 | ]) 43 | 44 | def authFileArg = input.tagAuthFile?.trim()?.length() <= 0 ? "" : "--authfile=${input.tagAuthFile}" 45 | def srcTlsVerifyArg = input.tagSourceTLSVerify?.trim()?.length() <= 0 ? "" : "--src-tls-verify=${input.tagSourceTLSVerify}" 46 | def destTlsVerifyArg = input.tagDestinationTLSVerify?.trim()?.length() <= 0 ? "" : "--dest-tls-verify=${input.tagDestinationTLSVerify}" 47 | def destCertDirArg = input.tagDestinationCertDir?.trim()?.length() <= 0 ? "" : "--dest-cert-dir=${input.tagDestinationCertDir}" 48 | def srcCertDirArg = input.tagSourceCertDir?.trim()?.length() <= 0 ? "" : "--src-cert-dir=${input.tagSourceCertDir}" 49 | 50 | def source = "docker://${input.registryFQDN}/${input.imageNamespace}/${input.imageName}:latest" 51 | def destination = "docker://${input.registryFQDN}/${input.imageNamespace}/${input.imageName}:${input.imageVersion}" 52 | 53 | echo "Attempting to tag; ${source} -> ${destination}" 54 | 55 | sh "skopeo copy $authFileArg $srcTlsVerifyArg $destTlsVerifyArg $destCertDirArg $srcCertDirArg $source $destination" 56 | } 57 | -------------------------------------------------------------------------------- /vars/buildAndTag.txt: -------------------------------------------------------------------------------- 1 | # buildAndTag 2 | 3 | ## Summary 4 | 5 | Trigger a BuildConfig using the [binary build strategy](https://docs.openshift.com/container-platform/3.11/dev_guide/dev_tutorials/binary_builds.html) 6 | and tag the resulting image. 7 | 8 | ## Usage 9 | 10 | ### Requirements 11 | 12 | Requires Jenkins agent with: 13 | - OC 14 | - Skopeo 15 | 16 | ### Parameters 17 | 18 | The method supports the following parameters: 19 | ```groovy 20 | // buildAndTag.groovy#L4-L22 21 | 22 | //Required 23 | String imageName = '' 24 | String imageNamespace = '' 25 | String imageVersion = '' 26 | String registryFQDN = '' 27 | 28 | //Optional 29 | String fromFilePath = "" 30 | String tagDestinationTLSVerify = "true" 31 | String tagSourceTLSVerify = "true" 32 | String tagAuthFile = "/var/run/secrets/kubernetes.io/dockerconfigjson/.dockerconfigjson" 33 | String tagDestinationCertDir = "/run/secrets/kubernetes.io/serviceaccount/" 34 | String tagSourceCertDir = "/run/secrets/kubernetes.io/serviceaccount/" 35 | 36 | //Optional - Platform 37 | String clusterAPI = "" 38 | String clusterToken = "" 39 | String buildProjectName = "" 40 | Integer loglevel = 0 41 | ``` 42 | 43 | ### Example 44 | 45 | ```groovy 46 | // ../test/Jenkinsfile-buildAndTag#L50-L58 47 | 48 | stage("TEST: Can build and tag") { 49 | buildAndTag([ 50 | imageName : "sample-build", 51 | fromFilePath : "${WORKSPACE}/target/", 52 | registryFQDN : "${dockerRegistry}", 53 | imageNamespace: "pipelinelib-testing", 54 | imageVersion : "v2" 55 | ]) 56 | } 57 | ``` 58 | 59 | ### Local vs Remote cluster support 60 | 61 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 62 | the ability to connect to a the local cluster, a cluster via URL/Token or using 63 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 64 | as setting the clusterAPI and clusterToken parameters. -------------------------------------------------------------------------------- /vars/clusterCredentials.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class ClusterCredentialsInput implements Serializable { 4 | //Required 5 | String secretName = "" 6 | 7 | //Optional 8 | boolean insecure = false 9 | 10 | //Optional - Platform 11 | String clusterAPI = "" 12 | String clusterToken = "" 13 | String projectName = "" 14 | Integer loglevel = 0 15 | } 16 | 17 | def call(Map input) { 18 | call(new ClusterCredentialsInput(input)) 19 | } 20 | 21 | def call(ClusterCredentialsInput input) { 22 | assert input.secretName?.trim() : "Param secretName should be defined." 23 | 24 | openshift.loglevel(input.loglevel) 25 | 26 | def encodedApi 27 | def encodedToken 28 | 29 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 30 | openshift.withProject(input.projectName) { 31 | echo "Attemping to retrieve ClusterCredentials 'secret/${input.secretName}' in ${openshift.project()}" 32 | 33 | def secret = openshift.selector("secret/${input.secretName}") 34 | def secretObject = secret.object() 35 | def secretData = secretObject.data 36 | 37 | encodedApi = secretData.api 38 | encodedToken = secretData.token 39 | } 40 | } 41 | 42 | def api = sh(script:"set +x; echo ${encodedApi} | base64 --decode", returnStdout: true) 43 | def token = sh(script:"set +x; echo ${encodedToken} | base64 --decode", returnStdout: true) 44 | 45 | //NOTE: the regex here makes it so that the jenkins-client-plugin wont verify the CA 46 | api = input.insecure ? api.replaceAll(/https?/, 'insecure') : api 47 | 48 | return [api, token] 49 | } 50 | -------------------------------------------------------------------------------- /vars/clusterCredentials.txt: -------------------------------------------------------------------------------- 1 | # clusterCredentials 2 | 3 | ## Summary 4 | 5 | Retrieve a [Secret](https://docs.openshift.com/container-platform/3.11/dev_guide/secrets.html) which contains 6 | credentials to authenticate against a cluster. 7 | 8 | ## Usage 9 | 10 | ### Requirements 11 | 12 | Requires Jenkins agent with: 13 | - OC 14 | 15 | ### Parameters 16 | 17 | The method supports the following parameters: 18 | ```groovy 19 | // clusterCredentials.groovy#L4-L14 20 | 21 | //Required 22 | String secretName = "" 23 | 24 | //Optional 25 | boolean insecure = false 26 | 27 | //Optional - Platform 28 | String clusterAPI = "" 29 | String clusterToken = "" 30 | String projectName = "" 31 | Integer loglevel = 0 32 | ``` 33 | 34 | ### Example 35 | 36 | ```groovy 37 | // ../test/Jenkinsfile-clusterCredentials#L30-L34 38 | 39 | stage("TEST: Can get credential") { 40 | credentials = clusterCredentials([ 41 | secretName: "cluster-credential" 42 | ]) 43 | } 44 | ``` 45 | 46 | ### Local vs Remote cluster support 47 | 48 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 49 | the ability to connect to a the local cluster, a cluster via URL/Token or using 50 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 51 | as setting the clusterAPI and clusterToken parameters. 52 | 53 | ### Secret Format 54 | 55 | The credentials which are retrieved by this method are expected to be in a secret using the following format. 56 | 57 | ```yaml 58 | --- 59 | kind: Template 60 | apiVersion: v1 61 | metadata: 62 | name: cluster-credential-secret 63 | annotations: 64 | openshift.io/display-name: Cluster Credential Secret 65 | objects: 66 | - kind: Secret 67 | apiVersion: v1 68 | metadata: 69 | name: "${NAME}" 70 | labels: 71 | credential.sync.jenkins.openshift.io: "true" 72 | type: Opaque 73 | data: 74 | api: "${API_B64}" 75 | token: "${TOKEN_B64}" 76 | parameters: 77 | - name: NAME 78 | displayName: Name 79 | description: The name of secret. 80 | required: true 81 | - name: API_B64 82 | displayName: API 83 | description: API url of the cluster the credential is for. 84 | required: true 85 | - name: TOKEN_B64 86 | displayName: Token 87 | description: Authentication token for the cluster. 88 | required: true 89 | ``` -------------------------------------------------------------------------------- /vars/configMap.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class ConfigMapInput implements Serializable { 4 | //Required 5 | String configMapName = "" 6 | 7 | //Optional - Platform 8 | String clusterAPI = "" 9 | String clusterToken = "" 10 | String projectName = "" 11 | Integer loglevel = 0 12 | } 13 | 14 | def call(Map input) { 15 | call(new ConfigMapInput(input)) 16 | } 17 | 18 | def call(ConfigMapInput input) { 19 | assert input.configMapName?.trim() : "Param configMapName should be defined." 20 | 21 | openshift.loglevel(input.loglevel) 22 | 23 | def configMapData 24 | 25 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 26 | openshift.withProject(input.projectName) { 27 | echo "Attemping to retrieve 'configmap/${input.configMapName}' in ${openshift.project()}" 28 | 29 | def configMap = openshift.selector("configmap/${input.configMapName}") 30 | def configMapObject = configMap.object() 31 | configMapData = configMapObject.data 32 | } 33 | } 34 | 35 | return configMapData 36 | } 37 | -------------------------------------------------------------------------------- /vars/configMap.txt: -------------------------------------------------------------------------------- 1 | # configMap 2 | 3 | ## Summary 4 | 5 | Retrieve a (ConfigMap)[https://docs.openshift.com/container-platform/3.11/dev_guide/configmaps.html] data. 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | 14 | ### Parameters 15 | 16 | The method supports the following parameters: 17 | ```groovy 18 | // configMap.groovy#L4-L11 19 | 20 | //Required 21 | String configMapName = "" 22 | 23 | //Optional - Platform 24 | String clusterAPI = "" 25 | String clusterToken = "" 26 | String projectName = "" 27 | Integer loglevel = 0 28 | ``` 29 | 30 | ### Example 31 | 32 | ```groovy 33 | // ../test/Jenkinsfile-configMap#L29-L33 34 | 35 | stage("TEST: Can get configmap data") { 36 | configMapData = configMap([ 37 | configMapName: "game-config" 38 | ]) 39 | } 40 | ``` 41 | 42 | ### Local vs Remote cluster support 43 | 44 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 45 | the ability to connect to a the local cluster, a cluster via URL/Token or using 46 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 47 | as setting the clusterAPI and clusterToken parameters. -------------------------------------------------------------------------------- /vars/crossClusterPromote.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class CopyImageInput implements Serializable { 4 | //Required 5 | String sourceImageName 6 | String sourceImageTag = "latest" 7 | String destinationImageName 8 | String destinationImageTag 9 | String destinationImagePath 10 | String targetRegistryCredentials = "other-cluster-credentials" 11 | 12 | //Optional 13 | String sourceImagePath = "" 14 | 15 | //Optional - Platform 16 | String clusterUrl = "" 17 | String clusterAPI = "" 18 | String clusterToken = "" 19 | Integer loglevel = 0 20 | 21 | CopyImageInput init() { 22 | if(!destinationImageName?.trim()) destinationImageName = sourceImageName 23 | if(!destinationImageTag?.trim()) destinationImageTag = sourceImageTag 24 | if(!destinationImagePath?.trim()) destinationImagePath = sourceImagePath 25 | return this 26 | } 27 | } 28 | 29 | def call(Map input) { 30 | call(new CopyImageInput(input).init()) 31 | } 32 | 33 | def call(CopyImageInput input) { 34 | assert input.targetRegistryCredentials?.trim() : "Param targetRegistryCredentials should be defined." 35 | assert input.sourceImageName?.trim() : "Param sourceImageName should be defined." 36 | assert input.sourceImageTag?.trim() : "Param sourceImageTag should be defined." 37 | assert input.destinationImagePath?.trim() : "Param destinationImagePath should be defined." 38 | assert input.destinationImageName?.trim() : "Param destinationImageName should be defined." 39 | assert input.destinationImageTag?.trim() : "Param destinationImageTag should be defined." 40 | 41 | openshift.loglevel(input.loglevel) 42 | 43 | if (input.clusterUrl?.trim().length() > 0) { 44 | error "clusterUrl is deprecated and will be removed in the next release. Please use 'clusterAPI'" 45 | } 46 | 47 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 48 | def localToken = readFile("/var/run/secrets/kubernetes.io/serviceaccount/token").trim() 49 | 50 | def secretData = openshift.selector("secret/${input.targetRegistryCredentials}").object().data 51 | def registry = sh(script:"set +x; echo ${secretData.registry} | base64 --decode", returnStdout: true) 52 | def token = sh(script:"set +x; echo ${secretData.token} | base64 --decode", returnStdout: true) 53 | def username = sh(script:"set +x; echo ${secretData.username} | base64 --decode", returnStdout: true) 54 | 55 | openshift.withProject(input.sourceImagePath) { 56 | def localRegistry = openshift.selector( "is", "${input.sourceImageName}").object().status.dockerImageRepository 57 | def from = "docker://${localRegistry}:${input.sourceImageTag}" 58 | def to = "docker://${registry}/${input.destinationImagePath}/${input.destinationImageName}:${input.destinationImageTag}" 59 | 60 | echo "Now Promoting ${from} -> ${to}" 61 | sh """ 62 | set +x 63 | skopeo copy --remove-signatures \ 64 | --src-creds openshift:${localToken} --src-cert-dir=/run/secrets/kubernetes.io/serviceaccount/ \ 65 | --dest-creds ${username}:${token} --dest-tls-verify=false ${from} ${to} 66 | """ 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /vars/crossClusterPromote.txt: -------------------------------------------------------------------------------- 1 | # crossClusterPromote 2 | 3 | ## Summary 4 | 5 | Promote an image from the local cluster to a remote registry. 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | - Skopeo 14 | 15 | ### Parameters 16 | 17 | The method supports the following parameters: 18 | ```groovy 19 | // crossClusterPromote.groovy#L4-L19 20 | 21 | //Required 22 | String sourceImageName 23 | String sourceImageTag = "latest" 24 | String destinationImageName 25 | String destinationImageTag 26 | String destinationImagePath 27 | String targetRegistryCredentials = "other-cluster-credentials" 28 | 29 | //Optional 30 | String sourceImagePath = "" 31 | 32 | //Optional - Platform 33 | String clusterUrl = "" 34 | String clusterAPI = "" 35 | String clusterToken = "" 36 | Integer loglevel = 0 37 | ``` 38 | 39 | ### Example 40 | 41 | ```groovy 42 | // ../test/Jenkinsfile-crossClusterPromote#L26-L33 43 | 44 | stage("TEST: Can promote image from one project to another") { 45 | crossClusterPromote([ 46 | sourceImageName : "jenkins-slave-ansible", 47 | sourceImagePath : "pipelinelib-testing", 48 | destinationImagePath : "pipelinelib-promotion-testing", 49 | targetRegistryCredentials: "local-registry-generic" 50 | ]) 51 | } 52 | ``` 53 | 54 | ### Local vs Remote cluster support 55 | 56 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 57 | the ability to connect to a the local cluster, a cluster via URL/Token or using 58 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 59 | as setting the clusterAPI and clusterToken parameters. 60 | 61 | ### Secret Format 62 | 63 | This method supports using a secret (via targetRegistryCredentials) which is used to login to the cluster that you want to push the image to. Typically, 64 | a [service account token](https://docs.openshift.com/container-platform/3.11/dev_guide/service_accounts.html#using-a-service-accounts-credentials-externally) 65 | would be used within the secret. 66 | 67 | ```yaml 68 | --- 69 | kind: Template 70 | apiVersion: v1 71 | metadata: 72 | name: cluster-promote-credential-secret 73 | annotations: 74 | openshift.io/display-name: Cluster Promote Credential Secret 75 | objects: 76 | - apiVersion: v1 77 | kind: Secret 78 | metadata: 79 | name: "${NAME}" 80 | type: Opaque 81 | data: 82 | username: "${USERNAME_B64}" 83 | token: "${TOKEN_B64}" 84 | registry: "${REGISTRY_URL_B64}" 85 | parameters: 86 | - name: NAME 87 | displayName: Name 88 | description: The name of secret. 89 | required: true 90 | - name: USERNAME_B64 91 | displayName: Username 92 | description: Username to use when authenticating against destination registry. 93 | required: true 94 | - name: TOKEN_B64 95 | displayName: Token 96 | description: Authentication token to use when authenticating against destination registry. 97 | required: true 98 | - name: REGISTRY_URL_B64 99 | displayName: Registry URL 100 | description: Registry URL of destination registry. 101 | required: true 102 | ``` -------------------------------------------------------------------------------- /vars/imageMirror.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class ImageMirrorInput implements Serializable { 4 | //Required 5 | String sourceSecret = "" 6 | String sourceRegistry = "" 7 | String destinationSecret = "" 8 | String destinationRegistry = "" 9 | String insecure = "false" 10 | String sourceNamespace = "" 11 | String destinationNamespace = "" 12 | String sourceImage = "" 13 | String destinationImage = "" 14 | String sourceImageVersion = "latest" 15 | String destinationImageVersion = "latest" 16 | 17 | //Optional - Platform 18 | Integer loglevel = 0 19 | 20 | ImageMirrorInput init() { 21 | if(!destinationImage?.trim()) destinationImage = sourceImage 22 | if(!destinationNamespace?.trim()) destinationNamespace = sourceNamespace 23 | return this 24 | } 25 | } 26 | 27 | def call(Map input) { 28 | call(new ImageMirrorInput(input).init()) 29 | } 30 | 31 | def call(ImageMirrorInput input) { 32 | assert input.sourceSecret?.trim(): "Param sourceSecret should be defined." 33 | assert input.sourceRegistry?.trim(): "Param sourceRegistry should be defined." 34 | assert input.destinationSecret?.trim(): "Param destinationSecret should be defined." 35 | assert input.destinationRegistry?.trim(): "Param destinationRegistry should be defined." 36 | assert input.sourceNamespace?.trim(): "Param sourceNamespace should be defined." 37 | assert input.sourceImage?.trim(): "Param sourceImage should be defined." 38 | assert input.destinationNamespace?.trim(): "Param destinationNamespace should be defined." 39 | assert input.destinationImage?.trim(): "Param destinationImage should be defined." 40 | assert input.destinationImageVersion?.trim(): "Param destinationImageVersion should be defined." 41 | assert input.insecure?.trim(): "Param insecure should be defined." 42 | 43 | openshift.loglevel(input.loglevel) 44 | 45 | String sourceApi = input.sourceRegistry.replaceFirst("^(http[s]?://\\.|http[s]?://)", "") 46 | String destinationApi = input.destinationRegistry.replaceFirst("^(http[s]?://\\.|http[s]?://)", "") 47 | 48 | withDockerRegistry([credentialsId: "${input.sourceSecret}", url: "${input.sourceRegistry}"]) { 49 | withDockerRegistry([credentialsId: "${input.destinationSecret}", url: "${input.destinationRegistry}"]) { 50 | openshift.withCluster() { 51 | def source = "${sourceApi}/${input.sourceNamespace}/${input.sourceImage}:${input.sourceImageVersion}" 52 | def destination = "${destinationApi}/${input.destinationNamespace}/${input.destinationImage}:${input.destinationImageVersion}" 53 | 54 | echo "Attempting to mirror; ${source} -> ${destination}" 55 | 56 | openshift.raw("image", "mirror", source, destination, "--insecure=${input.insecure}") 57 | } 58 | } 59 | } 60 | } 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /vars/imageMirror.txt: -------------------------------------------------------------------------------- 1 | # imageMirror 2 | 3 | ## Summary 4 | 5 | (Mirror)[https://docs.openshift.com/container-platform/3.11/dev_guide/managing_images.html#managing-images-mirror-registry-images] an image from one registry to another. 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | 14 | ### Parameters 15 | 16 | The method supports the following parameters: 17 | ```groovy 18 | // imageMirror.groovy#L4-L18 19 | 20 | //Required 21 | String sourceSecret = "" 22 | String sourceRegistry = "" 23 | String destinationSecret = "" 24 | String destinationRegistry = "" 25 | String insecure = "false" 26 | String sourceNamespace = "" 27 | String destinationNamespace = "" 28 | String sourceImage = "" 29 | String destinationImage = "" 30 | String sourceImageVersion = "latest" 31 | String destinationImageVersion = "latest" 32 | 33 | //Optional - Platform 34 | Integer loglevel = 0 35 | ``` 36 | 37 | ### Example 38 | 39 | ```groovy 40 | // ../test/Jenkinsfile-imageMirror#L35-L48 41 | 42 | stage("TEST: Can promote image from one project to another") { 43 | imageMirror([ 44 | sourceSecret : "pipelinelib-testing-my-token", 45 | sourceRegistry : "https://${dockerRegistry}", 46 | destinationSecret : "pipelinelib-testing-my-token", 47 | destinationRegistry : "https://${dockerRegistry}", 48 | insecure : "true", 49 | sourceNamespace : "pipelinelib-testing", 50 | destinationNamespace : "pipelinelib-promotion-testing", 51 | sourceImage : "jenkins-slave-image-mgmt", 52 | sourceImageVersion : "latest", 53 | destinationImageVersion: "latest" 54 | ]) 55 | } 56 | ``` 57 | 58 | ### Local vs Remote cluster support 59 | 60 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 61 | the ability to connect to a the local cluster, a cluster via URL/Token or using 62 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 63 | as setting the clusterAPI and clusterToken parameters. 64 | 65 | #### Secret Format 66 | 67 | This method supports using a Jenkins credential (via sourceSecret and destinationSecret) which is used to login to the cluster that the image mirror will work against. Typically, 68 | a [service account token](https://docs.openshift.com/container-platform/3.11/dev_guide/service_accounts.html#using-a-service-accounts-credentials-externally) 69 | would be used within the secret. 70 | 71 | ```yaml 72 | --- 73 | kind: Template 74 | apiVersion: v1 75 | metadata: 76 | name: image-mirror-credential-secret 77 | annotations: 78 | openshift.io/display-name: Image Mirror Credential Secret 79 | objects: 80 | - apiVersion: v1 81 | kind: Secret 82 | metadata: 83 | name: "${NAME}" 84 | labels: 85 | credential.sync.jenkins.openshift.io: "true" 86 | type: Opaque 87 | data: 88 | username: "${USERNAME_B64}" 89 | password: "${PASSWORD_B64}" 90 | parameters: 91 | - name: NAME 92 | displayName: Name 93 | description: The name of secret. 94 | required: true 95 | - name: USERNAME_B64 96 | displayName: Username 97 | description: Username to use when authenticating. 98 | required: true 99 | - name: PASSWORD_B64 100 | displayName: Password 101 | description: Password to use when authenticating. 102 | required: true 103 | ``` -------------------------------------------------------------------------------- /vars/patchBuildConfigOutputLabels.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | import groovy.json.JsonOutput 4 | 5 | // When using the non-declarative pipeline, git env variables need to be set through scm checkout 6 | class PatchBuildConfigOutputLabelsInput implements Serializable { 7 | //Required 8 | String domainPrefix = "com.redhat" 9 | String bcName = "" 10 | 11 | //Optional 12 | String clusterAPI = "" 13 | String clusterToken = "" 14 | String projectName = "" 15 | Integer loglevel = 0 16 | } 17 | 18 | def call(Map input) { 19 | call(new PatchBuildConfigOutputLabelsInput(input)) 20 | } 21 | 22 | def call(PatchBuildConfigOutputLabelsInput input) { 23 | assert input.domainPrefix?.trim(): "Param domainPrefix should be defined" 24 | assert input.bcName?.trim(): "Param bcName (build config name) should be defined" 25 | 26 | openshift.loglevel(input.loglevel) 27 | 28 | def patch = [ 29 | spec: [ 30 | output: [ 31 | imageLabels: [ 32 | [name: "${input.domainPrefix}.jenkins.build.url", value: "${env.BUILD_URL}"], 33 | [name: "${input.domainPrefix}.jenkins.build.tag", value: "${env.BUILD_NUMBER}"], 34 | [name: "${input.domainPrefix}.git.branch", value: "${env.GIT_BRANCH}"], 35 | [name: "${input.domainPrefix}.git.url", value: "${env.GIT_URL}"], 36 | [name: "${input.domainPrefix}.git.commit", value: "${env.GIT_COMMIT}"] 37 | ] 38 | ] 39 | ] 40 | ] 41 | 42 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 43 | openshift.withProject(input.projectName) { 44 | echo "Attemping to patch 'buildconfig/${input.bcName}' in ${openshift.project()}" 45 | 46 | def buildConfig = openshift.selector("bc", input.bcName) 47 | if (buildConfig.exists()) { 48 | openshift.patch(buildConfig.object(), "'" + JsonOutput.toJson(patch) + "'") 49 | } else { 50 | error "Failed to find 'bc/${input.bcName}' in ${openshift.project()}" 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /vars/patchBuildConfigOutputLabels.txt: -------------------------------------------------------------------------------- 1 | # patchBuildConfigOutputLabels 2 | 3 | ## Summary 4 | 5 | Patch a BuildConfig to contain annotations about the current Jenkins and GIT build information. 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | 14 | ### Parameters 15 | 16 | The method supports the following parameters: 17 | ```groovy 18 | // patchBuildConfigOutputLabels.groovy#L7-L15 19 | 20 | //Required 21 | String domainPrefix = "com.redhat" 22 | String bcName = "" 23 | 24 | //Optional 25 | String clusterAPI = "" 26 | String clusterToken = "" 27 | String projectName = "" 28 | Integer loglevel = 0 29 | ``` 30 | 31 | ### Example 32 | 33 | ```groovy 34 | // ../test/Jenkinsfile-patchBuildConfigOutputLabels#L18-L23 35 | 36 | stage("TEST: Can patch build config") { 37 | patchBuildConfigOutputLabels([ 38 | bcName : "sample-verbose-build", 39 | domainPrefix: "org.example" 40 | ]) 41 | } 42 | ``` 43 | 44 | ### Local vs Remote cluster support 45 | 46 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 47 | the ability to connect to a the local cluster, a cluster via URL/Token or using 48 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 49 | as setting the clusterAPI and clusterToken parameters. -------------------------------------------------------------------------------- /vars/rollback.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class Rollback implements Serializable { 4 | //Required 5 | String deploymentConfig 6 | String resourceKindAndName = "" 7 | 8 | //Optional 9 | String rollbackVersion = "" 10 | 11 | //Optional - Platform 12 | String clusterUrl = "" 13 | String clusterAPI = "" 14 | String clusterToken = "" 15 | String projectName = "" 16 | Integer loglevel = 0 17 | } 18 | 19 | def call(Map input) { 20 | call(new Rollback(input)) 21 | } 22 | 23 | def call(Rollback input) { 24 | if (input.deploymentConfig?.trim()?.length() > 0) { 25 | echo "deploymentConfig is deprecated. Please use 'resourceKindAndName'" 26 | 27 | input.resourceKindAndName = input.deploymentConfig 28 | } 29 | 30 | assert input.resourceKindAndName?.trim(): "Param resourceKindAndName should be defined" 31 | 32 | openshift.loglevel(input.loglevel) 33 | 34 | if (input.clusterUrl?.trim().length() > 0) { 35 | error "clusterUrl is deprecated and will be removed in the next release. Please use 'clusterAPI'" 36 | } 37 | 38 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 39 | openshift.withProject(input.projectName) { 40 | def cmd = input.rollbackVersion?.trim().length() <= 0 ? "" : "--to-revision=${input.rollbackVersion}" 41 | 42 | echo "Attempting to rollback '${input.resourceKindAndName}' in ${openshift.project()} ${cmd}" 43 | 44 | def resource = openshift.selector(input.resourceKindAndName) 45 | resource.rollout().undo(cmd) 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /vars/rollback.txt: -------------------------------------------------------------------------------- 1 | # rollback 2 | 3 | ## Summary 4 | 5 | (Rollback)[https://docs.openshift.com/container-platform/3.11/dev_guide/deployments/basic_deployment_operations.html#rolling-back-a-deployment] 6 | a deployment to a previous version. 7 | 8 | ## Usage 9 | 10 | ### Requirements 11 | 12 | Requires Jenkins agent with: 13 | - OC 14 | 15 | ### Parameters 16 | 17 | The method supports the following parameters: 18 | ```groovy 19 | // rollback.groovy#L4-L16 20 | 21 | //Required 22 | String deploymentConfig 23 | String resourceKindAndName = "" 24 | 25 | //Optional 26 | String rollbackVersion = "" 27 | 28 | //Optional - Platform 29 | String clusterUrl = "" 30 | String clusterAPI = "" 31 | String clusterToken = "" 32 | String projectName = "" 33 | Integer loglevel = 0 34 | ``` 35 | 36 | ### Example 37 | 38 | ```groovy 39 | // ../test/Jenkinsfile-rollback#L31-L35 40 | 41 | stage("TEST: Can rollback to earlier version") { 42 | rollback([ 43 | resourceKindAndName: "dc/rollback" 44 | ]) 45 | } 46 | ``` 47 | 48 | ### Local vs Remote cluster support 49 | 50 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 51 | the ability to connect to a the local cluster, a cluster via URL/Token or using 52 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 53 | as setting the clusterAPI and clusterToken parameters. -------------------------------------------------------------------------------- /vars/rollout.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class RolloutInput implements Serializable { 4 | //Required 5 | String deploymentConfigName = "" 6 | String resourceKindAndName = "" 7 | 8 | //Optional 9 | boolean latest = true 10 | 11 | //Optional - Platform 12 | String clusterAPI = "" 13 | String clusterToken = "" 14 | String projectName = "" 15 | Integer loglevel = 0 16 | } 17 | 18 | def call(Map input) { 19 | call(new RolloutInput(input)) 20 | } 21 | 22 | def call(RolloutInput input) { 23 | if (input.deploymentConfigName?.trim()?.length() > 0) { 24 | echo "deploymentConfig is deprecated. Please use 'resourceKindAndName'" 25 | 26 | input.resourceKindAndName = input.deploymentConfigName 27 | } 28 | 29 | assert input.resourceKindAndName?.trim() : "Param resourceKindAndName should be defined." 30 | 31 | openshift.loglevel(input.loglevel) 32 | 33 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 34 | openshift.withProject(input.projectName) { 35 | echo "Attemping to rollout latest '${input.resourceKindAndName}' in ${openshift.project()}" 36 | 37 | def resource = openshift.selector(input.resourceKindAndName) 38 | def rolloutManager = resource.rollout() 39 | 40 | if (input.latest) { 41 | rolloutManager.latest() 42 | } 43 | 44 | echo "Waiting for rollout of '${input.resourceKindAndName}' in ${openshift.project()} to complete..." 45 | 46 | try { 47 | rolloutManager.status("--watch=true") 48 | } catch (ex) { 49 | //Something went wrong, so lets print out some helpful information 50 | rolloutManager.history() 51 | resource.describe() 52 | 53 | throw ex 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /vars/rollout.txt: -------------------------------------------------------------------------------- 1 | # rollout 2 | 3 | ## Summary 4 | 5 | (Rollout)[https://docs.openshift.com/container-platform/3.11/dev_guide/deployments/basic_deployment_operations.html#start-deployment] 6 | a deployment and wait until it is successful. 7 | 8 | ## Usage 9 | 10 | ### Requirements 11 | 12 | Requires Jenkins agent with: 13 | - OC 14 | 15 | ### Parameters 16 | 17 | The method supports the following parameters: 18 | ```groovy 19 | // rollout.groovy#L4-L15 20 | 21 | //Required 22 | String deploymentConfigName = "" 23 | String resourceKindAndName = "" 24 | 25 | //Optional 26 | boolean latest = true 27 | 28 | //Optional - Platform 29 | String clusterAPI = "" 30 | String clusterToken = "" 31 | String projectName = "" 32 | Integer loglevel = 0 33 | ``` 34 | 35 | ### Example 36 | 37 | ```groovy 38 | // ../test/Jenkinsfile-rollout#L25-L29 39 | 40 | stage("TEST: Can rollout to latest version") { 41 | rollout([ 42 | resourceKindAndName: "dc/rollout" 43 | ]) 44 | } 45 | ``` 46 | 47 | ### Local vs Remote cluster support 48 | 49 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 50 | the ability to connect to a the local cluster, a cluster via URL/Token or using 51 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 52 | as setting the clusterAPI and clusterToken parameters. -------------------------------------------------------------------------------- /vars/sonarqubeStaticAnalysis.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class SonarQubeConfigurationInput implements Serializable { 4 | //Optional 5 | String pomFile = "pom.xml" 6 | String buildServerWebHookName = "jenkins" 7 | String curlOptions = "" 8 | } 9 | 10 | def call() { 11 | call(new SonarQubeConfigurationInput()) 12 | } 13 | 14 | def call(Map input) { 15 | call(new SonarQubeConfigurationInput(input)) 16 | } 17 | 18 | def call(SonarQubeConfigurationInput input) { 19 | // make sure build server web hook is available 20 | checkForBuildServerWebHook(input) 21 | 22 | // Execute the Maven goal sonar:sonar to attempt to generate 23 | // the report files. 24 | withSonarQubeEnv('sonar') { 25 | try { 26 | sh "mvn sonar:sonar -f ${input.pomFile}" 27 | } catch (error) { 28 | error error.getMessage() 29 | } 30 | } 31 | 32 | // Check the quality gate to make sure 33 | // it is in a passing state. 34 | def qualitygate = waitForQualityGate() 35 | if (qualitygate.status != "OK") { 36 | error "Pipeline aborted due to quality gate failure: ${qualitygate.status}" 37 | } 38 | } 39 | 40 | def checkForBuildServerWebHook(SonarQubeConfigurationInput input) { 41 | withSonarQubeEnv('sonar') { 42 | echo "Validating webhook with name ${input.buildServerWebHookName} exists..." 43 | 44 | def retVal = sh(returnStdout: true, script: "curl ${input.curlOptions} -u '${SONAR_AUTH_TOKEN}:' ${SONAR_HOST_URL}/api/webhooks/list") 45 | echo "Return Value is $retVal" 46 | 47 | def tmpfile = "/tmp/sonarwebhooks-${java.util.UUID.randomUUID()}.json" 48 | writeFile file: tmpfile, text: retVal 49 | 50 | def webhooksObj = readJSON file: tmpfile 51 | def foundHook = webhooksObj?.webhooks?.find { it.name.equalsIgnoreCase(input.buildServerWebHookName) } 52 | 53 | // webhook was not found 54 | // create the webhook - this should be more likely be part 55 | // of the sonarqube configuration automation 56 | if(foundHook == null) { 57 | error "No webhook found with name ${input.buildServerWebHookName}. Please create one in SonarQube." 58 | } 59 | 60 | echo "Build Server Webhook found. Continuing SonarQube analysis." 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /vars/sonarqubeStaticAnalysis.txt: -------------------------------------------------------------------------------- 1 | # sonarqubeStaticAnalysis 2 | 3 | ## Summary 4 | 5 | This function will: 6 | - validate that a build server webhook has been configured in SonarQube 7 | - run the sonar:sonar maven goal for the configured pom file 8 | - wait for the quality gate status to be OK. 9 | 10 | The pipeline will be stopped if the webhook has not been configured or the quality gate fails. Be advised that the 11 | SonarQube deployment @ https://github.com/redhat-cop/containers-quickstarts/tree/master/sonarqube 12 | will create this webhook for you. 13 | 14 | ## Usage 15 | 16 | ### Requirements 17 | 18 | Requires Jenkins agent with: 19 | - OC 20 | - Maven 21 | - SonarQube server and Jenkins plugin 22 | 23 | ### Parameters 24 | 25 | The method supports the following parameters: 26 | ```groovy 27 | // sonarqubeStaticAnalysis.groovy#L4-L7 28 | 29 | //Optional 30 | String pomFile = "pom.xml" 31 | String buildServerWebHookName = "jenkins" 32 | String curlOptions = "" 33 | ``` 34 | 35 | ### Example 36 | 37 | ```groovy 38 | // ../test/Jenkinsfile-sonarqubeStaticAnalysis#L84-L92 39 | 40 | stage("TEST: Can run sonarqube static analysis") { 41 | sh "git clone https://github.com/redhat-cop/pipeline-library.git" 42 | 43 | dir ("pipeline-library") { 44 | sonarqubeStaticAnalysis([ 45 | curlOptions: "--insecure" 46 | ]) 47 | } 48 | } 49 | ``` 50 | 51 | ### Local vs Remote cluster support 52 | 53 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 54 | the ability to connect to a the local cluster, a cluster via URL/Token or using 55 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 56 | as setting the clusterAPI and clusterToken parameters. -------------------------------------------------------------------------------- /vars/tagAndDeploy.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class TagAndDeployInput implements Serializable { 4 | //Required 5 | String imageName = '' 6 | String imageNamespace = '' 7 | String imageVersion = '' 8 | String registryFQDN = '' 9 | String deployDestinationVersionTag = '' 10 | 11 | //Optional 12 | String deployDestinationProjectName = "" 13 | String tagDestinationTLSVerify = "true" 14 | String tagSourceTLSVerify = "true" 15 | String tagAuthFile = "/var/run/secrets/kubernetes.io/dockerconfigjson/.dockerconfigjson" 16 | String tagDestinationCertDir = "/run/secrets/kubernetes.io/serviceaccount/" 17 | String tagSourceCertDir = "/run/secrets/kubernetes.io/serviceaccount/" 18 | 19 | //Optional - Platform 20 | String clusterAPI = "" 21 | String clusterToken = "" 22 | Integer loglevel = 0 23 | } 24 | 25 | def call(Map input) { 26 | call(new TagAndDeployInput(input)) 27 | } 28 | 29 | def call(TagAndDeployInput input) { 30 | assert input.imageName?.trim() : "Param imageName should be defined." 31 | assert input.imageNamespace?.trim() : "Param imageNamespace should be defined." 32 | assert input.imageVersion?.trim() : "Param imageVersion should be defined." 33 | assert input.registryFQDN?.trim() : "Param registryFQDN should be defined." 34 | assert input.deployDestinationVersionTag?.trim() : "Param deployDestinationVersionTag should be defined." 35 | 36 | def authFileArg = input.tagAuthFile?.trim()?.length() <= 0 ? "" : "--authfile=${input.tagAuthFile}" 37 | def srcTlsVerifyArg = input.tagSourceTLSVerify?.trim()?.length() <= 0 ? "" : "--src-tls-verify=${input.tagSourceTLSVerify}" 38 | def destTlsVerifyArg = input.tagDestinationTLSVerify?.trim()?.length() <= 0 ? "" : "--dest-tls-verify=${input.tagDestinationTLSVerify}" 39 | def destCertDirArg = input.tagDestinationCertDir?.trim()?.length() <= 0 ? "" : "--dest-cert-dir=${input.tagDestinationCertDir}" 40 | def srcCertDirArg = input.tagSourceCertDir?.trim()?.length() <= 0 ? "" : "--src-cert-dir=${input.tagSourceCertDir}" 41 | 42 | def source = "docker://${input.registryFQDN}/${input.imageNamespace}/${input.imageName}:${input.imageVersion}" 43 | def destination = "docker://${input.registryFQDN}/${input.imageNamespace}/${input.imageName}:${input.deployDestinationVersionTag}" 44 | 45 | echo "Attempting to tag; ${source} -> ${destination}" 46 | 47 | sh "skopeo copy $authFileArg $srcTlsVerifyArg $destTlsVerifyArg $destCertDirArg $srcCertDirArg $source $destination" 48 | 49 | rollout( 50 | clusterAPI : input.clusterAPI, 51 | clusterToken : input.clusterToken, 52 | projectName : input.deployDestinationProjectName, 53 | resourceKindAndName: "deploymentconfig/${input.imageName}", 54 | loglevel: input.loglevel 55 | ) 56 | } 57 | -------------------------------------------------------------------------------- /vars/tagAndDeploy.txt: -------------------------------------------------------------------------------- 1 | # tagAndDeploy 2 | 3 | ## Summary 4 | 5 | Tag and deploy an image. 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | - Skopeo 14 | 15 | ### Parameters 16 | 17 | The method supports the following parameters: 18 | ```groovy 19 | // tagAndDeploy.groovy#L4-L22 20 | 21 | //Required 22 | String imageName = '' 23 | String imageNamespace = '' 24 | String imageVersion = '' 25 | String registryFQDN = '' 26 | String deployDestinationVersionTag = '' 27 | 28 | //Optional 29 | String deployDestinationProjectName = "" 30 | String tagDestinationTLSVerify = "true" 31 | String tagSourceTLSVerify = "true" 32 | String tagAuthFile = "/var/run/secrets/kubernetes.io/dockerconfigjson/.dockerconfigjson" 33 | String tagDestinationCertDir = "/run/secrets/kubernetes.io/serviceaccount/" 34 | String tagSourceCertDir = "/run/secrets/kubernetes.io/serviceaccount/" 35 | 36 | //Optional - Platform 37 | String clusterAPI = "" 38 | String clusterToken = "" 39 | Integer loglevel = 0 40 | ``` 41 | 42 | ### Example 43 | 44 | ```groovy 45 | // ../test/Jenkinsfile-tagAndDeploy#L39-L48 46 | 47 | stage("TEST: Can tag and deploy") { 48 | tagAndDeploy([ 49 | registryFQDN : "${dockerRegistry}", 50 | imageNamespace : "pipelinelib-testing", 51 | imageName : "taganddeploy", 52 | imageVersion : "latest", 53 | deployDestinationVersionTag: "v2", 54 | deployDestinationProjectName: "pipelinelib-testing" 55 | ]) 56 | } 57 | ``` 58 | 59 | ### Local vs Remote cluster support 60 | 61 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 62 | the ability to connect to a the local cluster, a cluster via URL/Token or using 63 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 64 | as setting the clusterAPI and clusterToken parameters. 65 | -------------------------------------------------------------------------------- /vars/tagImage.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class TagImageInput implements Serializable { 4 | //Required 5 | String sourceImagePath = "" 6 | String sourceImageName = "" 7 | String sourceImageTag = "latest" 8 | String toImagePath 9 | 10 | //Optional 11 | String toImageName = "" 12 | String toImageTag = "" 13 | 14 | //Optional - Platform 15 | String clusterAPI = "" 16 | String clusterToken = "" 17 | Integer loglevel = 0 18 | 19 | TagImageInput init() { 20 | if(!toImageName?.trim()) toImageName = sourceImageName 21 | if(!toImageTag?.trim()) toImageTag = sourceImageTag 22 | return this 23 | } 24 | } 25 | 26 | def call(Map input) { 27 | call(new TagImageInput(input).init()) 28 | } 29 | 30 | def call(TagImageInput input) { 31 | assert input.sourceImageName?.trim() : "Param sourceImageName should be defined." 32 | assert input.sourceImagePath?.trim() : "Param sourceImagePath should be defined." 33 | assert input.sourceImageTag?.trim() : "Param sourceImageTag should be defined." 34 | assert input.toImagePath?.trim() : "Param toImagePath should be defined." 35 | 36 | openshift.loglevel(input.loglevel) 37 | 38 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 39 | def source = "${input.sourceImagePath}/${input.sourceImageName}:${input.sourceImageTag}" 40 | def destination = "${input.toImagePath}/${input.toImageName}:${input.toImageTag}" 41 | 42 | echo "Attempting to tag; ${source} -> ${destination}" 43 | 44 | openshift.tag(source,destination) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vars/tagImage.txt: -------------------------------------------------------------------------------- 1 | # tagImage 2 | 3 | ## Summary 4 | 5 | (Tag)[https://docs.openshift.com/container-platform/3.11/dev_guide/managing_images.html#tagging-images] an image. 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | 14 | ### Parameters 15 | 16 | The method supports the following parameters: 17 | ```groovy 18 | // tagImage.groovy#L4-L17 19 | 20 | //Required 21 | String sourceImagePath = "" 22 | String sourceImageName = "" 23 | String sourceImageTag = "latest" 24 | String toImagePath 25 | 26 | //Optional 27 | String toImageName = "" 28 | String toImageTag = "" 29 | 30 | //Optional - Platform 31 | String clusterAPI = "" 32 | String clusterToken = "" 33 | Integer loglevel = 0 34 | ``` 35 | 36 | ### Example 37 | 38 | ```groovy 39 | // ../test/Jenkinsfile-tagImage#L5-L14 40 | 41 | stage("TEST: Can tag image") { 42 | tagImage([ 43 | sourceImagePath: "openshift", 44 | sourceImageName: "jenkins", 45 | sourceImageTag : "2", 46 | toImagePath: "pipelinelib-testing", 47 | toImageName : "tagimage", 48 | toImageTag : "2" 49 | ]) 50 | } 51 | ``` 52 | 53 | ### Local vs Remote cluster support 54 | 55 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 56 | the ability to connect to a the local cluster, a cluster via URL/Token or using 57 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 58 | as setting the clusterAPI and clusterToken parameters. -------------------------------------------------------------------------------- /vars/verifyDeployment.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class ClusterInput implements Serializable { 4 | //Required 5 | String targetApp 6 | 7 | //Optional - Platform 8 | String clusterUrl = "" 9 | String clusterAPI = "" 10 | String clusterToken = "" 11 | String projectName = "" 12 | Integer loglevel = 0 13 | } 14 | 15 | // verify deployment 16 | def call(Map input) { 17 | call(new ClusterInput(input)) 18 | } 19 | 20 | def call(ClusterInput input) { 21 | echo "verifyDeployment has been deprecated. Please call rollout with latest:false to verify a deployment" 22 | assert input.targetApp?.trim(): "Param targetApp should be defined." 23 | 24 | openshift.loglevel(input.loglevel) 25 | 26 | if (input.clusterUrl?.trim().length() > 0) { 27 | error "clusterUrl is deprecated and will be removed in the next release. Please use 'clusterAPI'" 28 | } 29 | 30 | rollout([ 31 | clusterAPI : input.clusterAPI, 32 | clusterToken : input.clusterToken, 33 | projectName : input.projectName, 34 | resourceKindAndName: "dc/${input.targetApp}", 35 | latest : false 36 | ]) 37 | } 38 | -------------------------------------------------------------------------------- /vars/verifyDeployment.txt: -------------------------------------------------------------------------------- 1 | # verifyDeployment 2 | 3 | ## Summary 4 | DEPRECATION NOTICE 5 | This method has been deprecated in favor of the 'rollout' method in this repository. Calling that method with the 6 | 'latest' flag set to false will replicate the behavior of this method. 7 | 8 | Verify a DeploymentConfig has deployed successfully. 9 | 10 | ## Usage 11 | 12 | ### Requirements 13 | 14 | Requires Jenkins agent with: 15 | - OC 16 | 17 | ### Parameters 18 | 19 | The method supports the following parameters: 20 | ```groovy 21 | // verifyDeployment.groovy#L4-L12 22 | 23 | //Required 24 | String targetApp 25 | 26 | //Optional - Platform 27 | String clusterUrl = "" 28 | String clusterAPI = "" 29 | String clusterToken = "" 30 | String projectName = "" 31 | Integer loglevel = 0 32 | ``` 33 | 34 | ### Example 35 | 36 | ```groovy 37 | // ../test/Jenkinsfile-verifyDeployment#L16-L20 38 | 39 | stage("TEST: Can verify deployment") { 40 | verifyDeployment([ 41 | targetApp: "verifydeployment" 42 | ]) 43 | } 44 | ``` 45 | 46 | ### Local vs Remote cluster support 47 | 48 | As the underlying technology used is the [openshift-client-plugin](https://github.com/openshift/jenkins-client-plugin), 49 | the ability to connect to a the local cluster, a cluster via URL/Token or using 50 | [Jenkins configuration](https://github.com/openshift/jenkins-client-plugin#configuring-an-openshift-cluster) is as easy 51 | as setting the clusterAPI and clusterToken parameters. 52 | -------------------------------------------------------------------------------- /vars/verifyService.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | class VerifyServiceInput implements Serializable { 4 | //Required 5 | String serviceName = "" 6 | 7 | //Optional - Platform 8 | String clusterAPI = "" 9 | String clusterToken = "" 10 | String projectName = "" 11 | Integer loglevel = 0 12 | } 13 | 14 | def call(Map input) { 15 | call(new VerifyServiceInput(input)) 16 | } 17 | 18 | def call(VerifyServiceInput input) { 19 | assert input.serviceName?.trim(): "Param serviceName should be defined." 20 | 21 | openshift.loglevel(input.loglevel) 22 | 23 | openshift.withCluster(input.clusterAPI, input.clusterToken) { 24 | openshift.withProject(input.projectName) { 25 | def connected = openshift.verifyService(input.serviceName) 26 | if (!connected) { 27 | error "Failed to connect to service: '${input.serviceName}' in ${openshift.project()}" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vars/verifyService.txt: -------------------------------------------------------------------------------- 1 | # verifyService 2 | 3 | ## Summary 4 | 5 | Verify service has endpoints accepting connections. 6 | 7 | ## Usage 8 | 9 | ### Requirements 10 | 11 | Requires Jenkins agent with: 12 | - OC 13 | 14 | ### Parameters 15 | 16 | The method supports the following parameters: 17 | ```java 18 | // verifyService.groovy#L4-L11 19 | 20 | //Required 21 | String serviceName = "" 22 | 23 | //Optional - Platform 24 | String clusterAPI = "" 25 | String clusterToken = "" 26 | String projectName = "" 27 | Integer loglevel = 0 28 | ``` 29 | 30 | ### Example 31 | 32 | ```java 33 | // ../test/Jenkinsfile-verifyService#L19-L23 34 | 35 | stage("TEST: Can verify service") { 36 | verifyService([ 37 | serviceName: "verifyservice" 38 | ]) 39 | } 40 | ``` 41 | 42 | ### Local vs Remote cluster support 43 | 44 | As the method attempts to call service endpoints within the OCP SDN, the Jenkins Agent must be running on the cluster it is testing. --------------------------------------------------------------------------------