├── .gitignore ├── LICENSE ├── README.md ├── ch8-q6-answer ├── guestbook-cr │ ├── .helmignore │ ├── Chart.yaml │ ├── templates │ │ ├── _helpers.tpl │ │ └── charts.helm.k8s.io_v1alpha1_guestbook_cr.yaml │ └── values.yaml └── guestbook-operator │ ├── .helmignore │ ├── Chart.yaml │ ├── crds │ └── charts.helm.k8s.io_guestbooks_crd.yaml │ ├── templates │ ├── _helpers.tpl │ ├── operator.yaml │ ├── role.yaml │ ├── role_binding.yaml │ └── service_account.yaml │ └── values.yaml ├── chart_schema.yaml ├── ct.yaml ├── guestbook-operator ├── build │ └── Dockerfile ├── deploy │ ├── crds │ │ ├── charts.helm.k8s.io_guestbooks_crd.yaml │ │ └── charts.helm.k8s.io_v1alpha1_guestbook_cr.yaml │ ├── operator.yaml │ ├── role.yaml │ ├── role_binding.yaml │ └── service_account.yaml ├── helm-charts │ └── guestbook │ │ ├── .helmignore │ │ ├── Chart.lock │ │ ├── Chart.yaml │ │ ├── charts │ │ └── redis-10.5.14.tgz │ │ ├── templates │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ ├── backup │ │ │ ├── job.yaml │ │ │ └── persistentvolumeclaim.yaml │ │ ├── deployment.yaml │ │ ├── ingress.yaml │ │ ├── restore │ │ │ └── job.yaml │ │ ├── service.yaml │ │ ├── serviceaccount.yaml │ │ └── test │ │ │ ├── backend-connection.yaml │ │ │ └── frontend-connection.yaml │ │ └── values.yaml └── watches.yaml ├── helm-charts ├── Jenkinsfile └── charts │ ├── guestbook │ ├── .gitignore │ ├── .helmignore │ ├── Chart.lock │ ├── Chart.yaml │ ├── templates │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ ├── backup │ │ │ ├── job.yaml │ │ │ └── persistentvolumeclaim.yaml │ │ ├── deployment.yaml │ │ ├── ingress.yaml │ │ ├── restore │ │ │ └── job.yaml │ │ ├── service.yaml │ │ ├── serviceaccount.yaml │ │ └── test │ │ │ ├── backend-connection.yaml │ │ │ └── frontend-connection.yaml │ └── values.yaml │ └── nginx │ ├── .helmignore │ ├── Chart.yaml │ ├── ci │ ├── clusterip-values.yaml │ └── nodeport-values.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ │ └── test-connection.yaml │ └── values.yaml ├── jenkins └── values.yaml └── nginx-cd ├── Jenkinsfile ├── common-values.yaml ├── dev └── values.yaml ├── prod └── values.yaml └── qa └── values.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | helm-charts/charts/**/charts/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Learn Helm 5 | 6 | Learn Helm 7 | 8 | This is the code repository for [Learn Helm](https://www.packtpub.com/cloud-networking/learn-helm?utm_source=github&utm_medium=repository&utm_campaign=9781839214295), published by Packt. 9 | 10 | **Improve productivity, reduce complexity, and speed up cloud-native adoption with Helm for Kubernetes** 11 | 12 | ## What is this book about? 13 | Containerization is currently known to be one of the best ways to implement DevOps. While Docker introduced containers and changed the DevOps era, Google developed an extensive container orchestration system, Kubernetes, which is now considered the frontrunner in container orchestration. With the help of this book, you’ll explore the efficiency of managing applications running on Kubernetes using Helm. 14 | 15 | This book covers the following exciting features: 16 | * Develop an enterprise automation strategy on Kubernetes using Helm 17 | * Create easily consumable and configurable Helm charts 18 | * Use Helm in orchestration tooling and Kubernetes operators 19 | * Explore best practices for application delivery and life cycle management 20 | * Leverage Helm in a secure and stable manner that is fit for your enterprise 21 | 22 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1839214295) today! 23 | 24 | https://www.packtpub.com/ 25 | 26 | ## Instructions and Navigations 27 | All of the code is organized into folders. For example, Chapter02. 28 | 29 | The code will look like the following: 30 | ``` 31 | if (test expression) 32 | { 33 | Statement upon condition is true 34 | } 35 | ``` 36 | 37 | **Following is what you need for this book:** 38 | This book is for Kubernetes developers or administrators who are interested in learning Helm to provide automation for application development on Kubernetes. Although no prior knowledge of Helm is required, basic knowledge of Kubernetes application development will be useful. 39 | 40 | With the following software and hardware list you can run all code files present in the book (Chapter 1-9). 41 | 42 | ### Software and Hardware List 43 | 44 | | Chapter | Software required | OS required | 45 | | -------- | ------------------------------------| -----------------------------------| 46 | | 1-9 | Minikube | Windows, macOS X, and Linux (Any) | 47 | | 1-9 | Kubectl | Windows, macOS X, and Linux (Any) | 48 | | 1-9 | Helm | Windows, macOS X, and Linux (Any) | 49 | 50 | 51 | 52 | We also provide a PDF file that has color images of the screenshots/diagrams used in this book. [Click here to download it](http://www.packtpub.com/sites/default/ 53 | files/downloads/9781839214295_ColorImages.pdf.). 54 | 55 | ## Code in Action 56 | 57 | Click on the following link to see the Code in Action: 58 | 59 | [YouTube](https://www.youtube.com/playlist?list=PLeLcvrwLe1850eF3_HJGpOuIDs-1Rnays) 60 | 61 | ## Errata 62 | * In Pages 44, 59, 60, 127, 146, 147, 148 and 207 : 63 | 64 | **https://charts.bitnami.com** _needs to be changed/replaced with_ **https://charts.bitnami.com/bitnami** 65 | 66 | * In **Table of Contents**: 67 | 68 | **Section 3: Adanced Deployment Patterns** _needs to be changed/replaced with_ **Section 3: Advanced Deployment Patterns** 69 | 70 | ### Related products 71 | * Kubernetes - A Complete DevOps Cookbook [[Packt]](https://www.packtpub.com/cloud-networking/kubernetes-a-complete-devops-cookbook?utm_source=github&utm_medium=repository&utm_campaign=9781838828042) [[Amazon]](https://www.amazon.com/dp/1838828044) 72 | 73 | * Hands-On Kubernetes on Windows [[Packt]](https://www.packtpub.com/cloud-networking/hands-on-kubernetes-on-windows?utm_source=github&utm_medium=repository&utm_campaign=9781838821562) [[Amazon]](https://www.amazon.com/dp/1838821562) 74 | 75 | ## Get to Know the Authors 76 | 77 | **Andrew Block** is a Senior Principal Consultant at Red Hat who guides organizations on adopting container solutions and microservices architectures using automation principles across an array of deployment targets. As the author of the "Application Release Strategies With OpenShift", he preaches the importance of Continuous Integration and Continuous Delivery methodologies with an emphasis on security to develop and deploy software faster. Andrew also serves as a manager of the Container Community of Practice within Red Hat which aims to foster awareness around the container ecosystem. 78 | 79 | **Austin Dewey** is a Senior Consultant at Red Hat focused on enabling customers in cloud and container technologies. He has helped drive success at many different Fortune 500 companies through his expertise in CI/CD and deployment patterns on Red Hat's Kubernetes-based PaaS, OpenShift Container Platform. Delivering projects centered around DevOps and automation, Austin has guided many different customers to production by building pipelines that ensure fast, stable, and secure deliveries. When Austin is not working with his customers or engaging in the Kubernetes community, he can be found playing guitar and spending time outdoors. 80 | 81 | 82 | ### Suggestions and Feedback 83 | [Click here](https://docs.google.com/forms/d/e/1FAIpQLSdy7dATC6QmEL81FIUuymZ0Wy9vH1jHkvpY57OiMeKGqib_Ow/viewform) if you have any feedback or suggestions. 84 | ### Download a free PDF 85 | 86 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
87 |

https://packt.link/free-ebook/9781839214295

-------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-cr/.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 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | .vscode/ 23 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-cr/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: guestbook-cr 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 | version: 0.1.0 18 | 19 | # This is the version number of the application being deployed. This version number should be 20 | # incremented each time you make changes to the application. 21 | appVersion: 1.16.0 22 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-cr/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "guestbook-cr.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "guestbook-cr.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "guestbook-cr.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "guestbook-cr.labels" -}} 38 | helm.sh/chart: {{ include "guestbook-cr.chart" . }} 39 | {{ include "guestbook-cr.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end -}} 45 | 46 | {{/* 47 | Selector labels 48 | */}} 49 | {{- define "guestbook-cr.selectorLabels" -}} 50 | app.kubernetes.io/name: {{ include "guestbook-cr.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end -}} 53 | 54 | {{/* 55 | Create the name of the service account to use 56 | */}} 57 | {{- define "guestbook-cr.serviceAccountName" -}} 58 | {{- if .Values.serviceAccount.create -}} 59 | {{ default (include "guestbook-cr.fullname" .) .Values.serviceAccount.name }} 60 | {{- else -}} 61 | {{ default "default" .Values.serviceAccount.name }} 62 | {{- end -}} 63 | {{- end -}} 64 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-cr/templates/charts.helm.k8s.io_v1alpha1_guestbook_cr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: charts.helm.k8s.io/v1alpha1 2 | kind: Guestbook 3 | metadata: 4 | name: {{ include "guestbook-cr.fullname" . }} 5 | spec: 6 | fullnameOverride: {{ .Values.fullnameOverride }} 7 | image: 8 | pullPolicy: {{ .Values.image.pullPolicy }} 9 | repository: {{ .Values.image.repository }} 10 | replicaCount: {{ .Values.replicaCount }} 11 | resources: {{ .Values.resources | toYaml }} 12 | service: 13 | port: {{ .Values.service.port }} 14 | type: {{ .Values.service.type }} 15 | serviceAccount: 16 | create: {{ .Values.serviceAccount.create }} 17 | name: {{ .Values.serviceAccount.name }} 18 | redis: 19 | configmap: appendonly no 20 | fullnameOverride: redis 21 | usePassword: false 22 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-cr/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for guestbook-cr. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: gcr.io/google-samples/gb-frontend 9 | pullPolicy: IfNotPresent 10 | 11 | fullnameOverride: example-guestbook 12 | 13 | serviceAccount: 14 | # Specifies whether a service account should be created 15 | create: true 16 | # The name of the service account to use. 17 | # If not set and create is true, a name is generated using the fullname template 18 | name: 19 | 20 | service: 21 | type: ClusterIP 22 | port: 80 23 | 24 | resources: {} 25 | # We usually recommend not to specify default resources and to leave this as a conscious 26 | # choice for the user. This also increases chances charts run on environments with little 27 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 28 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 29 | # limits: 30 | # cpu: 100m 31 | # memory: 128Mi 32 | # requests: 33 | # cpu: 100m 34 | # memory: 128Mi 35 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-operator/.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 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | .vscode/ 23 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-operator/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: guestbook-operator 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 | version: 0.1.0 18 | 19 | # This is the version number of the application being deployed. This version number should be 20 | # incremented each time you make changes to the application. 21 | appVersion: 1.16.0 22 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-operator/crds/charts.helm.k8s.io_guestbooks_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: guestbooks.charts.helm.k8s.io 5 | spec: 6 | group: charts.helm.k8s.io 7 | names: 8 | kind: Guestbook 9 | listKind: GuestbookList 10 | plural: guestbooks 11 | singular: guestbook 12 | scope: Namespaced 13 | subresources: 14 | status: {} 15 | validation: 16 | openAPIV3Schema: 17 | type: object 18 | x-kubernetes-preserve-unknown-fields: true 19 | versions: 20 | - name: v1alpha1 21 | served: true 22 | storage: true 23 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-operator/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "guestbook-operator.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "guestbook-operator.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "guestbook-operator.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "guestbook-operator.labels" -}} 38 | helm.sh/chart: {{ include "guestbook-operator.chart" . }} 39 | {{ include "guestbook-operator.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end -}} 45 | 46 | {{/* 47 | Selector labels 48 | */}} 49 | {{- define "guestbook-operator.selectorLabels" -}} 50 | app.kubernetes.io/name: {{ include "guestbook-operator.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end -}} 53 | 54 | {{/* 55 | Create the name of the service account to use 56 | */}} 57 | {{- define "guestbook-operator.serviceAccountName" -}} 58 | {{- if .Values.serviceAccount.create -}} 59 | {{ default (include "guestbook-operator.fullname" .) .Values.serviceAccount.name }} 60 | {{- else -}} 61 | {{ default "default" .Values.serviceAccount.name }} 62 | {{- end -}} 63 | {{- end -}} 64 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-operator/templates/operator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "guestbook-operator.fullname" . }} 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | name: {{ include "guestbook-operator.fullname" . }} 10 | template: 11 | metadata: 12 | labels: 13 | name: {{ include "guestbook-operator.fullname" . }} 14 | spec: 15 | serviceAccountName: {{ .Values.serviceAccount.name }} 16 | containers: 17 | - name: guestbook-operator 18 | # Replace this with the built image name 19 | image: REPLACE_IMAGE 20 | imagePullPolicy: Always 21 | env: 22 | - name: WATCH_NAMESPACE 23 | valueFrom: 24 | fieldRef: 25 | fieldPath: metadata.namespace 26 | - name: POD_NAME 27 | valueFrom: 28 | fieldRef: 29 | fieldPath: metadata.name 30 | - name: OPERATOR_NAME 31 | value: "guestbook-operator" 32 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-operator/templates/role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | name: {{ include "guestbook-operator.fullname" . }} 5 | rules: 6 | - apiGroups: 7 | - "" 8 | resources: 9 | - namespaces 10 | verbs: 11 | - get 12 | - apiGroups: 13 | - "" 14 | resources: 15 | - configmaps 16 | - secrets 17 | verbs: 18 | - '*' 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - events 23 | verbs: 24 | - create 25 | - apiGroups: 26 | - "" 27 | resources: 28 | - configmaps 29 | - serviceaccounts 30 | - services 31 | verbs: 32 | - '*' 33 | - apiGroups: 34 | - apps 35 | resources: 36 | - deployments 37 | - statefulsets 38 | verbs: 39 | - '*' 40 | - apiGroups: 41 | - monitoring.coreos.com 42 | resources: 43 | - servicemonitors 44 | verbs: 45 | - get 46 | - create 47 | - apiGroups: 48 | - apps 49 | resourceNames: 50 | - guestbook-operator 51 | resources: 52 | - deployments/finalizers 53 | verbs: 54 | - update 55 | - apiGroups: 56 | - "" 57 | resources: 58 | - pods 59 | verbs: 60 | - get 61 | - apiGroups: 62 | - apps 63 | resources: 64 | - replicasets 65 | - deployments 66 | verbs: 67 | - get 68 | - apiGroups: 69 | - charts.helm.k8s.io 70 | resources: 71 | - '*' 72 | verbs: 73 | - create 74 | - delete 75 | - get 76 | - list 77 | - patch 78 | - update 79 | - watch 80 | - apiGroups: 81 | - "" 82 | resources: 83 | - persistentvolumeclaims 84 | verbs: 85 | - create 86 | - delete 87 | - get 88 | - list 89 | - patch 90 | - update 91 | - watch 92 | - apiGroups: 93 | - batch 94 | resources: 95 | - jobs 96 | verbs: 97 | - create 98 | - delete 99 | - get 100 | - list 101 | - patch 102 | - update 103 | - watch 104 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-operator/templates/role_binding.yaml: -------------------------------------------------------------------------------- 1 | kind: RoleBinding 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ include "guestbook-operator.fullname" . }} 5 | subjects: 6 | - kind: ServiceAccount 7 | name: {{ .Values.serviceAccount.name }} 8 | roleRef: 9 | kind: Role 10 | name: guestbook-operator 11 | apiGroup: rbac.authorization.k8s.io 12 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-operator/templates/service_account.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "guestbook-operator.fullname" . }} 6 | {{- end }} 7 | -------------------------------------------------------------------------------- /ch8-q6-answer/guestbook-operator/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for guestbook-operator. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: nginx 9 | pullPolicy: IfNotPresent 10 | 11 | imagePullSecrets: [] 12 | nameOverride: "" 13 | fullnameOverride: "" 14 | 15 | serviceAccount: 16 | # Specifies whether a new service account should be created 17 | create: true 18 | # The name of the service account to use. 19 | # If not set and create is true, a name is generated using the fullname template 20 | name: guestbook-operator 21 | 22 | podSecurityContext: {} 23 | # fsGroup: 2000 24 | 25 | securityContext: {} 26 | # capabilities: 27 | # drop: 28 | # - ALL 29 | # readOnlyRootFilesystem: true 30 | # runAsNonRoot: true 31 | # runAsUser: 1000 32 | 33 | service: 34 | type: ClusterIP 35 | port: 80 36 | 37 | ingress: 38 | enabled: false 39 | annotations: {} 40 | # kubernetes.io/ingress.class: nginx 41 | # kubernetes.io/tls-acme: "true" 42 | hosts: 43 | - host: chart-example.local 44 | paths: [] 45 | tls: [] 46 | # - secretName: chart-example-tls 47 | # hosts: 48 | # - chart-example.local 49 | 50 | resources: {} 51 | # We usually recommend not to specify default resources and to leave this as a conscious 52 | # choice for the user. This also increases chances charts run on environments with little 53 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 54 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 55 | # limits: 56 | # cpu: 100m 57 | # memory: 128Mi 58 | # requests: 59 | # cpu: 100m 60 | # memory: 128Mi 61 | 62 | nodeSelector: {} 63 | 64 | tolerations: [] 65 | 66 | affinity: {} 67 | -------------------------------------------------------------------------------- /chart_schema.yaml: -------------------------------------------------------------------------------- 1 | name: str() 2 | home: str(required=False) 3 | version: str() 4 | apiVersion: str() 5 | appVersion: any(str(), num()) 6 | description: str() 7 | keywords: list(str(), required=False) 8 | sources: list(str(), required=False) 9 | maintainers: list(include('maintainer'), required=False) 10 | dependencies: list(include('dependency'), required=False) 11 | icon: str(required=False) 12 | engine: str(required=False) 13 | condition: str(required=False) 14 | tags: str(required=False) 15 | deprecated: bool(required=False) 16 | kubeVersion: str(required=False) 17 | annotations: map(str(), str(), required=False) 18 | type: str(required=False) 19 | --- 20 | maintainer: 21 | name: str() 22 | email: str(required=False) 23 | url: str(required=False) 24 | --- 25 | dependency: 26 | name: str() 27 | version: str() 28 | repository: str() 29 | condition: str(required=False) 30 | tags: list(str(), required=False) 31 | enabled: bool(required=False) 32 | import-values: any(list(str()), list(include('import-value')), required=False) 33 | alias: str(required=False) 34 | --- 35 | import-value: 36 | child: str() 37 | parent: str() 38 | -------------------------------------------------------------------------------- /ct.yaml: -------------------------------------------------------------------------------- 1 | chart-dirs: 2 | - helm-charts/charts 3 | 4 | chart-repos: 5 | - bitnami=https://charts.bitnami.com/bitnami 6 | 7 | validate-maintainers: false 8 | -------------------------------------------------------------------------------- /guestbook-operator/build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/operator-framework/helm-operator:v0.15.2 2 | 3 | COPY watches.yaml ${HOME}/watches.yaml 4 | COPY helm-charts/ ${HOME}/helm-charts/ 5 | -------------------------------------------------------------------------------- /guestbook-operator/deploy/crds/charts.helm.k8s.io_guestbooks_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: guestbooks.charts.helm.k8s.io 5 | spec: 6 | group: charts.helm.k8s.io 7 | names: 8 | kind: Guestbook 9 | listKind: GuestbookList 10 | plural: guestbooks 11 | singular: guestbook 12 | scope: Namespaced 13 | subresources: 14 | status: {} 15 | validation: 16 | openAPIV3Schema: 17 | type: object 18 | x-kubernetes-preserve-unknown-fields: true 19 | versions: 20 | - name: v1alpha1 21 | served: true 22 | storage: true 23 | -------------------------------------------------------------------------------- /guestbook-operator/deploy/crds/charts.helm.k8s.io_v1alpha1_guestbook_cr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: charts.helm.k8s.io/v1alpha1 2 | kind: Guestbook 3 | metadata: 4 | name: example-guestbook 5 | spec: 6 | # Default values copied from /helm-charts/guestbook/values.yaml 7 | 8 | affinity: {} 9 | fullnameOverride: "" 10 | image: 11 | pullPolicy: IfNotPresent 12 | repository: gcr.io/google-samples/gb-frontend 13 | imagePullSecrets: [] 14 | ingress: 15 | annotations: {} 16 | enabled: false 17 | hosts: 18 | - host: chart-example.local 19 | paths: [] 20 | tls: [] 21 | nameOverride: "" 22 | nodeSelector: {} 23 | podSecurityContext: {} 24 | redis: 25 | configmap: appendonly no 26 | fullnameOverride: redis 27 | usePassword: false 28 | replicaCount: 1 29 | resources: {} 30 | securityContext: {} 31 | service: 32 | port: 80 33 | type: NodePort 34 | serviceAccount: 35 | create: true 36 | name: null 37 | tolerations: [] 38 | 39 | -------------------------------------------------------------------------------- /guestbook-operator/deploy/operator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: guestbook-operator 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | name: guestbook-operator 10 | template: 11 | metadata: 12 | labels: 13 | name: guestbook-operator 14 | spec: 15 | serviceAccountName: guestbook-operator 16 | containers: 17 | - name: guestbook-operator 18 | # Replace this with the built image name 19 | image: REPLACE_IMAGE 20 | imagePullPolicy: Always 21 | env: 22 | - name: WATCH_NAMESPACE 23 | valueFrom: 24 | fieldRef: 25 | fieldPath: metadata.namespace 26 | - name: POD_NAME 27 | valueFrom: 28 | fieldRef: 29 | fieldPath: metadata.name 30 | - name: OPERATOR_NAME 31 | value: "guestbook-operator" 32 | -------------------------------------------------------------------------------- /guestbook-operator/deploy/role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | creationTimestamp: null 5 | name: guestbook-operator 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - namespaces 11 | verbs: 12 | - get 13 | - apiGroups: 14 | - "" 15 | resources: 16 | - configmaps 17 | - secrets 18 | verbs: 19 | - '*' 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - events 24 | verbs: 25 | - create 26 | - apiGroups: 27 | - "" 28 | resources: 29 | - configmaps 30 | - serviceaccounts 31 | - services 32 | verbs: 33 | - '*' 34 | - apiGroups: 35 | - apps 36 | resources: 37 | - deployments 38 | - statefulsets 39 | verbs: 40 | - '*' 41 | - apiGroups: 42 | - monitoring.coreos.com 43 | resources: 44 | - servicemonitors 45 | verbs: 46 | - get 47 | - create 48 | - apiGroups: 49 | - apps 50 | resourceNames: 51 | - guestbook-operator 52 | resources: 53 | - deployments/finalizers 54 | verbs: 55 | - update 56 | - apiGroups: 57 | - "" 58 | resources: 59 | - pods 60 | verbs: 61 | - get 62 | - apiGroups: 63 | - apps 64 | resources: 65 | - replicasets 66 | - deployments 67 | verbs: 68 | - get 69 | - apiGroups: 70 | - charts.helm.k8s.io 71 | resources: 72 | - '*' 73 | verbs: 74 | - create 75 | - delete 76 | - get 77 | - list 78 | - patch 79 | - update 80 | - watch 81 | - apiGroups: 82 | - "" 83 | resources: 84 | - persistentvolumeclaims 85 | verbs: 86 | - create 87 | - delete 88 | - get 89 | - list 90 | - patch 91 | - update 92 | - watch 93 | - apiGroups: 94 | - batch 95 | resources: 96 | - jobs 97 | verbs: 98 | - create 99 | - delete 100 | - get 101 | - list 102 | - patch 103 | - update 104 | - watch 105 | -------------------------------------------------------------------------------- /guestbook-operator/deploy/role_binding.yaml: -------------------------------------------------------------------------------- 1 | kind: RoleBinding 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: guestbook-operator 5 | subjects: 6 | - kind: ServiceAccount 7 | name: guestbook-operator 8 | roleRef: 9 | kind: Role 10 | name: guestbook-operator 11 | apiGroup: rbac.authorization.k8s.io 12 | -------------------------------------------------------------------------------- /guestbook-operator/deploy/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: guestbook-operator 5 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/.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 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | .vscode/ 23 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: redis 3 | repository: https://charts.bitnami.com/bitnami 4 | version: 10.5.14 5 | digest: sha256:8ed332017bb16ac6c5eec54ad76156d4c2337a5b122e8f7f7e4a0f189a1f9a9c 6 | generated: "2020-08-10T09:11:45.941984395-05:00" 7 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | appVersion: v4 3 | dependencies: 4 | - name: redis 5 | repository: https://charts.bitnami.com/bitnami 6 | version: 10.5.x 7 | description: A Helm chart for Kubernetes 8 | name: guestbook 9 | type: application 10 | version: 1.0.0 11 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/charts/redis-10.5.14.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/-Learn-Helm/13060ce36b48efbf5eed04dbb298d64792b530cc/guestbook-operator/helm-charts/guestbook/charts/redis-10.5.14.tgz -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/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 }}{{ . }} 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 "guestbook.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 "guestbook.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "guestbook.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 "guestbook.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | echo "Visit http://127.0.0.1:8080 to use your application" 20 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "guestbook.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "guestbook.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "guestbook.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "guestbook.labels" -}} 38 | helm.sh/chart: {{ include "guestbook.chart" . }} 39 | {{ include "guestbook.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end -}} 45 | 46 | {{/* 47 | Selector labels 48 | */}} 49 | {{- define "guestbook.selectorLabels" -}} 50 | app.kubernetes.io/name: {{ include "guestbook.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end -}} 53 | 54 | {{/* 55 | Create the name of the service account to use 56 | */}} 57 | {{- define "guestbook.serviceAccountName" -}} 58 | {{- if .Values.serviceAccount.create -}} 59 | {{ default (include "guestbook.fullname" .) .Values.serviceAccount.name }} 60 | {{- else -}} 61 | {{ default "default" .Values.serviceAccount.name }} 62 | {{- end -}} 63 | {{- end -}} 64 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/backup/job.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.redis.master.persistence.enabled }} 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: {{ include "guestbook.fullname" . }}-backup 6 | labels: 7 | {{- include "guestbook.labels" . | nindent 4 }} 8 | annotations: 9 | "helm.sh/hook": pre-upgrade 10 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded 11 | "helm.sh/hook-weight": "1" 12 | spec: 13 | template: 14 | spec: 15 | containers: 16 | - name: backup 17 | image: redis:alpine3.11 18 | command: ["/bin/sh", "-c"] 19 | args: ["redis-cli -h {{ .Values.redis.fullnameOverride }}-master save && cp /data/dump.rdb /backup/dump.rdb"] 20 | volumeMounts: 21 | - name: redis-data 22 | mountPath: /data 23 | - name: backup 24 | mountPath: /backup 25 | restartPolicy: Never 26 | volumes: 27 | - name: redis-data 28 | persistentVolumeClaim: 29 | claimName: redis-data-{{ .Values.redis.fullnameOverride }}-master-0 30 | - name: backup 31 | persistentVolumeClaim: 32 | claimName: redis-data-{{ .Values.redis.fullnameOverride }}-master-0-backup-{{ sub .Release.Revision 1 }} 33 | {{- end }} 34 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/backup/persistentvolumeclaim.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.redis.master.persistence.enabled }} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: redis-data-{{ .Values.redis.fullnameOverride }}-master-0-backup-{{ sub .Release.Revision 1 }} 6 | labels: 7 | {{- include "guestbook.labels" . | nindent 4 }} 8 | annotations: 9 | "helm.sh/hook": pre-upgrade 10 | "helm.sh/hook-weight": "0" 11 | spec: 12 | accessModes: 13 | - ReadWriteOnce 14 | resources: 15 | requests: 16 | storage: {{ .Values.redis.master.persistence.size }} 17 | {{- end }} 18 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }} 5 | labels: 6 | {{- include "guestbook.labels" . | nindent 4 }} 7 | spec: 8 | replicas: {{ .Values.replicaCount }} 9 | selector: 10 | matchLabels: 11 | {{- include "guestbook.selectorLabels" . | nindent 6 }} 12 | template: 13 | metadata: 14 | labels: 15 | {{- include "guestbook.selectorLabels" . | nindent 8 }} 16 | spec: 17 | {{- with .Values.imagePullSecrets }} 18 | imagePullSecrets: 19 | {{- toYaml . | nindent 8 }} 20 | {{- end }} 21 | serviceAccountName: {{ include "guestbook.serviceAccountName" . }} 22 | securityContext: 23 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 24 | containers: 25 | - name: {{ .Chart.Name }} 26 | securityContext: 27 | {{- toYaml .Values.securityContext | nindent 12 }} 28 | image: "{{ required "value 'image.repository' is required" .Values.image.repository }}:{{ .Chart.AppVersion }}" 29 | imagePullPolicy: {{ .Values.image.pullPolicy }} 30 | ports: 31 | - name: http 32 | containerPort: 80 33 | protocol: TCP 34 | livenessProbe: 35 | httpGet: 36 | path: / 37 | port: http 38 | readinessProbe: 39 | httpGet: 40 | path: / 41 | port: http 42 | resources: 43 | {{- toYaml .Values.resources | nindent 12 }} 44 | {{- with .Values.nodeSelector }} 45 | nodeSelector: 46 | {{- toYaml . | nindent 8 }} 47 | {{- end }} 48 | {{- with .Values.affinity }} 49 | affinity: 50 | {{- toYaml . | nindent 8 }} 51 | {{- end }} 52 | {{- with .Values.tolerations }} 53 | tolerations: 54 | {{- toYaml . | nindent 8 }} 55 | {{- end }} 56 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "guestbook.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 5 | apiVersion: networking.k8s.io/v1beta1 6 | {{- else -}} 7 | apiVersion: extensions/v1beta1 8 | {{- end }} 9 | kind: Ingress 10 | metadata: 11 | name: {{ $fullName }} 12 | labels: 13 | {{- include "guestbook.labels" . | nindent 4 }} 14 | {{- with .Values.ingress.annotations }} 15 | annotations: 16 | {{- toYaml . | nindent 4 }} 17 | {{- end }} 18 | spec: 19 | {{- if .Values.ingress.tls }} 20 | tls: 21 | {{- range .Values.ingress.tls }} 22 | - hosts: 23 | {{- range .hosts }} 24 | - {{ . | quote }} 25 | {{- end }} 26 | secretName: {{ .secretName }} 27 | {{- end }} 28 | {{- end }} 29 | rules: 30 | {{- range .Values.ingress.hosts }} 31 | - host: {{ .host | quote }} 32 | http: 33 | paths: 34 | {{- range .paths }} 35 | - path: {{ . }} 36 | backend: 37 | serviceName: {{ $fullName }} 38 | servicePort: {{ $svcPort }} 39 | {{- end }} 40 | {{- end }} 41 | {{- end }} 42 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/restore/job.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.redis.master.persistence.enabled }} 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: {{ include "guestbook.fullname" . }}-restore 6 | labels: 7 | {{- include "guestbook.labels" . | nindent 4 }} 8 | annotations: 9 | "helm.sh/hook": pre-rollback 10 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded 11 | spec: 12 | template: 13 | spec: 14 | containers: 15 | - name: restore 16 | image: redis:alpine3.11 17 | command: ["/bin/sh", "-c"] 18 | args: ["cp /backup/dump.rdb /data/dump.rdb && 19 | redis-cli -h {{ .Values.redis.fullnameOverride }}-master debug restart || true"] 20 | volumeMounts: 21 | - name: redis-data 22 | mountPath: /data 23 | - name: backup 24 | mountPath: /backup 25 | restartPolicy: Never 26 | volumes: 27 | - name: redis-data 28 | persistentVolumeClaim: 29 | claimName: redis-data-{{ .Values.redis.fullnameOverride }}-master-0 30 | - name: backup 31 | persistentVolumeClaim: 32 | claimName: redis-data-{{ .Values.redis.fullnameOverride }}-master-0-backup-{{ .Release.Revision }} 33 | {{- end }} 34 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }} 5 | labels: 6 | {{- include "guestbook.labels" . | nindent 4 }} 7 | spec: 8 | {{- $serviceTypes := list "ClusterIP" "NodePort" }} 9 | {{- if has .Values.service.type $serviceTypes }} 10 | type: {{ .Values.service.type }} 11 | {{- else }} 12 | {{- fail "value 'service.type' must be either 'ClusterIP' or 'NodePort'" }} 13 | {{- end }} 14 | ports: 15 | - port: {{ .Values.service.port }} 16 | targetPort: http 17 | protocol: TCP 18 | name: http 19 | selector: 20 | {{- include "guestbook.selectorLabels" . | nindent 4 }} 21 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "guestbook.serviceAccountName" . }} 6 | labels: 7 | {{ include "guestbook.labels" . | nindent 4 }} 8 | {{- end -}} 9 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/test/backend-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }}-test-backend-connection 5 | labels: 6 | {{- include "guestbook.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | "helm.sh/hook-delete-policy": before-hook-creation 10 | spec: 11 | containers: 12 | - name: test-backend-connection 13 | image: redis:alpine3.11 14 | command: ["/bin/sh", "-c"] 15 | args: ["redis-cli -h {{ .Values.redis.fullnameOverride }}-master MGET messages"] 16 | restartPolicy: Never 17 | 18 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/templates/test/frontend-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }}-test-frontend-connection 5 | labels: 6 | {{- include "guestbook.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | "helm.sh/hook-delete-policy": before-hook-creation 10 | spec: 11 | containers: 12 | - name: test-frontend-connection 13 | image: curlimages/curl:7.68.0 14 | command: ["/bin/sh", "-c"] 15 | args: ["curl {{ include "guestbook.fullname" . }}"] 16 | restartPolicy: Never 17 | -------------------------------------------------------------------------------- /guestbook-operator/helm-charts/guestbook/values.yaml: -------------------------------------------------------------------------------- 1 | affinity: {} 2 | fullnameOverride: "" 3 | image: 4 | pullPolicy: IfNotPresent 5 | repository: gcr.io/google-samples/gb-frontend 6 | imagePullSecrets: [] 7 | ingress: 8 | annotations: {} 9 | enabled: false 10 | hosts: 11 | - host: chart-example.local 12 | paths: [] 13 | tls: [] 14 | nameOverride: "" 15 | nodeSelector: {} 16 | podSecurityContext: {} 17 | redis: 18 | configmap: appendonly no 19 | fullnameOverride: redis 20 | usePassword: false 21 | replicaCount: 1 22 | resources: {} 23 | securityContext: {} 24 | service: 25 | port: 80 26 | type: NodePort 27 | serviceAccount: 28 | create: true 29 | name: null 30 | tolerations: [] 31 | -------------------------------------------------------------------------------- /guestbook-operator/watches.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - version: v1alpha1 3 | group: charts.helm.k8s.io 4 | kind: Guestbook 5 | chart: helm-charts/guestbook 6 | -------------------------------------------------------------------------------- /helm-charts/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent { label "chart-testing-agent" } 3 | options { 4 | buildDiscarder(logRotator(numToKeepStr: '10')) 5 | } 6 | stages { 7 | stage("Lint") { 8 | steps { 9 | container("chart-testing") { 10 | sh "ct lint" 11 | } 12 | } 13 | } 14 | stage("Install & Test") { 15 | steps { 16 | container("chart-testing") { 17 | sh "ct install --upgrade" 18 | } 19 | } 20 | } 21 | stage("Package Charts") { 22 | steps { 23 | script { 24 | container("chart-testing") { 25 | sh "helm package --dependency-update helm-charts/charts/*" 26 | } 27 | } 28 | } 29 | } 30 | stage("Push Charts to Chart Repo") { 31 | steps { 32 | script { 33 | container("chart-testing") { 34 | // Handle master -> main branch renaming 35 | def baseBranch = "main" 36 | if (env.GITHUB_PAGES_BASE_BRANCH) { 37 | baseBranch = env.GITHUB_PAGES_BASE_BRANCH 38 | } 39 | 40 | // Clone GitHub Pages repository to a folder called "chart-repo" 41 | sh "git clone ${env.GITHUB_PAGES_REPO_URL} chart-repo" 42 | 43 | // Determine if these charts should be pushed to "stable" or "staging" based on the branch 44 | def repoType 45 | if (env.BRANCH_NAME == baseBranch) { 46 | repoType = "stable" 47 | } else { 48 | repoType = "staging" 49 | } 50 | 51 | // Create the corresponding "stable" or "staging" folder if it does not exist 52 | def files = sh(script: "ls chart-repo", returnStdout: true) 53 | if (!files.contains(repoType)) { 54 | sh "mkdir chart-repo/${repoType}" 55 | } 56 | 57 | // Move packaged charts to the corresponding "stable" or "staging" folder 58 | sh "mv *.tgz chart-repo/${repoType}" 59 | 60 | // Generate the updated index.yaml 61 | sh "helm repo index chart-repo/${repoType}" 62 | 63 | // Update git config details 64 | sh "git config --global user.email 'chartrepo-robot@example.com'" 65 | sh "git config --global user.name 'chartrepo-robot'" 66 | 67 | dir("chart-repo") { 68 | // Add and commit the changes 69 | sh "git add --all" 70 | sh "git commit -m 'pushing charts from branch ${env.BRANCH_NAME}'" 71 | withCredentials([usernameColonPassword(credentialsId: 'github-auth', variable: 'USERPASS')]) { 72 | script { 73 | 74 | // Inject GitHub auth and push to the repo where charts are being served 75 | def authRepo = env.GITHUB_PAGES_REPO_URL.replace("://", "://${USERPASS}@") 76 | sh "git push ${authRepo} ${baseBranch}" 77 | } 78 | } 79 | } 80 | } 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/.gitignore: -------------------------------------------------------------------------------- 1 | charts/ 2 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/.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 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | .vscode/ 23 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: redis 3 | repository: https://charts.bitnami.com/bitnami 4 | version: 10.5.14 5 | digest: sha256:8ed332017bb16ac6c5eec54ad76156d4c2337a5b122e8f7f7e4a0f189a1f9a9c 6 | generated: "2020-08-10T09:11:16.113592194-05:00" 7 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: guestbook 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 | version: 1.0.0 18 | 19 | # This is the version number of the application being deployed. This version number should be 20 | # incremented each time you make changes to the application. 21 | appVersion: v4 22 | 23 | dependencies: 24 | - name: redis 25 | version: 10.5.x 26 | repository: https://charts.bitnami.com/bitnami 27 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/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 }}{{ . }} 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 "guestbook.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 "guestbook.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "guestbook.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 "guestbook.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | echo "Visit http://127.0.0.1:8080 to use your application" 20 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "guestbook.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "guestbook.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "guestbook.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "guestbook.labels" -}} 38 | helm.sh/chart: {{ include "guestbook.chart" . }} 39 | {{ include "guestbook.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end -}} 45 | 46 | {{/* 47 | Selector labels 48 | */}} 49 | {{- define "guestbook.selectorLabels" -}} 50 | app.kubernetes.io/name: {{ include "guestbook.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end -}} 53 | 54 | {{/* 55 | Create the name of the service account to use 56 | */}} 57 | {{- define "guestbook.serviceAccountName" -}} 58 | {{- if .Values.serviceAccount.create -}} 59 | {{ default (include "guestbook.fullname" .) .Values.serviceAccount.name }} 60 | {{- else -}} 61 | {{ default "default" .Values.serviceAccount.name }} 62 | {{- end -}} 63 | {{- end -}} 64 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/backup/job.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.redis.master.persistence.enabled }} 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: {{ include "guestbook.fullname" . }}-backup 6 | labels: 7 | {{- include "guestbook.labels" . | nindent 4 }} 8 | annotations: 9 | "helm.sh/hook": pre-upgrade 10 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded 11 | "helm.sh/hook-weight": "1" 12 | spec: 13 | template: 14 | spec: 15 | containers: 16 | - name: backup 17 | image: redis:alpine3.11 18 | command: ["/bin/sh", "-c"] 19 | args: ["redis-cli -h {{ .Values.redis.fullnameOverride }}-master save && cp /data/dump.rdb /backup/dump.rdb"] 20 | volumeMounts: 21 | - name: redis-data 22 | mountPath: /data 23 | - name: backup 24 | mountPath: /backup 25 | restartPolicy: Never 26 | volumes: 27 | - name: redis-data 28 | persistentVolumeClaim: 29 | claimName: redis-data-{{ .Values.redis.fullnameOverride }}-master-0 30 | - name: backup 31 | persistentVolumeClaim: 32 | claimName: redis-data-{{ .Values.redis.fullnameOverride }}-master-0-backup-{{ sub .Release.Revision 1 }} 33 | {{- end }} 34 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/backup/persistentvolumeclaim.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.redis.master.persistence.enabled }} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: redis-data-{{ .Values.redis.fullnameOverride }}-master-0-backup-{{ sub .Release.Revision 1 }} 6 | labels: 7 | {{- include "guestbook.labels" . | nindent 4 }} 8 | annotations: 9 | "helm.sh/hook": pre-upgrade 10 | "helm.sh/hook-weight": "0" 11 | spec: 12 | accessModes: 13 | - ReadWriteOnce 14 | resources: 15 | requests: 16 | storage: {{ .Values.redis.master.persistence.size }} 17 | {{- end }} 18 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }} 5 | labels: 6 | {{- include "guestbook.labels" . | nindent 4 }} 7 | spec: 8 | replicas: {{ .Values.replicaCount }} 9 | selector: 10 | matchLabels: 11 | {{- include "guestbook.selectorLabels" . | nindent 6 }} 12 | template: 13 | metadata: 14 | labels: 15 | {{- include "guestbook.selectorLabels" . | nindent 8 }} 16 | spec: 17 | {{- with .Values.imagePullSecrets }} 18 | imagePullSecrets: 19 | {{- toYaml . | nindent 8 }} 20 | {{- end }} 21 | serviceAccountName: {{ include "guestbook.serviceAccountName" . }} 22 | securityContext: 23 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 24 | containers: 25 | - name: {{ .Chart.Name }} 26 | securityContext: 27 | {{- toYaml .Values.securityContext | nindent 12 }} 28 | image: "{{ required "value 'image.repository' is required" .Values.image.repository }}:{{ .Chart.AppVersion }}" 29 | imagePullPolicy: {{ .Values.image.pullPolicy }} 30 | ports: 31 | - name: http 32 | containerPort: 80 33 | protocol: TCP 34 | livenessProbe: 35 | httpGet: 36 | path: / 37 | port: http 38 | readinessProbe: 39 | httpGet: 40 | path: / 41 | port: http 42 | resources: 43 | {{- toYaml .Values.resources | nindent 12 }} 44 | {{- with .Values.nodeSelector }} 45 | nodeSelector: 46 | {{- toYaml . | nindent 8 }} 47 | {{- end }} 48 | {{- with .Values.affinity }} 49 | affinity: 50 | {{- toYaml . | nindent 8 }} 51 | {{- end }} 52 | {{- with .Values.tolerations }} 53 | tolerations: 54 | {{- toYaml . | nindent 8 }} 55 | {{- end }} 56 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "guestbook.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 5 | apiVersion: networking.k8s.io/v1beta1 6 | {{- else -}} 7 | apiVersion: extensions/v1beta1 8 | {{- end }} 9 | kind: Ingress 10 | metadata: 11 | name: {{ $fullName }} 12 | labels: 13 | {{- include "guestbook.labels" . | nindent 4 }} 14 | {{- with .Values.ingress.annotations }} 15 | annotations: 16 | {{- toYaml . | nindent 4 }} 17 | {{- end }} 18 | spec: 19 | {{- if .Values.ingress.tls }} 20 | tls: 21 | {{- range .Values.ingress.tls }} 22 | - hosts: 23 | {{- range .hosts }} 24 | - {{ . | quote }} 25 | {{- end }} 26 | secretName: {{ .secretName }} 27 | {{- end }} 28 | {{- end }} 29 | rules: 30 | {{- range .Values.ingress.hosts }} 31 | - host: {{ .host | quote }} 32 | http: 33 | paths: 34 | {{- range .paths }} 35 | - path: {{ . }} 36 | backend: 37 | serviceName: {{ $fullName }} 38 | servicePort: {{ $svcPort }} 39 | {{- end }} 40 | {{- end }} 41 | {{- end }} 42 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/restore/job.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.redis.master.persistence.enabled }} 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: {{ include "guestbook.fullname" . }}-restore 6 | labels: 7 | {{- include "guestbook.labels" . | nindent 4 }} 8 | annotations: 9 | "helm.sh/hook": pre-rollback 10 | "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded 11 | spec: 12 | template: 13 | spec: 14 | containers: 15 | - name: restore 16 | image: redis:alpine3.11 17 | command: ["/bin/sh", "-c"] 18 | args: ["cp /backup/dump.rdb /data/dump.rdb && 19 | redis-cli -h {{ .Values.redis.fullnameOverride }}-master debug restart || true"] 20 | volumeMounts: 21 | - name: redis-data 22 | mountPath: /data 23 | - name: backup 24 | mountPath: /backup 25 | restartPolicy: Never 26 | volumes: 27 | - name: redis-data 28 | persistentVolumeClaim: 29 | claimName: redis-data-{{ .Values.redis.fullnameOverride }}-master-0 30 | - name: backup 31 | persistentVolumeClaim: 32 | claimName: redis-data-{{ .Values.redis.fullnameOverride }}-master-0-backup-{{ .Release.Revision }} 33 | {{- end }} 34 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }} 5 | labels: 6 | {{- include "guestbook.labels" . | nindent 4 }} 7 | spec: 8 | {{- $serviceTypes := list "ClusterIP" "NodePort" }} 9 | {{- if has .Values.service.type $serviceTypes }} 10 | type: {{ .Values.service.type }} 11 | {{- else }} 12 | {{- fail "value 'service.type' must be either 'ClusterIP' or 'NodePort'" }} 13 | {{- end }} 14 | ports: 15 | - port: {{ .Values.service.port }} 16 | targetPort: http 17 | protocol: TCP 18 | name: http 19 | selector: 20 | {{- include "guestbook.selectorLabels" . | nindent 4 }} 21 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "guestbook.serviceAccountName" . }} 6 | labels: 7 | {{ include "guestbook.labels" . | nindent 4 }} 8 | {{- end -}} 9 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/test/backend-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }}-test-backend-connection 5 | labels: 6 | {{- include "guestbook.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | "helm.sh/hook-delete-policy": before-hook-creation 10 | spec: 11 | containers: 12 | - name: test-backend-connection 13 | image: redis:alpine3.11 14 | command: ["/bin/sh", "-c"] 15 | args: ["redis-cli -h {{ .Values.redis.fullnameOverride }}-master MGET messages"] 16 | restartPolicy: Never 17 | 18 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/templates/test/frontend-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }}-test-frontend-connection 5 | labels: 6 | {{- include "guestbook.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | "helm.sh/hook-delete-policy": before-hook-creation 10 | spec: 11 | containers: 12 | - name: test-frontend-connection 13 | image: curlimages/curl:7.68.0 14 | command: ["/bin/sh", "-c"] 15 | args: ["curl {{ include "guestbook.fullname" . }}"] 16 | restartPolicy: Never 17 | -------------------------------------------------------------------------------- /helm-charts/charts/guestbook/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for guestbook. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: gcr.io/google-samples/gb-frontend 9 | pullPolicy: IfNotPresent 10 | 11 | imagePullSecrets: [] 12 | nameOverride: "" 13 | fullnameOverride: "" 14 | 15 | serviceAccount: 16 | # Specifies whether a service account should be created 17 | create: true 18 | # The name of the service account to use. 19 | # If not set and create is true, a name is generated using the fullname template 20 | name: 21 | 22 | podSecurityContext: {} 23 | # fsGroup: 2000 24 | 25 | securityContext: {} 26 | # capabilities: 27 | # drop: 28 | # - ALL 29 | # readOnlyRootFilesystem: true 30 | # runAsNonRoot: true 31 | # runAsUser: 1000 32 | 33 | service: 34 | type: NodePort 35 | port: 80 36 | 37 | ingress: 38 | enabled: false 39 | annotations: {} 40 | # kubernetes.io/ingress.class: nginx 41 | # kubernetes.io/tls-acme: "true" 42 | hosts: 43 | - host: chart-example.local 44 | paths: [] 45 | tls: [] 46 | # - secretName: chart-example-tls 47 | # hosts: 48 | # - chart-example.local 49 | 50 | resources: {} 51 | # We usually recommend not to specify default resources and to leave this as a conscious 52 | # choice for the user. This also increases chances charts run on environments with little 53 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 54 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 55 | # limits: 56 | # cpu: 100m 57 | # memory: 128Mi 58 | # requests: 59 | # cpu: 100m 60 | # memory: 128Mi 61 | 62 | nodeSelector: {} 63 | 64 | tolerations: [] 65 | 66 | affinity: {} 67 | 68 | redis: 69 | # Override the redis.fullname template 70 | fullnameOverride: redis 71 | # Enable unauthenticated access to Redis 72 | usePassword: false 73 | # Disable AOF persistence 74 | configmap: |- 75 | appendonly no 76 | -------------------------------------------------------------------------------- /helm-charts/charts/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 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | .vscode/ 23 | -------------------------------------------------------------------------------- /helm-charts/charts/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 | version: 1.0.0 18 | 19 | # This is the version number of the application being deployed. This version number should be 20 | # incremented each time you make changes to the application. 21 | appVersion: 1.16.0 22 | 23 | maintainers: 24 | - name: PacktPublishing 25 | -------------------------------------------------------------------------------- /helm-charts/charts/nginx/ci/clusterip-values.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | type: ClusterIP 3 | -------------------------------------------------------------------------------- /helm-charts/charts/nginx/ci/nodeport-values.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | type: NodePort 3 | -------------------------------------------------------------------------------- /helm-charts/charts/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 }}{{ . }} 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 | echo "Visit http://127.0.0.1:8080 to use your application" 20 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /helm-charts/charts/nginx/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "nginx.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "nginx.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "nginx.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "nginx.labels" -}} 38 | helm.sh/chart: {{ include "nginx.chart" . }} 39 | {{ include "nginx.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end -}} 45 | 46 | {{/* 47 | Selector labels 48 | */}} 49 | {{- define "nginx.selectorLabels" -}} 50 | app.kubernetes.io/name: {{ include "nginx.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end -}} 53 | 54 | {{/* 55 | Create the name of the service account to use 56 | */}} 57 | {{- define "nginx.serviceAccountName" -}} 58 | {{- if .Values.serviceAccount.create -}} 59 | {{ default (include "nginx.fullname" .) .Values.serviceAccount.name }} 60 | {{- else -}} 61 | {{ default "default" .Values.serviceAccount.name }} 62 | {{- end -}} 63 | {{- end -}} 64 | -------------------------------------------------------------------------------- /helm-charts/charts/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 | replicas: {{ .Values.replicaCount }} 9 | selector: 10 | matchLabels: 11 | {{- include "nginx.selectorLabels" . | nindent 6 }} 12 | template: 13 | metadata: 14 | labels: 15 | {{- include "nginx.selectorLabels" . | nindent 8 }} 16 | spec: 17 | {{- with .Values.imagePullSecrets }} 18 | imagePullSecrets: 19 | {{- toYaml . | nindent 8 }} 20 | {{- end }} 21 | serviceAccountName: {{ include "nginx.serviceAccountName" . }} 22 | securityContext: 23 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 24 | containers: 25 | - name: {{ .Chart.Name }} 26 | securityContext: 27 | {{- toYaml .Values.securityContext | nindent 12 }} 28 | image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" 29 | imagePullPolicy: {{ .Values.image.pullPolicy }} 30 | {{- if .Values.env }} 31 | env: 32 | {{- toYaml .Values.env | nindent 12 }} 33 | {{- end }} 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | protocol: TCP 38 | livenessProbe: 39 | httpGet: 40 | path: / 41 | port: http 42 | readinessProbe: 43 | httpGet: 44 | path: / 45 | port: http 46 | resources: 47 | {{- toYaml .Values.resources | nindent 12 }} 48 | {{- with .Values.nodeSelector }} 49 | nodeSelector: 50 | {{- toYaml . | nindent 8 }} 51 | {{- end }} 52 | {{- with .Values.affinity }} 53 | affinity: 54 | {{- toYaml . | nindent 8 }} 55 | {{- end }} 56 | {{- with .Values.tolerations }} 57 | tolerations: 58 | {{- toYaml . | nindent 8 }} 59 | {{- end }} 60 | -------------------------------------------------------------------------------- /helm-charts/charts/nginx/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "nginx.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 5 | apiVersion: networking.k8s.io/v1beta1 6 | {{- else -}} 7 | apiVersion: extensions/v1beta1 8 | {{- end }} 9 | kind: Ingress 10 | metadata: 11 | name: {{ $fullName }} 12 | labels: 13 | {{- include "nginx.labels" . | nindent 4 }} 14 | {{- with .Values.ingress.annotations }} 15 | annotations: 16 | {{- toYaml . | nindent 4 }} 17 | {{- end }} 18 | spec: 19 | {{- if .Values.ingress.tls }} 20 | tls: 21 | {{- range .Values.ingress.tls }} 22 | - hosts: 23 | {{- range .hosts }} 24 | - {{ . | quote }} 25 | {{- end }} 26 | secretName: {{ .secretName }} 27 | {{- end }} 28 | {{- end }} 29 | rules: 30 | {{- range .Values.ingress.hosts }} 31 | - host: {{ .host | quote }} 32 | http: 33 | paths: 34 | {{- range .paths }} 35 | - path: {{ . }} 36 | backend: 37 | serviceName: {{ $fullName }} 38 | servicePort: {{ $svcPort }} 39 | {{- end }} 40 | {{- end }} 41 | {{- end }} 42 | -------------------------------------------------------------------------------- /helm-charts/charts/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 | -------------------------------------------------------------------------------- /helm-charts/charts/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 | {{- end -}} 9 | -------------------------------------------------------------------------------- /helm-charts/charts/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-success 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 | -------------------------------------------------------------------------------- /helm-charts/charts/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: 1 6 | 7 | image: 8 | repository: nginx 9 | pullPolicy: IfNotPresent 10 | 11 | imagePullSecrets: [] 12 | nameOverride: "" 13 | fullnameOverride: "" 14 | 15 | env: [] 16 | 17 | serviceAccount: 18 | # Specifies whether a service account should be created 19 | create: true 20 | # The name of the service account to use. 21 | # If not set and create is true, a name is generated using the fullname template 22 | name: 23 | 24 | podSecurityContext: {} 25 | # fsGroup: 2000 26 | 27 | securityContext: {} 28 | # capabilities: 29 | # drop: 30 | # - ALL 31 | # readOnlyRootFilesystem: true 32 | # runAsNonRoot: true 33 | # runAsUser: 1000 34 | 35 | service: 36 | type: ClusterIP 37 | port: 80 38 | 39 | ingress: 40 | enabled: false 41 | annotations: {} 42 | # kubernetes.io/ingress.class: nginx 43 | # kubernetes.io/tls-acme: "true" 44 | hosts: 45 | - host: chart-example.local 46 | paths: [] 47 | tls: [] 48 | # - secretName: chart-example-tls 49 | # hosts: 50 | # - chart-example.local 51 | 52 | resources: {} 53 | # We usually recommend not to specify default resources and to leave this as a conscious 54 | # choice for the user. This also increases chances charts run on environments with little 55 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 56 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 57 | # limits: 58 | # cpu: 100m 59 | # memory: 128Mi 60 | # requests: 61 | # cpu: 100m 62 | # memory: 128Mi 63 | 64 | nodeSelector: {} 65 | 66 | tolerations: [] 67 | 68 | affinity: {} 69 | -------------------------------------------------------------------------------- /jenkins/values.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | tag: 2.222.4 3 | resources: 4 | limits: 5 | cpu: 500m 6 | memory: 2Gi 7 | service: 8 | master: 9 | type: NodePort 10 | serviceAccount: 11 | master: 12 | create: true 13 | agent: 14 | create: true 15 | rbac: 16 | master: 17 | create: true 18 | rules: 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - pods 23 | verbs: 24 | - create 25 | - delete 26 | - get 27 | - list 28 | - watch 29 | - apiGroups: 30 | - "" 31 | resources: 32 | - pods/exec 33 | verbs: 34 | - get 35 | agent: 36 | create: true 37 | rules: 38 | - apiGroups: 39 | - "" 40 | resources: 41 | - pods 42 | - pods/log 43 | - services 44 | - configmaps 45 | - secrets 46 | - serviceaccounts 47 | - persistentvolumeclaims 48 | - namespaces 49 | - events 50 | verbs: 51 | - get 52 | - list 53 | - update 54 | - watch 55 | - create 56 | - delete 57 | - apiGroups: 58 | - "apps" 59 | resources: 60 | - statefulsets 61 | - deployments 62 | - replicasets 63 | verbs: 64 | - get 65 | - list 66 | - update 67 | - watch 68 | - create 69 | - delete 70 | persistence: 71 | size: 2Gi 72 | javaOpts: >- 73 | -Dhudson.slaves.NodeProvisioner.initialDelay=0 74 | -Dhudson.model.LoadStatistics.decay=0.7 75 | -Dhudson.slaves.NodeProvisioner.MARGIN=30 76 | -Dhudson.slaves.NodeProvisioner.MARGIN0=0.6 77 | -XX:+UnlockExperimentalVMOptions 78 | -XX:+UseCGroupMemoryLimitForHeap 79 | -XX:MaxRAMFraction=2 80 | -XshowSettings:vm 81 | -Djenkins.install.runSetupWizard=false 82 | referenceContent: 83 | - data: 84 | - fileName: plugins.txt 85 | fileContent: | 86 | configuration-as-code:1.46 87 | git:4.5.2 88 | job-dsl:1.77 89 | kubernetes:1.26.0 90 | workflow-aggregator:2.6 91 | 92 | - fileName: jenkins.yaml 93 | fileContent: | 94 | credentials: 95 | system: 96 | domainCredentials: 97 | - credentials: 98 | - usernamePassword: 99 | scope: GLOBAL 100 | id: github-auth 101 | username: {{ required "value 'githubUsername' is required" .Values.githubUsername }} 102 | password: {{ required "value 'githubPassword' is required" .Values.githubPassword }} 103 | description: Password to authenticate with GitHub 104 | jenkins: 105 | numExecutors: 0 106 | clouds: 107 | - kubernetes: 108 | name: kubernetes 109 | serverUrl: https://kubernetes.default 110 | namespace: {{ .Release.Namespace }} 111 | jenkinsUrl: http://{{ include "jenkins.fullname" . }}-master:{{ .Values.service.master.port }} 112 | jenkinsTunnel: {{ include "jenkins.fullname" . }}-agent:{{ .Values.service.agent.port }} 113 | templates: 114 | - name: chart-testing-agent 115 | label: chart-testing-agent 116 | idleMinutes: 0 117 | namespace: {{ .Release.Namespace }} 118 | nodeUsageMode: NORMAL 119 | serviceAccount: {{ if .Values.serviceAccount.agent.name }}{{ .Values.serviceAccount.agent.name }}{{ else }}{{ include "jenkins.fullname" . }}-agent{{ end }} 120 | containers: 121 | - name: chart-testing 122 | image: quay.io/helmpack/chart-testing:v3.0.0-beta.1 123 | ttyEnabled: true 124 | resourceLimitCpu: 200m 125 | resourceLimitMemory: 500Mi 126 | envVars: 127 | - envVar: 128 | key: GITHUB_PAGES_REPO_URL 129 | value: {{ required "value 'githubPagesRepoUrl' is required" .Values.githubPagesRepoUrl }} 130 | - envVar: 131 | key: GITHUB_PAGES_SITE_URL 132 | value: {{ .Values.githubPagesSiteUrl }} 133 | - envVar: 134 | key: GITHUB_PAGES_BASE_BRANCH 135 | value: {{ .Values.githubPagesBaseBranch }} 136 | jobs: 137 | - script: |- 138 | multibranchPipelineJob('Test and Release Helm Charts') { 139 | factory { 140 | workflowBranchProjectFactory { 141 | scriptPath('helm-charts/Jenkinsfile') 142 | } 143 | } 144 | branchSources { 145 | git { 146 | id('test') 147 | remote({{ required "value 'githubForkUrl' is required" .Values.githubForkUrl | quote }}) 148 | credentialsId('github-auth') 149 | } 150 | } 151 | orphanedItemStrategy { 152 | discardOldItems { 153 | numToKeep(10) 154 | } 155 | } 156 | } 157 | {{- /* 158 | The below job will be configured if the githubPagesSiteUrl value has been configured. 159 | This will imply that the reader is on the CD portion of Chapter 7, and that this 160 | job is now relevant and should be displayed. 161 | */ -}} 162 | {{- if .Values.githubPagesSiteUrl }} 163 | multibranchPipelineJob('Deploy NGINX Chart') { 164 | factory { 165 | workflowBranchProjectFactory { 166 | scriptPath('nginx-cd/Jenkinsfile') 167 | } 168 | } 169 | branchSources { 170 | git { 171 | id('test') 172 | remote({{ required "value 'githubForkUrl' is required" .Values.githubForkUrl | quote }}) 173 | credentialsId('github-auth') 174 | } 175 | } 176 | orphanedItemStrategy { 177 | discardOldItems { 178 | numToKeep(10) 179 | } 180 | } 181 | } 182 | {{- end }} 183 | -------------------------------------------------------------------------------- /nginx-cd/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent { label "chart-testing-agent" } 3 | options { 4 | buildDiscarder(logRotator(numToKeepStr: '10')) 5 | } 6 | stages { 7 | stage("Setup") { 8 | steps { 9 | container("chart-testing") { 10 | sh "helm repo add learnhelm ${env.GITHUB_PAGES_SITE_URL}" 11 | } 12 | } 13 | } 14 | stage("Deploy to Dev") { 15 | steps { 16 | container("chart-testing") { 17 | dir("nginx-cd") { 18 | sh "helm upgrade --install nginx-${env.BRANCH_NAME} learnhelm/nginx --values common-values.yaml --values dev/values.yaml -n dev --wait" 19 | } 20 | } 21 | } 22 | } 23 | stage("Smoke Test") { 24 | steps { 25 | container("chart-testing") { 26 | sh "helm test nginx-${env.BRANCH_NAME} -n dev" 27 | } 28 | } 29 | } 30 | stage("Deploy to QA") { 31 | when { 32 | expression { 33 | return env.BRANCH_NAME == "master" 34 | } 35 | } 36 | steps { 37 | container("chart-testing") { 38 | dir("nginx-cd") { 39 | sh "helm upgrade --install nginx-${env.BRANCH_NAME} learnhelm/nginx --values common-values.yaml --values qa/values.yaml -n qa --wait" 40 | } 41 | } 42 | } 43 | } 44 | stage("Wait for Input") { 45 | when { 46 | expression { 47 | return env.BRANCH_NAME == "master" 48 | } 49 | } 50 | steps { 51 | container("chart-testing") { 52 | input "Deploy to Prod?" 53 | } 54 | } 55 | } 56 | stage("Deploy to Prod") { 57 | when { 58 | expression { 59 | return env.BRANCH_NAME == "master" 60 | } 61 | } 62 | steps { 63 | container("chart-testing") { 64 | dir("nginx-cd") { 65 | sh "helm upgrade --install nginx-${env.BRANCH_NAME} learnhelm/nginx --values common-values.yaml --values prod/values.yaml -n prod --wait" 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /nginx-cd/common-values.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | type: NodePort -------------------------------------------------------------------------------- /nginx-cd/dev/values.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | - name: ENVIRONMENT 3 | value: dev -------------------------------------------------------------------------------- /nginx-cd/prod/values.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | - name: ENVIRONMENT 3 | value: prod -------------------------------------------------------------------------------- /nginx-cd/qa/values.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | - name: ENVIRONMENT 3 | value: qa --------------------------------------------------------------------------------