Skip to content

Commit 407e897

Browse files
committed
Initial commit
0 parents  commit 407e897

File tree

3 files changed

+312
-0
lines changed

3 files changed

+312
-0
lines changed

Diff for: .openshiftio/application.yaml

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
apiVersion: v1
2+
kind: Template
3+
metadata:
4+
name: launchpad-builder
5+
annotations:
6+
description: This template creates a Build Configuration using an S2I builder.
7+
tags: instant-app
8+
parameters:
9+
- name: SUFFIX_NAME
10+
description: The suffix name for the template objects
11+
displayName: Suffix name
12+
value: ''
13+
- name: RELEASE_VERSION
14+
description: The release version number of application
15+
displayName: Release version
16+
value: 1.0.0
17+
- name: SOURCE_REPOSITORY_URL
18+
description: The source URL for the application
19+
displayName: Source URL
20+
required: true
21+
- name: SOURCE_REPOSITORY_REF
22+
description: The branch name for the application
23+
displayName: Source Branch
24+
value: master
25+
required: true
26+
- name: GITHUB_WEBHOOK_SECRET
27+
description: A secret string used to configure the GitHub webhook.
28+
displayName: GitHub Webhook Secret
29+
required: true
30+
from: '[a-zA-Z0-9]{40}'
31+
generate: expression
32+
objects:
33+
- apiVersion: image.openshift.io/v1
34+
kind: ImageStream
35+
metadata:
36+
name: 'golang-health-check${SUFFIX_NAME}'
37+
labels:
38+
version: '${RELEASE_VERSION}'
39+
spec: {}
40+
- apiVersion: v1
41+
kind: BuildConfig
42+
metadata:
43+
name: 'golang-health-check-s2i${SUFFIX_NAME}'
44+
labels:
45+
version: '${RELEASE_VERSION}'
46+
spec:
47+
output:
48+
to:
49+
kind: ImageStreamTag
50+
name: 'golang-health-check${SUFFIX_NAME}:${RELEASE_VERSION}'
51+
postCommit: {}
52+
resources: {}
53+
source:
54+
git:
55+
uri: '${SOURCE_REPOSITORY_URL}'
56+
ref: '${SOURCE_REPOSITORY_REF}'
57+
type: Git
58+
strategy:
59+
type: Source
60+
sourceStrategy:
61+
from:
62+
kind: DockerImage
63+
name: 'centos/go-toolset-7-centos7'
64+
incremental: true
65+
triggers:
66+
- github:
67+
secret: '${GITHUB_WEBHOOK_SECRET}'
68+
type: GitHub
69+
- type: ConfigChange
70+
status:
71+
lastVersion: 0
72+
- apiVersion: v1
73+
kind: Service
74+
spec:
75+
ports:
76+
- protocol: TCP
77+
port: 8080
78+
targetPort: 8080
79+
type: ClusterIP
80+
selector:
81+
project: golang-health-check
82+
provider: golang-starters
83+
metadata:
84+
name: 'golang-health-check${SUFFIX_NAME}'
85+
labels:
86+
provider: golang-starters
87+
expose: 'true'
88+
project: golang-health-check
89+
version: '${RELEASE_VERSION}'
90+
- apiVersion: v1
91+
kind: DeploymentConfig
92+
metadata:
93+
name: 'golang-health-check${SUFFIX_NAME}'
94+
labels:
95+
app: golang-health-check
96+
provider: golang-starters
97+
project: golang-health-check
98+
version: '${RELEASE_VERSION}'
99+
spec:
100+
template:
101+
spec:
102+
containers:
103+
- readinessProbe:
104+
httpGet:
105+
path: /api/health
106+
port: 8080
107+
scheme: HTTP
108+
failureThreshold: 3
109+
initialDelaySeconds: 10
110+
periodSeconds: 5
111+
successThreshold: 1
112+
timeoutSeconds: 1
113+
livenessProbe:
114+
httpGet:
115+
path: /api/health
116+
port: 8080
117+
scheme: HTTP
118+
failureThreshold: 2
119+
initialDelaySeconds: 60
120+
periodSeconds: 3
121+
successThreshold: 1
122+
timeoutSeconds: 1
123+
image: ''
124+
name: golang-health-check
125+
securityContext:
126+
privileged: false
127+
ports:
128+
- containerPort: 8080
129+
name: http
130+
protocol: TCP
131+
metadata:
132+
labels:
133+
app: golang-health-check
134+
project: golang-health-check
135+
provider: golang-starters
136+
version: '${RELEASE_VERSION}'
137+
replicas: 1
138+
selector:
139+
app: golang-health-check
140+
project: golang-health-check
141+
provider: golang-starters
142+
triggers:
143+
- type: ConfigChange
144+
- type: ImageChange
145+
imageChangeParams:
146+
automatic: true
147+
containerNames:
148+
- golang-health-check
149+
from:
150+
kind: ImageStreamTag
151+
name: 'golang-health-check${SUFFIX_NAME}:${RELEASE_VERSION}'
152+
- apiVersion: v1
153+
kind: Route
154+
metadata:
155+
labels:
156+
project: golang-health-check
157+
provider: golang-starters
158+
version: '${RELEASE_VERSION}'
159+
name: 'golang-health-check${SUFFIX_NAME}'
160+
spec:
161+
port:
162+
targetPort: 8080
163+
to:
164+
kind: Service
165+
name: 'golang-health-check${SUFFIX_NAME}'

Diff for: main.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net/http"
7+
)
8+
9+
var isOnline = true
10+
11+
func main() {
12+
http.HandleFunc("/api/greeting", greeting)
13+
http.HandleFunc("/api/stop", stop)
14+
http.HandleFunc("/api/health", health)
15+
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
16+
http.ServeFile(w, r, "public/index.html")
17+
})
18+
log.Fatal(http.ListenAndServe(":8080", nil))
19+
}
20+
21+
func greeting(w http.ResponseWriter, r *http.Request) {
22+
if isOnline {
23+
message := "World"
24+
if m := r.FormValue("name"); m != "" {
25+
message = m
26+
}
27+
fmt.Fprintf(w, "Hello %s!", message)
28+
return
29+
}
30+
w.WriteHeader(503)
31+
w.Write([]byte("Not Online"))
32+
}
33+
34+
func stop(w http.ResponseWriter, r *http.Request) {
35+
isOnline = false
36+
w.Write([]byte("Stopping HTTP Server"))
37+
}
38+
39+
func health(w http.ResponseWriter, r *http.Request) {
40+
if isOnline {
41+
w.WriteHeader(200)
42+
return
43+
}
44+
w.WriteHeader(500)
45+
}

Diff for: public/index.html

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<html>
2+
<head>
3+
<meta charset="utf-8">
4+
<title>Health Check Mission - Golang</title>
5+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
6+
crossorigin="anonymous">
7+
</head>
8+
9+
<body>
10+
<div class="container">
11+
<div>
12+
<div class="sect1">
13+
<h2 id="_health_check_booster">Health Check Booster</h2>
14+
<div class="sectionbody">
15+
<div class="paragraph">
16+
<p>Demonstrates how the Kubernetes/Openshift health checks work to determine if a container is still alive (the <em>liveness</em>
17+
of the container) and ready to serve the traffic for the HTTP endpoints of the application (the <em>readiness</em>
18+
of the container).</p>
19+
</div>
20+
<div class="paragraph">
21+
<p>To demonstrate this behavior, the application configures a <code>/health</code> HTTP endpoint, which is
22+
used
23+
by Kubernetes/Openshift to issue HTTP requests. If the container is still alive—​which means the Health HTTP
24+
endpoint
25+
is able to reply—​the management platform will receive HTTP code 200 as a response, and no further action
26+
is taken. After you click the
27+
<code>Stop Service</code> button, the HTTP endpoint starts
28+
returning a 500 response, and the platform then
29+
restarts
30+
the pod with the failed container. While the pod is down, the booster UI polls the service
31+
periodically
32+
until the pod is restarted. In the meantime, do <strong>not</strong> refresh the page because it will
33+
not be served until the pod finishes restarting.</p>
34+
</div>
35+
<div class="sect2">
36+
<h3 id="_using_the_greeting_service">Using the greeting service</h3>
37+
</div>
38+
</div>
39+
</div>
40+
41+
<form class="form-inline">
42+
<div class="form-group">
43+
<label for="name">Name</label>
44+
<input type="text" class="form-control" id="name" placeholder="World">
45+
</div>
46+
<button id="invoke" type="submit" class="btn btn-success">Invoke</button>
47+
<button id="stop" type="submit" class="btn btn-danger">Stop Service</button>
48+
</form>
49+
50+
<h3>Result:</h3>
51+
<pre><code id="greeting-result">Invoke the service to see the result.</code></pre>
52+
</div>
53+
</div>
54+
55+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
56+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
57+
crossorigin="anonymous"></script>
58+
59+
<script>
60+
var stopTime;
61+
var attempts;
62+
63+
function invokeService() {
64+
var n = $("#name").val() || "World";
65+
$.get("/api/greeting?name=" + n, function (res) {
66+
$("#greeting-result").html(res);
67+
});
68+
}
69+
70+
function invokeServiceandRetryUponFailures() {
71+
var n = $("#name").val() || "World";
72+
$.get("/api/greeting?name=" + n, function (res) {
73+
var rebirth = new Date();
74+
var diff = (stopTime.getTime() - rebirth.getTime()) / 1000;
75+
var abs = Math.abs(diff);
76+
$("#greeting-result").html(res + " (the recovery took " + abs + " seconds)");
77+
})
78+
.fail(function () {
79+
$("#greeting-result").html("[" + ++attempts + "] Service not available... Retrying in 2 seconds");
80+
setTimeout(invokeServiceandRetryUponFailures, 2000);
81+
});
82+
}
83+
84+
$(document).ready(function () {
85+
$("#invoke").click(function (e) {
86+
invokeService();
87+
e.preventDefault();
88+
});
89+
90+
$("#stop").click(function (e) {
91+
$.get("/api/stop", function (data) {
92+
$("#greeting-result").html("The application has been stopped...");
93+
stopTime = new Date();
94+
attempts = 0;
95+
setTimeout(invokeServiceandRetryUponFailures, 2000);
96+
});
97+
e.preventDefault();
98+
});
99+
});
100+
</script>
101+
</body>
102+
</html>

0 commit comments

Comments
 (0)