Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Hans Kristian Flaatten
committed
Apr 30, 2020
1 parent
05af6c8
commit 08b0983
Showing
6 changed files
with
303 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# This workflow will build a docker container, publish it to Azure Container Registry, and deploy it to Azure Kubernetes Service using a helm chart. | ||
# | ||
# To configure this workflow: | ||
# | ||
# 1. Set up the following secrets in your workspace: | ||
# a. REGISTRY_USERNAME with ACR username | ||
# b. REGISTRY_PASSWORD with ACR Password | ||
# c. AZURE_CREDENTIALS with the output of `az ad sp create-for-rbac --sdk-auth` | ||
# | ||
# 2. Change the values for the REGISTRY_NAME, CLUSTER_NAME, CLUSTER_RESOURCE_GROUP and NAMESPACE environment variables (below). | ||
|
||
on: [push] | ||
|
||
# Environment variables available to all jobs and steps in this workflow | ||
env: | ||
REGISTRY_NAME: evryflaatten | ||
CLUSTER_NAME: aks-demo | ||
CLUSTER_RESOURCE_GROUP: aks-demo | ||
NAMESPACE: default | ||
IMAGE_NAME: myimage | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@master | ||
|
||
# Connect to Azure Container registry (ACR) | ||
- uses: azure/docker-login@v1 | ||
with: | ||
login-server: ${{ env.REGISTRY_NAME }}.azurecr.io | ||
username: ${{ secrets.REGISTRY_USERNAME }} | ||
password: ${{ secrets.REGISTRY_PASSWORD }} | ||
|
||
# Container build and push to a Azure Container registry (ACR) | ||
- run: | | ||
docker build . -t ${{ env.REGISTRY_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}:${{ github.sha }} | ||
docker push ${{ env.REGISTRY_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}:${{ github.sha }} | ||
# Set the target Azure Kubernetes Service (AKS) cluster. | ||
- uses: azure/aks-set-context@v1 | ||
with: | ||
creds: '${{ secrets.AZURE_CREDENTIALS }}' | ||
cluster-name: ${{ env.CLUSTER_NAME }} | ||
resource-group: ${{ env.CLUSTER_RESOURCE_GROUP }} | ||
|
||
# Create namespace if doesn't exist | ||
- run: | | ||
kubectl create namespace ${{ env.NAMESPACE }} --dry-run -o json | kubectl apply -f - | ||
# Create imagepullsecret for Azure Container registry (ACR) | ||
- uses: azure/k8s-create-secret@v1 | ||
with: | ||
container-registry-url: ${{ env.REGISTRY_NAME }}.azurecr.io | ||
container-registry-username: ${{ secrets.REGISTRY_USERNAME }} | ||
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }} | ||
secret-name: ${{ env.REGISTRY_NAME }}-registry-connection | ||
namespace: ${{ env.NAMESPACE }} | ||
|
||
# Baking the helm chart to generate the manifests to deploy | ||
- uses: azure/k8s-bake@v1 | ||
with: | ||
renderEngine: 'helm' | ||
helmChart: './mychart/' | ||
helm-version: 'latest' | ||
releaseName: 'myapp' | ||
overrideFiles: 'values.yaml' | ||
overrides: | | ||
image.repository:${{ env.REGISTRY_NAME }}.azurecr.io/${{ env.IMAGE_NAME }} | ||
image.tag:${{ github.sha }} | ||
imagePullSecrets[0].name:${{ env.REGISTRY_NAME }}-registry-connection | ||
id: bake | ||
|
||
# Deploy app to AKS | ||
- uses: azure/k8s-deploy@v1 | ||
with: | ||
manifests: ${{ steps.bake.outputs.manifestsBundle }} | ||
#images: | | ||
# ${{ env.REGISTRY_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}:${{ github.sha }} | ||
#imagepullsecrets: | | ||
# ${{ env.REGISTRY_NAME }}-registry-connection | ||
namespace: ${{ env.NAMESPACE }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
FROM tiangolo/uwsgi-nginx-flask:python3.6 | ||
RUN pip install redis | ||
ADD /azure-vote /app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# UI Configurations | ||
TITLE = 'Azure Voting App' | ||
VOTE1VALUE = 'Cats' | ||
VOTE2VALUE = 'Dogs' | ||
SHOWHOST = 'false' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
from flask import Flask, request, render_template | ||
import os | ||
import random | ||
import redis | ||
import socket | ||
import sys | ||
|
||
app = Flask(__name__) | ||
|
||
# Load configurations from environment or config file | ||
app.config.from_pyfile('config_file.cfg') | ||
|
||
if ("VOTE1VALUE" in os.environ and os.environ['VOTE1VALUE']): | ||
button1 = os.environ['VOTE1VALUE'] | ||
else: | ||
button1 = app.config['VOTE1VALUE'] | ||
|
||
if ("VOTE2VALUE" in os.environ and os.environ['VOTE2VALUE']): | ||
button2 = os.environ['VOTE2VALUE'] | ||
else: | ||
button2 = app.config['VOTE2VALUE'] | ||
|
||
if ("TITLE" in os.environ and os.environ['TITLE']): | ||
title = os.environ['TITLE'] | ||
else: | ||
title = app.config['TITLE'] | ||
|
||
# Redis configurations | ||
redis_server = os.environ['REDIS'] | ||
|
||
# Redis Connection | ||
try: | ||
if "REDIS_PWD" in os.environ: | ||
r = redis.StrictRedis(host=redis_server, | ||
port=6379, | ||
password=os.environ['REDIS_PWD']) | ||
else: | ||
r = redis.Redis(redis_server) | ||
r.ping() | ||
except redis.ConnectionError: | ||
exit('Failed to connect to Redis, terminating.') | ||
|
||
# Change title to host name to demo NLB | ||
if app.config['SHOWHOST'] == "true": | ||
title = socket.gethostname() | ||
|
||
# Init Redis | ||
if not r.get(button1): r.set(button1,0) | ||
if not r.get(button2): r.set(button2,0) | ||
|
||
@app.route('/', methods=['GET', 'POST']) | ||
def index(): | ||
|
||
if request.method == 'GET': | ||
|
||
# Get current values | ||
vote1 = r.get(button1).decode('utf-8') | ||
vote2 = r.get(button2).decode('utf-8') | ||
|
||
# Return index with values | ||
return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) | ||
|
||
elif request.method == 'POST': | ||
|
||
if request.form['vote'] == 'reset': | ||
|
||
# Empty table and return results | ||
r.set(button1,0) | ||
r.set(button2,0) | ||
vote1 = r.get(button1).decode('utf-8') | ||
vote2 = r.get(button2).decode('utf-8') | ||
return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) | ||
|
||
else: | ||
|
||
# Insert vote result into DB | ||
vote = request.form['vote'] | ||
r.incr(vote,1) | ||
|
||
# Get current values | ||
vote1 = r.get(button1).decode('utf-8') | ||
vote2 = r.get(button2).decode('utf-8') | ||
|
||
# Return results | ||
return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) | ||
|
||
if __name__ == "__main__": | ||
app.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
body { | ||
background-color:#F8F8F8; | ||
} | ||
|
||
div#container { | ||
margin-top:5%; | ||
} | ||
|
||
div#space { | ||
display:block; | ||
margin: 0 auto; | ||
width: 500px; | ||
height: 10px; | ||
|
||
} | ||
|
||
div#logo { | ||
display:block; | ||
margin: 0 auto; | ||
width: 500px; | ||
text-align: center; | ||
font-size:30px; | ||
font-family:Helvetica; | ||
/*border-bottom: 1px solid black;*/ | ||
} | ||
|
||
div#form { | ||
padding: 20px; | ||
padding-right: 20px; | ||
padding-top: 20px; | ||
display:block; | ||
margin: 0 auto; | ||
width: 500px; | ||
text-align: center; | ||
font-size:30px; | ||
font-family:Helvetica; | ||
border-bottom: 1px solid black; | ||
border-top: 1px solid black; | ||
} | ||
|
||
div#results { | ||
display:block; | ||
margin: 0 auto; | ||
width: 500px; | ||
text-align: center; | ||
font-size:30px; | ||
font-family:Helvetica; | ||
} | ||
|
||
.button { | ||
background-color: #4CAF50; /* Green */ | ||
border: none; | ||
color: white; | ||
padding: 16px 32px; | ||
text-align: center; | ||
text-decoration: none; | ||
display: inline-block; | ||
font-size: 16px; | ||
margin: 4px 2px; | ||
-webkit-transition-duration: 0.4s; /* Safari */ | ||
transition-duration: 0.4s; | ||
cursor: pointer; | ||
width: 250px; | ||
} | ||
|
||
.button1 { | ||
background-color: white; | ||
color: black; | ||
border: 2px solid #008CBA; | ||
} | ||
|
||
.button1:hover { | ||
background-color: #008CBA; | ||
color: white; | ||
} | ||
.button2 { | ||
background-color: white; | ||
color: black; | ||
border: 2px solid #555555; | ||
} | ||
|
||
.button2:hover { | ||
background-color: #555555; | ||
color: white; | ||
} | ||
|
||
.button3 { | ||
background-color: white; | ||
color: black; | ||
border: 2px solid #f44336; | ||
} | ||
|
||
.button3:hover { | ||
background-color: #f44336; | ||
color: white; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<!DOCTYPE html> | ||
<html xmlns="http://www.w3.org/1999/xhtml"> | ||
<head> | ||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='default.css') }}"> | ||
<title>{{title}}</title> | ||
|
||
<script language="JavaScript"> | ||
function send(form){ | ||
} | ||
</script> | ||
|
||
</head> | ||
<body> | ||
<div id="container"> | ||
<form id="form" name="form" action="/"" method="post"><center> | ||
<div id="logo">{{title}}</div> | ||
<div id="space"></div> | ||
<div id="form"> | ||
<button name="vote" value="{{button1}}" onclick="send()" class="button button1">{{button1}}</button> | ||
<button name="vote" value="{{button2}}" onclick="send()" class="button button2">{{button2}}</button> | ||
<button name="vote" value="reset" onclick="send()" class="button button3">Reset</button> | ||
<div id="space"></div> | ||
<div id="space"></div> | ||
<div id="results"> {{button1}} - {{ value1 }} | {{button2}} - {{ value2 }} </div> | ||
</form> | ||
</div> | ||
</div> | ||
</body> | ||
</html> |