├── azure-vote-mysql ├── Dockerfile └── azurevote.sql ├── charts └── azure-voting-app │ ├── Chart.yaml │ ├── .helmignore │ ├── templates │ ├── azure-vote-front-svc.yaml │ ├── azure-vote-back-svc.yaml │ ├── secret.yaml │ ├── pvc.yaml │ ├── _helpers.tpl │ ├── NOTES.txt │ ├── azure-vote-front-deployment.yaml │ └── azure-vote-back-deployment.yaml │ └── values.yaml ├── azure-vote ├── azure-vote │ ├── config_file.cfg │ ├── templates │ │ └── index.html │ ├── static │ │ └── default.css │ └── main.py └── Dockerfile ├── kubernetes-manifests ├── pod-secrets.yaml ├── services.yaml ├── storage-resources.yaml ├── azure-vote-deployment.yaml └── azure-vote-all-in-one.yaml ├── README.md ├── docker-compose.yaml ├── LICENSE └── .gitignore /azure-vote-mysql/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mysql 2 | ADD azurevote.sql /docker-entrypoint-initdb.d -------------------------------------------------------------------------------- /charts/azure-voting-app/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | description: A Helm chart for Azure Voting App 3 | name: azure-voting-app 4 | version: 0.1.0 5 | -------------------------------------------------------------------------------- /azure-vote-mysql/azurevote.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `azurevote`.`azurevote` (`voteid` INT NOT NULL AUTO_INCREMENT,`votevalue` VARCHAR(45) NULL,PRIMARY KEY (`voteid`)); -------------------------------------------------------------------------------- /azure-vote/azure-vote/config_file.cfg: -------------------------------------------------------------------------------- 1 | # UI Configurations 2 | TITLE = 'Azure Voting App' 3 | VOTE1VALUE = 'Cats' 4 | VOTE2VALUE = 'Dogs' 5 | SHOWHOST = 'false' -------------------------------------------------------------------------------- /azure-vote/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/uwsgi-nginx-flask:flask 2 | 3 | RUN apt-get update && \ 4 | apt-get install libmysqlclient-dev -y && \ 5 | pip install flask-mysql 6 | 7 | ADD /azure-vote /app -------------------------------------------------------------------------------- /kubernetes-manifests/pod-secrets.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: azure-vote 5 | type: Opaque 6 | data: 7 | MYSQL_USER: ZGJ1c2Vy 8 | MYSQL_PASSWORD: UGFzc3dvcmQxMg== 9 | MYSQL_DATABASE: YXp1cmV2b3Rl 10 | MYSQL_HOST: YXp1cmUtdm90ZS1iYWNr 11 | MYSQL_ROOT_PASSWORD: UGFzc3dvcmQxMg== -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 4 | -------------------------------------------------------------------------------- /kubernetes-manifests/services.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: azure-vote-back 5 | spec: 6 | ports: 7 | - port: 3306 8 | selector: 9 | app: azure-vote-back 10 | --- 11 | apiVersion: v1 12 | kind: Service 13 | metadata: 14 | name: azure-vote-front 15 | spec: 16 | type: LoadBalancer 17 | ports: 18 | - port: 80 19 | selector: 20 | app: azure-vote-front -------------------------------------------------------------------------------- /kubernetes-manifests/storage-resources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: slow 5 | provisioner: kubernetes.io/azure-disk 6 | parameters: 7 | skuName: Standard_LRS 8 | location: eastus 9 | --- 10 | apiVersion: v1 11 | kind: PersistentVolumeClaim 12 | metadata: 13 | name: mysql-pv-claim 14 | spec: 15 | accessModes: 16 | - ReadWriteOnce 17 | resources: 18 | requests: 19 | storage: 1Gi -------------------------------------------------------------------------------- /charts/azure-voting-app/.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 | -------------------------------------------------------------------------------- /charts/azure-voting-app/templates/azure-vote-front-svc.yaml: -------------------------------------------------------------------------------- 1 | {{- $serviceName := include "name" . -}} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ $serviceName }}-{{ .Values.azureVoteFront.service.name }} 6 | labels: 7 | {{ include "labels.standard" . | indent 4 }} 8 | spec: 9 | type: {{ .Values.azureVoteFront.service.type }} 10 | ports: 11 | - port: {{ .Values.azureVoteFront.service.externalPort }} 12 | selector: 13 | app: {{ include "name" . }} 14 | component: {{ $serviceName }}-{{ .Values.azureVoteFront.service.name }} 15 | release: {{ .Release.Name }} -------------------------------------------------------------------------------- /charts/azure-voting-app/templates/azure-vote-back-svc.yaml: -------------------------------------------------------------------------------- 1 | {{- $serviceName := include "name" . -}} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ $serviceName }}-{{ .Values.azureVoteBack.service.name }} 6 | labels: 7 | {{ include "labels.standard" . | indent 4 }} 8 | spec: 9 | type: {{ .Values.azureVoteBack.service.type }} 10 | ports: 11 | - port: {{ .Values.azureVoteBack.service.externalPort }} 12 | name: mysql 13 | selector: 14 | app: {{ include "name" . }} 15 | component: {{ $serviceName }}-{{ .Values.azureVoteBack.deployment.name }} 16 | release: {{ .Release.Name }} 17 | -------------------------------------------------------------------------------- /charts/azure-voting-app/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- $serviceName := include "name" . -}} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ $serviceName }}-azure-vote 6 | labels: 7 | {{ include "labels.standard" . | indent 4 }} 8 | type: Opaque 9 | data: 10 | MYSQL_USER: {{ .Values.mysql.user | b64enc | quote }} 11 | MYSQL_PASSWORD: {{ .Values.mysql.password | b64enc | quote }} 12 | MYSQL_DATABASE: {{ .Values.mysql.database | b64enc | quote }} 13 | MYSQL_HOST: {{ printf "%s-%s" $serviceName .Values.azureVoteBack.service.name | b64enc | quote }} 14 | MYSQL_ROOT_PASSWORD: {{ .Values.mysql.rootPassword | b64enc | quote }} -------------------------------------------------------------------------------- /charts/azure-voting-app/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.persistence.enabled -}} 2 | {{- $serviceName := include "name" . -}} 3 | apiVersion: v1 4 | kind: PersistentVolumeClaim 5 | metadata: 6 | name: {{ $serviceName }}-mysql-pv-claim 7 | labels: 8 | {{ include "labels.standard" . | indent 4 }} 9 | annotations: 10 | {{- if .Values.persistence.storageClass }} 11 | volume.beta.kubernetes.io/storage-class: {{ .Values.persistence.storageClass }} 12 | {{- else }} 13 | volume.alpha.kubernetes.io/storage-class: default 14 | {{- end }} 15 | spec: 16 | accessModes: 17 | - {{ .Values.persistence.accessMode | quote }} 18 | resources: 19 | requests: 20 | storage: {{ .Values.persistence.size | quote }} 21 | {{- end }} -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | azure-vote-back: 4 | build: ./azure-vote-mysql 5 | image: azure-vote-back 6 | container_name: azure-vote-back 7 | environment: 8 | MYSQL_USER: dbuser 9 | MYSQL_PASSWORD: Password12 10 | MYSQL_DATABASE: azurevote 11 | MYSQL_ROOT_PASSWORD: Password12 12 | ports: 13 | - "3306:3306" 14 | 15 | azure-vote-front: 16 | build: ./azure-vote 17 | depends_on: 18 | - azure-vote-back 19 | image: azure-vote-front 20 | container_name: azure-vote-front 21 | environment: 22 | MYSQL_USER: dbuser 23 | MYSQL_PASSWORD: Password12 24 | MYSQL_DATABASE: azurevote 25 | MYSQL_HOST: azure-vote-back 26 | ports: 27 | - "8080:80" -------------------------------------------------------------------------------- /azure-vote/azure-vote/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{title}} 6 | 7 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 |
{{button1}} - {{ value1 }} | {{button2}} - {{ value2 }}
25 |
26 |
27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 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 | -------------------------------------------------------------------------------- /charts/azure-voting-app/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "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 | */}} 13 | {{- define "fullname" -}} 14 | {{- $name := default .Chart.Name .Values.nameOverride -}} 15 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 16 | {{- end -}} 17 | 18 | {{- /* 19 | Credit: @technosophos 20 | https://github.com/technosophos/common-chart/ 21 | labels.standard prints the standard Helm labels. 22 | The standard labels are frequently used in metadata. 23 | */ -}} 24 | {{- define "labels.standard" -}} 25 | app: {{ template "name" . }} 26 | heritage: {{ .Release.Service | quote }} 27 | release: {{ .Release.Name | quote }} 28 | chart: {{ template "chartref" . }} 29 | {{- end -}} 30 | 31 | {{- /* 32 | Credit: @technosophos 33 | https://github.com/technosophos/common-chart/ 34 | chartref prints a chart name and version. 35 | It does minimal escaping for use in Kubernetes labels. 36 | Example output: 37 | zookeeper-1.2.3 38 | wordpress-3.2.1_20170219 39 | */ -}} 40 | {{- define "chartref" -}} 41 | {{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} 42 | {{- end -}} -------------------------------------------------------------------------------- /charts/azure-voting-app/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for azure-voting-app. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | mysql: 6 | user: dbuser 7 | password: Password12 8 | database: azurevote 9 | rootPassword: Password12 10 | 11 | azureVoteFront: 12 | service: 13 | name: front 14 | type: LoadBalancer 15 | externalPort: 80 16 | 17 | deployment: 18 | replicas: 1 19 | name: front 20 | image: microsoft/azure-vote-front 21 | imageTag: v1 22 | imagePullPolicy: Always 23 | internalPort: 80 24 | resources: 25 | limits: 26 | cpu: 500m 27 | # memory: 128Mi 28 | requests: 29 | cpu: 250m 30 | # memory: 128Mi 31 | 32 | azureVoteBack: 33 | service: 34 | name: back 35 | type: ClusterIP 36 | externalPort: 3306 37 | 38 | deployment: 39 | replicas: 1 40 | name: back 41 | image: microsoft/azure-vote-back 42 | imageTag: v1 43 | imagePullPolicy: IfNotPresent 44 | internalPort: 3306 45 | resources: {} 46 | # limits: 47 | # cpu: 100m 48 | # memory: 128Mi 49 | # requests: 50 | # cpu: 100m 51 | # memory: 128Mi 52 | 53 | persistence: 54 | enabled: true 55 | ## If defined, volume.beta.kubernetes.io/storage-class: 56 | ## Default: volume.alpha.kubernetes.io/storage-class: default 57 | ## 58 | # StorageClass: 59 | accessMode: ReadWriteOnce 60 | size: 1Gi -------------------------------------------------------------------------------- /charts/azure-voting-app/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | {{- $serviceName := include "name" . -}} 2 | 1. Get the Azure Voting App URL to visit by running these commands in the same shell: 3 | {{- if contains "NodePort" .Values.azureVoteFront.service.type }} 4 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ $serviceName }}-{{ .Values.azureVoteFront.service.name }}) 5 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 6 | echo http://$NODE_IP:$NODE_PORT/login 7 | 8 | {{- else if contains "LoadBalancer" .Values.azureVoteFront.service.type }} 9 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 10 | You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ $serviceName }}-{{ .Values.azureVoteFront.service.name }}' 11 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ $serviceName }}-{{ .Values.azureVoteFront.service.name }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") 12 | echo http://$SERVICE_IP:{{ .Values.azureVoteFront.service.externalPort }} 13 | 14 | {{- else if contains "ClusterIP" .Values.azureVoteFront.service.type }} 15 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "component={{ $serviceName }}-{{ .Values.azureVoteFront.deployment.name }}" -o jsonpath="{.items[0].metadata.name}") 16 | echo http://127.0.0.1:{{ .Values.azureVoteFront.deployment.internalPort }} 17 | kubectl port-forward $POD_NAME {{ .Values.azureVoteFront.deplopyment.internalPort }}:{{ .Values.azureVoteFront.deplopyment.internalPort }} 18 | {{- end }} -------------------------------------------------------------------------------- /charts/azure-voting-app/templates/azure-vote-front-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- $serviceName := include "name" . -}} 2 | apiVersion: extensions/v1beta1 3 | kind: Deployment 4 | metadata: 5 | name: {{ $serviceName }}-{{ .Values.azureVoteFront.deployment.name }} 6 | labels: 7 | {{ include "labels.standard" . | indent 4 }} 8 | component: {{ $serviceName }}-{{ .Values.azureVoteFront.deployment.name }} 9 | spec: 10 | replicas: {{ .Values.azureVoteFront.deployment.replicas }} 11 | strategy: 12 | rollingUpdate: 13 | maxSurge: 1 14 | maxUnavailable: 1 15 | minReadySeconds: 5 16 | template: 17 | metadata: 18 | labels: 19 | {{ include "labels.standard" . | indent 8 }} 20 | component: {{ $serviceName }}-{{ .Values.azureVoteFront.deployment.name }} 21 | spec: 22 | containers: 23 | - name: {{ $serviceName }}-{{ .Values.azureVoteFront.deployment.name }} 24 | image: "{{ .Values.azureVoteFront.deployment.image }}:{{ .Values.azureVoteFront.deployment.imageTag }}" 25 | imagePullPolicy: {{ .Values.azureVoteFront.deployment.imagePullPolicy }} 26 | ports: 27 | - containerPort: {{ .Values.azureVoteFront.deployment.internalPort }} 28 | env: 29 | - name: MYSQL_USER 30 | valueFrom: 31 | secretKeyRef: 32 | name: {{ $serviceName }}-azure-vote 33 | key: MYSQL_USER 34 | - name: MYSQL_PASSWORD 35 | valueFrom: 36 | secretKeyRef: 37 | name: {{ $serviceName }}-azure-vote 38 | key: MYSQL_PASSWORD 39 | - name: MYSQL_DATABASE 40 | valueFrom: 41 | secretKeyRef: 42 | name: {{ $serviceName }}-azure-vote 43 | key: MYSQL_DATABASE 44 | - name: MYSQL_HOST 45 | valueFrom: 46 | secretKeyRef: 47 | name: {{ $serviceName }}-azure-vote 48 | key: MYSQL_HOST 49 | resources: 50 | {{ toYaml .Values.azureVoteFront.deployment.resources | indent 10 }} -------------------------------------------------------------------------------- /azure-vote/azure-vote/static/default.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color:#F8F8F8; 3 | } 4 | 5 | div#container { 6 | margin-top:5%; 7 | } 8 | 9 | div#space { 10 | display:block; 11 | margin: 0 auto; 12 | width: 500px; 13 | height: 10px; 14 | 15 | } 16 | 17 | div#logo { 18 | display:block; 19 | margin: 0 auto; 20 | width: 500px; 21 | text-align: right; 22 | font-size:30px; 23 | font-family:Helvetica; 24 | /*border-bottom: 1px solid black;*/ 25 | } 26 | 27 | div#form { 28 | padding: 20px; 29 | padding-right: 20px; 30 | padding-top: 20px; 31 | display:block; 32 | margin: 0 auto; 33 | width: 500px; 34 | text-align: center; 35 | font-size:30px; 36 | font-family:Helvetica; 37 | border-bottom: 1px solid black; 38 | border-top: 1px solid black; 39 | } 40 | 41 | div#results { 42 | display:block; 43 | margin: 0 auto; 44 | width: 500px; 45 | text-align: center; 46 | font-size:30px; 47 | font-family:Helvetica; 48 | } 49 | 50 | .button { 51 | background-color: #4CAF50; /* Green */ 52 | border: none; 53 | color: white; 54 | padding: 16px 32px; 55 | text-align: center; 56 | text-decoration: none; 57 | display: inline-block; 58 | font-size: 16px; 59 | margin: 4px 2px; 60 | -webkit-transition-duration: 0.4s; /* Safari */ 61 | transition-duration: 0.4s; 62 | cursor: pointer; 63 | width: 250px; 64 | } 65 | 66 | .button1 { 67 | background-color: white; 68 | color: black; 69 | border: 2px solid #008CBA; 70 | } 71 | 72 | .button1:hover { 73 | background-color: #008CBA; 74 | color: white; 75 | } 76 | .button2 { 77 | background-color: white; 78 | color: black; 79 | border: 2px solid #555555; 80 | } 81 | 82 | .button2:hover { 83 | background-color: #555555; 84 | color: white; 85 | } 86 | 87 | .button3 { 88 | background-color: white; 89 | color: black; 90 | border: 2px solid #f44336; 91 | } 92 | 93 | .button3:hover { 94 | background-color: #f44336; 95 | color: white; 96 | } -------------------------------------------------------------------------------- /charts/azure-voting-app/templates/azure-vote-back-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- $serviceName := include "name" . -}} 2 | apiVersion: extensions/v1beta1 3 | kind: Deployment 4 | metadata: 5 | name: {{ $serviceName }}-{{ .Values.azureVoteBack.deployment.name }} 6 | labels: 7 | {{ include "labels.standard" . | indent 4 }} 8 | component: {{ $serviceName }}-{{ .Values.azureVoteBack.deployment.name }} 9 | spec: 10 | replicas: {{ .Values.azureVoteBack.deployment.replicas }} 11 | template: 12 | metadata: 13 | labels: 14 | {{ include "labels.standard" . | indent 8 }} 15 | component: {{ $serviceName }}-{{ .Values.azureVoteBack.deployment.name }} 16 | spec: 17 | containers: 18 | - name: {{ $serviceName }}-{{ .Values.azureVoteBack.deployment.name }} 19 | image: "{{ .Values.azureVoteBack.deployment.image }}:{{ .Values.azureVoteBack.deployment.imageTag }}" 20 | imagePullPolicy: {{ .Values.azureVoteBack.deployment.imagePullPolicy }} 21 | ports: 22 | - containerPort: {{ .Values.azureVoteBack.deployment.internalPort }} 23 | name: mysql 24 | args: 25 | - --ignore-db-dir=lost+found 26 | volumeMounts: 27 | - name: mysql-persistent-storage 28 | mountPath: /var/lib/mysql 29 | env: 30 | - name: MYSQL_ROOT_PASSWORD 31 | valueFrom: 32 | secretKeyRef: 33 | name: {{ $serviceName }}-azure-vote 34 | key: MYSQL_ROOT_PASSWORD 35 | - name: MYSQL_USER 36 | valueFrom: 37 | secretKeyRef: 38 | name: {{ $serviceName }}-azure-vote 39 | key: MYSQL_USER 40 | - name: MYSQL_PASSWORD 41 | valueFrom: 42 | secretKeyRef: 43 | name: {{ $serviceName }}-azure-vote 44 | key: MYSQL_PASSWORD 45 | - name: MYSQL_DATABASE 46 | valueFrom: 47 | secretKeyRef: 48 | name: {{ $serviceName }}-azure-vote 49 | key: MYSQL_DATABASE 50 | resources: 51 | {{ toYaml .Values.azureVoteBack.deployment.resources | indent 10 }} 52 | volumes: 53 | - name: mysql-persistent-storage 54 | {{- if .Values.persistence.enabled }} 55 | persistentVolumeClaim: 56 | claimName: {{ $serviceName }}-mysql-pv-claim 57 | {{- else }} 58 | emptyDir: {} 59 | {{- end }} -------------------------------------------------------------------------------- /kubernetes-manifests/azure-vote-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: azure-vote-back 5 | spec: 6 | replicas: 1 7 | template: 8 | metadata: 9 | labels: 10 | app: azure-vote-back 11 | spec: 12 | containers: 13 | - name: azure-vote-back 14 | image: microsoft/azure-vote-back:v1 15 | args: ["--ignore-db-dir=lost+found"] 16 | ports: 17 | - containerPort: 3306 18 | name: mysql 19 | volumeMounts: 20 | - name: mysql-persistent-storage 21 | mountPath: /var/lib/mysql 22 | env: 23 | - name: MYSQL_ROOT_PASSWORD 24 | valueFrom: 25 | secretKeyRef: 26 | name: azure-vote 27 | key: MYSQL_ROOT_PASSWORD 28 | - name: MYSQL_USER 29 | valueFrom: 30 | secretKeyRef: 31 | name: azure-vote 32 | key: MYSQL_USER 33 | - name: MYSQL_PASSWORD 34 | valueFrom: 35 | secretKeyRef: 36 | name: azure-vote 37 | key: MYSQL_PASSWORD 38 | - name: MYSQL_DATABASE 39 | valueFrom: 40 | secretKeyRef: 41 | name: azure-vote 42 | key: MYSQL_DATABASE 43 | volumes: 44 | - name: mysql-persistent-storage 45 | persistentVolumeClaim: 46 | claimName: mysql-pv-claim 47 | --- 48 | apiVersion: apps/v1beta1 49 | kind: Deployment 50 | metadata: 51 | name: azure-vote-front 52 | spec: 53 | replicas: 1 54 | strategy: 55 | rollingUpdate: 56 | maxSurge: 1 57 | maxUnavailable: 1 58 | minReadySeconds: 5 59 | template: 60 | metadata: 61 | labels: 62 | app: azure-vote-front 63 | spec: 64 | containers: 65 | - name: azure-vote-front 66 | image: microsoft/azure-vote-front:v1 67 | resources: 68 | requests: 69 | cpu: 250m 70 | limits: 71 | cpu: 500m 72 | ports: 73 | - containerPort: 80 74 | resources: 75 | requests: 76 | cpu: 250m 77 | limits: 78 | cpu: 500m 79 | imagePullPolicy: Always 80 | env: 81 | - name: MYSQL_USER 82 | valueFrom: 83 | secretKeyRef: 84 | name: azure-vote 85 | key: MYSQL_USER 86 | - name: MYSQL_PASSWORD 87 | valueFrom: 88 | secretKeyRef: 89 | name: azure-vote 90 | key: MYSQL_PASSWORD 91 | - name: MYSQL_DATABASE 92 | valueFrom: 93 | secretKeyRef: 94 | name: azure-vote 95 | key: MYSQL_DATABASE 96 | - name: MYSQL_HOST 97 | valueFrom: 98 | secretKeyRef: 99 | name: azure-vote 100 | key: MYSQL_HOST -------------------------------------------------------------------------------- /azure-vote/azure-vote/main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, render_template 2 | from flaskext.mysql import MySQL 3 | import os 4 | import random 5 | import socket 6 | import sys 7 | 8 | app = Flask(__name__) 9 | 10 | # Load configurations 11 | app.config.from_pyfile('config_file.cfg') 12 | button1 = app.config['VOTE1VALUE'] 13 | button2 = app.config['VOTE2VALUE'] 14 | title = app.config['TITLE'] 15 | 16 | # MySQL configurations 17 | app.config['MYSQL_DATABASE_USER'] = os.environ['MYSQL_USER'] 18 | app.config['MYSQL_DATABASE_PASSWORD'] = os.environ['MYSQL_PASSWORD'] 19 | app.config['MYSQL_DATABASE_DB'] = os.environ['MYSQL_DATABASE'] 20 | app.config['MYSQL_DATABASE_HOST'] = os.environ['MYSQL_HOST'] 21 | 22 | # MySQL Object 23 | mysql = MySQL() 24 | mysql.init_app(app) 25 | 26 | # Change title to host name to demo NLB 27 | if app.config['SHOWHOST'] == "true": 28 | title = socket.gethostname() 29 | 30 | 31 | @app.route('/', methods=['GET', 'POST']) 32 | def index(): 33 | 34 | # MySQL Connection 35 | connection = mysql.connect() 36 | cursor = connection.cursor() 37 | 38 | # Vote tracking 39 | vote1 = 0 40 | vote2 = 0 41 | 42 | if request.method == 'GET': 43 | 44 | # Get current values 45 | cursor.execute('''Select votevalue, count(votevalue) as count From azurevote.azurevote 46 | group by votevalue''') 47 | results = cursor.fetchall() 48 | 49 | # Parse results 50 | for i in results: 51 | if i[0] == app.config['VOTE1VALUE']: 52 | vote1 = i[1] 53 | elif i[0] == app.config['VOTE2VALUE']: 54 | vote2 = i[1] 55 | 56 | # Return index with values 57 | return render_template("index.html", value1=vote1, value2=vote2, button1=button1, button2=button2, title=title) 58 | 59 | elif request.method == 'POST': 60 | 61 | if request.form['vote'] == 'reset': 62 | 63 | # Empty table and return results 64 | cursor.execute('''Delete FROM azurevote''') 65 | connection.commit() 66 | return render_template("index.html", value1=vote1, value2=vote2, button1=button1, button2=button2, title=title) 67 | else: 68 | 69 | # Insert vote result into DB 70 | vote = request.form['vote'] 71 | cursor.execute( 72 | '''INSERT INTO azurevote (votevalue) VALUES (%s)''', (vote)) 73 | connection.commit() 74 | 75 | # Get current values 76 | cursor.execute('''Select votevalue, count(votevalue) as count From azurevote.azurevote 77 | group by votevalue''') 78 | results = cursor.fetchall() 79 | 80 | # Parse results 81 | for i in results: 82 | if i[0] == app.config['VOTE1VALUE']: 83 | vote1 = i[1] 84 | elif i[0] == app.config['VOTE2VALUE']: 85 | vote2 = i[1] 86 | 87 | # Return results 88 | return render_template("index.html", value1=vote1, value2=vote2, button1=button1, button2=button2, title=title) 89 | 90 | 91 | @app.route('/results') 92 | def results(): 93 | 94 | # MySQL Connection 95 | connection = mysql.connect() 96 | cursor = connection.cursor() 97 | 98 | # Get current values 99 | cursor.execute('''Select * FROM azurevote''') 100 | rv = cursor.fetchall() 101 | return str(rv) 102 | 103 | 104 | if __name__ == "__main__": 105 | app.run(host='0.0.0.0', debug=True, port=80) 106 | _ == "__main__": 107 | app.run(host='0.0.0.0', debug=True, port=80) -------------------------------------------------------------------------------- /kubernetes-manifests/azure-vote-all-in-one.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: slow 5 | provisioner: kubernetes.io/azure-disk 6 | parameters: 7 | skuName: Standard_LRS 8 | location: eastus 9 | --- 10 | apiVersion: v1 11 | kind: PersistentVolumeClaim 12 | metadata: 13 | name: mysql-pv-claim 14 | spec: 15 | accessModes: 16 | - ReadWriteOnce 17 | resources: 18 | requests: 19 | storage: 1Gi 20 | --- 21 | apiVersion: v1 22 | kind: Secret 23 | metadata: 24 | name: azure-vote 25 | type: Opaque 26 | data: 27 | MYSQL_USER: ZGJ1c2Vy 28 | MYSQL_PASSWORD: UGFzc3dvcmQxMg== 29 | MYSQL_DATABASE: YXp1cmV2b3Rl 30 | MYSQL_HOST: YXp1cmUtdm90ZS1iYWNr 31 | MYSQL_ROOT_PASSWORD: UGFzc3dvcmQxMg== 32 | --- 33 | apiVersion: apps/v1beta1 34 | kind: Deployment 35 | metadata: 36 | name: azure-vote-back 37 | spec: 38 | replicas: 1 39 | template: 40 | metadata: 41 | labels: 42 | app: azure-vote-back 43 | spec: 44 | containers: 45 | - name: azure-vote-back 46 | image: microsoft/azure-vote-back:v1 47 | args: ["--ignore-db-dir=lost+found"] 48 | ports: 49 | - containerPort: 3306 50 | name: mysql 51 | volumeMounts: 52 | - name: mysql-persistent-storage 53 | mountPath: /var/lib/mysql 54 | env: 55 | - name: MYSQL_ROOT_PASSWORD 56 | valueFrom: 57 | secretKeyRef: 58 | name: azure-vote 59 | key: MYSQL_ROOT_PASSWORD 60 | - name: MYSQL_USER 61 | valueFrom: 62 | secretKeyRef: 63 | name: azure-vote 64 | key: MYSQL_USER 65 | - name: MYSQL_PASSWORD 66 | valueFrom: 67 | secretKeyRef: 68 | name: azure-vote 69 | key: MYSQL_PASSWORD 70 | - name: MYSQL_DATABASE 71 | valueFrom: 72 | secretKeyRef: 73 | name: azure-vote 74 | key: MYSQL_DATABASE 75 | volumes: 76 | - name: mysql-persistent-storage 77 | persistentVolumeClaim: 78 | claimName: mysql-pv-claim 79 | --- 80 | apiVersion: v1 81 | kind: Service 82 | metadata: 83 | name: azure-vote-back 84 | spec: 85 | ports: 86 | - port: 3306 87 | selector: 88 | app: azure-vote-back 89 | --- 90 | apiVersion: apps/v1beta1 91 | kind: Deployment 92 | metadata: 93 | name: azure-vote-front 94 | spec: 95 | replicas: 1 96 | strategy: 97 | rollingUpdate: 98 | maxSurge: 1 99 | maxUnavailable: 1 100 | minReadySeconds: 5 101 | template: 102 | metadata: 103 | labels: 104 | app: azure-vote-front 105 | spec: 106 | containers: 107 | - name: azure-vote-front 108 | image: microsoft/azure-vote-front:v1 109 | resources: 110 | requests: 111 | cpu: 250m 112 | limits: 113 | cpu: 500m 114 | ports: 115 | - containerPort: 80 116 | resources: 117 | requests: 118 | cpu: 250m 119 | limits: 120 | cpu: 500m 121 | imagePullPolicy: Always 122 | env: 123 | - name: MYSQL_USER 124 | valueFrom: 125 | secretKeyRef: 126 | name: azure-vote 127 | key: MYSQL_USER 128 | - name: MYSQL_PASSWORD 129 | valueFrom: 130 | secretKeyRef: 131 | name: azure-vote 132 | key: MYSQL_PASSWORD 133 | - name: MYSQL_DATABASE 134 | valueFrom: 135 | secretKeyRef: 136 | name: azure-vote 137 | key: MYSQL_DATABASE 138 | - name: MYSQL_HOST 139 | valueFrom: 140 | secretKeyRef: 141 | name: azure-vote 142 | key: MYSQL_HOST 143 | --- 144 | apiVersion: v1 145 | kind: Service 146 | metadata: 147 | name: azure-vote-front 148 | spec: 149 | type: LoadBalancer 150 | ports: 151 | - port: 80 152 | selector: 153 | app: azure-vote-front -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | --------------------------------------------------------------------------------