Compare commits

...

618 Commits

Author SHA1 Message Date
Marcel Dempers
6de04aec72
Merge pull request #257 from marcel-dempers/crossplane
Crossplane
2025-05-28 21:37:07 +10:00
marcel-dempers
ed10aa296f crossplane tweaks 2025-05-22 10:32:06 +10:00
marcel-dempers
e89da26fa4 crossplane resources and readme 2025-05-20 16:32:56 +10:00
marcel-dempers
4135419bbd add provider 2025-05-17 13:01:35 +10:00
marcel-dempers
d103676b6e crossplane 2025-05-17 12:33:35 +10:00
marcel-dempers
aecb4c102e upgrade prometheus and grafana to latest 2025-04-26 22:08:04 +10:00
Marcel Dempers
d009357aea
Merge pull request #255 from marcel-dempers/prometheus
upgrade all prometheus clients and languages to latest versions
2025-04-26 22:01:07 +10:00
marcel-dempers
8ab37d3af3 update docker-compose to docker compose 2025-04-26 21:46:41 +10:00
marcel-dempers
71b0860e7f upgrade all prometheus clients and languages to latest versions 2025-04-26 21:43:00 +10:00
Marcel Dempers
0faa84adf7
Merge pull request #254 from marcel-dempers/opentel-logs
basic opentel overview demo
2025-04-26 21:21:03 +10:00
marcel-dempers
b1ff3584fe add opentel files 2025-04-24 16:30:23 +10:00
marcel-dempers
7df717d9cc helm updates 2025-04-03 14:09:38 +11:00
Marcel Dempers
69f68f4617
Merge pull request #251 from marcel-dempers/secrets
k8s secret guide updates
2025-03-17 21:21:36 +11:00
Marcel Dempers
3dc59d66f9
secret updates 2025-03-17 21:20:34 +11:00
marcel-dempers
f9315b9d33 k8s secret guide updates 2025-03-10 09:58:46 +11:00
marcel-dempers
9c289a54da upgrade to dotnet 8 2025-02-13 18:05:12 +11:00
marcel-dempers
c5c755b2c7 remove old asp dotnet files 2025-02-13 17:59:22 +11:00
Marcel Dempers
c78e6701e3
Merge pull request #250 from marcel-dempers/service
update k8s services guide
2025-02-07 08:07:35 +11:00
marcel-dempers
45a85870b8 update k8s services guide 2025-02-07 08:07:04 +11:00
marcel-dempers
544db5938a add ep5 for postgres content 2025-01-19 07:56:41 +11:00
marcel-dempers
0978619b02 add instructions for deployment 2025-01-19 07:55:33 +11:00
marceldempers
8394659448
add sidecar pod example 2025-01-08 22:16:57 +11:00
marcel-dempers
6d217aad29 fix kubectl exec 2025-01-08 14:49:36 +11:00
Marcel Dempers
ab284e1ef8
Merge pull request #248 from marcel-dempers/XE6k7WXsNMPaQg==
upgrade VPA to latest for kubernetes 1.30
2025-01-07 15:07:13 +11:00
marcel-dempers
0567bef2a5 upgrade VPA to latest for kubernetes 1.30 2025-01-07 15:06:31 +11:00
Marcel Dempers
6e6be4b3f4
Merge pull request #246 from marcel-dempers/pods
add example pod manifest
2024-12-31 06:41:33 +11:00
Marcel Dempers
1b8ca7bc4c
add example pod manifest 2024-12-31 06:41:14 +11:00
marceldempers
53cc8ff8bf
Merge pull request #245 from marcel-dempers/fix-pythonapp
fix python app by updating
2024-11-21 16:55:05 +11:00
marceldempers
e7e6b8cf75
fix python app by updating 2024-11-21 16:54:50 +11:00
marceldempers
39852a2849
Merge pull request #239 from marcel-dempers/dependabot/npm_and_yarn/monitoring/prometheus/nodejs-application/src/multi-9f37c16f8f
Bump cookie and express in /monitoring/prometheus/nodejs-application/src
2024-11-18 08:39:54 +11:00
dependabot[bot]
76a5becfbe
Bump cookie and express in /monitoring/prometheus/nodejs-application/src
Bumps [cookie](https://github.com/jshttp/cookie) to 0.7.1 and updates ancestor dependency [express](https://github.com/expressjs/express). These dependencies need to be updated together.


Updates `cookie` from 0.4.2 to 0.7.1
- [Release notes](https://github.com/jshttp/cookie/releases)
- [Commits](https://github.com/jshttp/cookie/compare/v0.4.2...v0.7.1)

Updates `express` from 4.17.3 to 4.21.1
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.1/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.3...4.21.1)

---
updated-dependencies:
- dependency-name: cookie
  dependency-type: indirect
- dependency-name: express
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-17 21:39:43 +00:00
marceldempers
29f6291913
Merge pull request #233 from marcel-dempers/dependabot/npm_and_yarn/monitoring/prometheus/nodejs-application/src/multi-ceff1a497b
Bump path-to-regexp and express in /monitoring/prometheus/nodejs-application/src
2024-11-18 08:37:04 +11:00
Marcel Dempers
ad009cd1ff
Merge pull request #244 from marcel-dempers/45pynvnWip0FciZLjQ==
upgrade linkerd
2024-11-17 19:44:34 +11:00
marcel-dempers
5694ff69f1 upgrade linkerd 2024-11-17 19:44:04 +11:00
Marcel Dempers
7c58dc9bdf
Merge pull request #243 from marcel-dempers/45pynvnWip0FciZLjQ==
upgrade ingress in the linkerd guide
2024-11-17 18:36:48 +11:00
marcel-dempers
73c507ad75 upgrade ingress in the linkerd guide 2024-11-17 18:36:16 +11:00
marceldempers
205f34545f
Merge pull request #240 from ArvinthC3000/patch-1
Updating go-application module and docerfile
2024-11-02 15:24:58 +11:00
Arvinth C
2943b35a71
Update go.mod 2024-10-16 21:07:54 +05:30
ArvinthC3000
cec7b5ddcf Updating dockerfile for go application
Signed-off-by: ArvinthC3000 <archand@progress.com>
2024-10-16 21:05:59 +05:30
Arvinth C
177883429c
Create go.mod 2024-10-16 21:00:53 +05:30
dependabot[bot]
50eba16f40
Bump path-to-regexp and express
Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) to 0.1.10 and updates ancestor dependency [express](https://github.com/expressjs/express). These dependencies need to be updated together.


Updates `path-to-regexp` from 0.1.7 to 0.1.10
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.7...v0.1.10)

Updates `express` from 4.17.3 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.3...4.20.0)

---
updated-dependencies:
- dependency-name: path-to-regexp
  dependency-type: indirect
- dependency-name: express
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-11 00:43:48 +00:00
marceldempers
a1fcfc975f
Merge pull request #218 from aatalrashid/modify
FIX: Can't open the append-only file: Permission denied
2024-09-09 09:07:13 +10:00
marceldempers
6e80ba9218
Merge pull request #227 from nxm/master
bump cluster role binding
2024-09-09 09:05:36 +10:00
marceldempers
ea497429ac
Merge pull request #231 from m-ocean-it/patch-1
fix crashing: await for Promise
2024-09-09 09:04:30 +10:00
m-ocean-it
6d7959e025
fix crashing: await for Promise 2024-08-24 18:29:19 +03:00
Jakub Szturomski
4b4de3272c bump cluster role binding 2024-05-29 16:48:22 +02:00
marceldempers
c7534eea94
Merge pull request #221 from marcel-dempers/k8s-postgres
add k8s postgres guide
2023-10-24 20:58:00 +11:00
marcel-dempers
3eb2e73c9e add k8s postgres guide 2023-10-24 20:57:21 +11:00
marceldempers
a17be8cad9
Update README.md 2023-10-18 20:34:07 +11:00
marceldempers
1d08bd1f9d
Merge pull request #214 from marcel-dempers/githubactions
github actions updates
2023-10-16 22:56:39 +11:00
marceldempers
e398b601e4
Merge pull request #220 from marcel-dempers/affinity
Kubernetes afffinity
2023-10-16 22:55:59 +11:00
marceldempers
b47b9092f4
Merge pull request #219 from marcel-dempers/k8sprobes
kubernetes probes
2023-10-16 22:55:12 +11:00
marcel-dempers
2393194e97 probe updates 2023-10-16 22:54:04 +11:00
marcel-dempers
8d7b27508b affinity updates 2023-10-16 16:58:53 +11:00
marcel-dempers
c31fc402d8 kubernetes probe examples 2023-10-16 10:10:16 +11:00
marceldempers
6ce511cd36
disable the workflow and keep it as reference 2023-10-15 15:15:55 +11:00
marcel-dempers
5b36f19e53 affinity updates 2023-10-14 18:45:10 +11:00
marcel-dempers
f5a6234ef4 affinity updates 2023-10-11 16:40:42 +11:00
marcel-dempers
f925d502f4 affinity notes 2023-10-10 16:34:06 +11:00
TrevorNathan
1031bc07c0 FIX: Can't open the append-only file: Permission denied
- redis dbs
2023-10-05 15:19:25 +03:00
marceldempers
3c7dc4e9da
Merge pull request #216 from marcel-dempers/dependabot/pip/kubernetes/shipa/developers/docker/python/flask-2.2.5
Bump flask from 1.0.3 to 2.2.5 in /kubernetes/shipa/developers/docker/python
2023-10-04 21:59:33 +11:00
marceldempers
2fda7d708f
Merge pull request #205 from marcel-dempers/dependabot/pip/python/src/flask-2.3.2
Bump flask from 2.0.3 to 2.3.2 in /python/src
2023-10-04 21:59:08 +11:00
dependabot[bot]
d4cd7c20d4
Bump flask in /kubernetes/shipa/developers/docker/python
Bumps [flask](https://github.com/pallets/flask) from 1.0.3 to 2.2.5.
- [Release notes](https://github.com/pallets/flask/releases)
- [Changelog](https://github.com/pallets/flask/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/flask/compare/1.0.3...2.2.5)

---
updated-dependencies:
- dependency-name: flask
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-04 10:59:08 +00:00
marceldempers
47b99f55e5
Merge pull request #203 from marcel-dempers/dependabot/pip/python/introduction/part-4.http/src/flask-2.3.2
Bump flask from 2.0.2 to 2.3.2 in /python/introduction/part-4.http/src
2023-10-04 21:58:46 +11:00
marceldempers
ff1a93d073
Merge pull request #204 from marcel-dempers/dependabot/pip/python/introduction/part-5.database.redis/flask-2.3.2
Bump flask from 2.0.2 to 2.3.2 in /python/introduction/part-5.database.redis
2023-10-04 21:58:22 +11:00
marceldempers
5337006f91
Merge pull request #206 from marcel-dempers/dependabot/pip/monitoring/prometheus/python-application/src/flask-2.3.2
Bump flask from 2.1.2 to 2.3.2 in /monitoring/prometheus/python-application/src
2023-10-04 21:57:55 +11:00
marceldempers
a2ae5796d7
Merge pull request #215 from marcel-dempers/openai
introduction to open AI
2023-10-04 21:56:59 +11:00
marcel-dempers
f49fff9af5 update readme 2023-10-03 16:48:36 +11:00
marcel-dempers
d37efdde16 add example workflow 2023-10-01 19:03:31 +11:00
marcel-dempers
3918c32e67 add example workflow 2023-10-01 18:58:42 +11:00
marcel-dempers
19d2d161b7 add docker dind support 2023-10-01 18:44:07 +11:00
marcel-dempers
1ef3232ea0 add new github actions updates 2023-10-01 18:27:03 +11:00
Marcel Dempers
c4d93da7f9
Merge pull request #213 from marcel-dempers/postgres-replication
postgres replication guide
2023-10-01 14:55:25 +11:00
marcel-dempers
23a2846758 postgres replication guide 2023-10-01 14:54:42 +11:00
marcel-dempers
9a78d2af15 add openai files 2023-10-01 14:50:22 +11:00
marceldempers
0c694e5a83
Merge pull request #202 from marcel-dempers/fluxcd-2022
flux-v2
2023-09-28 21:43:45 +10:00
fluxcdbot
1d046a120d docker.io/aimvector/example-app-2:0.0.2 2023-09-28 08:17:46 +00:00
Flux
015ab45dc0 Add Flux v2.1.1 component manifests 2023-09-28 07:57:34 +00:00
marcel-dempers
827536f63c updates 2023-09-28 17:50:40 +10:00
Flux
2c8fa23e1f Add Flux sync manifests 2023-09-28 07:22:09 +00:00
Flux
429df5d66f Add Flux v2.1.1 component manifests 2023-09-28 07:22:07 +00:00
marcel-dempers
524ca00611 reverting files for demo purpose 2023-09-26 11:35:43 +10:00
marcel-dempers
d703563f43 Merge branch 'fluxcd-2022' of https://github.com/marcel-dempers/docker-development-youtube-series into fluxcd-2022 2023-09-26 11:32:57 +10:00
marcel-dempers
5e800a5feb flux manifest updates 2023-09-26 11:32:51 +10:00
fluxcdbot
3a6be205a5 docker.io/aimvector/example-app-2:0.0.3 2023-09-26 01:31:36 +00:00
marcel-dempers
0cf869ea7c fluxcd version updates 2023-09-26 11:23:50 +10:00
marcel-dempers
25d04c81c7 Merge branch 'fluxcd-2022' of https://github.com/marcel-dempers/docker-development-youtube-series into fluxcd-2022 2023-09-26 09:43:10 +10:00
marcel-dempers
cb11199f37 flux bootrap command update for v2 2023-09-26 09:43:04 +10:00
Flux
13cadd8f42 Add Flux v2.1.1 component manifests 2023-09-25 23:03:35 +00:00
Flux
c7d7b8e770 Add Flux v2.1.1 component manifests 2023-09-25 22:32:59 +00:00
marcel-dempers
8a12d9bdef update flux manifests 2023-09-26 06:41:05 +10:00
Flux
09fe225846 Add Flux sync manifests 2023-09-25 05:02:03 +00:00
Flux
bba2fd54cc Add Flux v2.1.1 component manifests 2023-09-25 05:02:00 +00:00
marcel-dempers
f7cc5ca37e flux updates 2023-09-22 06:57:51 +10:00
marceldempers
d54e2ef51f
Merge pull request #211 from FeralWeasel/patch-1
Update cluster-role.yaml
2023-08-21 19:55:28 +10:00
FeralWeasel
a73921605f
Update cluster-role.yaml
remove beta as it will now cause issues in deployment.
2023-06-30 11:30:04 -07:00
dependabot[bot]
89556d4cd0
Bump flask in /monitoring/prometheus/python-application/src
Bumps [flask](https://github.com/pallets/flask) from 2.1.2 to 2.3.2.
- [Release notes](https://github.com/pallets/flask/releases)
- [Changelog](https://github.com/pallets/flask/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/flask/compare/2.1.2...2.3.2)

---
updated-dependencies:
- dependency-name: flask
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 23:51:53 +00:00
dependabot[bot]
378ae471ed
Bump flask from 2.0.3 to 2.3.2 in /python/src
Bumps [flask](https://github.com/pallets/flask) from 2.0.3 to 2.3.2.
- [Release notes](https://github.com/pallets/flask/releases)
- [Changelog](https://github.com/pallets/flask/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/flask/compare/2.0.3...2.3.2)

---
updated-dependencies:
- dependency-name: flask
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 23:35:35 +00:00
dependabot[bot]
2da868d742
Bump flask in /python/introduction/part-5.database.redis
Bumps [flask](https://github.com/pallets/flask) from 2.0.2 to 2.3.2.
- [Release notes](https://github.com/pallets/flask/releases)
- [Changelog](https://github.com/pallets/flask/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/flask/compare/2.0.2...2.3.2)

---
updated-dependencies:
- dependency-name: flask
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 23:19:12 +00:00
dependabot[bot]
e95f926d5d
Bump flask from 2.0.2 to 2.3.2 in /python/introduction/part-4.http/src
Bumps [flask](https://github.com/pallets/flask) from 2.0.2 to 2.3.2.
- [Release notes](https://github.com/pallets/flask/releases)
- [Changelog](https://github.com/pallets/flask/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/flask/compare/2.0.2...2.3.2)

---
updated-dependencies:
- dependency-name: flask
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 23:14:33 +00:00
marceldempers
634ba47ba1
Merge pull request #193 from myishay/patch-1
correct scan rerun command
2023-04-17 10:11:44 +10:00
marceldempers
3470911914
Merge pull request #201 from DerLev/master
Fixing Redis Kubernetes
2023-04-17 10:07:56 +10:00
marcel-dempers
689a52bf71 Merge branch 'master' into fluxcd-2022 2023-04-17 09:51:24 +10:00
marcel-dempers
10ef046978 update readme 2023-04-17 09:49:42 +10:00
DerLev
1a6f680e6f
fixing sentinel initContainer and updating redis 2023-04-14 14:23:33 +02:00
Flux
c1b3c6bd24 Add Flux sync manifests 2023-03-20 23:11:24 +00:00
Flux
da5f6a05e8 Add Flux v0.41.1 component manifests 2023-03-20 22:52:40 +00:00
marcel-dempers
2ce003d6dc sync 2023-03-21 09:51:00 +11:00
Flux
9334527d27 Add Flux v0.41.1 component manifests 2023-03-20 22:32:54 +00:00
marcel-dempers
8acc5661ad fluxcd update restructure repo 2023-03-20 22:08:00 +11:00
Marcel Dempers
b0c8e2b26c
Merge pull request #194 from marcel-dempers/ingress-nginx-2022
Ingress nginx 2023 update
2023-03-19 22:11:46 +11:00
Yishay Mendelsohn
3291f3edbb
correct scan rerun command 2023-03-16 10:52:38 +02:00
Marcel Dempers
04d1d86f12
datree hotfixes 2023-03-16 18:30:40 +11:00
Marcel Dempers
1935a34ead
Merge pull request #187 from lack3r/master
Updated kindest/node to resolve error
2023-03-15 08:59:56 +11:00
Marcel Dempers
2128acdd1f
Merge pull request #191 from agentblacksmith/patch-1
Updated the local Vault UI link
2023-03-15 08:58:54 +11:00
marcel-dempers
f8e77439aa flux doc updates 2023-03-14 08:30:32 +11:00
marcel-dempers
26fb40dce6 Merge branch 'master' into fluxcd-2022 2023-03-13 08:47:50 +11:00
marcel-dempers
48eace7204 updates 2023-03-11 23:10:49 +11:00
marcel-dempers
7fe61a2d6e Merge branch 'fluxcd-2022' of https://github.com/marcel-dempers/docker-development-youtube-series into fluxcd-2022 2023-03-11 23:09:56 +11:00
marcel-dempers
1795b32d54 readme and auto image updater wip 2023-03-11 23:09:53 +11:00
fluxcdbot
9380e336e5 docker.io/aimvector/example-app-2:0.0.2 2023-03-11 12:07:43 +00:00
marcel-dempers
8854b27c20 add image marker 2023-03-11 22:31:16 +11:00
marcel-dempers
1532cc5225 flux fix autoimage updater 2023-03-11 22:23:40 +11:00
marcel-dempers
80984b7639 readme updates 2023-03-11 22:07:22 +11:00
marcel-dempers
9f8decee66 update image 2023-03-11 22:07:22 +11:00
Flux
0e934abf5c Add Flux v0.41.1 component manifests 2023-03-11 10:16:49 +00:00
marcel-dempers
97ff18e1c0 flux updates 2023-03-11 20:57:30 +11:00
marcel-dempers
91d3db711b add app 2 2023-03-11 20:57:30 +11:00
marcel-dempers
8cf5032967 test 2023-03-11 20:57:30 +11:00
Flux
e6523900cf Add Flux v0.41.1 component manifests 2023-03-11 09:25:44 +00:00
marcel-dempers
a27f4ac11d flux updates - image scanning 2023-03-11 15:10:22 +11:00
marcel-dempers
4fcd8b86be flux image updates 2023-03-11 14:50:18 +11:00
Flux
0044a58dd5 Add Flux v0.41.1 component manifests 2023-03-11 03:40:39 +00:00
marcel-dempers
253821d863 fix flux app deployment image pull 2023-03-11 13:48:01 +11:00
marcel-dempers
6098108069 flux notes 2023-03-11 11:21:32 +11:00
marcel-dempers
fa0d9332ed update flux files 2023-03-11 11:20:31 +11:00
marcel-dempers
3774090ccb add namespaces to flux resources 2023-03-11 11:17:48 +11:00
marcel-dempers
000a878d7b restructure flux folders 2023-03-11 10:06:53 +11:00
marcel-dempers
b898ab2bf9 Merge branch 'fluxcd-2022' of https://github.com/marcel-dempers/docker-development-youtube-series into fluxcd-2022 2023-03-11 08:09:01 +11:00
marcel-dempers
51797bede7 flux readme WIP 2023-03-11 08:08:53 +11:00
Flux
1521df9042 Add Flux sync manifests 2023-03-10 21:06:33 +00:00
Flux
4da88ba980 Add Flux v0.41.1 component manifests 2023-03-10 21:06:28 +00:00
Praveen Gopinathan
387d4a329f
Updated the local Vault UI link
Removed the quotes from the link
2023-03-10 07:25:17 +05:30
Marcel Dempers
baf786af7b
Merge pull request #190 from marcel-dempers/postgres-config
postgres config files for part 2
2023-03-09 13:04:31 +11:00
marcel-dempers
812f2c141c postgres config files for part 2 2023-03-09 13:03:40 +11:00
Andreas Loizou (LACK3R)
ade7bc2ef4
Updated kindest/node to resolve error
Updated kindest/node to resolve the following error on Mac OS.
failed to create cluster: could not find a log line that matches "Reached target .*Multi-User System.*|detected cgroup v1"
2023-03-02 11:47:51 +02:00
Marcel Dempers
7ef03d3865
Merge pull request #184 from marcel-dempers/links
update video links
2023-02-07 12:19:40 +11:00
marcel-dempers
7a89e24437 update video links 2023-02-07 12:19:01 +11:00
marceldempers
c740ec50b8
Merge pull request #177 from manju369/patch-1
Update ssl_generate_self_signed.txt
2023-02-03 09:03:44 +11:00
marceldempers
dd832dbdeb
Merge pull request #175 from Schirrms/master
add 'include_timestamp true' in the elastic part of the configmap to …
2023-02-03 09:02:58 +11:00
marceldempers
b7ff7c45a1
Merge pull request #179 from aimoncabral/master
fix: docker build failing because of deprecated go version
2023-02-03 09:00:37 +11:00
marceldempers
4de5394bf0
Merge pull request #181 from marcel-dempers/datree-scoring
Datree scoring
2023-01-18 20:04:03 +11:00
marcel-dempers
bd566f9666 updates and testing 2023-01-18 20:02:59 +11:00
marcel-dempers
d271b80901 datree updates 2023-01-14 09:14:40 +11:00
marcel-dempers
93fef37b6e some new change 2023-01-12 16:45:11 +11:00
marcel-dempers
7125049bab datree test 2023-01-12 16:43:31 +11:00
marcel-dempers
51bf4bd383 datree test 2023-01-12 16:42:33 +11:00
marcel-dempers
ff52e92164 datree scoring walkthrough 2023-01-09 21:42:34 +11:00
marceldempers
945bed5bbc
Merge pull request #176 from marcel-dempers/dependabot/npm_and_yarn/monitoring/prometheus/nodejs-application/src/express-4.17.3
Bump express from 4.17.1 to 4.17.3 in /monitoring/prometheus/nodejs-application/src
2022-12-26 11:06:41 +11:00
Aimon
84ffb46275 fix: docker build failing because of deprecated go version 2022-12-22 21:35:12 -03:00
Manju
1250934379
Update ssl_generate_self_signed.txt
not able to download by just using `curl` , worked after using `curl -L` option
more info here - https://unix.stackexchange.com/a/321751/537201
2022-12-14 11:39:27 +05:30
dependabot[bot]
9f720b1046
Bump express in /monitoring/prometheus/nodejs-application/src
Bumps [express](https://github.com/expressjs/express) from 4.17.1 to 4.17.3.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.1...4.17.3)

---
updated-dependencies:
- dependency-name: express
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-13 13:22:11 +00:00
Schirrms
e1209446e3 add 'include_timestamp true' in the elastic part of the configmap to actually get the timestamp in elasticsearch 2022-12-08 13:16:12 +01:00
marcel-dempers
52738af7f4 flux wip 2022-11-22 16:52:44 +11:00
Marcel Dempers
022ec40bef
Merge pull request #172 from marcel-dempers/postgres-intro
add postgres-intro
2022-11-14 21:19:18 +11:00
marcel-dempers
9a2a27ea06 add postgres-intro 2022-11-14 21:18:41 +11:00
Marcel Dempers
0e50e4a50f
Merge pull request #169 from chan1992241/fix-typo
fix typo
2022-11-14 19:23:48 +11:00
Marcel Dempers
614adf003d
Merge pull request #171 from marcel-dempers/redis-update
non alpine shell script fix and update latest k8s
2022-11-14 19:12:08 +11:00
marcel-dempers
e6aa1e60de non alpine shell script fix and update latest k8s 2022-11-14 19:11:30 +11:00
Marcel Dempers
b96533c6e5
Merge pull request #170 from marcel-dempers/sealedsecrets
Sealed secrets
2022-11-14 18:58:35 +11:00
marcel-dempers
dc163cf341 nginx demo and features 2022-11-14 13:24:50 +11:00
marcel-dempers
4095c3050a nginx ingress wip 2022-11-11 10:10:14 +11:00
chan1992241
a9645aa4b2 fix typo 2022-11-09 10:04:23 +08:00
marcel-dempers
ee246f3e9f sealed secret prototyping 2022-11-08 19:44:56 +11:00
marcel-dempers
84890e84c3 updates to sealed secrets 2022-11-08 16:58:51 +11:00
marceldempers
c484d2f39f
Merge pull request #161 from user449993/master
fixes path to deploy example-app in readme.md
2022-11-07 10:45:30 +00:00
marcel-dempers
9b130c3b65 nginx wip 2022-11-07 21:21:40 +11:00
marceldempers
5a2f656dc8
Update requirements.txt 2022-11-07 15:55:00 +11:00
marcel-dempers
655764b074 sealedsecrets prototype 2022-11-07 15:52:54 +11:00
marceldempers
ec8bfc9325
Merge pull request #162 from marcel-dempers/kubectl
Kubectl
2022-10-20 21:21:50 +11:00
marcel-dempers
86c1954546 updates to sync kubectl video 2022-09-21 12:43:12 +10:00
marcel-dempers
c04feaf772 kubectl wip 2022-08-21 15:45:49 +10:00
user449993
753d36e402
Merge pull request #1 from user449993/fix/service-monitors-readme
fixes path to deploy example-app in readme.md
2022-08-13 16:25:03 +00:00
user449993
8bda52fc1d
fixes path to deploy example-app in readme.md 2022-08-13 16:24:02 +00:00
marcel-dempers
752f395e88 bump minor version on prometheus monitoring 2022-08-10 12:47:55 +10:00
marcel-dempers
77d46d0d69 kubectl wip 2022-08-10 09:31:15 +10:00
marcel-dempers
bdc235b29c update video link for kubectl basics 2022-08-07 13:58:11 +10:00
marceldempers
5e97959656
Merge pull request #159 from Ashikuroff/patch-3
Update deployment.yaml
2022-08-07 13:49:03 +10:00
marceldempers
52db04db21
Merge pull request #151 from marcel-dempers/servicemonitors
servicemonitors
2022-08-07 13:48:05 +10:00
Ashikuroff
ecf9e5b40f
Update deployment.yaml 2022-08-04 10:07:05 +08:00
marceldempers
0904659201
Merge pull request #147 from marcel-dempers/datree
datree
2022-07-30 18:42:25 +10:00
marcel-dempers
51d2e8357a remove sample pipeline 2022-07-30 18:42:04 +10:00
marcel-dempers
0633fac569 fix 2022-07-30 18:41:20 +10:00
marcel-dempers
7dcae42633 datree updates 2022-07-20 09:13:20 +10:00
Marcel Dempers
73430b6694
Merge pull request #154 from marcosvm/marcosvm-typo
update typo on readme.md
2022-07-19 08:49:15 +10:00
Marcos Oliveira
52e5c975f5
Update readme.md 2022-07-18 15:46:40 -07:00
Marcos Oliveira
97102574eb
update typo on readme.md 2022-07-18 15:39:37 -07:00
marcel-dempers
74878f5903 servicemonitors 2022-07-15 10:20:22 +10:00
marcel-dempers
8c7c9702f1 update 2022-07-07 10:49:57 +10:00
marcel-dempers
20af4e8de1 update 2022-07-07 10:42:17 +10:00
marcel-dempers
1915ff6889 pipeline update 2022-07-07 10:40:05 +10:00
marcel-dempers
a67ef5f2a9 remove unused action 2022-07-07 10:32:47 +10:00
marcel-dempers
9f9a467ae0 datree updates 2022-07-07 10:30:12 +10:00
marcel-dempers
02e0f20e67 datree updates 2022-07-06 16:35:52 +10:00
marcel-dempers
ecbf42ce83 datree updates 2022-07-05 16:11:58 +10:00
marcel-dempers
7a553d01f0 add vscode extension 2022-06-29 16:50:46 +10:00
marcel-dempers
374c47b244 updates and helm 2022-06-28 09:44:21 +10:00
marcel-dempers
72ef3db7df datree updates 2022-06-24 09:40:32 +10:00
marcel-dempers
fc42e298ba wip 2022-06-23 21:37:36 +10:00
marcel-dempers
44857147be install datree 2022-06-23 14:10:43 +10:00
marcel-dempers
d9f7a01a15 datree wip 2022-06-15 11:39:56 +10:00
Marcel Dempers
2d0c1d88e1
Merge pull request #145 from marcel-dempers/codespaces
codespaces
2022-06-13 16:54:19 +10:00
marcel-dempers
e150df6426 updates 2022-06-07 14:00:00 +10:00
marcel-dempers
143dfaaf97 update container add docker 2022-06-07 09:23:12 +10:00
marcel-dempers
b5a4621d58 codespaces container 2022-06-07 09:07:42 +10:00
Marcel Dempers
324fd41b5f
Merge pull request #143 from marcel-dempers/portainer-oauth
portainer oauth settings example
2022-06-07 08:44:40 +10:00
marcel-dempers
fcd45bea64 portainer oauth settings example 2022-05-23 08:59:09 +10:00
Marcel Dempers
0d637c1046
Merge pull request #135 from panki989/patch-1
Adding Issuer
2022-05-15 16:09:44 +10:00
marcel-dempers
3d107eacfb Merge branch 'master' of https://github.com/marcel-dempers/docker-development-youtube-series 2022-05-03 19:22:59 +10:00
Marcel Dempers
563663f309
Merge pull request #139 from marcel-dempers/k8s
K8s tutorial
2022-05-03 19:21:29 +10:00
marcel-dempers
3724902e8e k8s tutorial updates 2022-05-03 19:19:15 +10:00
marcel-dempers
61303ea8ee portainer volume ignore 2022-05-02 07:57:35 +10:00
marcel-dempers
f5e528ceca updates 2022-04-22 20:02:04 +10:00
marcel-dempers
77df499742 k8s guide update 2022-04-15 22:40:42 +10:00
marcel-dempers
71a1fcb7cd Merge branch 'master' into k8s 2022-04-15 15:54:26 +10:00
Marcel Dempers
7384d560d9 updates k8s 2022-04-15 15:52:17 +10:00
Pankaj
f91b1641d9
Adding Issuer
https://stackoverflow.com/a/69303712

As soon as our vault pods restarted and after unsealing them again, they are failing the auth mechanism in init container. This will fix the same.
2022-03-27 11:44:04 +05:30
Marcel Dempers
8dd82ada77
Update README.md 2022-03-22 16:48:36 +11:00
Marcel Dempers
920b78db41
Merge pull request #111 from marcel-dempers/python-redis
Python redis
2022-03-22 16:46:17 +11:00
marcel-dempers
c23f3a0cdc updates 2022-03-22 16:44:09 +11:00
marcel-dempers
1cd21b939b wip 2022-03-20 07:53:10 +11:00
Marcel Dempers
4aa9108b48
Merge pull request #128 from marcel-dempers/portainer
portainer
2022-03-11 17:11:15 +11:00
Marcel Dempers
27ff3314a5
Merge branch 'master' into portainer 2022-03-11 17:11:07 +11:00
marcel-dempers
79052248fa portainer files 2022-03-07 22:28:16 +11:00
marcel-dempers
4b42ca91c5 update 2022-02-26 12:02:03 +11:00
marcel-dempers
ac0e5cf053 test 2022-02-20 22:08:37 +11:00
marcel-dempers
99058f0d89 test 2022-02-20 21:36:14 +11:00
marcel-dempers
a2d82e4dc4 update 2022-02-20 18:49:53 +11:00
marcel-dempers
7335532373 update 2022-02-20 18:48:30 +11:00
marcel-dempers
da8749be10 update 2022-02-20 18:32:58 +11:00
marcel-dempers
5481fb7c46 update 2022-02-20 18:30:51 +11:00
marcel-dempers
a8ba3bba7c ingress update 2022-02-20 18:21:24 +11:00
marcel-dempers
4d02dbe534 example-app 2022-02-20 18:07:05 +11:00
Marcel Dempers
43b06a684d
Merge pull request #125 from marcel-dempers/rancher
rancher
2022-02-18 20:30:20 +11:00
marcel-dempers
633f8f2865 updates 2022-02-13 19:42:42 +11:00
marcel-dempers
769b335b22 wip 2022-02-10 13:00:51 +11:00
Marcel Dempers
cfb70bac24
Merge pull request #120 from marcel-dempers/vault
vault-2022
2022-01-26 12:17:19 +11:00
marcel-dempers
055d9e7992 updates 2022-01-26 12:16:46 +11:00
Marcel Dempers
36c880fb45
Merge pull request #123 from larsskj/master
Avoid fixed namespace
2022-01-26 10:36:40 +11:00
marcel-dempers
9449f8a2a7 wip 2022-01-26 10:32:43 +11:00
larsskj
e444489e9b Avoid fixed namespace in Sentinel setup. 2022-01-24 22:23:00 +01:00
marceldempers
0920c549b2
Merge pull request #114 from benchwang/bewang/fix_unique_target_error
Fix error: failed to find unique target for patch apps_v1_Deployment|…
2022-01-24 11:00:24 +11:00
marceldempers
7f890e1c56
Merge pull request #121 from marcel-dempers/kube-prometheus-2022
kube-prometheus-2022
2022-01-23 20:45:22 +11:00
marcel-dempers
88fbd12e50 add link 2022-01-19 22:33:48 +11:00
marcel-dempers
6f155829b5 updates 2022-01-16 22:58:08 +11:00
marcel-dempers
6632544f0c updates 2022-01-15 15:11:35 +11:00
marcel-dempers
a8c0a0d403 wip 2022-01-13 10:05:34 +11:00
Marcel Dempers
331ca31e48
Merge pull request #119 from strangiato/markdown-fix
Remove extra code quotes
2022-01-11 18:11:32 +11:00
marcel-dempers
80fc07a7ec wip 2022-01-11 18:08:06 +11:00
Trevor Royer
2f802d6c17 remove extra code quotes 2022-01-10 14:17:14 -06:00
Marcel Dempers
100be5c0ae
Merge pull request #117 from zizizach/kubernetes_aws_getting-started-eks
Remove additional whitespace in some commands
2022-01-10 08:33:44 +11:00
zizizach
77d3c97644
Remove additional whitespace in some commands
aws-cli is now rejecting some of the command with double whitespace

```
An error occurred (InvalidInput) when calling the AttachRolePolicy operation: ARN  arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly is not valid.
```
2021-12-11 23:09:55 +08:00
Marcel Dempers
63ccd689c7
Merge pull request #113 from Treehopper/master
Update az Container, Terraform and Kubernetes Versions.
2021-12-05 08:27:15 +11:00
marcel-dempers
23767a5644 video player side edit 2021-12-05 08:25:53 +11:00
Bench Wang
aa45329eb2 Fix error: failed to find unique target for patch apps_v1_Deployment|example-deploy 2021-12-01 16:28:18 +08:00
Treehopper
f88562ce1f Fix Warning: Version constraints inside provider configuration blocks are deprecated. 2021-11-25 13:19:07 +00:00
Treehopper
99a7535702 Fix terraform error: Unsupported argument
option has been dropped in terraform 2.x
2021-11-25 13:11:21 +00:00
Treehopper
ab38006fc8 Use fixed version for reproducibility. 2021-11-25 09:29:21 +00:00
Treehopper
e6c40a7f8a Fix: Version 1.16.10 is not supported in this region.
Full:
Error: creating Managed Kubernetes Cluster "aks-getting-started" (Resource Group "aks-getting-started"): containerservice.ManagedClustersClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="AgentPoolK8sVersionNotSupported" Message="Version 1.16.10 is not supported in this region. Please use [az aks get-versions] command to get the supported version list in this region. For more information, please check https://aka.ms/supported-version-list"
2021-11-24 16:22:11 +00:00
Treehopper
12ebd06694 Update to Terraform 1.0.11. 2021-11-24 15:58:51 +00:00
Treehopper
82c52098e7 Fix: "Values of identifierUris property must use a verified domain of the organization or its subdomain"
Full error:
Changing "aks-getting-started-sp" to a valid URI of "http://aks-getting-started-sp", which is the required format used for service principal names
Values of identifierUris property must use a verified domain of the organization or its subdomain: 'http://aks-getting-started-sp'

Replaced with:
WARNING: 'name' property in the output is deprecated and will be removed in the future. Use 'appId' instead.
2021-11-24 15:56:20 +00:00
Marcel Dempers
e43dac88f2
Merge pull request #110 from rajalokan/update_readme
Updated README to fix code formatting
2021-11-24 07:10:42 +11:00
Alok Kumar
73b9040354
Update readme.md 2021-11-22 13:28:50 +05:30
Alok Kumar
228906ea95
Updated README to fix code formatting
- Updated README to fix code formatting
2021-11-22 13:24:28 +05:30
marcel-dempers
6cc02eaff3 Merge branch 'master' into python-redis 2021-11-22 14:37:01 +11:00
marcel-dempers
c4fd6e6dea add python redis code and guide 2021-11-22 14:36:29 +11:00
Marcel Dempers
8cf81c68d5
Update redis.conf 2021-11-21 19:53:50 +11:00
Marcel Dempers
23c10a9572
Update redis.conf 2021-11-21 19:53:31 +11:00
Marcel Dempers
9ef2d6f454
Update redis.conf 2021-11-21 19:53:10 +11:00
Marcel Dempers
d52fb4d739
Merge pull request #105 from marcel-dempers/python-http
Python http
2021-11-18 08:58:15 +11:00
marcel-dempers
d47976ffa8 updates 2021-11-18 08:57:39 +11:00
Marcel Dempers
9e55e90c97
Merge pull request #107 from marcel-dempers/go-redis
Go redis
2021-11-17 07:26:15 +11:00
marcel-dempers
77c038d44d updates 2021-11-12 22:15:01 +11:00
marcel-dempers
f796c4bfc6 updates 2021-11-12 12:38:00 +11:00
marcel-dempers
f48c3bd323 improvements 2021-10-20 13:44:27 +11:00
marcel-dempers
bb3ef94b2d improvements 2021-10-20 13:43:54 +11:00
marcel-dempers
d1ed631367 go-redis 2021-10-16 16:08:42 +11:00
Marcel Dempers
65d89acefb
Merge pull request #103 from orcema/master
automatically remove the container when it exits
2021-10-06 09:13:25 +11:00
Marcel Dempers
e707365e75
Merge pull request #104 from ewhitesides/small_fix
mv go.mod so dockerfile works
2021-10-05 20:37:11 +11:00
marcel-dempers
80773627a3 http with python 2021-10-05 20:26:34 +11:00
Erik Whitesides
7c0ffaff4b mv go.mod so dockerfile works 2021-09-29 00:11:50 -04:00
Orce Marinkovski
fcb13a94f6 automatically remove the container when it exits 2021-09-26 09:55:34 +02:00
marcel-dempers
9f23c5cfbf Merge branch 'master' into python-http 2021-09-23 07:46:12 +10:00
Marcel Dempers
0009d42207
Merge pull request #102 from marcel-dempers/rbac
k8s-rbac
2021-09-20 23:33:09 +10:00
marcel-dempers
5de4cf18c8 update 2021-09-15 19:08:40 +10:00
marcel-dempers
18d9ac2ca0 rbac 2021-09-14 12:59:35 +10:00
Marcel Dempers
9fda23d80b
Merge pull request #100 from marcel-dempers/python-json
python-json
2021-09-13 13:35:25 +10:00
marcel-dempers
960563164b Merge branch 'master' into python-json 2021-09-13 13:34:47 +10:00
marcel-dempers
9fb836b8d4 wip 2021-09-13 13:28:23 +10:00
marcel-dempers
4021f0f14e init 2021-09-06 21:11:46 +10:00
Marcel Dempers
fac08a0109
Merge pull request #99 from marcel-dempers/python-files
python-files
2021-09-06 20:05:49 +10:00
marcel-dempers
976e397c1f updates 2021-09-04 09:14:37 +10:00
marcel-dempers
16306a52c4 remove 2021-09-01 22:15:03 +10:00
marcel-dempers
2f778931f3 json 2021-09-01 22:11:28 +10:00
marcel-dempers
55290df2e0 files 2021-08-31 21:01:02 +10:00
Marcel Dempers
029c91e3e0
Merge pull request #97 from marcel-dempers/python-intro
python-intro
2021-08-29 10:24:27 +10:00
marcel-dempers
fdeec671de updates 2021-08-27 19:39:47 +10:00
marcel-dempers
ea0634f207 add files for python 2021-08-21 09:19:15 +10:00
marcel-dempers
c01029aba3 fix stale action 2021-08-14 08:57:17 +10:00
marcel-dempers
c96e7afb93 Merge branch 'master' of https://github.com/marcel-dempers/docker-development-youtube-series 2021-08-14 08:56:06 +10:00
marcel-dempers
fb2b314836 fix stale action 2021-08-14 08:55:53 +10:00
Marcel Dempers
3ff331078e
Merge pull request #94 from marcel-dempers/fix-find-master-regex
find master by host and ip
2021-08-14 08:41:15 +10:00
marcel-dempers
e4bd0085cc find master by host and ip 2021-08-14 08:39:00 +10:00
Marcel Dempers
7d7404a8ae
Merge pull request #88 from marcel-dempers/kafka-consumer
Kafka consumer
2021-08-09 21:49:08 +10:00
marcel-dempers
fd94ebd341 consumer guide updates 2021-07-11 18:54:06 +10:00
marcel-dempers
81476f540d consumer wip 2021-06-15 20:27:23 +10:00
marcel-dempers
b051ff867f Merge branch 'master' into kafka-consumer 2021-06-14 15:18:12 +10:00
marcel-dempers
c75fe6c76c consumer wip 2021-06-14 15:16:56 +10:00
Marcel Dempers
b65c9fe1d0
Merge pull request #86 from marcel-dempers/kafka-compose
Kafka compose
2021-06-13 20:07:03 +10:00
marcel-dempers
f15521318d ignore kafka data folders 2021-06-09 20:08:34 +10:00
marcel-dempers
f012ac32be compose steps 2021-06-09 09:06:21 +10:00
marceldempers
1bd98cb9a3
Merge pull request #78 from marcel-dempers/kafka
kafka-intro
2021-06-06 21:27:02 +10:00
marcel-dempers
816953d517 updates 2021-06-03 11:29:46 +10:00
marcel-dempers
0ba3a32a24 Merge branch 'master' into kafka 2021-05-27 14:53:21 +10:00
marcel-dempers
6be9fe471b Merge branch 'master' of https://github.com/marcel-dempers/docker-development-youtube-series 2021-05-27 13:42:41 +10:00
marcel-dempers
dceb5e2946 tracing optimizations + netcore examples 2021-05-27 13:42:24 +10:00
Marcel Dempers
274a661bee
Merge pull request #84 from marcel-dempers/daemonsets
Daemonsets
2021-05-27 07:09:42 +10:00
Marcel Dempers
469d09aa68
Update README.md 2021-05-27 07:09:19 +10:00
Marcel Dempers
8927a39200
Rename headlress-service.yaml to headless-service.yaml 2021-05-27 07:08:11 +10:00
Marcel Dempers
2567cbed15
Merge pull request #83 from eriksegecs/patch-1
flask run wrong ip
2021-05-26 20:59:27 +10:00
Marcel Dempers
3a006ede01
Merge pull request #82 from Soren90/master
Update to redis:6.2.3-alpine
2021-05-26 20:48:37 +10:00
Erik Segecs
f224b6f502
flask run wrong ip
missing a ".0" on flask run -h
2021-05-14 02:06:03 -03:00
Nicklas Sörensen
cacdf5dc55 Update to redis:6.2.3-alpine 2021-05-11 07:59:35 +02:00
marcel-dempers
8a7a1e3699 producer+consumer and walkthrough 2021-05-06 08:13:20 +10:00
marcel-dempers
7ec37e4826 Merge branch 'master' into kafka 2021-05-02 13:04:11 +10:00
marcel-dempers
2877ef0188 Merge branch 'master' into daemonsets 2021-05-02 12:59:10 +10:00
marcel-dempers
4dd0bbd98b daemonset intro 2021-05-02 12:53:19 +10:00
marceldempers
d64c813018
Merge pull request #76 from fortinj66/master
Add  location.port to indexes in case application is on non-standard ports
2021-04-21 08:11:22 +10:00
marcel-dempers
24cb687c30 start 2021-04-21 08:09:46 +10:00
marceldempers
25ca0a292e
Merge pull request #75 from marcel-dempers/admission-controllers
admission-controllers
2021-04-20 18:52:43 +10:00
marcel-dempers
1774bfcc15 updates 2021-04-19 17:12:35 +10:00
marcel-dempers
094458c69f fix cfssl download 2021-04-19 17:12:26 +10:00
marceldempers
e61f0b31b7
Merge pull request #77 from salmanwaheed/patch-1
Update README.md
2021-04-19 07:53:53 +10:00
marcel-dempers
6c51b181fc kafka wip 2021-04-19 07:51:15 +10:00
marcel-dempers
e688761141 updates 2021-04-14 19:04:42 +10:00
marcel-dempers
f3c8f1fb5c demo 2021-04-10 15:17:10 +10:00
Salman Waheed
64339c0904
Update README.md 2021-04-08 08:56:57 +04:00
John Fortin
99c045a799 Add location.port to indexes in case application is on non-standard port
Signed-off-by: John Fortin <fortinj66@gmail.com>
2021-04-07 10:34:52 -04:00
Marcel Dempers
ec38685fcd
Update getting-started.md 2021-04-05 21:51:53 +10:00
Marcel Dempers
acf2195e54
Merge pull request #71 from rdtechie/patch-1
Install kubectl
2021-04-05 21:47:56 +10:00
Marcel Dempers
55d401ceee
Update README.md 2021-04-05 21:24:04 +10:00
marcel-dempers
bf23d4668c wip 2021-04-05 20:43:11 +10:00
Marcel Dempers
dcd35c6b70
Merge pull request #69 from marcel-dempers/tracing-intro
tracing-intro
2021-03-31 08:58:02 +11:00
marcel-dempers
b62ee94b7d disable toggles 2021-03-29 13:55:03 +11:00
marcel-dempers
9ea23b5c03 add flaky and delays for testing 2021-03-28 11:39:08 +11:00
marceldempers
633a5d11c0
Merge pull request #68 from marcel-dempers/go-cmd
go-cmd
2021-03-21 11:19:16 +00:00
marcel-dempers
e183d4b9b8 tidy up 2021-03-21 22:18:54 +11:00
Richard Diphoorn
9f6e038b7c
Install kubectl
This change shows an easier way to install kubectl, when using AKS.
2021-02-15 23:42:02 +01:00
marcel-dempers
d2278b7e2e tracing examples 2021-02-03 08:18:08 +11:00
marcel-dempers
e3dfa21ca6 update docs 2021-02-01 08:28:31 +11:00
Marcel Dempers
5c86259aff
Merge pull request #53 from schmiddim/master
Create FDQN for Redis dynamicly
2021-01-24 10:03:53 +00:00
marcel-dempers
138a127ac2 go-cmd 2021-01-20 12:33:42 +11:00
marcel-dempers
91839c9822 Merge branch 'master' into go-cmd 2021-01-07 08:33:39 +11:00
marcel-dempers
2059ace2f1 add file 2021-01-07 08:33:15 +11:00
Marcel Dempers
daf73d2cec
Merge pull request #63 from marcel-dempers/go-intro
go-intro
2021-01-04 10:18:30 +00:00
marcel-dempers
75e20b239f part 1,2,3 2021-01-04 21:17:54 +11:00
marcel-dempers
776e42da90 go intro 2020-12-25 07:28:53 +11:00
Marcel Dempers
ab2db8a435
Merge pull request #62 from edwinwongy/redis-configmap-fix
Delete 'user default on' in  redis config
2020-12-18 06:45:33 +00:00
Edwin Wong
29fb4daa36 Delete 'user default on' in redis config 2020-12-18 11:14:55 +08:00
Marcel Dempers
b91d28b95d
Merge pull request #59 from marcel-dempers/shipa
Shipa
2020-12-09 20:58:40 +00:00
Marcel Dempers
d31cff5cef
Merge branch 'master' into shipa 2020-12-09 20:58:15 +00:00
marcel-dempers
88a86f681a cert-manager refactoring 2020-12-09 20:57:27 +00:00
marcel-dempers
fa92a6fd70 cert-wip 2020-12-09 20:57:27 +00:00
marcel-dempers
eb531a57a4 wip 2020-12-09 20:57:27 +00:00
marcel-dempers
45b2aecdbf shipa wip 2020-11-29 14:33:00 +11:00
marcel-dempers
1b2bce85fe updates 2020-11-29 10:50:04 +11:00
marcel-dempers
d39ea77c12 docs - fluentd k8s 2020-11-26 09:07:07 +00:00
marcel-dempers
eaec3a66c3 wip 2020-11-26 09:07:07 +00:00
marcel-dempers
992d78042f fluent wip 2020-11-26 09:07:07 +00:00
marcel-dempers
f9b9a3f1fe fluent-k8s wip 2020-11-26 09:07:07 +00:00
marcel-dempers
2b4df899b1 fluent-k8s-wip 2020-11-26 09:07:07 +00:00
marcel-dempers
921737efb3 shipa wip 2020-11-24 11:33:08 +11:00
marcel-dempers
d384353ef9 app build + deploy 2020-11-22 19:07:37 +11:00
marcel-dempers
3d563ad550 shipa wip 2020-11-20 18:09:29 +11:00
Ben Chatelain
bbf9ee299d 🐛 Wrap SERVICE_PRINCIPAL_SECRET in double quotes
This helps prevent special characters in the password from being interpreted by the shell. Doesn't handle when the password contains double-quotes.
2020-11-16 21:09:20 +00:00
marcel-dempers
26f7c9c37f file refactor for grafana 2020-11-14 08:53:16 +11:00
marcel-dempers
63cf075fd7 helm wip 2020-11-10 07:40:54 +00:00
marcel-dempers
5e0e4a52bc helm wip 2020-11-10 07:40:54 +00:00
Marcel Dempers
84d6df644b
Update readme.md 2020-11-09 07:27:05 +11:00
Marcel Dempers
f9432bf112
Update readme.md 2020-11-09 07:26:32 +11:00
Marcel Dempers
341efada7e
Fix links 2020-11-09 07:04:50 +11:00
Marcel Dempers
5b29059681
Update README.md 2020-11-09 07:03:57 +11:00
Michael
10aad91e3f
Update redis-statefulset.yaml
Create FDQN  for Redis dynamicly
2020-11-06 17:32:32 +01:00
Michael
f8ac773d6a
Merge pull request #1 from marcel-dempers/master
update repo
2020-11-06 17:31:32 +01:00
Marcel Dempers
7483d9b678
fix up docs 2020-11-04 10:06:06 +00:00
marcel-dempers
a95b9c8c2c doc updates 2020-10-31 14:51:00 +11:00
marcel-dempers
5f5c337a81 istio readme and cleanups 2020-10-31 14:51:00 +11:00
marcel-dempers
fce0fb89b2 test traffic split and auto retry 2020-10-31 14:51:00 +11:00
marcel-dempers
17ad5d11a7 remove port names for TCP issue 2020-10-31 14:51:00 +11:00
marcel-dempers
e641758cf0 v2 videos-web 2020-10-31 14:51:00 +11:00
marcel-dempers
28b9def878 istio wip 2020-10-31 14:51:00 +11:00
C.Lee Taylor
cc5d627723 Update vault readme.md, fix some typos
Two spelling mistakes.
Formatting.
Better linking to text file.
Fix last link.
2020-10-27 07:24:39 +11:00
marcel-dempers
4458691860 docs updates 2020-10-24 14:38:06 +11:00
marcel-dempers
28a126dcf9 docs update 2020-10-24 12:57:41 +11:00
marcel-dempers
60c5f6062c notes 2020-10-21 21:26:37 +11:00
marcel-dempers
81b46c0157 add editor to edit VPA controllers 2020-10-21 21:26:37 +11:00
marcel-dempers
52910fd190 wip 2020-10-21 21:26:37 +11:00
marcel-dempers
02cdb52eb8 set env vars 2020-10-19 22:33:46 +11:00
marcel-dempers
0c8be9ddbd wip 2020-10-19 22:33:46 +11:00
marcel-dempers
08fa3baaae update links add toolbox 2020-10-11 14:28:23 +11:00
marcel-dempers
d157df6ee6 ux improvements 2020-10-11 14:14:55 +11:00
marcel-dempers
e1a551112d doc updates 2020-10-06 18:56:20 +11:00
marcel-dempers
a4a663fb96 add init containers to add dummy data 2020-10-06 18:56:20 +11:00
marcel-dempers
507ca6d65f update linkerd 2020-10-06 18:56:20 +11:00
marcel-dempers
ce513bd875 wip 2020-10-06 18:56:20 +11:00
marcel-dempers
6508a2ad22 docs wip 2020-10-06 18:56:20 +11:00
marcel-dempers
19289fd9cf docs wip 2020-10-06 18:56:20 +11:00
marcel-dempers
d51d72f3d2 linkerd manifest 2020-10-06 18:56:20 +11:00
marcel-dempers
6012dbaaf8 dynamic url for localhost + ingress functionality 2020-10-06 18:56:20 +11:00
marcel-dempers
0ad5d30834 imagepull + add ingress 2020-10-06 18:56:20 +11:00
marcel-dempers
25dd067b44 error handling for init dummydata 2020-10-06 18:56:20 +11:00
marcel-dempers
c78c6a84da add ingress controller 2020-10-06 18:56:20 +11:00
marcel-dempers
eaa40af16e cache go mod 2020-10-06 18:56:20 +11:00
marcel-dempers
0a6f7ebad0 configs 2020-09-27 15:29:14 +10:00
marcel-dempers
b0a6b7af40 wip 2020-09-27 15:29:14 +10:00
marcel-dempers
474770827c elastic 2020-09-27 15:29:14 +10:00
marcel-dempers
5cd2b71a85 fluentd intro 2020-09-27 15:29:14 +10:00
marcel-dempers
b43943a058 fluentd intro wip 2020-09-27 15:29:14 +10:00
marcel-dempers
83934aa47f letsencrypt basics 2020-09-25 19:08:30 +10:00
marcel-dempers
ce7d6fb980 ignore output letsencrypt certs 2020-09-25 19:08:30 +10:00
marcel-dempers
8bc1f100f3 wip 2020-09-25 19:08:30 +10:00
marcel-dempers
23cbd8cf83 wip 2020-09-25 19:08:30 +10:00
marcel-dempers
6d1cefacfd deploy examples to k8s 2020-09-25 19:07:02 +10:00
marcel-dempers
7eb88e36b2 wip 2020-09-25 19:07:02 +10:00
marcel-dempers
d59a07521a logging wip 2020-09-22 03:15:01 +10:00
marcel-dempers
67c54641ea logging-wip 2020-09-22 03:15:01 +10:00
marcel-dempers
ad51319efb add stale 2020-09-14 07:19:11 +10:00
Marcel Dempers
4093b374a7
Merge pull request #35 from marcel-dempers/terraform-aws-eks
terraform-aws-eks
2020-09-13 20:52:44 +00:00
Marcel Dempers
bde29bc670
Merge pull request #32 from marcel-dempers/redis-kubernetes
redis on kubernetes
2020-09-09 10:50:41 +00:00
marcel-dempers
44fcb20b50 Merge branch 'master' into terraform-aws-eks 2020-09-03 08:13:24 +10:00
marcel-dempers
cc2eb8680f refactor - move prometheus to monitoring folder , introduce logging folder 2020-09-01 07:24:58 +10:00
marcel-dempers
85f23c51ab minor updates 2020-08-30 17:07:07 +10:00
marcel-dempers
fdb7cbc1b5 remove step from readme 2020-08-28 09:46:16 +10:00
marcel-dempers
9e886a82c3 update to new terraform version + k8s 1.17 2020-08-27 19:37:16 +10:00
marcel-dempers
01ac5a8659 Merge branch 'master' into terraform-aws-eks 2020-08-27 14:28:54 +10:00
marcel-dempers
d0c430bd82 remove insecure tls option for kind 2020-08-27 14:27:58 +10:00
marcel-dempers
2798c4bb3f hpa + ca into one guide 2020-08-25 21:41:56 +10:00
Marcel Dempers
641b16ab12
Merge pull request #33 from marcel-dempers/k8s-autoscaling
autoscaling
2020-08-24 20:40:16 +00:00
marcel-dempers
74ea9524dd autoscaling-wip 2020-08-21 10:40:42 +10:00
marcel-dempers
a3c8003ec3 redis on kubernetes 2020-08-13 11:21:07 +10:00
marcel-dempers
ffcfb28c4a disable github action 2020-08-09 15:09:16 +10:00
Marcel Dempers
d45a1e3e1d
Merge pull request #26 from marcel-dempers/redis-getting-started
Redis getting started
2020-08-09 05:03:30 +00:00
marcel-dempers
af6a960c17 redis clustering 2020-08-09 15:01:15 +10:00
Marcel Dempers
09af3d9d51
Merge pull request #27 from marcel-dempers/deployment-volumes-optional
add optional comment section for mounting volumes
2020-08-06 21:20:32 +00:00
Marcel Dempers
59d07f9544
Merge pull request #28 from gaurav04/patch-1
update the durable property while declaring queue in consumer.go
2020-08-06 09:40:41 +00:00
gaurav04
903cb6ec38
update the durable property while declaring queue in consumer.go
FATA[0000] Failed to declare a queue: Exception (406) Reason: "PRECONDITION_FAILED - inequivalent arg 'durable' for queue 'publisher' in vhost '/': received 'false' but current is 'true'"
For publisher and consumer, it should be same.
2020-08-06 15:07:36 +05:30
marcel-dempers
25daf0ff5a add optional comment section for mounting volumes 2020-08-05 19:26:41 +10:00
Marcel Dempers
8e03dd55c2
Merge pull request #24 from marcel-dempers/rabbitmq-docker
Rabbitmq Docker + Clustering + Kubernetes
2020-08-05 08:07:02 +00:00
marcel-dempers
4b8f92df85 wip 2020-08-05 18:00:53 +10:00
marcel-dempers
2b14f61e87 redis wip 2020-08-03 22:07:53 +10:00
marcel-dempers
89c82195fc work in progress 2020-08-01 11:43:00 +10:00
marcel-dempers
744f2e42cb redis add files 2020-07-31 23:08:07 +10:00
marcel-dempers
e8c05bbe4e rabbitmq on k8s 2020-07-31 15:04:07 +10:00
Marcel Dempers
22df30dc9a
Merge pull request #23 from marcel-dempers/k8s-1.18.4-monitoring-update
add manifests for 1.15 to 1.17
2020-07-25 21:52:07 +00:00
marcel-dempers
80ee1c1c33 add manifests for 1.15 to 1.17 2020-07-26 07:51:31 +10:00
marcel-dempers
ac1743d0d4 add readme 2020-07-26 06:58:32 +10:00
marcel-dempers
f62a79be33 publish+consumer 2020-07-24 15:59:33 +10:00
marcel-dempers
b798a4f702 updates 2020-07-22 22:53:06 +10:00
marcel-dempers
0c8a7c68cb a messy eks start 2020-07-21 18:07:46 +10:00
Marcel Dempers
9f53661cfc
Merge pull request #22 from marcel-dempers/terraform-azure-aks
Terraform azure aks
2020-07-19 10:04:55 +00:00
Marcel Dempers
0e9e83ed7e
Merge pull request #16 from marcel-dempers/jenkins-aws
jenkins-on-aws-eks
2020-07-17 04:36:47 +00:00
Marcel Dempers
52be982157
Merge pull request #18 from marcel-dempers/k8s-1.18.4-monitoring-update
prometheus+kubernetes-1.18-updates
2020-07-17 04:36:31 +00:00
marcel-dempers
837f69f019 updates 2020-07-17 13:00:33 +10:00
marcel-dempers
877810d147 fix docs 2020-07-15 10:45:39 +10:00
marcel-dempers
56e7eb473f kubernetes on azure with terraform 2020-07-14 20:52:24 +10:00
marcel-dempers
7d9aa53bbd doco updates 2020-07-11 22:11:21 +10:00
marcel-dempers
eb3e655bb3 kind updates 2020-07-11 21:30:21 +10:00
marcel-dempers
c0bb603bb9 updates and readme 2020-07-10 23:51:59 +00:00
marcel-dempers
dabbc618ef add node-exporter dash configmap 2020-07-11 07:53:35 +10:00
Marcel Dempers
539918c3ea
Merge pull request #17 from marcel-dempers/persisted-volumes
persistent-volumes
2020-07-10 09:03:25 +00:00
marcel-dempers
de227f02cc prometheus+kubernetes-1.18-updates 2020-07-10 19:02:08 +10:00
Marcel Dempers
befe92eb39
Merge pull request #15 from marcel-dempers/kustomize
Kustomize
2020-07-08 12:31:29 +00:00
Marcel Dempers
e97d63db55
Merge pull request #14 from marcel-dempers/flux-test
Flux
2020-07-08 12:30:40 +00:00
marcel-dempers
5c64dd7c9a updates 2020-07-08 12:19:27 +10:00
marcel-dempers
4b9dd849cd add files 2020-07-07 19:24:55 +10:00
marcel-dempers
52f655f881 basics 2020-07-05 10:40:00 +10:00
marcel-dempers
a7f169b884 flux update 2020-07-02 08:36:17 +10:00
marcel-dempers
91ea892b36 updates 2020-07-02 08:36:17 +10:00
marcel-dempers
97535fc3d7 patch headless service 2020-07-02 08:36:17 +10:00
marcel-dempers
9230a00222 add check for storage class host path 2020-07-02 08:36:17 +10:00
marcel-dempers
7128b76adf add notes 2020-07-02 08:36:17 +10:00
marcel-dempers
61d29d8ac1 add files 2020-07-02 08:36:17 +10:00
marcel-dempers
8fd9595943 Auto-release aimvector/python:1.0.4 2020-07-01 03:19:13 +00:00
marcel-dempers
c5fc304df9 Auto-release aimvector/python:1.0.3 2020-06-30 03:19:07 +00:00
marcel-dempers
198273d14a Auto-release aimvector/python:1.0.2 2020-06-30 03:17:23 +00:00
Marcel Dempers
978f3dea56
update 2020-06-30 13:17:03 +10:00
marcel-dempers
3ddba6bf8f Updated policies: default:deployment/example-deploy 2020-06-30 03:14:32 +00:00
marcel-dempers
bc355559de Auto-release aimvector/python:1.0.0 2020-06-30 02:12:10 +00:00
marcel-dempers
2d3577d1fd Updated policies: default:deployment/example-deploy 2020-06-30 02:07:24 +00:00
marcel-dempers
94e0e8a8a5 Auto-release aimvector/python:1.0.1 2020-06-30 01:04:58 +00:00
marcel-dempers
6ca7e2ffb2 Updated workload policies
- Updated policies: default:deployment/example-deploy
- Automated: default:deployment/example-deploy
2020-06-30 01:04:51 +00:00
marcel-dempers
8969aea0ba Updated workload policies
- Automated: default:deployment/example-deploy
- Updated policies: default:deployment/example-deploy
2020-06-30 01:02:35 +00:00
marcel-dempers
1c9e8d26a0 Updated workload policies
- Updated policies: default:deployment/example-deploy
- Automated: default:deployment/example-deploy
2020-06-30 00:58:32 +00:00
marcel-dempers
c03a1b608d Updated policies: default:deployment/example-deploy 2020-06-30 00:52:07 +00:00
marcel-dempers
0aca4d7f5d test deploy 2020-06-30 10:50:31 +10:00
marcel-dempers
6a66fa75f7 test deploy manifest 2020-06-30 10:43:36 +10:00
marcel-dempers
123be244e6 test 2020-06-30 10:27:36 +10:00
marcel-dempers
45cd191f3c patch headless service 2020-06-29 18:38:39 +10:00
marcel-dempers
209e3dc041 readme 2020-06-29 18:36:52 +10:00
Marcel Dempers
a8bad89fc0
Merge pull request #13 from marcel-dempers/statefulset
Statefulset
2020-06-29 08:36:06 +00:00
Marcel Dempers
fda8b41724
Merge pull request #12 from schmiddim/master
example-ns was missing
2020-06-28 00:25:37 +00:00
Michael Schmitt
8020ca3dcd namespace declaration was missing - argo version v1.5.4+36bade7 2020-06-27 19:23:20 +02:00
Michael Schmitt
97652a6f14 namespace declaration was missing - argo version v1.5.4+36bade7 2020-06-27 19:07:12 +02:00
marcel-dempers
7c4a86d7bb add pv files 2020-06-25 18:12:37 +10:00
marcel-dempers
3889efcd86 add check for storage class host path 2020-06-19 15:33:13 +10:00
Marcel Dempers
bcf8e55856
Merge pull request #11 from marcel-dempers/cloud-series
kubernetes-in-the-cloud
2020-06-16 10:26:13 +00:00
marcel-dempers
f67f5e919a add notes 2020-06-14 13:48:27 +10:00
marcel-dempers
02db1d7098 add files 2020-06-12 22:34:55 +10:00
marcel-dempers
b2aae260a3 add files 2020-06-12 17:34:30 +10:00
Marcel Dempers
09223e2dcb
Merge pull request #10 from marcel-dempers/deno-docker
deno-overview-video
2020-05-21 08:23:16 +00:00
marcel-dempers
dbacbffe7b deno code 2020-05-21 18:05:37 +10:00
Marcel Dempers
bc96847851
Merge pull request #9 from marcel-dempers/drone-ci
drone-ci-video
2020-05-20 13:08:41 +00:00
marcel-dempers
4a71879521 disable actions 2020-05-16 12:23:05 +10:00
marcel-dempers
151375082e drone files 2020-05-16 12:22:43 +10:00
marcel-dempers
b811a5723a test a change 2020-05-16 12:02:40 +10:00
marcel-dempers
7a756c20a9 drone stuff 2020-05-13 18:51:10 +10:00
marcel-dempers
96827d3543 disable github action trigger 2020-05-13 18:41:12 +10:00
marcel-dempers
4027722182 convert to statefulset 2020-05-13 18:33:07 +10:00
marcel-dempers
9d008aa662 consume secrets for docker registry 2020-05-13 18:05:06 +10:00
marcel-dempers
d11a11754f try a go build 2020-05-13 17:59:30 +10:00
marcel-dempers
cc780b2df3 test pipeline 2020-05-13 17:35:17 +10:00
marcel-dempers
4ae1661ece test postgres server 2020-05-13 17:27:37 +10:00
marcel-dempers
9cbd210704 test drone.yml 2020-05-13 11:46:17 +10:00
Marcel Dempers
f0c8be9554
Merge pull request #7 from marcel-dempers/github-self-hosted
add runner and manifests
2020-05-12 05:29:08 +00:00
marcel-dempers
c5214cffed add runner and manifests 2020-05-12 15:27:08 +10:00
Marcel Dempers
6cd1038893
Merge pull request #6 from marcel-dempers/java-springboot
java-spring-video
2020-05-07 05:15:22 +00:00
marcel-dempers
63f9945d2a files for java examples 2020-05-07 15:14:26 +10:00
Marcel Dempers
a8a7c120c1
Merge pull request #5 from marcel-dempers/nginx-ingress
nginx ingress examples and files
2020-04-28 22:07:14 +00:00
marcel-dempers
86a146a02c paths and cluster ip 2020-04-29 08:06:27 +10:00
marcel-dempers
33e7e8dfd2 nginx-ingress files 2020-04-24 18:09:20 +10:00
Marcel Dempers
876232d53c
Merge pull request #4 from marcel-dempers/node-js-k8s
Node js k8s videos
2020-04-23 23:18:17 +00:00
marcel-dempers
ac3aed8fb9 docker nodejs debugging 2020-04-24 09:16:53 +10:00
marcel-dempers
a6ea3373aa add production stage 2020-03-29 22:49:13 +11:00
marcel-dempers
772ef7e985 add nodejs debugger 2020-03-29 22:36:26 +11:00
marcel-dempers
26b1cc8d2d add files 2020-03-29 15:19:40 +11:00
Marcel Dempers
eeeb23d625
Merge pull request #3 from marcel-dempers/hashicorpvault
Hashicorpvault
2020-03-13 00:23:46 +00:00
marcel-dempers
b7f939855d add pgadmin interface 2020-03-06 20:29:21 +11:00
marcel-dempers
b279955aff pgadmin 2020-03-06 09:54:33 +11:00
marcel-dempers
c12a0f1443 dynamic secret injection 2020-03-04 15:38:24 +11:00
marcel-dempers
e711ed29fa dynamic secrets and docos 2020-03-04 08:52:23 +11:00
marcel-dempers
2415cb33b2 example basic secret injection 2020-03-02 22:00:58 +00:00
marcel-dempers
428fc51e76 updates 2020-03-01 18:23:22 +11:00
marcel-dempers
f2c3647b7d WIP - injector examples 2020-02-29 22:21:08 +11:00
marcel-dempers
aebfab763c updates to pvc and steps list 2020-02-28 21:37:02 +11:00
marcel-dempers
8d893d63d8 example TLS enable 2020-02-26 16:56:09 +11:00
marcel-dempers
e454f2783b basic injector 2020-02-23 23:14:17 +00:00
marcel-dempers
1f6ccdc4bb remove notes txt 2020-02-24 08:26:56 +11:00
marcel-dempers
151b9817fd base template from helm chart 2020-02-24 08:25:57 +11:00
marcel-dempers
d11a812ec6 remove storage class- not needed 2020-02-23 17:12:25 +11:00
marcel-dempers
93ff675562 get a vault server up 2020-02-20 16:03:28 +11:00
Marcel Dempers
63c6d0910d
docker push step 2020-02-15 11:27:04 +11:00
Marcel Dempers
18f8d8f586
map secrets for docker login 2020-02-15 11:25:15 +11:00
Marcel Dempers
513c7736e1
fix pipeline 2020-02-15 11:14:14 +11:00
Marcel Dempers
9a4c55a38a
fix build 2020-02-15 11:11:45 +11:00
Marcel Dempers
4f3b493bf4
new github action 2020-02-15 11:06:48 +11:00
marcel-dempers
b72228ed94
alert manager rule 2020-02-07 09:17:57 +11:00
marcel-dempers
c5e73e22d4 add alert manager to a prom instance 2020-02-05 08:13:52 +11:00
marcel-dempers
6ebb169ee2 grafana updates 2020-02-04 20:44:16 +11:00
marcel-dempers
33907264a2 add alertmanager 2020-02-04 14:44:40 +11:00
marcel-dempers
03fc7912b8 rule sync with upstream kube-prometheus repo 2020-02-04 14:42:59 +11:00
Marcel Dempers
e26582502a
Update readme.md 2020-02-04 03:39:34 +00:00
Marcel Dempers
c237f66ca1
Update readme.md 2020-02-04 03:35:09 +00:00
marcel-dempers
7a3d3b7858 cluster monitoring components 2020-02-02 20:28:41 +11:00
marcel-dempers
37c562c2c1 links update 2020-01-24 21:04:16 +11:00
marcel-dempers
41e5e3332c prometheus node-exporter updates 2020-01-24 20:56:53 +11:00
marcel-dempers
6c0f87f911 link to the guide 2019-12-25 21:15:16 +11:00
marcel-dempers
850595939c basic readme 2019-12-25 21:13:32 +11:00
marcel-dempers
149db75516 prometheus operator video files 2019-12-24 11:16:52 +11:00
marcel-dempers
50117a6a2b infra for prometheus cluster monitoring 2019-12-08 22:02:19 +11:00
marcel-dempers
6eda362268 increase jenkins pv storage size 2019-11-21 15:38:41 +11:00
marcel-dempers
256912c484 jenkins 2019-11-21 13:36:03 +11:00
marcel-dempers
b67c5d4297 version bump 2019-11-02 17:46:32 +11:00
marcel-dempers
ada19a5590 version bump 2019-11-02 17:36:37 +11:00
marcel-dempers
18113996d3 version bump 2019-11-02 14:17:05 +11:00
marcel-dempers
4548b01086 version update 2019-11-02 14:11:37 +11:00
marcel-dempers
7f0e7435d1 remove live probe since its not needed 2019-11-02 13:34:57 +11:00
marcel-dempers
1c41fe3e40 bump up version 2019-11-02 13:32:15 +11:00
marcel-dempers
6a43fbe890 introduction to argo with examples 2019-11-02 12:56:08 +11:00
marcel-dempers
bfebd40a76 updates and ingress controllers 2019-10-26 09:21:01 +11:00
Marcel Dempers
969c35524e
Update README.md 2019-09-30 20:43:20 +10:00
marcel-dempers
e19376f909 python debugging examples 2019-09-30 20:39:46 +10:00
marcel-dempers
e66d185444 updates to deploy and secret yaml 2019-09-15 13:09:45 +10:00
marcel-dempers
1dd2779121 secret management 2019-09-13 06:06:07 +00:00
marcel-dempers
96ff1cb1f8 updates to add config to deployments 2019-09-12 03:47:31 +00:00
marcel-dempers
20011946e7 updates to kubernetes deployments 2019-09-10 21:42:26 +10:00
marcel-dempers
a8664272e9 k8s 2019-09-08 19:45:51 +10:00
marcel-dempers
04b9870255 cleanup 2019-09-06 08:43:28 +10:00
marcel-dempers
33752dd072 cleanup go prom code 2019-08-28 06:44:18 +00:00
marcel-dempers
32877a10f7 container to import grafana dashboards 2019-08-27 19:37:34 +10:00
marcel-dempers
aca91ac997 updates to go and dotnet metrics integrations 2019-08-27 19:37:09 +10:00
marcel-dempers
17394dde98 add prometheus integration for node and netcore 2019-08-26 22:43:46 +10:00
marcel-dempers
8bb97ec9e7 add code for prometheus monitoring guide 2019-08-26 15:31:45 +10:00
Marcel Dempers
a906ff68b7 prometheus examples 2019-08-25 19:46:44 +10:00
marcel-dempers
a0d7e2ad36 switch cmd to entrypoint 2019-08-13 22:45:10 +00:00
Marcel Dempers
c42c5f9c27
Update README.md 2019-08-04 21:18:28 +10:00
Marcel Dempers
a7e24785c7
Update README.md 2019-08-04 21:16:23 +10:00
Marcel Dempers
fef3ee8630
Update README.md 2019-08-04 21:15:13 +10:00
Marcel Dempers
017d05aa17
Update README.md 2019-08-04 21:14:55 +10:00
Marcel Dempers
ed398d3742 part 5 - dotnet 2019-08-04 21:12:53 +10:00
Marcel Dempers
0e2ad9f05d debugging go part 4 2019-07-18 21:12:53 +10:00
Marcel Dempers
cba88d61db debugging in go 2019-07-18 21:11:55 +10:00
Marcel Dempers
914b6f4ab9 part 3 details 2019-06-30 19:34:25 +10:00
Marcel Dempers
0147ab746f part 3 code 2019-06-30 19:33:50 +10:00
Marcel Dempers
f06b5886e7
Update README.md 2019-06-20 22:28:33 +10:00
Marcel Dempers
f38c38ec6b
Update README.md 2019-06-20 22:28:00 +10:00
Marcel Dempers
8da3b2ed32 part 2 2019-06-20 22:25:55 +10:00
Marcel Dempers
bbe4bd13a4
Update README.md 2019-06-16 20:45:15 +10:00
Marcel Dempers
79c6748acd
Update README.md 2019-06-16 20:44:57 +10:00
825 changed files with 307839 additions and 27 deletions

View File

@ -0,0 +1,42 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/javascript-node
{
"name": "kubernetes-tutorial-basic",
"build": {
"dockerfile": "dockerfile",
"args": { "KIND_VERSION": "0.14.0" }
},
"mounts": ["type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock"],
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/sh"
},
// Add the IDs of extensions you want installed when the container is created.
// "extensions": [
// "dbaeumer.vscode-eslint"
// ],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "root"
}
//Notes:
// Set site url for wordpress
// mysql -u exampleuser -p exampledb
// UPDATE wp_options
// SET option_value = 'https://docker-development-youtube-series-4rjv9rg7hqrg9-80.githubpreview.dev'
// WHERE option_name = 'home';
// UPDATE wp_options
// SET option_value = 'https://docker-development-youtube-series-4rjv9rg7hqrg9-80.githubpreview.dev'
// WHERE option_name = 'siteurl';

12
.devcontainer/dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM alpine:latest
ARG KIND_VERSION=0.14.0
RUN apk add --no-cache curl docker-cli
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
RUN chmod +x ./kubectl
RUN mv ./kubectl /usr/local/bin/kubectl
RUN curl -L https://github.com/kubernetes-sigs/kind/releases/download/v${KIND_VERSION}/kind-linux-amd64 -o /usr/local/bin/kind && \
chmod +x /usr/local/bin/kind

37
.github/workflows/docker._yaml vendored Normal file
View File

@ -0,0 +1,37 @@
###########################################################
# Rename the file extension to ".yaml" (remove "_") to enable
###########################################################
name: Docker Series Builds
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: docker login
env:
DOCKER_USER: ${{ secrets.DOCKER_USER }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
- name: docker build csharp
run: |
docker build ./c# -t aimvector/csharp:1.0.0
- name: docker build nodejs
run: |
docker build ./nodejs -t aimvector/nodejs:1.0.0
- name: docker build python
run: |
docker build ./python -t aimvector/python:1.0.0
- name: docker build golang
run: |
docker build ./golang -t aimvector/golang:1.0.0
- name: docker push
run: |
docker push aimvector/csharp:1.0.0
docker push aimvector/nodejs:1.0.0
docker push aimvector/golang:1.0.0
docker push aimvector/python:1.0.0

View File

@ -0,0 +1,20 @@
###########################################################
# IMPORTANT -> Rename the file extension to ".yaml" (remove "_") to enable this
###########################################################
name: Self-Hosted Runner Test
on:
push:
branches:
- <branch-name>
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v2
- name: docker build python
run: |
docker build ./python/introduction/ -t python:1.0.0

21
.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
c#/src/bin/
c#/src/obj/
node_modules/
__pycache__/
*.pem
*.csr
.terraform
*.tfstate
*.tfstate.*
security/letsencrypt/introduction/certs/**
kubernetes/shipa/installs/shipa-helm-chart-1.1.1/
messaging/kafka/data/*
kubernetes/portainer/volume*
kubernetes/rancher/volume/*
kubernetes/portainer/business/volume*
#ignore postgres data for sample and database tutorials
pgdata
#ignore sample data mount points
.data

58
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,58 @@
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Docker Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickRemoteProcess}",
"pipeTransport": {
"pipeProgram": "docker",
"pipeArgs": [ "exec", "-i", "csharp" ],
"debuggerPath": "/root/vsdbg/vsdbg",
"pipeCwd": "${workspaceRoot}",
"quoteArgs": false
},
"sourceFileMap": {
"/work": "${workspaceRoot}/c#/src/"
}
},
{
"name": "Remote Docker",
"type": "go",
"request": "launch",
"mode": "remote",
"remotePath":"/go/src/work/",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceFolder}/golang/src/",
"args": [],
"trace" : "verbose",
"env" : {}
},
{
"name": "Python Attach",
"type": "python",
"request": "attach",
"pathMappings": [
{
"localRoot": "${workspaceFolder}/python/src/",
"remoteRoot": "/work"
}
],
"port": 5678,
"host": "127.0.0.1"
},
{
"name": "Docker: Attach to Node",
"type": "node",
"request": "attach",
"remoteRoot": "/work/src/",
"port": 9229,
"address": "localhost",
"localRoot": "${workspaceFolder}/nodejs/src/",
"protocol": "inspector",
"restart": true
}
]
}

View File

@ -1,9 +1,37 @@
# docker-development-youtube-series
# The Ultimate Engineer Toolbox <img src="https://www.shareicon.net/data/128x128/2017/04/11/883708_media_512x512.png" alt="YouTube" width="5%" height="5%"> :hammer::wrench:
Hi!
A Collection of tools, hands-on walkthroughs with source code. <br/>
The Ultimate Swiss Army knife for DevOps, Developers and Platform Engineers
This is the source code for the YouTube series covering docker-based development workflows.
<br/>
Part #1 https://youtu.be/wyjNpxLRmLg
More details coming soon!
| Steps | Playlist :tv: | Source :octocat: |
|---|---|---|
| [Learn Kubernetes](./kubernetes/README.md) :snowflake: | <a href="https://www.youtube.com/playlist?list=PLHq1uqvAteVvUEdqaBeMK2awVThNujwMd" title="Kubernetes"><img src="https://i.ytimg.com/vi/8h4FoWK7tIA/hqdefault.jpg" width="50%" alt="Kubernetes Guide" /></a> | [source](./kubernetes/readme.md) |
| Learn about CI/CD tools :whale: | <a href="https://www.youtube.com/playlist?list=PLHq1uqvAteVsSsrnZimHEf7NJ1MlRhQUj" title="CI/CD"><img src="https://i.ytimg.com/vi/myCcJJ_Fk10/hqdefault.jpg" width="50%" alt="CI/CD Guide" /></a> | | | |
| Deploy Kubernetes to the cloud :partly_sunny: | <a href="https://www.youtube.com/playlist?list=PLHq1uqvAteVsUhzNBkn-rPzXtPNpJu1-k" title="Cloud K8s"><img src="https://i.ytimg.com/vi/3jA9EfkSAUU/hqdefault.jpg" width="50%" alt="Cloud Guide" /></a> | [source](./kubernetes/cloud/readme.md) |
| Monitoring Kubernetes :mag: | <a href="https://www.youtube.com/playlist?list=PLHq1uqvAteVuEXCrRkPFWLXRKWNLOVUHn" title="Cloud K8s"><img src="https://i.ytimg.com/vi/5o37CGlNLr8/hqdefault.jpg" width="50%" alt="Cloud Guide" /></a> | [source](./monitoring/prometheus/kubernetes/readme.md) |
| Guide to Logging :page_with_curl: | <a href="https://www.youtube.com/playlist?list=PLHq1uqvAteVvfDxFW50Mdezk0xum-tyHT" title="Cloud K8s"><img src="https://i.ytimg.com/vi/MMVdkzeQ848/hqdefault.jpg" width="50%" alt="Cloud Guide" /></a> | [source](./monitoring/logging/readme.md) |
| Guide to ServiceMesh :globe_with_meridians: | <a href="https://www.youtube.com/playlist?list=PLHq1uqvAteVsmxHpGsMjTOROn3i99lzTA" title="Cloud K8s"><img src="https://i.ytimg.com/vi/rVNPnHeGYBE/hqdefault.jpg" width="50%" alt="Cloud Guide" /></a> | [source](./kubernetes/servicemesh/readme.md) |
## Docker Development Basics
| Step :heavy_check_mark: | Video :movie_camera: | Source Code :octocat: |
|---|---|---|
| Working with `Dockerfiles` <br/>(.NET, Golang, Python, NodeJS) | <a href="https://youtu.be/wyjNpxLRmLg" title="Docker 1"><img src="https://i.ytimg.com/vi/wyjNpxLRmLg/hqdefault.jpg" width="50%" alt="Docker 1" /></a> | [source](https://github.com/marcel-dempers/docker-development-youtube-series/tree/part1) |
| Working with code <br/>(.NET, Golang, Python, NodeJS) | <a href="https://youtu.be/EdmKENqnQUw" title="Docker 1"><img src="https://i.ytimg.com/vi/EdmKENqnQUw/hqdefault.jpg" width="50%" alt="Docker 1" /></a> | [source](https://github.com/marcel-dempers/docker-development-youtube-series/tree/part2) |
| Docker Multistage explained | <a href="https://youtu.be/2lQ7WrwpZfI" title="Docker 1"><img src="https://i.ytimg.com/vi/2lQ7WrwpZfI/hqdefault.jpg" width="50%" alt="Docker 1" /></a> | [source](https://github.com/marcel-dempers/docker-development-youtube-series/tree/part3) |
| Debugging Go in Docker | <a href="https://youtu.be/kToyI16IFxs" title="Docker 1"><img src="https://i.ytimg.com/vi/kToyI16IFxs/hqdefault.jpg" width="50%" alt="Docker 1" /></a> | [source](https://github.com/marcel-dempers/docker-development-youtube-series/tree/master/golang) |
| Debugging .NET in Docker | <a href="https://youtu.be/ds2bud0ZYTY" title="Docker 1"><img src="https://i.ytimg.com/vi/ds2bud0ZYTY/hqdefault.jpg" width="50%" alt="Docker 1" /></a> | [source](https://github.com/marcel-dempers/docker-development-youtube-series/tree/part5) |
| Debugging Python in Docker | <a href="https://youtu.be/b78Tg-YmJZI" title="Docker 1"><img src="https://i.ytimg.com/vi/b78Tg-YmJZI/hqdefault.jpg" width="50%" alt="Docker 1" /></a> | [source](https://github.com/marcel-dempers/docker-development-youtube-series/tree/debugging-python) |
| Debugging NodeJS in Docker | <a href="https://youtu.be/ktvgr9VZ4dc" title="Docker 1"><img src="https://i.ytimg.com/vi/ktvgr9VZ4dc/hqdefault.jpg" width="50%" alt="Docker 1" /></a> | [source](https://github.com/marcel-dempers/docker-development-youtube-series/tree/master/nodejs) |
## Engineering Toolbox :hammer::wrench:
Checkout the toolbox [website](https://marceldempers.dev/toolbox)
<a href="https://marceldempers.dev/toolbox" title="toolbox 1"><img src="./toolbox.png" alt="toolbox 1" /></a>

View File

@ -0,0 +1,151 @@
# Introduction to Open AI
## Overview
What is [Open AI](https://openai.com/) ?
* Research company on AI development
* Builds and provides models
* Builds and provides a standard protocol for using AI
What is a model ?
I see a model as a language super database. </br>
Instead of writing a query, that is slow to query a traditional database like SQL, you can throw a question at a model and it gives you an answer really fast </br>
Model examples:
* GPT 3.5
* GPT 4
## Getting started
The best way to get started and to understand OpenAI, is to learn hands on
* Create an OpenAI account [here](https://openai.com/)
## Chat GPT
Here you can find the link to [ChatGPT](https://chat.openai.com/)
## Open AI Playground
Here you can find the link to the [OpenAI Playground](https://platform.openai.com/playground)
## Build an AI powered app
We can start with a `main.py` that reads a message
```
import sys
message = sys.argv[0]
```
Then we will need the code from the Open AI playground and add it to our `main.py`. </br>
Move the `import` statements to the top </br>
Once you have tidied up everything, you can get the response message from the AI:
```
responseMessage = response.choices[0].message.content
```
Let's build our app
```
cd ai\openai\introduction
docker build . -t ai-app
```
Set my OpenAI API key
```
$ENV:OPENAI_API_KEY=""
```
Run our AI App:
```
docker run -it -e OPENAI_API_KEY=$ENV:OPENAI_API_KEY ai-app
```
When we run the app, notice it has no concept of memory. </br>
The playground works because it keeps track of all the user and AI messages and keeps appending new messages to it </br>
So it can track the conversation.
Let's keep track of messages, by writing it to a local file </br>
We will also take the system message out and keep it as a constant in our code </br>
Full example:
```
import sys
import os
import json
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
#read the incoming message
message = sys.argv[1]
user_message = {
"role" : "user",
"content" : message
}
systemMessage = {
"role": "system",
"content": "You are a kubernetes exper that can assist developers with troubleshooting deployments\n\nTo help the developer you will need to know the namespaces as well as the pod name. Ask for missing information\n\nGenerate a command to help the developer surface logs or information\n"
}
# read the cached user messages if there are any
userMessages = []
if os.path.isfile("messages.json"):
with open('messages.json', newline='') as messagesFile:
data = messagesFile.read()
userMessages = json.loads(data)
# add the new message to it and update the cached messages
userMessages.append(user_message)
with open('messages.json', 'w', newline='') as messagesFile:
msgJSON = json.dumps(userMessages)
messagesFile.write(msgJSON)
print(msgJSON)
messages = []
messages.append(systemMessage)
messages.extend(userMessages)
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
temperature=1,
max_tokens=256,
top_p=1,
frequency_penalty=0,
presence_penalty=0
)
responseMessage = response.choices[0].message.content
print(responseMessage)
```
Now we can mount our volume so we persist the cache of messages
```
docker run -it -e OPENAI_API_KEY=$ENV:OPENAI_API_KEY -v ${PWD}:/app ai-app "can you help me with my deployment?"
Of course! I'd be happy to help with your deployment. Could you please provide me with the namespace and the name of the pod you're encountering issues with?
docker run -it -e OPENAI_API_KEY=$ENV:OPENAI_API_KEY -v ${PWD}:/app ai-app "my pod is pod-123"
Sure, I can help you with your deployment. Can you please provide me with the namespace in which the pod is running?
docker run -it -e OPENAI_API_KEY=$ENV:OPENAI_API_KEY -v ${PWD}:/app ai-app "its in the products namespace"
Great! To surface the logs for the pod "pod-123" in the "products" namespace, you can use the following command:
```shell
kubectl logs -n products pod-123
```
This command will retrieve the logs for the specified pod in the given namespace. Make sure you have the necessary permissions to access the namespace.
```

View File

@ -0,0 +1,11 @@
FROM python:3.11-alpine
RUN mkdir /app
WORKDIR /app
COPY requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
COPY main.py /app/
ENTRYPOINT ["python3", "main.py"]

View File

@ -0,0 +1,49 @@
import sys
import os
import json
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
#read the incoming message
message = sys.argv[1]
user_message = {
"role" : "user",
"content" : message
}
systemMessage = {
"role": "system",
"content": "You are a kubernetes exper that can assist developers with troubleshooting deployments\n\nTo help the developer you will need to know the namespaces as well as the pod name. Ask for missing information\n\nGenerate a command to help the developer surface logs or information\n"
}
# read the cached user messages if there are any
userMessages = []
if os.path.isfile("messages.json"):
with open('messages.json', newline='') as messagesFile:
data = messagesFile.read()
userMessages = json.loads(data)
# add the new message to it and update the cached messages
userMessages.append(user_message)
with open('messages.json', 'w', newline='') as messagesFile:
msgJSON = json.dumps(userMessages)
messagesFile.write(msgJSON)
print(msgJSON)
messages = []
messages.append(systemMessage)
messages.extend(userMessages)
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
temperature=1,
max_tokens=256,
top_p=1,
frequency_penalty=0,
presence_penalty=0
)
responseMessage = response.choices[0].message.content
print(responseMessage)

View File

@ -0,0 +1 @@
openai==0.28.0

4
apache/kafka/README.md Normal file
View File

@ -0,0 +1,4 @@
# Introduction to Kafka
This guide is under the messaging section alongside other message brokers like `RabbitMQ` etc. </br>
Checkout the guide under the [messaging/kafka](../../messaging/kafka/README.md) folder

3
argo/argo-cd/README.md Normal file
View File

@ -0,0 +1,3 @@
# Introduction to Argo CD
<a href="https://youtu.be/2WSJF7d8dUg" title="argo"><img src="https://i.ytimg.com/vi/2WSJF7d8dUg/hqdefault.jpg" width="20%" alt="introduction to argo cd" /></a>

20
argo/argo-cd/app.yaml Normal file
View File

@ -0,0 +1,20 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: example-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/marcel-dempers/docker-development-youtube-series.git
targetRevision: HEAD
path: argo/example-app
directory:
recurse: true
destination:
server: https://kubernetes.default.svc
namespace: example-app
syncPolicy:
automated:
prune: false
selfHeal: false

View File

@ -0,0 +1,28 @@
CLI
```
argocd app create --name test \
--repo https://github.com/marcel-dempers/docker-development-youtube-series \
--dest-server https://kubernetes.default.svc \
--dest-namespace marcel --path kubernetes
```
YAML
```
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: test
namespace: marcel
spec:
project: default
source:
repoURL: https://github.com/marcel-dempers/docker-development-youtube-series.git
targetRevision: HEAD
path: argo/example-app
destination:
server: https://kubernetes.default.svc
namespace: marcel
```

2870
argo/argo-cd/install.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: example-config
data:
config.json: |
{
"environment" : "dev"
}
# kubectl create configmap example-config --from-file ./golang/configs/config.json

View File

@ -0,0 +1,47 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deploy
labels:
app: example-app
annotations:
spec:
selector:
matchLabels:
app: example-app
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: example-app
spec:
containers:
- name: example-app
image: aimvector/python:1.0.0
imagePullPolicy: Always
ports:
- containerPort: 5000
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "500m"
volumeMounts:
- name: secret-volume
mountPath: /secrets/
- name: config-volume
mountPath: /configs/
volumes:
- name: secret-volume
secret:
secretName: mysecret
- name: config-volume
configMap:
name: example-config #name of our configmap object

View File

@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: example-app

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
stringData:
secret.json: |-
{
"api_key" : "somesecretgoeshere"
}
#kubectl create secret generic mysecret --from-file .\golang\secrets\secret.json

View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: example-service
spec:
selector:
app: example-app
ports:
- protocol: TCP
port: 80
targetPort: 5000

View File

@ -1 +1,27 @@
FROM mcr.microsoft.com/dotnet/core/sdk:2.2
FROM mcr.microsoft.com/dotnet/sdk:8.0 as build
#install debugger for NET Core
RUN apt-get update
RUN apt-get install -y unzip
RUN curl -sSL https://aka.ms/getvsdbgsh | /bin/sh /dev/stdin -v latest -l ~/vsdbg
RUN mkdir /src/
WORKDIR /src/
COPY ./src/helloworld.csproj /src/helloworld.csproj
RUN dotnet restore
COPY ./src/ /src/
RUN mkdir /out/
RUN dotnet build helloworld.csproj --configuration Debug --no-restore
RUN dotnet publish helloworld.csproj --output /out --configuration Debug --no-restore
ENTRYPOINT ["dotnet", "run"]
FROM mcr.microsoft.com/dotnet/aspnet:8.0 as runtime
WORKDIR /app
COPY --from=build /out/ /app
ENTRYPOINT ["dotnet", "helloworld.dll"]

26
c#/src/Program.cs Normal file
View File

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Hosting;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.Configure<HostOptions>(builder.Configuration.GetSection("HostOptions"));
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5000);
});
var app = builder.Build();
Console.WriteLine(Environment.ProcessorCount.ToString());
app.UseHttpsRedirection();
app.MapGet("/", async () =>
{
await Task.Delay(40000); // Sleep for 40 seconds
return "Hello World!";
});
app.Run();

View File

@ -0,0 +1,31 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59079",
"sslPort": 44372
}
},
"profiles": {
"helloworld": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7158;http://localhost:5122",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

13
c#/src/helloworld.csproj Normal file
View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>
</Project>

3
deno/README.md Normal file
View File

@ -0,0 +1,3 @@
# Introduction to Deno with Docker
<a href="https://youtu.be/4EfnECkCx8E" title="Kubernetes"><img src="https://i.ytimg.com/vi/4EfnECkCx8E/hqdefault.jpg" width="20%" alt="introduction to deno" /></a>

View File

@ -0,0 +1,13 @@
FROM aimvector/deno:1.0.0-buster-slim as build
COPY ./src/ $DENO_DIR
RUN mkdir /out/
RUN deno bundle /deno-dir/server.js /out/server.js
FROM aimvector/deno:1.0.0-buster-slim as final
COPY --from=build /out/server.js /deno-dir/server.js
ENTRYPOINT ["deno"]
CMD ["run", "--allow-net", "/deno-dir/server.js"]

25
deno/deno.dockerfile Normal file
View File

@ -0,0 +1,25 @@
FROM debian:buster-slim
ENV DENO_VERSION=1.0.0
RUN apt-get -qq update \
&& apt-get -qq install -y --no-install-recommends curl ca-certificates unzip \
&& curl -fsSL https://github.com/denoland/deno/releases/download/v${DENO_VERSION}/deno-x86_64-unknown-linux-gnu.zip \
--output deno.zip \
&& unzip deno.zip \
&& rm deno.zip \
&& chmod 777 deno \
&& mv deno /usr/bin/deno \
&& apt-get -qq remove --purge -y curl ca-certificates unzip \
&& apt-get -y -qq autoremove \
&& apt-get -qq clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN useradd --uid 1993 --user-group deno \
&& mkdir /deno-dir/ \
&& chown deno:deno /deno-dir/
ENV DENO_DIR /deno-dir/
ENTRYPOINT ["deno"]
CMD ["run", "https://deno.land/std/examples/welcome.ts"]

View File

@ -0,0 +1,35 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deploy
labels:
app: example-app
annotations:
spec:
selector:
matchLabels:
app: example-app
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: example-app
spec:
containers:
- name: example-app
image: aimvector/deno-app:v1
imagePullPolicy: Always
ports:
- containerPort: 5000
resources:
requests:
memory: "64Mi"
cpu: "10m"
limits:
memory: "256Mi"
cpu: "500m"

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: example-service
labels:
app: example-app
spec:
type: LoadBalancer
selector:
app: example-app
ports:
- protocol: TCP
name: http
port: 80
targetPort: 5000

6
deno/dockerfile Normal file
View File

@ -0,0 +1,6 @@
FROM aimvector/deno:1.0.0-buster-slim as build
COPY ./src/ $DENO_DIR
ENTRYPOINT ["deno"]
CMD ["run", "--allow-net", "/deno-dir/server.js"]

5
deno/src/server.js Normal file
View File

@ -0,0 +1,5 @@
import { serve } from "https://deno.land/std@0.50.0/http/server.ts";
for await (const req of serve({ port: 5000 })) {
req.respond({ body: "Hello World! - from Deno 1.0.0\n" });
}

View File

@ -1,18 +1,71 @@
version: "3"
services:
csharp:
container_name: csharp
image: aimvector/csharp:1.0.0
build: ./c#
golang:
container_name: golang
image: aimvector/golang:1.0.0
build: ./golang
nodejs:
container_name: nodejs
image: aimvector/nodejs:1.0.0
build: ./nodejs
python:
container_name: python
image: aimvector/python:1.0.0
build: ./python
version: "3.4"
services:
csharp: #docker run --rm -it -v ${PWD}:/work -w /work -p 5000:5000 aimvector/csharp:1.0.0 /bin/sh
container_name: csharp
image: aimvector/csharp:1.0.0
build:
context: ./c#
target: debug
volumes:
- ./c#/src/:/work/
ports:
- 5000:5000
golang: #docker run --rm -it -v ${PWD}:/go/src/work -v ${PWD}/golang/configs/:/configs -v ${PWD}/golang/secrets/:/secrets -p 5001:5000 -p 2345:2345 --security-opt "seccomp:unconfined" aimvector/golang:1.0.0
container_name: golang
image: aimvector/golang:1.0.0
build:
context: ./golang
target: prod
volumes:
- ./golang/configs:/configs/
- ./golang/secrets:/secrets/
- ./golang/src/:/go/src/work/
ports:
- 5001:5000
- 2345:2345
security_opt:
- "seccomp:unconfined"
python: #docker run --rm -it -v ${PWD}:/work -w /work -p 5003:5000 aimvector/python:1.0.0 /bin/sh
container_name: python
image: aimvector/python:1.0.0
build:
context: ./python
target: debug
#working_dir: /work #comment out for build.target:prod
#entrypoint: /bin/sh #comment out for build.target:prod
#stdin_open: true #comment out for build.target:prod
#tty: true #comment out for build.target:prod
volumes:
- ./python/src/:/work
ports:
- 5003:5000
- 5678:5678
nodejs: #docker run --rm -it -v ${PWD}:/work -w /work -p 5002:5000 aimvector/nodejs:1.0.0 /bin/sh
container_name: nodejs
image: aimvector/nodejs:1.0.0
build:
context: ./nodejs
target: debug
#working_dir: /work #comment out for build.target:prod
#entrypoint: /bin/sh #comment out for build.target:prod
#stdin_open: true #comment out for build.target:prod
#tty: true #comment out for build.target:prod
volumes:
- ./nodejs/src/:/work/src/
ports:
- 5002:5000
- 9229:9229 #debug port
spring-java: #docker run --rm -it -v ${PWD}:/work -w /work -p 5002:5000 aimvector/nodejs:1.0.0 /bin/sh
container_name: spring-java
image: aimvector/spring-java:1.0.0
build:
context: ./springboot/java/
target: debug
working_dir: /work/src/ #comment out for build.target:prod
entrypoint: /bin/sh #comment out for build.target:prod
stdin_open: true #comment out for build.target:prod
tty: true #comment out for build.target:prod
volumes:
- ./springboot/java/:/work/src/
ports:
- 9999:8080

3
drone-ci/README.md Normal file
View File

@ -0,0 +1,3 @@
# Introduction to Drone CI
<a href="https://youtu.be/myCcJJ_Fk10" title="drone ci"><img src="https://i.ytimg.com/vi/myCcJJ_Fk10/hqdefault.jpg" width="20%" alt="introduction to drone ci" /></a>

32
drone-ci/drone.yml Normal file
View File

@ -0,0 +1,32 @@
---
kind: pipeline
type: kubernetes
name: default
steps:
- name: build-push
image: docker:dind
volumes:
- name: dockersock
path: /var/run
environment:
DOCKER_USER:
from_secret: DOCKER_USER
DOCKER_PASSWORD:
from_secret: DOCKER_PASSWORD
commands:
- sleep 5 ## give docker enough time to start
- docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
- docker build ./golang -t aimvector/golang:1.0.0
- docker push aimvector/golang:1.0.0
services:
- name: docker
image: docker:dind
privileged: true
volumes:
- name: dockersock
path: /var/run
volumes:
- name: dockersock
temp: {}

View File

@ -0,0 +1,50 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
labels:
app: postgres
data:
POSTGRES_DB: postgresdb
POSTGRES_USER: postgresadmin
POSTGRES_PASSWORD: admin123
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: "postgres"
selector:
matchLabels:
app: postgres
replicas: 1
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:10.4
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 5432
envFrom:
- configMapRef:
name: postgres-config
---
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app: postgres
spec:
selector:
app: postgres
ports:
- protocol: TCP
name: http
port: 5432
targetPort: 5432

View File

@ -0,0 +1,40 @@
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: drone
name: drone-runner
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- delete
- apiGroups:
- ""
resources:
- pods
- pods/log
verbs:
- get
- create
- delete
- list
- watch
- update
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: drone-runner
namespace: drone
subjects:
- kind: ServiceAccount
name: drone-runner
namespace: drone
roleRef:
kind: Role
name: drone-runner
apiGroup: rbac.authorization.k8s.io

View File

@ -0,0 +1,43 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: drone-runner
labels:
app.kubernetes.io/name: drone-runner
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: drone
template:
metadata:
labels:
app.kubernetes.io/name: drone
spec:
serviceAccountName: drone-runner
containers:
- name: runner
image: drone/drone-runner-kube:latest
ports:
- containerPort: 3000
env:
- name: DRONE_NAMESPACE_DEFAULT
value: drone
- name: DRONE_SERVICE_ACCOUNT_DEFAULT
value: drone-runner
- name: DRONE_RPC_HOST
value: droneserver.drone
- name: DRONE_RPC_PROTO
value: http
- name: DRONE_RPC_SECRET
valueFrom:
secretKeyRef:
name: drone-server-secret
key: DRONE_RPC_SECRET
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: drone-runner
labels:
app.kubernetes.io/name: drone-runner

View File

@ -0,0 +1,64 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: drone-server
labels:
app: drone-server
annotations:
spec:
selector:
matchLabels:
app: drone-server
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: drone-server
spec:
containers:
- name: drone-server
image: drone/drone:1.6.5
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
- containerPort: 443
env:
- name: DRONE_USER_CREATE
valueFrom:
secretKeyRef:
name: drone-server-secret
key: DRONE_USER_CREATE
- name: DRONE_DATABASE_DRIVER
value: postgres
- name: DRONE_DATABASE_DATASOURCE
valueFrom:
secretKeyRef:
name: drone-server-secret
key: DRONE_DATABASE_DATASOURCE
- name: DRONE_SERVER_PROTO
value: https
- name: DRONE_SERVER_HOST
valueFrom:
secretKeyRef:
name: drone-server-secret
key: DRONE_SERVER_HOST
- name: DRONE_GITHUB_CLIENT_ID
valueFrom:
secretKeyRef:
name: drone-server-secret
key: DRONE_GITHUB_CLIENT_ID
- name: DRONE_GITHUB_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: drone-server-secret
key: DRONE_GITHUB_CLIENT_SECRET
- name: DRONE_RPC_SECRET
valueFrom:
secretKeyRef:
name: drone-server-secret
key: DRONE_RPC_SECRET

View File

@ -0,0 +1,18 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: drone-server
annotations:
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/frontend-entry-points: http,https
traefik.ingress.kubernetes.io/redirect-entry-point: https
traefik.ingress.kubernetes.io/redirect-permanent: "true"
spec:
rules:
- host: drone.marceldempers.dev
http:
paths:
- backend:
serviceName: droneserver
servicePort: 80
path: /

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
name: drone-server-secret
type: Opaque
data:
DRONE_GITHUB_CLIENT_ID: xxxxxxx #Get this from GitHub OAUTH
DRONE_GITHUB_CLIENT_SECRET: xxxxxxx #Get this from GitHub OAUTH
DRONE_RPC_SECRET: xxxxxxx #openssl rand -hex 16
DRONE_DATABASE_DATASOURCE: xxxxxxx #postgres://postgresadmin:admin123@postgres:5432/postgresdb?sslmode=disable
DRONE_USER_CREATE: xxxxxxx #username:marcel-dempers,admin:true
DRONE_SERVER_HOST: xxxxxxx #drone.marceldempers.dev

View File

@ -0,0 +1,19 @@
apiVersion: v1
kind: Service
metadata:
name: droneserver
labels:
app: drone-server
spec:
type: ClusterIP
selector:
app: drone-server
ports:
- protocol: TCP
name: http
port: 80
targetPort: 80
- protocol: TCP
name: https
port: 443
targetPort: 443

View File

@ -0,0 +1,84 @@
<a href="https://youtu.be/RcHGqCBofvw" title="githubactions"><img src="https://i.ytimg.com/vi/RcHGqCBofvw/hqdefault.jpg" width="20%" alt="introduction to github actions runners" /></a>
# Introduction to GitHub Actions: Self hosted runners
## Create a kubernetes cluster
In this guide we we''ll need a Kubernetes cluster for testing. Let's create one using [kind](https://kind.sigs.k8s.io/) </br>
```
kind create cluster --name githubactions --image kindest/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31
```
Let's test our cluster:
```
kubectl get nodes
NAME STATUS ROLES AGE VERSION
githubactions-control-plane Ready control-plane 2m53s v1.28.0
```
## Running the Runner in Docker
We can simply install this directly on to virtual machines , but for this demo, I'd like to run it in Kubernetes inside a container. </br>
### Security notes
* Running in Docker needs high priviledges.
* Would not recommend to use these on public repositories.
* Would recommend to always run your CI systems in seperate Kubernetes clusters.
### Creating a Dockerfile
* Installing Docker CLI
For this to work we need a `dockerfile` and follow instructions to [Install Docker](https://docs.docker.com/engine/install/debian/).
I would grab the content and create statements for my `dockerfile` </br>
Now notice that we only install the `docker` CLI. </br>
This is because we want our running to be able to run docker commands , but the actual docker server runs elsewhere </br>
This gives you flexibility to tighten security by running docker on the host itself and potentially run the container runtime in a non-root environment </br>
* Installing Github Actions Runner
Next up we will need to install the [GitHub actions runner](https://github.com/actions/runner) in our `dockerfile`
Now to give you a "behind the scenes" of how I usually build my `dockerfile`s, I run a container to test my installs:
```
docker build . -t github-runner:latest
docker run -it github-runner bash
```
Next steps:
* Now we can see `docker` is installed
* To see how a runner is installed, lets go to our repo | runner and click "New self-hosted runner"
* Try these steps in the container
* We will needfew dependencies
* We download the runner
* TODO
Finally lets test the runner in `docker`
```
docker run -it -e GITHUB_PERSONAL_TOKEN="" -e GITHUB_OWNER=marcel-dempers -e GITHUB_REPOSITORY=docker-development-youtube-series github-runner
```
## Deploy to Kubernetes
Load our github runner image so we dont need to push it to a registry:
```
kind load docker-image github-runner:latest --name githubactions
```
Create a kubernetes secret with our github details
```
kubectl create ns github
kubectl -n github create secret generic github-secret `
--from-literal GITHUB_OWNER=marcel-dempers `
--from-literal GITHUB_REPOSITORY=docker-development-youtube-series `
--from-literal GITHUB_PERSONAL_TOKEN=""
kubectl -n github apply -f kubernetes.yaml
```

View File

@ -0,0 +1,46 @@
FROM debian:bookworm-slim
ARG RUNNER_VERSION="2.302.1"
ENV GITHUB_PERSONAL_TOKEN ""
ENV GITHUB_OWNER ""
ENV GITHUB_REPOSITORY ""
# Install Docker -> https://docs.docker.com/engine/install/debian/
# Add Docker's official GPG key:
RUN apt-get update && \
apt-get install -y ca-certificates curl gnupg
RUN install -m 0755 -d /etc/apt/keyrings
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
RUN chmod a+r /etc/apt/keyrings/docker.gpg
# Add the repository to Apt sources:
RUN echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
RUN apt-get update
# I only install the CLI, we will run docker in another container!
RUN apt-get install -y docker-ce-cli
# Install the GitHub Actions Runner
RUN apt-get update && apt-get install -y sudo jq
RUN useradd -m github && \
usermod -aG sudo github && \
echo "%sudo ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER github
WORKDIR /actions-runner
RUN curl -Ls https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz | tar xz \
&& sudo ./bin/installdependencies.sh
COPY --chown=github:github entrypoint.sh /actions-runner/entrypoint.sh
RUN sudo chmod u+x /actions-runner/entrypoint.sh
#working folder for the runner
RUN sudo mkdir /work
ENTRYPOINT ["/actions-runner/entrypoint.sh"]

View File

@ -0,0 +1,26 @@
#!/bin/sh
registration_url="https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/actions/runners/registration-token"
echo "Requesting registration URL at '${registration_url}'"
payload=$(curl -sX POST -H "Authorization: token ${GITHUB_PERSONAL_TOKEN}" ${registration_url})
export RUNNER_TOKEN=$(echo $payload | jq .token --raw-output)
./config.sh \
--name $(hostname) \
--token ${RUNNER_TOKEN} \
-- labels my-runner \
--url https://github.com/${GITHUB_OWNER}/${GITHUB_REPOSITORY} \
--work "/work" \
--unattended \
--replace
remove() {
./config.sh remove --unattended --token "${RUNNER_TOKEN}"
}
trap 'remove; exit 130' INT
trap 'remove; exit 143' TERM
./run.sh "$*" &
wait $!

View File

@ -0,0 +1,64 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: github-runner
labels:
app: github-runner
spec:
replicas: 1
selector:
matchLabels:
app: github-runner
template:
metadata:
labels:
app: github-runner
spec:
containers:
- name: github-runner
imagePullPolicy: Never #use local kind image
image: github-runner:latest
env:
- name: GITHUB_OWNER
valueFrom:
secretKeyRef:
name: github-secret
key: GITHUB_OWNER
- name: GITHUB_REPOSITORY
valueFrom:
secretKeyRef:
name: github-secret
key: GITHUB_REPOSITORY
- name: GITHUB_PERSONAL_TOKEN
valueFrom:
secretKeyRef:
name: github-secret
key: GITHUB_PERSONAL_TOKEN
- name: DOCKER_HOST
value: tcp://localhost:2375
volumeMounts:
- name: data
mountPath: /work/
- name: dind
image: docker:24.0.6-dind
env:
- name: DOCKER_TLS_CERTDIR
value: ""
resources:
requests:
cpu: 20m
memory: 512Mi
securityContext:
privileged: true
volumeMounts:
- name: docker-graph-storage
mountPath: /var/lib/docker
- name: data
mountPath: /work/
volumes:
- name: docker-graph-storage
emptyDir: {}
- name: data
emptyDir: {}

View File

@ -0,0 +1,3 @@
{
"environment" : "dev"
}

3
golang/dlv.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/sh
cd /go/src/work
dlv debug --headless --log -l 0.0.0.0:2345 --api-version=2

View File

@ -1 +1,32 @@
FROM golang:1.12.5-alpine3.9 as builder
FROM golang:1.12.5-alpine3.9 as debug
# installing git
RUN apk update && apk upgrade && \
apk add --no-cache git \
dpkg \
gcc \
git \
musl-dev
ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN go get github.com/sirupsen/logrus
RUN go get github.com/buaazp/fasthttprouter
RUN go get github.com/valyala/fasthttp
RUN go get github.com/go-delve/delve/cmd/dlv
WORKDIR /go/src/work
COPY ./src /go/src/work/
RUN go build -o app
### Run the Delve debugger ###
COPY ./dlv.sh /
RUN chmod +x /dlv.sh
ENTRYPOINT [ "/dlv.sh"]
###########START NEW IMAGE###################
FROM alpine:3.9 as prod
COPY --from=debug /go/src/work/app /
CMD ./app

View File

@ -0,0 +1,36 @@
package main
import (
"fmt"
)
func main() {
customers := GetCustomers()
for _, customer := range customers {
//we can access the "customer" variable in this approach
fmt.Println(customer)
}
}
func getData() (customers []string) {
customers = []string{ "Marcel Dempers", "Bob Smith", "John Smith"}
customers = append(customers, "Ben Spain")
customers = append(customers, "Aleem Janmohamed")
customers = append(customers, "Jamie le Notre")
customers = append(customers, "Victor Savkov")
customers = append(customers, "P The Admin")
customers = append(customers, "Adrian Oprea")
customers = append(customers, "Jonathan D")
for _, customer := range customers {
fmt.Println(customer)
}
return customers
}

View File

@ -0,0 +1,28 @@
package main
type (
Customer struct {
FirstName string
LastName string
FullName string
}
)
func GetCustomers()(customers []Customer) {
marcel := Customer{ FirstName: "Marcel", LastName: "Dempers"}
customers = append(customers, marcel,
Customer{ FirstName: "Ben", LastName: "Spain" },
Customer{ FirstName: "Aleem", LastName: "Janmohamed" },
Customer{ FirstName: "Jamie", LastName: "le Notre" },
Customer{ FirstName: "Victor", LastName: "Savkov" },
Customer{ FirstName: "P", LastName: "The Admin" },
Customer{ FirstName: "Adrian", LastName: "Oprea" },
Customer{ FirstName: "Jonathan", LastName: "D" },
)
return customers
}

View File

@ -0,0 +1,3 @@
module github.com/docker-development-youtube-series/golang/introdouction/app
go 1.15

View File

@ -0,0 +1,13 @@
FROM golang:1.15-alpine as dev
WORKDIR /work
FROM golang:1.15-alpine as build
WORKDIR /app
COPY ./app/* /app/
RUN go build -o app
FROM alpine as runtime
COPY --from=build /app/app /
CMD ./app

View File

@ -0,0 +1,3 @@
FROM golang:1.15-alpine as dev
WORKDIR /work

View File

@ -0,0 +1,326 @@
# Introduction to Go: JSON
<a href="https://youtu.be/_ok29xwZ11k" title="golang-part-2"><img src="https://i.ytimg.com/vi/_ok29xwZ11k/hqdefault.jpg" width="20%" alt="introduction to Go part 2" /></a>
In programming languages, you will very often deal with data structures internally. <br/>
Sometimes, you need to pass data outside of your application or read data from another application, or even a file. <br/>
API, for example often expose data in `json`, `xml`, `grpc` and all sorts of formats.
Before we can really take a look at building APIs and even storing data in databases,
we need some fundamental knowledge about how to convert these data structures, into structures
that our application can understand. <br/>
In part 1, we dealt with [Variables]("https://tour.golang.org/basics/8") and more importantly, <br/> we dealt with `struct` data type, which made us build a `customer` object.
If we wanted to pass the `customer` to a database, or an external system, it's often required that we convert this to `json` format.
## Dev Environment
The same as Part 1, we start with a [dockerfile](./dockerfile) where we declare our version of `go`.
```
cd golang\introduction\part-2.json
docker build --target dev . -t go
docker run -it -v ${PWD}:/work go sh
go version
```
## Create our App
Create a new directory that holds defines our `repository` and holds our `module`
```
mkdir videos
```
* Define a module path
```
# change directory to your application source code
cd videos
# create a go module file
go mod init videos
```
## Create our base code
We start out all our applications with a `main.go` defining our `package`, declaring our `import` dependencies <br/>
and our entrypoint `main()` function
```
package main
import "fmt"
func main() {
fmt.Println("Hello, world.")
}
```
## Create our Videos app
Firstly, we create a seperate code file `videos.go` that deals with our YouTube videos <br/>
Similar to Part 1, we define the file, we define what a video looks like using a `struct` <br/>
and a function for returning a slice of videos.
```
package main
import ()
type video struct {
Id string
Title string
Description string
Imageurl string
Url string
}
func getVideos()(videos []video){
//Get our videos here,
//and return them
return videos
}
```
## Populating our Video Struct
Similar to our customers app, we created a `struct` and populated it with data:
Let's add the following to our `getVideos()` function:
```
video1 := video{
Id : "eyvLwK5C2dw",
Title : "Kubernetes on Azure",
Imageurl : "https://i.ytimg.com/vi/eyvLwK5C2dw/mqdefault.jpg?sqp=CISC_PoF&rs=AOn4CLDo7kizrJozB0pxBhxL9JbyiW_EPw",
Url : "https://youtu.be/eyvLwK5C2dw",
Description : "",
}
video2 := video{
Id : "QThadS3Soig",
Title : "Kubernetes on Amazon",
Imageurl : "https://i.ytimg.com/vi/QThadS3Soig/sddefault.jpg",
Url : "https://youtu.be/QThadS3Soig",
Description : "",
}
return []video{ video1, video2}
```
We need to also invoke our function that will return the videos
Don't worry about where the videos will come from. <br/>
We always start with the building blocks and move on from there <br/>
In our `main()` function: <br/>
```
func main() {
videos := getVideos()
fmt.Println(videos)
}
```
## Files
Now, Ideally, we do not want to "hard code" our videos like this. <br/>
Currently, our videos are embedded into the code and we can only return 2 videos. <br/>
If we want to introduce a new video, we have to rebuild the application. <br/>
In the real world, videos are our data. <br/>
Data lives outside of the application. Like in a database.
Technically, we can use a database, but that is too big of a step for now. <br/>
So let's start with a file instead.
### Introducing ioutil
It's important to learn how to navigate and read go documentation.
Let's go to https://golang.org/pkg/io/ioutil/
We can import this library since its part of the Go standard library set.
```
import (
"io/ioutil"
)
```
Let's move our videos into a `json` file called `videos.json` :
```
[
{
"id" : "QThadS3Soig",
"title" : "Kubernetes on Amazon",
"imageurl" : "https://i.ytimg.com/vi/QThadS3Soig/sddefault.jpg",
"url" : "https://youtu.be/QThadS3Soig",
"description" : ""
},
{
"id" : "eyvLwK5C2dw",
"title" : "Kubernetes on Azure",
"imageurl" : "https://i.ytimg.com/vi/eyvLwK5C2dw/mqdefault.jpg?sqp=CISC_PoF&rs=AOn4CLDo7kizrJozB0pxBhxL9JbyiW_EPw",
"url" : "https://youtu.be/eyvLwK5C2dw",
"description" : ""
}
]
```
## Reading a file
Let's take another look at https://golang.org/pkg/io/ioutil/ <br/>
Notice the `ReadFile` function
We can read a file from disk:
```
fileBytes, err := ioutil.ReadFile("./videos.json")
if err != nil {
panic(err)
}
fileContent := string(fileBytes)
fmt.Println(fileContent)
```
## Panic
Also notice the function `panic`. <br/>
"A panic typically means something went unexpectedly wrong. Mostly we use it to fail fast on errors that shouldnt occur during normal operation, or that we arent prepared to handle gracefully."
- https://gobyexample.com/panic
For now, we will panic on every potential error. <br/>
In a future video, we'll cover Error handling in more depth
## JSON
Working with JSON is pretty straightforward in go. <br/>
`struct` objects are pretty well synergized with `json`
Let's take a look at the `json` package that is part of go.
https://golang.org/pkg/encoding/json/
```
"encoding/json"
```
This package allows us to marshal and unmarshal JSON. <br/>
This allows conversion between a `struct` or a go type, and `json`
## Unmarshal
From JSON(bytes) ==> Struct\Go type
```
err = json.Unmarshal(fileBytes, &videos)
if err != nil {
panic(err)
}
return videos
```
## Using our Data
Now in the real world, you would use your data to do something. <br/>
Let's say we'd like to update some common terms and conditions to the video description <br/>
In our `main` function, let's loop the videos & update the description.
Feel free to checkout Part 1 of the series on `loops`!
```
for _, video := range videos {
}
```
Now we dont want to override the description, we want to inject the terms and conditions on a new line
```
video.Description = video.Description + "\n Remember to Like & Subscribe!"
```
Note that when we run this, it does not print our new description field </br>
This is because the loop `range` is giving us a copy of the video object. </br>
This means we are updating a copy, but printing out the original. </br>
We need to use the loop indexer and update the original object in the slice. </br>
```
for i, _ := range videos {
videos[i].Description = videos[i].Description + "\n Remember to Like & Subscribe!"
}
```
Run our app again and now it updates the original video!
## Marshal
https://golang.org/pkg/encoding/json/#Marshal
From Struct\Go type ==> JSON(bytes)
Let's create a new function for saving our video back to file
```
func saveVideos(videos []video)(){
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
}
```
## Writing to File
https://golang.org/pkg/io/ioutil/
```
err = ioutil.WriteFile("./videos-updated.json", videoBytes, 0644)
if err != nil {
panic(err)
}
```
Then in our `main` function we can save our videos after the update:
```
saveVideos(videos)
```
## Mapping fields
In our example our `json` and our struct fields match exactly.
Sometimes this is not possible to maintain.
Sometimes we need to tell go, to map certain `json` fields to certain fields in our `struct`
We can do it like so:
```
type video struct {
Id string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Imageurl string `json:"imageurl"`
Url string `json:"url"`
}
```

View File

@ -0,0 +1,3 @@
module videos
go 1.15

View File

@ -0,0 +1,17 @@
package main
import "fmt"
func main() {
videos := getVideos()
for i, _ := range videos {
videos[i].Description = videos[i].Description + "\n Remember to Like & Subscribe!"
}
fmt.Println(videos)
saveVideos(videos)
}

View File

@ -0,0 +1,16 @@
[
{
"id": "QThadS3Soig",
"title": "Kubernetes on Amazon",
"description": "\n Remember to Like \u0026 Subscribe!",
"imageurl": "https://i.ytimg.com/vi/QThadS3Soig/sddefault.jpg",
"url": "https://youtu.be/QThadS3Soig"
},
{
"id": "eyvLwK5C2dw",
"title": "Kubernetes on Azure",
"description": "\n Remember to Like \u0026 Subscribe!",
"imageurl": "https://i.ytimg.com/vi/eyvLwK5C2dw/mqdefault.jpg?sqp=CISC_PoF\u0026rs=AOn4CLDo7kizrJozB0pxBhxL9JbyiW_EPw",
"url": "https://youtu.be/eyvLwK5C2dw"
}
]

View File

@ -0,0 +1,44 @@
package main
import (
"io/ioutil"
"encoding/json"
)
type video struct {
Id string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Imageurl string `json:"imageurl"`
Url string `json:"url"`
}
func getVideos()(videos []video){
fileBytes, err := ioutil.ReadFile("./videos.json")
if err != nil {
panic(err)
}
err = json.Unmarshal(fileBytes, &videos)
if err != nil {
panic(err)
}
return videos
}
func saveVideos(videos []video){
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
err = ioutil.WriteFile("./videos-updated.json", videoBytes, 0644)
if err != nil {
panic(err)
}
}

View File

@ -0,0 +1,16 @@
[
{
"id" : "QThadS3Soig",
"title" : "Kubernetes on Amazon",
"imageurl" : "https://i.ytimg.com/vi/QThadS3Soig/sddefault.jpg",
"url" : "https://youtu.be/QThadS3Soig",
"description" : ""
},
{
"id" : "eyvLwK5C2dw",
"title" : "Kubernetes on Azure",
"imageurl" : "https://i.ytimg.com/vi/eyvLwK5C2dw/mqdefault.jpg?sqp=CISC_PoF&rs=AOn4CLDo7kizrJozB0pxBhxL9JbyiW_EPw",
"url" : "https://youtu.be/eyvLwK5C2dw",
"description" : ""
}
]

View File

@ -0,0 +1,14 @@
FROM golang:1.15-alpine as dev
WORKDIR /work
FROM golang:1.15-alpine as build
WORKDIR /videos
COPY ./videos/* /videos/
RUN go build -o videos
FROM alpine as runtime
COPY --from=build /videos/videos /
COPY ./videos/videos.json /
CMD ./videos

View File

@ -0,0 +1,435 @@
# Introduction to Go: HTTP
<a href="https://youtu.be/MKkokYpGyTU" title="golang-part-3"><img src="https://i.ytimg.com/vi/MKkokYpGyTU/hqdefault.jpg" width="20%" alt="introduction to Go part 3" /></a>
HTTP is a fundamental part of Microservices and Web distributed systems <br/>
Go has a built in HTTP web server package. The package can be found [here](https://golang.org/pkg/net/http/) <br/>
We simply have to import the `http` package:
```
import (
"net/http"
)
```
[In part 1](../readme.md), we covered the fundamentals of writing basic Go <br/>
[In part 2](../part-2.json/readme.md), we've learn how to use basic data structures like `json` so we can send\receive data. <br/>
We'll be combining both these techniques so we can serve our `videos` data over a web endpoint.
As always, let's start with our `dockerfile` , `main.go` and `videos.go` we created in Part 2
## Dev Environment
The same as Part 1+2, we start with a [dockerfile](./dockerfile) where we declare our version of `go`.
```
cd golang\introduction\part-3.http
docker build --target dev . -t go
docker run -it -v ${PWD}:/work go sh
go version
```
## Create our App
Create a new directory that holds defines our `repository` and holds our `module`
```
mkdir videos
```
* Define a module path
```
# change directory to your application source code
cd videos
# create a go module file
go mod init videos
```
## Create our base code
We start out all our applications with a `main.go` defining our `package`, declaring our `import` dependencies <br/>
and our entrypoint `main()` function
```
package main
import "fmt"
func main() {
fmt.Println("Hello, world.")
}
```
## Create our Videos app
Firstly, we create a seperate code file `videos.go` that deals with our YouTube videos <br/>
The `videos.go` file defines what a video `struct` looks like, a `getVideos()` function to retrieve <br/>
videos list as a slice and a `saveVideos()` function to save videos to a file locally. <br/>
Let's copy the following content from Part 2 and create `videos.go` :
We want `videos.go` to be part of package main:
```
package main
```
We import 2 packages, 1 for reading and writing files, and another for dealing with `json`
```
import (
"io/ioutil"
"encoding/json"
)
```
Then we define what a video `struct` looks like:
```
type video struct {
Id string
Title string
Description string
Imageurl string
Url string
}
```
We have a function for retrieving `video` objects as a list of type `slice` :
```
func getVideos()(videos []video){
fileBytes, err := ioutil.ReadFile("./videos.json")
if err != nil {
panic(err)
}
err = json.Unmarshal(fileBytes, &videos)
if err != nil {
panic(err)
}
return videos
}
```
We also need to copy our `videos.json` file which contains our video data. <br/>
And finally, we have a function that accepts a list of type `slice` and stores the videos to a local file
```
func saveVideos(videos []video)(){
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
err = ioutil.WriteFile("./videos-updated.json", videoBytes, 0644)
if err != nil {
panic(err)
}
}
```
## HTTP Package
https://golang.org/pkg/net/http/
The HTTP package allows us to implement an HTTP client and a server.
A client is a component that makes HTTP calls.
A server is a component that receives or serves HTTP.
The HTTP package is capable of sending HTTP requests as well as defining a server
for receiving HTTP requests.
We can use this to run an HTTP server to serve files, or serve data, like an API.
Let's define a server in `main.go` :
```
# just one line :)
http.ListenAndServe(":8080", nil)
# ListenAndServe starts an HTTP server with a given address and handler.
# The handler is usually nil, which means to use DefaultServeMux.
# Handle and HandleFunc add handlers to DefaultServeMux
```
Now before we run this, since we're running in Docker, we want to exit the container <br/>
and rerun it, but this time open port `8080`
```
docker run -it -p 8080:8080 -v ${PWD}:/work go sh
cd videos
go run main.go
# you will notice the application pausing
```
We should see our server with a 404 on http://localhost:8080/
## Handle HTTP requests
In order to handle requests, we can tell the HTTP service that we want it to run a function </br>
for the request coming in.
We can see the `http` package has a `HandleFunc` function: https://golang.org/pkg/net/http/
To see this in action, lets create a `Hello()` function:
```
func Hello(){
}
```
And tell our `http` service to run it:
```
http.HandleFunc("/", Hello)
```
We cannot run this yet. As per `http` documentation, our `Hello` function needs to take in some inputs.
`func HandleFunc(pattern string, handler func(ResponseWriter, *Request))`
Therefore we need to add inputs to our function:
```
func Hello(w http.ResponseWriter, r *http.Request){
}
```
This allows us to get the request, its `body`, `headers` and a write where we can send a response.
Run this in the browser and you will notice the 404 goes away, but we now get an empty response.
## HTTP Response
Let's write a reponse to the incoming request. </br>
The response write has a `Write()` function that takes a bunch of bytes. <br/>
We can convert string to bytes by casting a `string` to a `[]byte` <br/> like:
`[]byte("Hello!")`. Let's convert it and write "Hello" to the response:
```
w.Write([]byte("Hello!"))
```
IF we run this code, we can see "Hello!" in the response body
## HTTP Headers
Headers play an important role in HTTP communication. </br>
Lets access all the headers of the incoming request!
If we look at the Header definition [here](https://golang.org/pkg/net/http), we can see how to access it.
Let's use the `for` loop we learnt in [part 1](../readme.md)
```
for i, value := range r.Header {
}
```
We learn't from our loop, we have in indexer and a value.
For `i`, we can rename it to header since it represents the header key in the dictionary.
And the `value` is the value of type `[]string`, containing the value of the header:
```
for header, value := range r.Header {
fmt.Printf("Key: %v \t Value: %v \n", header, value)
}
```
We can use `fmt` to print out the values and look at the headers.
We can also set headers on our response. <br/>
If we take a look at the `http` docs, we can see header is also a dictionary or strings.
```
w.Header().Add("TestHeader", "TestValue")
```
You can now see the headers in the response value if you use `curl` or your browser development tools
## HTTP Methods | GET
Web servers can serve data in a number of ways and support multiple type of HTTP methods.
`GET` is used to request data from a specified resource.
So far, our HTTP route for our Hello function is using the `GET` method.
Let's make our `GET` method more useful by serving our video data </br>
Let's rename our `Hello()` function to `HandleGetVideos()`. </br>
Our `/` route will return all videos:
```
videos := getVideos()
```
In [part 2](../part-2.json/readme.md) we covered `JSON`.
We need to convert our video `slice` of `struct`'s to `JSON` in order to return it to the client.
For this we learnt about the Marshall function:
Import the `JSON` package:
```
"encoding/json"
```
Convert our videos to `JSON` :
```
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
w.Write(videoBytes)
```
If we run this code and hit our `/` endpoint, we can now see `JSON` data being returned. <br/>
This is a core part of building an API in Go. <br/>
## HTTP Methods | POST
A `POST` method is used to send data to a server to create/update a resource. <br/>
Since we built a `saveVideos` function, lets use that so a client can update videos! <br/>
We need to define a new route, we can all it `/update` :
```
http.HandleFunc("/update", HandleUpdateVideos)
```
And we need to define an `HandleUpdateVideos()` function:
```
func HandleUpdateVideos(w http.ResponseWriter, r *http.Request){
}
```
Let's validate the request method to ensure its `POST`
We need to also ensure we send a status code to inform the user of method not allowed.
https://golang.org/pkg/net/http/#ResponseWriter
```
if r.Method == "POST" {
//update our videos here!
} else {
w.WriteHeader(405)
fmt.Fprintf(w, "Method not Supported!")
}
```
Now we need to accept `JSON` from the `POST` request body
https://golang.org/pkg/net/http/#Request
In the docs above, we can see the request Body is of type `Body io.ReadCloser`
To read that, we can use the `ioutil` package
https://golang.org/pkg/io/ioutil/
```
import "io/ioutil"
```
Then we can read the body into a `slice` of `bytes`:
```
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
```
Now that we have the body in a `[]byte`, we need to use our knowledge from [part 2](../part-2.json/readme.md) where we <br/>
convert `[]byte` to a `slice` of `video` items.
```
var videos []video
err = json.Unmarshal(body, &videos)
if err != nil {
panic(err)
}
```
Creating our video objects allows us to do some validation if we wanted to. <br/>
We can ensure the request body adheres to our API contract for this videos API. <br/>
So instead of calling `panic`, lets return a `400` Bad request status code if we cannot <br/>
Unmarshal the `JSON` data. This might help with some basic validation.
```
w.WriteHeader(400)
fmt.Fprintf(w, "Bad request")
```
And Finally, let's update our videos file! :
```
saveVideos(videos)
```
# Build our Docker container
Let's uncomment all the build lines in the `dockerfile`
Full `dockerfile` :
```
FROM golang:1.15-alpine as dev
WORKDIR /work
FROM golang:1.15-alpine as build
WORKDIR /videos
COPY ./videos/* /videos/
RUN go build -o videos
FROM alpine as runtime
COPY --from=build /videos/videos /
COPY ./videos/videos.json /
CMD ./videos
```
Build :
```
cd golang\introduction\part-3.http
docker build . -t videos
```
Run :
```
docker run -it -p 8080:8080 videos
```
## Things to know
* SSL for secure web connection
* Authentication
* Good API validation
* Support a backwards compatible contract (Inputs remain consistent)

View File

@ -0,0 +1,3 @@
module videos
go 1.15

View File

@ -0,0 +1,54 @@
package main
import (
"net/http"
"encoding/json"
"io/ioutil"
"fmt"
)
func main() {
http.HandleFunc("/", HandleGetVideos)
http.HandleFunc("/update", HandleUpdateVideos)
http.ListenAndServe(":8080", nil)
}
func HandleGetVideos(w http.ResponseWriter, r *http.Request){
videos := getVideos()
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
w.Write(videoBytes)
}
func HandleUpdateVideos(w http.ResponseWriter, r *http.Request){
if r.Method == "POST" {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
var videos []video
err = json.Unmarshal(body, &videos)
if err != nil {
w.WriteHeader(400)
fmt.Fprintf(w, "Bad request")
}
saveVideos(videos)
} else {
w.WriteHeader(405)
fmt.Fprintf(w, "Method not Supported!")
}
}

View File

@ -0,0 +1,16 @@
[
{
"Id": "QThadS3Soig",
"Title": "Kubernetes on Amazon",
"Description": "TEST",
"Imageurl": "https://i.ytimg.com/vi/QThadS3Soig/sddefault.jpg",
"Url": "https://youtu.be/QThadS3Soig"
},
{
"Id": "eyvLwK5C2dw",
"Title": "Kubernetes on Azure",
"Description": "TEST",
"Imageurl": "https://i.ytimg.com/vi/eyvLwK5C2dw/mqdefault.jpg?sqp=CISC_PoF\u0026rs=AOn4CLDo7kizrJozB0pxBhxL9JbyiW_EPw",
"Url": "https://youtu.be/eyvLwK5C2dw"
}
]

View File

@ -0,0 +1,46 @@
package main
import (
"io/ioutil"
"encoding/json"
)
type video struct {
Id string
Title string
Description string
Imageurl string
Url string
}
func getVideos()(videos []video){
fileBytes, err := ioutil.ReadFile("./videos.json")
if err != nil {
panic(err)
}
err = json.Unmarshal(fileBytes, &videos)
if err != nil {
panic(err)
}
return videos
}
func saveVideos(videos []video)(){
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
err = ioutil.WriteFile("./videos-updated.json", videoBytes, 0644)
if err != nil {
panic(err)
}
}

View File

@ -0,0 +1,16 @@
[
{
"id" : "QThadS3Soig",
"title" : "Kubernetes on Amazon",
"imageurl" : "https://i.ytimg.com/vi/QThadS3Soig/sddefault.jpg",
"url" : "https://youtu.be/QThadS3Soig",
"description" : ""
},
{
"id" : "eyvLwK5C2dw",
"title" : "Kubernetes on Azure",
"imageurl" : "https://i.ytimg.com/vi/eyvLwK5C2dw/mqdefault.jpg?sqp=CISC_PoF&rs=AOn4CLDo7kizrJozB0pxBhxL9JbyiW_EPw",
"url" : "https://youtu.be/eyvLwK5C2dw",
"description" : ""
}
]

View File

@ -0,0 +1,17 @@
FROM golang:1.15-alpine as dev
WORKDIR /work
# FROM golang:1.15-alpine as build
# WORKDIR /videos
# COPY ./videos/* /videos/
# RUN go build -o videos
# FROM alpine as runtime
# COPY --from=build /videos/videos /usr/local/bin/videos
# COPY ./videos/videos.json /
# COPY run.sh /
# RUN chmod +x /run.sh
# ENTRYPOINT [ "./run.sh" ]

View File

@ -0,0 +1,418 @@
# Introduction to Go: Command Line
<a href="https://youtu.be/CODqM_rzwtk" title="golang-part-4"><img src="https://i.ytimg.com/vi/CODqM_rzwtk/hqdefault.jpg" width="20%" alt="introduction to Go part 4" /></a>
Command line apps are a fundamental part of software development <br/>
Go has a built in Commandline parser package. The package can be found [here](https://golang.org/pkg/flag/) <br/>
We simply have to import the `flag` package:
```
import (
"flag"
)
```
[In part 1](../readme.md), we covered the fundamentals of writing basic Go <br/>
[In part 2](../part-2.json/readme.md), we've learn how to use basic data structures like `json` so we can send\receive data. <br/>
[Part 3](../part-3.http/readme.md) was about exposing data via a Web server.
We'll be combining these techniques so we can serve our `videos` data over a commandline application.
As always, let's start with our `dockerfile` , `main.go` and `videos.go` we created in Part 2
## Dev Environment
The same as Part 1+2+3, we start with a [dockerfile](./dockerfile) where we declare our version of `go`.
```
cd golang\introduction\part-4.commandline
docker build --target dev . -t go
docker run -it -v ${PWD}:/work go sh
go version
```
## Create our App
Create a new directory that holds defines our `repository` and holds our `module`
```
mkdir videos
cd videos
```
* Define a module path
```
# create a go module file
go mod init videos
```
## Create our base code
We start out all our applications with a `main.go` defining our `package`, declaring our `import` dependencies <br/>
and our entrypoint `main()` function
```
package main
import "fmt"
func main() {
fmt.Println("Hello, world.")
}
```
## Create our Videos app
Firstly, we create a seperate code file `videos.go` that deals with our YouTube videos <br/>
The `videos.go` file defines what a video `struct` looks like, a `getVideos()` function to retrieve <br/>
videos list as a slice and a `saveVideos()` function to save videos to a file locally. <br/>
Let's copy the following content from Part 2 and create `videos.go` :
We want `videos.go` to be part of package main:
```
package main
```
We import 2 packages, 1 for reading and writing files, and another for dealing with `json`
```
import (
"io/ioutil"
"encoding/json"
)
```
Then we define what a video `struct` looks like:
```
type video struct {
Id string
Title string
Description string
Imageurl string
Url string
}
```
We have a function for retrieving `video` objects as a list of type `slice` :
```
func getVideos()(videos []video){
fileBytes, err := ioutil.ReadFile("./videos.json")
if err != nil {
panic(err)
}
err = json.Unmarshal(fileBytes, &videos)
if err != nil {
panic(err)
}
return videos
}
```
We also need to copy our `videos.json` file which contains our video data. <br/>
And finally, we have a function that accepts a list of type `slice` and stores the videos to a local file
```
func saveVideos(videos []video)(){
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
err = ioutil.WriteFile("./videos.json", videoBytes, 0644)
if err != nil {
panic(err)
}
}
```
## Flag Package
https://golang.org/pkg/flag/
Package flag implements command-line flag parsing.
So we can run our videos app and pass it inputs like any other CLI.
Let's build a CLI tool that users our `getVideos()` and `saveVideos` functions.
To get all videos, perhaps we'd like a command
```
# get all videos
videos get --all
# get video by ID
videos get -id <video-id>
# add a video to our list
videos add -id -title -url -imageurl -desc
```
To start, we import package `flag`
```
import (
"flag"
"fmt"
)
```
Let's define our subcommands in `main.go` :
```
//'videos get' subcommand
getCmd := flag.NewFlagSet("get", flag.ExitOnError)
```
`videos get` command will need two inputs, `--all` if the user wants to return all videos, or `--id` if the user only wants a specific video
```
// inputs for `videos get` command
getAll := getCmd.Bool("all", false, "Get all videos")
getID := getCmd.String("id", "", "YouTube video ID")
```
`videos add` command will take a bit more inputs to be able to add a video to our storage.
```
addCmd := flag.NewFlagSet("add", flag.ExitOnError)
addID := addCmd.String("id", "", "YouTube video ID")
addTitle := addCmd.String("title", "", "YouTube video Title")
addUrl := addCmd.String("url", "", "YouTube video URL")
addImageUrl := addCmd.String("imageurl", "", "YouTube video Image URL")
addDesc := addCmd.String("desc", "", "YouTube video description")
```
When a user runs our videos CLI tool, we may need to validate that
our application receives the right subcommands. So lets ensure a simple validation to check if the user has passed a subcommand
To check the arguments passed to our CLI, we use the ["os"](https://golang.org/pkg/os/) package. Check the Args variable, it holds usefull information passed to our application including its name.
`var Args []string`
We can do a simple check by ensuring the length of `os.Args` is atleast 2.
We firstly need to add `os` to our import section </br>
Followed by our check:
```
if len(os.Args) < 2 {
fmt.Println("expected 'get' or 'add' subcommands")
os.Exit(1)
}
```
## Handling our subcommands
So to handle each sub command like `get` and `add`, we add a simple
`switch` statement that can branch into different pathways of execution,
based on a variables content.
Let's take a look at this simple `switch` statement:
```
//look at the 2nd argument's value
switch os.Args[1] {
case "get": // if its the 'get' command
//hande get here
case "add": // if its the 'add' command
//hande add here
default: // if we don't understand the input
}
```
Let's create seperate handler functions for each sub command to keep our code tidy:
```
func HandleGet(getCmd *flag.FlagSet, all *bool, id *string){
}
func HandleAdd(addCmd *flag.FlagSet,id *string, title *string, url *string, imageUrl *string, description *string ){
}
```
Now that we have seperate functions for each subcommand, we can take appropriate actions in each. Let's firstly parse the command flags for each subcommand:
This allows us to parse everything after the `videos <subcommand>` arguments:
```
getCmd.Parse(os.Args[2:])
```
## Input Validation
For our `HandleGet` function, let's validate input to ensure its correct.
```
if *all == false && *id == "" {
fmt.Print("id is required or specify --all for all videos")
getCmd.PrintDefaults()
os.Exit(1)
}
```
Let's handle the scenario if user passing `--all` flag:
```
if *all {
//return all videos
videos := getVideos()
fmt.Printf("ID \t Title \t URL \t ImageURL \t Description \n")
for _, video := range videos {
fmt.Printf("%v \t %v \t %v \t %v \t %v \n",video.Id, video.Title, video.Url, video.Imageurl,video.Description)
}
return
}
```
Let's handle when user is searching for a video by ID
```
if *id != "" {
videos := getVideos()
id := *id
for _, video := range videos {
if id == video.Id {
fmt.Printf("ID \t Title \t URL \t ImageURL \t Description \n")
fmt.Printf("%v \t %v \t %v \t %v \t %v \n",video.Id, video.Title, video.Url, video.Imageurl,video.Description)
}
}
}
```
## Parsing multiple fields
For our `HandleAdd` function, we need to validate multiple inputs, create a `video` struct, append it to the existing video list and save it back to file
Let's create a `ValidateVideo()` function with similar inputs to our `HandleAdd()`:
```
func ValidateVideo(addCmd *flag.FlagSet,id *string, title *string, url *string, imageUrl *string, description *string ){
}
```
Let's simply validate all fields since they are all required:
```
if *id == "" || *title == "" || *url == "" || *imageUrl == "" || *description == "" {
fmt.Print("all fields are required for adding a video")
addCmd.PrintDefaults()
os.Exit(1)
}
```
And we can now call this function in our add function:
```
ValidateVideo(addCmd, id,title,url, imageUrl, description)
```
## Adding our video
Now that we have some basic validation, not perfect, but good enough to get started, let's add our video to the existing file.
Define a video struct with the CLI input:
```
video := video{
Id: *id,
Title: *title,
Description: *description,
Imageurl: *imageUrl,
Url: *url,
}
```
Get the existing videos:
```
videos := getVideos()
```
Append our video to the list:
```
videos = append(videos,video)
```
Save the new updated video list:
```
saveVideos(videos)
```
# Build our Docker container
Let's uncomment all the build lines in the `dockerfile`
Full `dockerfile` :
```
FROM golang:1.15-alpine as dev
WORKDIR /work
FROM golang:1.15-alpine as build
WORKDIR /videos
COPY ./videos/* /videos/
RUN go build -o videos
FROM alpine as runtime
COPY --from=build /videos/videos /usr/local/bin/videos
COPY ./videos/videos.json /
COPY run.sh /
RUN chmod +x /run.sh
ENTRYPOINT [ "./run.sh" ]
```
For our entrypoint, we need to create a shell script to accept all the arguments:
Let's create a script called `run.sh`
```
#!/bin/sh
videos $@
```
Build :
```
cd golang\introduction\part-4.commandline
docker build . -t videos
```
Run :
```
docker run -it videos get --help
```

View File

@ -0,0 +1,3 @@
#!/bin/sh
videos $@

View File

@ -0,0 +1,3 @@
module videos
go 1.15

View File

@ -0,0 +1,111 @@
package main
import (
"flag"
"fmt"
"os"
)
func main() {
//'videos get' subcommand
getCmd := flag.NewFlagSet("get", flag.ExitOnError)
// inputs for `videos get` command
getAll := getCmd.Bool("all", false, "Get all videos")
getID := getCmd.String("id", "", "YouTube video ID")
//'videos add' subcommand
addCmd := flag.NewFlagSet("add", flag.ExitOnError)
// inputs for `videos add` command
addID := addCmd.String("id", "", "YouTube video ID")
addTitle := addCmd.String("title", "", "YouTube video Title")
addUrl := addCmd.String("url", "", "YouTube video URL")
addImageUrl := addCmd.String("imageurl", "", "YouTube video Image URL")
addDesc := addCmd.String("desc", "", "YouTube video description")
if len(os.Args) < 2 {
fmt.Println("expected 'get' or 'add' subcommands")
os.Exit(1)
}
//look at the 2nd argument's value
switch os.Args[1] {
case "get": // if its the 'get' command
HandleGet(getCmd, getAll, getID)
case "add": // if its the 'add' command
HandleAdd(addCmd, addID,addTitle,addUrl, addImageUrl, addDesc)
default: // if we don't understand the input
}
}
func HandleGet(getCmd *flag.FlagSet, all *bool, id *string){
getCmd.Parse(os.Args[2:])
if *all == false && *id == "" {
fmt.Print("id is required or specify --all for all videos")
getCmd.PrintDefaults()
os.Exit(1)
}
if *all {
//return all videos
videos := getVideos()
fmt.Printf("ID \t Title \t URL \t ImageURL \t Description \n")
for _, video := range videos {
fmt.Printf("%v \t %v \t %v \t %v \t %v \n",video.Id, video.Title, video.Url, video.Imageurl,video.Description)
}
return
}
if *id != "" {
videos := getVideos()
id := *id
for _, video := range videos {
if id == video.Id {
fmt.Printf("ID \t Title \t URL \t ImageURL \t Description \n")
fmt.Printf("%v \t %v \t %v \t %v \t %v \n",video.Id, video.Title, video.Url, video.Imageurl,video.Description)
}
}
}
}
func ValidateVideo(addCmd *flag.FlagSet,id *string, title *string, url *string, imageUrl *string, description *string ){
addCmd.Parse(os.Args[2:])
if *id == "" || *title == "" || *url == "" || *imageUrl == "" || *description == "" {
fmt.Print("all fields are required for adding a video")
addCmd.PrintDefaults()
os.Exit(1)
}
}
func HandleAdd(addCmd *flag.FlagSet,id *string, title *string, url *string, imageUrl *string, description *string ){
ValidateVideo(addCmd, id,title,url, imageUrl, description)
video := video{
Id: *id,
Title: *title,
Description: *description,
Imageurl: *imageUrl,
Url: *url,
}
videos := getVideos()
videos = append(videos,video)
saveVideos(videos)
}

Binary file not shown.

View File

@ -0,0 +1,45 @@
package main
import (
"io/ioutil"
"encoding/json"
)
type video struct {
Id string
Title string
Description string
Imageurl string
Url string
}
func getVideos()(videos []video){
fileBytes, err := ioutil.ReadFile("./videos.json")
if err != nil {
panic(err)
}
err = json.Unmarshal(fileBytes, &videos)
if err != nil {
panic(err)
}
return videos
}
func saveVideos(videos []video)(){
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
err = ioutil.WriteFile("./videos.json", videoBytes, 0644)
if err != nil {
panic(err)
}
}

View File

@ -0,0 +1,16 @@
[
{
"Id": "QThadS3Soig",
"Title": "Kubernetes on Amazon",
"Description": "",
"Imageurl": "https://i.ytimg.com/vi/QThadS3Soig/sddefault.jpg",
"Url": "https://youtu.be/QThadS3Soig"
},
{
"Id": "eyvLwK5C2dw",
"Title": "Kubernetes on Azure",
"Description": "",
"Imageurl": "https://i.ytimg.com/vi/eyvLwK5C2dw/mqdefault.jpg?sqp=CISC_PoF\u0026rs=AOn4CLDo7kizrJozB0pxBhxL9JbyiW_EPw",
"Url": "https://youtu.be/eyvLwK5C2dw"
}
]

View File

@ -0,0 +1,13 @@
FROM golang:1.15-alpine as dev
WORKDIR /work
FROM golang:1.15-alpine as build
WORKDIR /videos
COPY ./videos/* /videos/
RUN go build -o videos
FROM alpine as runtime
COPY --from=build /videos/videos /
CMD ./videos

View File

@ -0,0 +1,559 @@
# Introduction to Go: Storing data in Redis Database
<a href="https://youtu.be/6lJCyKwoQaQ" title="golang-part-5"><img src="https://i.ytimg.com/vi/6lJCyKwoQaQ/hqdefault.jpg" width="20%" alt="introduction to Go part 5" /></a>
Up until now, we've learned the fundamentals of Go and built a small web microservice that handles our video data.
Our service has a `/` `GET` endpoint for returning all videos, as well as a simple `/update` endpoint for updating our list of videos.
We've learnt how to read and write from files and learn how to work with `json` data. </br>
This is important for learning Go, however there are a few challenges for using a file as storage. <br/>
* It can be problematic if we have more than one instance of our service writing to the same file
* It's important to keep state out of our application, so if our application crashes, we don't lose our data
[In part 1](../readme.md), we covered the fundamentals of writing basic Go <br/>
[In part 2](../part-2.json/readme.md), we've learnt how to use basic data structures like `json` so we can send\receive data. <br/>
[In part 3](../part-3.http/readme.md), we've learnt how to write a HTTP service to expose our videos data <br/>
## Start up a Redis Cluster
Follow my Redis clustering Tutorial </br>
<a href="https://youtube.com/playlist?list=PLHq1uqvAteVtlgFkmOlIqWro3XP26y_oW" title="Redis"><img src="https://i.ytimg.com/vi/L3zp347cWNw/hqdefault.jpg" width="30%" alt="Redis Guide" /></a>
Code is over [here](../../../storage/redis/clustering/readme.md)
## Go Dev Environment
The same as Part 1+2+3+4, we start with a [dockerfile](./dockerfile) where we declare our version of `go`.
The `dockerfile`:
```
FROM golang:1.15-alpine as dev
WORKDIR /work
```
Let's build and start our container:
```
cd golang\introduction\part-5.database.redis
docker build --target dev . -t go
docker run -it -p 80:80 -v ${PWD}:/work go sh
go version
```
## Our application
Create a new directory that holds defines our `repository` and holds our `module`
```
mkdir videos
```
* Define a module path
```
# change directory to your application source code
cd videos
# create a go module file
go mod init videos
```
## Create our base code
We start out all our applications with a `main.go` defining our `package`, declaring our `import` dependencies <br/>
and our entrypoint `main()` function
```
package main
import (
"net/http"
"encoding/json"
"io/ioutil"
"fmt"
)
func main() {
http.HandleFunc("/", HandleGetVideos)
http.HandleFunc("/update", HandleUpdateVideos)
http.ListenAndServe(":80", nil)
}
```
Now before we write these handler functions, we need our videos application
## Create our Videos app
Firstly, we create a separate code file `videos.go` that deals with our YouTube videos <br/>
The `videos.go` file defines what a video `struct` looks like, a `getVideos()` function to retrieve <br/>
videos list as a slice and a `saveVideos()` function to save videos to a file locally. <br/>
We start with our dependencies. <br>
We import 2 packages, 1 for reading and writing files, and another for dealing with `json`
```
package main
import (
"io/ioutil"
"encoding/json"
)
```
Then we define what a video `struct` looks like:
```
type video struct {
Id string
Title string
Description string
Imageurl string
Url string
}
```
We have a function for retrieving `video` objects as a list of type `slice` :
```
func getVideos()(videos []video){
fileBytes, err := ioutil.ReadFile("./videos.json")
if err != nil {
panic(err)
}
err = json.Unmarshal(fileBytes, &videos)
if err != nil {
panic(err)
}
return videos
}
```
We also need to copy our `videos.json` file which contains our video data. <br/>
And finally, we have a function that accepts a list of type `slice` and stores the videos to a local file
```
func saveVideos(videos []video)(){
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
err = ioutil.WriteFile("./videos.json", videoBytes, 0644)
if err != nil {
panic(err)
}
}
```
## HTTP Handlers
Now we have to define our handler functions `HandleGetVideos` and `HandleUpdateVideos`,
```
func HandleGetVideos(w http.ResponseWriter, r *http.Request){
videos := getVideos()
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
w.Write(videoBytes)
}
func HandleUpdateVideos(w http.ResponseWriter, r *http.Request){
if r.Method == "POST" {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
var videos []video
err = json.Unmarshal(body, &videos)
if err != nil {
w.WriteHeader(400)
fmt.Fprintf(w, "Bad request")
}
saveVideos(videos)
} else {
w.WriteHeader(405)
fmt.Fprintf(w, "Method not Supported!")
}
}
```
Now so far, we have a web HTTP application that can list and update our youtube videos. <br/>
Let's build and run it
```
go build
./videos
```
If we head over to `http://localhost` in the browser we can see our application returns our 2 videos. </br>.
We can use tools like PostMan to generate a `POST` request to update our videos too.
## Redis Go Package
Now instead of reading and writing our records to a `json` file, we are going to read and write records to Redis.
https://github.com/go-redis/redis/
```
go get github.com/go-redis/redis/v8
```
And to use the library, we have to import it
```
import (
"github.com/go-redis/redis/v8"
)
```
Now to connect to any database, you're going to need a bit of information:
* Database Address
* Database Port
* Database Username\Password
We can define these as environment variables and read those in our code
```
import (
"os"
)
//main.go (global variables)
var redis_sentinels = os.Getenv("REDIS_SENTINELS")
var redis_master = os.Getenv("REDIS_MASTER_NAME")
var redis_password = os.Getenv("REDIS_PASSWORD")
```
We define an empty context and Redis client
Context can be used to control timeouts and deadlines for our application. We can set up an empty context for now.
```
import (
"context"
)
var ctx = context.Background()
var redisClient *redis.Client
```
## Redis Sentinel Client
https://redis.uptrace.dev/guide/sentinel.html#redis-server-client
```
import (
"strings"
)
sentinelAddrs := strings.Split(redis_sentinels, ",")
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: redis_master,
SentinelAddrs: sentinelAddrs,
Password: redis_password,
DB: 0,
})
redisClient = rdb
rdb.Ping(ctx)
```
We can also add the `Ping()` to our handler functions to ensure it can connect using the global redis client variable
## Networking
Now we need to remember our go container may not be able to talk to the redis containers because they are running on different networks.
If you took note, we started our Redis containers on a `redis` network by passing `--net redis` as a flag to our `docker run` commands. </br>
Let's restart our Go container on the same network
We also need to set our `ENV` variables to point our container to the redis sentinels. </br>
If we look at our sentinel configuration, our master alias is set to `mymaster`
```
docker run -it -p 80:80 `
--net redis `
-e REDIS_SENTINELS="sentinel-0:5000,sentinel-1:5000,sentinel-2:5000" `
-e REDIS_MASTER_NAME="mymaster" `
-e REDIS_PASSWORD="a-very-complex-password-here" `
-v ${PWD}:/work go sh
```
We can now observe our container is connected to Redis. </br>
Our application: [http://localhost](http://localhost)
# Store our Data
So now we can store our video data in Redis instead of a local `json` file. </br>
We'll write the `json` document of a video (struct) to Redis. </br>
Let's create a `saveVideo()` function that stores a single record.
```
func saveVideo(video video)(){
videoBytes, err := json.Marshal(video)
if err != nil {
panic(err)
}
err = redisClient.Set(ctx, video.Id, videoBytes, 0).Err()
if err != nil {
panic(err)
}
}
```
Now since we have one endpoint that saves all videos, we need to update it to save each video it has.
```
func saveVideos(videos []video)(){
for _, video := range videos {
saveVideo(video)
}
}
```
To get the videos, let's create a function to retrieve a single record:
```
func getVideo(id string)(video video) {
value, err := redisClient.Get(ctx, id).Result()
if err != nil {
panic(err)
}
if err != redis.Nil {
err = json.Unmarshal([]byte(value), &video)
}
return video
}
```
And finally we need to update our `GetVideos()` function to loop all the video keys and return all videos
```
func getVideos()(videos []video){
keys, err := redisClient.Keys(ctx,"*").Result()
if err != nil {
panic(err)
}
for _, key := range keys {
video := getVideo(key)
videos = append(videos, video)
}
return videos
}
```
And we need all our imports
```
import (
"encoding/json"
"github.com/go-redis/redis/v8"
)
```
Now if we rebuild our all and access it, we get `null` as there are no videos in Redis. Let's add two!
Let's `POST` the following using PostMan to url `http://localhost/update`
```
[
{
"id" : "QThadS3Soig",
"title" : "Kubernetes on Amazon",
"imageurl" : "https://i.ytimg.com/vi/QThadS3Soig/sddefault.jpg",
"url" : "https://youtu.be/QThadS3Soig",
"description" : "TEST"
},
{
"id" : "eyvLwK5C2dw",
"title" : "Kubernetes on Azure",
"imageurl" : "https://i.ytimg.com/vi/eyvLwK5C2dw/mqdefault.jpg?sqp=CISC_PoF&rs=AOn4CLDo7kizrJozB0pxBhxL9JbyiW_EPw",
"url" : "https://youtu.be/eyvLwK5C2dw",
"description" : "TEST"
}
]
```
If we refresh our page, we can now see two records!
# Improvements
Now that you have the fundamental knowledge of HTTP and Redis, </br>
you can update the code to retrieve 1 video by ID, or delete a video by ID. </br>
You can add search functionality and more! </br>
Let's update our `/ GET` handler to be able to return a single video
```
func HandleGetVideos(w http.ResponseWriter, r *http.Request){
id, ok := r.URL.Query()["id"]
if ok {
videoID := id[0]
video := getVideo(videoID)
if video.Id == "" { //video not found, or empty ID
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("{}"))
return
}
videoBytes, err := json.Marshal(video)
if err != nil {
panic(err)
}
w.Write(videoBytes)
return
}
videos := getVideos()
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
w.Write(videoBytes)
}
```
We can also update our `/update POST` endpoint to be able to update a single video
```
func HandleUpdateVideos(w http.ResponseWriter, r *http.Request){
if r.Method == "POST" {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
_, ok := r.URL.Query()["id"]
if ok {
var video video
err = json.Unmarshal(body, &video)
if err != nil {
w.WriteHeader(400)
fmt.Fprintf(w, "Bad request")
}
saveVideo(video)
return
}
var videos []video
err = json.Unmarshal(body, &videos)
if err != nil {
w.WriteHeader(400)
fmt.Fprintf(w, "Bad request")
}
saveVideos(videos)
return
} else {
w.WriteHeader(405)
fmt.Fprintf(w, "Method not Supported!")
}
}
```
# Build our Docker container
Full `dockerfile` :
```
FROM golang:1.15-alpine as dev
WORKDIR /work
FROM golang:1.15-alpine as build
WORKDIR /videos
COPY ./videos/* /videos/
RUN go build -o videos
FROM alpine as runtime
COPY --from=build /videos/videos /
CMD ./videos
```
Build :
```
cd golang\introduction\part-5.database.redis
docker build . -t videos
```
Run :
```
docker run -it -p 80:80 `
--net redis `
-e REDIS_SENTINELS="sentinel-0:5000,sentinel-1:5000,sentinel-2:5000" `
-e REDIS_MASTER_NAME="mymaster" `
-e REDIS_PASSWORD="a-very-complex-password-here" `
videos
```

View File

@ -0,0 +1,5 @@
module videos
go 1.15
require github.com/go-redis/redis/v8 v8.11.4

View File

@ -0,0 +1,89 @@
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

View File

@ -0,0 +1,113 @@
package main
import (
"net/http"
"encoding/json"
"io/ioutil"
"fmt"
"os"
"context"
"strings"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
var redisClient *redis.Client
func main() {
var redis_sentinels = os.Getenv("REDIS_SENTINELS")
var redis_master = os.Getenv("REDIS_MASTER_NAME")
var redis_password = os.Getenv("REDIS_PASSWORD")
sentinelAddrs := strings.Split(redis_sentinels, ",")
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: redis_master,
SentinelAddrs: sentinelAddrs,
Password: redis_password,
DB: 0,
})
redisClient = rdb
rdb.Ping(ctx)
http.HandleFunc("/", HandleGetVideos)
http.HandleFunc("/update", HandleUpdateVideos)
http.ListenAndServe(":80", nil)
}
func HandleGetVideos(w http.ResponseWriter, r *http.Request){
id, ok := r.URL.Query()["id"]
if ok {
videoID := id[0]
video := getVideo(videoID)
if video.Id == "" { //video not found, or empty ID
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("{}"))
return
}
videoBytes, err := json.Marshal(video)
if err != nil {
panic(err)
}
w.Write(videoBytes)
return
}
videos := getVideos()
videoBytes, err := json.Marshal(videos)
if err != nil {
panic(err)
}
w.Write(videoBytes)
}
func HandleUpdateVideos(w http.ResponseWriter, r *http.Request){
if r.Method == "POST" {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
_, ok := r.URL.Query()["id"]
if ok {
var video video
err = json.Unmarshal(body, &video)
if err != nil {
w.WriteHeader(400)
fmt.Fprintf(w, "Bad request")
}
saveVideo(video)
return
}
var videos []video
err = json.Unmarshal(body, &videos)
if err != nil {
w.WriteHeader(400)
fmt.Fprintf(w, "Bad request")
}
saveVideos(videos)
return
} else {
w.WriteHeader(405)
fmt.Fprintf(w, "Method not Supported!")
}
}

View File

@ -0,0 +1,64 @@
package main
import (
"encoding/json"
"github.com/go-redis/redis/v8"
)
type video struct {
Id string
Title string
Description string
Imageurl string
Url string
}
func getVideos()(videos []video){
keys, err := redisClient.Keys(ctx,"*").Result()
if err != nil {
panic(err)
}
for _, key := range keys {
video := getVideo(key)
videos = append(videos, video)
}
return videos
}
func getVideo(id string)(video video) {
value, err := redisClient.Get(ctx, id).Result()
if err != nil {
panic(err)
}
if err != redis.Nil {
err = json.Unmarshal([]byte(value), &video)
}
return video
}
func saveVideo(video video)(){
videoBytes, err := json.Marshal(video)
if err != nil {
panic(err)
}
err = redisClient.Set(ctx, video.Id, videoBytes, 0).Err()
if err != nil {
panic(err)
}
}
func saveVideos(videos []video)(){
for _, video := range videos {
saveVideo(video)
}
}

View File

@ -0,0 +1,431 @@
# Introduction to Learning Go
<a href="https://youtu.be/jpKysZwllVw" title="golang-part-1"><img src="https://i.ytimg.com/vi/jpKysZwllVw/hqdefault.jpg" width="20%" alt="introduction to Go part 1" /></a>
Go can be downloaded from [golang.org](https://golang.org/doc/install) <br/>
Test your `go` installation:
```
go version
```
# Run Go in Docker
We can also run go in a small docker container: <br/>
```
cd golang\introduction
docker build --target dev . -t go
docker run -it -v ${PWD}:/work go sh
go version
```
# Code Structure
https://golang.org/doc/code.html
* Package:
- Source files in same directory that are compiled together
- Have visibility on all source files in the same package
* Modules:
- Collection of packages that are released together
Our repository can contain one or more go modules, but usually 1.
- At the root of the repo
`go.mod` Declares module path + import path for packages. (Where to download them)
- When we write our own program, we can define a module path
- This allows us to publish our code (if we want), so others can download it
- The module path could be something like `github.com/google/go-cmp`
- Makes it easy for other programs to consume our module
# Our first Program
* Create a folder containing our application
```
mkdir app
```
* Define a module path (github.com/docker-development-youtube-series/golang/introdouction/app)
```
# change directory to your application source code
cd app
# create a go module file
go mod init github.com/docker-development-youtube-series/golang/introdouction/app
```
* Create basic source code
In the `app` folder, create a program called `app.go`
Paste the following content into it.
```
package main
import "fmt"
func main() {
fmt.Println("Hello, world.")
}
```
* Run your application code
You can run your application
```
go run app.go
```
# Building our Program
Build your application into a static binary: <br/>
```
go build
```
This will produce a compiled program called `app`
You can run this program easily:
```
./app
```
# Install your application (optional)
"This command builds the app command, producing an executable binary. <br/>
It then installs that binary as $HOME/go/bin/app (or, under Windows, %USERPROFILE%\go\bin\app.exe)"
```
go install github.com/docker-development-youtube-series/golang/introdouction/app
```
# The Code
## Functions
In the video we cover writing functions. </br>
It allows us to execute a block of code <br/>
You want to give your function a single purpose <br/>
Functions can have an input and return an output <br/>
Well thought out functions makes it easier to write tests <br/>
Instead of doing a boring `x + y` function that adds two numbers, let's do something a little
more realistic but still basic:
```
// This function returns some data
// The data could be coming from a database, or a file.
// The person calling the function should not care
// Since the function does not leak its Data provider
func getData(inputs)(outputs){
}
// functions can take multiple inputs, and return multiple outputs
// lets say we have 1) customers and 2) the cities they are from
// we may want to 1) get a list of customers and 2) get a list of cities
// therefore we have 2 types of data, 1) customers 2) cities
// let's improve our function so its gets data based on the type
func getData(customerId int) (customer string) {
}
```
## Variables
To hold data in programming languages, we use variables. <br/>
Variables take up space in memory, so we want to keep it minimal. <br/>
Let's declare variables in our function
```
func getData(customerId int) (customer string) {
var firstName = "Marcel"
lastName := "Dempers"
fullName := firstName + " " + lastName
return fullName
//or we can return the computation instead of adding another variable!
return firstName + " " + lastName
//or we dont even need to declare variables :)
return "Marcel Dempers"
}
```
## Control Flows (if\else)
You can see we're not using the `customerId` input in our function. <br/>
Let's use it! <br/>
Control flows allow us to add "rules" to our code. </br>
"If this is the case, then do that, else do something else".
So let's say we have a customer ID 1 coming in, we may only want to
return our customer if it matches the `customerId`
```
func getData(customerId int) (customer string) {
if customerId == 1 {
return "Marcel Dempers"
} else if customerId == 2 {
return "Bob Smith"
} else {
return ""
}
}
```
Let's invoke our function :
```
//in the main() function
//get our customer
customer := getData(1)
fmt.Println(customer)
//get the wrong customer
customer := getData(3)
fmt.Println(customer)
```
## Arrays
At the moment, we can only return 1 customer at a time on our function. <br/>
Realistically we need the ability to return more data, not just a single customer. <br/>
Arrays allow us to make a collection of variables of the same type. <br/>
We can now return a list of customers! <br/>
Let's change our function to get an array of customers!
```
func getData() (customers [2]string) {
//create 1 record
customer := "Marcel Dempers"
//assign our customer to the array
customers[0] = customer
//OR we can assign it like this
customers[1] = "Bob Smith"
//send it back to the caller
return customers
}
```
Now we also have to change our calling function to expect an array:
```
customers := getData()
fmt.Println(customers)
```
## Slices
Since arrays are fixed size, Slices are a dynamically-sized view into arrays.
Let's create a slice instead of array so we can add customers dynamically!
```
func getData() (customers []string) {
//initialise our slice of type string
customers = []string{ "Marcel Dempers", "Bob Smith", "John Smith"}
//add more legendary customers dynamically
customers = append(customers, "Ben Spain")
customers = append(customers, "Aleem Janmohamed")
customers = append(customers, "Jamie le Notre")
customers = append(customers, "Victor Savkov")
customers = append(customers, "P The Admin")
customers = append(customers, "Adrian Oprea")
customers = append(customers, "Jonathan D")
//send it back to the caller
return customers
}
```
## Loops
Loops are used to iterate over collections, lists, arrays etc. <br/>
Let's say we need to loop through our customers
In the `main()` function, we can grab the list of customers and loop them.
In this demo, we'll cover a basic for loop, but there are several approaches to writing loops.
```
//loop forever
for {
//any code in here will run forever!
fmt.Println("Infinite Loop 1")
time.Sleep(time.Second)
//unless we break out the loop like this
break
}
//loop for x number of loops
for x := 0; x < 10; x++ {
//any code in here will run 10 times! (unless we break!)
fmt.Println(customers[x])
}
//loop for ALL our customer
for x, customer := range customers {
//we can access the "customer" variable in this approach
customer = customers[x]
fmt.Println(customer)
//OR
//we can use the supplied customer from the loop
// and silence the x variable, replace it with a _ character
fmt.Println(customer)
}
```
## Structs
So far so good, however, customer data is not useful as strings. <br/>
Customers can have a firstname, lastname, and more properties. <br/>
For this purpose we'd like to group some variables into a single variable. <br/>
This is what `struct` allows us to do. <br/>
Let's create a `struct` for our customer
Let's create a new `go` file called `customers.go`
```
package main
Customer struct {
FirstName string
LastName string
FullName string
}
```
Let's put it all together:
In `customers.go`, let's create a function to get customers
```
func GetCustomers()(customers []Customer) {
//we can declare customers like this:
marcel := Customer{ FirstName: "Marcel", LastName: "Dempers" }
customers = append(customers,
Customer{ FirstName: "Marcel", LastName: "Dempers" },
Customer{ FirstName: "Ben", LastName: "Spain" },
Customer{ FirstName: "Aleem", LastName: "Janmohamed" },
Customer{ FirstName: "Jamie", LastName: "le Notre" },
Customer{ FirstName: "Victor", LastName: "Savkov" },
Customer{ FirstName: "P", LastName: "The Admin" },
Customer{ FirstName: "Adrian", LastName: "Oprea" },
Customer{ FirstName: "Jonathan", LastName: "D" },
)
return customers
}
```
In `main()` we can now call our shiny new function
```
customers := GetCustomers()
for _, customer := range customers {
//we can access the "customer" variable in this approach
fmt.Println(customer)
}
```
# Docker
For our dev environment, we have a simple image using `go` <br/>
We also set a work directory and alias the target as `dev`
This means we can use this container layer as a development environment. <br/>
Later down the track we can add debuggers in here for example. <br/>
Checkout my debugging video for go: https://youtu.be/kToyI16IFxs <br/>
## Development environment
```
FROM golang:1.15 as dev
WORKDIR /work
```
## Building our code
```
FROM golang:1.15 as build
WORKDIR /app
COPY ./app/* /app/
RUN go build -o app
```
## The Runtime
```
FROM alpine as runtime
COPY --from=build /app/app /
CMD ./app
```
## Building the Container
```
docker build . -t customer-app
```
## Running the Container
```
docker run customer-app
```

View File

@ -0,0 +1,3 @@
{
"api_key" : "somesecretgoeshere"
}

58
golang/src/main.go Normal file
View File

@ -0,0 +1,58 @@
package main
import (
"fmt" //to print messages to stdout
"log" //logging :)
//our web server that will host the mock
"github.com/buaazp/fasthttprouter"
"github.com/valyala/fasthttp"
"os"
"io/ioutil"
)
var configuration []byte
var secret []byte
func Response(ctx *fasthttp.RequestCtx) {
fmt.Fprintf(ctx, "Hello")
}
func Status(ctx *fasthttp.RequestCtx) {
fmt.Fprintf(ctx, "ok")
}
func ReadConfig(){
fmt.Println("reading config...")
config, e := ioutil.ReadFile("/configs/config.json")
if e != nil {
fmt.Printf("Error reading config file: %v\n", e)
os.Exit(1)
}
configuration = config
fmt.Println("config loaded!")
}
func ReadSecret(){
fmt.Println("reading secret...")
s, e := ioutil.ReadFile("/secrets/secret.json")
if e != nil {
fmt.Printf("Error reading secret file: %v\n", e)
os.Exit(1)
}
secret = s
fmt.Println("secret loaded!")
}
func main() {
fmt.Println("starting...")
ReadConfig()
ReadSecret()
router := fasthttprouter.New()
router.GET("/", Response)
router.GET("/status", Status)
log.Fatal(fasthttp.ListenAndServe(":5000", router.Handler))
}

View File

@ -0,0 +1,11 @@
global:
datacenter: vault-kubernetes-guide
client:
enabled: true
server:
replicas: 1
bootstrapExpect: 1
disruptionBudget:
maxUnavailable: 0

View File

@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: basic-secret
labels:
app: basic-secret
spec:
selector:
matchLabels:
app: basic-secret
replicas: 1
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/tls-skip-verify: "true"
vault.hashicorp.com/agent-inject-secret-helloworld: "secret/basic-secret/helloworld"
vault.hashicorp.com/agent-inject-template-helloworld: |
{{- with secret "secret/basic-secret/helloworld" -}}
{
"username" : "{{ .Data.username }}",
"password" : "{{ .Data.password }}"
}
{{- end }}
vault.hashicorp.com/role: "basic-secret-role"
labels:
app: basic-secret
spec:
serviceAccountName: basic-secret
containers:
- name: app
image: jweissig/app:0.0.1
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: basic-secret
labels:
app: basic-secret

View File

@ -0,0 +1,52 @@
# Basic Secret Injection
In order for us to start using secrets in vault, we need to setup a policy.
```
#Create a role for our app
kubectl -n vault exec -it vault-0 -- sh
vault write auth/kubernetes/role/basic-secret-role \
bound_service_account_names=basic-secret \
bound_service_account_namespaces=example-app \
policies=basic-secret-policy \
ttl=1h
```
The above maps our Kubernetes service account, used by our pod, to a policy.
Now lets create the policy to map our service account to a bunch of secrets
```
kubectl -n vault exec -it vault-0 -- sh
cat <<EOF > /home/vault/app-policy.hcl
path "secret/basic-secret/*" {
capabilities = ["read"]
}
EOF
vault policy write basic-secret-policy /home/vault/app-policy.hcl
```
Now our service account for our pod can access all secrets under `secret/basic-secret/*`
Lets create some secrets.
```
kubectl -n vault exec -it vault-0 -- sh
vault secrets enable -path=secret/ kv
vault kv put secret/basic-secret/helloworld username=dbuser password=sUp3rS3cUr3P@ssw0rd
```
Lets deploy our app and see if it works:
```
kubectl create ns example-app
kubectl -n example-app apply -f ./example-apps/basic-secret/deployment.yaml
kubectl -n example-app get pods
```
Once the pod is ready, the secret is injected into the pod at the following location:
```
kubectl -n example-app exec <pod-name> -- sh -c "cat /vault/secrets/helloworld"
```

View File

@ -0,0 +1,7 @@
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker

View File

@ -0,0 +1,626 @@
---
# Source: consul/templates/server-disruptionbudget.yaml
# PodDisruptionBudget to prevent degrading the server cluster through
# voluntary cluster changes.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: consul-consul-server
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: server
spec:
maxUnavailable: 0
selector:
matchLabels:
app: consul
release: "consul"
component: server
---
# Source: consul/templates/client-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: consul-consul-client
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: client
---
# Source: consul/templates/server-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: consul-consul-server
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: server
---
# Source: consul/templates/client-config-configmap.yaml
# ConfigMap with extra configuration specified directly to the chart
# for client agents only.
apiVersion: v1
kind: ConfigMap
metadata:
name: consul-consul-client-config
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: client
data:
extra-from-values.json: |-
{}
central-config.json: |-
{
"enable_central_service_config": true
}
---
# Source: consul/templates/server-config-configmap.yaml
# StatefulSet to run the actual Consul server cluster.
apiVersion: v1
kind: ConfigMap
metadata:
name: consul-consul-server-config
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: server
data:
extra-from-values.json: |-
{}
central-config.json: |-
{
"enable_central_service_config": true
}
---
# Source: consul/templates/client-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: consul-consul-client
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: client
rules: []
---
# Source: consul/templates/server-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: consul-consul-server
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: server
rules: []
---
# Source: consul/templates/client-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: consul-consul-client
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: client
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: consul-consul-client
subjects:
- kind: ServiceAccount
name: consul-consul-client
---
# Source: consul/templates/server-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: consul-consul-server
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: consul-consul-server
subjects:
- kind: ServiceAccount
name: consul-consul-server
---
# Source: consul/templates/dns-service.yaml
# Service for Consul DNS.
apiVersion: v1
kind: Service
metadata:
name: consul-consul-dns
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: dns
spec:
type: ClusterIP
ports:
- name: dns-tcp
port: 53
protocol: "TCP"
targetPort: dns-tcp
- name: dns-udp
port: 53
protocol: "UDP"
targetPort: dns-udp
selector:
app: consul
release: "consul"
hasDNS: "true"
---
# Source: consul/templates/server-service.yaml
# Headless service for Consul server DNS entries. This service should only
# point to Consul servers. For access to an agent, one should assume that
# the agent is installed locally on the node and the NODE_IP should be used.
# If the node can't run a Consul agent, then this service can be used to
# communicate directly to a server agent.
apiVersion: v1
kind: Service
metadata:
name: consul-consul-server
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: server
annotations:
# This must be set in addition to publishNotReadyAddresses due
# to an open issue where it may not work:
# https://github.com/kubernetes/kubernetes/issues/58662
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
clusterIP: None
# We want the servers to become available even if they're not ready
# since this DNS is also used for join operations.
publishNotReadyAddresses: true
ports:
- name: http
port: 8500
targetPort: 8500
- name: serflan-tcp
protocol: "TCP"
port: 8301
targetPort: 8301
- name: serflan-udp
protocol: "UDP"
port: 8301
targetPort: 8301
- name: serfwan-tcp
protocol: "TCP"
port: 8302
targetPort: 8302
- name: serfwan-udp
protocol: "UDP"
port: 8302
targetPort: 8302
- name: server
port: 8300
targetPort: 8300
- name: dns-tcp
protocol: "TCP"
port: 8600
targetPort: dns-tcp
- name: dns-udp
protocol: "UDP"
port: 8600
targetPort: dns-udp
selector:
app: consul
release: "consul"
component: server
---
# Source: consul/templates/ui-service.yaml
# UI Service for Consul Server
apiVersion: v1
kind: Service
metadata:
name: consul-consul-ui
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: ui
spec:
selector:
app: consul
release: "consul"
component: server
ports:
- name: http
port: 80
targetPort: 8500
---
# Source: consul/templates/client-daemonset.yaml
# DaemonSet to run the Consul clients on every node.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: consul-consul
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: client
spec:
selector:
matchLabels:
app: consul
chart: consul-helm
release: consul
component: client
hasDNS: "true"
template:
metadata:
labels:
app: consul
chart: consul-helm
release: consul
component: client
hasDNS: "true"
annotations:
"consul.hashicorp.com/connect-inject": "false"
"consul.hashicorp.com/config-checksum": 797b3593a73b78fc74f3b1e3b978107b3022d4649802185631f959f000234331
spec:
terminationGracePeriodSeconds: 10
serviceAccountName: consul-consul-client
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 100
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: consul-consul-client-config
containers:
- name: consul
image: "hashicorp/consul:1.11.1"
env:
- name: ADVERTISE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: NODE
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: CONSUL_DISABLE_PERM_MGMT
value: "true"
command:
- "/bin/sh"
- "-ec"
- |
CONSUL_FULLNAME="consul-consul"
mkdir -p /consul/extra-config
cp /consul/config/extra-from-values.json /consul/extra-config/extra-from-values.json
[ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /consul/extra-config/extra-from-values.json
[ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /consul/extra-config/extra-from-values.json
[ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /consul/extra-config/extra-from-values.json
exec /usr/local/bin/docker-entrypoint.sh consul agent \
-node="${NODE}" \
-advertise="${ADVERTISE_IP}" \
-bind=0.0.0.0 \
-client=0.0.0.0 \
-node-meta=host-ip:${HOST_IP} \
-node-meta=pod-name:${HOSTNAME} \
-hcl='leave_on_terminate = true' \
-hcl='ports { grpc = 8502 }' \
-config-dir=/consul/config \
-datacenter=vault-kubernetes-guide \
-data-dir=/consul/data \
-retry-join="${CONSUL_FULLNAME}-server-0.${CONSUL_FULLNAME}-server.${NAMESPACE}.svc:8301" \
-config-file=/consul/extra-config/extra-from-values.json \
-domain=consul
volumeMounts:
- name: data
mountPath: /consul/data
- name: config
mountPath: /consul/config
ports:
- containerPort: 8500
hostPort: 8500
name: http
- containerPort: 8502
hostPort: 8502
name: grpc
- containerPort: 8301
protocol: "TCP"
name: serflan-tcp
- containerPort: 8301
protocol: "UDP"
name: serflan-udp
- containerPort: 8600
name: dns-tcp
protocol: "TCP"
- containerPort: 8600
name: dns-udp
protocol: "UDP"
readinessProbe:
# NOTE(mitchellh): when our HTTP status endpoints support the
# proper status codes, we should switch to that. This is temporary.
exec:
command:
- "/bin/sh"
- "-ec"
- |
curl http://127.0.0.1:8500/v1/status/leader \
2>/dev/null | grep -E '".+"'
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi
securityContext:
null
---
# Source: consul/templates/server-statefulset.yaml
# StatefulSet to run the actual Consul server cluster.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: consul-consul-server
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
component: server
spec:
serviceName: consul-consul-server
podManagementPolicy: Parallel
replicas: 1
selector:
matchLabels:
app: consul
chart: consul-helm
release: consul
component: server
hasDNS: "true"
template:
metadata:
labels:
app: consul
chart: consul-helm
release: consul
component: server
hasDNS: "true"
annotations:
"consul.hashicorp.com/connect-inject": "false"
"consul.hashicorp.com/config-checksum": c9b100f895d5bda6a5c8bbebac73e1ab5bdc4cad06b04e72eb1b620677bfe41d
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: consul
release: "consul"
component: server
topologyKey: kubernetes.io/hostname
terminationGracePeriodSeconds: 30
serviceAccountName: consul-consul-server
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 100
volumes:
- name: config
configMap:
name: consul-consul-server-config
containers:
- name: consul
image: "hashicorp/consul:1.11.1"
env:
- name: ADVERTISE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: CONSUL_DISABLE_PERM_MGMT
value: "true"
command:
- "/bin/sh"
- "-ec"
- |
CONSUL_FULLNAME="consul-consul"
mkdir -p /consul/extra-config
cp /consul/config/extra-from-values.json /consul/extra-config/extra-from-values.json
[ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /consul/extra-config/extra-from-values.json
[ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /consul/extra-config/extra-from-values.json
[ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /consul/extra-config/extra-from-values.json
exec /usr/local/bin/docker-entrypoint.sh consul agent \
-advertise="${ADVERTISE_IP}" \
-bind=0.0.0.0 \
-bootstrap-expect=1 \
-client=0.0.0.0 \
-config-dir=/consul/config \
-datacenter=vault-kubernetes-guide \
-data-dir=/consul/data \
-domain=consul \
-hcl="connect { enabled = true }" \
-ui \
-retry-join="${CONSUL_FULLNAME}-server-0.${CONSUL_FULLNAME}-server.${NAMESPACE}.svc:8301" \
-serf-lan-port=8301 \
-config-file=/consul/extra-config/extra-from-values.json \
-server
volumeMounts:
- name: data-vault
mountPath: /consul/data
- name: config
mountPath: /consul/config
ports:
- name: http
containerPort: 8500
- name: serflan-tcp
containerPort: 8301
protocol: "TCP"
- name: serflan-udp
containerPort: 8301
protocol: "UDP"
- name: serfwan-tcp
containerPort: 8302
protocol: "TCP"
- name: serfwan-udp
containerPort: 8302
protocol: "UDP"
- name: server
containerPort: 8300
- name: dns-tcp
containerPort: 8600
protocol: "TCP"
- name: dns-udp
containerPort: 8600
protocol: "UDP"
readinessProbe:
# NOTE(mitchellh): when our HTTP status endpoints support the
# proper status codes, we should switch to that. This is temporary.
exec:
command:
- "/bin/sh"
- "-ec"
- |
curl http://127.0.0.1:8500/v1/status/leader \
2>/dev/null | grep -E '".+"'
failureThreshold: 2
initialDelaySeconds: 5
periodSeconds: 3
successThreshold: 1
timeoutSeconds: 5
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi
securityContext:
null
volumeClaimTemplates:
- metadata:
name: data-vault
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
# Source: consul/templates/tests/test-runner.yaml
apiVersion: v1
kind: Pod
metadata:
name: "consul-consul-test"
namespace: vault
labels:
app: consul
chart: consul-helm
heritage: Helm
release: consul
annotations:
"helm.sh/hook": test-success
spec:
containers:
- name: consul-test
image: "hashicorp/consul:1.11.1"
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: CONSUL_HTTP_ADDR
value: http://$(HOST_IP):8500
command:
- "/bin/sh"
- "-ec"
- |
consul members | tee members.txt
if [ $(grep -c consul-server members.txt) != $(grep consul-server members.txt | grep -c alive) ]
then
echo "Failed because not all consul servers are available"
exit 1
fi
restartPolicy: Never

View File

@ -0,0 +1,710 @@
---
# Source: vault/templates/server-disruptionbudget.yaml
# PodDisruptionBudget to prevent degrading the server cluster through
# voluntary cluster changes.
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: vault
namespace: vault
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
spec:
maxUnavailable: 1
selector:
matchLabels:
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
component: server
---
# Source: vault/templates/injector-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-agent-injector
namespace: vault
labels:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
---
# Source: vault/templates/server-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault
namespace: vault
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
---
# Source: vault/templates/server-config-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: vault-config
namespace: vault
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
data:
extraconfig-from-values.hcl: |-
disable_mlock = true
ui = true
listener "tcp" {
tls_disable = 0
address = "0.0.0.0:8200"
tls_cert_file = "/vault/userconfig/tls-server/tls.crt"
tls_key_file = "/vault/userconfig/tls-server/tls.key"
tls_min_version = "tls12"
}
storage "consul" {
path = "vault"
address = "consul-consul-server:8500"
}
---
# Source: vault/templates/injector-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: vault-agent-injector-clusterrole
labels:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
rules:
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["mutatingwebhookconfigurations"]
verbs:
- "get"
- "list"
- "watch"
- "patch"
---
# Source: vault/templates/injector-clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-agent-injector-binding
labels:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: vault-agent-injector-clusterrole
subjects:
- kind: ServiceAccount
name: vault-agent-injector
namespace: vault
---
# Source: vault/templates/server-clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-server-binding
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault
namespace: vault
---
# Source: vault/templates/server-discovery-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: vault
name: vault-discovery-role
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list", "update", "patch"]
---
# Source: vault/templates/server-discovery-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: vault-discovery-rolebinding
namespace: vault
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: vault-discovery-role
subjects:
- kind: ServiceAccount
name: vault
namespace: vault
---
# Source: vault/templates/injector-service.yaml
apiVersion: v1
kind: Service
metadata:
name: vault-agent-injector-svc
namespace: vault
labels:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
spec:
ports:
- name: https
port: 443
targetPort: 8080
selector:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: vault
component: webhook
---
# Source: vault/templates/server-ha-active-service.yaml
# Service for active Vault pod
apiVersion: v1
kind: Service
metadata:
name: vault-active
namespace: vault
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
annotations:
spec:
publishNotReadyAddresses: true
ports:
- name: https
port: 8200
targetPort: 8200
- name: https-internal
port: 8201
targetPort: 8201
selector:
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
component: server
vault-active: "true"
---
# Source: vault/templates/server-ha-standby-service.yaml
# Service for standby Vault pod
apiVersion: v1
kind: Service
metadata:
name: vault-standby
namespace: vault
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
annotations:
spec:
publishNotReadyAddresses: true
ports:
- name: https
port: 8200
targetPort: 8200
- name: https-internal
port: 8201
targetPort: 8201
selector:
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
component: server
vault-active: "false"
---
# Source: vault/templates/server-headless-service.yaml
# Service for Vault cluster
apiVersion: v1
kind: Service
metadata:
name: vault-internal
namespace: vault
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
annotations:
spec:
clusterIP: None
publishNotReadyAddresses: true
ports:
- name: "https"
port: 8200
targetPort: 8200
- name: https-internal
port: 8201
targetPort: 8201
selector:
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
component: server
---
# Source: vault/templates/server-service.yaml
# Service for Vault cluster
apiVersion: v1
kind: Service
metadata:
name: vault
namespace: vault
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
annotations:
spec:
# We want the servers to become available even if they're not ready
# since this DNS is also used for join operations.
publishNotReadyAddresses: true
ports:
- name: https
port: 8200
targetPort: 8200
- name: https-internal
port: 8201
targetPort: 8201
selector:
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
component: server
---
# Source: vault/templates/ui-service.yaml
apiVersion: v1
kind: Service
metadata:
name: vault-ui
namespace: vault
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault-ui
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
spec:
selector:
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
component: server
publishNotReadyAddresses: true
ports:
- name: https
port: 8200
targetPort: 8200
type: ClusterIP
---
# Source: vault/templates/injector-deployment.yaml
# Deployment for the injector
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault-agent-injector
namespace: vault
labels:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
component: webhook
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: vault
component: webhook
template:
metadata:
labels:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: vault
component: webhook
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: "vault"
component: webhook
topologyKey: kubernetes.io/hostname
serviceAccountName: "vault-agent-injector"
hostNetwork: false
securityContext:
runAsNonRoot: true
runAsGroup: 1000
runAsUser: 100
containers:
- name: sidecar-injector
resources:
limits:
cpu: 250m
memory: 256Mi
requests:
cpu: 50m
memory: 50Mi
image: "hashicorp/vault-k8s:0.14.1"
imagePullPolicy: "IfNotPresent"
securityContext:
allowPrivilegeEscalation: false
env:
- name: AGENT_INJECT_LISTEN
value: :8080
- name: AGENT_INJECT_LOG_LEVEL
value: info
- name: AGENT_INJECT_VAULT_ADDR
value: https://vault.vault.svc:8200
- name: AGENT_INJECT_VAULT_AUTH_PATH
value: auth/kubernetes
- name: AGENT_INJECT_VAULT_IMAGE
value: "hashicorp/vault:1.9.2"
- name: AGENT_INJECT_TLS_AUTO
value: vault-agent-injector-cfg
- name: AGENT_INJECT_TLS_AUTO_HOSTS
value: vault-agent-injector-svc,vault-agent-injector-svc.vault,vault-agent-injector-svc.vault.svc
- name: AGENT_INJECT_LOG_FORMAT
value: standard
- name: AGENT_INJECT_REVOKE_ON_SHUTDOWN
value: "false"
- name: AGENT_INJECT_CPU_REQUEST
value: "250m"
- name: AGENT_INJECT_CPU_LIMIT
value: "500m"
- name: AGENT_INJECT_MEM_REQUEST
value: "64Mi"
- name: AGENT_INJECT_MEM_LIMIT
value: "128Mi"
- name: AGENT_INJECT_DEFAULT_TEMPLATE
value: "map"
- name: AGENT_INJECT_TEMPLATE_CONFIG_EXIT_ON_RETRY_FAILURE
value: "true"
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
args:
- agent-inject
- 2>&1
livenessProbe:
httpGet:
path: /health/ready
port: 8080
scheme: HTTPS
failureThreshold: 2
initialDelaySeconds: 5
periodSeconds: 2
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /health/ready
port: 8080
scheme: HTTPS
failureThreshold: 2
initialDelaySeconds: 5
periodSeconds: 2
successThreshold: 1
timeoutSeconds: 5
---
# Source: vault/templates/server-statefulset.yaml
# StatefulSet to run the actual vault server cluster.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: vault
namespace: vault
labels:
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
spec:
serviceName: vault-internal
podManagementPolicy: Parallel
replicas: 3
updateStrategy:
type: OnDelete
selector:
matchLabels:
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
component: server
template:
metadata:
labels:
helm.sh/chart: vault-0.19.0
app.kubernetes.io/name: vault
app.kubernetes.io/instance: vault
component: server
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: vault
app.kubernetes.io/instance: "vault"
component: server
topologyKey: kubernetes.io/hostname
terminationGracePeriodSeconds: 10
serviceAccountName: vault
securityContext:
runAsNonRoot: true
runAsGroup: 1000
runAsUser: 100
fsGroup: 1000
volumes:
- name: config
configMap:
name: vault-config
- name: userconfig-tls-server
secret:
secretName: tls-server
defaultMode: 420
- name: userconfig-tls-ca
secret:
secretName: tls-ca
defaultMode: 420
- name: home
emptyDir: {}
containers:
- name: vault
resources:
limits:
cpu: 2000m
memory: 16Gi
requests:
cpu: 500m
memory: 50Mi
image: hashicorp/vault:1.9.2
imagePullPolicy: IfNotPresent
command:
- "/bin/sh"
- "-ec"
args:
- |
cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl;
[ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl;
[ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl;
[ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl;
[ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl;
[ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl;
[ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl;
/usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl
securityContext:
allowPrivilegeEscalation: false
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: VAULT_K8S_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: VAULT_K8S_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: VAULT_ADDR
value: "https://127.0.0.1:8200"
- name: VAULT_API_ADDR
value: "https://$(POD_IP):8200"
- name: SKIP_CHOWN
value: "true"
- name: SKIP_SETCAP
value: "true"
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: VAULT_CLUSTER_ADDR
value: "https://$(HOSTNAME).vault-internal:8201"
- name: HOME
value: "/home/vault"
- name: "VAULT_CACERT"
value: "/vault/userconfig/tls-ca/tls.crt"
volumeMounts:
- name: config
mountPath: /vault/config
- name: userconfig-tls-server
readOnly: true
mountPath: /vault/userconfig/tls-server
- name: userconfig-tls-ca
readOnly: true
mountPath: /vault/userconfig/tls-ca
- name: home
mountPath: /home/vault
ports:
- containerPort: 8200
name: https
- containerPort: 8201
name: https-internal
- containerPort: 8202
name: https-rep
readinessProbe:
httpGet:
path: "/v1/sys/health?standbyok=true&sealedcode=204&uninitcode=204"
port: 8200
scheme: HTTPS
failureThreshold: 2
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 3
livenessProbe:
httpGet:
path: "/v1/sys/health?standbyok=true"
port: 8200
scheme: HTTPS
failureThreshold: 2
initialDelaySeconds: 60
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 3
lifecycle:
# Vault container doesn't receive SIGTERM from Kubernetes
# and after the grace period ends, Kube sends SIGKILL. This
# causes issues with graceful shutdowns such as deregistering itself
# from Consul (zombie services).
preStop:
exec:
command: [
"/bin/sh", "-c",
# Adding a sleep here to give the pod eviction a
# chance to propagate, so requests will not be made
# to this pod while it's terminating
"sleep 5 && kill -SIGTERM $(pidof vault)",
]
volumeClaimTemplates:
---
# Source: vault/templates/injector-mutating-webhook.yaml
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: vault-agent-injector-cfg
labels:
app.kubernetes.io/name: vault-agent-injector
app.kubernetes.io/instance: vault
app.kubernetes.io/managed-by: Helm
webhooks:
- name: vault.hashicorp.com
sideEffects: None
admissionReviewVersions:
- "v1beta1"
- "v1"
clientConfig:
service:
name: vault-agent-injector-svc
namespace: vault
path: "/mutate"
caBundle: ""
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
failurePolicy: Ignore
---
# Source: vault/templates/tests/server-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: "vault-server-test"
namespace: vault
annotations:
"helm.sh/hook": test
spec:
containers:
- name: vault-server-test
image: hashicorp/vault:1.9.2
imagePullPolicy: IfNotPresent
env:
- name: VAULT_ADDR
value: https://vault.vault.svc:8200
- name: "VAULT_CACERT"
value: "/vault/userconfig/tls-ca/tls.crt"
command:
- /bin/sh
- -c
- |
echo "Checking for sealed info in 'vault status' output"
ATTEMPTS=10
n=0
until [ "$n" -ge $ATTEMPTS ]
do
echo "Attempt" $n...
vault status -format yaml | grep -E '^sealed: (true|false)' && break
n=$((n+1))
sleep 5
done
if [ $n -ge $ATTEMPTS ]; then
echo "timed out looking for sealed info in 'vault status' output"
exit 1
fi
exit 0
volumeMounts:
volumes:
restartPolicy: Never

View File

@ -0,0 +1,203 @@
# Hashicorp Vault Guide
<a href="https://youtu.be/2Owo4Ioo9tQ" title="hashicorp-vault"><img src="https://i.ytimg.com/vi/2Owo4Ioo9tQ/hqdefault.jpg" width="20%" alt="introduction hashicorp vault" /></a>
Requirements:
* Kubernetes 1.21
* Kind or Minikube
For this tutorial, I will be using Kubernetes 1.21.
If you are watching the old guide for Kubernetes 1.17, go [here](..\vault\readme.md)
Lets create a Kubernetes cluster to play with using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/)
```
cd hashicorp/vault-2022
kind create cluster --name vault --image kindest/node:v1.21.1 --config kind.yaml
```
Next up, I will be running a small container where I will be doing all the work from:
You can skip this part if you already have `kubectl` and `helm` on your machine.
```
docker run -it --rm --net host -v ${HOME}/.kube/:/root/.kube/ -v ${PWD}:/work -w /work alpine sh
```
Install `kubectl`
```
apk add --no-cache curl
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
chmod +x ./kubectl
mv ./kubectl /usr/local/bin/kubectl
```
Install `helm`
```
curl -LO https://get.helm.sh/helm-v3.7.2-linux-amd64.tar.gz
tar -C /tmp/ -zxvf helm-v3.7.2-linux-amd64.tar.gz
rm helm-v3.7.2-linux-amd64.tar.gz
mv /tmp/linux-amd64/helm /usr/local/bin/helm
chmod +x /usr/local/bin/helm
```
Now we have `helm` and `kubectl` and can access our `kind` cluster:
```
kubectl get nodes
NAME STATUS ROLES AGE VERSION
vault-control-plane Ready control-plane,master 37s v1.21.1
```
Let's add the Helm repositories, so we can access the Kubernetes manifests
```
helm repo add hashicorp https://helm.releases.hashicorp.com
```
## Storage: Consul
We will use a very basic Consul cluster for our Vault backend. </br>
Let's find what versions of Consul are available:
```
helm search repo hashicorp/consul --versions
```
We can use chart `0.39.0` which is the latest at the time of this demo
Let's create a manifests folder and grab the YAML:
```
mkdir manifests
helm template consul hashicorp/consul \
--namespace vault \
--version 0.39.0 \
-f consul-values.yaml \
> ./manifests/consul.yaml
```
Deploy the consul services:
```
kubectl create ns vault
kubectl -n vault apply -f ./manifests/consul.yaml
kubectl -n vault get pods
```
## TLS End to End Encryption
See steps in [./tls/ssl_generate_self_signed.md](./tls/ssl_generate_self_signed.md)
You'll need to generate TLS certs (or bring your own)
Remember not to check-in your TLS to GIT :)
Create the TLS secret
```
kubectl -n vault create secret tls tls-ca \
--cert ./tls/ca.pem \
--key ./tls/ca-key.pem
kubectl -n vault create secret tls tls-server \
--cert ./tls/vault.pem \
--key ./tls/vault-key.pem
```
## Generate Kubernetes Manifests
Let's find what versions of vault are available:
```
helm search repo hashicorp/vault --versions
```
In this demo I will use the `0.19.0` chart </br>
Let's firstly create a `values` file to customize vault.
Let's grab the manifests:
```
helm template vault hashicorp/vault \
--namespace vault \
--version 0.19.0 \
-f vault-values.yaml \
> ./manifests/vault.yaml
```
## Deployment
```
kubectl -n vault apply -f ./manifests/vault.yaml
kubectl -n vault get pods
```
## Initialising Vault
```
kubectl -n vault exec -it vault-0 -- sh
kubectl -n vault exec -it vault-1 -- sh
kubectl -n vault exec -it vault-2 -- sh
vault operator init
vault operator unseal
kubectl -n vault exec -it vault-0 -- vault status
kubectl -n vault exec -it vault-1 -- vault status
kubectl -n vault exec -it vault-2 -- vault status
```
## Web UI
Let's checkout the web UI:
```
kubectl -n vault get svc
kubectl -n vault port-forward svc/vault-ui 443:8200
```
Now we can access the web UI [here](https://localhost/)
## Enable Kubernetes Authentication
For the injector to be authorised to access vault, we need to enable K8s auth
```
kubectl -n vault exec -it vault-0 -- sh
vault login
vault auth enable kubernetes
vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host=https://${KUBERNETES_PORT_443_TCP_ADDR}:443 \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
issuer="https://kubernetes.default.svc.cluster.local"
exit
```
# Summary
So we have a vault, an injector, TLS end to end, stateful storage.
The injector can now inject secrets for pods from the vault.
Now we are ready to use the platform for different types of secrets:
## Secret Injection Guides
### Basic Secrets
Objective:
----------
* Let's create a basic secret in vault manually
* Application consumes the secret automatically
[Try it](./example-apps/basic-secret/readme.md)

View File

@ -0,0 +1,13 @@
{
"signing": {
"default": {
"expiry": "175200h"
},
"profiles": {
"default": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "175200h"
}
}
}
}

View File

@ -0,0 +1,18 @@
{
"hosts": [
"cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "AU",
"L": "Melbourne",
"O": "Example",
"OU": "CA",
"ST": "Example"
}
]
}

View File

@ -0,0 +1,40 @@
# Use CFSSL to generate certificates
More about [CFSSL here]("https://github.com/cloudflare/cfssl")
```
cd hashicorp\vault-2022\tls
docker run -it --rm -v ${PWD}:/work -w /work debian bash
apt-get update && apt-get install -y curl &&
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.1_linux_amd64 -o /usr/local/bin/cfssl && \
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_linux_amd64 -o /usr/local/bin/cfssljson && \
chmod +x /usr/local/bin/cfssl && \
chmod +x /usr/local/bin/cfssljson
#generate ca in /tmp
cfssl gencert -initca ca-csr.json | cfssljson -bare /tmp/ca
#generate certificate in /tmp
cfssl gencert \
-ca=/tmp/ca.pem \
-ca-key=/tmp/ca-key.pem \
-config=ca-config.json \
-hostname="vault,vault.vault.svc.cluster.local,vault.vault.svc,localhost,127.0.0.1" \
-profile=default \
ca-csr.json | cfssljson -bare /tmp/vault
```
view the files:
```
ls -l /tmp
```
access the files:
```
mv /tmp/* .
```

View File

@ -0,0 +1,85 @@
# Vault Helm Chart Value Overrides
global:
enabled: true
tlsDisable: false
injector:
enabled: true
# Use the Vault K8s Image https://github.com/hashicorp/vault-k8s/
image:
repository: "hashicorp/vault-k8s"
tag: "0.14.1"
resources:
requests:
memory: 50Mi
cpu: 50m
limits:
memory: 256Mi
cpu: 250m
server:
image:
repository: "hashicorp/vault"
tag: "1.9.2"
# These Resource Limits are in line with node requirements in the
# Vault Reference Architecture for a Small Cluster
resources:
requests:
memory: 50Mi
cpu: 500m
limits:
memory: 16Gi
cpu: 2000m
# For HA configuration and because we need to manually init the vault,
# we need to define custom readiness/liveness Probe settings
readinessProbe:
enabled: true
path: "/v1/sys/health?standbyok=true&sealedcode=204&uninitcode=204"
livenessProbe:
enabled: true
path: "/v1/sys/health?standbyok=true"
initialDelaySeconds: 60
# extraEnvironmentVars is a list of extra environment variables to set with the stateful set. These could be
# used to include variables required for auto-unseal.
extraEnvironmentVars:
VAULT_CACERT: /vault/userconfig/tls-ca/tls.crt
# extraVolumes is a list of extra volumes to mount. These will be exposed
# to Vault in the path `/vault/userconfig/<name>/`.
extraVolumes:
- type: secret
name: tls-server
- type: secret
name: tls-ca
standalone:
enabled: false
# Run Vault in "HA" mode.
ha:
enabled: true
replicas: 3
config: |
ui = true
listener "tcp" {
tls_disable = 0
address = "0.0.0.0:8200"
tls_cert_file = "/vault/userconfig/tls-server/tls.crt"
tls_key_file = "/vault/userconfig/tls-server/tls.key"
tls_min_version = "tls12"
}
storage "consul" {
path = "vault"
address = "consul-consul-server:8500"
}
# Vault UI
ui:
enabled: true
externalPort: 8200

View File

@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: basic-secret
labels:
app: basic-secret
spec:
selector:
matchLabels:
app: basic-secret
replicas: 1
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/tls-skip-verify: "true"
vault.hashicorp.com/agent-inject-secret-helloworld: "secret/basic-secret/helloworld"
vault.hashicorp.com/agent-inject-template-helloworld: |
{{- with secret "secret/basic-secret/helloworld" -}}
{
"username" : "{{ .Data.username }}",
"password" : "{{ .Data.password }}"
}
{{- end }}
vault.hashicorp.com/role: "basic-secret-role"
labels:
app: basic-secret
spec:
serviceAccountName: basic-secret
containers:
- name: app
image: jweissig/app:0.0.1
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: basic-secret
labels:
app: basic-secret

View File

@ -0,0 +1,50 @@
# Basic Secret Injection
In order for us to start using secrets in vault, we need to setup a policy.
```
#Create a role for our app
kubectl -n vault-example exec -it vault-example-0 sh
vault write auth/kubernetes/role/basic-secret-role \
bound_service_account_names=basic-secret \
bound_service_account_namespaces=vault-example \
policies=basic-secret-policy \
ttl=1h
```
The above maps our Kubernetes service account, used by our pod, to a policy.
Now lets create the policy to map our service account to a bunch of secrets
```
kubectl -n vault-example exec -it vault-example-0 sh
cat <<EOF > /home/vault/app-policy.hcl
path "secret/basic-secret/*" {
capabilities = ["read"]
}
EOF
vault policy write basic-secret-policy /home/vault/app-policy.hcl
exit
```
Now our service account for our pod can access all secrets under `secret/basic-secret/*`
Lets create some secrets.
```
kubectl -n vault-example exec -it vault-example-0 sh
vault secrets enable -path=secret/ kv
vault kv put secret/basic-secret/helloworld username=dbuser password=sUp3rS3cUr3P@ssw0rd
exit
```
Lets deploy our app and see if it works:
```
kubectl -n vault-example apply -f ./hashicorp/vault/example-apps/basic-secret/deployment.yaml
kubectl -n vault-example get pods
```

View File

@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: dynamic-postgres
labels:
app: dynamic-postgres
spec:
selector:
matchLabels:
app: dynamic-postgres
replicas: 1
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/tls-skip-verify: "true"
vault.hashicorp.com/agent-inject-secret-sql-role: "database/creds/sql-role"
vault.hashicorp.com/agent-inject-template-sql-role: |
{
{{- with secret "database/creds/sql-role" -}}
"db_connection": "host=postgres.postgress port=5432 user={{ .Data.username }} password={{ .Data.password }} dbname=postgresdb sslmode=disable"
{{- end }}
}
vault.hashicorp.com/role: "sql-role"
labels:
app: dynamic-postgres
spec:
serviceAccountName: dynamic-postgres
containers:
- name: app
image: jweissig/app:0.0.1
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: dynamic-postgres
labels:
app: dynamic-postgres

View File

@ -0,0 +1,33 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: pgadmin-config
labels:
app: pgadmin
data:
PGADMIN_DEFAULT_EMAIL: admin@admin.com
PGADMIN_DEFAULT_PASSWORD: admin123
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: pgadmin
spec:
selector:
matchLabels:
app: pgadmin
replicas: 1
template:
metadata:
labels:
app: pgadmin
spec:
containers:
- name: pgadmin
image: dpage/pgadmin4
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: pgadmin-config

Some files were not shown because too many files have changed in this diff Show More