├── .github └── workflows │ └── ansible-lint.yml ├── Dockerfile ├── LICENSE ├── README.md ├── WORKSHOP.md ├── ansible ├── ansible.cfg ├── files │ ├── workshop-argo-cluster-cr.yaml │ ├── workshop-argo-project-cr.yaml │ ├── workshop-sample-app-cr.yaml │ └── workshop-sample-infra-cr.yaml ├── inventory │ ├── group_vars │ │ └── local.yaml │ └── inventory.yaml ├── participants-deploy.yaml ├── participants-make-changes.yaml ├── participants-pipeline-deploy.yaml ├── participants-setup.yaml ├── playbook.yaml ├── requirements.yaml ├── secrets.yaml ├── temp │ └── .keep └── templates │ ├── files │ ├── workshop-argo-cluster-cr.yaml.j2 │ └── workshop-sample-app-cr.yaml.j2 │ ├── sample-app-ci │ ├── 10-buildah-task.yaml.j2 │ ├── 10-git-cli-task.yaml.j2 │ ├── 10-git-clone-task.yaml.j2 │ ├── 10-make-sample-app-task.yaml.j2 │ └── 10-version-increment-task.yaml.j2 │ └── sample-app-config │ ├── VERSION │ ├── sample-app-deployment.yaml.j2 │ ├── sample-app-namespace.yaml.j2 │ └── sample-app-networkpolicy.yaml.j2 ├── code-ready-workspace.yaml ├── docs └── images │ ├── 01 - ArgoCD Route.png │ ├── 02 - ArgoCD Login.png │ ├── 03 - ArgoCD Console.png │ ├── 04 - CI Pipeline.png │ ├── 05 - Sample App Update.png │ ├── 06 - Updated Deployment.png │ ├── 07 - Updated Pod.png │ ├── 08 - SYNC.png │ ├── 09 - New PipelineRun.png │ ├── 10 - PipelineRun Complete.png │ ├── 11 - Manual PipelineRun.png │ └── Big Picture.png ├── sample-app-ci ├── 01-sample-app-ci-namespace.yaml ├── 02-sample-app-pvc.yaml ├── 10-buildah-task.yaml ├── 10-git-cli-task.yaml ├── 10-git-clone-task.yaml ├── 10-make-sample-app-task.yaml ├── 10-version-increment-task.yaml ├── 20-pipeline.yaml └── 30-pipeline-run.yaml ├── sample-app-config ├── sample-app-deployment.yaml ├── sample-app-namespace.yaml └── sample-app-networkpolicy.yaml ├── sample-app ├── .gitignore ├── Dockerfile ├── Makefile ├── README.md ├── go.mod └── main.go └── sample-infra ├── integration-secret-example.yaml └── sample-infra-namespace.yaml /.github/workflows/ansible-lint.yml: -------------------------------------------------------------------------------- 1 | name: Ansible Lint 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | # Steps represent a sequence of tasks that will be executed as part of the job 13 | steps: 14 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 15 | - uses: actions/checkout@v2 16 | # Run ansible-lint 17 | - name: ansible-lint 18 | uses: ansible/ansible-lint-action@master 19 | with: 20 | targets: | 21 | ansible/playbook.yaml 22 | ansible/participants-setup.yaml 23 | ansible/participants-deploy.yaml 24 | override-deps: ansible==2.9 25 | args: "" 26 | # args: | 27 | # --exclude=ansible/files 28 | # --exclude=ansible/vars 29 | # --exclude=ansible/templates 30 | # --exclude=ansible/requirements.yaml 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.access.redhat.com/ubi8:latest 2 | 3 | # Install dependencies 4 | RUN yum install -y python3-pip git && \ 5 | /usr/bin/pip3 install ansible github3.py openshift && \ 6 | curl -o /tmp/openshift-client-linux.tar.gz https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/openshift-client-linux.tar.gz && \ 7 | tar -xzvf /tmp/openshift-client-linux.tar.gz -C /usr/local/bin/ && \ 8 | chmod +x /usr/local/bin/oc && \ 9 | rm /usr/local/bin/README.md && \ 10 | rm /usr/local/bin/kubectl && \ 11 | rm /tmp/openshift-client-linux.tar.gz && \ 12 | yum clean all -y 13 | -------------------------------------------------------------------------------- /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 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitOps Workshop 2 | 3 | Authors: 4 | - Brian Tomlinson 5 | - Skylar Scaling 6 | 7 | 8 | ## Description 9 | 10 | A workshop designed to impart the core principals of GitOps and Infrastructure as Code (IaC) using 11 | [Ansible](https://www.ansible.com/), [ArgoCD](https://argoproj.github.io/projects/argo-cd), [Tekton](https://tekton.dev/), and [OpenShift](https://www.openshift.com/). 12 | 13 | 14 | ## Prerequisites 15 | 16 | ### Tools 17 | 18 | The following are requirements for both administrators setting up and facilitating the workshop, as well as attendees 19 | participating in the workshop. 20 | 21 | - [Ansible 2.8+](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-ansible) 22 | - [Git 2.26+](https://git-scm.com/downloads) 23 | 24 | 25 | ### Environment 26 | 27 | For the best possible performance, it is recommended the workshop be conducted on a hosted (either bare-metal or via cloud provider) 28 | Red Hat OpenShift 4.x or Kubernetes 1.16+ cluster. However, the following local solutions have been tested and verified to 29 | work well enough for small audiences. 30 | 31 | - [Code Ready Containers 1.13+](https://access.redhat.com/documentation/en-us/red_hat_codeready_containers/1.13/html/getting_started_guide/index) 32 | - [Minishift 1.34+](https://www.okd.io/minishift/) 33 | 34 | 35 | ## Facilitator Usage 36 | 37 | Facilitators of this workshop can automatically provision the requisite components using the supplied playbooks. You 38 | must have `cluster-admin` or an administrative role that allows creation and modification of `CustomResourceDefinitions` 39 | and `InstallPlans` at the cluster scope in order to install the operator components used herein. 40 | 41 | 42 | ### Using the Dockerfile 43 | 44 | This workshop comes with a `Dockerfile` defining an environment from which facilitators and participants may execute the 45 | Ansible playbooks from this repository. The resulting image of the `Dockerfile` is available at 46 | [https://quay.io/btomlins/gitops-workshop](https://quay.io/btomlins/gitops-workshop). The simplest way to use the image 47 | is: 48 | 49 | ``` 50 | $ podman pull quay.io/btomlins/gitops-workshop:latest 51 | $ podman run -v /path/to/gitops-workshop:/projects/gitops-workshop:z -it quay.io/btomlins/gitops-workshop:latest /bin/sh 52 | >> sh-4.4# 53 | sh-4.4# cd /projects/gitops-workshop 54 | sh-4.4# ls -allh 55 | ``` 56 | From there, you may execute `ansible-playbook`, `git`, and `oc` commands described in this workshop. 57 | 58 | 59 | ### Building the image from the Dockerfile 60 | 61 | Your local machine or cluster may not be able to pull the pre-built image due to policy restrictions. In that case, you 62 | may execte the following to build the image via the `Dockerfile`: 63 | 64 | ``` 65 | $ podman build -f Dockerfile -t $REGISTRY/gitops-workshop:$TAG 66 | ``` 67 | 68 | From there, execute the steps defined in the previous section in order to use the image. 69 | 70 | 71 | ### Setup the facilitator's local host 72 | 73 | The following commands will: 74 | - Install the requirements for the facilitator's `playbook.yaml` 75 | - Install CLI pre-requisite tools (`oc`, `kubectl`, `argocd`) 76 | - Install the ArgoCD Operator 77 | - Instantiate/Deploy the `sample-app`, `sample-app-ci`, and `sample-infra` operands 78 | 79 | > *NOTE:* If you do not have a kubeconfig file in your workspace, be sure to perform an oc login to your destination cluster from your workspace. 80 | 81 | ``` 82 | $ cd /path/to/gitops-workshop/ansible 83 | $ ansible-galaxy collection install -r requirements.yaml 84 | $ ansible-playbook -i inventory playbook.yaml \ 85 | -e kubeconfig=/path/to/kubeconfig \ 86 | -e scope=cluster \ # Alternatively, you can use 'namespace' 87 | -e internal_registry=$REGISTRY_NAME \ # Omit this unless using a registry such as Artifactory or Nexus to limit image access 88 | -e state=present \ # Use 'absent' to undeploy 89 | -e argo_release_tag=v1.7.1 \ 90 | -e operator_release_tag=v0.0.12 91 | ``` 92 | 93 | Now we have to update the Tekton pipeline to have the proper GitHub and registry-pull Secrets: 94 | 95 | > *NOTE:* If facilitating this workshop yourself, you will need to create your own secrets in the `secrets.yaml` playbook. 96 | 97 | ``` 98 | $ ansible-playbook -i inventory secrets.yaml \ 99 | -e kubeconfig=/path/to/kubeconfig \ 100 | --ask-vault-pass 101 | ``` 102 | 103 | Enter your ansible-vault password when prompted, and the pipeline service account will be patched with the required Secrets. 104 | 105 | ### Setup Code Ready Workspace 106 | 107 | The workshop image specified in the `Dockerfile` is consumable within Code Ready Workspaces, a `devfile` called 108 | `code-ready-workspace.yaml` is provided at the root of this repository. To use it, simply execute the steps described 109 | [here](https://access.redhat.com/documentation/en-us/red_hat_codeready_workspaces/2.2/html/end-user_guide/workspaces-overview_crw#creating-a-workspace-from-custom-workspace-view-of-user-dashboard_creating-a-workspace-from-code-sample) and provide the Devfile URL in the appropriate field rather than from the drop-down list as described in the doc. 110 | The Devfile URL for the primary copy of the `code-ready-workspace.yaml` Devfile is [https://raw.githubusercontent.com/darthlukan/gitops-workshop/master/code-ready-workspace.yaml](https://raw.githubusercontent.com/darthlukan/gitops-workshop/master/code-ready-workspace.yaml). 111 | 112 | Alternatively, you may simply copy and paste the contents of `code-ready-workspace.yaml` into the `Devfile` editor box 113 | in the Custom Workspace creation page. 114 | 115 | 116 | ## License 117 | 118 | Apache-2.0. See LICENSE file. 119 | -------------------------------------------------------------------------------- /WORKSHOP.md: -------------------------------------------------------------------------------- 1 | # Agenda 2 | 3 | - Overview 4 | - What is GitOps? 5 | - Why GitOps? 6 | - Sample Application Walkthrough 7 | - Sample App CI Walkthrough 8 | - Sample App GitOps in Action 9 | - Prepare Your Environment 10 | - Initial Deployment 11 | - Making Changes 12 | - What Just Happened? 13 | - Running the Tekton Pipeline 14 | - Sample Infrastructure Demo 15 | - Considerations for production implementations 16 | - Further reading 17 | 18 | 19 | ## Overview 20 | 21 | In this workshop we will cover GitOps concepts in the context of a sample application with a CI/CD pipeline. We will use 22 | Tekton for our CI (Continuous Integration) solution and ArgoCD for CD (Continuous Delivery) solution. There are other 23 | tools we could use for CI/CD under a GitOps model on Kubernetes/OpenShift, however Tekton was purpose-built to be a 24 | cloud and Kubernetes native CI solution and ArgoCD provides a class 5 ("Autopilot") operator for Kubernetes. The important 25 | parts are the functionality, level of automation, and familiarity of Kubernetes objects so as not to distract 26 | participants from the purpose of the workshop: Understanding GitOps and its value as a methodology. 27 | 28 | This workshop makes use of Ansible to install components and set up the workshop environment. Participants are not 29 | required to use the provided `partcipant-*.yaml` playbooks, they are merely provided to save time. If you find that 30 | following along is difficult or if you are pressed for time, run the associated playbook (will be noted in each relevant 31 | section) to catch up. 32 | 33 | You can see a visual overview of the workshop contents below: 34 | 35 | ![Workshop Overview](/docs/images/Big Picture.png "Workshop Overview") 36 | 37 | ## What is GitOps? 38 | 39 | GitOps is a continuous delivery methodology for applying configuration based on assets stored in a git repository. 40 | Typical implementations of GitOps include manually applying configuration assets or making use of tools which can 41 | automatically apply those assets by responding to events. 42 | 43 | 44 | ## Why GitOps? 45 | 46 | GitOps provides a way for Developers and Operations Engineers to declaratively describe application and infrastructure 47 | components and their desired state, provide traceability of changes, and perform operations via pull request, among other things. 48 | Developers are already used to managing their application source code via `git`, as are Operations Engineers who 49 | make use of Infrastructure as Code practices. GitOps makes use of all of that and fills the continuous delivery gap. 50 | 51 | 52 | ## Sample Application Walkthrough 53 | 54 | Our `sample-app` for today is a simple Go program which periodically prints a greeting to `STDOUT`. It will continue to 55 | run until stopped and can be executed via a container image defined in its `Dockerfile`. It includes a `Makefile` to 56 | simplify building the binary and the container image. 57 | 58 | The desired deployment target of this application is a Kubernetes/OpenShift cluster. The desired configuration for our 59 | application is stored in `sample-app-config`. Within this directory we have defined the objects necessary for the 60 | app to run on a cluster: a `Deployment` in `sample-app-deployment.yaml`, a `Namespace` in `sample-app-namespace.yaml`, 61 | and a `Networkpolicy` in `sample-app-networkpolicy.yaml`. This `sample-app-config` would generally be deployed to a 62 | separate Git repository, but for our purposes we are maintaining it in a separate directory within this repository. 63 | 64 | 65 | ## Sample Application CI Walkthrough 66 | 67 | The `sample-app-ci` directory contains the object manifests which define the CI implementation for our sample 68 | application. Because the CI solution uses Tekton, we already have a delcarative definition of the pipeline and its 69 | required objects, so there's no need to separate the pipeline pre-requisite infrastructure and components from the 70 | pipeline: they are one and the same. 71 | 72 | In this case, we have the `sub.yaml` which defines [OpenShift Pipelines Operator](https://www.openshift.com/learn/topics/pipelines) subscription 73 | which allows us to install the OpenShift Pipelines Operator and have it managed via the OpenShift cluster's [Operator 74 | Lifecycle 75 | Manager](https://docs.openshift.com/container-platform/4.5/operators/understanding_olm/olm-understanding-olm.html). We 76 | also have a `Persistant Volume Claim` as defined in `sample-app-pvc.yaml`, a custom `Task` in 77 | `make-sample-app-task.yaml`, the actual `Pipeline` in `pipeline.yaml`, and a `PipelineRun` in `run.yaml`. 78 | 79 | In Tekton, a `Pipeline` is a pipeline definition componsed of `Task` objects. `Tasks` can be executed individually via a 80 | `TaskRun` object, but here we want to use them in a pipeline. In order to execute a `Pipeline`, Tekton provides a 81 | `PipelineRun` object. We use this to provide values to parameters defined in the `Pipeline` and its `Tasks`. 82 | 83 | Our `Pipeline` contains tasks for performing a `git-clone`, building the application and its container image, pushing 84 | the image to an image registry, and committing a change to the `sample-app-config/sample-app-deployment.yaml` so that it 85 | is updated with the image it just built. 86 | 87 | 88 | ## Sample App GitOps in Action 89 | 90 | DEMO SAMPLE APP RECONCILIATION 91 | 92 | 93 | ## 1) Prepare Your Environment 94 | 95 | For ease of using the commands below, set an environment variable that contains YOUR_USERNAME (replacing "yourusername" with a username of your choice, in lowercase): 96 | 97 | > *NOTE:* Your username MUST be entered as all lowercase characters to create a valid namespace. You can choose any username, so long as it will be unique to you. 98 | 99 | ``` 100 | $ export YOUR_USERNAME=yourusername 101 | ``` 102 | 103 | > *NOTE:* If you do not have a kubeconfig file in your workspace, be sure to perform an oc login to your destination cluster from your workspace. 104 | 105 | ``` 106 | $ cd ansible 107 | $ ansible-playbook -i inventory participants-setup.yaml \ 108 | -e kubeconfig=/path/to/kubeconfig \ 109 | -e participant="${YOUR_USERNAME}" 110 | ``` 111 | 112 | > *INSTRUCTION:* Execute the playbook referenced above during the workshop in the interest of time. The steps executed by the 113 | > playbook are described below. 114 | 115 | Make sure you are logged into the cluster with a user that has `self-provisioner` set, then execute the following to 116 | create the directories to work from and copy over the files we'll be editing: 117 | 118 | ``` 119 | $ cd /path/to/gitops-workshop 120 | $ mkdir "${YOUR_USERNAME}"-sample-app-config 121 | $ cp -r sample-app-config "${YOUR_USERNAME}"-sample-app-config 122 | $ mkdir "${YOUR_USERNAME}"-customresources 123 | $ cp -r ansible/files/workshop-sample-app-cr.yaml "${YOUR_USERNAME}"-customresources 124 | ``` 125 | 126 | Next we need to edit the files so that they are personalized and don't cause conflicts with any other workshop 127 | participants: 128 | 129 | ``` 130 | $ cd "${YOUR_USERNAME}"-sample-app-config 131 | $ sed -i 's/sample-app/"${YOUR_USERNAME}"-sample-app/g' sample-app-deployment.yaml sample-app-namespace.yaml sample-app-networkpolicy.yaml 132 | $ cd ../"${YOUR_USERNAME}"-customresources 133 | $ sed -i 's/sample-app/"${YOUR_USERNAME}"-sample-app/g' workshop-sample-app-cr.yaml 134 | ``` 135 | 136 | Finally, we need to copy and modify the file that will allow us to set up our github and pull secrets: 137 | 138 | ``` 139 | $ cd /path/to/gitops-workshop/ansible 140 | $ cp secrets.yaml "${YOUR_USERNAME}"-secrets.yaml 141 | $ sed -i 's/sample-app-ci/"${YOUR_USERNAME}"-sample-app-ci/g' "${YOUR_USERNAME}"-secrets.yaml 142 | ``` 143 | 144 | *NOTE:* _The following is NOT completed by the playbook referenced at the top of this section and must be executed manually._ 145 | 146 | Create a branch that is named `YOUR_USERNAME` and push your first commit: 147 | 148 | ``` 149 | $ cd /path/to/gitops-workshop 150 | $ git checkout -b "${YOUR_USERNAME}" 151 | $ git add . 152 | $ git commit -m "environment set up" 153 | $ git push -u origin "${YOUR_USERNAME}" 154 | ``` 155 | 156 | That's it, your environment is now prepared for the rest of the workshop content. To recap, we've branched the workshop 157 | content, copied and personalized the files with which we'll be working, and established this as our 158 | "feature" branch. 159 | 160 | 161 | ## 2) Initial Deployment 162 | 163 | In this section we will tell ArgoCD to deploy our application. We will be using `CustomResources`, which 164 | are instances of a `CustomResourceDefinition`, to represent our deployments. In this case we will be using the 165 | `Application` "type" object to tell ArgoCD about our `sample-app` deployment. 166 | 167 | > *NOTE:* Execute the following playbook if you have difficulty following along or just wish to save time: 168 | 169 | ``` 170 | $ cd /path/to/gitops-workshop/ansible 171 | $ ansible-playbook -i inventory participants-deploy.yaml -e kubeconfig=/path/to/kubeconfig -e participant="${YOUR_USERNAME}" 172 | ``` 173 | 174 | First, let's deploy the application and ci pipeline. You will need to change to the `YOUR_USERNAME-customresources` directory and use 175 | either `oc` or `kubectl` to apply the `CustomResources` depending on the cluster type you're using ("Vanilla" Kubernetes 176 | or OpenShift): 177 | 178 | ``` 179 | $ cd "${YOUR_USERNAME}"-customresources 180 | $ oc apply -f workshop-sample-app-cr.yaml 181 | ``` 182 | 183 | Inside your cluster console, from the navigation pane you can select Networking -> Routes to view the available URLs for connection to your deployed ArgoCD instance. 184 | 185 | > *NOTE:* You will need to have the `argocd` project selected to view the relevant routes. 186 | 187 | ![ArgoCD Routes](/docs/images/01 - ArgoCD Route.png "ArgoCD Routes") 188 | 189 | Click on the URL in the Location column for the route named `workshop-argocd-server`. This will open the ArgoCD login page: 190 | 191 | ![ArgoCD Login Page](/docs/images/02 - ArgoCD Login.png "ArgoCD Login Page") 192 | 193 | In order to login to the ArgoCD server, you will need to retrieve the admin password from the Argo CD deployed secret. Execute the following commands to retrieve the password: 194 | 195 | ``` 196 | $ oc project argocd 197 | $ export ARGOCD_CLUSTER_NAME=workshop 198 | $ oc get secret $ARGOCD_CLUSTER_NAME-argocd-cluster -o jsonpath='{.data.admin\.password}' | base64 -d 199 | ``` 200 | 201 | The returned string will be the password for the admin user login to Argo CD. 202 | 203 | You will see the Argo CD Applications dashboard, and you should see the pipelines we created for our `workshop` project: 204 | 205 | ![ArgoCD Console](/docs/images/03 - ArgoCD Console.png "ArgoCD Console") 206 | 207 | ## 3) Making Changes 208 | 209 | Now comes the fun part. We are going to make some changes to our files in git, commit and push them, and watch how ArgoCD 210 | automatically syncs those changes so that we don't have to manually log into the cluster and perform the deployment 211 | operation ourselves. 212 | 213 | > *NOTE:* Execute the following playbook to save time or if you encounter an error attempting to follow the steps in 214 | > this section: 215 | 216 | ``` 217 | $ cd /path/to/gitops-workshop/ansible 218 | $ ansible-playbook -i inventory participants-make-changes.yaml -e kubeconfig=/path/to/kubeconfig -e participant="${YOUR_USERNAME}" 219 | ``` 220 | 221 | First let's make a small change, adding a more personalized greeting to the `sample-app-deployment.yaml` manifest. The 222 | provided `sample-app-deployment.yaml` defaults to a very generic greeting, `'Hello participant\!'` as described by the 223 | file content below: 224 | 225 | ``` 226 | --- 227 | apiVersion: apps/v1 228 | kind: Deployment 229 | metadata: 230 | name: sample-app 231 | namespace: sample-app 232 | spec: 233 | replicas: 1 234 | selector: 235 | matchLabels: 236 | app: sample-app 237 | template: 238 | metadata: 239 | labels: 240 | app: sample-app 241 | spec: 242 | containers: 243 | - name: sample-app 244 | image: "quay.io/sscaling/gitops-workshop:v0.0.1" 245 | command: 246 | - '/usr/bin/greet' 247 | args: 248 | - 'Hello participant\!' 249 | ... 250 | ``` 251 | 252 | To change this, you can use your text editor or execute the following commands: 253 | 254 | ``` 255 | $ cd /path/to/gitops-workshop/"${YOUR_USERNAME}"-sample-app-config 256 | $ sed -i 's/participant/"${YOUR_USERNAME}"/g' sample-app-deployment.yaml 257 | ``` 258 | 259 | The result is that the arg on line `25` no longer says `'Hello participant\!'`, but instead reflects whatever 260 | `YOUR_USERNAME` is. For example: `'Hello btomlins\!'`. If `YOUR_USERNAME` is `btomlins`, then you should see the 261 | following completed file: 262 | 263 | ``` 264 | --- 265 | apiVersion: apps/v1 266 | kind: Deployment 267 | metadata: 268 | name: sample-app 269 | namespace: sample-app 270 | spec: 271 | replicas: 1 272 | selector: 273 | matchLabels: 274 | app: sample-app 275 | template: 276 | metadata: 277 | labels: 278 | app: sample-app 279 | spec: 280 | containers: 281 | - name: sample-app 282 | image: "quay.io/sscaling/gitops-workshop:v0.0.1" 283 | command: 284 | - '/usr/bin/greet' 285 | args: 286 | - 'Hello btomlins\!' 287 | ... 288 | ``` 289 | 290 | In order for ArgoCD to act upon this change, we will need to commit our changes and push them to our remote repo. You 291 | can do so using the following commands: 292 | 293 | ``` 294 | $ cd /path/to/gitops-workshop/"${YOUR_USERNAME}"-sample-app-config 295 | $ git add sample-app-deployment.yaml 296 | $ git commit -m "Add ${YOUR_USERNAME} to deployment" 297 | $ git push -u origin "${YOUR_USERNAME}" 298 | ``` 299 | 300 | If you observe the ArgoCD Dashboard, you will see the YOUR_USERNAME-sample-app Application recognize the change to the repository, sync the updated file, and apply the change to the deployment: 301 | 302 | ![ArgoCD Sample App Update](/docs/images/05 - Sample App Update.png "ArgoCD Sample App Update") 303 | 304 | ## What Just Happened? 305 | 306 | Several things just happened "auto-magically" based on our ArgoCD configuration. 307 | 308 | 1) ArgoCD detected a new commit to your git repository 309 | - `git fetch` 310 | 2) ArgoCD pulled the change into our configured Application from the latest revision 311 | - `git merge` 312 | 3) ArgoCD pushed the updated file to our OCP deployment 313 | - `oc apply -f sample-app-deployment.yaml` 314 | 4) OCP spun up a new pod containing the updated Application file, and spun down the outdated deployed pod 315 | 316 | You can see the updated deployment in your OCP console by navigating to Workloads -> Deployments for your YOUR_USERNAME-sample-app project: 317 | 318 | ![Updated Deployment](/docs/images/06 - Updated Deployment.png "Updated Deployment") 319 | 320 | ![Updated Pod](/docs/images/07 - Updated Pod.png "Updated Pod") 321 | 322 | ## 4) Running the Tekton Pipeline 323 | 324 | Now we will demonstrate how a Tekton pipeline can be incorporated in the GitOps process to automate the creation of a new image version in our desired image registry. 325 | 326 | First, we will deploy our Tekton pipeline. In order to save time, you should run the following playbook: 327 | 328 | ``` 329 | $ cd /path/to/gitops-workshop/ansible 330 | $ ansible-playbook -i inventory participants-pipeline-deploy.yaml \ 331 | -e kubeconfig=/path/to/kubeconfig \ 332 | -e participant="${YOUR_USERNAME}" \ 333 | -e state=present \ # Use 'absent' to undeploy 334 | -e internal_registry=$REGISTRY_NAME # Omit this unless using a registry such as Artifactory or Nexus to limit image access 335 | ``` 336 | 337 | > *NOTE* - This playbook performs several tasks for the participant. The equivalent commands can been seen below: 338 | 339 | Copy the necessary CRD files for the Tekton pipeline and its component tasks: 340 | 341 | ``` 342 | $ cp -r sample-app-ci "${YOUR_USERNAME}"-sample-app-ci 343 | ``` 344 | 345 | Replace the namespace, git branch, and config path with the participant's respective values: 346 | 347 | ``` 348 | $ cd ../"${YOUR_USERNAME}"-sample-app-ci 349 | $ sed -i 's/sample-app-ci/"${YOUR_USERNAME}"-sample-app-ci/g' 01-sample-app-ci-namespace.yaml 350 | $ sed -i 's/master/"${YOUR_USERNAME}"/g' 30-pipeline-run.yaml 351 | $ sed -i 's/sample-app-config/"${YOUR_USERNAME}"-sample-app-config/g' 30-pipeline-run.yaml 352 | ``` 353 | 354 | Deploy the pipeline and its component tasks from the CRDs: 355 | 356 | > *NOTE* - If you specified an `internal_registry` during deployment, the appropriate images used in the pipeline will be updated to the correct paths. 357 | 358 | ``` 359 | $ oc create -f 01-sample-app-ci-namespace.yaml 360 | $ oc create -f 02-sample-app-pvc.yaml 361 | $ oc create -f 10-buildah-task.yaml 362 | $ oc create -f 10-git-cli-task.yaml 363 | $ oc create -f 10-git-clone-task.yaml 364 | $ oc create -f 10-make-sample-app-task.yaml 365 | $ oc create -f 10-version-increment-task.yaml 366 | $ oc create -f 20-pipeline.yaml 367 | ``` 368 | 369 | > *NOTE* - The following steps are not executed by the playbook above and must be run by the participant: 370 | 371 | Finally, we need to patch our GitHub token and image pull secrets into the Tekton pipeline Service Account for our namespace: 372 | 373 | ``` 374 | $ ansible-playbook -i inventory "${YOUR_USERNAME}"-secrets.yaml \ 375 | -e kubeconfig=/path/to/kubeconfig --ask-vault-pass 376 | ``` 377 | 378 | > *NOTE* - Your workshop facilitator will provide you with the Ansible vault password you need to enter. 379 | 380 | Now we can make a change to our pipeline run CRD. For this change, we will update the version number for our image (`image-version` in `YOUR_USERNAME-sample-app-ci/30-pipeline-run.yaml`): 381 | 382 | ``` 383 | apiVersion: tekton.dev/v1beta1 384 | kind: PipelineRun 385 | metadata: 386 | generateName: gitops-workshop-pipeline-run- 387 | annotations: 388 | argocd.argoproj.io/hook: Sync 389 | spec: 390 | pipelineRef: 391 | name: build-increment-commit 392 | workspaces: 393 | - name: gitops-workshop-repo-source 394 | persistentVolumeClaim: 395 | claimName: git-clone-output 396 | params: 397 | - name: repo-url 398 | value: https://github.com/darthlukan/gitops-workshop 399 | - name: git-branch 400 | value: master 401 | - name: image-name 402 | value: quay.io/sscaling/gitops-workshop 403 | - name: image-version 404 | value: v0.0.2 405 | - name: app-path 406 | value: sample-app 407 | - name: app-config-path 408 | value: sample-app-config 409 | - name: app-config-filename 410 | value: sample-app-deployment.yaml 411 | ``` 412 | 413 | Now we will commit this change to our git repo: 414 | 415 | ``` 416 | $ cd /path/to/gitops-workshop 417 | $ git pull 418 | $ git add . 419 | $ git commit -m "changed image version" 420 | $ git push 421 | ``` 422 | 423 | And our final step is to kick off a new `PipelineRun`, which will trigger a new image build and push that image to our desired image registry with the new version number we specified: 424 | 425 | ``` 426 | $ cd ../"${YOUR_USERNAME}"-sample-app-ci 427 | $ oc create -f 30-pipeline-run.yaml -n "${YOUR_USERNAME}"-sample-app-ci 428 | ``` 429 | 430 | After one PipelineRun has been created, you can also choose to trigger a new run from the OCP console by navigating to `Pipelines` -> `Pipeline Runs` -> `Rerun` (on the last `PipelineRun`): 431 | 432 | ![Manual PipelineRun](/docs/images/11 - Manual PipelineRun.png "Manual PipelineRun") 433 | 434 | The following actions will then be triggered automatically: 435 | 436 | - A new PipelineRun is created in OCP with a generated name following the pattern: `gitops-workshop-pipeline-run-` 437 | 438 | ![New PipelineRun](/docs/images/09 - New PipelineRun.png "New PipelineRun") 439 | 440 | - The Tekton pipeline checks out our feature branch, builds a new image, and pushes it to our image repository 441 | 442 | ![PipelineRun Complete](/docs/images/10 - PipelineRun Complete.png "PipelineRun Complete") 443 | 444 | - Tekton commits a NEW change to our repository indicating the updated image has been created (updates image name in `sample-app-deployment.yaml`) 445 | 446 | > *NOTE* - It would be possible at this point to configure an app in ArgoCD that would watch the sample-app repository and automatically deploy the updated image. That is beyond the current scope of this workshop. 447 | 448 | ## Considerations for production implementations 449 | 450 | This section includes some best practices to note when considering the use of GitOps and/or related tools through production. As 451 | the focus of the workshop is on concepts and techniques, any mention of specific tools is meant to be illustrative and 452 | not prescriptive. 453 | 454 | ### Security 455 | 456 | - Follow the ["Principle of Least Privilege"](https://en.wikipedia.org/wiki/Principle_of_least_privilege). Do not grant 457 | broad access unless broad access is actually warranted. A best practice is to have engineers document the roles and 458 | permissions required for their workloads based on the functionality those roles and permissions provide. 459 | - Operations should be audited. GitOps by nature provides traceability (who did what and when) but someone or some thing 460 | should periodically review traced actions to ensure correctness. 461 | - All tools should be vetted by your security team(s) and tools prior to being used in production. 462 | - Use SSO to set up users and roles, and then remove the `admin` account. ArgoCD and other GitOps tools have [SSO functionality](https://argoproj.github.io/argo-cd/operator-manual/user-management/#sso) 463 | that should be used instead of "local users". 464 | - Plan for and make use of Secrets Management before implementing GitOps or choosing your tools. Examples of tools known 465 | to work well in a GitOps setting are [HashiCorp Vault](https://www.vaultproject.io/), [Helm Secrets](https://github.com/zendesk/helm-secrets), and 466 | [Ansible Vault](https://docs.ansible.com/ansible/latest/user_guide/vault.html). 467 | 468 | ### Configuration 469 | 470 | - Separate application configuration from application source code. Practically, this means your application manifests 471 | "live" in their own repository (e.g. `sample-app-config`) and your application sources (e.g. `sample-app`) are also 472 | stored in their own repository. 473 | - The application configuration repo(s) should be owned by the same team writing the application, not an external team 474 | who can be a bottleneck to deployment. 475 | - Test your configuration changes before committing them. 476 | - Configuration should not change due to external changes. For example, pin your modules to versions so that you don't 477 | introduce drift. This also makes it easier to control version changes with Continuous Integration tools. 478 | 479 | ### Execution 480 | 481 | - Document the steps necessary to deploy manually. With GitOps, these are primarily `git` tasks along with corresponding 482 | automation tools such as `ansible`, `oc`, and `kubectl`. Ensure the team understands these steps before 483 | introducing further automation via tools such as [ArgoCD](https://argoproj.github.io/) or [FluxCD](https://toolkit.fluxcd.io/). 484 | - Once the manual steps are well understood, documented, and automation tools implemented, automate as much as possible. This limits 485 | errors caused by typos or distractions common during manual execution of tasks. 486 | 487 | 488 | ## Further Reading 489 | 490 | For those that wish to learn more about GitOps, and the tools that are currently available to implement GitOps workflows 491 | quickly and efficiently, check out the following resources: 492 | 493 | - [ArgoCD - GitOps continuous delivery tool for Kubernetes](https://argoproj.github.io/argo-cd/ "ArgoCD Overview") 494 | 495 | - [Tekton - Continuous integration and delivery solution for Kubernetes](https://tekton.dev/docs/ "Tekton Docs") 496 | 497 | - [OpenShift Pipelines - OCP specific Tekton integration](https://www.openshift.com/learn/topics/pipelines "OpenShift Pipelines Overview") 498 | 499 | - [Introduction to GitOps with OpenShift](https://www.openshift.com/blog/introduction-to-gitops-with-openshift "GitOps with OpenShift") 500 | 501 | - [GitOps Overview - High level explanation of GitOps Philosophy](https://www.gitops.tech/ "GitOps") 502 | 503 | - [5 GitOps Best Practices](https://blog.argoproj.io/5-gitops-best-practices-d95cb0cbe9ff) 504 | 505 | - [Understanding GitOps with Advanced Cluster Management](https://www.openshift.com/blog/understanding-gitops-with-red-hat-advanced-cluster-management) 506 | -------------------------------------------------------------------------------- /ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | remote_tmp = /tmp 3 | local_tmp = /tmp 4 | -------------------------------------------------------------------------------- /ansible/files/workshop-argo-cluster-cr.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: ArgoCD 4 | metadata: 5 | name: workshop-argocd 6 | spec: 7 | grafana: 8 | enabled: false 9 | prometheus: 10 | enabled: false 11 | server: 12 | route: 13 | enabled: true 14 | rbac: 15 | defaultPolicy: 'role:readonly' 16 | policy: | 17 | g, system:cluster-admins, role:admin 18 | ... 19 | -------------------------------------------------------------------------------- /ansible/files/workshop-argo-project-cr.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: AppProject 4 | metadata: 5 | name: workshop 6 | namespace: argocd 7 | spec: 8 | description: Workshop Project 9 | # Allow manifests to deploy from any Git repos 10 | sourceRepos: 11 | - '*' 12 | destinations: 13 | - namespace: '*' 14 | server: https://kubernetes.default.svc 15 | # Deny all cluster-scoped resources from being created, except for Namespace 16 | clusterResourceWhitelist: 17 | - group: '' 18 | kind: Namespace 19 | # Allow all namespaced-scoped resources to be created, except for ResourceQuota and LimitRange 20 | namespaceResourceBlacklist: 21 | - group: '' 22 | kind: ResourceQuota 23 | - group: '' 24 | kind: LimitRange 25 | roles: 26 | # A role which provides read-only access to all applications in the project 27 | - name: read-only 28 | description: Read-only privileges to workshop 29 | policies: 30 | - p, proj:workshop:read-only, applications, get, workshop/*, allow 31 | - name: ci-role 32 | description: Sync privileges for workshop 33 | policies: 34 | - p, proj:workshop:ci-role, applications, sync, workshop/*, allow 35 | ... 36 | -------------------------------------------------------------------------------- /ansible/files/workshop-sample-app-cr.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: Application 4 | metadata: 5 | name: sample-app 6 | namespace: argocd 7 | spec: 8 | project: workshop 9 | source: 10 | repoURL: https://github.com/darthlukan/gitops-workshop.git 11 | targetRevision: HEAD 12 | path: sample-app-config 13 | destination: 14 | # Need to get this automagically via detection 15 | server: https://kubernetes.default.svc 16 | namespace: sample-app 17 | finalizers: 18 | - resources-finalizer.argocd.argoproj.io 19 | syncPolicy: 20 | automated: 21 | selfHeal: true 22 | prune: true 23 | ... 24 | -------------------------------------------------------------------------------- /ansible/files/workshop-sample-infra-cr.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: Application 4 | metadata: 5 | name: sample-infra 6 | namespace: argocd 7 | spec: 8 | project: workshop 9 | source: 10 | repoURL: https://github.com/darthlukan/gitops-workshop.git 11 | targetRevision: HEAD 12 | path: sample-infra 13 | destination: 14 | # Need to get this automagically via detection 15 | server: https://kubernetes.default.svc 16 | namespace: sample-infra 17 | finalizers: 18 | - resources-finalizer.argocd.argoproj.io 19 | syncPolicy: 20 | automated: 21 | selfHeal: true 22 | prune: true 23 | ... 24 | -------------------------------------------------------------------------------- /ansible/inventory/group_vars/local.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | namespace: argocd 3 | state: present 4 | scope: cluster 5 | 6 | # Add default kubeconfig path 7 | kubeconfig: "/home/{{ ansible_user_id }}/.crc/machines/crc/kubeconfig" 8 | ... 9 | -------------------------------------------------------------------------------- /ansible/inventory/inventory.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | all: 3 | children: 4 | local: 5 | hosts: 6 | 127.0.0.1: 7 | ansible_connection: local 8 | ... 9 | -------------------------------------------------------------------------------- /ansible/participants-deploy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "{{ 'Deploy' if state == 'present' else 'Remove' }} CustomResources" 3 | hosts: local 4 | tasks: 5 | - name: "{{ 'Apply' if state == 'present' else 'Remove' }} CR Manifests" 6 | k8s: 7 | src: "{{ playbook_dir }}/../{{ participant }}-customresources/{{ item }}" 8 | kubeconfig: "{{ kubeconfig }}" 9 | state: "{{ state }}" 10 | loop: 11 | - workshop-sample-app-cr.yaml 12 | ... 13 | -------------------------------------------------------------------------------- /ansible/participants-make-changes.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Making Changes to sample-app-deployment.yaml 3 | hosts: local 4 | tasks: 5 | - name: Replace 'participant' with {{ participant }} 6 | replace: 7 | path: "{{ playbook_dir }}/../{{ participant }}-sample-app-config/sample-app-deployment.yaml" 8 | regexp: 'participant' 9 | replace: "{{ participant }}" 10 | register: replaced 11 | 12 | - name: Commit and push to {{ participant }} branch 13 | shell: | 14 | git add {{ playbook_dir }}/../{{ participant }}-sample-app-config/sample-app-deployment.yaml && \ 15 | git commit -m 'update greeting' && \ 16 | git push -u origin {{ participant }} 17 | when: replaced.changed 18 | ... 19 | -------------------------------------------------------------------------------- /ansible/participants-pipeline-deploy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Setup Participant Pipeline 3 | hosts: local 4 | vars: 5 | internal_registry: "false" 6 | git_clone_image_version: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.14.2" 7 | git_cli_image_version: "docker.io/alpine/git:v2.26.2" 8 | buildah_image_version: "quay.io/buildah/stable:v1.14.8" 9 | go_image_version: "registry.redhat.io/rhel8/go-toolset:1.13.4" 10 | 11 | tasks: 12 | - name: Set external registry image locations 13 | set_fact: 14 | git_clone_image: "{{ git_clone_image_version }}" 15 | git_cli_image: "{{ git_cli_image_version }}" 16 | buildah_image: "{{ buildah_image_version }}" 17 | go_image: "{{ go_image_version }}" 18 | when: internal_registry == "false" 19 | 20 | - name: Set internal registry image locations 21 | set_fact: 22 | git_clone_image: "{{ internal_registry }}/{{ git_clone_image_version }}" 23 | git_cli_image: "{{ internal_registry }}/{{ git_cli_image_version }}" 24 | buildah_image: "{{ internal_registry }}/{{ buildah_image_version }}" 25 | go_image: "{{ internal_registry }}/{{ go_image_version }}" 26 | when: internal_registry != "false" 27 | 28 | - name: Copy sample-app-ci to {{ participant }}-sample-app-ci 29 | copy: 30 | src: "{{ playbook_dir }}/../sample-app-ci/" 31 | dest: "{{ playbook_dir }}/../{{ participant }}-sample-app-ci" 32 | mode: preserve 33 | when: state == 'present' 34 | 35 | - name: Remove {{ participant }}-sample-app-ci 36 | file: 37 | state: "{{ state }}" 38 | path: "{{ playbook_dir }}/../{{ participant }}-sample-app-ci" 39 | mode: preserve 40 | when: state != 'present' 41 | 42 | - name: Replace namespace in {{ participant }}-sample-app-ci 43 | replace: 44 | dest: "{{ playbook_dir }}/../{{ participant }}-sample-app-ci/01-sample-app-ci-namespace.yaml" 45 | regexp: 'sample-app-ci' 46 | replace: "{{ participant }}-sample-app-ci" 47 | mode: 'ugo+rw,o-w' 48 | 49 | - name: Replace branch name in {{ participant }}-sample-app-ci 50 | replace: 51 | dest: "{{ playbook_dir }}/../{{ participant }}-sample-app-ci/30-pipeline-run.yaml" 52 | regexp: 'master' 53 | replace: "{{ participant }}" 54 | mode: 'ugo+rw,o-w' 55 | 56 | - name: Update app-config-path in {{ participant }}-sample-app-ci PipelineRun 57 | replace: 58 | dest: "{{ playbook_dir }}/../{{ participant }}-sample-app-ci/30-pipeline-run.yaml" 59 | regexp: 'sample-app-config' 60 | replace: "{{ participant }}-sample-app-config" 61 | mode: 'ugo+rw,o-w' 62 | 63 | - name: Populate Tekton task templates 64 | template: 65 | src: "{{ playbook_dir }}/templates/sample-app-ci/{{ item }}.j2" 66 | dest: "{{ playbook_dir }}/../{{ participant }}-sample-app-ci/{{ item }}" 67 | mode: preserve 68 | force: true 69 | loop: 70 | - 10-buildah-task.yaml 71 | - 10-git-cli-task.yaml 72 | - 10-git-clone-task.yaml 73 | - 10-make-sample-app-task.yaml 74 | - 10-version-increment-task.yaml 75 | 76 | - name: Deploy Tekton pipeline 77 | k8s: 78 | namespace: "{{ participant }}-sample-app-ci" 79 | src: "{{ playbook_dir }}/../{{ participant }}-sample-app-ci/{{ item }}" 80 | state: "{{ state }}" 81 | kubeconfig: "{{ kubeconfig }}" 82 | loop: 83 | - 01-sample-app-ci-namespace.yaml 84 | - 02-sample-app-pvc.yaml 85 | - 10-buildah-task.yaml 86 | - 10-git-cli-task.yaml 87 | - 10-git-clone-task.yaml 88 | - 10-make-sample-app-task.yaml 89 | - 10-version-increment-task.yaml 90 | - 20-pipeline.yaml 91 | ... 92 | -------------------------------------------------------------------------------- /ansible/participants-setup.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Setup Participant 3 | hosts: local 4 | tasks: 5 | - name: "{{ 'Create' if state == 'present' else 'Remove' }} {{ participant }} dirs" 6 | file: 7 | state: "{{ 'directory' if state == 'present' else 'absent' }}" 8 | path: "{{ playbook_dir }}/../{{ participant }}-{{ item }}" 9 | mode: 'ugo+rw' 10 | loop: 11 | - sample-app-config 12 | - customresources 13 | 14 | - name: Render sample templates to {{ participant }}-sample-app-config 15 | template: 16 | src: "{{ playbook_dir }}/templates/sample-app-config/{{ item }}.yaml.j2" 17 | dest: "{{ playbook_dir }}/../{{ participant }}-sample-app-config/{{ item }}.yaml" 18 | mode: preserve 19 | loop: 20 | - sample-app-deployment 21 | - sample-app-namespace 22 | - sample-app-networkpolicy 23 | when: state == 'present' 24 | 25 | - name: Render CR templates to {{ participant }}-customresources 26 | template: 27 | src: "{{ playbook_dir }}/templates/files/{{ item }}.yaml.j2" 28 | dest: "{{ playbook_dir }}/../{{ participant }}-customresources/{{ item }}.yaml" 29 | mode: preserve 30 | loop: 31 | - workshop-sample-app-cr 32 | when: state == 'present' 33 | 34 | - name: Copy secrets to {{ participant }}-secrets 35 | copy: 36 | src: "{{ playbook_dir }}/secrets.yaml" 37 | dest: "{{ playbook_dir }}/{{ participant }}-secrets.yaml" 38 | mode: preserve 39 | when: state == 'present' 40 | 41 | - name: Replace namespace in {{ participant }}-secrets 42 | replace: 43 | dest: "{{ playbook_dir }}/{{ participant }}-secrets.yaml" 44 | regexp: 'sample-app-ci' 45 | replace: "{{ participant }}-sample-app-ci" 46 | mode: 'ugo+rw,o-w' 47 | ... 48 | -------------------------------------------------------------------------------- /ansible/playbook.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Setup Workshop 3 | hosts: local 4 | vars: 5 | internal_registry: "false" 6 | argo_release_tag: "latest" 7 | operator_release_tag: "latest" 8 | git_clone_image_version: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.14.2" 9 | git_cli_image_version: "docker.io/alpine/git:v2.26.2" 10 | buildah_image_version: "quay.io/buildah/stable:v1.14.8" 11 | go_image_version: "registry.redhat.io/rhel8/go-toolset:1.13.4" 12 | 13 | tasks: 14 | - name: Create bin directory if necessary 15 | file: 16 | path: "~/bin" 17 | state: directory 18 | mode: "u=rwx,g=rwx,o=rw" 19 | 20 | - import_role: 21 | name: darthlukan.argocd_install.install_prereqs 22 | 23 | - import_role: 24 | name: darthlukan.argocd_install.install_argocd 25 | vars: 26 | operator_release_tag: "{{ operator_release_tag }}" 27 | 28 | - name: Apply {{ internal_registry }} to manifests 29 | block: 30 | - name: Get latest ArgoCD release 31 | github_release: 32 | user: argoproj 33 | repo: argo-cd 34 | action: latest_release 35 | register: argocd_release 36 | 37 | - name: Get latest ArgoCD sources 38 | git: 39 | repo: https://github.com/argoproj/argo-cd.git 40 | dest: "{{ playbook_dir }}/temp/argo-cd" 41 | version: "{{ argocd_release.tag }}" 42 | when: argo_release_tag == "latest" 43 | 44 | - name: Get {{ argo_release_tag }} ArgoCD sources 45 | git: 46 | repo: https://github.com/argoproj/argo-cd.git 47 | dest: "{{ playbook_dir }}/temp/argo-cd" 48 | version: "{{ argo_release_tag }}" 49 | when: argo_release_tag != "latest" 50 | 51 | - name: Set deployment manifest facts 52 | set_fact: 53 | redis_deployment_json: "{{ lookup('file', playbook_dir + '/temp/argo-cd/manifests/base/redis/argocd-redis-deployment.yaml') | from_yaml }}" 54 | dex_deployment_json: "{{ lookup('file', playbook_dir + '/temp/argo-cd/manifests/base/dex/argocd-dex-server-deployment.yaml') | from_yaml }}" 55 | server_deployment_json: "{{ lookup('file', playbook_dir + '/temp/argo-cd/manifests/base/server/argocd-server-deployment.yaml') | from_yaml }}" 56 | 57 | - name: Set image facts 58 | set_fact: 59 | redis_image: "{{ redis_deployment_json.spec.template.spec.containers[0].image }}" 60 | dex_image: "{{ dex_deployment_json.spec.template.spec.containers[0].image }}" 61 | server_image: "{{ server_deployment_json.spec.template.spec.containers[0].image }}" 62 | 63 | - name: Set image version and image name facts 64 | set_fact: 65 | redis_image_version: "{{ redis_image.split(':')[-1] }}" 66 | redis_image_name: "{{ redis_image.split(':')[0] }}" 67 | dex_image_version: "{{ dex_image.split(':')[-1] }}" 68 | dex_image_name: "{{ dex_image.split(':')[0] }}" 69 | server_image_version: "{{ server_image.split(':')[-1] }}" 70 | server_image_name: "{{ server_image.split(':')[0] }}" 71 | 72 | - name: Backup dir for original workshop-argo-cluster-cr manifest exists 73 | file: 74 | state: directory 75 | recurse: true 76 | path: "{{ playbook_dir }}/original" 77 | mode: "ugo+rw" 78 | 79 | - name: Backup workshop-argo-cluster-cr 80 | copy: 81 | mode: preserve 82 | src: "{{ playbook_dir }}/files/workshop-argo-cluster-cr.yaml" 83 | dest: "{{ playbook_dir }}/original/workshop-argo-cluster-cr.yaml" 84 | 85 | - name: Populate workshop-argo-cluster-cr.yaml 86 | template: 87 | src: "{{ playbook_dir }}/templates/files/workshop-argo-cluster-cr.yaml.j2" 88 | dest: "{{ playbook_dir }}/files/workshop-argo-cluster-cr.yaml" 89 | mode: preserve 90 | force: true 91 | 92 | - name: temp/argo-cd is absent 93 | file: 94 | path: "{{ playbook_dir }}/temp/argo-cd" 95 | state: "absent" 96 | when: internal_registry != "false" and state == 'present' 97 | 98 | - name: Create Pipelines Operator Subscription 99 | k8s: 100 | kubeconfig: "{{ kubeconfig }}" 101 | definition: 102 | apiVersion: operators.coreos.com/v1alpha1 103 | kind: Subscription 104 | metadata: 105 | name: openshift-pipelines-operator 106 | namespace: openshift-operators 107 | spec: 108 | channel: ocp-4.4 109 | name: openshift-pipelines-operator-rh 110 | source: redhat-operators 111 | sourceNamespace: openshift-marketplace 112 | 113 | - name: Set external registry image locations 114 | set_fact: 115 | git_clone_image: "{{ git_clone_image_version }}" 116 | git_cli_image: "{{ git_cli_image_version }}" 117 | buildah_image: "{{ buildah_image_version }}" 118 | go_image: "{{ go_image_version }}" 119 | when: internal_registry == "false" 120 | 121 | - name: Set internal registry image locations 122 | set_fact: 123 | git_clone_image: "{{ internal_registry }}/{{ git_clone_image_version }}" 124 | git_cli_image: "{{ internal_registry }}/{{ git_cli_image_version }}" 125 | buildah_image: "{{ internal_registry }}/{{ buildah_image_version }}" 126 | go_image: "{{ internal_registry }}/{{ go_image_version }}" 127 | when: internal_registry != "false" 128 | 129 | - name: Populate Tekton task templates 130 | template: 131 | src: "{{ playbook_dir }}/templates/sample-app-ci/{{ item }}.j2" 132 | dest: "{{ playbook_dir }}/../sample-app-ci/{{ item }}" 133 | mode: preserve 134 | force: true 135 | loop: 136 | - 10-buildah-task.yaml 137 | - 10-git-cli-task.yaml 138 | - 10-git-clone-task.yaml 139 | - 10-make-sample-app-task.yaml 140 | - 10-version-increment-task.yaml 141 | 142 | - name: Deploy Tekton pipeline 143 | k8s: 144 | namespace: sample-app-ci 145 | src: "{{ playbook_dir }}/../sample-app-ci/{{ item }}" 146 | state: "{{ state }}" 147 | kubeconfig: "{{ kubeconfig }}" 148 | loop: 149 | - 01-sample-app-ci-namespace.yaml 150 | - 02-sample-app-pvc.yaml 151 | - 10-buildah-task.yaml 152 | - 10-git-cli-task.yaml 153 | - 10-git-clone-task.yaml 154 | - 10-make-sample-app-task.yaml 155 | - 10-version-increment-task.yaml 156 | - 20-pipeline.yaml 157 | 158 | # k8s module doesn't currently support generateName: https://github.com/ansible-collections/community.kubernetes/issues/186 159 | - name: Create PipelineRun # noqa 301 305 160 | shell: 161 | cmd: oc create -f "{{ playbook_dir }}/../sample-app-ci/30-pipeline-run.yaml" -n sample-app-ci 162 | 163 | - name: Deploy workshop applications 164 | k8s: 165 | namespace: argocd 166 | src: "{{ playbook_dir }}/files/{{ item }}" 167 | state: "{{ state }}" 168 | kubeconfig: "{{ kubeconfig }}" 169 | loop: 170 | - workshop-argo-cluster-cr.yaml 171 | - workshop-argo-project-cr.yaml 172 | - workshop-sample-app-cr.yaml 173 | - workshop-sample-infra-cr.yaml 174 | ... 175 | -------------------------------------------------------------------------------- /ansible/requirements.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | collections: 3 | - name: darthlukan.argocd_install 4 | version: 1.2.2 5 | ... 6 | -------------------------------------------------------------------------------- /ansible/secrets.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Setup Secrets 3 | hosts: local 4 | tasks: 5 | - python_requirements_info: 6 | dependencies: 7 | - openshift 8 | - name: Create GitHub Secret 9 | k8s: 10 | state: present 11 | kubeconfig: "{{ kubeconfig }}" 12 | definition: 13 | apiVersion: v1 14 | kind: Secret 15 | metadata: 16 | name: github-token-secret 17 | namespace: sample-app-ci 18 | annotations: 19 | tekton.dev/git-0: https://github.com # Described below 20 | type: kubernetes.io/basic-auth 21 | stringData: 22 | username: "pipeline" 23 | password: "{{ password }}" 24 | 25 | - name: Patch ServiceAccount Secrets 26 | k8s: 27 | kubeconfig: "{{ kubeconfig }}" 28 | definition: 29 | apiVersion: v1 30 | kind: ServiceAccount 31 | metadata: 32 | name: pipeline 33 | namespace: sample-app-ci 34 | secrets: 35 | - name: github-token-secret 36 | 37 | - name: Lookup namespace Secrets 38 | k8s_info: 39 | api_version: v1 40 | kind: Secret 41 | namespace: sample-app-ci 42 | kubeconfig: "{{ kubeconfig }}" 43 | register: secret_list 44 | no_log: true 45 | 46 | - name: Collect Secret names 47 | set_fact: 48 | secret_names: "{{ secret_names }} + [ '{{ item.metadata.name }}' ]" 49 | with_items: 50 | - "{{ secret_list.resources }}" 51 | no_log: true 52 | 53 | - name: Get pipeline dockercfg Secret Name 54 | set_fact: 55 | pipeline_secret: "{{ secret_names | select('match', 'pipeline-dockercfg-[a-z0-9]{5,}') | list | first }}" 56 | 57 | - name: Patch pipeline dockercfg secret 58 | k8s: 59 | kubeconfig: "{{ kubeconfig }}" 60 | definition: 61 | apiVersion: v1 62 | kind: Secret 63 | metadata: 64 | name: "{{ pipeline_secret }}" 65 | namespace: sample-app-ci 66 | data: 67 | .dockercfg: "{{ pull_secret }}" 68 | vars: 69 | secret_names: [] 70 | password: !vault | 71 | $ANSIBLE_VAULT;1.1;AES256 72 | 33616337343331373564646533666163393734313834666662383461633332313465393161343463 73 | 3735663138656530656433343062633030333630393835650a643131623134383037626266663237 74 | 36323935353430396236613463633431303662336632343663316532633130336534323131663161 75 | 6262353038666165640a643561316461646132383164303933336461353539356561663562663765 76 | 64653238613137393932646130643230343839306135396264306633343534306464313730643133 77 | 6434613538393061353465643434376638343731623363636164 78 | pull_secret: !vault | 79 | $ANSIBLE_VAULT;1.1;AES256 80 | 37333232313162656335303766336561623436333638313265666136323862343436633437653033 81 | 3133313136626130326631626339383565396361623933350a353364386331626665303530656335 82 | 31383536323834396161396531306166363133336438636630613836366537366631386637356530 83 | 3037346566323733320a636138336161613566313834666138383361626365333764303962363834 84 | 61613263336462616263663437386561656236633531343363656164323266383462616135353933 85 | 63633135653036636666653438303663376434393431343533393534333861643235396564353961 86 | 35653139386235363061333231386231303237353133646465626436666537326432633436316266 87 | 66396635623665303431643937653837343264336331663066666336616261386634646166343430 88 | 61386233616563663362313463386331663766346337373530626432323430346433653264333331 89 | 34326364393430646630323134643636613162636230383638326631616234303065366265323930 90 | 38376337336135303931326130656638666137323061386261623038353037646533343366316635 91 | 31623565353663656465386132613532346165386464336435393261346461653436623133636134 92 | 38623865303334393364626439316239656366663832313338643830393334636562393032643265 93 | 38653064623436356230666532303366373939613937356433653066383534653165333561623938 94 | 63346432383231653561303339306635333662656230666465333361363234333763333031333332 95 | 62396137613165353139643639306630613861633730643939326533346330646131353263373734 96 | 33393163393834383338326138666436313132396237343032386638373832373234326461373534 97 | 36326234323335333564656538616434383366376230303462313166343465356632646639316639 98 | 38366333306366653639323366323332326639336431623735313531353035643930353836363466 99 | 62353932343532303065653934383965373230393132383239383031633630363336623232626535 100 | 35626334343331646532326365343633343730323833643163326531383934623233383935323336 101 | 61333561396166653665313031343539346535626431353662333634356538313232623937363033 102 | 36363861656637656263346231383634613032336130333862663036653562306530643135303832 103 | 35336332623665336664343963396261333632303065626362626533323463646138396365333634 104 | 37653834313065303033323566633431386537616239393135653134306538316165353337303566 105 | 36396566343263653233643033633865383538323464326166393735323063663532323239623465 106 | 33626465643231343239313832303766353933363937633065396264343032376331326364623065 107 | 62633536383733393963393338336163356461366532353830303735663731326533353930313632 108 | 31366132613633306366346437666462623730623664663262323165306264323535303765383564 109 | 36656562373232663361336439376638386531363262383362396338633632646539393439366463 110 | 39373833643230353136376364313635363766643665623864656661306235616162633732613764 111 | 37356633303461646464333662653933333565666237363665333535353633646230303230666561 112 | 31666263383131366666353962336539366131613238356465346333336462333330663262366137 113 | 38623761616161343965313036623432623030346163623135346432343361343166313266313537 114 | 36663739313066623163343865323037383534366662626530663561356264633839363632323436 115 | 33393035636530643563653436333331663734303465393634386335336336396164346163613530 116 | 34306438383062393436383631623463656634386537323661316164306165646562663530616162 117 | 35643966373339353233326365663038613762306130666130616135653938373766373261623533 118 | 30393265396433653366663433363631376435623537646630643038653138366232643365326232 119 | 62333061656232626661343433326165386238356337366365313663323861613431646562346131 120 | 64633635346133373031383430623961393466333839306330316564613361356332373139356265 121 | 31373930613939393161643062613765653831656533613737363338353933333062326237303166 122 | 33316333306230393662333631343361623333653238633663653063323363393536666562653538 123 | 30363961363035386233613130323332363631386266633038646566303039616163343430303063 124 | 33653031313063343632643830376231323664376631363530323336303931636337353531346238 125 | 31613636303639396666346134376638663663613532646530383834616633633061646266643133 126 | 36353965336130636233336531343266326639353937616633313061623639303263306234373530 127 | 63393233326134393338326130353366636134633733303636623735633062613938633234613631 128 | 31383662313032656134343531373330303465613765363434613133646461633034643736386235 129 | 37653634613933373266303931386535633666333261613334306631343033376434343136666463 130 | 64386237383861316139306562653136316235326231323834616463363137346661343463613330 131 | 37623239376431613932313030613164306239366439626465663663383764326433346665626661 132 | 35616566313733386434653036613034666266613139653366393765323434393466353661313963 133 | 39336262363637353132336339616438353638396564356439366530323733383636633265393236 134 | 38366336646634663135613139343765383937393737363537346132613463396135636262636535 135 | 65646464303564626465303339666636666132393334633738333065626332643539336261336361 136 | 66636365376436366435373736376532363130623239306434616661306135383631313539613535 137 | 66393939653863343939363764396166636263336337366563326235303963376661346130303436 138 | 30363361373535616332383166626136613639363162353363633336643964316463613437613334 139 | 38613236616364373436616632313631373663636465313732633162313134386361353032333862 140 | 37616530383236636137613839356532663266626631306638323535646535333037636431623365 141 | 32313532306537666465393336616561393639646264656637383066663435343836303066326532 142 | 66326137396234346139373235323464646135613965626236383331613638336438313064316639 143 | 32323230623836336430336336653131323261303361316237386661393565323031346564636132 144 | 35306162613663303766333931386636343263653339366364373439623638373238613837323836 145 | 32663165343863336135653832646133613861656262373164353832366432343064363833333532 146 | 61633137353234613238656466353932356362353639346663663238656634633836643163353462 147 | 34613237653766626164363363376136323065393364623632386534386534623530643163393433 148 | 64666335616364383434396561613438636266316566623431333737616238666239393436326565 149 | 61666434333131656332333062666162653431396535396435636430376232353933386333393764 150 | 65313234303430626136633164366235626362376165323831626532653563373262653664393364 151 | 61363035383064396462343539623766366137326139636562353433353538386562636239313838 152 | 61373833383464383238366163623737313964626434336264326339386264313065363030396263 153 | 32363130333236623862653131616234346633663336313537313335653464323838393730363635 154 | 33326563613930326164633065356334623839393766346565323230353434373262623739333934 155 | 66653564646234343563366463626231356139376531653065633332306139303265643533646466 156 | 34386561623736626437393133666466313231653166316333323432323030333661663031303331 157 | 39653861363962646462326430373763373334393933616534636336353837643739656366323761 158 | 38366335373030346535323039383231383730616263643837353036393363346431303261646463 159 | 32383130366261346336333563393863623632346366633636393137316461363138343835343039 160 | 32373336373538316232346431323263666532333031613565376165656364316661346233313763 161 | 33366632383966333433663465323164626535303561393531303438386132363135333533663437 162 | 37636564343633336165393766633235313132646435616531306562663432643132313761303830 163 | 32383831356333636265623431623764313130643938653931646637616439633230356433343466 164 | 30343563616338623639356461333238323135626461636338313339386532633339613136313830 165 | 35353036653863653261646636306134666438613338366562316661663661643537643331653132 166 | 32623530323061353365626332656437663935383762303865363430336334316231616536656661 167 | 66323564616365343336623536313030633062643563656133356464386563376466366461356238 168 | 62393730346362313234356333313966333531386161343533343966353765363534396539636538 169 | 37376631366463393762363430356534343337396164373931316431343764353635343464383233 170 | 63386134613936376431626666393266666363633466363038306135626562383266323235366434 171 | 36643330313534636231636230323335323432616631343735663738363165666266333837636334 172 | 37666538353638346464373262313666313236373430353465346362316230363461623462353730 173 | 33663661363236386138643962623565323730613532346336323532333735363035613631343134 174 | 37333037613935373366613962643235343035633535393435666636616266323965346438326439 175 | 31343031346237396639393163396365323837666535636536653836383637633438303934333161 176 | 33623462646161343562303964653034643939313934376239303537313738653438643562326136 177 | 34343563333931633666613939313536363961363165383664363038363566326530356430666563 178 | 65333634373339356363363339633932663166353130396664393133333166363635356462363237 179 | 37303730653530353837393433643132643262646263363335366139646239313836633832663339 180 | 36656365636437313466623930623861323261363538356138333061356137653837386333393233 181 | 62643734313332353761376138396362393861306564666139396561623366386430396664396634 182 | 62383135393264326333393630303263326332656662333330666265346635353364363665393162 183 | 62316162343132396131653032643332313261383833386336386636326563366338643533343139 184 | 36323363663730303262666663356134666661646539643036383936616663656537373835633763 185 | 64383832633265313865663934303637353232393664656437313737633865393131386137393264 186 | 30326464626536626234363333316263363663616130353732376538346434366566646234636265 187 | 31373066343362326663323038663064663932303538303031326565656133376262373562626338 188 | 64356466633137343764633031663136623964353731666438636337336633396463656339396132 189 | 61383135643534623238363037303361323131633933343135373963383562336538663030386166 190 | 63633432623162353634316461303232643536656337643734376464663032623830316333383435 191 | 34343435613431326266383065383431616630323534636262643264316537373331666432376361 192 | 31646531306565343733653238346564616563613734303339376661623566623962376131343535 193 | 65323263633961303937616634383138346234306233393765373135623335636336623339666532 194 | 61383863656262623138656266393732363362333039383665393761653664333132306636313433 195 | 65626235303361396562363432623365306130363434653930373266326638313165646538663235 196 | 34663831383432636231623163643164306231386332613562346136323335306562393962366439 197 | 33343363373861373435393561363938643063636338646365366138336438353638656435383939 198 | 64356461303538633562333063303033366534653034343632373863373064396539656531353836 199 | 31336434336635363064353333626564646564373739663830393230306334663834383062653634 200 | 39363935616662626233303064636562313036616535336264653239386263626631363330353634 201 | 33653961653432326131653232316565373430636566303539613961383661663231663839353230 202 | 61333062613361363762303962653632646361666632373933643433323433373664643264326630 203 | 66363436666132313532356461366562383764373138323335326562346336363461636430616333 204 | 61376138643165616664303637613365666330313632386538343632353863653362386464363961 205 | 39626230613435636530623535343739303565613865626236323964316537373536376562636336 206 | 62366437396433303335396563663866623662323766656664336661356238366133353165376335 207 | 62393731633238306533356231623339376564633836616639636630373164656536633338376363 208 | 33376231353735386630363964303331666431386361383733633537366237616164643663333761 209 | 65626539626662363839323531653036643338346435616561383261613136633935623764623761 210 | 31333336666462623338356135623535613730386535643635653463303936613236383066396262 211 | 30356137386536363238343065363062616332663263396339326338623362636465616466363166 212 | 61353062383236363831396566366237653935363865313161333939343437376539396466323066 213 | 31303439363464336139623535373430646266346636636266303435303763343734653365616166 214 | 36393238663763306161386263343833663663613039323130653761616531376631333531613234 215 | 63386137633234393964626239353530346331313336336435653637303333326132626232303164 216 | 64376537626462323337346239643637636161383964346262353236396138363238366234346462 217 | 61343238386665323064666532343735633837316666353731353037366466663635363236653635 218 | 31396664613364356565306633616535343361383734366434373762326335633664363962643030 219 | 32386462643737323261333031316462616332363934306563333765616138663539663366376161 220 | 38303430373532643532303964326633653530636465616464306464366561336334303436373265 221 | 37626265666164393138313434333834363136393830343638663036336236633666613934623664 222 | 37326466306335343234386437323663363861666637303164333764663537336138653264623166 223 | 30303435656465613364613063643633653532613966343461336164393362336235343337376262 224 | 66326165666463346135316265646136626663383663373734363934323966306665383331323164 225 | 65656630366664646435366664653966363134396339326138386332656533653135313232356232 226 | 65386161663766333132613637356364623739623363323265383335623031353762303661653530 227 | 39623163303130626565616232373937626663333939396130363431653032663366383465633537 228 | 65353030376135366234626536663764383433653766663564393939633065623735336135373034 229 | 31343663393733393363326335623736306335613131626235363739623765616265343431326162 230 | 30653338333064363432666139346363343234636530313362393433383331386264623136633830 231 | 34386261346234373161383932383434343836653366653931323665306234326534663732363634 232 | 61363734653664333139636232346361663633623264316133386438323434643665633766383735 233 | 33626139396539333939326433613664326538623662316635323261366362323466393038653431 234 | 63326535306438353566353837346130336464333261313238623236383362346533626439313933 235 | 62363434633332313939653438303233666432363961663839653834623433366632356636383039 236 | 66323033353835303037303038616562323932663134623464623761663737346636653237396663 237 | 33356365333464383764333266626534313935306234616261613539386531616366356533343138 238 | 38393334633138333234373563666436336434363139373762373433343232633532346132643836 239 | 37656337393463383263313937316138663236666664383861643663363935316435343563363038 240 | 34383332653866366264646131323062646362386330656632303032383764326464653533623062 241 | 66376362306332316230326436336461333461316230363363303865333561373032373635633364 242 | 39336338366331353534393134363930616233663264336463346561326133636365336435323163 243 | 65346261356136643831353065636264393739356238613665613233376664336461353735626365 244 | 62323863353739373035373138356266303463643137643736333563336361343731386533313238 245 | 62663732323232353830616661633439326362396537346166656632653934346637316264323734 246 | 34626533323063663232396166303639663564633564363536323361386663346465393235313934 247 | 30633563623063383838613465656537643633333663343833393836643162623662646636623266 248 | 30323731323731313261386236653764633030653336363964343035333665393939313439363237 249 | 65386363346639323661633238393932643030643361646566303065623939343561316530326637 250 | 66363834613766623935623866363231343139333936366461396364336434396466316139363437 251 | 34386139656162333666326636633965396565363332323137366562613238356633393038353138 252 | 63346237363034633637323733323439633861373032316164323766333634363331623636326162 253 | 39393262633932636133323164313831303263636231336566323332366332363033613265336564 254 | 35303665663566393136393365356137373664373634656261383464393531616131623465306565 255 | 30383735386236316637396438366365376430306264616135356238303538613661363062656261 256 | 35373866353762613939353636313730336232663865663530343261633763663435663761613138 257 | 64623833316263656130396538323635613539343132616636393432383131323662613133386632 258 | 65626136623239333266353366303963303635333365363863336363643261336432383633366661 259 | 30653835366339373539393537303237636638636462346566306238323636653464363335386534 260 | 37326437386139373238376437346534343063306263643437353365633461626135393966316533 261 | 37636639376261366634613437623363363963653532313137366336646461633832306635323163 262 | 37303134323363323236393561646536333935316362326330373765393132613966323461306634 263 | 66383531353431616230396435643730306438666635663434373138653730353435343030363966 264 | 32316433666137653432383466363064396532363361336135333239363035343930333930396334 265 | 36366161666631333730373364363166333966326238333262613464633964613536613039316537 266 | 65376433306566386331623730333861623034616433663335653132333963316532333765323833 267 | 65306237393237626231373863326337356631313064373463646339616464623261393366623134 268 | 35616235663465353135353735346564366333363832303265656130363864323430656164613466 269 | 33383830663631353438363337313766346138336636316439353836333233663863346562636237 270 | 34633035353139346233663364613731616237373030363737333839333966326366653534663631 271 | 63363266613739643063393932343831393061633435346235316132663337323832313961376563 272 | 62303064303564316333313135613662396161623266613235333633313839343130343339623731 273 | 30366261633135313666643632613338363464653665646535383935623061353036396532383831 274 | 32336634656362393964333065373563356265613433633938393863653034343337646666383234 275 | 61653436613735373565663834613438303066613566633864356536653936653437336433616666 276 | 34393665356663306336336535646231326266626533663361376433323231396630656636636135 277 | 35636630303065386237343062616233613661323134373130623662346462663563353861346462 278 | 35633537633132663034343339303732303835613834633038306639623533313361656236623632 279 | 63633036633763636466346565393036313861373539396130626234633836373565306635333031 280 | 66363133623933623339343030656635666237356338616636643430366238343635626163333337 281 | 39313137316361633038363361373735353635613563633139613230633663623537323962663039 282 | 66326139613361616463616633613637613034363338656162666331326234346566623739353464 283 | 64323132383636393662346330643064336562656237663065656664336236333734383333396436 284 | 39646236623537356361636236643766613230316330633539653936366365363433643561633134 285 | 64623930316134643933623737646230363366323565303639666161653261623436626338313566 286 | 62303338303235646136393532633035373637663465643864383538313631636663353231366332 287 | 65646534313834346133633139323438396232633065386361643931623339323832353139396231 288 | 31666636643661313535336265326530313435353061316163303562643738366661343064636138 289 | 34613635666132376465646537363864346233663963373365396530376334613035366639346566 290 | 63363637336263636362613766343164666263303062323635373132653266623262316534356165 291 | 30383064353566303636303664613961383536616633616230333231353438303039616362376139 292 | 62643634356530663366363665336265323361323531363434633234303461366139373934626639 293 | 32643432653164643135663833653138383464643565353035336634613938656536663433643066 294 | 37376561306365363531373364376434346434323635343964656239343761626238303832656331 295 | 37373963663661326566613465653834343933346465643565646662346430656665386339323662 296 | 62633537363566306166346635636261363638636431653162346165663034633133633362343434 297 | 32643436626538386439306535376432366465613537373864303639386235663931383462303865 298 | 32636362613137313639343232376263343436353236373636626438303935326236316437623964 299 | 66623462336132366131306462393562346532323161383835643238316564616265643366653237 300 | 39663434643432323966313231663265353836343361633739663136663064636461633333613037 301 | 63313032383362666365623164303666326463316563353238346337643335626236316166383137 302 | 34326139303562626631336539666335396339353132613565363634653266613739663063363265 303 | 66313530353065363863373936303538323365653934333063363562656365626166663335636334 304 | 32313130633230626639626134343239346566636331663631643632326334643237313066306339 305 | 33383030363163396530653634663533633964393861323139393037663131323666323136316162 306 | 36633465346466333562613330343138663466383330373831373064633538663461326163393862 307 | 30366438376564346537366463356334323038386264323837333833303935653432633161306532 308 | 37353730326135303034666163333766396533323233376630343231636163666236383034333436 309 | 31646561613338333738333661326636343236353061656165316163353431393432636431656661 310 | 39623165363561656234643835626434303464303433346539356636366432393331323739303530 311 | 66646666306639663664386439666631383064393333653764356338643666663365613038666663 312 | 32366639656362373265336161373036333430386361626530636235616237666563373434326462 313 | 39393766306462616665643165646530326330333830393062313665626436656364363866326430 314 | 66313764626364633338383734623034333133316535333436666365343534643733303661346635 315 | 66333736646433393266326132653133366538656538383633646563323631366461333738666131 316 | 37383539396336386532373037373865613137396437636464303134306361326136316137386535 317 | 31643862356231323731316432313033323739353232666134333565646166333365343331356132 318 | 39333637353630326538343639626638633937366634623634613462343831623334323062383837 319 | 31353334643236306138623261353832303336613861306430643339383635396639353736666639 320 | 35363762366337376237343065663761313362373332663039643261336234366336666336376362 321 | 35363333353136646631306530393938633663643538363633613263356564326638353539633461 322 | 39353936303663373336663436363033323238353035386463303362316439323532323238623938 323 | 62646662373961663933616630616238636332323937303633383466363333316339656562343765 324 | 62633564363864303962333462316430613330386335626534393962386365356166333936383837 325 | 38663265373634313933613634333139666131323861363238636335636433663732363563616164 326 | 66396462376638336433376130393031663562643230313661623232323638373766306262643734 327 | 62303437336332336138646337613363643937646130663537373434646465653662666235383035 328 | 66643934333135666463653763373965316538333030656634393563333438656163633762383538 329 | 61373366373132363430333031636665383830326538396337633235633734343839643237626666 330 | 61626231663136376430393835396163633535623934393336323065393662363136326662386638 331 | 66316534646463383764366234343965316631396163363232303364373932646336343039623061 332 | 61633765663064663362316661353132633864636236626430313530356639363433623537343636 333 | 35646662393866376365336565303334656163323539316535343931346131623733653363656138 334 | 30633164306366653565663365396436393136383563303264613330396339386132366564333737 335 | 61383965353234306165396437613064386561633133616234666261343762663236306638383865 336 | 39333962643563343739353531316662623938316530306461363434336365373237323462353337 337 | 39633364633962623739306530363233333134393834396262626163393037633335333264626438 338 | 38363336643761376361646164626132353666356561653936656131393766353834666263366530 339 | 37333965633730383365306666616235643863316531623334613536633934393035396236626439 340 | 66613563636437396465626163663034663436336534333261326164613563396362633466363832 341 | 62353939656236663538373238336561663631653434623766383931356333373464323533303330 342 | 64626562626362646166343239636363343765633065623264306363363036366337363336623561 343 | 36346436656531333834636432646666363761323464623966323433333937326364636463386439 344 | 33616666306362356430623266613832353561396561323464663938656635386663623934383761 345 | 62326138653162326232666534373164643237356535326166343536656134383734333164363839 346 | 65623262313131343766303139386133306235366135376432613062623161363838613063303838 347 | 34313333663337636163303431353364383133363766663964656163653230393934666132383238 348 | 35653437633562636465393262383833613763653962636238306435613438666165303532623134 349 | 38636435613935316561363436626532356562393836633864663535613936303233396563646137 350 | 63613964356265313763656438633435626666633231613366623062663237613963626531303832 351 | 65386333656339633661666438313333336638333763636465343464333861303361383238656464 352 | 63653835383866306165333032646539653065363436636466373166326535623435366663613364 353 | 34663338376336356263303862313539666639363362383066313636326132636564636161366638 354 | 30396431356134336638316437343830373431386330623261623165633261646233396461393537 355 | 37316132633138666437616632643434656337633065663335636632653033303562373530323236 356 | 38343734333365373465363830616462363637383632613535333135333365373039356566633863 357 | 63623961303261373533336335336633316266343131323332623936646264616136613962633666 358 | 64393234303533333262313337333962303961633234633531316565633638366434343134623630 359 | 39313434383537386664303333323036333137613863613837636434353236343161613162356433 360 | 31326231613939616634633336313035306332626430663862663532363761363765616438313430 361 | 39653761653365343065616339383733303933343865623764326266616365303363623432373132 362 | 39313331343438373031396534346365383239663535656635363261343964323064643233643032 363 | 30663362313265346434633936666262633537656431303639633165363932303536623765353331 364 | 32663465383534653863373766363335353132643932353535663665336134666231383061646336 365 | 33383761343334623639313865666335306234383461623839316664346365373234303137663330 366 | 30653833386562613264386231303639626565366239393063303266343934646463383834613038 367 | 64336233353935333138646563663234323131663038643163613931336435336234346264313534 368 | 63356433666564386437646633363938663333323638353835336364376236383031393338626331 369 | 63336631343466633530323036356266356266653937343036393365366139343038643034393935 370 | 62643136666362366561376436376339663135303936353630343565646636356130643038663238 371 | 37313966333764326238376165356465346463646136396434323731633035633261656638666635 372 | 62633066326666633130666565623536663466303733656130383263313833313737333466313236 373 | 35313834386562353365316531653530353966383636313136356565666537643337623763313830 374 | 32333731363465306165336434343733653535643834643338626363613039666463356536613164 375 | 34313739383731646238336163623461303136323563396261643430346632396439306662343433 376 | 35623165636465343762373932313033313730386138323961623463373062323266666432343666 377 | 37633462363039613366303131366262643437626664323462383838353661643038376363306466 378 | 38663932353165323232663662313066316139653430656538383133623134626334633437373138 379 | 63636632333765373761646538623436326636336235333839396262396465333835316632363838 380 | 33316539633637323564376436366336373432656138303739646333353436643135326261326331 381 | 62306538323262333738376535333933366363343339656630353633636662336363343034343465 382 | 39353865353534636331303265383362326364366433353665306337653332656663373637623931 383 | 66336663333132646561346565643761343566306466323663373932353765336139343539653336 384 | 33323536326261613465333137343863323136613630373462396634633638356435303665323561 385 | 65663538656632373863656335313565623565333964326665663064343831316361623238393634 386 | 64356463393130623465376362646264343838373339623561356465303365626462393336333037 387 | 33643039663035343661313764313538366137653333396133306433656262633634636561333638 388 | 37623332643635623464643130366264633663333761303131346661303563376233313432366531 389 | 34316562646462373437393739313138613062646264323561303462386336376661666363306531 390 | 66666262356361323235376566303838343335313734343764396564663334623330643162646465 391 | 66633832373531323334356461313762396364653665623030613935363632623066376235663362 392 | 62383430336265313061666565353239613465316466643135323134393261306335373034643566 393 | 33646134306231616261363966333533363466633465343232613033666138663231376263616465 394 | 64326463323437613965613039393038636637363964333837613036366630666436346332356535 395 | 37353834666361383032383336356661356265663031646662316338633339316661623263386438 396 | 36313432323937366536373134636338623163373831623130313930363634383066623234313632 397 | 63653237393366326661393530643131633263613563326230356334333364656632326439383431 398 | 33316134613963636435643939646163366635326237366233653232353935653239373630373439 399 | 61633665353233613931666632303763353133626162343232616236363432336135336333633738 400 | 66383164383862363435633537656666316639643362336430326463336661643130366562633333 401 | 39333735303938323462363062633065366535643038343165663335653263346164316565656334 402 | 30383930656430383839316535343937616134623636306332383165633336616330366533633063 403 | 34346237373834633462303630653436313633336237316539373964316133343835313638336365 404 | 65366364623561633734663833356238336661653039316630333466383938383930633330636537 405 | 61376233303732636532636566643331616535376364333736353132656235616133353530663466 406 | 39346365663637363438643433643638393032623331323631666136316334373037353236356235 407 | 62343164623061646638626264363461303937323166623432303061373834323464383634383831 408 | 65376232353862373038656166646363663962653565343534643066386638396565353438323234 409 | 65616161373761363439376539333934343663633832636161313732373434313335303033333330 410 | 36623735373439386230343761396631646638363461316334656131666161653538383366663434 411 | 39383938323131646561663438386461613138636539656331663038663264636562393266346438 412 | 65383432646137636333306534636334383866303361626163616564333163663430663736333738 413 | 31313533356239303466366130663033653234613861383363333931326536343338336332346538 414 | 30636662393335616535653661376563643332303861643663393836663433646161613366313634 415 | 34306537613333303864663461643362353838316637613435393265333937313331346631656366 416 | 33323739656463326639343164633538646366386438303663393034353234333031343635313166 417 | 36363564356530633464646462376166313266343636633130623531306266396231633961636338 418 | 66393662373938643335326130373561653138666336626636393866386238613037643939346161 419 | 63373633623330363633316435616334373461643330343566383262373832363536303539346565 420 | 38623232653065653633383939326663616134613666623336346366306663383062383738613930 421 | 63666263373930666535396664376535343231636231383766656631353161343038323361653362 422 | 36333532613961363936353665393632396561343263373761626232303131393336386435316532 423 | 37373066376664356661386136303537393666346563346132633832383836643863633939663165 424 | 61633534656630633937356564323032666266653061353336386238633137343263663230303736 425 | 65663262303363333233333763383361663736383233363731653361666437633964333539373931 426 | 39326534373935363165663066323165356266616462356333643764623036666137333464366334 427 | 37616433313261306364306430666238646262646533396561383930393663316139326430616566 428 | 66323738643865323435326432646535643637313962343632363666333733623961613534643266 429 | 38343639303937363362636632633735316661393230626435323830653364633964383533386462 430 | 38656337653339303930303561633463363532393963356632313165376233313766633562653963 431 | 32363233616661386562333138326463343630653032626466656136346332303838376631323935 432 | 63363338333030333562306134363237356262393339666664636139643137363037626337303063 433 | 31376163623636323039643431333530383030643039653436393431313133313134653863656138 434 | 34363564656534306337303933303130356534306463346663323566626661653430633064306136 435 | 32373066376635626133393736393835323735653335363736303137356236396464613534333433 436 | 63646336323034323335336134373661613033373135356362663531646662363735356433336261 437 | 63353535623837336132383263623038373437633261353832363631313131623439656431306438 438 | 36613038303637303734363132313936366362336239653335626634376630333833326462343432 439 | 34626533313763623331663966326231323134666137386563373563346133346262353930663333 440 | 35643533383038323766313434306135663662313364373337376138616534303832653962336536 441 | 34656562653135623666316462323635633962313931306635623566626235643563656165336530 442 | 39323565343032326563653737316463623735303836643231633561333133643933313337633264 443 | 38653963383562623761616439363065303861303662336130303332613132323862323964383136 444 | 31626333323434663630373330393630333237336561656362666530356631623432613537353031 445 | 39326136363266323164313164383763636439663464353034646265343437623663643036633538 446 | 32356632373264383164383137343564363435616161346436353532636563616135383833383431 447 | 30383166346533376339623033306332663562316437653766643965623637326234373562316161 448 | 66393061356163376563626230333462356133373661363666363039383966393736623236643032 449 | 65626335393539376232336433643363316263666462396261346666393439353465656364383263 450 | 31373138636333666431306437323361316431613139316537356666613835333139373434333666 451 | 31663338326333616466636632373937393036323365363637323162646135343439316363343134 452 | 31656435353835306565313832646237643633306135643463643135333964323664353534623031 453 | 31396566376138613563373037366231303265393937356565643734623139666361646565343661 454 | 65383137353261363134613232393165613566326533666134623837386233316366393764353466 455 | 36343733353865303331396165303134616632313332616438306265386433343631393964393133 456 | 61653538653066353036643039396634373164613230636661663836366631316362636362386138 457 | 30363035323931366230656537343831363065646437323736376333623637323265313464343935 458 | 36653365383830376432646630633138383464323737323936643935306161316464386530663666 459 | 39356331323034626234386331343237353964383336656233316364623861663538633431326163 460 | 31356437303863633465333166393836366563343962303638656430616366666534336234616161 461 | 63613235333238373930316262316630633265363633316332316266353634306262356263633731 462 | 39633132396638623238613461343936346362343562326664326630373330323861376537663633 463 | 61313462623135613263646364383037366161353936663331653665626530346338633438316132 464 | 36336261646530376238613338363334656431393234643633633466343833353364346664383034 465 | 64636664336439373531353130626539636636343133373136363265393761356430663464343237 466 | 62666566643365656465313437316538306331663535663935636239623166376238303431633230 467 | 30386339306137306261366164333534303637373533626338336232643332653631633935336265 468 | 35663034633331323066663062653863663136346437623133626665653139386262366136663565 469 | 37353066313432646233333538643262396230323430336164356337646266326462663439663031 470 | 63313232616433616132323839343164326562666635393365373232343137623264383166653761 471 | 37323134346364303961656533363766303734373136313634353737623234323164393937613365 472 | 38613666633861633939653630633335626663326462323939643937383066663766613262323666 473 | 30336263623835663064626634633765633465363834663731393332323963633839356131663866 474 | 66326662303130313535313630363937633166393939666133623666346533613232333466343064 475 | 32623863356634643363616437393266666566653162363236616231303831353163396364383932 476 | 61323536386261616264353761386362316661303962336333623835656131363439383562313665 477 | 62643934366465613063633966616134326633333932353637386233313364666336313739616635 478 | 38323336306264396635323135333833353266333165633630383265356639636237623630303735 479 | 61363464616531316236373735376638613731653066616134636362366366373435353132336238 480 | 63333938663761356262663030306132383433633638316533626331303532343132326262363032 481 | 62333331326435616237643462643161303966303437353164323138316563353834316336323734 482 | 32346339343430623934646635353165313466653431653136646137626133326538376233366639 483 | 30333866306462653337333362666636333864323263663733376135363635373365346334663163 484 | 38653262623439623335326333363064666161633532613433656431313431333934313434396332 485 | 64383838623935376264656134343166653462303830386630363732376530363332656639396238 486 | 39353238623530333338663735633231643837643438333564363065383134333331376332613765 487 | 39373162336437626339313563393039393662663637663939323063373864373638363031613564 488 | 66366231346262336636306661316465366135383538336333396332363834313437323337393439 489 | 31376139663363306631353965373735646539353463623164613365316633373864343836383538 490 | 38323237616337376262613437663563653966313937653535663662303235646637366235386465 491 | 31363764646235373930366463653861383635366131353035336666363637656130333130306665 492 | 31323232626535666232643537373765336166623263626436303434333135383536623634353961 493 | 35346636346536313636366464633266633965643731313665363031366537343064623561653835 494 | 31306235366565386438373561373962316566666336646666336231346238656162333963326230 495 | 65373861396362663730373338346133363932333837653836366163633036356330376332363631 496 | 38396635616632323632643266646664643733393838363465333032646566623534313639313439 497 | 39313739373436356633663662353133316236663733626535633538633931396535643636613139 498 | 31396662303439653030323932636339343861323237663864616136323639613163383739383734 499 | 32396230356632613461306536363763316362633336323665396434376563663762646265306136 500 | 64643638633139653739333362636630636139333861623535623730323230386539336332663662 501 | 62643762663738613037363736383765653437663233623561386462626362373664636132383739 502 | 65346563646163663166343363393539646661643763333430353438373338343662313739383766 503 | 31373639333934303834643538326430323764333039383232643861323861626634653234666261 504 | 33366663303837333830333262343463376564393933653836383661393933346438363532393364 505 | 38303632346333313065393165373834396461313036643833363962623464643036313330633263 506 | 31376163323066633438383732373363616263383439353235653264393764643531383666303765 507 | 35643261636335636434326263363663626231333063373532643963663464306436316364653466 508 | 37366666666661376237363032383664333233643033333061323133633864343234333566633031 509 | 36326633303433623863393037353265663765323564616330643435613064626366316564636630 510 | 32383163373933313661376464376533356235333537303563653063313439356566346662613565 511 | 30383461373135353264666465383931383230383930613062303938313531653035633266666362 512 | 33386135393534396261633630303230313830623664633061313034313538343333393432626137 513 | 33383532653063616235373265663630653563653164386138343161373961323633393234346538 514 | 37613865633064623530306466303265623030333633363236356334386332346661316432326463 515 | 34326363396235663035343535373932343061656463613239376439623065376639643262393033 516 | 65626435393537346432393534636434626233613935303039623133393134646138396462326539 517 | 35356431613236343337613930343964316133633539326665306535623835326338613662373764 518 | 39316538343865373333316361643536613462316438306235366565303731306432346363343837 519 | 36306537373562633761353732313861616637643938363837623431313464636437656633343535 520 | 65623261613764393131613230373433306539663635386465303564373133626665663961616132 521 | 62393438303636623032666161333935653530363762336537373732353139336131343438346638 522 | 30653266313163336232623462613263636262386138396562306639353365663138386164653266 523 | 61313032663534303838363034623939326539653563383238616361366631333837623139396566 524 | 62616163383263633666643062353138303331623765306639393437373962613264656165653131 525 | 34316230323161333032313030363161373763623936663535613666663765623532636235343265 526 | 37653764653738373331343462633631616435303561366538663464306465666638326333336566 527 | 38656336633730323665633431396232653131393030353130366561383336633038653231323937 528 | 33626132653561393764313539613035326238313936663165383364316534386666646564643639 529 | 33396238633361616337303630656533336530333831363066343231326636663266393532336366 530 | 35313431323733373464323436363162383433653162616664323639353837373531636165656534 531 | 65346533663766373163363734383738323166386134643665336163366637666363656238396264 532 | 32363234653036373438363536623464646164326163383166356136636239623163336432363863 533 | 34346233363361643862323131656234303938343437386362393233356566323532333263366130 534 | 33376335303635343163323863636261373435316232633939383534613964663064333832626133 535 | 64306431343139613736366638376438623433323663343939383836313834636361313265653362 536 | 35643363663131666138303433346536663464326436303730613133333265383330356561666364 537 | 63616438616132646238303835653762363066643663616635303466646539643535623134313464 538 | 62653661333638653462363166333332316364633961626665366439306536373162316237383036 539 | 38326234333466393239363565336135383564343463323339623066623238346636643034343961 540 | 64626233363662356133636337356435326562393737303431313830646333323236313533663431 541 | 37333431656236346239333931313364363530366138356266346238346235636338626266306635 542 | 64656338313034346635613032663361613833633832353434303061366539316464623538376437 543 | 39356336356466343035366666623661653434356232313361306239383738313363363830386464 544 | 37316432353762356335306664323766323432396264663937323834373032306236633062323761 545 | 64386236363733323330336435663035663431623161383539313531353662376266323233366434 546 | 31643330643633616466303366333039373736373536316232356332643336306433343532636233 547 | 64656635393738386463613739303365393434376531366264643531613063633265666435366633 548 | 65323339653031623066613431626431653563326665313038376434343466356531613766613261 549 | 33616331363732653763333365653064333534343239666636343034623238306265623237383535 550 | 63323237656635386164633434623665623232636233343562643732393962366332623966636163 551 | 63333565316137303966653935323463386435316438616336323061643030363538626262326439 552 | 38313065343438633832313364353866333361633932383462373333363636656339656436343938 553 | 64333764333661333134353234643130343966326562636236363161646666303738663263393163 554 | 62353639613739373430326437386561393765303639613239643639633265666266636461663938 555 | 66376263643066383032616638623933623261613164643264366631366466373865616434396665 556 | 38326263663161623935303961653736663362396232373263336435386437333234393162326436 557 | 39666132336262653465396636626661633738353761633937613030633737373765333332643963 558 | 64303336636334643931643338323235366431333132386235616635646564653237376237366331 559 | 61613936303865363864643233393331313938653262663838613539323239666539386161316430 560 | 61366564623439376164396163356465316638633462383130643763303937663562393739333835 561 | 36383132366537383731663361343963613330616662346339613438353033623237383762383030 562 | 64326331336663623564653064623335626566343564336430613864343236353762336236616234 563 | 33633932303539306465373539323061656465633535313337323934643034653266323766393036 564 | 64303734383566363430663036306232346537313165616636343231373364613137356133636461 565 | 31306565363437653533306530623965363962656363326633613433656636666635396339363433 566 | 61306264363039353034643563646663356566653564313861656664326564623933663435313830 567 | 65346564643266313966333634393064646634356339643464363631333430653034633563343035 568 | 62336638376365653364633336383731666131383063666262313438366232356363383337656665 569 | 39363230383762333136383830356537306237323037386438313861393737613836366230343137 570 | 64363133393661626564356432346161383233636133623730323638663030613564633962323065 571 | 34303137343637663432623261376131643264363061376430343835373335623265653136313863 572 | 62333861353365656634653234336166333936363164636235366262643933623564333435343165 573 | 32396565633766323665313134306238383432313764643865316338313639656665336463666336 574 | 37303037663531643734313033323339316564616566353730643739323136323463363632313737 575 | 66646136323539353437663938303364383532333332383535663638363434633836393132313361 576 | 64383165613765643164656365343431653066383261323830363339386162613564626136623139 577 | 35386536336130366435393138306131313531313561336333363166363838303366303061666431 578 | 66343135316638316331353933383439346364626162656137303739663037653163376437663062 579 | 31313961663035313738303533323930613061633435623333646563383031303133396133363136 580 | 30663465653337643565316230666662663963323039666235643930636639323837393439616132 581 | 30306333396636633566646336643561386464636662333535393062356664306533613136346366 582 | 64376666373262616365356331656263636338656631383637373830323661623337356130656631 583 | 37343235366532393063653263303266326437346231356536393164626535393063366637643339 584 | 64636262646162666431653931646135306338366165646465356631613638363037666636616165 585 | 37616332356330656461313535613633373237363433666332333263613033633861373163666238 586 | 64303763326231303265343266336534613434346565636136366561373830393163306465376237 587 | 35633363336533383031323463333239666331366365636535303132326564323764396561653435 588 | 37353962363864373033666136333436383736666235326237623463346461626363626561316333 589 | 31643062363466303135633834343630303737303263623032333639323636633665616264646166 590 | 38353936616462376633633662353562396266366563316335663664373734353335653331316536 591 | 30663562653461646235303964323930323338666534636566633166623664656638616633316136 592 | 61306632386265616235663737653337666530356139333932303263336163613462336535663131 593 | 39353764383334356635623633366466343761363264313465316330626432393636636566363562 594 | 36636562303766353836323439626533386339373138663531346338663563363735656439336433 595 | 31363662643232346234616162383566653832306130316536366634333363303232393463653832 596 | 38383639643031393238613962366532346435353164316237386435396338306562383737356263 597 | 32636631376261383238316264333533626565633166316533643238393935373434343663663438 598 | 65303332646136333238346139383239663264373532386337363431323337343931633038343963 599 | 65313537613734356564623639313839636337366236306438366666393163326339393039333434 600 | 63383231386665386532336166373761383036353863653637313365323065393436613165323730 601 | 39343730626332663861343265386562613266303738366238376564383966373564326534616538 602 | 39626564346661346163656237353635303730393336353162356635383066643534333536626131 603 | 37336563643934653139356332626661623565643933353035663133313663313530396439626430 604 | 37343232643839356535633232343437356165376138383766353932626334366137323833326166 605 | 34373734383466316564623961613666333830346161353030303530316432316433336535343336 606 | 39643133303565303032333133623462376165643139313862383437643239373837663135616164 607 | 34636436306562643062316136303136333761356634636435636638316665666563396634303032 608 | 33373237393938353463396234633762613734326262373939346164643664373864373834363631 609 | 36316436323135646166376432303331383035383665613566306333366262393365613164383835 610 | 31623435656530643431346163623339343063363463633833373933333038626635393461336562 611 | 66306364323436623838363765633738373335323065356666323532306462626362373737386563 612 | 62346266656334646664613438626236336236653364376164396164636231623132663763636661 613 | 62346137373432656631363064313361386364663735323131626634366262333561636231313938 614 | 65323163626261666230633339666533663365373235383432663434316233663430366633353165 615 | 31353130613238303365633161653038613861303266363238656334376464646566613265636462 616 | 32626338323439633330343138646135383039376433373637626362656262313961626331356664 617 | 66643532306662313664666233663336323031646438336661616231333061316631613630653438 618 | 62663331626239343235643661663337363435363335633932336538376438376237383932386336 619 | 30616237313561656533646165386163393737313235336164396366313562343365613636653266 620 | 34396565646666316433626163626330346631633338626461343232393537626561363163336437 621 | 63663135656435376332393330613062306531336638616536376662356361323038633061353336 622 | 63656433663966366435313835336131623838336165306339333230383931623066313863616462 623 | 61316333646432353862393337383233386237316265333764313835376564613663363837323662 624 | 33396466343264336430636433346637396637353461633866323137616231316163373366333733 625 | 62316137383738643131366564633739326631336134333761623033313464386338303035636662 626 | 64326231646631396363626434633563346139653738316166613661643531613334323364313862 627 | 35393739663532383732306465653039626135333365393539323236303566393932626437386530 628 | 39373663363865323731336633306636646635396531356334346131666264366666393364363861 629 | 33383336666361623438303162353663363232303235366166366430323864343739643931653263 630 | 62353362656235343862336532373437316464306438366265323937633363313639326134626361 631 | 39666331313137663938616666623562303530343564653732666235396533343564313861646639 632 | 63643139376631343064306564353961333863376130383731376166373232356465643739383363 633 | 65666464636139306461623066303334396162396639346230633566353032393363383661343538 634 | 33343935353064646361656134636535653933646532363061373333373636363035666630393164 635 | 61326133663732353264303861326432316233616533353062383837393866303665323764633535 636 | 36376361616366653166613661663130336437316432303966376161343038343339323437376265 637 | 64393234613537313637386663636336386563363064376434653939663464616134373863396130 638 | 64643538393133626531303032316336353833633838653534656564303932326261313039666532 639 | 65363962353861646361336533643631636563306464303261626330616136643436656537386639 640 | 61363165616263323663326338616565306534643763626632323631306465643365386139323436 641 | 30383138303634653961326231353331623037306432653765346366343861373966666162333234 642 | 323564363630653336366361343038643463 643 | 644 | ... 645 | -------------------------------------------------------------------------------- /ansible/temp/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/ansible/temp/.keep -------------------------------------------------------------------------------- /ansible/templates/files/workshop-argo-cluster-cr.yaml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: ArgoCD 4 | metadata: 5 | name: workshop-argocd 6 | spec: 7 | # Image to use for all ArgoCD server components: server, application-controller, repo-server 8 | # by default this is 'argoproj/argocd:latest' 9 | image: {{ internal_registry }}/{{ server_image_name }}:{{ server_image_version }} 10 | 11 | grafana: 12 | enabled: false 13 | prometheus: 14 | enabled: false 15 | dex: 16 | image: {{ internal_registry }}/{{ dex_image_name }} 17 | version: {{ dex_image_version }} 18 | redis: 19 | image: {{ internal_registry }}/{{ redis_image_name }} 20 | version: {{ redis_image_version }} 21 | server: 22 | route: 23 | enabled: true 24 | rbac: 25 | defaultPolicy: 'role:readonly' 26 | policy: | 27 | g, system:cluster-admins, role:admin 28 | ... 29 | -------------------------------------------------------------------------------- /ansible/templates/files/workshop-sample-app-cr.yaml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: Application 4 | metadata: 5 | name: {{ participant }}-sample-app 6 | namespace: argocd 7 | spec: 8 | project: workshop 9 | source: 10 | repoURL: https://github.com/darthlukan/gitops-workshop.git 11 | targetRevision: {{ participant }} 12 | path: {{ participant }}-sample-app-config 13 | destination: 14 | # Need to get this automagically via detection 15 | server: https://kubernetes.default.svc 16 | namespace: {{ participant }}-sample-app 17 | finalizers: 18 | - resources-finalizer.argocd.argoproj.io 19 | syncPolicy: 20 | automated: 21 | selfHeal: true 22 | prune: true 23 | ... 24 | -------------------------------------------------------------------------------- /ansible/templates/sample-app-ci/10-buildah-task.yaml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: tekton.dev/v1beta1 3 | kind: Task 4 | metadata: 5 | name: buildah 6 | labels: 7 | app.kubernetes.io/version: "0.1" 8 | annotations: 9 | tekton.dev/pipelines.minVersion: "0.12.1" 10 | tekton.dev/tags: image-build 11 | spec: 12 | description: >- 13 | Buildah task builds source into a container image and 14 | then pushes it to a container registry. 15 | 16 | Buildah Task builds source into a container image using Project Atomic's 17 | Buildah build tool.It uses Buildah's support for building from Dockerfiles, 18 | using its buildah bud command.This command executes the directives in the 19 | Dockerfile to assemble a container image, then pushes that image to a 20 | container registry. 21 | 22 | params: 23 | - name: IMAGE 24 | description: Reference of the image buildah will produce. 25 | - name: BUILDER_IMAGE 26 | description: The location of the buildah builder image. 27 | default: "{{ buildah_image }}" 28 | - name: STORAGE_DRIVER 29 | description: Set buildah storage driver 30 | default: overlay 31 | - name: DOCKERFILE 32 | description: Path to the Dockerfile to build. 33 | default: ./Dockerfile 34 | - name: CONTEXT 35 | description: Path to the directory to use as context. 36 | default: . 37 | - name: TLSVERIFY 38 | description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry) 39 | default: "true" 40 | - name: FORMAT 41 | description: The format of the built container, oci or docker 42 | default: "oci" 43 | - name: BUILD_EXTRA_ARGS 44 | description: Extra parameters passed for the build command when building images. 45 | default: "" 46 | - name: PUSH_EXTRA_ARGS 47 | description: Extra parameters passed for the push command when pushing images. 48 | type: string 49 | default: "" 50 | workspaces: 51 | - name: source 52 | 53 | results: 54 | - name: IMAGE_DIGEST 55 | description: Digest of the image just built. 56 | 57 | steps: 58 | - name: build 59 | image: $(params.BUILDER_IMAGE) 60 | workingDir: $(workspaces.source.path) 61 | script: | 62 | buildah --storage-driver=$(params.STORAGE_DRIVER) bud \ 63 | $(params.BUILD_EXTRA_ARGS) --format=$(params.FORMAT) \ 64 | --tls-verify=$(params.TLSVERIFY) --no-cache \ 65 | -f $(params.DOCKERFILE) -t $(params.IMAGE) $(params.CONTEXT) 66 | volumeMounts: 67 | - name: varlibcontainers 68 | mountPath: /var/lib/containers 69 | securityContext: 70 | privileged: true 71 | 72 | - name: push 73 | image: $(params.BUILDER_IMAGE) 74 | workingDir: $(workspaces.source.path) 75 | script: | 76 | buildah --storage-driver=$(params.STORAGE_DRIVER) push \ 77 | $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \ 78 | --digestfile $(workspaces.source.path)/image-digest $(params.IMAGE) \ 79 | docker://$(params.IMAGE) 80 | volumeMounts: 81 | - name: varlibcontainers 82 | mountPath: /var/lib/containers 83 | securityContext: 84 | privileged: true 85 | 86 | - name: digest-to-results 87 | image: $(params.BUILDER_IMAGE) 88 | script: cat $(workspaces.source.path)/image-digest | tee /tekton/results/IMAGE_DIGEST 89 | 90 | volumes: 91 | - name: varlibcontainers 92 | emptyDir: {} 93 | -------------------------------------------------------------------------------- /ansible/templates/sample-app-ci/10-git-cli-task.yaml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: tekton.dev/v1beta1 3 | kind: Task 4 | metadata: 5 | name: git-cli 6 | labels: 7 | app.kubernetes.io/version: "0.1" 8 | annotations: 9 | tekton.dev/pipelines.minVersion: "0.12.1" 10 | tekton.dev/tags: git 11 | tekton.dev/displayName: "git cli" 12 | spec: 13 | description: >- 14 | This task can be used to perform git operations. 15 | 16 | Git command that needs to be run can be passed as a script to 17 | the task.This task needs authentication to git in order to push 18 | after the git operation. 19 | 20 | workspaces: 21 | - name: source 22 | description: A workspace that contains the fetched git repository. 23 | - name: input 24 | description: A workspace that contains file that needs to be added to git. 25 | params: 26 | - name: BASE_IMAGE 27 | description: | 28 | The base image for the task. 29 | type: string 30 | default: "{{ git_cli_image }}" 31 | 32 | - name: GIT_USER_NAME 33 | type: string 34 | description: | 35 | Git user name for performing git operation. 36 | default: "" 37 | 38 | - name: GIT_USER_EMAIL 39 | type: string 40 | description: | 41 | Git user email for performing git operation. 42 | default: "" 43 | 44 | - name: GIT_SCRIPT 45 | description: The git script to run. 46 | type: string 47 | default: | 48 | git help 49 | 50 | results: 51 | - name: commit 52 | description: The precise commit SHA after the git operation. 53 | 54 | steps: 55 | - name: git 56 | image: $(params.BASE_IMAGE) 57 | workingDir: $(workspaces.source.path) 58 | script: | 59 | 60 | # Setting up the config for the git. 61 | git config --global user.email "$(params.GIT_USER_EMAIL)" 62 | git config --global user.name "$(params.GIT_USER_NAME)" 63 | 64 | $(params.GIT_SCRIPT) 65 | 66 | RESULT_SHA="$(git rev-parse HEAD | tr -d '\n')" 67 | EXIT_CODE="$?" 68 | if [ "$EXIT_CODE" != 0 ] 69 | then 70 | exit $EXIT_CODE 71 | fi 72 | # Make sure we don't add a trailing newline to the result! 73 | echo -n "$RESULT_SHA" > $(results.commit.path) 74 | -------------------------------------------------------------------------------- /ansible/templates/sample-app-ci/10-git-clone-task.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: git-clone 5 | labels: 6 | app.kubernetes.io/version: "0.1" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: git 10 | tekton.dev/displayName: "git clone" 11 | spec: 12 | description: >- 13 | These Tasks are Git tasks to work with repositories used by other tasks 14 | in your Pipeline. 15 | 16 | The git-clone Task will clone a repo from the provided url into the 17 | output Workspace. By default the repo will be cloned into the root of 18 | your Workspace. You can clone into a subdirectory by setting this Task's 19 | subdirectory param. 20 | 21 | workspaces: 22 | - name: output 23 | description: The git repo will be cloned onto the volume backing this workspace 24 | params: 25 | - name: url 26 | description: git url to clone 27 | type: string 28 | - name: revision 29 | description: git revision to checkout (branch, tag, sha, ref…) 30 | type: string 31 | default: master 32 | - name: refspec 33 | description: (optional) git refspec to fetch before checking out revision 34 | default: "" 35 | - name: submodules 36 | description: defines if the resource should initialize and fetch the submodules 37 | type: string 38 | default: "true" 39 | - name: depth 40 | description: performs a shallow clone where only the most recent commit(s) will be fetched 41 | type: string 42 | default: "1" 43 | - name: sslVerify 44 | description: defines if http.sslVerify should be set to true or false in the global git config 45 | type: string 46 | default: "true" 47 | - name: subdirectory 48 | description: subdirectory inside the "output" workspace to clone the git repo into 49 | type: string 50 | default: "" 51 | - name: deleteExisting 52 | description: clean out the contents of the repo's destination directory (if it already exists) before trying to clone the repo there 53 | type: string 54 | default: "false" 55 | - name: httpProxy 56 | description: git HTTP proxy server for non-SSL requests 57 | type: string 58 | default: "" 59 | - name: httpsProxy 60 | description: git HTTPS proxy server for SSL requests 61 | type: string 62 | default: "" 63 | - name: noProxy 64 | description: git no proxy - opt out of proxying HTTP/HTTPS requests 65 | type: string 66 | default: "" 67 | results: 68 | - name: commit 69 | description: The precise commit SHA that was fetched by this Task 70 | steps: 71 | - name: clone 72 | image: {{ git_clone_image }} 73 | script: | 74 | CHECKOUT_DIR="$(workspaces.output.path)/$(params.subdirectory)" 75 | 76 | cleandir() { 77 | # Delete any existing contents of the repo directory if it exists. 78 | # 79 | # We don't just "rm -rf $CHECKOUT_DIR" because $CHECKOUT_DIR might be "/" 80 | # or the root of a mounted volume. 81 | if [[ -d "$CHECKOUT_DIR" ]] ; then 82 | # Delete non-hidden files and directories 83 | rm -rf "$CHECKOUT_DIR"/* 84 | # Delete files and directories starting with . but excluding .. 85 | rm -rf "$CHECKOUT_DIR"/.[!.]* 86 | # Delete files and directories starting with .. plus any other character 87 | rm -rf "$CHECKOUT_DIR"/..?* 88 | fi 89 | } 90 | 91 | if [[ "$(params.deleteExisting)" == "true" ]] ; then 92 | cleandir 93 | fi 94 | 95 | test -z "$(params.httpProxy)" || export HTTP_PROXY=$(params.httpProxy) 96 | test -z "$(params.httpsProxy)" || export HTTPS_PROXY=$(params.httpsProxy) 97 | test -z "$(params.noProxy)" || export NO_PROXY=$(params.noProxy) 98 | 99 | /ko-app/git-init \ 100 | -url "$(params.url)" \ 101 | -revision "$(params.revision)" \ 102 | -refspec "$(params.refspec)" \ 103 | -path "$CHECKOUT_DIR" \ 104 | -sslVerify="$(params.sslVerify)" \ 105 | -submodules="$(params.submodules)" \ 106 | -depth "$(params.depth)" 107 | cd "$CHECKOUT_DIR" 108 | RESULT_SHA="$(git rev-parse HEAD | tr -d '\n')" 109 | EXIT_CODE="$?" 110 | if [ "$EXIT_CODE" != 0 ] 111 | then 112 | exit $EXIT_CODE 113 | fi 114 | # Make sure we don't add a trailing newline to the result! 115 | echo -n "$RESULT_SHA" > $(results.commit.path) 116 | -------------------------------------------------------------------------------- /ansible/templates/sample-app-ci/10-make-sample-app-task.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: make-sample-app-task 5 | spec: 6 | params: 7 | - name: app-path 8 | description: Path to sample-app 9 | workspaces: 10 | - name: src 11 | steps: 12 | - name: make-build 13 | image: "{{ go_image }}" 14 | workingDir: $(workspaces.src.path)/$(params.app-path) 15 | command: ["/usr/bin/make"] 16 | args: 17 | - "build" 18 | -------------------------------------------------------------------------------- /ansible/templates/sample-app-ci/10-version-increment-task.yaml.j2: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: version-increment-task 5 | spec: 6 | params: 7 | - name: image-name 8 | - name: image-version 9 | - name: app-config-path 10 | - name: app-config-filename 11 | workspaces: 12 | - name: src 13 | steps: 14 | - name: increment-version 15 | image: "{{ go_image }}" 16 | workingDir: $(workspaces.src.path)/$(params.app-config-path) 17 | command: ["/usr/bin/sed"] 18 | args: 19 | - "-i" 20 | - 's@image:.*@image: "$(params.image-name):$(params.image-version)"@' 21 | - "$(params.app-config-filename)" 22 | 23 | -------------------------------------------------------------------------------- /ansible/templates/sample-app-config/VERSION: -------------------------------------------------------------------------------- 1 | 0.0.1 -------------------------------------------------------------------------------- /ansible/templates/sample-app-config/sample-app-deployment.yaml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ participant }}-sample-app 6 | namespace: {{ participant }}-sample-app 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: {{ participant }}-sample-app 12 | template: 13 | metadata: 14 | labels: 15 | app: {{ participant }}-sample-app 16 | spec: 17 | containers: 18 | - name: {{ participant }}-sample-app 19 | image: "quay.io/btomlins/greet:v0.0.1" 20 | command: 21 | - '/usr/bin/greet' 22 | args: 23 | - 'Hello participant\!' 24 | ... 25 | -------------------------------------------------------------------------------- /ansible/templates/sample-app-config/sample-app-namespace.yaml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: {{ participant }}-sample-app 6 | ... 7 | -------------------------------------------------------------------------------- /ansible/templates/sample-app-config/sample-app-networkpolicy.yaml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | kind: NetworkPolicy 3 | apiVersion: networking.k8s.io/v1 4 | metadata: 5 | name: allow-ci-to-namespace 6 | namespace: {{ participant }}-sample-app 7 | spec: 8 | podSelector: {} 9 | ingress: 10 | - from: 11 | - namespaceSelector: 12 | matchLabels: 13 | app.kubernetes.io/instance: {{ participant }}-sample-app-ci 14 | podSelector: {} 15 | ... 16 | -------------------------------------------------------------------------------- /code-ready-workspace.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: 1.0.0 3 | metadata: 4 | name: gitops-workshop 5 | projects: 6 | - name: gitops-workshop 7 | source: 8 | type: git 9 | location: "https://github.com/darthlukan/gitops-workshop.git" 10 | components: 11 | - type: dockerimage 12 | image: "quay.io/btomlins/gitops-workshop:latest" 13 | alias: workshop-env 14 | memoryLimit: 512Mi 15 | mountSources: true 16 | command: ['sleep', 'infinity'] 17 | env: 18 | - name: HOME 19 | value: /projects 20 | ... 21 | -------------------------------------------------------------------------------- /docs/images/01 - ArgoCD Route.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/01 - ArgoCD Route.png -------------------------------------------------------------------------------- /docs/images/02 - ArgoCD Login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/02 - ArgoCD Login.png -------------------------------------------------------------------------------- /docs/images/03 - ArgoCD Console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/03 - ArgoCD Console.png -------------------------------------------------------------------------------- /docs/images/04 - CI Pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/04 - CI Pipeline.png -------------------------------------------------------------------------------- /docs/images/05 - Sample App Update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/05 - Sample App Update.png -------------------------------------------------------------------------------- /docs/images/06 - Updated Deployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/06 - Updated Deployment.png -------------------------------------------------------------------------------- /docs/images/07 - Updated Pod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/07 - Updated Pod.png -------------------------------------------------------------------------------- /docs/images/08 - SYNC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/08 - SYNC.png -------------------------------------------------------------------------------- /docs/images/09 - New PipelineRun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/09 - New PipelineRun.png -------------------------------------------------------------------------------- /docs/images/10 - PipelineRun Complete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/10 - PipelineRun Complete.png -------------------------------------------------------------------------------- /docs/images/11 - Manual PipelineRun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/11 - Manual PipelineRun.png -------------------------------------------------------------------------------- /docs/images/Big Picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/docs/images/Big Picture.png -------------------------------------------------------------------------------- /sample-app-ci/01-sample-app-ci-namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: sample-app-ci -------------------------------------------------------------------------------- /sample-app-ci/02-sample-app-pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: git-clone-output 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce 8 | resources: 9 | requests: 10 | storage: 1Gi 11 | -------------------------------------------------------------------------------- /sample-app-ci/10-buildah-task.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: tekton.dev/v1beta1 3 | kind: Task 4 | metadata: 5 | name: buildah 6 | labels: 7 | app.kubernetes.io/version: "0.1" 8 | annotations: 9 | tekton.dev/pipelines.minVersion: "0.12.1" 10 | tekton.dev/tags: image-build 11 | spec: 12 | description: >- 13 | Buildah task builds source into a container image and 14 | then pushes it to a container registry. 15 | 16 | Buildah Task builds source into a container image using Project Atomic's 17 | Buildah build tool.It uses Buildah's support for building from Dockerfiles, 18 | using its buildah bud command.This command executes the directives in the 19 | Dockerfile to assemble a container image, then pushes that image to a 20 | container registry. 21 | 22 | params: 23 | - name: IMAGE 24 | description: Reference of the image buildah will produce. 25 | - name: BUILDER_IMAGE 26 | description: The location of the buildah builder image. 27 | default: quay.io/buildah/stable:v1.14.8 28 | - name: STORAGE_DRIVER 29 | description: Set buildah storage driver 30 | default: overlay 31 | - name: DOCKERFILE 32 | description: Path to the Dockerfile to build. 33 | default: ./Dockerfile 34 | - name: CONTEXT 35 | description: Path to the directory to use as context. 36 | default: . 37 | - name: TLSVERIFY 38 | description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry) 39 | default: "true" 40 | - name: FORMAT 41 | description: The format of the built container, oci or docker 42 | default: "oci" 43 | - name: BUILD_EXTRA_ARGS 44 | description: Extra parameters passed for the build command when building images. 45 | default: "" 46 | - name: PUSH_EXTRA_ARGS 47 | description: Extra parameters passed for the push command when pushing images. 48 | type: string 49 | default: "" 50 | workspaces: 51 | - name: source 52 | 53 | results: 54 | - name: IMAGE_DIGEST 55 | description: Digest of the image just built. 56 | 57 | steps: 58 | - name: build 59 | image: $(params.BUILDER_IMAGE) 60 | workingDir: $(workspaces.source.path) 61 | script: | 62 | buildah --storage-driver=$(params.STORAGE_DRIVER) bud \ 63 | $(params.BUILD_EXTRA_ARGS) --format=$(params.FORMAT) \ 64 | --tls-verify=$(params.TLSVERIFY) --no-cache \ 65 | -f $(params.DOCKERFILE) -t $(params.IMAGE) $(params.CONTEXT) 66 | volumeMounts: 67 | - name: varlibcontainers 68 | mountPath: /var/lib/containers 69 | securityContext: 70 | privileged: true 71 | 72 | - name: push 73 | image: $(params.BUILDER_IMAGE) 74 | workingDir: $(workspaces.source.path) 75 | script: | 76 | buildah --storage-driver=$(params.STORAGE_DRIVER) push \ 77 | $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \ 78 | --digestfile $(workspaces.source.path)/image-digest $(params.IMAGE) \ 79 | docker://$(params.IMAGE) 80 | volumeMounts: 81 | - name: varlibcontainers 82 | mountPath: /var/lib/containers 83 | securityContext: 84 | privileged: true 85 | 86 | - name: digest-to-results 87 | image: $(params.BUILDER_IMAGE) 88 | script: cat $(workspaces.source.path)/image-digest | tee /tekton/results/IMAGE_DIGEST 89 | 90 | volumes: 91 | - name: varlibcontainers 92 | emptyDir: {} 93 | -------------------------------------------------------------------------------- /sample-app-ci/10-git-cli-task.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: tekton.dev/v1beta1 3 | kind: Task 4 | metadata: 5 | name: git-cli 6 | labels: 7 | app.kubernetes.io/version: "0.1" 8 | annotations: 9 | tekton.dev/pipelines.minVersion: "0.12.1" 10 | tekton.dev/tags: git 11 | tekton.dev/displayName: "git cli" 12 | spec: 13 | description: >- 14 | This task can be used to perform git operations. 15 | 16 | Git command that needs to be run can be passed as a script to 17 | the task.This task needs authentication to git in order to push 18 | after the git operation. 19 | 20 | workspaces: 21 | - name: source 22 | description: A workspace that contains the fetched git repository. 23 | - name: input 24 | description: A workspace that contains file that needs to be added to git. 25 | params: 26 | - name: BASE_IMAGE 27 | description: | 28 | The base image for the task. 29 | type: string 30 | default: alpine/git:latest 31 | 32 | - name: GIT_USER_NAME 33 | type: string 34 | description: | 35 | Git user name for performing git operation. 36 | default: "" 37 | 38 | - name: GIT_USER_EMAIL 39 | type: string 40 | description: | 41 | Git user email for performing git operation. 42 | default: "" 43 | 44 | - name: GIT_SCRIPT 45 | description: The git script to run. 46 | type: string 47 | default: | 48 | git help 49 | 50 | results: 51 | - name: commit 52 | description: The precise commit SHA after the git operation. 53 | 54 | steps: 55 | - name: git 56 | image: $(params.BASE_IMAGE) 57 | workingDir: $(workspaces.source.path) 58 | script: | 59 | 60 | # Setting up the config for the git. 61 | git config --global user.email "$(params.GIT_USER_EMAIL)" 62 | git config --global user.name "$(params.GIT_USER_NAME)" 63 | 64 | $(params.GIT_SCRIPT) 65 | 66 | RESULT_SHA="$(git rev-parse HEAD | tr -d '\n')" 67 | EXIT_CODE="$?" 68 | if [ "$EXIT_CODE" != 0 ] 69 | then 70 | exit $EXIT_CODE 71 | fi 72 | # Make sure we don't add a trailing newline to the result! 73 | echo -n "$RESULT_SHA" > $(results.commit.path) 74 | -------------------------------------------------------------------------------- /sample-app-ci/10-git-clone-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: git-clone 5 | labels: 6 | app.kubernetes.io/version: "0.1" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: git 10 | tekton.dev/displayName: "git clone" 11 | spec: 12 | description: >- 13 | These Tasks are Git tasks to work with repositories used by other tasks 14 | in your Pipeline. 15 | 16 | The git-clone Task will clone a repo from the provided url into the 17 | output Workspace. By default the repo will be cloned into the root of 18 | your Workspace. You can clone into a subdirectory by setting this Task's 19 | subdirectory param. 20 | 21 | workspaces: 22 | - name: output 23 | description: The git repo will be cloned onto the volume backing this workspace 24 | params: 25 | - name: url 26 | description: git url to clone 27 | type: string 28 | - name: revision 29 | description: git revision to checkout (branch, tag, sha, ref…) 30 | type: string 31 | default: master 32 | - name: refspec 33 | description: (optional) git refspec to fetch before checking out revision 34 | default: "" 35 | - name: submodules 36 | description: defines if the resource should initialize and fetch the submodules 37 | type: string 38 | default: "true" 39 | - name: depth 40 | description: performs a shallow clone where only the most recent commit(s) will be fetched 41 | type: string 42 | default: "1" 43 | - name: sslVerify 44 | description: defines if http.sslVerify should be set to true or false in the global git config 45 | type: string 46 | default: "true" 47 | - name: subdirectory 48 | description: subdirectory inside the "output" workspace to clone the git repo into 49 | type: string 50 | default: "" 51 | - name: deleteExisting 52 | description: clean out the contents of the repo's destination directory (if it already exists) before trying to clone the repo there 53 | type: string 54 | default: "false" 55 | - name: httpProxy 56 | description: git HTTP proxy server for non-SSL requests 57 | type: string 58 | default: "" 59 | - name: httpsProxy 60 | description: git HTTPS proxy server for SSL requests 61 | type: string 62 | default: "" 63 | - name: noProxy 64 | description: git no proxy - opt out of proxying HTTP/HTTPS requests 65 | type: string 66 | default: "" 67 | results: 68 | - name: commit 69 | description: The precise commit SHA that was fetched by this Task 70 | steps: 71 | - name: clone 72 | image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.14.2 73 | script: | 74 | CHECKOUT_DIR="$(workspaces.output.path)/$(params.subdirectory)" 75 | 76 | cleandir() { 77 | # Delete any existing contents of the repo directory if it exists. 78 | # 79 | # We don't just "rm -rf $CHECKOUT_DIR" because $CHECKOUT_DIR might be "/" 80 | # or the root of a mounted volume. 81 | if [[ -d "$CHECKOUT_DIR" ]] ; then 82 | # Delete non-hidden files and directories 83 | rm -rf "$CHECKOUT_DIR"/* 84 | # Delete files and directories starting with . but excluding .. 85 | rm -rf "$CHECKOUT_DIR"/.[!.]* 86 | # Delete files and directories starting with .. plus any other character 87 | rm -rf "$CHECKOUT_DIR"/..?* 88 | fi 89 | } 90 | 91 | if [[ "$(params.deleteExisting)" == "true" ]] ; then 92 | cleandir 93 | fi 94 | 95 | test -z "$(params.httpProxy)" || export HTTP_PROXY=$(params.httpProxy) 96 | test -z "$(params.httpsProxy)" || export HTTPS_PROXY=$(params.httpsProxy) 97 | test -z "$(params.noProxy)" || export NO_PROXY=$(params.noProxy) 98 | 99 | /ko-app/git-init \ 100 | -url "$(params.url)" \ 101 | -revision "$(params.revision)" \ 102 | -refspec "$(params.refspec)" \ 103 | -path "$CHECKOUT_DIR" \ 104 | -sslVerify="$(params.sslVerify)" \ 105 | -submodules="$(params.submodules)" \ 106 | -depth "$(params.depth)" 107 | cd "$CHECKOUT_DIR" 108 | RESULT_SHA="$(git rev-parse HEAD | tr -d '\n')" 109 | EXIT_CODE="$?" 110 | if [ "$EXIT_CODE" != 0 ] 111 | then 112 | exit $EXIT_CODE 113 | fi 114 | # Make sure we don't add a trailing newline to the result! 115 | echo -n "$RESULT_SHA" > $(results.commit.path) 116 | -------------------------------------------------------------------------------- /sample-app-ci/10-make-sample-app-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: make-sample-app-task 5 | spec: 6 | params: 7 | - name: app-path 8 | description: Path to sample-app 9 | workspaces: 10 | - name: src 11 | steps: 12 | - name: make-build 13 | image: registry.redhat.io/rhel8/go-toolset 14 | workingDir: $(workspaces.src.path)/$(params.app-path) 15 | command: ["/usr/bin/make"] 16 | args: 17 | - "build" 18 | -------------------------------------------------------------------------------- /sample-app-ci/10-version-increment-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: version-increment-task 5 | spec: 6 | params: 7 | - name: image-name 8 | - name: image-version 9 | - name: app-config-path 10 | - name: app-config-filename 11 | workspaces: 12 | - name: src 13 | steps: 14 | - name: increment-version 15 | image: registry.redhat.io/rhel8/go-toolset 16 | workingDir: $(workspaces.src.path)/$(params.app-config-path) 17 | command: ["/usr/bin/sed"] 18 | args: 19 | - "-i" 20 | - 's@image:.*@image: "$(params.image-name):$(params.image-version)"@' 21 | - "$(params.app-config-filename)" 22 | 23 | -------------------------------------------------------------------------------- /sample-app-ci/20-pipeline.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Pipeline 3 | metadata: 4 | name: build-increment-commit 5 | spec: 6 | params: 7 | - name: repo-url 8 | type: string 9 | - name: git-branch 10 | type: string 11 | - name: image-name 12 | type: string 13 | - name: app-path 14 | type: string 15 | - name: app-config-path 16 | type: string 17 | - name: app-config-filename 18 | type: string 19 | - name: image-version 20 | type: string 21 | workspaces: 22 | - name: gitops-workshop-repo-source 23 | tasks: 24 | - name: git-clone 25 | taskRef: 26 | name: git-clone 27 | params: 28 | - name: url 29 | value: $(params.repo-url) 30 | - name: revision 31 | value: $(params.git-branch) 32 | - name: deleteExisting 33 | value: "true" 34 | workspaces: 35 | - name: output 36 | workspace: gitops-workshop-repo-source 37 | - name: make-sample-app 38 | taskRef: 39 | name: make-sample-app-task 40 | params: 41 | - name: app-path 42 | value: $(params.app-path) 43 | runAfter: 44 | - git-clone 45 | workspaces: 46 | - name: src 47 | workspace: gitops-workshop-repo-source 48 | - name: build-image 49 | taskRef: 50 | name: buildah 51 | runAfter: 52 | - make-sample-app 53 | params: 54 | - name: IMAGE 55 | value: $(params.image-name):$(params.image-version) 56 | - name: DOCKERFILE 57 | value: $(workspaces.source.path)/$(params.app-path)/Dockerfile 58 | workspaces: 59 | - name: source 60 | workspace: gitops-workshop-repo-source 61 | - name: version-increment 62 | taskRef: 63 | name: version-increment-task 64 | runAfter: 65 | - build-image 66 | workspaces: 67 | - name: src 68 | workspace: gitops-workshop-repo-source 69 | params: 70 | - name: image-name 71 | value: $(params.image-name) 72 | - name: image-version 73 | value: $(params.image-version) 74 | - name: app-config-path 75 | value: $(params.app-config-path) 76 | - name: app-config-filename 77 | value: $(params.app-config-filename) 78 | - name: git-commit 79 | taskRef: 80 | name: git-cli 81 | params: 82 | - name: GIT_USER_NAME 83 | value: "SkylarScaling" 84 | - name: GIT_USER_EMAIL 85 | value: "skylar@redhat.com" 86 | - name: GIT_SCRIPT 87 | value: | 88 | git checkout $(params.git-branch) 89 | git status 90 | git pull 91 | git add $(params.app-config-path)/$(params.app-config-filename) 92 | git commit --allow-empty -m "Pipeline execution and version update: $(params.image-name)/$(params.image-version)" 93 | git push 94 | runAfter: 95 | - version-increment 96 | workspaces: 97 | - name: source 98 | workspace: gitops-workshop-repo-source 99 | - name: input 100 | workspace: gitops-workshop-repo-source 101 | 102 | 103 | -------------------------------------------------------------------------------- /sample-app-ci/30-pipeline-run.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: PipelineRun 3 | metadata: 4 | generateName: gitops-workshop-pipeline-run- 5 | annotations: 6 | argocd.argoproj.io/hook: Sync 7 | spec: 8 | pipelineRef: 9 | name: build-increment-commit 10 | workspaces: 11 | - name: gitops-workshop-repo-source 12 | persistentVolumeClaim: 13 | claimName: git-clone-output 14 | params: 15 | - name: repo-url 16 | value: https://github.com/darthlukan/gitops-workshop 17 | - name: git-branch 18 | value: master 19 | - name: image-name 20 | value: quay.io/sscaling/gitops-workshop 21 | - name: image-version 22 | value: v0.0.1 23 | - name: app-path 24 | value: sample-app 25 | - name: app-config-path 26 | value: sample-app-config 27 | - name: app-config-filename 28 | value: sample-app-deployment.yaml -------------------------------------------------------------------------------- /sample-app-config/sample-app-deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: sample-app 6 | namespace: sample-app 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: sample-app 12 | template: 13 | metadata: 14 | labels: 15 | app: sample-app 16 | spec: 17 | containers: 18 | - name: sample-app 19 | image: "quay.io/sscaling/gitops-workshop:v0.0.1" 20 | command: 21 | - '/usr/bin/greet' 22 | args: 23 | - 'Hello participant\!' 24 | ... 25 | -------------------------------------------------------------------------------- /sample-app-config/sample-app-namespace.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: sample-app 6 | ... 7 | -------------------------------------------------------------------------------- /sample-app-config/sample-app-networkpolicy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: NetworkPolicy 3 | apiVersion: networking.k8s.io/v1 4 | metadata: 5 | name: allow-ci-to-namespace 6 | namespace: sample-app 7 | spec: 8 | podSelector: {} 9 | ingress: 10 | - from: 11 | - namespaceSelector: 12 | matchLabels: 13 | app.kubernetes.io/instance: sample-app-ci 14 | podSelector: {} 15 | ... 16 | -------------------------------------------------------------------------------- /sample-app/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | build 3 | -------------------------------------------------------------------------------- /sample-app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.redhat.io/rhel8/go-toolset 2 | 3 | USER nobody 4 | 5 | ADD sample-app/build/greet /usr/bin/greet 6 | -------------------------------------------------------------------------------- /sample-app/Makefile: -------------------------------------------------------------------------------- 1 | BINARY := greet 2 | VERSION := v0.0.1 3 | 4 | setup: 5 | go mod init gitops-workshop/sample-app/greet 6 | 7 | build: 8 | mkdir -p build 9 | GOOS=linux GOARCH=amd64 go build -o build/$(BINARY) 10 | 11 | container: build 12 | buildah bud -f Dockerfile -t quay.io/btomlins/greet:$(VERSION) 13 | 14 | clean: 15 | rm -rf ./build 16 | -------------------------------------------------------------------------------- /sample-app/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darthlukan/gitops-workshop/35741cd28615fadb1397ca8c1606f613942a95a7/sample-app/README.md -------------------------------------------------------------------------------- /sample-app/go.mod: -------------------------------------------------------------------------------- 1 | module gitops-workshop/sample-app/greet 2 | 3 | go 1.14 4 | -------------------------------------------------------------------------------- /sample-app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | for { 11 | fmt.Printf("%v\n", os.Args[1]) 12 | time.Sleep(3 * time.Second) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /sample-infra/integration-secret-example.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: integration-auth-secret 6 | namespace: sample-infra 7 | type: Opaque 8 | data: 9 | # values are "CHANGE_ME" 10 | username: Q0hBTkdFX01FCg== 11 | password: Q0hBTkdFX01FCg== 12 | ... 13 | -------------------------------------------------------------------------------- /sample-infra/sample-infra-namespace.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: sample-infra 6 | ... 7 | --------------------------------------------------------------------------------