├── .gitignore ├── README.md ├── argo.jpg ├── v02-argocd-setting-up ├── install-using-helm-nginx-ingress │ ├── note.txt │ └── values-nginx-ingress.yml ├── install-using-helm-nodeport │ ├── note.txt │ └── values-nodePort.yml └── install-using-kubectl │ ├── install-using-kubectl.yml │ └── note.txt ├── v03-argocd-applications ├── application-directory.yml ├── application-helm.yml ├── application-using-terraform │ ├── main.tf │ ├── providers.tf │ └── variables.tf ├── directoryOfmanifests │ ├── deployment.yml │ ├── service.yml │ ├── serviceaccount.yml │ ├── sub-directory │ │ └── service.yml │ └── test-connection.yml └── helm │ └── nginx │ ├── .helmignore │ ├── Chart.yaml │ ├── custom-values.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ │ └── test-connection.yaml │ └── values.yaml ├── v04-argocd-projects ├── project-manifest-examples │ ├── project-destination-restriction.yml │ ├── project-resource-blacklist.yml │ ├── project-resource-whitelist.yml │ ├── project-role.yml │ └── project-source-restriction.yml └── project-using-terraform │ ├── main.tf │ ├── providers.tf │ ├── terraform.tfvars │ └── variables.tf ├── v05-argocd-private-repositories ├── private-repos-manifests-examples │ ├── credential-template-secret.yml │ ├── https-private-repo-secret.yml │ └── ssh-private-repo-secret.yml └── private-repos-using-terraform │ ├── main.tf │ ├── providers.tf │ ├── terraform.tfvars │ └── variables.tf ├── v06-argocd-sync-policies-options ├── sync-options │ ├── application-level │ │ ├── create-namespace.yml │ │ ├── fail-on-shared-resource.yml │ │ ├── namespace-metadata.yml │ │ ├── prune-last.yml │ │ ├── replace.yml │ │ └── selective-sync.yml │ └── resource-level │ │ ├── delete.yml │ │ ├── disable-kubectl-validation.yml │ │ ├── no-prune.yml │ │ ├── prune-last.yml │ │ └── replace.yml ├── sync-policies-options-using-terraform │ ├── .terraform.lock.hcl │ ├── main.tf │ ├── providers.tf │ ├── terraform.tfvars │ └── variables.tf └── sync-policies │ ├── automated-sync.yml │ ├── prune-sync.yml │ └── selfheal-sync.yml ├── v07-argocd-sync-phases-waves ├── python_mattermost_api │ ├── Dockerfile │ ├── mattermost_api.py │ └── requirements.txt └── sync-phases-waves-manifests-examples │ ├── deployment.yml │ ├── fail-job.yml │ ├── post-job.yml │ ├── pre-job.yml │ ├── service.yml │ └── serviceaccount.yml ├── v08-argocd-add-cluster ├── add-cluster │ ├── add-cluster-using-manifest │ │ └── add-cluster.yml │ └── add-cluster-using-terraform │ │ ├── main.tf │ │ ├── providers.tf │ │ ├── terraform.tfvars │ │ └── variables.tf └── tracking-strategies │ ├── git.yml │ └── helm.yml ├── v09-argocd-applicationSet-1 ├── cluster-generator │ ├── cluster-generator-ex1.yml │ ├── cluster-generator-ex2.yml │ ├── cluster-generator-ex3.yml │ └── cluster-generator-ex4.yml ├── git-generator │ ├── cluster-config │ │ ├── pre-staging │ │ │ └── config.json │ │ └── staging │ │ │ └── config.json │ ├── directories-subtype │ │ ├── git-generator-ex1.yml │ │ └── git-generator-ex2.yml │ ├── files-subtype │ │ └── git-generator-ex1.yml │ └── resources │ │ ├── nginx-helm │ │ ├── Chart.yaml │ │ ├── custom-values.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── hpa.yaml │ │ │ ├── ingress.yaml │ │ │ ├── service.yaml │ │ │ ├── serviceaccount.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ │ └── nginx-manifests │ │ ├── deployment.yml │ │ ├── service.yml │ │ ├── serviceaccount.yml │ │ ├── sub-directory │ │ └── service.yml │ │ └── test-connection.yml └── list-generator │ ├── list-generator-ex1.yml │ └── list-generator-ex2.yml ├── v10-argocd-applicationSet-2 ├── matrix-generator │ ├── matrix-generator-ex1.yml │ ├── matrix-generator-ex2.yml │ └── matrix-generator-ex3.yml └── merge-generator │ └── merge-generator-ex1.yml ├── v12-argo-rollouts-blue-green ├── blue-green-app │ ├── Dockerfile │ ├── blue-green.py │ ├── requirements.txt │ └── templates │ │ ├── app-v1.html │ │ └── app-v2.html └── blue-green-manifests │ ├── ingress.yml │ └── rollout.yml ├── v13-argo-rollouts-canary ├── rolling-update-ingress.yml ├── rolling-update.yml ├── rollouts-setweight-ingress.yml ├── rollouts-setweight.yml ├── rollouts-traffic-management-ingress.yml └── rollouts-traffic-management.yml ├── v14-argo-rollouts-analysis ├── blue-green-analysis │ ├── Dockerfile │ ├── app-success-rate.sh │ ├── ingress.yml │ ├── post-promotion-analysis.yml │ ├── pre-promotion-analysis.yml │ └── rollout-with-analysis.yml └── canary-analysis │ ├── analysis-app.py │ ├── canary-analysis.yml │ ├── ingress.yml │ └── rollout-with-analysis.yml ├── v15-argo-workflows-getting-started ├── setting-up │ ├── note.txt │ └── values.yml └── template-types │ └── templates.yml ├── v16-argo-workflows-crds-and-artifacts ├── artifacts │ ├── conditional-artifacts.yml │ ├── conditional-parameters.yml │ ├── hardwired-artifacts.yml │ ├── minio-artifact-repo-cm.yml │ ├── workflow-artiafcts.yml │ ├── workflow-input-parameters.yml │ └── workflow-output-parameters.yml └── customResource-kinds │ ├── cluster-workflow-template.yml │ ├── cron-workflow.yml │ ├── workflow-ref.yml │ ├── workflow-template.yml │ └── workflow.yml ├── v17-combining-argo-tools ├── app │ ├── Dockerfile │ └── index.html ├── argo-cd │ └── argo-app.yml ├── argo-rollouts │ ├── nginx-ingress.yml │ └── nginx-rollouts.yml └── argo-workflows │ ├── build-push.yml │ ├── clone-repo.yml │ ├── update-manifest.yml │ └── workflows.yml └── v18-combining-argo-tools-part-2 ├── argo-cd └── argo-app.yml ├── argo-events ├── event-source.yml └── sensor.yml └── argo-rollouts ├── nginx-ingress.yml └── nginx-rollouts.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | crash.*.log 11 | 12 | 13 | # Ignore override files as they are usually used to override resources locally and so 14 | # are not checked in 15 | override.tf 16 | override.tf.json 17 | *_override.tf 18 | *_override.tf.json 19 | 20 | # Include override files you do wish to add to version control using negated pattern 21 | # !example_override.tf 22 | 23 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 24 | # example: *tfplan* 25 | 26 | # Ignore CLI configuration files 27 | .terraformrc 28 | terraform.rc 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Argoproj 2 | ![Argo Image](argo.jpg) 3 | 4 | ## Tools we are going to learn together 5 | * [Argo CD](https://github.com/argoproj/argo-cd) - Declarative GitOps Continuous Delivery 6 | * [Argo Rollouts](https://github.com/argoproj/argo-rollouts) - Progressive Delivery with support for Canary and Blue Green deployment strategies 7 | * [Argo Workflows](https://github.com/argoproj/argo-workflows) - Container-native Workflow Engine 8 | * [Argo Events](https://github.com/argoproj/argo-events) - Event-based Dependency Manager 9 | 10 | 11 | ## About the Author 12 | - **Mohammad Madanipour** 13 | - [GitHub](https://github.com/mohammadll) 14 | - [Linkedin](https://linkedin.com/in/mohammad-madanipour) 15 | 16 | 17 | ## You can also follow the videos of the Argo-Stack course on YouTube 18 | - **Argo-CD** 19 | - [Argo-CD Core Concepts](https://www.youtube.com/watch?v=T-ERIOb_3z0&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4) 20 | - [Argo-CD Setting-up](https://www.youtube.com/watch?v=pVnk9utUit8&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=2) 21 | - [Argo-CD Applications](https://www.youtube.com/watch?v=3tzMmhvD6p0&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=3) 22 | - [Argo-CD Projects](https://www.youtube.com/watch?v=VT4NTt5rUew&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=4) 23 | - [Argo-CD Private Repos](https://www.youtube.com/watch?v=SsewuwHuA08&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=5) 24 | - [Argo-CD Sync Policies And Sync Options](https://www.youtube.com/watch?v=XU08NQH11-Q&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=6) 25 | - [Argo-CD Sync Phases And Sync Waves](https://www.youtube.com/watch?v=nXx-Y3Vbn_0&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=7) 26 | - [Argo-CD Adding Cluster & Tracking Strategies](https://www.youtube.com/watch?v=dBpauFPL64A&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=8) 27 | - [Argo-CD ApplicationSet Part-1](https://www.youtube.com/watch?v=LoFazAmwWOw&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=9) 28 | - [Argo-CD ApplicationSet Part-2](https://www.youtube.com/watch?v=yT3w2iig9MI&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=10) 29 | - **Argo-Rollouts** 30 | - [Argo-Rollouts Overview & Installation](https://www.youtube.com/watch?v=hgEVcHhBwPw&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=11) 31 | - [Argo-Rollouts Blue-Green Deployment Strategy](https://www.youtube.com/watch?v=q1pMzZE8Ugw&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=12) 32 | - [Argo-Rollouts Canary Deployment Strategy](https://www.youtube.com/watch?v=MY4E8TgQ5Gs&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=13) 33 | - [Argo-Rollouts Analysis](https://www.youtube.com/watch?v=qbHv3riNN0g&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=15) 34 | - **Argo-Workflows** 35 | - [Argo-Workflows Getting-Started](https://www.youtube.com/watch?v=UgpVX5Sn5OI&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=14) 36 | - [Argo-Workflows Custom Resource Kinds & Artifacts](https://www.youtube.com/watch?v=ugB7v5WadGY&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=16) 37 | - **Final Project (Argo-CD + Argo-Rollouts + Argo-Workflows + Argo-Events)** 38 | - [CICD with Argo tools ( Part 1 )](https://www.youtube.com/watch?v=WxLqz9TyRSc&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=17) 39 | - [CICD with Argo tools ( Part 2 )](https://www.youtube.com/watch?v=ex-F_VXNYNA&list=PLYrn63eEqAzYttcyB6On1oH35O5rxgDt4&index=18) 40 | -------------------------------------------------------------------------------- /argo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devopshobbies/argocd-tutorial/9e00b5cb8aa9c164004eb4e2954986b7fc54a232/argo.jpg -------------------------------------------------------------------------------- /v02-argocd-setting-up/install-using-helm-nginx-ingress/note.txt: -------------------------------------------------------------------------------- 1 | ### Installing Argocd Helm Chart by overriding the parameters related to Ingress 2 | ### Please Note that before installing Argo, you must have nginx-ingress-controller installed on the cluster 3 | ### Also make sure to add the host used in the ingress to the /etc/hosts file 4 | 5 | ### Install Argocd Helm Chart as following: 6 | kubectl create ns argocd 7 | helm repo add argo https://argoproj.github.io/argo-helm 8 | helm install argocd argo/argo-cd -n argocd -f values-nginx-ingress.yml 9 | 10 | ### You can also use ingress with cert manager if you want -------------------------------------------------------------------------------- /v02-argocd-setting-up/install-using-helm-nginx-ingress/values-nginx-ingress.yml: -------------------------------------------------------------------------------- 1 | server: 2 | ingress: 3 | enabled: true 4 | annotations: 5 | nginx.ingress.kubernetes.io/force-ssl-redirect: "true" 6 | nginx.ingress.kubernetes.io/ssl-passthrough: "true" 7 | ingressClassName: nginx 8 | hostname: "devops.hobbies" 9 | -------------------------------------------------------------------------------- /v02-argocd-setting-up/install-using-helm-nodeport/note.txt: -------------------------------------------------------------------------------- 1 | ### Installing Argocd Helm Chart by overriding the parameters related to argocd-server service and changing it from ClusterIP type to NodePort 2 | 3 | ### Install Argocd Helm Chart as following: 4 | kubectl create ns argocd 5 | helm repo add argo https://argoproj.github.io/argo-helm 6 | helm install argocd argo/argo-cd -n argocd -f values-nodePort.yml -------------------------------------------------------------------------------- /v02-argocd-setting-up/install-using-helm-nodeport/values-nodePort.yml: -------------------------------------------------------------------------------- 1 | server: 2 | service: 3 | type: NodePort 4 | nodePortHttp: 32073 5 | nodePortHttps: 32074 -------------------------------------------------------------------------------- /v02-argocd-setting-up/install-using-kubectl/note.txt: -------------------------------------------------------------------------------- 1 | ### We have changed the type of the argocd-server service from the ClusterIP to NodePort as following: 2 | 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | labels: 7 | app.kubernetes.io/component: server 8 | app.kubernetes.io/name: argocd-server 9 | app.kubernetes.io/part-of: argocd 10 | name: argocd-server 11 | spec: 12 | ports: 13 | - name: http 14 | nodePort: 32073 15 | port: 80 16 | protocol: TCP 17 | targetPort: 8080 18 | - name: https 19 | nodePort: 32074 20 | port: 443 21 | protocol: TCP 22 | targetPort: 8080 23 | selector: 24 | app.kubernetes.io/name: argocd-server 25 | type: NodePort 26 | 27 | 28 | ### If you want to connect to argocd-server in an insecure manner , add the following DATA block to argocd-cmd-params-cm ConfigMap: 29 | 30 | apiVersion: v1 31 | kind: ConfigMap 32 | data: 33 | server.insecure: "true" 34 | metadata: 35 | labels: 36 | app.kubernetes.io/name: argocd-cmd-params-cm 37 | app.kubernetes.io/part-of: argocd 38 | name: argocd-cmd-params-cm -------------------------------------------------------------------------------- /v03-argocd-applications/application-directory.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: application-directory 5 | spec: 6 | destination: 7 | namespace: directory 8 | server: https://kubernetes.default.svc 9 | project: default 10 | source: 11 | # directory: 12 | # exclude: 'service.yml' 13 | # include: '{serviceaccount.yml,service.yml}' 14 | # recurse: true 15 | path: v03-argocd-applications/directoryOfmanifests 16 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 17 | targetRevision: main 18 | -------------------------------------------------------------------------------- /v03-argocd-applications/application-helm.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: application-from-scratch 5 | spec: 6 | destination: 7 | namespace: default 8 | server: https://kubernetes.default.svc 9 | project: default 10 | source: 11 | # It's possible to override helm values through different ways such as "valueFiles", "values", "valuesObject" and "parameters". 12 | # Values injections have the following order of precedence parameters > valuesObject > values > valueFiles > helm repository values.yaml Or rather 13 | # helm: 14 | # releaseName: application-from-helm 15 | # valueFiles: 16 | # - custom-values.yaml 17 | # values: | 18 | # replicaCount: 3 19 | # valuesObject: 20 | # replicaCount: 5 21 | # parameters: 22 | # - name: "replicaCount" 23 | # value: "1" 24 | path: v03-argocd-applications/helm/nginx 25 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 26 | targetRevision: main 27 | -------------------------------------------------------------------------------- /v03-argocd-applications/application-using-terraform/main.tf: -------------------------------------------------------------------------------- 1 | resource "argocd_application" "helm" { 2 | metadata { 3 | name = "helm-app-using-terraform" 4 | namespace = var.namespace 5 | labels = { 6 | test = "true" 7 | } 8 | } 9 | 10 | spec { 11 | destination { 12 | server = var.destination_server 13 | namespace = var.destination_namespace 14 | } 15 | 16 | source { 17 | repo_url = var.repo_url 18 | path = var.path 19 | target_revision = var.target_revision 20 | helm { 21 | value_files = var.values_files 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /v03-argocd-applications/application-using-terraform/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | argocd = { 4 | source = "oboukili/argocd" 5 | version = "6.0.2" 6 | } 7 | } 8 | } 9 | 10 | provider "argocd" { 11 | server_addr = var.server_addr 12 | username = var.username 13 | password = var.password 14 | insecure = var.insecure 15 | } 16 | -------------------------------------------------------------------------------- /v03-argocd-applications/application-using-terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "username" { 2 | type = string 3 | description = "Username Value" 4 | } 5 | 6 | variable "password" { 7 | type = string 8 | description = "Password Value" 9 | } 10 | 11 | variable "namespace" { 12 | type = string 13 | description = "Namespace Value" 14 | } 15 | 16 | variable "destination_namespace" { 17 | type = string 18 | description = "Destination Namespace Value" 19 | } 20 | 21 | variable "destination_server" { 22 | type = string 23 | description = "Destination Server Value" 24 | } 25 | 26 | variable "server_addr" { 27 | type = string 28 | description = "server_addr Value" 29 | } 30 | 31 | variable "repo_url" { 32 | type = string 33 | description = "Repo_url Value" 34 | } 35 | 36 | variable "path" { 37 | type = string 38 | description = "Path Value" 39 | } 40 | 41 | variable "target_revision" { 42 | type = string 43 | description = "Target_revision Value" 44 | } 45 | 46 | variable "values_files" { 47 | type = list(string) 48 | description = "Values_files Value as a list" 49 | } 50 | 51 | variable "insecure" { 52 | type = bool 53 | description = "insecure Value as a boolean" 54 | } 55 | -------------------------------------------------------------------------------- /v03-argocd-applications/directoryOfmanifests/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx 5 | labels: 6 | helm.sh/chart: nginx-0.1.0 7 | app.kubernetes.io/name: nginx 8 | app.kubernetes.io/instance: nginx 9 | app.kubernetes.io/version: "1.16.0" 10 | app.kubernetes.io/managed-by: Helm 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app.kubernetes.io/name: nginx 16 | app.kubernetes.io/instance: nginx 17 | template: 18 | metadata: 19 | labels: 20 | app.kubernetes.io/name: nginx 21 | app.kubernetes.io/instance: nginx 22 | spec: 23 | serviceAccountName: nginx 24 | securityContext: 25 | {} 26 | containers: 27 | - name: nginx 28 | securityContext: 29 | {} 30 | image: "nginx:1.16.0" 31 | imagePullPolicy: IfNotPresent 32 | ports: 33 | - name: http 34 | containerPort: 80 35 | protocol: TCP 36 | livenessProbe: 37 | httpGet: 38 | path: / 39 | port: http 40 | readinessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | resources: 45 | {} 46 | -------------------------------------------------------------------------------- /v03-argocd-applications/directoryOfmanifests/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx 5 | annotations: 6 | argocd.argoproj.io/sync-options: Replace=true 7 | labels: 8 | helm.sh/chart: nginx-0.1.0 9 | app.kubernetes.io/name: nginx 10 | app.kubernetes.io/instance: nginx 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | spec: 14 | type: ClusterIP 15 | ports: 16 | - port: 80 17 | targetPort: http 18 | protocol: TCP 19 | name: http 20 | selector: 21 | app.kubernetes.io/name: nginx 22 | app.kubernetes.io/instance: nginx 23 | -------------------------------------------------------------------------------- /v03-argocd-applications/directoryOfmanifests/serviceaccount.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: nginx 5 | annotations: 6 | argocd.argoproj.io/sync-options: Prune=false 7 | labels: 8 | helm.sh/chart: nginx-0.1.0 9 | app.kubernetes.io/name: nginx 10 | app.kubernetes.io/instance: nginx 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | -------------------------------------------------------------------------------- /v03-argocd-applications/directoryOfmanifests/sub-directory/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-sub-directory 5 | # annotations: 6 | # argocd.argoproj.io/sync-options: Prune=false 7 | labels: 8 | helm.sh/chart: nginx-0.1.0 9 | app.kubernetes.io/name: nginx 10 | app.kubernetes.io/instance: nginx 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | spec: 14 | type: ClusterIP 15 | ports: 16 | - port: 80 17 | targetPort: http 18 | protocol: TCP 19 | name: http 20 | selector: 21 | app.kubernetes.io/name: nginx 22 | app.kubernetes.io/instance: nginx 23 | -------------------------------------------------------------------------------- /v03-argocd-applications/directoryOfmanifests/test-connection.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "nginx-test-connection" 5 | labels: 6 | helm.sh/chart: nginx-0.1.0 7 | app.kubernetes.io/name: nginx 8 | app.kubernetes.io/instance: nginx 9 | app.kubernetes.io/version: "1.16.0" 10 | app.kubernetes.io/managed-by: Helm 11 | annotations: 12 | "helm.sh/hook": test 13 | spec: 14 | containers: 15 | - name: wget 16 | image: busybox 17 | command: ['wget'] 18 | args: ['nginx:80'] 19 | restartPolicy: Never 20 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: nginx 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/custom-values.yaml: -------------------------------------------------------------------------------- 1 | replicaCount: 4 2 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "nginx.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "nginx.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "nginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "nginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "nginx.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "nginx.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "nginx.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "nginx.labels" -}} 37 | helm.sh/chart: {{ include "nginx.chart" . }} 38 | {{ include "nginx.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "nginx.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "nginx.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "nginx.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "nginx.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "nginx.fullname" . }} 5 | labels: 6 | {{- include "nginx.labels" . | nindent 4 }} 7 | spec: 8 | {{- if not .Values.autoscaling.enabled }} 9 | replicas: {{ .Values.replicaCount }} 10 | {{- end }} 11 | selector: 12 | matchLabels: 13 | {{- include "nginx.selectorLabels" . | nindent 6 }} 14 | template: 15 | metadata: 16 | {{- with .Values.podAnnotations }} 17 | annotations: 18 | {{- toYaml . | nindent 8 }} 19 | {{- end }} 20 | labels: 21 | {{- include "nginx.selectorLabels" . | nindent 8 }} 22 | spec: 23 | {{- with .Values.imagePullSecrets }} 24 | imagePullSecrets: 25 | {{- toYaml . | nindent 8 }} 26 | {{- end }} 27 | serviceAccountName: {{ include "nginx.serviceAccountName" . }} 28 | securityContext: 29 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 30 | containers: 31 | - name: {{ .Chart.Name }} 32 | securityContext: 33 | {{- toYaml .Values.securityContext | nindent 12 }} 34 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 35 | imagePullPolicy: {{ .Values.image.pullPolicy }} 36 | ports: 37 | - name: http 38 | containerPort: {{ .Values.service.port }} 39 | protocol: TCP 40 | livenessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | readinessProbe: 45 | httpGet: 46 | path: / 47 | port: http 48 | resources: 49 | {{- toYaml .Values.resources | nindent 12 }} 50 | {{- with .Values.nodeSelector }} 51 | nodeSelector: 52 | {{- toYaml . | nindent 8 }} 53 | {{- end }} 54 | {{- with .Values.affinity }} 55 | affinity: 56 | {{- toYaml . | nindent 8 }} 57 | {{- end }} 58 | {{- with .Values.tolerations }} 59 | tolerations: 60 | {{- toYaml . | nindent 8 }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "nginx.fullname" . }} 6 | labels: 7 | {{- include "nginx.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "nginx.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | target: 21 | type: Utilization 22 | averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 23 | {{- end }} 24 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 25 | - type: Resource 26 | resource: 27 | name: memory 28 | target: 29 | type: Utilization 30 | averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "nginx.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "nginx.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 51 | service: 52 | name: {{ $fullName }} 53 | port: 54 | number: {{ $svcPort }} 55 | {{- else }} 56 | serviceName: {{ $fullName }} 57 | servicePort: {{ $svcPort }} 58 | {{- end }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "nginx.fullname" . }} 5 | labels: 6 | {{- include "nginx.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "nginx.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "nginx.serviceAccountName" . }} 6 | labels: 7 | {{- include "nginx.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "nginx.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "nginx.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "nginx.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /v03-argocd-applications/helm/nginx/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for nginx. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 2 6 | 7 | image: 8 | repository: nginx 9 | pullPolicy: IfNotPresent 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: "" 12 | 13 | imagePullSecrets: [] 14 | nameOverride: "" 15 | fullnameOverride: "" 16 | 17 | serviceAccount: 18 | # Specifies whether a service account should be created 19 | create: true 20 | # Annotations to add to the service account 21 | annotations: {} 22 | # The name of the service account to use. 23 | # If not set and create is true, a name is generated using the fullname template 24 | name: "" 25 | 26 | podAnnotations: {} 27 | 28 | podSecurityContext: {} 29 | # fsGroup: 2000 30 | 31 | securityContext: {} 32 | # capabilities: 33 | # drop: 34 | # - ALL 35 | # readOnlyRootFilesystem: true 36 | # runAsNonRoot: true 37 | # runAsUser: 1000 38 | 39 | service: 40 | type: ClusterIP 41 | port: 80 42 | 43 | ingress: 44 | enabled: false 45 | className: "" 46 | annotations: {} 47 | # kubernetes.io/ingress.class: nginx 48 | # kubernetes.io/tls-acme: "true" 49 | hosts: 50 | - host: chart-example.local 51 | paths: 52 | - path: / 53 | pathType: ImplementationSpecific 54 | tls: [] 55 | # - secretName: chart-example-tls 56 | # hosts: 57 | # - chart-example.local 58 | 59 | resources: {} 60 | # We usually recommend not to specify default resources and to leave this as a conscious 61 | # choice for the user. This also increases chances charts run on environments with little 62 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 63 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 64 | # limits: 65 | # cpu: 100m 66 | # memory: 128Mi 67 | # requests: 68 | # cpu: 100m 69 | # memory: 128Mi 70 | 71 | autoscaling: 72 | enabled: false 73 | minReplicas: 1 74 | maxReplicas: 100 75 | targetCPUUtilizationPercentage: 80 76 | # targetMemoryUtilizationPercentage: 80 77 | 78 | nodeSelector: {} 79 | 80 | tolerations: [] 81 | 82 | affinity: {} 83 | -------------------------------------------------------------------------------- /v04-argocd-projects/project-manifest-examples/project-destination-restriction.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: AppProject 3 | metadata: 4 | name: project-destination-restriction 5 | namespace: argocd 6 | spec: 7 | clusterResourceWhitelist: 8 | - group: '*' 9 | kind: '*' 10 | destinations: 11 | - namespace: '!dev' ## Use '!' to place namespace in BlackList, if we remove '!' the namespace will be placed in WhiteList 12 | server: '*' ## '*' means we are allowed to use any servers 13 | sourceRepos: 14 | - '*' 15 | -------------------------------------------------------------------------------- /v04-argocd-projects/project-manifest-examples/project-resource-blacklist.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: AppProject 3 | metadata: 4 | name: project-resource-blacklist 5 | namespace: argocd 6 | spec: 7 | clusterResourceWhitelist: 8 | - group: '*' ## it means we are allowed to use any kinds of clusterscoped resources 9 | kind: '*' 10 | namespaceResourceBlacklist: 11 | - group: '' 12 | kind: 'ServiceAccount' ## it means we are NOT allowd to use 'serviceaccount' namespacescoped resource 13 | destinations: 14 | - namespace: '*' 15 | server: '*' 16 | sourceRepos: 17 | - '*' 18 | -------------------------------------------------------------------------------- /v04-argocd-projects/project-manifest-examples/project-resource-whitelist.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: AppProject 3 | metadata: 4 | name: project-resource-whitelist 5 | namespace: argocd 6 | spec: 7 | clusterResourceWhitelist: 8 | - group: '*' ## it means we are allowed to use any kinds of clusterscoped resources 9 | kind: '*' 10 | namespaceResourceWhitelist: 11 | - group: '' 12 | kind: 'ServiceAccount' ## it means we are allowd to use 'serviceaccount' namespacescoped resource Only 13 | destinations: 14 | - namespace: '*' 15 | server: '*' 16 | sourceRepos: 17 | - '*' 18 | -------------------------------------------------------------------------------- /v04-argocd-projects/project-manifest-examples/project-role.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: AppProject 3 | metadata: 4 | name: project-role 5 | namespace: argocd 6 | spec: 7 | clusterResourceWhitelist: 8 | - group: '*' 9 | kind: '*' 10 | namespaceResourceWhitelist: 11 | - group: '*' 12 | kind: '*' 13 | destinations: 14 | - namespace: '*' 15 | server: '*' 16 | sourceRepos: 17 | - '*' 18 | roles: 19 | - name: read-sync 20 | description: "this role can be used for reading applications" 21 | policies: 22 | - p, proj:project-role:read-sync, applications, get, project-role/*, allow 23 | - p, proj:project-role:read-sync, applications, sync, project-role/*, allow 24 | -------------------------------------------------------------------------------- /v04-argocd-projects/project-manifest-examples/project-source-restriction.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: AppProject 3 | metadata: 4 | name: project-source-restriction 5 | namespace: argocd 6 | spec: 7 | clusterResourceWhitelist: 8 | - group: '*' 9 | kind: '*' 10 | destinations: 11 | - namespace: '*' 12 | server: '*' 13 | sourceRepos: 14 | - '!https://github.com/devopshobbies/argocd-tutorial.git' ## Use '!' to place repo in BlackList, if we remove '!' the repo will be placed in WhiteList 15 | - '*' ## '*' means we are allowed to use any repos 16 | -------------------------------------------------------------------------------- /v04-argocd-projects/project-using-terraform/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | roles_count = length(var.roles) 3 | } 4 | 5 | resource "argocd_project" "terraform-project" { 6 | metadata { 7 | name = var.project_name 8 | namespace = var.project_namespace 9 | labels = var.project_labels 10 | } 11 | 12 | spec { 13 | description = var.project_description 14 | 15 | source_namespaces = var.source_namespaces 16 | source_repos = var.source_repos 17 | 18 | dynamic "destination" { 19 | for_each = var.destinations 20 | content { 21 | server = destination.value.server 22 | namespace = destination.value.namespace 23 | } 24 | } 25 | 26 | dynamic "cluster_resource_whitelist" { 27 | for_each = var.cluster_resources_whitelist 28 | content { 29 | group = cluster_resource_whitelist.value.group 30 | kind = cluster_resource_whitelist.value.kind 31 | } 32 | } 33 | 34 | dynamic "namespace_resource_whitelist" { 35 | for_each = var.namespace_resources_whitelist 36 | content { 37 | group = namespace_resource_whitelist.value.group 38 | kind = namespace_resource_whitelist.value.kind 39 | } 40 | } 41 | 42 | dynamic "role" { 43 | for_each = var.roles 44 | content { 45 | name = role.value.name 46 | policies = role.value.policies 47 | } 48 | } 49 | } 50 | } 51 | 52 | resource "argocd_project_token" "secret" { 53 | count = local.roles_count 54 | project = var.project_name 55 | role = var.roles[count.index]["name"] 56 | depends_on = [ 57 | argocd_project.terraform-project 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /v04-argocd-projects/project-using-terraform/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | argocd = { 4 | source = "oboukili/argocd" 5 | version = "6.0.2" 6 | } 7 | } 8 | } 9 | 10 | provider "argocd" { 11 | server_addr = var.server_addr 12 | username = var.username 13 | password = var.password 14 | insecure = var.insecure 15 | } 16 | -------------------------------------------------------------------------------- /v04-argocd-projects/project-using-terraform/terraform.tfvars: -------------------------------------------------------------------------------- 1 | server_addr = "localhost:32073" 2 | username = "admin" 3 | password = "O0Nk42qUhEOMK4q8" 4 | insecure = true 5 | project_name = "terraform-project" 6 | project_namespace = "argocd" 7 | project_labels = { 8 | acceptance = "true" 9 | } 10 | project_description = "this project has been created using terraform" 11 | source_namespaces = ["argocd"] 12 | source_repos = ["*"] 13 | destinations = { 14 | destination_one = { 15 | server = "*", 16 | namespace = "dev" 17 | }, 18 | destination_two = { 19 | server = "*", 20 | namespace = "prod" 21 | } 22 | } 23 | cluster_resources_whitelist = { 24 | resource_one = { 25 | group = "*" 26 | kind = "*" 27 | } 28 | } 29 | namespace_resources_whitelist = { 30 | resource_one = { 31 | group = "apps" 32 | kind = "Deployment" 33 | }, 34 | resource_two = { 35 | group = "" 36 | kind = "Service" 37 | } 38 | } 39 | roles = [ 40 | { 41 | name = "read-only" 42 | policies = [ 43 | "p, proj:terraform-project:read-only, applications, get, terraform-project/*, allow", 44 | ] 45 | } 46 | ] 47 | -------------------------------------------------------------------------------- /v04-argocd-projects/project-using-terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "server_addr" { 2 | type = string 3 | description = "The server address" 4 | } 5 | 6 | variable "username" { 7 | type = string 8 | description = "The Username" 9 | } 10 | 11 | variable "password" { 12 | type = string 13 | description = "The Password" 14 | } 15 | 16 | variable "insecure" { 17 | type = bool 18 | description = "The Connection Insecure flag" 19 | } 20 | 21 | variable "project_name" { 22 | type = string 23 | description = "The Name of the Project" 24 | } 25 | 26 | variable "project_namespace" { 27 | type = string 28 | description = "The Namespace of the Project" 29 | } 30 | 31 | variable "project_labels" { 32 | type = map(string) 33 | description = "The Labels of the Project" 34 | } 35 | 36 | variable "project_description" { 37 | type = string 38 | description = "The Description of the Project" 39 | } 40 | 41 | variable "source_namespaces" { 42 | type = list(string) 43 | description = "The Source Namespaces of the Project" 44 | } 45 | 46 | variable "source_repos" { 47 | type = list(string) 48 | description = "The Source Repos of the Project" 49 | } 50 | 51 | variable "destinations" { 52 | type = map(object({ 53 | server = string, 54 | namespace = string 55 | })) 56 | } 57 | 58 | variable "cluster_resources_whitelist" { 59 | type = map(object({ 60 | group = string, 61 | kind = string 62 | })) 63 | } 64 | 65 | variable "namespace_resources_whitelist" { 66 | type = map(object({ 67 | group = string, 68 | kind = string 69 | })) 70 | } 71 | 72 | variable "roles" { 73 | type = list(object({ 74 | name = string, 75 | policies = list(string) 76 | })) 77 | } 78 | -------------------------------------------------------------------------------- /v05-argocd-private-repositories/private-repos-manifests-examples/credential-template-secret.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: credential-template-secret 5 | namespace: argocd 6 | labels: 7 | argocd.argoproj.io/secret-type: repo-creds 8 | stringData: 9 | type: git 10 | url: https://github.com/mohammadll 11 | username: argocd-privare-repo 12 | password: CHANGE_ME_WITH_TOKEN 13 | -------------------------------------------------------------------------------- /v05-argocd-private-repositories/private-repos-manifests-examples/https-private-repo-secret.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: https-private-repo-secret 5 | namespace: argocd 6 | labels: 7 | argocd.argoproj.io/secret-type: repository 8 | stringData: 9 | type: git 10 | url: https://github.com/mohammadll/argo-tutorial.git 11 | username: argocd-privare-repo 12 | password: CHANGE_ME_WITH_TOKEN 13 | -------------------------------------------------------------------------------- /v05-argocd-private-repositories/private-repos-manifests-examples/ssh-private-repo-secret.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: ssh-private-repo-secret 5 | namespace: argocd 6 | labels: 7 | argocd.argoproj.io/secret-type: repository 8 | stringData: 9 | type: git 10 | url: git@github.com:mohammadll/argo-tutorial.git 11 | sshPrivateKey: | 12 | -----BEGIN OPENSSH PRIVATE KEY----- 13 | ......................................... 14 | -----END OPENSSH PRIVATE KEY----- 15 | -------------------------------------------------------------------------------- /v05-argocd-private-repositories/private-repos-using-terraform/main.tf: -------------------------------------------------------------------------------- 1 | # Private Git repository 2 | resource "argocd_repository" "private" { 3 | repo = var.repo_url 4 | username = var.repo_username 5 | password = var.repo_password 6 | } 7 | -------------------------------------------------------------------------------- /v05-argocd-private-repositories/private-repos-using-terraform/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | argocd = { 4 | source = "oboukili/argocd" 5 | version = "6.0.2" 6 | } 7 | } 8 | } 9 | 10 | provider "argocd" { 11 | server_addr = var.server_addr 12 | username = var.username 13 | password = var.password 14 | insecure = var.insecure 15 | } -------------------------------------------------------------------------------- /v05-argocd-private-repositories/private-repos-using-terraform/terraform.tfvars: -------------------------------------------------------------------------------- 1 | server_addr = "localhost:32073" 2 | username = "admin" 3 | password = "-TzDOP0pmtM-reCX" 4 | insecure = true 5 | repo_password = "CHANGE-ME-WITH-TOKEN" 6 | repo_username = "argocd-privare-repo" 7 | repo_url = "https://github.com/mohammadll/argo-tutorial.git" 8 | -------------------------------------------------------------------------------- /v05-argocd-private-repositories/private-repos-using-terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "server_addr" { 2 | type = string 3 | description = "The server address" 4 | } 5 | 6 | variable "username" { 7 | type = string 8 | description = "The Username" 9 | } 10 | 11 | variable "password" { 12 | type = string 13 | description = "The Password" 14 | } 15 | 16 | variable "insecure" { 17 | type = bool 18 | description = "The Connection Insecure flag" 19 | } 20 | 21 | variable "repo_password" { 22 | type = string 23 | description = "The Password or the token of my github account" 24 | } 25 | 26 | variable "repo_username" { 27 | type = string 28 | description = "The username or the token name" 29 | } 30 | 31 | variable "repo_url" { 32 | type = string 33 | description = "The Private Repository Url" 34 | } 35 | -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/application-level/create-namespace.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | namespace: argocd 5 | spec: 6 | destination: 7 | server: https://kubernetes.default.svc 8 | namespace: some-namespace 9 | syncPolicy: 10 | syncOptions: 11 | - CreateNamespace=true -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/application-level/fail-on-shared-resource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | spec: 4 | syncPolicy: 5 | syncOptions: 6 | - FailOnSharedResource=true -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/application-level/namespace-metadata.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | namespace: test 5 | spec: 6 | syncPolicy: 7 | managedNamespaceMetadata: 8 | labels: # The labels to set on the application namespace 9 | any: label 10 | you: like 11 | annotations: # The annotations to set on the application namespace 12 | the: same 13 | applies: for 14 | annotations: on-the-namespace 15 | syncOptions: 16 | - CreateNamespace=true -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/application-level/prune-last.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | spec: 4 | syncPolicy: 5 | syncOptions: 6 | - PruneLast=true -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/application-level/replace.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | spec: 4 | syncPolicy: 5 | syncOptions: 6 | - Replace=true -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/application-level/selective-sync.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | spec: 4 | syncPolicy: 5 | syncOptions: 6 | - ApplyOutOfSyncOnly=true -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/resource-level/delete.yml: -------------------------------------------------------------------------------- 1 | metadata: 2 | annotations: 3 | argocd.argoproj.io/sync-options: Delete=false 4 | -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/resource-level/disable-kubectl-validation.yml: -------------------------------------------------------------------------------- 1 | metadata: 2 | annotations: 3 | argocd.argoproj.io/sync-options: Validate=false -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/resource-level/no-prune.yml: -------------------------------------------------------------------------------- 1 | metadata: 2 | annotations: 3 | argocd.argoproj.io/sync-options: Prune=false -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/resource-level/prune-last.yml: -------------------------------------------------------------------------------- 1 | metadata: 2 | annotations: 3 | argocd.argoproj.io/sync-options: PruneLast=true -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-options/resource-level/replace.yml: -------------------------------------------------------------------------------- 1 | metadata: 2 | annotations: 3 | argocd.argoproj.io/sync-options: Replace=true -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-policies-options-using-terraform/.terraform.lock.hcl: -------------------------------------------------------------------------------- 1 | # This file is maintained automatically by "terraform init". 2 | # Manual edits may be lost in future updates. 3 | 4 | provider "registry.terraform.io/oboukili/argocd" { 5 | version = "6.0.2" 6 | constraints = "6.0.2" 7 | hashes = [ 8 | "h1:wyeXBDZkKqdnj/8luX78jI1DdnCOb3R3FNAx6vHG+6Y=", 9 | "zh:1e9be24a93d1f0739be7dba490c9a12226e68dfcf9f10ac132ef74b28d53f3e6", 10 | "zh:26fb94f3d70bb5b7416863af2eb38867fee04cccbf4b9989e4c45e031e9176e2", 11 | "zh:730dfdf3d671bf94bf6e7c5b7095e02fdd61f37b18cc2efbaec165db31ed9526", 12 | "zh:74bacd85536d5c70b19a2f5e5d9504ce57fd48ac33a89fab0d5ad0b08896f5a3", 13 | "zh:77abd7cf8484cc53942b20ec902e6600b74f4108b76e8aaf6dc5c8e2cfbbae60", 14 | "zh:9784c1cd03d7de8bb8cb9c851fbb5371f7b2db932c9b1438c75fd9e0fe7ae884", 15 | "zh:a430b8974bcfd92f10313a39423b1f5c313082576f2638d2e1c035165d17b086", 16 | "zh:d7189c67872ad6826702806c3a894d5e972659667f1a6c7579fe50afebc3c314", 17 | "zh:fb7ab84c065941297a98aba2b0222e039eeafabf794efc4ef2a18a96d1f7705b", 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-policies-options-using-terraform/main.tf: -------------------------------------------------------------------------------- 1 | resource "argocd_application" "application" { 2 | metadata { 3 | name = "sync-policy-options-using-terraform" 4 | namespace = var.namespace 5 | labels = { 6 | using_sync_policy_options = "true" 7 | } 8 | } 9 | 10 | spec { 11 | destination { 12 | server = var.destination_server 13 | namespace = var.destination_namespace 14 | } 15 | 16 | source { 17 | repo_url = var.repo_url 18 | path = var.path 19 | target_revision = var.target_revision 20 | } 21 | sync_policy { 22 | managed_namespace_metadata { 23 | labels = var.namespace_metadata_labels 24 | } 25 | automated { 26 | prune = var.prune_enabled 27 | self_heal = var.selfheal_enabled 28 | } 29 | sync_options = var.sync_options 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-policies-options-using-terraform/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | argocd = { 4 | source = "oboukili/argocd" 5 | version = "6.0.2" 6 | } 7 | } 8 | } 9 | 10 | provider "argocd" { 11 | server_addr = var.server_addr 12 | username = var.username 13 | password = var.password 14 | insecure = var.insecure 15 | } -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-policies-options-using-terraform/terraform.tfvars: -------------------------------------------------------------------------------- 1 | username = "admin" 2 | password = "GOeR1fjOnQRDFfHp" 3 | namespace = "argocd" 4 | destination_namespace = "sync-policy-options" 5 | destination_server = "https://kubernetes.default.svc" 6 | server_addr = "localhost:32073" 7 | insecure = true 8 | repo_url = "https://github.com/devopshobbies/argocd-tutorial.git" 9 | path = "v03-argocd-applications/directoryOfmanifests" 10 | target_revision = "main" 11 | prune_enabled = true 12 | selfheal_enabled = true 13 | sync_options = ["CreateNamespace=true", "FailOnSharedResource=true"] 14 | namespace_metadata_labels = { 15 | created_by = "Terraform" 16 | Course_creator = "Mohammad" 17 | } -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-policies-options-using-terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "username" { 2 | type = string 3 | description = "Username Value" 4 | } 5 | 6 | variable "password" { 7 | type = string 8 | description = "Password Value" 9 | } 10 | 11 | variable "namespace" { 12 | type = string 13 | description = "Namespace Value" 14 | } 15 | 16 | variable "destination_namespace" { 17 | type = string 18 | description = "Destination Namespace Value" 19 | } 20 | 21 | variable "destination_server" { 22 | type = string 23 | description = "Destination Server Value" 24 | } 25 | 26 | variable "server_addr" { 27 | type = string 28 | description = "server_addr Value" 29 | } 30 | 31 | variable "repo_url" { 32 | type = string 33 | description = "Repo_url Value" 34 | } 35 | 36 | variable "path" { 37 | type = string 38 | description = "Path Value" 39 | } 40 | 41 | variable "target_revision" { 42 | type = string 43 | description = "Target_revision Value" 44 | } 45 | 46 | variable "insecure" { 47 | type = bool 48 | description = "insecure Value as a boolean" 49 | } 50 | 51 | variable "prune_enabled" { 52 | type = bool 53 | description = "Auto-prune Value as a boolean" 54 | } 55 | 56 | variable "selfheal_enabled" { 57 | type = bool 58 | description = "Auto-selfheal Value as a boolean" 59 | } 60 | 61 | variable "sync_options" { 62 | type = list(string) 63 | description = "List of sync options as a list of strings" 64 | } 65 | 66 | variable "namespace_metadata_labels" { 67 | type = map(string) 68 | description = "Map of namespace metadata labels as a map of strings" 69 | } -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-policies/automated-sync.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: automated-application 5 | spec: 6 | destination: 7 | namespace: automated-sync 8 | server: https://kubernetes.default.svc 9 | project: default 10 | source: 11 | path: v03-argocd-applications/directoryOfmanifests 12 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 13 | targetRevision: main 14 | syncPolicy: 15 | automated: {} 16 | -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-policies/prune-sync.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: prune-application 5 | spec: 6 | destination: 7 | namespace: prune-sync 8 | server: https://kubernetes.default.svc 9 | project: default 10 | source: 11 | path: v03-argocd-applications/directoryOfmanifests 12 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 13 | targetRevision: main 14 | syncPolicy: 15 | automated: 16 | prune: true 17 | -------------------------------------------------------------------------------- /v06-argocd-sync-policies-options/sync-policies/selfheal-sync.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: selfheal-application 5 | spec: 6 | destination: 7 | namespace: selfheal-sync 8 | server: https://kubernetes.default.svc 9 | project: default 10 | source: 11 | path: v03-argocd-applications/directoryOfmanifests 12 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 13 | targetRevision: main 14 | syncPolicy: 15 | automated: 16 | selfHeal: true 17 | -------------------------------------------------------------------------------- /v07-argocd-sync-phases-waves/python_mattermost_api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim-buster 2 | WORKDIR /devops-hobbies 3 | COPY requirements.txt . 4 | RUN pip3 install -r requirements.txt 5 | COPY mattermost_api.py . 6 | -------------------------------------------------------------------------------- /v07-argocd-sync-phases-waves/python_mattermost_api/mattermost_api.py: -------------------------------------------------------------------------------- 1 | from mattermostdriver import Driver 2 | from os import environ 3 | import json 4 | 5 | server = Driver({ 6 | 'url': environ['url'], 7 | 'token': environ['token'], 8 | 'scheme': environ['scheme'], 9 | 'port': int(environ['port']) 10 | }) 11 | 12 | server.login() 13 | 14 | channel_name = environ['channel_name'] 15 | team_name = environ['team_name'] 16 | 17 | channel_id = server.channels.get_channel_by_name_and_team_name(team_name, channel_name)['id'] 18 | 19 | server.posts.create_post(options = { 20 | 'channel_id': channel_id, 21 | 'message': environ['message'] 22 | }) 23 | -------------------------------------------------------------------------------- /v07-argocd-sync-phases-waves/python_mattermost_api/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2023.7.22 2 | charset-normalizer==3.2.0 3 | idna==3.4 4 | mattermostdriver==7.3.2 5 | requests==2.31.0 6 | urllib3==2.0.4 7 | websockets==11.0.3 -------------------------------------------------------------------------------- /v07-argocd-sync-phases-waves/sync-phases-waves-manifests-examples/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx 5 | labels: 6 | helm.sh/chart: nginx-0.1.0 7 | app.kubernetes.io/name: nginx 8 | app.kubernetes.io/instance: nginx 9 | app.kubernetes.io/version: "1.16.0" 10 | app.kubernetes.io/managed-by: Helm 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app.kubernetes.io/name: nginx 16 | app.kubernetes.io/instance: nginx 17 | template: 18 | metadata: 19 | labels: 20 | app.kubernetes.io/name: nginx 21 | app.kubernetes.io/instance: nginx 22 | spec: 23 | serviceAccountName: nginx 24 | securityContext: 25 | {} 26 | containers: 27 | - name: nginx 28 | securityContext: 29 | {} 30 | image: "nginx:1.16.0" 31 | imagePullPolicy: IfNotPresent 32 | ports: 33 | - name: http 34 | containerPort: 80 35 | protocol: TCP 36 | livenessProbe: 37 | httpGet: 38 | path: / 39 | port: http 40 | readinessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | resources: 45 | {} 46 | -------------------------------------------------------------------------------- /v07-argocd-sync-phases-waves/sync-phases-waves-manifests-examples/fail-job.yml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: mattermost-post-job-failure 5 | annotations: 6 | argocd.argoproj.io/hook: SyncFail 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: mattermost-failure 12 | image: mattermost:final 13 | command: [ "python3", "mattermost_api.py"] 14 | env: 15 | - name: message 16 | value: "MESSAGE FROM ARGOCD: The last sync is: *** Sync Failed ***" 17 | - name: url 18 | value: "mattermost.local" 19 | - name: token 20 | value: "1mh8r35js7dhpcswb4mpnkwpcw" 21 | - name: scheme 22 | value: "http" 23 | - name: port 24 | value: "8065" 25 | - name: channel_name 26 | value: "argocd-course" 27 | - name: team_name 28 | value: "DevOps-Hobbies" 29 | restartPolicy: Never 30 | backoffLimit: 0 31 | -------------------------------------------------------------------------------- /v07-argocd-sync-phases-waves/sync-phases-waves-manifests-examples/post-job.yml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: mattermost-post-job-success 5 | annotations: 6 | argocd.argoproj.io/hook: PostSync 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: mattermost-success 12 | image: mattermost:final 13 | command: [ "python3", "mattermost_api.py"] 14 | env: 15 | - name: message 16 | value: "MESSAGE FROM ARGOCD: The last sync is: *** Sync OK ***" 17 | - name: url 18 | value: "mattermost.local" 19 | - name: token 20 | value: "1mh8r35js7dhpcswb4mpnkwpcw" 21 | - name: scheme 22 | value: "http" 23 | - name: port 24 | value: "8065" 25 | - name: channel_name 26 | value: "argocd-course" 27 | - name: team_name 28 | value: "DevOps-Hobbies" 29 | restartPolicy: Never 30 | backoffLimit: 0 31 | -------------------------------------------------------------------------------- /v07-argocd-sync-phases-waves/sync-phases-waves-manifests-examples/pre-job.yml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: health-check-pre-job 5 | annotations: 6 | argocd.argoproj.io/hook: PreSync 7 | argocd.argoproj.io/hook-delete-policy: HookFailed 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: health-check 13 | image: curlimages/curl 14 | command: ["/bin/sh", "-c"] 15 | args: ["if curl -s http://myapp.local:5000 | grep -qi 'running'; then echo 'Demo Application is up and Running'; exit 0; else echo 'Demo Application is NOT accessible'; exit 1; fi"] 16 | restartPolicy: Never 17 | backoffLimit: 0 18 | -------------------------------------------------------------------------------- /v07-argocd-sync-phases-waves/sync-phases-waves-manifests-examples/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx 5 | annotations: 6 | argocd.argoproj.io/sync-wave: "-2" 7 | labels: 8 | helm.sh/chart: nginx-0.1.0 9 | app.kubernetes.io/name: nginx 10 | app.kubernetes.io/instance: nginx 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | spec: 14 | type: ClusterIP 15 | ports: 16 | - port: 80 17 | targetPort: http 18 | protocol: TCP 19 | name: http 20 | selector: 21 | app.kubernetes.io/name: nginx 22 | app.kubernetes.io/instance: nginx 23 | -------------------------------------------------------------------------------- /v07-argocd-sync-phases-waves/sync-phases-waves-manifests-examples/serviceaccount.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: nginx 5 | annotations: 6 | argocd.argoproj.io/sync-wave: "-1" 7 | labels: 8 | helm.sh/chart: nginx-0.1.0 9 | app.kubernetes.io/name: nginx 10 | app.kubernetes.io/instance: nginx 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | -------------------------------------------------------------------------------- /v08-argocd-add-cluster/add-cluster/add-cluster-using-manifest/add-cluster.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: external 5 | labels: 6 | argocd.argoproj.io/secret-type: cluster 7 | type: Opaque 8 | stringData: 9 | name: external 10 | server: API_SERVER_ADDRESS 11 | config: | 12 | { 13 | "bearerToken": "SERVICE_ACCOUNT_TOKEN", 14 | "tlsClientConfig": { 15 | "insecure": false, 16 | "caData": "BASE64 ENCODED CERTIFICATE" 17 | } 18 | } -------------------------------------------------------------------------------- /v08-argocd-add-cluster/add-cluster/add-cluster-using-terraform/main.tf: -------------------------------------------------------------------------------- 1 | resource "kubernetes_service_account" "argocd_manager_sa" { 2 | metadata { 3 | name = var.sa_name 4 | namespace = var.sa_namespace 5 | } 6 | } 7 | 8 | resource "kubernetes_secret" "argocd_manager_secret" { 9 | metadata { 10 | name = var.argocd-manager-secret 11 | annotations = { 12 | "kubernetes.io/service-account.name" = "${kubernetes_service_account.argocd_manager_sa.metadata.0.name}" 13 | } 14 | } 15 | type = "kubernetes.io/service-account-token" 16 | } 17 | 18 | resource "kubernetes_cluster_role_binding" "argocd_manager_binding" { 19 | metadata { 20 | name = var.argocd-manager-binding 21 | } 22 | 23 | role_ref { 24 | api_group = "rbac.authorization.k8s.io" 25 | kind = "ClusterRole" 26 | name = "cluster-admin" 27 | } 28 | 29 | subject { 30 | kind = "ServiceAccount" 31 | name = kubernetes_service_account.argocd_manager_sa.metadata.0.name 32 | namespace = kubernetes_service_account.argocd_manager_sa.metadata.0.namespace 33 | } 34 | } 35 | 36 | data "kubernetes_secret" "argocd_manager_secret" { 37 | metadata { 38 | name = kubernetes_secret.argocd_manager_secret.metadata.0.name 39 | } 40 | } 41 | 42 | resource "argocd_cluster" "new_cluster" { 43 | provider = argocd.argocd_server 44 | server = var.new_cluster_server_addr 45 | 46 | config { 47 | bearer_token = "${lookup(data.kubernetes_secret.argocd_manager_secret.data, "token")}" 48 | 49 | tls_client_config { 50 | ca_data = "${lookup(data.kubernetes_secret.argocd_manager_secret.data, "ca.crt")}" 51 | insecure = false 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /v08-argocd-add-cluster/add-cluster/add-cluster-using-terraform/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | kubernetes = { 4 | source = "hashicorp/kubernetes" 5 | version = "2.23.0" 6 | } 7 | argocd = { 8 | source = "oboukili/argocd" 9 | version = "6.0.3" 10 | } 11 | } 12 | } 13 | 14 | provider "kubernetes" { 15 | config_path = var.config_path 16 | config_context = var.config_context 17 | } 18 | 19 | provider "argocd" { 20 | alias = "argocd_server" 21 | server_addr = var.server_addr 22 | username = var.username 23 | password = var.password 24 | insecure = var.insecure 25 | } -------------------------------------------------------------------------------- /v08-argocd-add-cluster/add-cluster/add-cluster-using-terraform/terraform.tfvars: -------------------------------------------------------------------------------- 1 | server_addr = "localhost:32073" 2 | username = "admin" 3 | password = "vGiZPEnfe9wEToPc" 4 | insecure = true 5 | sa_name = "argocd-manager-sa" 6 | sa_namespace = "default" 7 | config_path = "~/.kube/config" 8 | config_context = "new-cluster-context" 9 | argocd-manager-binding = "argocd-manager-binding" 10 | argocd-manager-secret = "argocd-manager-secret" 11 | argocd_secret_cluster = "argocd-secret-cluster" 12 | secret_labels = { 13 | "argocd.argoproj.io/secret-type" = "cluster" 14 | } 15 | new_cluster = "external" 16 | new_cluster_server_addr = "https://192.168.64.93:6443" -------------------------------------------------------------------------------- /v08-argocd-add-cluster/add-cluster/add-cluster-using-terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "server_addr" { 2 | type = string 3 | description = "The server address" 4 | } 5 | 6 | variable "username" { 7 | type = string 8 | description = "The Username" 9 | } 10 | 11 | variable "password" { 12 | type = string 13 | description = "The Password" 14 | } 15 | 16 | variable "insecure" { 17 | type = bool 18 | description = "The Connection Insecure flag" 19 | } 20 | 21 | variable "sa_name" { 22 | type = string 23 | description = "The name of argocd serviceaccount" 24 | } 25 | 26 | variable "sa_namespace" { 27 | type = string 28 | description = "The namespace of argocd serviceaccount" 29 | } 30 | 31 | variable "config_path" { 32 | type = string 33 | description = "The path of kube config" 34 | } 35 | 36 | variable "config_context" { 37 | type = string 38 | description = "The context in kube config" 39 | } 40 | 41 | variable "argocd-manager-binding" { 42 | type = string 43 | description = "The name of argocd manager clusterrole binding" 44 | } 45 | 46 | variable "argocd-manager-secret" { 47 | type = string 48 | description = "The name of argocd manager secret" 49 | } 50 | 51 | variable "argocd_secret_cluster" { 52 | type = string 53 | description = "The name of argocd secret cluster" 54 | } 55 | 56 | variable "secret_labels" { 57 | type = map(string) 58 | description = "The Labels of argocd manager secret" 59 | } 60 | 61 | variable "new_cluster" { 62 | type = string 63 | description = "The name of new cluster" 64 | } 65 | 66 | variable "new_cluster_server_addr" { 67 | type = string 68 | description = "The name of new cluster server address" 69 | } -------------------------------------------------------------------------------- /v08-argocd-add-cluster/tracking-strategies/git.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: git-tracking-strategies 5 | namespace: argocd 6 | spec: 7 | destination: 8 | namespace: git-tracking-strategies 9 | name: in-cluster 10 | project: default 11 | source: 12 | path: v03-argocd-applications/directoryOfmanifests 13 | repoURL: "https://github.com/devopshobbies/argocd-tutorial.git" 14 | targetRevision: # HEAD/Branch tracking ex: HEAD/main || tag tracking ex: v1 || commit pinning ex: 9814933 15 | syncPolicy: 16 | syncOptions: 17 | - CreateNamespace=true 18 | automated: {} 19 | -------------------------------------------------------------------------------- /v08-argocd-add-cluster/tracking-strategies/helm.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: helm-tracking-strategies 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | chart: sealed-secrets 10 | repoURL: https://bitnami-labs.github.io/sealed-secrets 11 | targetRevision: # use the version number ex: 1.16.1 || use a range ex: 1.* or 1.2.* or >=1.2.0 <1.3.0 || use the latest version ex: '*' 12 | helm: 13 | releaseName: sealed-secrets 14 | destination: 15 | server: "https://kubernetes.default.svc" 16 | namespace: helm-tracking-strategies 17 | syncPolicy: 18 | syncOptions: 19 | - CreateNamespace=true 20 | automated: {} 21 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/cluster-generator/cluster-generator-ex1.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: cluster-generator-ex1 5 | namespace: argocd 6 | spec: 7 | generators: 8 | - clusters: {} 9 | template: 10 | metadata: 11 | name: '{{name}}-application' 12 | spec: 13 | project: "default" 14 | source: 15 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 16 | targetRevision: main 17 | path: v03-argocd-applications/helm/nginx 18 | destination: 19 | server: '{{server}}' 20 | namespace: cluster-generator 21 | syncPolicy: 22 | automated: {} 23 | syncOptions: 24 | - CreateNamespace=true -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/cluster-generator/cluster-generator-ex2.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: cluster-generator-ex2 5 | namespace: argocd 6 | spec: 7 | generators: 8 | - clusters: 9 | selector: 10 | matchLabels: 11 | argocd.argoproj.io/secret-type: cluster 12 | environment: staging 13 | template: 14 | metadata: 15 | name: '{{name}}-application' 16 | spec: 17 | project: "default" 18 | source: 19 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 20 | targetRevision: main 21 | path: v03-argocd-applications/helm/nginx 22 | destination: 23 | server: '{{server}}' 24 | namespace: cluster-generator 25 | syncPolicy: 26 | automated: {} 27 | syncOptions: 28 | - CreateNamespace=true -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/cluster-generator/cluster-generator-ex3.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: cluster-generator-ex3 5 | namespace: argocd 6 | spec: 7 | generators: 8 | - clusters: 9 | selector: 10 | matchLabels: 11 | environment: staging 12 | values: 13 | path: helm/nginx 14 | namespace: staging-ns 15 | - clusters: 16 | selector: 17 | matchLabels: 18 | environment: pre-staging 19 | values: 20 | path: directoryOfmanifests 21 | namespace: pre-staging-ns 22 | template: 23 | metadata: 24 | name: '{{name}}-application' 25 | spec: 26 | project: "default" 27 | source: 28 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 29 | targetRevision: main 30 | path: v03-argocd-applications/{{values.path}} 31 | destination: 32 | server: '{{server}}' 33 | namespace: '{{values.namespace}}' 34 | syncPolicy: 35 | automated: {} 36 | syncOptions: 37 | - CreateNamespace=true -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/cluster-generator/cluster-generator-ex4.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: cluster-generator 5 | namespace: argocd 6 | spec: 7 | generators: 8 | - clusters: 9 | selector: 10 | matchExpressions: 11 | - key: argocd.argoproj.io/kubernetes-version # the label argocd.argoproj.io/auto-label-cluster-info needs to be set to true on the cluster secret. 12 | operator: In 13 | values: 14 | - "1.28" 15 | - "1.31" 16 | template: 17 | metadata: 18 | name: '{{name}}-application' 19 | spec: 20 | project: "default" 21 | source: 22 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 23 | targetRevision: main 24 | path: v03-argocd-applications/helm/nginx 25 | destination: 26 | server: '{{server}}' 27 | namespace: prod 28 | syncPolicy: 29 | automated: {} 30 | syncOptions: 31 | - CreateNamespace=true 32 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/cluster-config/pre-staging/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "cluster": { 3 | "owner": "mohammad", 4 | "name": "pre-staging", 5 | "path": "v03-argocd-applications/directoryOfmanifests", 6 | "source_type": "directoryOfManifests", 7 | "address": "https://kubernetes.default.svc", 8 | "namespace": "pre-staging-ns" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/cluster-config/staging/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "cluster": { 3 | "owner": "mohammad", 4 | "name": "staging", 5 | "path": "v03-argocd-applications/helm/nginx", 6 | "source_type": "helm", 7 | "address": "https://192.168.226.93:6443", 8 | "namespace": "staging-ns" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/directories-subtype/git-generator-ex1.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: git-directories-generator-ex1 5 | namespace: argocd 6 | spec: 7 | generators: 8 | - git: 9 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 10 | revision: main 11 | directories: 12 | - path: v09-argocd-applicationSet-1/git-generator/resources/* 13 | template: 14 | metadata: 15 | name: '{{path.basename}}-application' 16 | spec: 17 | project: default 18 | source: 19 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 20 | targetRevision: main 21 | path: '{{path}}' 22 | destination: 23 | server: https://kubernetes.default.svc 24 | namespace: '{{path.basename}}-ns' 25 | syncPolicy: 26 | automated: {} 27 | syncOptions: 28 | - CreateNamespace=true 29 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/directories-subtype/git-generator-ex2.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: git-directories-generator-ex2 5 | namespace: argocd 6 | spec: 7 | generators: 8 | - git: 9 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 10 | revision: main 11 | directories: 12 | - path: v09-argocd-applicationSet-1/git-generator/resources/* 13 | - path: v09-argocd-applicationSet-1/git-generator/resources/nginx-manifests 14 | exclude: true 15 | template: 16 | metadata: 17 | name: '{{path.basename}}-application' 18 | spec: 19 | project: default 20 | source: 21 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 22 | targetRevision: main 23 | path: '{{path}}' 24 | destination: 25 | server: https://kubernetes.default.svc 26 | namespace: '{{path.basename}}-ns' 27 | syncPolicy: 28 | automated: {} 29 | syncOptions: 30 | - CreateNamespace=true 31 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/files-subtype/git-generator-ex1.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: git-files-generator-ex1 5 | namespace: argocd 6 | spec: 7 | generators: 8 | - git: 9 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 10 | revision: main 11 | files: 12 | - path: v09-argocd-applicationSet-1/git-generator/cluster-config/**/config.json 13 | template: 14 | metadata: 15 | name: '{{cluster.name}}-application' 16 | spec: 17 | project: default 18 | source: 19 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 20 | targetRevision: main 21 | path: '{{cluster.path}}' 22 | destination: 23 | server: '{{cluster.address}}' 24 | namespace: '{{cluster.namespace}}' 25 | syncPolicy: 26 | automated: {} 27 | syncOptions: 28 | - CreateNamespace=true 29 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: nginx 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/custom-values.yaml: -------------------------------------------------------------------------------- 1 | replicaCount: 4 2 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "nginx.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "nginx.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "nginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "nginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "nginx.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "nginx.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "nginx.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "nginx.labels" -}} 37 | helm.sh/chart: {{ include "nginx.chart" . }} 38 | {{ include "nginx.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "nginx.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "nginx.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "nginx.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "nginx.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "nginx.fullname" . }} 5 | labels: 6 | {{- include "nginx.labels" . | nindent 4 }} 7 | spec: 8 | {{- if not .Values.autoscaling.enabled }} 9 | replicas: {{ .Values.replicaCount }} 10 | {{- end }} 11 | selector: 12 | matchLabels: 13 | {{- include "nginx.selectorLabels" . | nindent 6 }} 14 | template: 15 | metadata: 16 | {{- with .Values.podAnnotations }} 17 | annotations: 18 | {{- toYaml . | nindent 8 }} 19 | {{- end }} 20 | labels: 21 | {{- include "nginx.selectorLabels" . | nindent 8 }} 22 | spec: 23 | {{- with .Values.imagePullSecrets }} 24 | imagePullSecrets: 25 | {{- toYaml . | nindent 8 }} 26 | {{- end }} 27 | serviceAccountName: {{ include "nginx.serviceAccountName" . }} 28 | securityContext: 29 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 30 | containers: 31 | - name: {{ .Chart.Name }} 32 | securityContext: 33 | {{- toYaml .Values.securityContext | nindent 12 }} 34 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 35 | imagePullPolicy: {{ .Values.image.pullPolicy }} 36 | ports: 37 | - name: http 38 | containerPort: {{ .Values.service.port }} 39 | protocol: TCP 40 | livenessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | readinessProbe: 45 | httpGet: 46 | path: / 47 | port: http 48 | resources: 49 | {{- toYaml .Values.resources | nindent 12 }} 50 | {{- with .Values.nodeSelector }} 51 | nodeSelector: 52 | {{- toYaml . | nindent 8 }} 53 | {{- end }} 54 | {{- with .Values.affinity }} 55 | affinity: 56 | {{- toYaml . | nindent 8 }} 57 | {{- end }} 58 | {{- with .Values.tolerations }} 59 | tolerations: 60 | {{- toYaml . | nindent 8 }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "nginx.fullname" . }} 6 | labels: 7 | {{- include "nginx.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "nginx.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | target: 21 | type: Utilization 22 | averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 23 | {{- end }} 24 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 25 | - type: Resource 26 | resource: 27 | name: memory 28 | target: 29 | type: Utilization 30 | averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "nginx.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "nginx.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 51 | service: 52 | name: {{ $fullName }} 53 | port: 54 | number: {{ $svcPort }} 55 | {{- else }} 56 | serviceName: {{ $fullName }} 57 | servicePort: {{ $svcPort }} 58 | {{- end }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "nginx.fullname" . }} 5 | labels: 6 | {{- include "nginx.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "nginx.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "nginx.serviceAccountName" . }} 6 | labels: 7 | {{- include "nginx.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "nginx.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "nginx.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "nginx.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-helm/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for nginx. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 2 6 | 7 | image: 8 | repository: nginx 9 | pullPolicy: IfNotPresent 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: "" 12 | 13 | imagePullSecrets: [] 14 | nameOverride: "" 15 | fullnameOverride: "" 16 | 17 | serviceAccount: 18 | # Specifies whether a service account should be created 19 | create: true 20 | # Annotations to add to the service account 21 | annotations: {} 22 | # The name of the service account to use. 23 | # If not set and create is true, a name is generated using the fullname template 24 | name: "" 25 | 26 | podAnnotations: {} 27 | 28 | podSecurityContext: {} 29 | # fsGroup: 2000 30 | 31 | securityContext: {} 32 | # capabilities: 33 | # drop: 34 | # - ALL 35 | # readOnlyRootFilesystem: true 36 | # runAsNonRoot: true 37 | # runAsUser: 1000 38 | 39 | service: 40 | type: ClusterIP 41 | port: 80 42 | 43 | ingress: 44 | enabled: false 45 | className: "" 46 | annotations: {} 47 | # kubernetes.io/ingress.class: nginx 48 | # kubernetes.io/tls-acme: "true" 49 | hosts: 50 | - host: chart-example.local 51 | paths: 52 | - path: / 53 | pathType: ImplementationSpecific 54 | tls: [] 55 | # - secretName: chart-example-tls 56 | # hosts: 57 | # - chart-example.local 58 | 59 | resources: {} 60 | # We usually recommend not to specify default resources and to leave this as a conscious 61 | # choice for the user. This also increases chances charts run on environments with little 62 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 63 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 64 | # limits: 65 | # cpu: 100m 66 | # memory: 128Mi 67 | # requests: 68 | # cpu: 100m 69 | # memory: 128Mi 70 | 71 | autoscaling: 72 | enabled: false 73 | minReplicas: 1 74 | maxReplicas: 100 75 | targetCPUUtilizationPercentage: 80 76 | # targetMemoryUtilizationPercentage: 80 77 | 78 | nodeSelector: {} 79 | 80 | tolerations: [] 81 | 82 | affinity: {} 83 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-manifests/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx 5 | labels: 6 | helm.sh/chart: nginx-0.1.0 7 | app.kubernetes.io/name: nginx 8 | app.kubernetes.io/instance: nginx 9 | app.kubernetes.io/version: "1.16.0" 10 | app.kubernetes.io/managed-by: Helm 11 | spec: 12 | replicas: 3 13 | selector: 14 | matchLabels: 15 | app.kubernetes.io/name: nginx 16 | app.kubernetes.io/instance: nginx 17 | template: 18 | metadata: 19 | labels: 20 | app.kubernetes.io/name: nginx 21 | app.kubernetes.io/instance: nginx 22 | spec: 23 | serviceAccountName: nginx 24 | securityContext: 25 | {} 26 | containers: 27 | - name: nginx 28 | securityContext: 29 | {} 30 | image: "nginx:1.16.0" 31 | imagePullPolicy: IfNotPresent 32 | ports: 33 | - name: http 34 | containerPort: 80 35 | protocol: TCP 36 | livenessProbe: 37 | httpGet: 38 | path: / 39 | port: http 40 | readinessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | resources: 45 | {} 46 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-manifests/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx 5 | annotations: 6 | argocd.argoproj.io/sync-options: Replace=true 7 | labels: 8 | helm.sh/chart: nginx-0.1.0 9 | app.kubernetes.io/name: nginx 10 | app.kubernetes.io/instance: nginx 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | spec: 14 | type: ClusterIP 15 | ports: 16 | - port: 80 17 | targetPort: http 18 | protocol: TCP 19 | name: http 20 | selector: 21 | app.kubernetes.io/name: nginx 22 | app.kubernetes.io/instance: nginx 23 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-manifests/serviceaccount.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: nginx 5 | annotations: 6 | argocd.argoproj.io/sync-options: Prune=false 7 | labels: 8 | helm.sh/chart: nginx-0.1.0 9 | app.kubernetes.io/name: nginx 10 | app.kubernetes.io/instance: nginx 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-manifests/sub-directory/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-sub-directory 5 | # annotations: 6 | # argocd.argoproj.io/sync-options: Prune=false 7 | labels: 8 | helm.sh/chart: nginx-0.1.0 9 | app.kubernetes.io/name: nginx 10 | app.kubernetes.io/instance: nginx 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | spec: 14 | type: ClusterIP 15 | ports: 16 | - port: 80 17 | targetPort: http 18 | protocol: TCP 19 | name: http 20 | selector: 21 | app.kubernetes.io/name: nginx 22 | app.kubernetes.io/instance: nginx 23 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/git-generator/resources/nginx-manifests/test-connection.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "nginx-test-connection" 5 | labels: 6 | helm.sh/chart: nginx-0.1.0 7 | app.kubernetes.io/name: nginx 8 | app.kubernetes.io/instance: nginx 9 | app.kubernetes.io/version: "1.16.0" 10 | app.kubernetes.io/managed-by: Helm 11 | annotations: 12 | "helm.sh/hook": test 13 | spec: 14 | containers: 15 | - name: wget 16 | image: busybox 17 | command: ['wget'] 18 | args: ['nginx:80'] 19 | restartPolicy: Never 20 | -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/list-generator/list-generator-ex1.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: list-generator-ex1 5 | namespace: argocd 6 | spec: 7 | generators: 8 | - list: 9 | elements: 10 | - cluster: local 11 | url: https://kubernetes.default.svc 12 | path: directoryOfmanifests 13 | - cluster: external 14 | url: https://192.168.64.93:6443 15 | path: helm/nginx 16 | template: 17 | metadata: 18 | name: '{{cluster}}-application' 19 | spec: 20 | project: default 21 | source: 22 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 23 | targetRevision: main 24 | path: v03-argocd-applications/{{path}} 25 | destination: 26 | server: '{{url}}' 27 | namespace: '{{cluster}}' 28 | syncPolicy: 29 | automated: {} 30 | syncOptions: 31 | - CreateNamespace=true -------------------------------------------------------------------------------- /v09-argocd-applicationSet-1/list-generator/list-generator-ex2.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: list-generator-ex2 5 | namespace: argocd 6 | spec: 7 | generators: 8 | - list: 9 | elements: 10 | - environment: pre-staging 11 | server: https://kubernetes.default.svc 12 | path: directoryOfmanifests 13 | - environment: staging 14 | server: https://192.168.64.93:6443 15 | path: helm/nginx 16 | template: 17 | metadata: 18 | name: '{{environment}}-application' 19 | spec: 20 | project: default 21 | source: 22 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 23 | targetRevision: main 24 | path: v03-argocd-applications/{{path}} 25 | destination: 26 | server: '{{server}}' 27 | namespace: '{{environment}}' 28 | syncPolicy: 29 | automated: {} 30 | syncOptions: 31 | - CreateNamespace=true -------------------------------------------------------------------------------- /v10-argocd-applicationSet-2/matrix-generator/matrix-generator-ex1.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: matrix-generator-ex1 5 | spec: 6 | generators: 7 | - matrix: 8 | generators: 9 | - git: 10 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 11 | revision: main 12 | directories: 13 | - path: v09-argocd-applicationSet-1/git-generator/resources/* 14 | - clusters: {} 15 | template: 16 | metadata: 17 | name: '{{path.basename}}-{{name}}' 18 | spec: 19 | project: default 20 | source: 21 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 22 | targetRevision: main 23 | path: '{{path}}' 24 | destination: 25 | server: '{{server}}' 26 | namespace: '{{metadata.labels.environment}}' 27 | syncPolicy: 28 | automated: {} 29 | syncOptions: 30 | - CreateNamespace=true -------------------------------------------------------------------------------- /v10-argocd-applicationSet-2/matrix-generator/matrix-generator-ex2.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: matrix-generator-ex2 5 | spec: 6 | generators: 7 | - matrix: 8 | generators: 9 | - git: 10 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 11 | revision: main 12 | directories: 13 | - path: v09-argocd-applicationSet-1/git-generator/resources/* 14 | - list: 15 | elements: 16 | - environment: pre-staging 17 | server: https://kubernetes.default.svc 18 | - environment: staging 19 | server: https://192.168.226.93:6443 20 | template: 21 | metadata: 22 | name: '{{path.basename}}-{{environment}}' 23 | spec: 24 | project: default 25 | source: 26 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 27 | targetRevision: main 28 | path: '{{path}}' 29 | destination: 30 | server: '{{server}}' 31 | namespace: '{{environment}}' 32 | syncPolicy: 33 | automated: {} 34 | syncOptions: 35 | - CreateNamespace=true -------------------------------------------------------------------------------- /v10-argocd-applicationSet-2/matrix-generator/matrix-generator-ex3.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: matrix-generator-ex3 5 | spec: 6 | generators: 7 | - matrix: 8 | generators: 9 | - git: 10 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 11 | revision: main 12 | files: 13 | - path: v09-argocd-applicationSet-1/git-generator/cluster-config/**/config.json 14 | - clusters: 15 | selector: 16 | matchLabels: 17 | argocd.argoproj.io/secret-type: cluster 18 | environment: '{{cluster.name}}' 19 | template: 20 | metadata: 21 | name: '{{name}}-application' 22 | spec: 23 | project: default 24 | source: 25 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 26 | targetRevision: main 27 | path: '{{cluster.path}}' 28 | destination: 29 | server: '{{server}}' 30 | namespace: '{{metadata.labels.environment}}' 31 | syncPolicy: 32 | automated: {} 33 | syncOptions: 34 | - CreateNamespace=true -------------------------------------------------------------------------------- /v10-argocd-applicationSet-2/merge-generator/merge-generator-ex1.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ApplicationSet 3 | metadata: 4 | name: merge-generator-ex1 5 | spec: 6 | generators: 7 | - merge: 8 | mergeKeys: 9 | - server 10 | generators: 11 | - clusters: 12 | values: 13 | tag: '1.23' 14 | replicas: '1' 15 | - clusters: 16 | selector: 17 | matchLabels: 18 | environment: 'staging' 19 | values: 20 | tag: '1.24' 21 | - list: 22 | elements: 23 | - server: https://kubernetes.default.svc 24 | values.replicas: '3' 25 | template: 26 | metadata: 27 | name: '{{name}}-application' 28 | spec: 29 | project: default 30 | source: 31 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 32 | targetRevision: main 33 | path: v03-argocd-applications/helm/nginx 34 | helm: 35 | parameters: 36 | - name: "image.tag" 37 | value: '{{values.tag}}' 38 | - name: "replicaCount" 39 | value: '{{values.replicas}}' 40 | destination: 41 | server: '{{server}}' 42 | namespace: '{{metadata.labels.environment}}' 43 | syncPolicy: 44 | automated: {} 45 | syncOptions: 46 | - CreateNamespace=true -------------------------------------------------------------------------------- /v12-argo-rollouts-blue-green/blue-green-app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim-buster 2 | WORKDIR /devops-hobbies 3 | ENV FLASK_APP blue-green.py 4 | COPY requirements.txt . 5 | RUN pip3 install -r requirements.txt 6 | COPY blue-green.py . 7 | COPY templates ./templates 8 | CMD ["flask", "run", "--host=0.0.0.0"] -------------------------------------------------------------------------------- /v12-argo-rollouts-blue-green/blue-green-app/blue-green.py: -------------------------------------------------------------------------------- 1 | from os import environ 2 | from flask import Flask, render_template 3 | app = Flask(__name__) 4 | 5 | @app.route('/') 6 | def home(): 7 | return render_template(environ['html_name']) 8 | if __name__ == '__main__': 9 | app.run() -------------------------------------------------------------------------------- /v12-argo-rollouts-blue-green/blue-green-app/requirements.txt: -------------------------------------------------------------------------------- 1 | blinker==1.6.2 2 | click==8.1.7 3 | flask==3.0.0 4 | importlib-metadata==6.8.0 5 | itsdangerous==2.1.2 6 | Jinja2==3.1.2 7 | MarkupSafe==2.1.3 8 | werkzeug==3.0.0 9 | zipp==3.17.0 -------------------------------------------------------------------------------- /v12-argo-rollouts-blue-green/blue-green-app/templates/app-v1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Blue-Sky Background - Version 1 5 | 18 | 19 | 20 |
Argo-Rollouts Course by DevOps Hobbies
21 |
Version 1
22 | 23 | -------------------------------------------------------------------------------- /v12-argo-rollouts-blue-green/blue-green-app/templates/app-v2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Green Background - Version 2 5 | 18 | 19 | 20 |
Argo-Rollouts Course by DevOps Hobbies
21 |
Version 2
22 | 23 | -------------------------------------------------------------------------------- /v12-argo-rollouts-blue-green/blue-green-manifests/ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: blue-green-ingress 5 | spec: 6 | ingressClassName: nginx 7 | rules: 8 | - host: blue-green.demo 9 | http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: rollout-bluegreen-active 16 | port: 17 | number: 5000 18 | -------------------------------------------------------------------------------- /v12-argo-rollouts-blue-green/blue-green-manifests/rollout.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Rollout 3 | metadata: 4 | name: blue-green-deployment 5 | spec: 6 | replicas: 4 7 | selector: 8 | matchLabels: 9 | app: blue-green-deployment 10 | template: 11 | metadata: 12 | labels: 13 | app: blue-green-deployment 14 | spec: 15 | containers: 16 | - name: blue-green 17 | image: blue-green 18 | imagePullPolicy: Never 19 | env: 20 | - name: html_name 21 | value: "app-v1.html" 22 | ports: 23 | - containerPort: 5000 24 | strategy: 25 | blueGreen: 26 | activeService: rollout-bluegreen-active 27 | previewService: rollout-bluegreen-preview 28 | autoPromotionEnabled: false 29 | # abortScaleDownDelaySeconds: 10 30 | # autoPromotionEnabled: false 31 | # scaleDownDelaySeconds: 60 32 | # previewReplicaCount: 2 33 | # autoPromotionSeconds: 20 34 | --- 35 | kind: Service 36 | apiVersion: v1 37 | metadata: 38 | name: rollout-bluegreen-active 39 | spec: 40 | selector: 41 | app: blue-green-deployment 42 | ports: 43 | - protocol: TCP 44 | port: 5000 45 | targetPort: 5000 46 | 47 | --- 48 | kind: Service 49 | apiVersion: v1 50 | metadata: 51 | name: rollout-bluegreen-preview 52 | spec: 53 | selector: 54 | app: blue-green-deployment 55 | ports: 56 | - protocol: TCP 57 | port: 5000 58 | targetPort: 5000 59 | -------------------------------------------------------------------------------- /v13-argo-rollouts-canary/rolling-update-ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: rolling-update 5 | spec: 6 | ingressClassName: nginx 7 | rules: 8 | - host: rolling-update.demo 9 | http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: rolling-update 16 | port: 17 | number: 5000 18 | -------------------------------------------------------------------------------- /v13-argo-rollouts-canary/rolling-update.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Rollout 3 | metadata: 4 | name: rolling-update 5 | spec: 6 | replicas: 5 7 | strategy: 8 | canary: 9 | maxSurge: 2 10 | maxUnavailable: 2 11 | selector: 12 | matchLabels: 13 | app: rolling-update 14 | template: 15 | metadata: 16 | labels: 17 | app: rolling-update 18 | spec: 19 | containers: 20 | - name: rolling-update 21 | image: canary # This is the same image that we built in the previous session (v12-argo-rollouts-blue-green) , I just re-tagged it 22 | imagePullPolicy: Never 23 | env: 24 | - name: html_name 25 | value: "app-v1.html" 26 | ports: 27 | - containerPort: 5000 28 | --- 29 | apiVersion: v1 30 | kind: Service 31 | metadata: 32 | name: rolling-update 33 | spec: 34 | ports: 35 | - port: 5000 36 | targetPort: 5000 37 | selector: 38 | app: rolling-update 39 | -------------------------------------------------------------------------------- /v13-argo-rollouts-canary/rollouts-setweight-ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: rolling-update 5 | spec: 6 | ingressClassName: nginx 7 | rules: 8 | - host: rollouts-setweight.demo 9 | http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: rollouts-setweight 16 | port: 17 | number: 5000 18 | -------------------------------------------------------------------------------- /v13-argo-rollouts-canary/rollouts-setweight.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Rollout 3 | metadata: 4 | name: rollouts-setweight 5 | spec: 6 | replicas: 5 7 | strategy: 8 | canary: 9 | steps: 10 | - setWeight: 20 11 | - pause: {} 12 | - setWeight: 40 13 | - pause: {duration: 10s} 14 | - setWeight: 60 15 | - pause: {duration: 20s} 16 | - setWeight: 80 17 | - pause: {duration: 1m} 18 | selector: 19 | matchLabels: 20 | app: rollouts-setweight 21 | template: 22 | metadata: 23 | labels: 24 | app: rollouts-setweight 25 | spec: 26 | containers: 27 | - name: rollouts-setweight 28 | image: canary # This is the same image that we built in the previous session (v12-argo-rollouts-blue-green) , I just re-tagged it 29 | imagePullPolicy: Never 30 | env: 31 | - name: html_name 32 | value: "app-v1.html" 33 | ports: 34 | - containerPort: 5000 35 | --- 36 | apiVersion: v1 37 | kind: Service 38 | metadata: 39 | name: rollouts-setweight 40 | spec: 41 | ports: 42 | - port: 5000 43 | targetPort: 5000 44 | selector: 45 | app: rollouts-setweight 46 | -------------------------------------------------------------------------------- /v13-argo-rollouts-canary/rollouts-traffic-management-ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: rollouts-traffic-management 5 | spec: 6 | ingressClassName: nginx 7 | rules: 8 | - host: rollouts-traffic-management.demo 9 | http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: stable-service 16 | port: 17 | number: 5000 18 | -------------------------------------------------------------------------------- /v13-argo-rollouts-canary/rollouts-traffic-management.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Rollout 3 | metadata: 4 | name: rollouts-traffic-management 5 | spec: 6 | replicas: 5 7 | strategy: 8 | canary: 9 | # dynamicStableScale: true 10 | # abortScaleDownDelaySeconds: 20 11 | canaryService: canary-service 12 | stableService: stable-service 13 | trafficRouting: 14 | nginx: 15 | stableIngress: rollouts-traffic-management 16 | steps: 17 | - setWeight: 20 # Using Setweight Only 18 | - pause: {} 19 | # .................... 20 | # - setCanaryScale: # Using SetCanaryScale with SetWeight 21 | # weight: 40 22 | # - setWeight: 40 23 | # - pause: {} 24 | selector: 25 | matchLabels: 26 | app: rollouts-traffic-management 27 | template: 28 | metadata: 29 | labels: 30 | app: rollouts-traffic-management 31 | spec: 32 | containers: 33 | - name: rollouts-traffic-management 34 | image: canary # This is the same image that we built in the previous session (v12-argo-rollouts-blue-green) , I just re-tagged it 35 | imagePullPolicy: Never 36 | env: 37 | - name: html_name 38 | value: "app-v1.html" 39 | ports: 40 | - containerPort: 5000 41 | --- 42 | apiVersion: v1 43 | kind: Service 44 | metadata: 45 | name: canary-service 46 | spec: 47 | ports: 48 | - port: 5000 49 | targetPort: 5000 50 | selector: 51 | app: rollouts-traffic-management 52 | --- 53 | apiVersion: v1 54 | kind: Service 55 | metadata: 56 | name: stable-service 57 | spec: 58 | ports: 59 | - port: 5000 60 | targetPort: 5000 61 | selector: 62 | app: rollouts-traffic-management 63 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/blue-green-analysis/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | RUN apk add --no-cache bash curl 3 | workdir /devops-hobbies 4 | COPY app-success-rate.sh . 5 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/blue-green-analysis/app-success-rate.sh: -------------------------------------------------------------------------------- 1 | ### WE are using curl command to get success_rate of active and preview services in blue-green strategy 2 | ### $service_url variable will be initialized in kubernetes job as an container environment variable 3 | ### The Value of $service_url variable will be one of the active or preview services names 4 | #!/bin/bash 5 | success=0 6 | failure=0 7 | ################## 8 | for i in {1..5} 9 | do 10 | response=$(curl -s -o /dev/null -w "%{http_code}" $service_url) 11 | if [ "$response" -eq 200 ] 12 | then 13 | ((success++)) 14 | else 15 | ((failure++)) 16 | fi 17 | sleep 5s 18 | done 19 | ################## 20 | echo "Success rate: $success/5" 21 | ################## 22 | if [ "$success" -ge 3 ] 23 | then 24 | exit 0 25 | else 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/blue-green-analysis/ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: blue-green-ingress 5 | spec: 6 | ingressClassName: nginx 7 | rules: 8 | - host: blue-green.demo 9 | http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: rollout-bluegreen-active 16 | port: 17 | number: 5000 18 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/blue-green-analysis/post-promotion-analysis.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: AnalysisTemplate 3 | metadata: 4 | name: success-rate-post ######## post-promotion-analysis 5 | spec: 6 | args: 7 | - name: service-port 8 | value: "5000" 9 | - name: service-namespace 10 | metrics: 11 | - name: success-rate-post 12 | provider: 13 | job: 14 | metadata: 15 | labels: 16 | analysis: post-promotion # labels defined here will be copied to the Job object 17 | spec: 18 | backoffLimit: 0 19 | template: 20 | spec: 21 | containers: 22 | - name: success-rate-post 23 | image: analysis 24 | imagePullPolicy: Never 25 | env: 26 | - name: service_url 27 | value: "http://rollout-bluegreen-active.{{args.service-namespace}}.svc.cluster.local:{{args.service-port}}" 28 | command: ["/bin/bash", "-c"] 29 | args: 30 | - ./app-success-rate.sh 31 | restartPolicy: Never 32 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/blue-green-analysis/pre-promotion-analysis.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: AnalysisTemplate 3 | metadata: 4 | name: success-rate-pre ######## pre-promotion-analysis 5 | spec: 6 | args: 7 | - name: service-port 8 | value: "5000" 9 | - name: service-namespace 10 | metrics: 11 | - name: success-rate-pre 12 | provider: 13 | job: 14 | metadata: 15 | labels: 16 | analysis: pre-promotion # labels defined here will be copied to the Job object 17 | spec: 18 | backoffLimit: 0 19 | template: 20 | spec: 21 | containers: 22 | - name: success-rate-pre 23 | image: analysis ##### this is the same image that we built to get success_rate . you can find related files (Dockerfile, app-success-rate.sh) in the current directory 24 | imagePullPolicy: Never 25 | env: 26 | - name: service_url 27 | value: "http://rollout-bluegreen-preview.{{args.service-namespace}}.svc.cluster.local:{{args.service-port}}" 28 | command: ["/bin/bash", "-c"] 29 | args: 30 | - ./app-success-rate.sh 31 | restartPolicy: Never 32 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/blue-green-analysis/rollout-with-analysis.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Rollout 3 | metadata: 4 | name: blue-green-deployment 5 | spec: 6 | replicas: 4 7 | selector: 8 | matchLabels: 9 | app: blue-green-deployment 10 | template: 11 | metadata: 12 | labels: 13 | app: blue-green-deployment 14 | spec: 15 | containers: 16 | - name: blue-green 17 | image: blue-green 18 | imagePullPolicy: Never 19 | env: 20 | - name: html_name 21 | value: "app-v1.html" 22 | ports: 23 | - containerPort: 5000 24 | strategy: 25 | blueGreen: 26 | activeService: rollout-bluegreen-active 27 | previewService: rollout-bluegreen-preview 28 | autoPromotionEnabled: true 29 | prePromotionAnalysis: #### Pre-Promotion Analysis 30 | templates: 31 | - templateName: success-rate-pre 32 | args: 33 | - name: service-namespace 34 | value: blue-green 35 | # postPromotionAnalysis: #### Post-Promotion Analysis 36 | # templates: 37 | # - templateName: success-rate-post 38 | # args: 39 | # - name: service-namespace 40 | # value: blue-green 41 | # abortScaleDownDelaySeconds: 10 42 | # scaleDownDelaySeconds: 60 43 | # previewReplicaCount: 2 44 | # autoPromotionSeconds: 70 45 | --- 46 | kind: Service 47 | apiVersion: v1 48 | metadata: 49 | name: rollout-bluegreen-active 50 | spec: 51 | selector: 52 | app: blue-green-deployment 53 | ports: 54 | - protocol: TCP 55 | port: 5000 56 | targetPort: 5000 57 | 58 | --- 59 | kind: Service 60 | apiVersion: v1 61 | metadata: 62 | name: rollout-bluegreen-preview 63 | spec: 64 | selector: 65 | app: blue-green-deployment 66 | ports: 67 | - protocol: TCP 68 | port: 5000 69 | targetPort: 5000 70 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/canary-analysis/analysis-app.py: -------------------------------------------------------------------------------- 1 | ### WE are using a flask script to get the url of the application and try to connect to it 5 times at 5 seconds intervals and returns one of the true or false values based on "200 response_code" in a json format, if the success_rate is 80% or more , it returns "true" value, Otherwise it returns "false" value 2 | from flask import Flask, request, jsonify 3 | import requests, time 4 | 5 | app = Flask(__name__) 6 | 7 | @app.route('/measure_success_rate', methods=['POST']) 8 | def measure_success_rate(): 9 | url = request.json.get('url') 10 | 11 | if not url: 12 | return jsonify({'error': 'URL is missing in the request body'}), 400 13 | 14 | success_count = 0 15 | 16 | for _ in range(5): 17 | try: 18 | response = requests.get(url) 19 | except requests.exceptions.RequestException: 20 | pass 21 | else: 22 | if response.status_code == 200: 23 | success_count += 1 24 | time.sleep(5) 25 | else: 26 | time.sleep(5) 27 | success_rate = (success_count / 5) * 100 28 | if int(success_rate) >= 80: 29 | return jsonify({'data': {'ok': 'true'}}) 30 | else: 31 | return jsonify({'data': {'ok': 'false'}}) 32 | 33 | if __name__ == '__main__': 34 | app.run() 35 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/canary-analysis/canary-analysis.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: AnalysisTemplate 3 | metadata: 4 | name: success-rate 5 | spec: 6 | args: 7 | - name: service_address ### This is the variable related to the ip address where the analysis-app.py is located 8 | value: "192.168.1.5" #### WE are using a flask script to get the url of the application and try to connect to it 5 times at 5 seconds intervals and returns one of the true or false values based on "200 response_code" in a json format, if the success_rate is 80% or more , it returns "true" value, Otherwise it returns "false" value, you can find this simple app in the current directory (its name is analysis-app.py). 9 | - name: service_port ### This is the variable related to the port of analysis-app.py flask app 10 | metrics: 11 | - name: success-rate 12 | successCondition: result == "true" 13 | provider: 14 | web: 15 | method: POST 16 | url: "http://{{args.service_address}}:{{args.service_port}}/measure_success_rate" #### The url related to the analysis-app.py flask app 17 | timeoutSeconds: 50 # defaults to 10 seconds 18 | headers: 19 | - key: Content-Type # if body is a json, it is recommended to set the Content-Type 20 | value: "application/json" 21 | jsonBody: # If using jsonBody Content-Type header will be automatically set to json 22 | url: "http://rollouts-setweight.demo" 23 | jsonPath: "{$.data.ok}" 24 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/canary-analysis/ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: rolling-update 5 | spec: 6 | ingressClassName: nginx 7 | rules: 8 | - host: rollouts-setweight.demo 9 | http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: rollouts-setweight 16 | port: 17 | number: 5000 18 | -------------------------------------------------------------------------------- /v14-argo-rollouts-analysis/canary-analysis/rollout-with-analysis.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Rollout 3 | metadata: 4 | name: rollouts-setweight 5 | spec: 6 | replicas: 5 7 | strategy: 8 | canary: 9 | # analysis: #### This is a Backgound Analysis 10 | # templates: 11 | # - templateName: success-rate 12 | # args: 13 | # - name: service_port #### This is the variable related to the port of analysis-app.py flask app 14 | # value: "5001" 15 | steps: 16 | - setWeight: 20 17 | - pause: {} 18 | - setWeight: 40 19 | - pause: {duration: 10s} 20 | - analysis: #### This is an Inline Analysis 21 | templates: 22 | - templateName: success-rate 23 | args: 24 | - name: service_port #### This is the variable related to the port of analysis-app.py flask app 25 | value: "5001" 26 | - setWeight: 60 27 | - pause: {duration: 20s} 28 | - setWeight: 80 29 | - pause: {duration: 1m} 30 | selector: 31 | matchLabels: 32 | app: rollouts-setweight 33 | template: 34 | metadata: 35 | labels: 36 | app: rollouts-setweight 37 | spec: 38 | containers: 39 | - name: rollouts-setweight 40 | image: canary # This is the same image that we built in blue-green session , I just re-tagged it 41 | imagePullPolicy: Never 42 | env: 43 | - name: html_name 44 | value: "app-v1.html" 45 | ports: 46 | - containerPort: 5000 47 | --- 48 | apiVersion: v1 49 | kind: Service 50 | metadata: 51 | name: rollouts-setweight 52 | spec: 53 | ports: 54 | - port: 5000 55 | targetPort: 5000 56 | selector: 57 | app: rollouts-setweight 58 | -------------------------------------------------------------------------------- /v15-argo-workflows-getting-started/setting-up/note.txt: -------------------------------------------------------------------------------- 1 | ### Installing Argo-Workflows Helm Chart 2 | ### Please Note that before installing Argo-workflows, you must have nginx-ingress-controller installed on the cluster 3 | ### Also make sure to add the host used in the ingress to the /etc/hosts file 4 | 5 | ### Install Argo-Workflows Helm Chart as following: 6 | kubectl create ns argo 7 | helm repo add argo https://argoproj.github.io/argo-helm 8 | helm install <> argo/argo-cd -n argocd -f values.yml 9 | -------------------------------------------------------------------------------- /v15-argo-workflows-getting-started/setting-up/values.yml: -------------------------------------------------------------------------------- 1 | server: 2 | extraArgs: 3 | - --auth-mode=server ## The argo-server (and thus the UI) defaults to client authentication, which requires clients to provide their Kubernetes bearer token in order to authenticate, We switch the authentication mode to server so that we can bypass the UI login 4 | # serviceType: NodePort ## use NodePort instead of ingress if you want 5 | # serviceNodePort: 32746 6 | ingress: 7 | enabled: true 8 | ingressClassName: nginx 9 | hosts: 10 | - devops.hobbies 11 | -------------------------------------------------------------------------------- /v15-argo-workflows-getting-started/template-types/templates.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: argo-wf- # Name of this Workflow 5 | spec: 6 | entrypoint: dag-template # Defines "dag-template" as the "main" template 7 | templates: 8 | - name: dag-template # Defining the "dag template" as a Template Invocator, You must use one of "dag" or "steps" as a template invocator 9 | dag: 10 | tasks: 11 | - name: A 12 | template: container-template 13 | - name: B 14 | template: script-template 15 | dependencies: [A] 16 | - name: C 17 | template: resource-template 18 | dependencies: [A] 19 | - name: D 20 | template: delay-template 21 | dependencies: [B, C] 22 | # - name: steps-template # Defining the "steps template" as a Template Invocator, You must use one of "dag" or "steps" as a template invocator 23 | # steps: 24 | # - - name: step1 25 | # template: container-template 26 | # - - name: step2a 27 | # template: script-template 28 | # - name: step2b 29 | # template: resource-template 30 | # - - name: step3 31 | # template: delay-template 32 | 33 | 34 | - name: container-template # Defining the "container template" as a Template Definition 35 | container: 36 | image: alpine 37 | command: ["/bin/sh", "-c"] 38 | args: ["echo Hello from container template"] 39 | - name: script-template # Defining the "script template" as a Template Definition 40 | script: 41 | image: python:alpine3.6 42 | command: [python] 43 | source: | 44 | import random 45 | i = random.randint(1, 100) 46 | print(i) 47 | - name: resource-template # Defining the "resource template" as a Template Definition 48 | resource: 49 | action: create 50 | manifest: | 51 | apiVersion: v1 52 | kind: ConfigMap 53 | metadata: 54 | generateName: argo-wf-resource-template-cm- 55 | data: 56 | created_by: argo-workflows 57 | - name: delay-template # Defining the "delay template" as a Template Definition 58 | suspend: 59 | duration: "20s" 60 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/artifacts/conditional-artifacts.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: conditional-artifacts- 5 | labels: 6 | workflows.argoproj.io/test: "true" 7 | annotations: 8 | workflows.argoproj.io/description: | 9 | Conditional artifacts provide a way to choose the output artifacts based on expression. 10 | 11 | In this example the main template has two steps which will run conditionall using `when` . 12 | 13 | Based on the `when` condition one of step will not execute. The main template's output artifact named "result" 14 | will be set to the executed step's output. 15 | workflows.argoproj.io/version: '>= 3.1.0' 16 | spec: 17 | artifactRepositoryRef: 18 | configMap: artifact-repository ## Defining a specific artifact repository for a workflow. there is no need to specify the name of the artifact repository configmap unless its name is artifact-repositories 19 | entrypoint: main 20 | templates: 21 | - name: main 22 | steps: 23 | - - name: flip-coin 24 | template: flip-coin 25 | - - name: heads 26 | template: heads 27 | when: "{{steps.flip-coin.outputs.result}} == heads" 28 | - name: tails 29 | template: tails 30 | when: "{{steps.flip-coin.outputs.result}} == tails" 31 | outputs: 32 | artifacts: 33 | - name: result 34 | fromExpression: "steps['flip-coin'].outputs.result == 'heads' ? steps.heads.outputs.artifacts.result : steps.tails.outputs.artifacts.result" 35 | 36 | - name: flip-coin 37 | script: 38 | image: python:alpine3.6 39 | command: [ python ] 40 | source: | 41 | import random 42 | print("heads" if random.randint(0,1) == 0 else "tails") 43 | 44 | - name: heads 45 | script: 46 | image: python:alpine3.6 47 | command: [ python ] 48 | source: | 49 | with open("result.txt", "w") as f: 50 | f.write("it was heads") 51 | outputs: 52 | artifacts: 53 | - name: result 54 | path: /result.txt 55 | 56 | - name: tails 57 | script: 58 | image: python:alpine3.6 59 | command: [ python ] 60 | source: | 61 | with open("result.txt", "w") as f: 62 | f.write("it was tails") 63 | outputs: 64 | artifacts: 65 | - name: result 66 | path: /result.txt 67 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/artifacts/conditional-parameters.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: dag-conditional-parameter- 5 | labels: 6 | workflows.argoproj.io/test: "true" 7 | annotations: 8 | workflows.argoproj.io/description: | 9 | Conditional parameters provide a way to choose the output parameters based on expression. 10 | 11 | In this example DAG template has two task which will run conditionally based on `when`. 12 | 13 | Based on this condition one of task may not execute. The template's output parameter will be set to the 14 | executed taks's output result. 15 | workflows.argoproj.io/version: '>= 3.1.0' 16 | spec: 17 | entrypoint: main 18 | templates: 19 | - name: main 20 | dag: 21 | tasks: 22 | - name: flip-coin 23 | template: flip-coin 24 | - name: heads 25 | depends: flip-coin 26 | template: heads 27 | when: "{{tasks.flip-coin.outputs.result}} == heads" 28 | - name: tails 29 | depends: flip-coin 30 | template: tails 31 | when: "{{tasks.flip-coin.outputs.result}} == tails" 32 | outputs: 33 | parameters: 34 | - name: stepresult 35 | valueFrom: 36 | expression: "tasks['flip-coin'].outputs.result == 'heads' ? tasks.heads.outputs.result : tasks.tails.outputs.result" 37 | 38 | - name: flip-coin 39 | script: 40 | image: python:alpine3.6 41 | command: [python] 42 | source: | 43 | import random 44 | print("heads" if random.randint(0,1) == 0 else "tails") 45 | 46 | - name: heads 47 | script: 48 | image: python:alpine3.6 49 | command: [python] 50 | source: | 51 | print("heads") 52 | 53 | - name: tails 54 | script: 55 | image: python:alpine3.6 56 | command: [python] 57 | source: | 58 | print("tails") 59 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/artifacts/hardwired-artifacts.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: hardwired-artifact- 5 | spec: 6 | entrypoint: hardwired-artifact 7 | templates: 8 | - name: hardwired-artifact 9 | inputs: 10 | artifacts: 11 | # Check out the main branch of the argo repo and place it at /devopshobies 12 | # revision can be anything that git checkout accepts: branch, commit, tag, etc. 13 | - name: argo-source 14 | path: /devopshobbies 15 | git: 16 | repo: https://github.com/devopshobbies/argocd-tutorial.git 17 | revision: "main" 18 | # Download docker-compose v2.23.0 and place it at /usr/local/bin/ 19 | - name: docker-compose 20 | path: /usr/local/bin/docker-compose 21 | mode: 0755 22 | http: 23 | url: https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 24 | container: 25 | image: alpine 26 | command: [sh, -c] 27 | args: ["ls -l /devopshobbies /usr/local/bin/docker-compose"] 28 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/artifacts/minio-artifact-repo-cm.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | # If you want to use this config map by default, name it "artifact-repositories". Otherwise, you can provide a reference to a 5 | # different config map in `artifactRepositoryRef.configMap`. 6 | name: artifact-repository 7 | annotations: 8 | # v3.0 and after - if you want to use a specific key, put that key into this annotation. 9 | workflows.argoproj.io/default-artifact-repository: minio-artifact-repo 10 | data: 11 | minio-artifact-repo: | 12 | s3: 13 | bucket: my-bucket 14 | endpoint: argo-artifacts.argo:9000 15 | insecure: true 16 | accessKeySecret: 17 | name: my-minio-cred 18 | key: access-key 19 | secretKeySecret: 20 | name: my-minio-cred 21 | key: secret-key 22 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/artifacts/workflow-artiafcts.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: argo-wf- # Name of this Workflow 5 | spec: 6 | artifactRepositoryRef: 7 | configMap: artifact-repository ## Defining a specific artifact repository for a workflow. there is no need to specify the name of the artifact repository configmap unless its name is artifact-repositories 8 | arguments: 9 | entrypoint: dag-template # Defines "dag-template" as the "main" template 10 | templates: 11 | - name: dag-template # Defining the "dag template" as a Template Invocator, You must use one of "dag" or "steps" as a template invocator 12 | dag: 13 | tasks: 14 | - name: A 15 | template: container-template 16 | arguments: 17 | - name: B 18 | template: script-template 19 | dependencies: [A] 20 | - name: C 21 | template: resource-template 22 | dependencies: [A, B] 23 | - name: D 24 | template: script-template-new 25 | dependencies: [A, B, C] 26 | arguments: 27 | artifacts: 28 | - name: random_num_in 29 | from: "{{tasks.B.outputs.artifacts.random_num_out}}" 30 | - name: E 31 | template: delay-template 32 | dependencies: [A, B, C, D] 33 | # - name: steps-template # Defining the "steps template" as a Template Invocator, You must use one of "dag" or "steps" as a template invocator 34 | # steps: 35 | # - - name: step1 36 | # template: container-template 37 | # - - name: step2a 38 | # template: script-template 39 | # - name: step2b 40 | # template: resource-template 41 | # - - name: step3 42 | # template: delay-template 43 | 44 | 45 | - name: container-template # Defining the "container template" as a Template Definition 46 | container: 47 | image: alpine 48 | command: ["/bin/sh", "-c"] 49 | args: ["echo hello from container template"] 50 | - name: script-template # Defining the "script template" as a Template Definition 51 | script: 52 | image: python:alpine3.6 53 | command: [python] 54 | source: | 55 | import random 56 | i = random.randint(1, 100) 57 | with open('/tmp/rand-num.txt', 'w') as f: 58 | f.write(str(i)) 59 | # print(i) 60 | outputs: 61 | artifacts: 62 | - name: random_num_out 63 | path: /tmp/rand-num.txt 64 | - name: resource-template # Defining the "resource template" as a Template Definition 65 | resource: 66 | action: create 67 | manifest: | 68 | apiVersion: v1 69 | kind: ConfigMap 70 | metadata: 71 | generateName: argo-wf-resource-template-cm- 72 | data: 73 | created_by: argo-workflows 74 | - name: script-template-new # # Defining the "script template new" as a Template Definition 75 | inputs: 76 | artifacts: 77 | - name: random_num_in 78 | path: /tmp/rand.txt 79 | script: 80 | image: python:alpine3.6 81 | command: [python] 82 | source: | 83 | with open('/tmp/rand.txt', 'r') as f: 84 | number = f.read() 85 | print(number) 86 | - name: delay-template # Defining the "delay template" as a Template Definition 87 | suspend: 88 | duration: "20s" 89 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/artifacts/workflow-input-parameters.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: argo-wf- # Name of this Workflow 5 | spec: 6 | arguments: 7 | parameters: 8 | - name: message 9 | value: "Hello from spec.arguments" ## You can also comment out the value from here and pass it using "-p" when submitting the workflow, ex: argo submit templates.yml -p 'message="hello from terminal"' -n argo 10 | entrypoint: dag-template # Defines "dag-template" as the "main" template 11 | templates: 12 | - name: dag-template # Defining the "dag template" as a Template Invocator, You must use one of "dag" or "steps" as a template invocator 13 | dag: 14 | tasks: 15 | - name: A 16 | template: container-template 17 | arguments: 18 | parameters: 19 | - name: message 20 | value: "{{workflow.parameters.message}}" 21 | - name: B 22 | template: script-template 23 | dependencies: [A] 24 | - name: C 25 | template: resource-template 26 | dependencies: [A] 27 | - name: D 28 | template: delay-template 29 | dependencies: [B, C] 30 | # - name: steps-template # Defining the "steps template" as a Template Invocator, You must use one of "dag" or "steps" as a template invocator 31 | # steps: 32 | # - - name: step1 33 | # template: container-template 34 | # - - name: step2a 35 | # template: script-template 36 | # - name: step2b 37 | # template: resource-template 38 | # - - name: step3 39 | # template: delay-template 40 | 41 | 42 | - name: container-template # Defining the "container template" as a Template Definition 43 | inputs: 44 | parameters: 45 | - name: message 46 | container: 47 | image: alpine 48 | command: ["/bin/sh", "-c"] 49 | args: ["echo {{inputs.parameters.message}}"] 50 | - name: script-template # Defining the "script template" as a Template Definition 51 | script: 52 | image: python:alpine3.6 53 | command: [python] 54 | source: | 55 | import random 56 | i = random.randint(1, 100) 57 | print(i) 58 | - name: resource-template # Defining the "resource template" as a Template Definition 59 | resource: 60 | action: create 61 | manifest: | 62 | apiVersion: v1 63 | kind: ConfigMap 64 | metadata: 65 | generateName: argo-wf-resource-template-cm- 66 | data: 67 | created_by: argo-workflows 68 | - name: delay-template # Defining the "delay template" as a Template Definition 69 | suspend: 70 | duration: "20s" 71 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/artifacts/workflow-output-parameters.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: argo-wf- # Name of this Workflow 5 | spec: 6 | arguments: 7 | entrypoint: dag-template # Defines "dag-template" as the "main" template 8 | templates: 9 | - name: dag-template # Defining the "dag template" as a Template Invocator, You must use one of "dag" or "steps" as a template invocator 10 | dag: 11 | tasks: 12 | - name: A 13 | template: container-template 14 | arguments: 15 | - name: B 16 | template: script-template 17 | dependencies: [A] 18 | - name: C 19 | template: resource-template 20 | dependencies: [A, B] 21 | arguments: 22 | parameters: 23 | - name: random_num_in 24 | value: "{{tasks.B.outputs.parameters.random_num_out}}" 25 | - name: D 26 | template: delay-template 27 | dependencies: [A, B, C] 28 | # - name: steps-template # Defining the "steps template" as a Template Invocator, You must use one of "dag" or "steps" as a template invocator 29 | # steps: 30 | # - - name: step1 31 | # template: container-template 32 | # - - name: step2a 33 | # template: script-template 34 | # - name: step2b 35 | # template: resource-template 36 | # - - name: step3 37 | # template: delay-template 38 | 39 | 40 | - name: container-template # Defining the "container template" as a Template Definition 41 | container: 42 | image: alpine 43 | command: ["/bin/sh", "-c"] 44 | args: ["echo hello from container template"] 45 | - name: script-template # Defining the "script template" as a Template Definition 46 | script: 47 | image: python:alpine3.6 48 | command: [python] 49 | source: | 50 | import random 51 | i = random.randint(1, 100) 52 | with open('/tmp/rand-num.txt', 'w') as f: 53 | f.write(str(i)) 54 | # print(i) 55 | outputs: 56 | parameters: 57 | - name: random_num_out 58 | # value: "20" 59 | valueFrom: 60 | path: /tmp/rand-num.txt 61 | - name: resource-template # Defining the "resource template" as a Template Definition 62 | inputs: 63 | parameters: 64 | - name: random_num_in 65 | resource: 66 | action: create 67 | manifest: | 68 | apiVersion: v1 69 | kind: ConfigMap 70 | metadata: 71 | generateName: argo-wf-resource-template-cm- 72 | data: 73 | created_by: argo-workflows 74 | random_number_from_script_template: "{{inputs.parameters.random_num_in}}" 75 | - name: delay-template # Defining the "delay template" as a Template Definition 76 | suspend: 77 | duration: "20s" 78 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/customResource-kinds/cluster-workflow-template.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: ClusterWorkflowTemplate 3 | metadata: 4 | name: argo-cluster-wf-template 5 | spec: 6 | templates: 7 | - name: container-template 8 | # inputs: 9 | # parameters: 10 | # - name: message 11 | container: 12 | image: alpine 13 | command: ["/bin/sh", "-c"] 14 | args: ["echo {{workflow.parameters.message}}"] ### you can instantiate your global variables in your "Workflow" and then directly reference them in your "WorkflowTemplate" 15 | # args: ["echo {{inputs.parameters.message}}"] ### Use <> instead of <> if you want to get the variable from inputs.parameters 16 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/customResource-kinds/cron-workflow.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: CronWorkflow 3 | metadata: 4 | generateName: argo-cron-wf- 5 | spec: 6 | schedule: "*/2 * * * *" 7 | suspend: false 8 | concurrencyPolicy: "Forbid" 9 | startingDeadlineSeconds: 0 10 | successfulJobsHistoryLimit: 2 11 | failedJobsHistoryLimit: 2 12 | workflowSpec: 13 | entrypoint: dag-template 14 | templates: 15 | - name: dag-template 16 | dag: 17 | tasks: 18 | - name: A 19 | template: script-template 20 | - name: B 21 | template: resource-template 22 | dependencies: [A] 23 | - name: C 24 | template: suspend-template 25 | dependencies: [A, B] 26 | - name: script-template 27 | script: 28 | image: python:alpine3.6 29 | command: [python] 30 | source: | 31 | import random 32 | i = random.randint(1, 10) 33 | print(i) 34 | - name: resource-template 35 | resource: 36 | action: create 37 | manifest: | 38 | apiVersion: v1 39 | kind: ConfigMap 40 | metadata: 41 | generateName: argo-wf-resource-template-cm- 42 | data: 43 | created_by: argo-wrkflows 44 | - name: suspend-template 45 | suspend: 46 | duration: "20s" 47 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/customResource-kinds/workflow-ref.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: argo-wf-ref- 5 | spec: 6 | entrypoint: container-template 7 | # arguments: 8 | # parameters: 9 | # - name: message 10 | # value: "created from workflow-template" 11 | workflowTemplateRef: 12 | name: argo-wf-template 13 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/customResource-kinds/workflow-template.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: WorkflowTemplate 3 | metadata: 4 | name: argo-wf-template 5 | spec: 6 | templates: 7 | - name: container-template 8 | # inputs: 9 | # parameters: 10 | # - name: message 11 | container: 12 | image: alpine 13 | command: ["/bin/sh", "-c"] 14 | args: ["echo {{workflow.parameters.message}}"] ### you can instantiate your global variables in your "Workflow" and then directly reference them in your "WorkflowTemplate" 15 | # args: ["echo {{inputs.parameters.message}}"] ### Use <> instead of <> if you want to get the variable from inputs.parameters 16 | -------------------------------------------------------------------------------- /v16-argo-workflows-crds-and-artifacts/customResource-kinds/workflow.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: argo-wf- 5 | spec: 6 | entrypoint: dag-template 7 | # arguments: 8 | # parameters: 9 | # - name: message 10 | # value: "hello from workflow.spec.arguments.parameters" 11 | templates: 12 | - name: dag-template 13 | dag: 14 | tasks: 15 | - name: A 16 | templateRef: 17 | # name: argo-cluster-wf-template 18 | # template: container-template 19 | # clusterScope: true ### it's needed to use <> if your templateRef is a ClusterWorkflowTemplate 20 | # arguments: 21 | # parameters: 22 | # - name: message 23 | # value: "hello from workflow.spec.templates.dag.tasks.A" 24 | - name: B 25 | template: script-template 26 | dependencies: [A] 27 | - name: C 28 | template: resource-template 29 | dependencies: [A] 30 | - name: D 31 | template: suspend-template 32 | dependencies: [B, C] 33 | - name: script-template 34 | script: 35 | image: python:alpine3.6 36 | command: [python] 37 | source: | 38 | import random 39 | i = random.randint(1, 10) 40 | print(i) 41 | - name: resource-template 42 | resource: 43 | action: create 44 | manifest: | 45 | apiVersion: v1 46 | kind: ConfigMap 47 | metadata: 48 | generateName: argo-wf-resource-template-cm- 49 | data: 50 | created_by: argo-wrkflows 51 | - name: suspend-template 52 | suspend: 53 | duration: "20s" 54 | -------------------------------------------------------------------------------- /v17-combining-argo-tools/app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | COPY index.html /usr/share/nginx/html/ 3 | -------------------------------------------------------------------------------- /v17-combining-argo-tools/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Welcome to My Website 8 | 36 | 37 | 38 | 39 |
40 |

Welcome to My Website, Version 1.0

41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /v17-combining-argo-tools/argo-cd/argo-app.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: argo-demo-application 5 | namespace: argocd 6 | spec: 7 | destination: 8 | namespace: argo-demo 9 | server: https://kubernetes.default.svc 10 | project: default 11 | source: 12 | path: v17-combining-argo-tools/argo-rollouts 13 | repoURL: https://github.com/devopshobbies/argocd-tutorial.git 14 | targetRevision: main 15 | syncPolicy: 16 | syncOptions: 17 | - CreateNamespace=true 18 | automated: 19 | prune: true 20 | selfHeal: true 21 | -------------------------------------------------------------------------------- /v17-combining-argo-tools/argo-rollouts/nginx-ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: nginx-ingress 5 | spec: 6 | ingressClassName: nginx 7 | rules: 8 | - host: argo.demo 9 | http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: nginx-service 16 | port: 17 | number: 8080 18 | -------------------------------------------------------------------------------- /v17-combining-argo-tools/argo-rollouts/nginx-rollouts.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Rollout 3 | metadata: 4 | name: nginx-rollouts 5 | spec: 6 | replicas: 5 7 | strategy: 8 | canary: 9 | steps: 10 | - setWeight: 20 11 | - pause: {} 12 | - setWeight: 40 13 | - pause: {duration: 10s} 14 | - setWeight: 60 15 | - pause: {duration: 20s} 16 | - setWeight: 80 17 | - pause: {duration: 1m} 18 | selector: 19 | matchLabels: 20 | app: nginx-rollouts 21 | template: 22 | metadata: 23 | labels: 24 | app: nginx-rollouts 25 | spec: 26 | containers: 27 | - name: nginx-rollouts 28 | image: 192.168.1.2:8085/nginx:130a5b21-3166-4ab7-a27c-51f64a198f35 29 | ports: 30 | - containerPort: 80 31 | --- 32 | apiVersion: v1 33 | kind: Service 34 | metadata: 35 | name: nginx-service 36 | spec: 37 | ports: 38 | - port: 8080 39 | targetPort: 80 40 | selector: 41 | app: nginx-rollouts 42 | -------------------------------------------------------------------------------- /v17-combining-argo-tools/argo-workflows/build-push.yml: -------------------------------------------------------------------------------- 1 | # First of all, use the below command to create docker-config-secret for pushing images to your private registry 2 | # kubectl create secret generic docker-config-secret --from-file=/path/to/.docker/config.json -n argo 3 | apiVersion: argoproj.io/v1alpha1 4 | kind: WorkflowTemplate 5 | metadata: 6 | name: build-push-wf-template 7 | spec: 8 | templates: 9 | - name: build-and-push 10 | inputs: 11 | artifacts: 12 | - name: source 13 | path: /tmp/source 14 | volumes: 15 | - name: docker-config-secret 16 | secret: 17 | secretName: docker-config-secret 18 | container: 19 | readinessProbe: 20 | exec: 21 | command: [ sh, -c, "buildctl debug workers" ] 22 | image: moby/buildkit:v0.9.3-rootless 23 | volumeMounts: 24 | - name: docker-config-secret 25 | mountPath: /.docker 26 | workingDir: /tmp/source/v17-combining-argo-tools/app 27 | env: 28 | - name: BUILDKITD_FLAGS 29 | value: --oci-worker-no-process-sandbox 30 | - name: DOCKER_CONFIG 31 | value: /.docker 32 | command: 33 | - buildctl-daemonless.sh 34 | args: 35 | - build 36 | - --frontend 37 | - dockerfile.v0 38 | - --local 39 | - context=. 40 | - --local 41 | - dockerfile=. 42 | - --output 43 | - type=image,name={{workflow.parameters.nexus-registry}}/nginx:{{workflow.uid}},push=true,registry.insecure=true 44 | securityContext: 45 | privileged: true 46 | -------------------------------------------------------------------------------- /v17-combining-argo-tools/argo-workflows/clone-repo.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: WorkflowTemplate 3 | metadata: 4 | name: clone-repo-wf-template 5 | spec: 6 | templates: 7 | - name: clone-repo 8 | outputs: 9 | artifacts: 10 | - name: source 11 | path: /tmp/source 12 | script: 13 | image: alpine/git 14 | command: [sh] 15 | source: | 16 | git clone {{workflow.parameters.repo-url}} /tmp/source 17 | -------------------------------------------------------------------------------- /v17-combining-argo-tools/argo-workflows/update-manifest.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: WorkflowTemplate 3 | metadata: 4 | name: update-manifest-wf-template 5 | spec: 6 | templates: 7 | - name: update-manifest 8 | inputs: 9 | artifacts: 10 | - name: source 11 | path: /tmp/source 12 | script: 13 | image: alpine/git 14 | workingDir: /tmp/source/v17-combining-argo-tools/argo-rollouts 15 | command: [sh] 16 | source: | 17 | sed -i s'/image:.*/image: {{workflow.parameters.nexus-registry}}\/nginx:{{workflow.uid}}/' nginx-rollouts.yml 18 | git config user.name "USERNAME" 19 | git config user.email "EMAIL" 20 | git add . 21 | git commit -m "image.tag has been changed to {{workflow.uid}}" 22 | git push origin {{workflow.parameters.branch}} 23 | -------------------------------------------------------------------------------- /v17-combining-argo-tools/argo-workflows/workflows.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Workflow 3 | metadata: 4 | generateName: argo-demo- 5 | spec: 6 | arguments: 7 | parameters: 8 | - name: repo-url 9 | value: https://USERNAME:TOKEN@github.com/devopshobbies/argocd-tutorial.git 10 | - name: branch 11 | value: main 12 | - name: nexus-registry 13 | value: 192.168.233.214:8085 14 | artifactRepositoryRef: 15 | configMap: artifact-repository 16 | entrypoint: ci 17 | templates: 18 | - name: ci 19 | dag: 20 | tasks: 21 | - name: clone-repo-task 22 | templateRef: 23 | name: clone-repo-wf-template 24 | template: clone-repo 25 | - name: build-push-task 26 | templateRef: 27 | name: build-push-wf-template 28 | template: build-and-push 29 | arguments: 30 | artifacts: 31 | - name: source 32 | from: "{{tasks.clone-repo-task.outputs.artifacts.source}}" 33 | dependencies: [clone-repo-task] 34 | - name: update-manifest-task 35 | templateRef: 36 | name: update-manifest-wf-template 37 | template: update-manifest 38 | arguments: 39 | artifacts: 40 | - name: source 41 | from: "{{tasks.clone-repo-task.outputs.artifacts.source}}" 42 | dependencies: [clone-repo-task, build-push-task] 43 | -------------------------------------------------------------------------------- /v18-combining-argo-tools-part-2/argo-cd/argo-app.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: argo-demo-application 5 | namespace: argocd 6 | spec: 7 | destination: 8 | namespace: argo-demo 9 | server: https://kubernetes.default.svc 10 | project: default 11 | source: 12 | path: argo-rollouts 13 | repoURL: http://gitlab.isc/root/argo-config.git 14 | targetRevision: main 15 | syncPolicy: 16 | syncOptions: 17 | - CreateNamespace=true 18 | automated: 19 | prune: true 20 | selfHeal: true 21 | -------------------------------------------------------------------------------- /v18-combining-argo-tools-part-2/argo-events/event-source.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: gitlab-access 5 | namespace: argo-events 6 | type: Opaque 7 | data: 8 | token: TOKEN 9 | --- 10 | apiVersion: argoproj.io/v1alpha1 11 | kind: EventSource 12 | metadata: 13 | name: ci 14 | namespace: argo-events 15 | spec: 16 | service: 17 | ports: 18 | - port: 12000 19 | targetPort: 12000 20 | gitlab: 21 | argo-demo: 22 | projects: 23 | - "35" 24 | webhook: 25 | endpoint: /push 26 | port: "12000" 27 | url: http://argo.events 28 | events: 29 | - PushEvents 30 | accessToken: 31 | key: token 32 | name: gitlab-access 33 | enableSSLVerification: false 34 | gitlabBaseURL: http://gitlab.isc 35 | deleteHookOnFinish: true 36 | --- 37 | apiVersion: networking.k8s.io/v1 38 | kind: Ingress 39 | metadata: 40 | name: argo-demo-ingress 41 | namespace: argo-events 42 | spec: 43 | ingressClassName: nginx 44 | rules: 45 | - host: argo.events 46 | http: 47 | paths: 48 | - path: / 49 | pathType: Prefix 50 | backend: 51 | service: 52 | name: ci-eventsource-svc 53 | port: 54 | number: 12000 55 | -------------------------------------------------------------------------------- /v18-combining-argo-tools-part-2/argo-events/sensor.yml: -------------------------------------------------------------------------------- 1 | # Create a service account with RBAC settings to allow the sensor to trigger workflows, and allow workflows to function. 2 | # kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/rbac/sensor-rbac.yaml 3 | # kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/rbac/workflow-rbac.yaml 4 | apiVersion: argoproj.io/v1alpha1 5 | kind: Sensor 6 | metadata: 7 | name: ci 8 | namespace: argo-events 9 | spec: 10 | template: 11 | serviceAccountName: operate-workflow-sa 12 | dependencies: 13 | - name: ci 14 | eventSourceName: ci 15 | eventName: argo-demo 16 | triggers: 17 | - template: 18 | name: ci 19 | argoWorkflow: 20 | operation: submit 21 | source: 22 | resource: 23 | apiVersion: argoproj.io/v1alpha1 24 | kind: Workflow 25 | metadata: 26 | generateName: argo-demo- 27 | spec: 28 | arguments: 29 | parameters: 30 | - name: app-repo-url 31 | value: http://USERNAME:TOKEN@gitlab.isc/root/my-app.git 32 | - name: argo-config-repo-url 33 | value: http://USERNAME:TOKEN@gitlab.isc/root/argo-config.git 34 | - name: app-clone-dest 35 | value: /tmp/app 36 | - name: argo-config-clone-dest 37 | value: /tmp/argo-config 38 | - name: argo-config-branch 39 | value: main 40 | - name: nexus-registry 41 | value: 192.168.1.2:8085 42 | artifactRepositoryRef: 43 | configMap: artifact-repository 44 | entrypoint: ci 45 | templates: 46 | - name: ci 47 | dag: 48 | tasks: 49 | - name: clone-repo-task 50 | template: clone-repo 51 | - name: build-push-task 52 | template: build-and-push 53 | arguments: 54 | artifacts: 55 | - name: app-repo 56 | from: "{{tasks.clone-repo-task.outputs.artifacts.app-repo}}" 57 | dependencies: [clone-repo-task] 58 | - name: update-manifest-task 59 | template: update-manifest 60 | arguments: 61 | artifacts: 62 | - name: argo-config-repo 63 | from: "{{tasks.clone-repo-task.outputs.artifacts.argo-config-repo}}" 64 | dependencies: [clone-repo-task, build-push-task] 65 | - name: clone-repo 66 | outputs: 67 | artifacts: 68 | - name: app-repo 69 | path: "{{workflow.parameters.app-clone-dest}}" 70 | - name: argo-config-repo 71 | path: "{{workflow.parameters.argo-config-clone-dest}}" 72 | script: 73 | image: alpine/git 74 | command: [sh] 75 | source: | 76 | git clone {{workflow.parameters.app-repo-url}} {{workflow.parameters.app-clone-dest}} && git clone {{workflow.parameters.argo-config-repo-url}} {{workflow.parameters.argo-config-clone-dest}} 77 | - name: build-and-push 78 | inputs: 79 | artifacts: 80 | - name: app-repo 81 | path: "{{workflow.parameters.app-clone-dest}}" 82 | volumes: 83 | - name: docker-config-secret 84 | secret: 85 | secretName: docker-config-secret 86 | container: 87 | readinessProbe: 88 | exec: 89 | command: [ sh, -c, "buildctl debug workers" ] 90 | image: moby/buildkit:v0.9.3-rootless 91 | volumeMounts: 92 | - name: docker-config-secret 93 | mountPath: /.docker 94 | workingDir: "{{workflow.parameters.app-clone-dest}}" 95 | env: 96 | - name: BUILDKITD_FLAGS 97 | value: --oci-worker-no-process-sandbox 98 | - name: DOCKER_CONFIG 99 | value: /.docker 100 | command: 101 | - buildctl-daemonless.sh 102 | args: 103 | - build 104 | - --frontend 105 | - dockerfile.v0 106 | - --local 107 | - context=. 108 | - --local 109 | - dockerfile=. 110 | - --output 111 | - type=image,name={{workflow.parameters.nexus-registry}}/nginx:{{workflow.uid}},push=true,registry.insecure=true 112 | securityContext: 113 | privileged: true 114 | - name: update-manifest 115 | inputs: 116 | artifacts: 117 | - name: argo-config-repo 118 | path: "{{workflow.parameters.argo-config-clone-dest}}" 119 | script: 120 | image: alpine/git 121 | workingDir: "{{workflow.parameters.argo-config-clone-dest}}/argo-rollouts" 122 | command: [sh] 123 | source: | 124 | sed -i s'/image:.*/image: {{workflow.parameters.nexus-registry}}\/nginx:{{workflow.uid}}/' nginx-rollouts.yml 125 | git config user.name "USERNAME" 126 | git config user.email "EMAIL" 127 | git add . 128 | git commit -m "image.tag has been changed to {{workflow.uid}}" 129 | git push origin {{workflow.parameters.argo-config-branch}} 130 | -------------------------------------------------------------------------------- /v18-combining-argo-tools-part-2/argo-rollouts/nginx-ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: nginx-ingress 5 | spec: 6 | ingressClassName: nginx 7 | rules: 8 | - host: argo.demo 9 | http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: nginx-service 16 | port: 17 | number: 8080 18 | -------------------------------------------------------------------------------- /v18-combining-argo-tools-part-2/argo-rollouts/nginx-rollouts.yml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Rollout 3 | metadata: 4 | name: nginx-rollouts 5 | spec: 6 | replicas: 5 7 | strategy: 8 | canary: 9 | steps: 10 | - setWeight: 20 11 | - pause: {} 12 | - setWeight: 40 13 | - pause: {duration: 10s} 14 | - setWeight: 60 15 | - pause: {duration: 20s} 16 | - setWeight: 80 17 | - pause: {duration: 1m} 18 | selector: 19 | matchLabels: 20 | app: nginx-rollouts 21 | template: 22 | metadata: 23 | labels: 24 | app: nginx-rollouts 25 | spec: 26 | containers: 27 | - name: nginx-rollouts 28 | image: 192.168.1.2:8085/nginx:130a5b21-3166-4ab7-a27c-51f64a198f35 29 | ports: 30 | - containerPort: 80 31 | --- 32 | apiVersion: v1 33 | kind: Service 34 | metadata: 35 | name: nginx-service 36 | spec: 37 | ports: 38 | - port: 8080 39 | targetPort: 80 40 | selector: 41 | app: nginx-rollouts 42 | --------------------------------------------------------------------------------