{"id":41112167,"url":"https://github.com/titanlien/workshop","last_synced_at":"2026-01-22T16:05:07.744Z","repository":{"id":37722720,"uuid":"224019501","full_name":"titanlien/workshop","owner":"titanlien","description":"Work smarter, Life easier","archived":false,"fork":false,"pushed_at":"2025-09-03T08:53:20.000Z","size":17428,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-03T10:27:00.665Z","etag":null,"topics":["ansible","aws","docker","docker-container","fastapi","github-workflow","gitlab-ci","golang","helm","istio","jupyter-notebook","kubernetes","kustomize","python","terraform","workshop"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/titanlien.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-11-25T18:55:16.000Z","updated_at":"2025-09-03T08:53:24.000Z","dependencies_parsed_at":"2025-09-03T10:30:07.273Z","dependency_job_id":null,"html_url":"https://github.com/titanlien/workshop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/titanlien/workshop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/titanlien%2Fworkshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/titanlien%2Fworkshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/titanlien%2Fworkshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/titanlien%2Fworkshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/titanlien","download_url":"https://codeload.github.com/titanlien/workshop/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/titanlien%2Fworkshop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28666099,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T14:01:31.714Z","status":"ssl_error","status_checked_at":"2026-01-22T13:59:23.143Z","response_time":144,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","aws","docker","docker-container","fastapi","github-workflow","gitlab-ci","golang","helm","istio","jupyter-notebook","kubernetes","kustomize","python","terraform","workshop"],"created_at":"2026-01-22T16:04:41.231Z","updated_at":"2026-01-22T16:05:07.738Z","avatar_url":"https://github.com/titanlien.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Mao-Hsiang's GitHub stats](https://github-readme-stats.vercel.app/api?username=titanlien\u0026show_icons=true\u0026theme=ocean_dark)\n\n[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=titanlien\u0026hide=c,perl,html,java,objective-c,css\u0026theme=ocean_dark)](https://github.com/anuraghazra/github-readme-stats)\n# workshop\n# [Task 1](task01)\n## Terraform + AWS + Ansible\n* create a new VPC with CIDR 172.16.0.0\n* create two new subnets with CIDR 172.16.1.0/24 and 172.16.2.0/24 in two different availability zones\n* create 5 new ec2 instances based on Ubuntu 18.04 (bionic)\n* deploy the following Java application on these instances\n* create a load balancer for the Java application on port 80\n* setup route53 to host CNAME record of elb url\n---\n# [Task 2](task02)\n## Nginx + docker-compose + python\n* creates a new Docker container running nginx and proxies all requests on /\u003ccontainer_name\u003e to the appropriate container and port\n\t* there is only one nginx container running at all times\n\t* if the nginx container is down, it needs to be started\n\t* when a new application container is created the nginx configuration is updated to proxy requests to the new container\n* creates a new Docker container running Java and deploys demo-0.0.1-SNAPTSHOT.jar from the previous step\n\t* the Docker container publishes container 8080 on a free port between 8000 and 8200\n\t* the container name is a unique identifier\n\t* container is only created if it does not exist\n\t* there can be multiple Docker containers with different names running at the same time\n\n---\n# [Task 3](task03)\n# github workflow + kustomize + kubectl: deployment + svc\n* Implement a piece of software exposing a JSON document:\n```\n{\n\"id\": \"1\",\n\"message\": \"Hello world\"\n}\n```\nwhen visited with a HTTP client\n* Dockerize the application\n* Put the application to kind's Kubernetes\n* Create a second application, that utilizes the first and displays reversed message text\n* Deployment docker image with github workflow and login github registry with k8s secret config.\n* Update application with kubctl in script\n---\n# [Task 4](task04)\n# Python CLI\n* Please consider the work you submit here a small, but production-ready deliverable, in the sense that you are happy to ship such code, tests and documentation.\n* Write a Roman numeral converter that converts integer numbers into Roman numerals:\n\n```\nfunc(36)\n\nOutput: \"XXXVI\"\n```\n---\n# [Task 5](task05)\n# Go tutorial on jupyter notebook\n## Create html from ipynb\n```bash\njupyter nbconvert --execute task05/go_tuturial.ipynb --to html\n```\n[html preview](https://htmlpreview.github.io/?https://github.com/titanlien/workshop/blob/master/task05/go_tuturial.html)\n\n---\n# [Task 6](task06)\n## 6.1 Creare a ruby script\n### It shows top 10 process in swap and sorts output by KB. It will ignore Zero values\n\n\n## 6.2 Create a bach script\n\n```\nperforms occasional test queries to the hostname \"google.com\" to each of the DNS servers configured in /etc/resolv.conf\n```\n\n## 6.3 Fix a client certificateds issue in nginx configure.\n\n\n---\n# [Task 7](task07)\n### setup backend api to handle POST/PUT/PATCH and query value metadata by filtering metadata key\n\n* Technical scopes\n\n```\ngithub action\ndocker-compose\npytest\nfastapi\nminikube\nmake\nUsing helm to provision mongodb\n```\n\n---\n# [Task 8](task08)\n### Istio 1.6.8 present canary deploy on minikube\n\n---\n# [Task 9](https://gitlab.com/maohsiang_lien/blue-green)\n### CI/CD within helm bluegreen deploy and release tag on gitlab  pipelines\n[Gitlab pipeline](https://gitlab.com/maohsiang_lien/blue-green)\n\n---\n# [Task 10](task10)\n### build up a API to return GET request, and create a docker image on minikube, then create manifests to bring up the service and deployment.\n\n---\n# [Task 11](task11)\n\n### This program is going to be provided ​json​ lines as input in the ​stdin​, and should provide a ​json​ line output for each one — imagine this as a stream of events arriving at the authorizer.\n```\n$ cat operations\n{\"account\": {\"active-card\": true, \"available-limit\": 100}} {\"transaction\": {\"merchant\": \"Burger King\", \"amount\": 20, \"time\": \"2019-02-13T10:00:00.000Z\"}}\n{\"transaction\": {\"merchant\": \"Habbib's\", \"amount\": 90, \"time\": \"2019-02-13T11:00:00.000Z\"}}\n$ authorize \u003c operations\n{\"account\": {\"active-card\": true, \"available-limit\": 100}, \"violations\": []} {\"account\": {\"active-card\": true, \"available-limit\": 80}, \"violations\": []} {\"account\": {\"active-card\": true, \"available-limit\": 80}, \"violations\": [\"insufficient-limit\"]}\n```\n\n---\n# [Task 12](task12)\n### Provision kubeflow on minikube\n\n---\n# [Task 13](task13)\n### Use FastAPI and sqlalchemy to create shortened URL similar to https://goo.gl/\n\n---\n# [Task 14](task14)\n### Using terraform to create a private s3 bucket and a authorized user(IAM) to upload files. Using WhitelistIPs to grant user's exteral public IP address permission to access bucket.\n#### :warning: When you provision this task, you can not depend on STS token. Because there is a lack support of STS to create a new IAM user. :warning:\n```yml\n# sample for whitelist to access s3 bucket\nwhitelistIPs = [\"127.0.0.1/32\"]\n```\n\n```bash\n# get access_key from ssm\naws ssm get-parameter --name /system_user/backup-dev-uploader/access_key_id --with-decryption | jq .Parameter.Value\n\n# get secret_key from ssm\naws ssm get-parameter --name /system_user/backup-dev-uploader/secret_access_key --with-decryption | jq .Parameter.Value\n\n# terraform output\nbucket_domain_name = \"backup-dev-upload-task14.s3.amazonaws.com\"\n```\n---\n# [Task 15](task15)\n\nYou will find two applications: A Golang-based and a Java-based application. Both need to be\ncontainerized according to industry best practices. The Golang application needs to be compiled from\nsource, while the Java application is delivered as a pre-built Jar file, runnable using Java 11.\nBoth are providing an HTTP service, binding to all interfaces on port 8080, with the same endpoints:\n| Route | Description |\n|-----------|---------------------------------------------------------------|\n| / | A static site. Should *not* appear in the final setup |\n| /hotels | JSON object containing hotel search results |\n| /health | Exposes the health status of the application |\n| /ready | Readiness probe |\n| /metrics | Exposes Prometheus metrics of the application |\n\nYour challenge will be to provide a load balancer setup like the following:\n```bash\n                            +------------------\u003eJava app\n                            |\n                            |\n                            |\n                            30% of traffic\n                            |\n                            |\nUser +-------\u003e load balancer+\n                            |\n                            |\n                            70% of traffic\n                            |\n                            |\n                            |\n                            +------------------\u003eGo app\n```\n\nThe traffic distribution should be as follows: 70% of the requests are going to the application written in\nGolang, 30% of the requests are going to the application written in Java. Also, each HTTP response needs\nto carry a custom header, called x-trv-heritage which indicates the application that responded.\nYour implementation must be runnable on a machine using x86_64 CPU architecture and must be built\non top of Kubernetes.\nOne should be able to at least see that the traffic distribution works as expected in some form. As a\nbonus, you can try to show other metrics, like CPU usage, memory utilization, and latency as well to\ncompare the two services.\nYour implementation should:\n\n- Build both container images locally\n- Find a solution to make them available to a Kubernetes cluster\n- Do not push them to a public registry on the internet!\n- Setup an ingress solution of your choice\n- Deploy both workloads\n- Wait for the readiness of the system\n- Run 100 requests against / of the applications under test\n\n---\n# [Task 16](task16)\n```bash\nYou are tasked with the creation of a small infrastructure stack on\nAWS:\n* Deploy a redundant and scalable EKS cluster\n* Deploy on the cluster a simple Web Server application, exposing on\nthe public internet a simple home page with a custom message.\n* Provide basic monitoring for your infrastructure *[Optional Task]*\n* Increase the scalability of the stack *[Optional Task]*\n* Provide cost estimations *[Optional Task]*\n```\n\n### Functional\n#### EKS\n* `EKS` cluster must consist of at least 3 `Worker Nodes`\n* `Worker Nodes` should be distributed on at least `2 AZ`\n* `Worker Nodes` should be assigned to at least `2 Worker Groups`\n* You must run the latest version of `EKS-1.21`\n#### Web Server\n* Deploy, using `Helm`, a web server of your choice on the above\nrunning cluster.\n* The deployment should span the 2AZ where EKS nodes are spread, and\nhave a minimal redundancy.\n* Customise the web server in order to show a home page with custom\nmessage like \"Hello bot, welcome to your simple web page\"\n* Expose securely the page in order to be reached from public internet\n\n---\n# [Task 17](task17)\n* Present k8s with digitalocean provider, using resource digitalocean_kubernetes_cluster and digitalocean_kubernetes_node_pool.\n* Deploy bitnami/nginx-ingress-controller helm chart by using resource helm_release.\n\n---\n# [Task 18](task18)\n* A simple example to present how `helmfile` can depend on includeing vaules.yaml from different directory to share the common setting between landscape.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftitanlien%2Fworkshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftitanlien%2Fworkshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftitanlien%2Fworkshop/lists"}