├── .gitattributes ├── .gitignore ├── 01-introduction ├── .gitattributes ├── README.md ├── exercise │ ├── README.md │ ├── jdk-test-1 │ │ ├── .gitignore │ │ ├── .mvn │ │ │ └── wrapper │ │ │ │ ├── maven-wrapper.jar │ │ │ │ └── maven-wrapper.properties │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── demo │ │ │ │ │ └── DemoApplication.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ └── DemoApplicationTests.java │ ├── jdk-test-2 │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ ├── settings.gradle │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── demo │ │ │ │ │ └── DemoApplication.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ └── DemoApplicationTests.java │ └── kubernetes-cluster-setup │ │ ├── Tiltfile │ │ ├── echo-http-ingress-config.yaml │ │ ├── kind-cluster-config.yaml │ │ └── nginx-ingress-controller.yaml ├── lecture │ ├── .gitattributes │ └── 01-Introduction.pdf └── organizational-matters.pdf ├── 02-communication ├── examples │ ├── dropwizard │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── edu │ │ │ │ │ └── qaware │ │ │ │ │ └── cc │ │ │ │ │ └── zwitscher │ │ │ │ │ ├── api │ │ │ │ │ ├── entities │ │ │ │ │ │ └── ZwitscherMessage.java │ │ │ │ │ └── resources │ │ │ │ │ │ └── ZwitscherMessageResource.java │ │ │ │ │ └── core │ │ │ │ │ ├── ZwitscherApplication.java │ │ │ │ │ └── ZwitscherConfiguration.java │ │ │ └── resources │ │ │ │ ├── banner.txt │ │ │ │ └── zwitscher-config.yml │ │ │ └── test │ │ │ └── java │ │ │ └── edu │ │ │ └── qaware │ │ │ └── cc │ │ │ └── zwitscher │ │ │ └── TestApi.java │ ├── grpc │ │ ├── .mvn │ │ │ └── wrapper │ │ │ │ ├── maven-wrapper.jar │ │ │ │ └── maven-wrapper.properties │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── edu │ │ │ │ │ └── qaware │ │ │ │ │ └── cc │ │ │ │ │ └── grpc │ │ │ │ │ └── helloworld │ │ │ │ │ ├── HelloWorldClient.java │ │ │ │ │ └── HelloWorldServer.java │ │ │ └── proto │ │ │ │ └── helloworld.proto │ │ │ └── test │ │ │ └── sample_calls │ │ │ └── hello.http │ └── hazelcast │ │ ├── README.md │ │ ├── loesung │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── edu │ │ │ └── qaware │ │ │ └── cc │ │ │ └── minicloud │ │ │ └── Chatter.java │ │ └── vorlage │ │ ├── pom.xml │ │ └── src │ │ └── main │ │ └── java │ │ └── edu │ │ └── qaware │ │ └── cc │ │ └── minicloud │ │ └── Chatter.java ├── exercise │ ├── README.md │ ├── grpc │ │ ├── README.md │ │ └── solution │ │ │ ├── .editorconfig │ │ │ ├── .gitignore │ │ │ ├── .mvn │ │ │ └── wrapper │ │ │ │ ├── maven-wrapper.jar │ │ │ │ └── maven-wrapper.properties │ │ │ ├── README.md │ │ │ ├── mvnw │ │ │ ├── mvnw.cmd │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── de │ │ │ │ └── qaware │ │ │ │ └── edu │ │ │ │ └── cc │ │ │ │ └── bookservice │ │ │ │ ├── client │ │ │ │ └── Client.java │ │ │ │ └── server │ │ │ │ ├── BookServiceImpl.java │ │ │ │ ├── Server.java │ │ │ │ └── domain │ │ │ │ ├── Book.java │ │ │ │ ├── BookAlreadyExistsException.java │ │ │ │ ├── BookNotFoundException.java │ │ │ │ └── BookRepository.java │ │ │ └── proto │ │ │ └── book.proto │ └── rest │ │ ├── README.md │ │ └── solution │ │ ├── .gitignore │ │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ │ ├── Dockerfile │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── de │ │ │ │ └── qaware │ │ │ │ └── edu │ │ │ │ └── cc │ │ │ │ └── bookservice │ │ │ │ ├── Book.java │ │ │ │ ├── BookController.java │ │ │ │ ├── BookNotFoundException.java │ │ │ │ ├── BookNotFoundExceptionMapper.java │ │ │ │ ├── BookServiceApplication.java │ │ │ │ └── Bookshelf.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── de │ │ └── qaware │ │ └── edu │ │ └── cc │ │ └── bookservice │ │ └── BookServiceApplicationTests.java └── lecture │ ├── .gitattributes │ └── 02-Communication.pdf ├── 03-virtualization ├── exercise │ ├── 1-vagrant │ │ ├── Readme.md │ │ ├── solution │ │ │ └── Vagrantfile │ │ └── vagrant │ │ │ ├── default │ │ │ ├── index.html │ │ │ └── info.php │ └── 2-docker │ │ ├── README.md │ │ ├── content │ │ ├── .gitattributes │ │ ├── index.html │ │ └── logo.png │ │ └── solution │ │ ├── Dockerfile │ │ ├── nginx_mit_alpine.sh │ │ └── website.sh ├── lecture │ ├── .gitattributes │ └── 03_virtualization.pdf └── outdated │ └── docker-compose │ ├── README.md │ └── loesung │ ├── Dockerfile │ └── docker-compose.yml ├── 04-provisionierung ├── examples │ ├── README.md │ ├── asciinema.cast │ ├── clean.sh │ ├── packer.json │ ├── provision.sh │ └── welcome.txt ├── exercise │ └── README.md ├── lecture │ ├── .gitattributes │ └── 04 Provisioning.pdf └── solution │ ├── uebung-ansible │ ├── Dockerfile_Managed_Node │ ├── ansible │ │ └── hosts │ ├── docker-compose.yml │ ├── playbooks │ │ ├── index.html │ │ └── install-apache.yml │ └── ssh │ │ └── config │ ├── uebung-docker │ ├── Dockerfile │ ├── docker-compose.yml │ └── nginx-config │ │ └── index.html │ └── uebung-packer │ ├── index.html │ └── nginx.json ├── 05-iaas ├── exercise │ ├── README.md │ ├── aws-part-1 │ │ └── Readme.md │ ├── aws-part-2 │ │ ├── .gitignore │ │ ├── README.md │ │ ├── autoscaling.tf │ │ ├── init.sh │ │ ├── loadbalancer.tf │ │ ├── main.tf │ │ ├── network.tf │ │ └── output.tf │ ├── iaas-container │ │ ├── Dockerfile │ │ ├── aws-cli-pub.key │ │ └── terraform-cli-pub.key │ └── localstack │ │ ├── .gitignore │ │ ├── Readme.md │ │ ├── docker-compose.yml │ │ ├── provider.tf │ │ ├── src │ │ ├── lambda-publisher.py │ │ └── lambda-receiver.py │ │ └── volume │ │ └── .keep ├── lecture │ ├── .gitattributes │ └── 05 IaaS.pdf └── solution │ └── terraform │ ├── aws │ ├── .gitignore │ ├── autoscaling.tf │ ├── init.sh │ ├── loadbalancer.tf │ ├── main.tf │ ├── network.tf │ └── output.tf │ └── localstack │ ├── .gitignore │ ├── bucket.tf │ ├── output.tf │ ├── provider.tf │ ├── publisher.tf │ ├── receiver.tf │ ├── sqs.tf │ └── src │ ├── lambda-publisher.py │ └── lambda-receiver.py ├── 06-cloud-architecture ├── beispiele │ ├── README.md │ ├── loesung │ │ ├── fabio.properties │ │ ├── pom.xml │ │ └── src │ │ │ ├── infrastructure │ │ │ └── k8s │ │ │ │ ├── consul-rc.yaml │ │ │ │ └── consul-svc.yaml │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── edu │ │ │ │ │ └── qaware │ │ │ │ │ └── cc │ │ │ │ │ └── zwitscher │ │ │ │ │ ├── api │ │ │ │ │ ├── entities │ │ │ │ │ │ └── ZwitscherMessage.java │ │ │ │ │ └── resources │ │ │ │ │ │ └── ZwitscherMessageResource.java │ │ │ │ │ └── core │ │ │ │ │ ├── ZwitscherApplication.java │ │ │ │ │ └── ZwitscherConfiguration.java │ │ │ └── resources │ │ │ │ ├── banner.txt │ │ │ │ └── zwitscher-config.yml │ │ │ └── test │ │ │ └── java │ │ │ └── edu │ │ │ └── qaware │ │ │ └── cc │ │ │ └── zwitscher │ │ │ ├── TestApi.java │ │ │ └── TestConsul.java │ └── vorlage │ │ ├── pom.xml │ │ └── src │ │ └── main │ │ ├── infrastructure │ │ └── k8s │ │ │ ├── consul-rc.yaml │ │ │ └── consul-svc.yaml │ │ ├── java │ │ └── edu │ │ │ └── qaware │ │ │ └── cc │ │ │ └── zwitscher │ │ │ ├── api │ │ │ ├── entities │ │ │ │ └── ZwitscherMessage.java │ │ │ └── resources │ │ │ │ └── ZwitscherMessageResource.java │ │ │ └── core │ │ │ ├── ZwitscherApplication.java │ │ │ └── ZwitscherConfiguration.java │ │ └── resources │ │ ├── banner.txt │ │ └── zwitscher-config.yml ├── etcd │ ├── README.md │ └── docker-compose.yaml ├── loesung │ ├── book-service │ │ ├── .gitignore │ │ ├── .mvn │ │ │ └── wrapper │ │ │ │ ├── maven-wrapper.jar │ │ │ │ └── maven-wrapper.properties │ │ ├── Dockerfile │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── de │ │ │ │ │ └── qaware │ │ │ │ │ └── edu │ │ │ │ │ └── cc │ │ │ │ │ └── bookservice │ │ │ │ │ ├── Book.java │ │ │ │ │ ├── BookController.java │ │ │ │ │ ├── BookNotFoundException.java │ │ │ │ │ ├── BookServiceApplication.java │ │ │ │ │ └── Bookshelf.java │ │ │ └── resources │ │ │ │ ├── application.properties │ │ │ │ └── bootstrap.properties │ │ │ └── test │ │ │ └── java │ │ │ └── de │ │ │ └── qaware │ │ │ └── edu │ │ │ └── cc │ │ │ └── bookservice │ │ │ └── BookServiceApplicationTests.java │ └── docker-compose.yml ├── uebung │ ├── README.md │ ├── book-service │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── .mvn │ │ │ └── wrapper │ │ │ │ ├── maven-wrapper.jar │ │ │ │ └── maven-wrapper.properties │ │ ├── Dockerfile │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── de │ │ │ │ │ └── qaware │ │ │ │ │ └── edu │ │ │ │ │ └── cc │ │ │ │ │ └── bookservice │ │ │ │ │ ├── Book.java │ │ │ │ │ ├── BookController.java │ │ │ │ │ ├── BookNotFoundException.java │ │ │ │ │ ├── BookServiceApplication.java │ │ │ │ │ └── Bookshelf.java │ │ │ └── resources │ │ │ │ ├── application.properties │ │ │ │ └── bootstrap.properties │ │ │ └── test │ │ │ └── java │ │ │ └── de │ │ │ └── qaware │ │ │ └── edu │ │ │ └── cc │ │ │ └── bookservice │ │ │ └── BookServiceApplicationTests.java │ └── docker-compose.yml └── vorlesung │ ├── .gitattributes │ └── 06 Cloud Architecture.pdf ├── 07-orchestration ├── exercise │ ├── .gitignore │ ├── 01_exercise_pods_deployments.md │ ├── 02_exercise_probes_resources.md │ ├── 03_exercise_services.md │ ├── 04_exercise_config_maps.md │ ├── 05_bonus_exercise_ingress.md │ ├── 06_bonus_exercise_persistent_volumes.md │ ├── 07_bonus_tilt_kustomize.md │ ├── 08_bonus_dashboard.md │ ├── README.md │ ├── cheat-sheet.md │ ├── code │ │ ├── .gitkeep │ │ └── hello-service │ │ │ ├── .mvn │ │ │ └── wrapper │ │ │ │ ├── maven-wrapper.jar │ │ │ │ └── maven-wrapper.properties │ │ │ ├── Dockerfile │ │ │ ├── build-to-kubernetes.sh │ │ │ ├── k8s │ │ │ └── .gitkeep │ │ │ ├── mvnw │ │ │ ├── mvnw.cmd │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── demo │ │ │ │ ├── HelloApplication.java │ │ │ │ └── HelloWorldController.java │ │ │ └── resources │ │ │ └── application.yml │ └── loesung │ │ ├── 01_loesungen_pods_deployments │ │ ├── 01_deployment.yaml │ │ └── 01_loesung_pods_deployments.md │ │ ├── 02_loesungen_probes_resources │ │ ├── 01_deployment.yaml │ │ └── 02_loesung_probes_resources.md │ │ ├── 03_loesungen_services │ │ ├── 02_service.yaml │ │ └── 03_loesung_services.md │ │ ├── 04_loesungen_config_maps │ │ ├── 01_deployment.yaml │ │ ├── 03_config.yaml │ │ └── 04_loesung_config_maps.md │ │ ├── 05_loesung_ingress │ │ ├── 04_ingress.yaml │ │ └── 05_loesung_ingress.md │ │ ├── 06_loesung_persistent_volumes │ │ ├── 01_deployment.yaml │ │ ├── 05_pvc.yaml │ │ └── 06_loesung_persistent_volumes.md │ │ └── README.md └── lecture │ ├── .gitattributes │ └── 07 Orchestration.pdf ├── 08-service-meshes ├── exercise │ ├── README.md │ └── code │ │ ├── clusterconfig │ │ └── kind-cluster-config.yaml │ │ ├── dashboard │ │ ├── admin-user-cluster-role-binding.yaml │ │ ├── admin-user-serviceaccount.yaml │ │ └── dashboard-ingress.yaml │ │ ├── linkerd │ │ ├── server-authorization.yaml │ │ └── server-policy.yaml │ │ └── nginx-ingress-controller.yaml └── lecture │ ├── .gitattributes │ └── 08 Service Meshes.pdf ├── 09-devops&ci-cd ├── exercise │ └── Readme.md ├── lecture │ ├── .gitattributes │ └── 09 DevOps & Continuous Delivery.pdf └── solution │ ├── Readme.md │ └── clusters │ └── my-cluster │ ├── flux-system │ ├── gotk-components.yaml │ ├── gotk-sync.yaml │ └── kustomization.yaml │ ├── podinfo-kustomization.yaml │ ├── podinfo-source.yaml │ └── weave-gitops-dashboard.yaml ├── 10-paas ├── exercise │ └── README.md └── lecture │ ├── .gitattributes │ └── 10 Paas & IdP.pdf ├── 11-observability ├── exercise │ ├── .dockerignore │ ├── .editorconfig │ ├── .gitignore │ ├── LICENSE.txt │ ├── README.md │ ├── UEBUNG.md │ ├── alloy │ │ └── alloy.river │ ├── docker-compose.yaml │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── grafana │ │ ├── dashboards │ │ │ └── micrometer-jvm.json │ │ ├── grafana.ini │ │ └── provisioning │ │ │ ├── dashboards │ │ │ └── dashboards.yaml │ │ │ └── datasources │ │ │ ├── loki.yaml │ │ │ ├── mimir.yaml │ │ │ └── tempo.yaml │ ├── loki │ │ └── loki.yaml │ ├── mimir │ │ └── mimir.yaml │ ├── promtail │ │ └── promtail.yaml │ ├── settings.gradle.kts │ ├── sky-map │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── de │ │ │ │ └── qaware │ │ │ │ └── cloudcomputing │ │ │ │ ├── health │ │ │ │ └── LivenessProbe.java │ │ │ │ ├── parser │ │ │ │ ├── SatPosCalculator.java │ │ │ │ └── TleParser.java │ │ │ │ ├── satellite │ │ │ │ └── SatelliteResource.java │ │ │ │ └── tle │ │ │ │ ├── TleClient.java │ │ │ │ └── TleMember.java │ │ │ └── resources │ │ │ ├── META-INF │ │ │ └── resources │ │ │ │ ├── css │ │ │ │ └── style.css │ │ │ │ ├── index.html │ │ │ │ └── js │ │ │ │ ├── jquery.min.js │ │ │ │ ├── skymap.js │ │ │ │ └── three.min.js │ │ │ └── application.properties │ ├── solution │ │ └── alloy.river │ ├── tempo │ │ └── tempo.yaml │ └── tle-fetcher │ │ ├── build.gradle.kts │ │ └── src │ │ └── main │ │ ├── java │ │ └── de │ │ │ └── qaware │ │ │ └── cloudcomputing │ │ │ ├── TleResource.java │ │ │ ├── health │ │ │ └── LivenessProbe.java │ │ │ └── tle │ │ │ ├── TleMember.java │ │ │ ├── TleSearchResult.java │ │ │ └── TleService.java │ │ └── resources │ │ ├── META-INF │ │ └── resources │ │ │ └── index.html │ │ └── application.properties └── lecture │ ├── .gitattributes │ └── 11 Observability.pdf ├── 12-serverless ├── exercise │ ├── README.md │ └── src │ │ ├── .gitignore │ │ ├── api_gw.tf │ │ ├── hello.mjs │ │ ├── lambda.tf │ │ ├── main.tf │ │ └── outputs.tf └── lecture │ ├── .gitattributes │ └── 12 Serverless.pdf ├── 13-summary ├── .gitattributes └── Cloud Computing 2024_25 - Summary.pdf ├── LICENSE ├── README.md ├── WiSe2425-Cloud-Computing.pptx ├── archive ├── 100-project-template │ ├── .env │ ├── Readme.md │ ├── Tiltfile │ └── nginx-ingress-controller.yaml ├── 99-big-data │ ├── loesung │ │ ├── HelloWorld.java │ │ ├── README.md │ │ ├── WordCountMapReduce.java │ │ ├── WordCountSplitAdapter.java │ │ ├── WordCountStreaming.java │ │ └── WordStreamCounter.java │ ├── uebung │ │ ├── .gitattributes │ │ ├── .gitignore │ │ ├── .run │ │ │ ├── HelloWorld.run.xml │ │ │ ├── WordCountMapReduce.run.xml │ │ │ ├── WordCountStreaming.run.xml │ │ │ └── WordStreamCounter.run.xml │ │ ├── README.md │ │ ├── build.gradle.kts │ │ ├── docker-compose.yaml │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ ├── settings.gradle.kts │ │ └── src │ │ │ └── main │ │ │ ├── ignite │ │ │ ├── Dockerfile │ │ │ └── config │ │ │ │ └── ignite.xml │ │ │ ├── java │ │ │ └── de │ │ │ │ └── qaware │ │ │ │ └── cloudcomputing │ │ │ │ └── bigdata │ │ │ │ ├── HelloWorld.java │ │ │ │ ├── WordCountMapReduce.java │ │ │ │ ├── WordCountStreaming.java │ │ │ │ ├── WordStreamCounter.java │ │ │ │ ├── adapter │ │ │ │ └── WordCountSplitAdapter.java │ │ │ │ ├── ignite │ │ │ │ └── IgniteConfigurationProvider.java │ │ │ │ └── util │ │ │ │ └── FileUtil.java │ │ │ └── resources │ │ │ └── ulysses.txt │ └── vorlesung │ │ ├── .gitattributes │ │ └── m11-bigdata.pdf ├── 99-ci-cd_serverless │ ├── uebung │ │ └── README.md │ └── vorlesung │ │ ├── .gitattributes │ │ └── 11 DevOps & Continuous Delivery.pdf ├── 99-cluster-scheduling │ ├── uebung │ │ ├── README.md │ │ └── binpacking │ │ │ ├── .gitattributes │ │ │ ├── First Fit DecreasingV2.pdf │ │ │ ├── Scheduling – Next Fit.pdf │ │ │ ├── Worst Fit.pdf │ │ │ └── cloudcomputing_scheduling_best_fit.pdf │ └── vorlesung │ │ ├── .gitattributes │ │ └── m05-cluster-scheduling.pdf ├── 99-programmiermodelle │ ├── uebung-optional │ │ ├── .gitattributes │ │ ├── README.md │ │ ├── loesung │ │ │ ├── .mvn │ │ │ │ └── wrapper │ │ │ │ │ ├── maven-wrapper.jar │ │ │ │ │ └── maven-wrapper.properties │ │ │ ├── mvnw │ │ │ ├── mvnw.cmd │ │ │ ├── pom.xml │ │ │ └── src │ │ │ │ ├── main │ │ │ │ ├── java │ │ │ │ │ └── edu │ │ │ │ │ │ └── qaware │ │ │ │ │ │ └── cc │ │ │ │ │ │ └── reactive │ │ │ │ │ │ ├── Main.java │ │ │ │ │ │ ├── MainWithActors.java │ │ │ │ │ │ ├── actor │ │ │ │ │ │ ├── MessageCollectorActor.java │ │ │ │ │ │ ├── OpenLibraryActor.java │ │ │ │ │ │ └── WikipediaActor.java │ │ │ │ │ │ ├── connector │ │ │ │ │ │ ├── openlibrary │ │ │ │ │ │ │ └── OpenLibraryConnector.java │ │ │ │ │ │ └── wikipedia │ │ │ │ │ │ │ └── WikipediaConnector.java │ │ │ │ │ │ └── message │ │ │ │ │ │ ├── SearchMessage.java │ │ │ │ │ │ └── SearchResultMessage.java │ │ │ │ └── resources │ │ │ │ │ └── application.conf │ │ │ │ └── test │ │ │ │ └── java │ │ │ │ └── edu │ │ │ │ └── qaware │ │ │ │ └── cc │ │ │ │ └── reactive │ │ │ │ ├── OpenLibraryConnectorTest.java │ │ │ │ └── WikipediaConnectorTest.java │ │ ├── vorlage │ │ │ ├── .mvn │ │ │ │ └── wrapper │ │ │ │ │ ├── maven-wrapper.jar │ │ │ │ │ └── maven-wrapper.properties │ │ │ ├── mvnw │ │ │ ├── mvnw.cmd │ │ │ ├── pom.xml │ │ │ └── src │ │ │ │ ├── main │ │ │ │ ├── java │ │ │ │ │ └── edu │ │ │ │ │ │ └── qaware │ │ │ │ │ │ └── cc │ │ │ │ │ │ └── reactive │ │ │ │ │ │ ├── Main.java │ │ │ │ │ │ ├── MainWithActors.java │ │ │ │ │ │ ├── actors │ │ │ │ │ │ ├── MessageCollectorActor.java │ │ │ │ │ │ ├── OpenLibraryActor.java │ │ │ │ │ │ └── WikipediaActor.java │ │ │ │ │ │ └── connectors │ │ │ │ │ │ ├── openlibrary │ │ │ │ │ │ └── OpenLibraryConnector.java │ │ │ │ │ │ └── wikipedia │ │ │ │ │ │ └── WikipediaConnector.java │ │ │ │ └── resources │ │ │ │ │ └── application.conf │ │ │ │ └── test │ │ │ │ └── java │ │ │ │ └── edu │ │ │ │ └── qaware │ │ │ │ └── cc │ │ │ │ └── reactive │ │ │ │ ├── OpenLibraryConnectorTest.java │ │ │ │ └── WikipediaConnectorTest.java │ │ └── ziel.png │ └── vorlesung │ │ ├── .gitattributes │ │ └── m12-programmiermodelle.pdf └── projektarbeit │ ├── .gitattributes │ └── Projekt.pdf ├── cloud-computing.code-workspace ├── vl-cc-logo.jpg └── vl-cc-logo.png /.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /01-introduction/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /01-introduction/README.md: -------------------------------------------------------------------------------- 1 | # Introduction Cloud Computing 2 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-1/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-1/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/01-introduction/exercise/jdk-test-1/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-1/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=bin 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar 5 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.5.6 9 | 10 | 11 | com.example 12 | demo 13 | 0.0.1-SNAPSHOT 14 | demo 15 | Demo project for Spring Boot 16 | 17 | 18 | 21 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-test 35 | test 36 | 37 | 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-maven-plugin 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-1/src/main/java/com/example/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-1/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-1/src/test/java/com/example/demo/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class DemoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-2/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | !**/src/main/**/out/ 24 | !**/src/test/**/out/ 25 | 26 | ### NetBeans ### 27 | /nbproject/private/ 28 | /nbbuild/ 29 | /dist/ 30 | /nbdist/ 31 | /.nb-gradle/ 32 | 33 | ### VS Code ### 34 | .vscode/ 35 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-2/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "org.springframework.boot" version "3.5.6" 3 | id 'io.spring.dependency-management' version '1.1.7' 4 | id 'java' 5 | id "jvm-test-suite" 6 | } 7 | 8 | group = 'com.example' 9 | version = '0.0.1-SNAPSHOT' 10 | 11 | java { 12 | toolchain { 13 | languageVersion = JavaLanguageVersion.of("21") 14 | } 15 | } 16 | 17 | repositories { 18 | mavenCentral() 19 | } 20 | 21 | dependencies { 22 | implementation 'org.springframework.boot:spring-boot-starter' 23 | implementation 'org.springframework.boot:spring-boot-starter-web' 24 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 25 | } 26 | 27 | testing { 28 | suites { 29 | test { 30 | useJUnitJupiter("5.13.4") 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-2/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/01-introduction/exercise/jdk-test-2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-2/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=a17ddd85a26b6a7f5ddb71ff8b05fc5104c0202c6e64782429790c933686c806 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-2/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'demo' 2 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-2/src/main/java/com/example/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /01-introduction/exercise/jdk-test-2/src/test/java/com/example/demo/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class DemoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /01-introduction/exercise/kubernetes-cluster-setup/Tiltfile: -------------------------------------------------------------------------------- 1 | # Installing the nginx ingress controller 2 | k8s_yaml('nginx-ingress-controller.yaml') 3 | # Labelling the resources for prettier grouping in the UI 4 | k8s_resource(workload='ingress-nginx-controller', labels=['nginx-ingress-controller']) 5 | k8s_resource(workload='ingress-nginx-admission-create', labels=['nginx-ingress-controller']) 6 | k8s_resource(workload='ingress-nginx-admission-patch', labels=['nginx-ingress-controller']) 7 | 8 | # Installing the echo dev server components 9 | k8s_yaml('echo-http-ingress-config.yaml') 10 | # Labelling the resources for prettier grouping in the UI 11 | k8s_resource(workload='foo-app', labels=['traffic-test'], resource_deps=['ingress-nginx-controller']) 12 | k8s_resource(workload='bar-app', labels=['traffic-test'], resource_deps=['ingress-nginx-controller']) 13 | 14 | # Makes the dependencies clear. Apparently, one has to wait for the ingress controller to be fully 15 | # ready before creating any ingresses. Otherwise the system will not reach a stable state. 16 | k8s_resource( 17 | objects=['example-ingress', 'foo-service', 'bar-service'], 18 | resource_deps=['foo-app', 'bar-app'], 19 | new_name='ingress', 20 | labels=['traffic-test'] 21 | ) -------------------------------------------------------------------------------- /01-introduction/exercise/kubernetes-cluster-setup/echo-http-ingress-config.yaml: -------------------------------------------------------------------------------- 1 | kind: Pod 2 | apiVersion: v1 3 | metadata: 4 | name: foo-app 5 | labels: 6 | app: foo 7 | spec: 8 | containers: 9 | - command: 10 | - /agnhost 11 | - netexec 12 | - --http-port 13 | - "8080" 14 | image: registry.k8s.io/e2e-test-images/agnhost:2.57 15 | name: foo-app 16 | --- 17 | kind: Service 18 | apiVersion: v1 19 | metadata: 20 | name: foo-service 21 | spec: 22 | selector: 23 | app: foo 24 | ports: 25 | # Default port used by the image 26 | - port: 8080 27 | --- 28 | kind: Pod 29 | apiVersion: v1 30 | metadata: 31 | name: bar-app 32 | labels: 33 | app: bar 34 | spec: 35 | containers: 36 | - command: 37 | - /agnhost 38 | - netexec 39 | - --http-port 40 | - "8080" 41 | image: registry.k8s.io/e2e-test-images/agnhost:2.57 42 | name: bar-app 43 | --- 44 | kind: Service 45 | apiVersion: v1 46 | metadata: 47 | name: bar-service 48 | spec: 49 | selector: 50 | app: bar 51 | ports: 52 | # Default port used by the image 53 | - port: 8080 54 | --- 55 | apiVersion: networking.k8s.io/v1 56 | kind: Ingress 57 | metadata: 58 | name: example-ingress 59 | annotations: 60 | nginx.ingress.kubernetes.io/rewrite-target: /$2 61 | spec: 62 | rules: 63 | - http: 64 | paths: 65 | - pathType: Prefix 66 | path: /foo(/|$)(.*) 67 | backend: 68 | service: 69 | name: foo-service 70 | port: 71 | number: 8080 72 | - pathType: Prefix 73 | path: /bar(/|$)(.*) 74 | backend: 75 | service: 76 | name: bar-service 77 | port: 78 | number: 8080 -------------------------------------------------------------------------------- /01-introduction/exercise/kubernetes-cluster-setup/kind-cluster-config.yaml: -------------------------------------------------------------------------------- 1 | # three node (two workers) cluster config 2 | kind: Cluster 3 | apiVersion: kind.x-k8s.io/v1alpha4 4 | nodes: 5 | - role: control-plane 6 | kubeadmConfigPatches: 7 | - | 8 | kind: InitConfiguration 9 | nodeRegistration: 10 | kubeletExtraArgs: 11 | node-labels: "ingress-ready=true" 12 | extraPortMappings: 13 | - containerPort: 80 14 | hostPort: 9999 15 | protocol: TCP 16 | - role: worker 17 | - role: worker -------------------------------------------------------------------------------- /01-introduction/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /01-introduction/lecture/01-Introduction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/01-introduction/lecture/01-Introduction.pdf -------------------------------------------------------------------------------- /01-introduction/organizational-matters.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/01-introduction/organizational-matters.pdf -------------------------------------------------------------------------------- /02-communication/examples/dropwizard/src/main/java/edu/qaware/cc/zwitscher/api/entities/ZwitscherMessage.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.zwitscher.api.entities; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | 5 | import java.util.Date; 6 | 7 | @Schema(description = "Eine Nachricht - versendet mit Zwitscher") 8 | public class ZwitscherMessage { 9 | private Date timestamp; 10 | private String message; 11 | 12 | public ZwitscherMessage(String message){ 13 | this.message = message; 14 | this.timestamp = new Date(); 15 | } 16 | 17 | public Date getTimestamp() { 18 | return timestamp; 19 | } 20 | 21 | @Schema(description = "Versandzeitpunkt", requiredMode = Schema.RequiredMode.REQUIRED) 22 | public void setTimestamp(Date timestamp) { 23 | this.timestamp = timestamp; 24 | } 25 | 26 | public String getMessage() { 27 | return message; 28 | } 29 | 30 | @Schema(description = "Nachricht", requiredMode = Schema.RequiredMode.REQUIRED, allowableValues = {"Yo!", "yo!", "YO!"}) 31 | public void setMessage(String message) { 32 | this.message = message; 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /02-communication/examples/dropwizard/src/main/java/edu/qaware/cc/zwitscher/core/ZwitscherApplication.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.zwitscher.core; 2 | 3 | import edu.qaware.cc.zwitscher.api.resources.ZwitscherMessageResource; 4 | import io.dropwizard.core.Application; 5 | import io.dropwizard.core.setup.Bootstrap; 6 | import io.dropwizard.core.setup.Environment; 7 | import io.federecio.dropwizard.swagger.SwaggerBundle; 8 | import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration; 9 | 10 | public class ZwitscherApplication extends Application { 11 | 12 | public static void main(String[] args) throws Exception { 13 | new ZwitscherApplication().run( 14 | "server", 15 | "./src/main/resources/zwitscher-config.yml" 16 | ); 17 | } 18 | 19 | @Override 20 | /** 21 | * Prüft die Konfiguration 22 | */ 23 | public void initialize(Bootstrap bootstrap) { 24 | bootstrap.addBundle(new SwaggerBundle<>() { 25 | @Override 26 | protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(ZwitscherConfiguration configuration) { 27 | return configuration.swaggerBundleConfiguration; 28 | } 29 | }); 30 | } 31 | 32 | @Override 33 | /** 34 | * Komponenten registrieren und konfigurieren 35 | * In unserem Fall: REST Ressourcen registrieren 36 | */ 37 | public void run(ZwitscherConfiguration t, Environment e) { 38 | e.jersey().register(ZwitscherMessageResource.class); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /02-communication/examples/dropwizard/src/main/java/edu/qaware/cc/zwitscher/core/ZwitscherConfiguration.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.zwitscher.core; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import io.dropwizard.core.Configuration; 5 | import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration; 6 | 7 | public class ZwitscherConfiguration extends Configuration { 8 | @JsonProperty("swagger") 9 | public SwaggerBundleConfiguration swaggerBundleConfiguration; 10 | } 11 | -------------------------------------------------------------------------------- /02-communication/examples/dropwizard/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _______ _ _______ ______ _______ _______ _______ _______ __________________ _ _______ 2 | ( ____ \( \ ( ___ )|\ /|( __ \ ( ____ \( ___ )( )( ____ )|\ /|\__ __/\__ __/( ( /|( ____ \ 3 | | ( \/| ( | ( ) || ) ( || ( \ ) | ( \/| ( ) || () () || ( )|| ) ( | ) ( ) ( | \ ( || ( \/ 4 | | | | | | | | || | | || | ) | | | | | | || || || || (____)|| | | | | | | | | \ | || | 5 | | | | | | | | || | | || | | | | | | | | || |(_)| || _____)| | | | | | | | | (\ \) || | ____ 6 | | | | | | | | || | | || | ) | | | | | | || | | || ( | | | | | | | | | | \ || | \_ ) 7 | | (____/\| (____/\| (___) || (___) || (__/ ) | (____/\| (___) || ) ( || ) | (___) | | | ___) (___| ) \ || (___) | 8 | (_______/(_______/(_______)(_______)(______/ (_______/(_______)|/ \||/ (_______) )_( \_______/|/ )_)(_______) 9 | -------------------------------------------------------------------------------- /02-communication/examples/dropwizard/src/main/resources/zwitscher-config.yml: -------------------------------------------------------------------------------- 1 | server: 2 | applicationConnectors: 3 | - type: http 4 | port: 2890 5 | adminConnectors: 6 | - type: http 7 | port: 2891 8 | logging: 9 | level: INFO 10 | 11 | # the only required property is resourcePackage, for more config options see below 12 | swagger: 13 | resourcePackage: edu.qaware.cc.zwitscher -------------------------------------------------------------------------------- /02-communication/examples/dropwizard/src/test/java/edu/qaware/cc/zwitscher/TestApi.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.zwitscher; 2 | 3 | import edu.qaware.cc.zwitscher.core.ZwitscherApplication; 4 | import edu.qaware.cc.zwitscher.core.ZwitscherConfiguration; 5 | import io.dropwizard.testing.junit5.DropwizardAppExtension; 6 | import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.jupiter.api.extension.ExtendWith; 9 | 10 | import static io.restassured.RestAssured.get; 11 | import static org.hamcrest.Matchers.equalTo; 12 | 13 | @ExtendWith(DropwizardExtensionsSupport.class) 14 | public class TestApi { 15 | 16 | public static final DropwizardAppExtension app = new DropwizardAppExtension<>(ZwitscherApplication.class, "./src/main/resources/zwitscher-config.yml"); 17 | 18 | @Test 19 | public void testRandomMessage(){ 20 | get("http://localhost:2890/messages/random") 21 | .then().body("message", equalTo("YO!")); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /02-communication/examples/grpc/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/02-communication/examples/grpc/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /02-communication/examples/grpc/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=bin 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar 5 | -------------------------------------------------------------------------------- /02-communication/examples/grpc/src/main/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_multiple_files = true; 4 | option java_package = "io.grpc.examples.helloworld"; 5 | option java_outer_classname = "HelloWorldProto"; 6 | option objc_class_prefix = "HLW"; 7 | 8 | package helloworld; 9 | 10 | // The greeting service definition. 11 | service Greeter { 12 | // Sends a greeting 13 | rpc SayHello (HelloRequest) returns (HelloReply) {} 14 | } 15 | 16 | // The request message containing the user's name. 17 | message HelloRequest { 18 | string name = 1; 19 | } 20 | 21 | // The response message containing the greetings 22 | message HelloReply { 23 | string message = 1; 24 | } -------------------------------------------------------------------------------- /02-communication/examples/grpc/src/test/sample_calls/hello.http: -------------------------------------------------------------------------------- 1 | GRPC localhost:50051/helloworld.Greeter/SayHello 2 | 3 | { 4 | "name": "Cloud Computing" 5 | } -------------------------------------------------------------------------------- /02-communication/examples/hazelcast/loesung/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | edu.qaware.cc 5 | minicloud 6 | 1.0-SNAPSHOT 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 3.6.3 13 | 14 | 15 | 16 | com.hazelcast 17 | hazelcast 18 | ${hazelcast.version} 19 | 20 | 21 | -------------------------------------------------------------------------------- /02-communication/examples/hazelcast/vorlage/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | edu.qaware.cc 5 | minicloud 6 | 1.0-SNAPSHOT 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 3.6.3 13 | 14 | 15 | 16 | com.hazelcast 17 | hazelcast 18 | ${hazelcast.version} 19 | 20 | 21 | -------------------------------------------------------------------------------- /02-communication/examples/hazelcast/vorlage/src/main/java/edu/qaware/cc/minicloud/Chatter.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.minicloud; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | public class Chatter { 8 | 9 | 10 | public static void main(String[] args) throws IOException { 11 | 12 | //TODO-1: Passende Hazelcast-Datenstruktur initialisieren 13 | 14 | //TODO-2: Alle bisherigen Nachrichten ausgeben 15 | 16 | //TODO-3: Die Klasse Chatter als Listener an der Hazelcast-Datenstruktur 17 | // regisrieren, damit sie bei neuen Nachrichten (= Änderungen an der Datenstruktur) 18 | // informiert wird und diese dann auf der Kommandozeile ausgibt. 19 | 20 | String msg; 21 | BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 22 | do { 23 | msg = in.readLine(); 24 | //TODO-4: Nachricht (msg) zur Datenstruktur hinzufügen (senden) 25 | } while (msg != "!e"); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /02-communication/exercise/README.md: -------------------------------------------------------------------------------- 1 | # Practice session - communication 2 | 3 | This session includes two parts: 4 | 5 | * [REST](rest) 6 | * [gRPC](grpc) 7 | -------------------------------------------------------------------------------- /02-communication/exercise/grpc/solution/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = false 9 | max_line_length = 120 10 | tab_width = 4 11 | 12 | [*.xml] 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /02-communication/exercise/grpc/solution/.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ 2 | .idea/ 3 | *.iml 4 | 5 | # Maven 6 | target/ 7 | -------------------------------------------------------------------------------- /02-communication/exercise/grpc/solution/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/02-communication/exercise/grpc/solution/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /02-communication/exercise/grpc/solution/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=bin 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar 5 | -------------------------------------------------------------------------------- /02-communication/exercise/grpc/solution/README.md: -------------------------------------------------------------------------------- 1 | # Lösung gRPC 2 | 3 | 1. Starten Sie in Ihrer IDE die `main`-Methode der Klasse `de.qaware.edu.cc.bookservice.server.Server` 4 | 2. Starten Sie in Ihrer IDE die `main`-Methode der Klasse `de.qaware.edu.cc.bookservice.client.Client` 5 | 6 | * [gRPC Definition](src/main/proto/book.proto) 7 | * [Server-Implementierung](src/main/java/de/qaware/edu/cc/bookservice/server/BookServiceImpl.java) 8 | * [Client-Implementierung](src/main/java/de/qaware/edu/cc/bookservice/client/Client.java) 9 | -------------------------------------------------------------------------------- /02-communication/exercise/grpc/solution/src/main/java/de/qaware/edu/cc/bookservice/server/Server.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice.server; 2 | 3 | import de.qaware.edu.cc.bookservice.server.domain.Book; 4 | import de.qaware.edu.cc.bookservice.server.domain.BookAlreadyExistsException; 5 | import de.qaware.edu.cc.bookservice.server.domain.BookRepository; 6 | import io.grpc.ServerBuilder; 7 | 8 | import java.io.IOException; 9 | 10 | public class Server { 11 | private static final int PORT = 12345; 12 | 13 | public static void main(String[] args) throws IOException, InterruptedException { 14 | BookRepository repository = new BookRepository(); 15 | BookServiceImpl service = new BookServiceImpl(repository); 16 | 17 | addSampleBooks(repository); 18 | 19 | io.grpc.Server server = ServerBuilder.forPort(PORT).addService(service).build(); 20 | server.start(); 21 | 22 | System.out.println("Server running on port " + PORT); 23 | server.awaitTermination(); 24 | } 25 | 26 | private static void addSampleBooks(BookRepository repository) { 27 | try { 28 | repository.add(new Book("0345391802", "The Hitchhiker's Guide to the Galaxy", "Douglas Adams")); 29 | repository.add(new Book("0553418025", "The Martian", "Andy Weir")); 30 | repository.add(new Book("0062225758", "Guards! Guards!", "Terry Pratchett")); 31 | repository.add(new Book("3458317422", "Alice in Wonderland", "Lewis Carroll")); 32 | repository.add(new Book("0345391829", "Life, the Universe and Everything", "Douglas Adams")); 33 | } catch (BookAlreadyExistsException e) { 34 | throw new AssertionError("Shouldn't happen", e); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /02-communication/exercise/grpc/solution/src/main/java/de/qaware/edu/cc/bookservice/server/domain/BookAlreadyExistsException.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice.server.domain; 2 | 3 | /** 4 | * Is thrown if a book with that isbn already exists. 5 | */ 6 | public class BookAlreadyExistsException extends Exception { 7 | private final String isbn; 8 | 9 | public BookAlreadyExistsException(String isbn) { 10 | super(String.format("Book with ISBN '%s' already exists", isbn)); 11 | 12 | this.isbn = isbn; 13 | } 14 | 15 | public String getIsbn() { 16 | return isbn; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /02-communication/exercise/grpc/solution/src/main/java/de/qaware/edu/cc/bookservice/server/domain/BookNotFoundException.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice.server.domain; 2 | 3 | /** 4 | * Is thrown if a book with that isbn doesn't exist. 5 | */ 6 | public class BookNotFoundException extends Exception { 7 | private final String isbn; 8 | 9 | public BookNotFoundException(String isbn) { 10 | super(String.format("Book with ISBN '%s' not found", isbn)); 11 | 12 | this.isbn = isbn; 13 | } 14 | 15 | public String getIsbn() { 16 | return isbn; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /02-communication/exercise/grpc/solution/src/main/proto/book.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "de.qaware.edu.cc.generated"; 4 | option java_outer_classname = "BookProto"; 5 | 6 | service BookService { 7 | rpc ListBooks(ListBooksRequest) returns (stream Book) {} 8 | 9 | rpc AddBook(Book) returns (Book) {} 10 | 11 | rpc DeleteBook(Isbn) returns (Void) {} 12 | 13 | rpc UpdateBook(UpdateBookRequest) returns (Book) {} 14 | } 15 | 16 | message Void {} 17 | 18 | message ListBooksRequest {} 19 | 20 | message Book { 21 | string isbn = 1; 22 | string author = 2; 23 | string title = 3; 24 | } 25 | 26 | message Isbn { 27 | string value = 1; 28 | } 29 | 30 | message UpdateBookRequest { 31 | string isbn = 1; 32 | Book new_book = 2; 33 | } -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/02-communication/exercise/rest/solution/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=bin 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar 5 | -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:21-jdk-slim 2 | 3 | COPY target/book-service-1.0.1.jar /app/ 4 | RUN chmod +x /app/book-service-1.0.1.jar 5 | 6 | ENTRYPOINT ["/app/book-service-1.0.1.jar"] 7 | -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | de.qaware.edu.cc 7 | book-service 8 | 1.0.1 9 | jar 10 | 11 | book-service 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 3.5.6 18 | 19 | 20 | 21 | 22 | 21 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | 32 | org.springdoc 33 | springdoc-openapi-starter-webmvc-ui 34 | 2.8.13 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-test 40 | test 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-maven-plugin 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/src/main/java/de/qaware/edu/cc/bookservice/BookNotFoundException.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | /** 4 | * Custom exception class in case a book was not found. 5 | */ 6 | public class BookNotFoundException extends RuntimeException { 7 | /** 8 | * Construct message with given ISBN. 9 | * 10 | * @param isbn the ISBN 11 | */ 12 | public BookNotFoundException(String isbn) { 13 | super("Book with ISBN " + isbn + " not found."); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/src/main/java/de/qaware/edu/cc/bookservice/BookNotFoundExceptionMapper.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseBody; 7 | import org.springframework.web.bind.annotation.ResponseStatus; 8 | 9 | @ControllerAdvice 10 | class BookNotFoundExceptionMapper { 11 | 12 | @ResponseBody 13 | @ExceptionHandler(BookNotFoundException.class) 14 | @ResponseStatus(HttpStatus.NOT_FOUND) 15 | String bookNotFoundHandler(BookNotFoundException ex) { 16 | return ex.getMessage(); 17 | } 18 | } -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/src/main/java/de/qaware/edu/cc/bookservice/BookServiceApplication.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * The main Spring boot application class. 8 | */ 9 | @SpringBootApplication 10 | public class BookServiceApplication { 11 | public static void main(String[] args) { 12 | SpringApplication.run(BookServiceApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/02-communication/exercise/rest/solution/src/main/resources/application.properties -------------------------------------------------------------------------------- /02-communication/exercise/rest/solution/src/test/java/de/qaware/edu/cc/bookservice/BookServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class BookServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /02-communication/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /02-communication/lecture/02-Communication.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/02-communication/lecture/02-Communication.pdf -------------------------------------------------------------------------------- /03-virtualization/exercise/1-vagrant/vagrant/default: -------------------------------------------------------------------------------- 1 | server { 2 | root /usr/share/nginx/www; 3 | index index.php index.html index.htm; 4 | 5 | # Make site accessible from http://localhost/ 6 | server_name localhost; 7 | 8 | location / { 9 | # First attempt to serve request as file, then 10 | # as directory, then fall back to index.html 11 | try_files $uri $uri/ /index.html; 12 | } 13 | 14 | # pass the PHP scripts to PHP-FPM 15 | location ~ \.php$ { 16 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 17 | # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini 18 | 19 | # With php5-cgi alone: 20 | # fastcgi_pass 127.0.0.1:9000; 21 | # With php-fpm: 22 | fastcgi_pass unix:/run/php/php8.3-fpm.sock; 23 | fastcgi_index index.php; 24 | include fastcgi_params; 25 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 26 | fastcgi_param SCRIPT_NAME $fastcgi_script_name; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /03-virtualization/exercise/1-vagrant/vagrant/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Cloud Computing 2025

6 | 7 |

Virtualization with Vagrant

8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /03-virtualization/exercise/1-vagrant/vagrant/info.php: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /03-virtualization/exercise/2-docker/content/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /03-virtualization/exercise/2-docker/content/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello, World! 6 | 10 | 11 | 12 |
13 |
14 |
15 | 16 |
17 |
18 |
19 |

Hello from QAware!

20 |
21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /03-virtualization/exercise/2-docker/content/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/03-virtualization/exercise/2-docker/content/logo.png -------------------------------------------------------------------------------- /03-virtualization/exercise/2-docker/solution/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | 3 | EXPOSE 80 4 | 5 | RUN apk update && apk add nginx curl && mkdir /run/nginx 6 | 7 | ENTRYPOINT ["nginx", "-g", "daemon off;"] 8 | -------------------------------------------------------------------------------- /03-virtualization/exercise/2-docker/solution/nginx_mit_alpine.sh: -------------------------------------------------------------------------------- 1 | # get alpine 2 | docker pull alpine:latest 3 | # start in an interactive terminal session, i.e. you have an open shell inside the container 4 | docker run -it alpine:latest /bin/sh 5 | 6 | # start nginx in the forgreound with port 80 mapping, i.e. port 80 on host maps to port 80 in the container 7 | docker run -d -p 80:80 cloudcomputing/nginx nginx -g "daemon off;" 8 | 9 | # in a different terminal window 10 | curl "localhost:80" 11 | 12 | -------------------------------------------------------------------------------- /03-virtualization/exercise/2-docker/solution/website.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # mounts the content folder to the directory in the container that is served by nginx 4 | docker run -p 80:80 -v "$(pwd)/content:/usr/share/nginx/html" nginx:mainline 5 | -------------------------------------------------------------------------------- /03-virtualization/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /03-virtualization/lecture/03_virtualization.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/03-virtualization/lecture/03_virtualization.pdf -------------------------------------------------------------------------------- /03-virtualization/outdated/docker-compose/README.md: -------------------------------------------------------------------------------- 1 | # Übung: Virtualisierung 2 | 3 | ## Vorbereitung 4 | 5 | Prüfen sie dass Docker und Docker Compose auf ihrem Rechner installiert sind. 6 | 7 | ### Aufgabe: Docker Compose 8 | 9 | In dieser Aufgabe sollen sie den Technologie-Stack aus NGINX, PHP und MySQL mittels Docker Compose hochfahren. Verwenden sie hierfür Images von Docker Hub sowie selbst erzeugte Images. 10 | 11 | (1) Legen sie ein Docker Compose File an und definieren sie einen MySQL 5.5 Service sowie einen Service für einen Nginx+PHP7 Container. 12 | 13 | (2) Legen sie für das Nginx+PHP7 Image ein Dockerfile an. Folgen sie im Wesentlichen den Installationsanweisungen auf https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mysql-php-lemp-stack-on-centos-7 14 | 15 | Die wesentlichen Änderungen der Konfigurationsdateien sind: 16 | ```bash 17 | sed -i -e "s/;\?cgi.fix_pathinfo\s*=\s*1/cgi.fix_pathinfo = 0/g" /etc/php.ini && \ 18 | sed -i -e "s/daemonize = no/daemonize = yes/g" /etc/php-fpm.conf && \ 19 | 20 | sed -i -e "s/;\?listen.owner\s*=\s*nobody/listen.owner = nobody/g" /etc/php-fpm.d/www.conf && \ 21 | sed -i -e "s/;\?listen.group\s*=\s*nobody/listen.group = nobody/g" /etc/php-fpm.d/www.conf && \ 22 | 23 | sed -i -e "s/user = apache/user = nginx/g" /etc/php-fpm.d/www.conf && \ 24 | sed -i -e "s/group = apache/group = nginx/g" /etc/php-fpm.d/www.conf 25 | ``` 26 | 27 | (3) Starten sie die Container mit Docker Compose und prüfen sie ob sowohl Nginx und PHP laufen. 28 | Prüfen sie mittels Docker ob alles Prozesse innerhalb des Containers sauber laufen. 29 | 30 | ## Quellen 31 | Diese Übung soll auch eine eigenständige Problemlösung auf Basis von Informationen aus dem Internet vermitteln. 32 | 33 | Docker 34 | * https://docs.docker.com/compose/overview/ 35 | * https://hub.docker.com/ 36 | -------------------------------------------------------------------------------- /03-virtualization/outdated/docker-compose/loesung/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7.4.1708 2 | 3 | RUN yum install -y epel-release && \ 4 | yum install -y wget nginx && \ 5 | yum install -y php php-mysql php-fpm && \ 6 | sed -i -e "s/;\?cgi.fix_pathinfo\s*=\s*1/cgi.fix_pathinfo = 0/g" /etc/php.ini && \ 7 | sed -i -e "s/daemonize = no/daemonize = yes/g" /etc/php-fpm.conf && \ 8 | sed -i -e "s/;\?listen.owner\s*=\s*nobody/listen.owner = nobody/g" /etc/php-fpm.d/www.conf && \ 9 | sed -i -e "s/;\?listen.group\s*=\s*nobody/listen.group = nobody/g" /etc/php-fpm.d/www.conf && \ 10 | sed -i -e "s/user = apache/user = nginx/g" /etc/php-fpm.d/www.conf && \ 11 | sed -i -e "s/group = apache/group = nginx/g" /etc/php-fpm.d/www.conf 12 | 13 | COPY docker/php.conf /etc/nginx/default.d/ 14 | 15 | # COPY docker/index.html /usr/share/nginx/html/ 16 | # COPY docker/info.php /usr/share/nginx/html/ 17 | 18 | EXPOSE 80 19 | ENTRYPOINT php-fpm && nginx -g 'daemon off;' 20 | -------------------------------------------------------------------------------- /03-virtualization/outdated/docker-compose/loesung/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | nginx-php7: 5 | build: . 6 | image: nginx-php7:1.0.1 7 | ports: 8 | - "18080:80" 9 | volumes: 10 | - "./docker/:/usr/share/nginx/html/:ro" 11 | networks: 12 | - cc2017 13 | 14 | mysql: 15 | image: mysql:5.5 16 | environment: 17 | MYSQL_ROOT_PASSWORD: secret 18 | ports: 19 | - "3306:3306" 20 | networks: 21 | - cc2017 22 | 23 | networks: 24 | cc2017: 25 | driver: bridge 26 | -------------------------------------------------------------------------------- /04-provisionierung/examples/README.md: -------------------------------------------------------------------------------- 1 | # Beispiel: Provisionierung mit Packer 2 | 3 | Dieses Beispiel demonstriert die Erzeugung eines Amazon Images mit Packer zur Erzeugung von standadisierten [Dokku](http://dokku.viewdocs.io/dokku/) Instanzen. 4 | 5 | [asciinema](https://asciinema.org) demonstration ausführbar mit: 6 | 7 | ```bash 8 | asciinema play asciinema.cast 9 | ``` 10 | 11 | -------------------------------------------------------------------------------- /04-provisionierung/examples/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # this script deletes the created image if it is tagged with 'purpose: demo' 3 | set -e 4 | set -u 5 | set -o pipefail 6 | 7 | aws ec2 describe-images --owners self --filters "Name=tag:purpose,Values=demo" --query 'Images[].ImageId' --output text | xargs aws ec2 deregister-image --image-id 8 | -------------------------------------------------------------------------------- /04-provisionierung/examples/packer.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": { 3 | "region": "eu-central-1" 4 | }, 5 | "builders": [ 6 | { 7 | "type": "amazon-ebs", 8 | "ami_name": "dokku-{{timestamp}}", 9 | "source_ami": "ami-0c960b947cbb2dd16", 10 | "instance_type": "t3a.micro", 11 | "region": "{{user `region`}}", 12 | "ssh_username": "ubuntu", 13 | "tags": { 14 | "owner": "alex", 15 | "purpose": "demo" 16 | } 17 | } 18 | ], 19 | "provisioners": [ 20 | { 21 | "type": "file", 22 | "source": "./welcome.txt", 23 | "destination": "/home/ubuntu/" 24 | }, 25 | { 26 | "type": "shell", 27 | "inline":[ 28 | "ls -al /home/ubuntu", 29 | "cat /home/ubuntu/welcome.txt" 30 | ] 31 | }, 32 | { 33 | "type": "shell", 34 | "script": "./provision.sh" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /04-provisionierung/examples/provision.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | echo "This is provision.sh 👋" 5 | 6 | echo "installing dokku..." 7 | wget https://raw.githubusercontent.com/dokku/dokku/v0.21.4/bootstrap.sh; 8 | sudo DOKKU_TAG=v0.21.4 bash bootstrap.sh 9 | 10 | echo "installing dokku postgres plugin..." 11 | sudo dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres 12 | -------------------------------------------------------------------------------- /04-provisionierung/examples/welcome.txt: -------------------------------------------------------------------------------- 1 | Hello Packer people! 😎 -------------------------------------------------------------------------------- /04-provisionierung/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /04-provisionierung/lecture/04 Provisioning.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/04-provisionierung/lecture/04 Provisioning.pdf -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-ansible/Dockerfile_Managed_Node: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update && apt-get install -y openssh-server 4 | RUN mkdir /var/run/sshd 5 | RUN echo 'root:verysecretpassword' | chpasswd 6 | RUN sed -i 's/#*PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config 7 | 8 | # SSH login fix. Otherwise user is kicked off after login 9 | RUN sed -i 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' /etc/pam.d/sshd 10 | 11 | ENV NOTVISIBLE "in users profile" 12 | RUN echo "export VISIBLE=now" >> /etc/profile 13 | 14 | EXPOSE 22 15 | CMD ["/usr/sbin/sshd", "-D"] -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-ansible/ansible/hosts: -------------------------------------------------------------------------------- 1 | [server_hosts] 2 | uebung-ansible_managed-node_[1:3] 3 | 4 | [server_hosts:vars] 5 | ansible_python_interpreter=/usr/bin/python3 6 | ansible_ssh_user=root 7 | ansible_ssh_pass=verysecretpassword 8 | ansible_ssh_common_args='-o StrictHostKeyChecking=no' -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-ansible/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | managed-node: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile_Managed_Node 8 | image: "cc-managed:latest" 9 | networks: 10 | - cloudcomputing 11 | ports: 12 | - "80" 13 | 14 | ansible-node: 15 | image: "willhallonline/ansible:2.13-alpine-3.12" 16 | networks: 17 | - cloudcomputing 18 | depends_on: 19 | - managed-node 20 | volumes: 21 | - "./ansible/hosts:/etc/ansible/hosts" 22 | - "./playbooks:/root/playbooks" 23 | 24 | networks: 25 | cloudcomputing: 26 | driver: bridge 27 | -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-ansible/playbooks/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello Cloud Computing! 5 | 6 | 7 |

Hello Cloud Computing! Apache is up and running!

8 | 9 | -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-ansible/playbooks/install-apache.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: server_hosts 3 | remote_user: root 4 | 5 | tasks: 6 | - name: test connection 7 | ping: 8 | remote_user: root 9 | 10 | - name: install apache 11 | apt: 12 | name: apache2 13 | update_cache: yes 14 | state: latest 15 | 16 | - name: copy custom index.html 17 | copy: 18 | src: index.html 19 | dest: /var/www/html/index.html 20 | 21 | - name: ensure apache is running 22 | service: 23 | name: apache2 24 | state: started -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-ansible/ssh/config: -------------------------------------------------------------------------------- 1 | Host * 2 | StrictHostKeyChecking no 3 | 4 | -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:1.21-alpine 2 | COPY nginx-config/index.html /usr/share/nginx/html 3 | EXPOSE 80 4 | CMD nginx -g 'daemon off;' -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | cc-nginx: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | stdin_open: true # docker run -i 9 | tty: true # docker run -t 10 | ports: 11 | - "8080:80" -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-docker/nginx-config/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello Cloud Computing! 5 | 6 | 7 |

Hello Cloud Computing! Nginx is up and running!

8 | 9 | -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-packer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello Cloud Computing! 5 | 6 | 7 |

Hello Cloud Computing! Nginx build by packer is up and running!

8 | 9 | -------------------------------------------------------------------------------- /04-provisionierung/solution/uebung-packer/nginx.json: -------------------------------------------------------------------------------- 1 | { 2 | "builders": [ 3 | { 4 | "type": "docker", 5 | "image": "nginx:1.19-alpine", 6 | "commit": true, 7 | "run_command": [ "-d", "-t", "-i", "{{.Image}}", "/bin/sh" ], 8 | "changes": [ 9 | "EXPOSE 80", 10 | "CMD [\"nginx\", \"-g\", \"daemon off;\"]" 11 | ] 12 | } 13 | ], 14 | "provisioners": [ 15 | { 16 | "type": "file", 17 | "source": "./index.html", 18 | "destination": "/usr/share/nginx/html/" 19 | } 20 | ], 21 | "post-processors": [ 22 | [ 23 | { 24 | "type": "docker-tag", 25 | "repository": "packer-nginx", 26 | "tag": "1.0" 27 | } 28 | ] 29 | ] 30 | } -------------------------------------------------------------------------------- /05-iaas/exercise/README.md: -------------------------------------------------------------------------------- 1 | # Practice session IaaS 2 | 3 | In today's practice session you will get yourself familiar with the AWS management console, setting up infrastructure with terraform and using the aws cli. 4 | It is split in 3 parts, where the first 2 parts require an AWS account, the third does not. 5 | 6 | It is unlikely you manage to work through all 3 parts, therefore I suggest you pick part 1 & 2. 7 | In case you have no access to an AWS account, work through part 3. 8 | 9 | ## Warm Up (Optional): Getting familiar with Terraform 10 | 11 | Walk through the interactive terraform lab https://learn.hashicorp.com/tutorials/terraform/infrastructure-as-code?in=terraform/aws-get-started#quick-start. 12 | 13 | ## Parts 14 | 15 | [Part - 1](./aws-part-1) Setting up infrastructure using the AWS Management console 16 | [Part - 2](./aws-part-2) Setting up infrastructure in AWS with terraform 17 | [Part - 3](./localstack) Setting up infrastructure locally with terraform and localstack 18 | 19 | -------------------------------------------------------------------------------- /05-iaas/exercise/aws-part-2/README.md: -------------------------------------------------------------------------------- 1 | # Exercise: Infrastructure as Code with Terraform on AWS 2 | 3 | The goal of this exercise is to learn fundamental Infrastructure as Code skills with Terraform on the AWS Cloud. 4 | You will recreate the architecture from the previous exercise using Terraform. 5 | Basic steps have already been prepared for this. 6 | 7 | 1. Start the `iaas-container` and mount the `exercise/aws-part-2` directory in the container. 8 | Example with Bash from the directory: 9 | 10 | ``` shell 11 | docker run -it --rm -w /code --mount type=bind,source="$(pwd)",target=/code iaas-container 12 | ``` 13 | 14 | 2. Configure your AWS access with `aws configure sso` as in part-1. 15 | Enter session name `my-sso`, SSO start URL `https://cc-th-rosenheim.awsapps.com/start`, region `eu-central-1`, output format `json`, and profile name `student`. Leave other values unchanged. 16 | 17 | 3. Initialize the working directory with `terraform init`. 18 | 19 | 4. Review the existing Terraform files and familiarize yourself with the basic structure. 20 | 21 | 5. Implement all sections marked with `#ToDo`. 22 | Define a sensible order for yourself. 23 | You should regularly apply your implementations to the AWS Cloud with `terraform apply`. 24 | 25 | 6. At the end, the Terraform configuration should contain an output parameter with a valid and functional URL. 26 | 27 | 7. Create a new workspace with `terraform workspace new dev` and switch to it with `terraform workspace select dev`. 28 | Check whether you can create a second environment with `terraform apply`. 29 | If not, adjust your configurations to make this possible. 30 | Make resource names dependent on the workspace used. 31 | 32 | 8. Destroy all created resources with `terraform destroy` in both workspaces. -------------------------------------------------------------------------------- /05-iaas/exercise/aws-part-2/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | apt-get update 5 | apt-get install -y busybox cowsay 6 | rm -rf /var/lib/apt/lists/* 7 | 8 | { 9 | echo "
"
10 |   /usr/games/cowsay -f dragon ${message}
11 |   echo "
" 12 | } >> index.html 13 | 14 | nohup busybox httpd -f index.html -p 8080 & 15 | -------------------------------------------------------------------------------- /05-iaas/exercise/aws-part-2/loadbalancer.tf: -------------------------------------------------------------------------------- 1 | # ToDo: Create a Security Group for the Load Balancer 2 | # See: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group 3 | 4 | # ToDo: Allow incoming traffic on the Load Balancer on port 80 from everywhere 5 | # See: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule 6 | 7 | # ToDo: Allow outgoing traffic from the LB to everywhere 8 | # See: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule 9 | 10 | # ToDo: Create the Load Balancer 11 | # See: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb 12 | 13 | # resource "aws_lb" "app" { 14 | # name = 15 | # load_balancer_type = "application" 16 | # security_groups = 17 | # subnets = 18 | # 19 | # tags = local.standard_tags 20 | # } 21 | 22 | # ToDo: Create a target group 23 | # See: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group 24 | 25 | # resource "aws_lb_target_group" "app" { 26 | # name = 27 | # port = 28 | # protocol = 29 | # vpc_id = 30 | # 31 | # health_check { 32 | # healthy_threshold = 33 | # unhealthy_threshold = 34 | # interval = 35 | # path = 36 | # port = 37 | # protocol = 38 | # } 39 | # 40 | # tags = local.standard_tags 41 | # } 42 | 43 | # ToDo: Create a listener 44 | # See: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener 45 | 46 | # resource "aws_lb_listener" "lb_forward_to_app" { 47 | # ... 48 | # default_action { 49 | # ... 50 | # } 51 | # 52 | # tags = local.standard_tags 53 | # } 54 | -------------------------------------------------------------------------------- /05-iaas/exercise/aws-part-2/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.8.0" 3 | 4 | required_providers { 5 | aws = { 6 | # https://github.com/hashicorp/terraform-provider-aws/blob/main/CHANGELOG.md 7 | source = "hashicorp/aws" 8 | version = "5.50.0" 9 | } 10 | random = { 11 | # https://github.com/hashicorp/terraform-provider-random/blob/main/CHANGELOG.md 12 | source = "hashicorp/random" 13 | version = "3.6.2" 14 | } 15 | } 16 | } 17 | 18 | ################################################################################ 19 | 20 | provider "aws" { 21 | region = "eu-central-1" 22 | } 23 | 24 | ################################################################################ 25 | 26 | resource "random_string" "id_suffix" { 27 | length = 4 28 | special = false 29 | upper = false 30 | } 31 | 32 | locals { 33 | # Use this variable as prefix for all resource names. 34 | # This avoids conflicts with globally unique resources (all resources with a hostname). 35 | env = "default" 36 | 37 | # Use this map to apply env-specific values for certain components. 38 | env_config = { 39 | default = { 40 | message = "Hello World!" 41 | } 42 | dev = { 43 | message = "Hello DEV Workspaces!" 44 | } 45 | test = { 46 | message = "Hello TEST Workspaces!" 47 | } 48 | prod = { 49 | message = "Hello PROD Workspaces!" 50 | } 51 | } 52 | config = merge(local.env_config["default"], lookup(local.env_config, terraform.workspace, {})) 53 | 54 | # Tag all resources at least with these tags. 55 | # Allows filtering in AWS and distinction between environments. 56 | standard_tags = { 57 | "environment" = local.env 58 | } 59 | 60 | standard_tags_asg = [ 61 | for key in keys(local.standard_tags) : { 62 | key = key 63 | value = lookup(local.standard_tags, key) 64 | propagate_at_launch = true 65 | } 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /05-iaas/exercise/aws-part-2/network.tf: -------------------------------------------------------------------------------- 1 | module "vpc" { 2 | # https://github.com/terraform-aws-modules/terraform-aws-vpc/tags 3 | source = "git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git?ref=25322b6b6be69db6cca7f167d7b0e5327156a595" # 5.8.1 4 | 5 | name = local.env 6 | cidr = "10.0.0.0/16" 7 | azs = ["eu-central-1a", "eu-central-1b"] 8 | public_subnets = ["10.0.101.0/24", "10.0.102.0/24"] 9 | 10 | tags = local.standard_tags 11 | } 12 | -------------------------------------------------------------------------------- /05-iaas/exercise/aws-part-2/output.tf: -------------------------------------------------------------------------------- 1 | # ToDo: Define an output for the LoadBalancer URL 2 | -------------------------------------------------------------------------------- /05-iaas/exercise/iaas-container/aws-cli-pub.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mQINBF2Cr7UBEADJZHcgusOJl7ENSyumXh85z0TRV0xJorM2B/JL0kHOyigQluUG 4 | ZMLhENaG0bYatdrKP+3H91lvK050pXwnO/R7fB/FSTouki4ciIx5OuLlnJZIxSzx 5 | PqGl0mkxImLNbGWoi6Lto0LYxqHN2iQtzlwTVmq9733zd3XfcXrZ3+LblHAgEt5G 6 | TfNxEKJ8soPLyWmwDH6HWCnjZ/aIQRBTIQ05uVeEoYxSh6wOai7ss/KveoSNBbYz 7 | gbdzoqI2Y8cgH2nbfgp3DSasaLZEdCSsIsK1u05CinE7k2qZ7KgKAUIcT/cR/grk 8 | C6VwsnDU0OUCideXcQ8WeHutqvgZH1JgKDbznoIzeQHJD238GEu+eKhRHcz8/jeG 9 | 94zkcgJOz3KbZGYMiTh277Fvj9zzvZsbMBCedV1BTg3TqgvdX4bdkhf5cH+7NtWO 10 | lrFj6UwAsGukBTAOxC0l/dnSmZhJ7Z1KmEWilro/gOrjtOxqRQutlIqG22TaqoPG 11 | fYVN+en3Zwbt97kcgZDwqbuykNt64oZWc4XKCa3mprEGC3IbJTBFqglXmZ7l9ywG 12 | EEUJYOlb2XrSuPWml39beWdKM8kzr1OjnlOm6+lpTRCBfo0wa9F8YZRhHPAkwKkX 13 | XDeOGpWRj4ohOx0d2GWkyV5xyN14p2tQOCdOODmz80yUTgRpPVQUtOEhXQARAQAB 14 | tCFBV1MgQ0xJIFRlYW0gPGF3cy1jbGlAYW1hem9uLmNvbT6JAlQEEwEIAD4CGwMF 15 | CwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQT7Xbd/1cEYuAURraimMQrMRnJHXAUC 16 | ZMKcEgUJCSEf3QAKCRCmMQrMRnJHXCilD/4vior9J5tB+icri5WbDudS3ak/ve4q 17 | XS6ZLm5S8l+CBxy5aLQUlyFhuaaEHDC11fG78OduxatzeHENASYVo3mmKNwrCBza 18 | NJaeaWKLGQT0MKwBSP5aa3dva8P/4oUP9GsQn0uWoXwNDWfrMbNI8gn+jC/3MigW 19 | vD3fu6zCOWWLITNv2SJoQlwILmb/uGfha68o4iTBOvcftVRuao6DyqF+CrHX/0j0 20 | klEDQFMY9M4tsYT7X8NWfI8Vmc89nzpvL9fwda44WwpKIw1FBZP8S0sgDx2xDsxv 21 | L8kM2GtOiH0cHqFO+V7xtTKZyloliDbJKhu80Kc+YC/TmozD8oeGU2rEFXfLegwS 22 | zT9N+jB38+dqaP9pRDsi45iGqyA8yavVBabpL0IQ9jU6eIV+kmcjIjcun/Uo8SjJ 23 | 0xQAsm41rxPaKV6vJUn10wVNuhSkKk8mzNOlSZwu7Hua6rdcCaGeB8uJ44AP3QzW 24 | BNnrjtoN6AlN0D2wFmfE/YL/rHPxU1XwPntubYB/t3rXFL7ENQOOQH0KVXgRCley 25 | sHMglg46c+nQLRzVTshjDjmtzvh9rcV9RKRoPetEggzCoD89veDA9jPR2Kw6RYkS 26 | XzYm2fEv16/HRNYt7hJzneFqRIjHW5qAgSs/bcaRWpAU/QQzzJPVKCQNr4y0weyg 27 | B8HCtGjfod0p1A== 28 | =gdMc 29 | -----END PGP PUBLIC KEY BLOCK----- 30 | -------------------------------------------------------------------------------- /05-iaas/exercise/localstack/.gitignore: -------------------------------------------------------------------------------- 1 | .terraform/ 2 | terraform.tfstate* 3 | .terraform.lock.hcl 4 | builds/ 5 | output.txt -------------------------------------------------------------------------------- /05-iaas/exercise/localstack/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | localstack: 5 | container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}" 6 | image: localstack/localstack 7 | ports: 8 | - "127.0.0.1:4566:4566" # LocalStack Gateway 9 | - "127.0.0.1:4510-4559:4510-4559" # external services port range 10 | environment: 11 | - DEBUG=${DEBUG-} 12 | - DOCKER_HOST=unix:///var/run/docker.sock 13 | volumes: 14 | - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" 15 | - "/var/run/docker.sock:/var/run/docker.sock" 16 | networks: 17 | custom: 18 | aliases: 19 | - result-bucket.s3.localhost.localstack.cloud 20 | - s3.localhost.localstack.cloud 21 | 22 | iaas-container: 23 | build: ../iaas-container/ 24 | environment: 25 | LOCALSTACK_HOSTNAME: localstack 26 | volumes: 27 | - .:/root/terraform 28 | networks: 29 | - custom 30 | 31 | networks: 32 | custom: -------------------------------------------------------------------------------- /05-iaas/exercise/localstack/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | access_key = "mock_access_key" 3 | region = "us-east-1" 4 | secret_key = "mock_secret_key" 5 | skip_credentials_validation = true 6 | skip_metadata_api_check = true 7 | skip_requesting_account_id = true 8 | 9 | endpoints { 10 | apigateway = "http://localstack:4566" 11 | cloudformation = "http://localstack:4566" 12 | cloudwatch = "http://localstack:4566" 13 | dynamodb = "http://localstack:4566" 14 | es = "http://localstack:4566" 15 | firehose = "http://localstack:4566" 16 | iam = "http://localstack:4566" 17 | kinesis = "http://localstack:4566" 18 | lambda = "http://localstack:4566" 19 | route53 = "http://localstack:4566" 20 | redshift = "http://localstack:4566" 21 | s3 = "http://localstack:4566" 22 | secretsmanager = "http://localstack:4566" 23 | ses = "http://localstack:4566" 24 | sns = "http://localstack:4566" 25 | sqs = "http://localstack:4566" 26 | ssm = "http://localstack:4566" 27 | stepfunctions = "http://localstack:4566" 28 | sts = "http://localstack:4566" 29 | } 30 | } -------------------------------------------------------------------------------- /05-iaas/exercise/localstack/src/lambda-publisher.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | 3 | # Replace 'YOUR_QUEUE_URL' with your actual SQS queue URL 4 | QUEUE_URL = 'http://localstack:4566/000000000000/terraform-example-queue' 5 | 6 | def lambda_handler(event, context): 7 | # Initialize the SQS client 8 | sqs = boto3.client('sqs', endpoint_url = 'http://localstack:4566') 9 | 10 | # Define the message to send 11 | message = "Hello, World!" 12 | 13 | try: 14 | # Send the message to the SQS queue 15 | response = sqs.send_message( 16 | QueueUrl=QUEUE_URL, 17 | MessageBody=message 18 | ) 19 | 20 | # Print the response for debugging 21 | print(f"Message sent with MessageId: {response['MessageId']}") 22 | 23 | return { 24 | 'statusCode': 200, 25 | 'body': 'Message sent successfully!' 26 | } 27 | except Exception as e: 28 | print(f"Error: {str(e)}") 29 | return { 30 | 'statusCode': 500, 31 | 'body': str(e) 32 | } -------------------------------------------------------------------------------- /05-iaas/exercise/localstack/src/lambda-receiver.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | import json 3 | 4 | # Replace 'YOUR_BUCKET_NAME' with your S3 bucket name 5 | BUCKET_NAME = 'result-bucket' 6 | 7 | def lambda_handler(event, context): 8 | # Initialize the S3 client 9 | s3 = boto3.client('s3', endpoint_url = 'http://localstack:4566') 10 | 11 | try: 12 | # Convert the data to a JSON string 13 | data_json = json.dumps(event) 14 | 15 | # Define the S3 object key (file name) where you want to store the data 16 | object_key = "index.json" 17 | 18 | # Upload the data to the S3 bucket 19 | s3.put_object( 20 | Bucket=BUCKET_NAME, 21 | Key=object_key, 22 | Body=data_json 23 | ) 24 | 25 | return { 26 | 'statusCode': 200, 27 | 'body': 'Data uploaded to S3 bucket successfully!' 28 | } 29 | except Exception as e: 30 | print(f"Error: {str(e)}") 31 | return { 32 | 'statusCode': 500, 33 | 'body': 'Error uploading data to S3 bucket.' 34 | } -------------------------------------------------------------------------------- /05-iaas/exercise/localstack/volume/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/05-iaas/exercise/localstack/volume/.keep -------------------------------------------------------------------------------- /05-iaas/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /05-iaas/lecture/05 IaaS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/05-iaas/lecture/05 IaaS.pdf -------------------------------------------------------------------------------- /05-iaas/solution/terraform/aws/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | apt-get update 5 | apt-get install -y busybox cowsay 6 | rm -rf /var/lib/apt/lists/* 7 | 8 | { 9 | echo "
"
10 |   /usr/games/cowsay -f dragon ${message}
11 |   echo "
" 12 | } >> index.html 13 | 14 | nohup busybox httpd -f index.html -p 8080 & 15 | -------------------------------------------------------------------------------- /05-iaas/solution/terraform/aws/network.tf: -------------------------------------------------------------------------------- 1 | module "vpc" { 2 | # https://github.com/terraform-aws-modules/terraform-aws-vpc/tags 3 | source = "git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git?ref=25322b6b6be69db6cca7f167d7b0e5327156a595" # 5.8.1 4 | 5 | name = local.env 6 | cidr = "10.0.0.0/16" 7 | azs = ["eu-central-1a", "eu-central-1b"] 8 | public_subnets = ["10.0.101.0/24", "10.0.102.0/24"] 9 | 10 | tags = local.standard_tags 11 | } 12 | -------------------------------------------------------------------------------- /05-iaas/solution/terraform/aws/output.tf: -------------------------------------------------------------------------------- 1 | output "load_balancer_url" { 2 | description = "The URL of the Load Balancer" 3 | value = "http://${aws_lb.app.dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /05-iaas/solution/terraform/localstack/.gitignore: -------------------------------------------------------------------------------- 1 | .terraform/ 2 | terraform.tfstate* 3 | .terraform.lock.hcl 4 | builds/ 5 | output.txt -------------------------------------------------------------------------------- /05-iaas/solution/terraform/localstack/bucket.tf: -------------------------------------------------------------------------------- 1 | resource "aws_s3_bucket" "result-bucket" { 2 | bucket = "result-bucket" 3 | } 4 | 5 | resource "aws_s3_bucket_website_configuration" "example" { 6 | bucket = aws_s3_bucket.result-bucket.id 7 | 8 | index_document { 9 | suffix = "index.json" 10 | } 11 | } -------------------------------------------------------------------------------- /05-iaas/solution/terraform/localstack/output.tf: -------------------------------------------------------------------------------- 1 | output sqs_url { 2 | value = aws_sqs_queue.terraform_queue.url 3 | } 4 | 5 | -------------------------------------------------------------------------------- /05-iaas/solution/terraform/localstack/provider.tf: -------------------------------------------------------------------------------- 1 | provider aws { 2 | region = "us-east-1" 3 | } 4 | -------------------------------------------------------------------------------- /05-iaas/solution/terraform/localstack/publisher.tf: -------------------------------------------------------------------------------- 1 | module "lambda_publisher" { 2 | source = "terraform-aws-modules/lambda/aws" 3 | 4 | function_name = "publisher" 5 | description = "My awesome lambda publisher" 6 | handler = "lambda-publisher.lambda_handler" 7 | runtime = "python3.8" 8 | 9 | source_path = "./src/lambda-publisher.py" 10 | 11 | attach_policy_json = true 12 | policy_name = "write_to_sqs_policy" 13 | policy_json = < getMessageStream( 40 | @DefaultValue("") @QueryParam("keyword") String keyword){ 41 | List messages = new ArrayList(); 42 | messages.add(new ZwitscherMessage("yo")); 43 | return messages; 44 | } 45 | } -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/loesung/src/main/java/edu/qaware/cc/zwitscher/core/ZwitscherConfiguration.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.zwitscher.core; 2 | 3 | import io.dropwizard.Configuration; 4 | 5 | public class ZwitscherConfiguration extends Configuration { 6 | //vorerst haben wir keine applikationsspezifischen Konfigurationsparameter 7 | } 8 | -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/loesung/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _______ _ _______ ______ _______ _______ _______ _______ __________________ _ _______ 2 | ( ____ \( \ ( ___ )|\ /|( __ \ ( ____ \( ___ )( )( ____ )|\ /|\__ __/\__ __/( ( /|( ____ \ 3 | | ( \/| ( | ( ) || ) ( || ( \ ) | ( \/| ( ) || () () || ( )|| ) ( | ) ( ) ( | \ ( || ( \/ 4 | | | | | | | | || | | || | ) | | | | | | || || || || (____)|| | | | | | | | | \ | || | 5 | | | | | | | | || | | || | | | | | | | | || |(_)| || _____)| | | | | | | | | (\ \) || | ____ 6 | | | | | | | | || | | || | ) | | | | | | || | | || ( | | | | | | | | | | \ || | \_ ) 7 | | (____/\| (____/\| (___) || (___) || (__/ ) | (____/\| (___) || ) ( || ) | (___) | | | ___) (___| ) \ || (___) | 8 | (_______/(_______/(_______)(_______)(______/ (_______/(_______)|/ \||/ (_______) )_( \_______/|/ )_)(_______) 9 | -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/loesung/src/main/resources/zwitscher-config.yml: -------------------------------------------------------------------------------- 1 | server: 2 | applicationConnectors: 3 | - type: http 4 | port: 0 5 | adminConnectors: 6 | - type: http 7 | port: 0 8 | logging: 9 | level: INFO -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/loesung/src/test/java/edu/qaware/cc/zwitscher/TestApi.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.zwitscher; 2 | 3 | import static com.jayway.restassured.RestAssured.*; 4 | import static com.jayway.restassured.matcher.RestAssuredMatchers.*; 5 | import edu.qaware.cc.zwitscher.core.ZwitscherApplication; 6 | import edu.qaware.cc.zwitscher.core.ZwitscherConfiguration; 7 | import io.dropwizard.testing.junit.DropwizardAppRule; 8 | import static org.hamcrest.Matchers.*; 9 | import org.junit.ClassRule; 10 | import org.junit.Test; 11 | 12 | public class TestApi { 13 | 14 | @ClassRule 15 | public static final DropwizardAppRule RULE = 16 | new DropwizardAppRule<>(ZwitscherApplication.class, "./src/main/resources/zwitscher-config.yml"); 17 | 18 | @Test 19 | public void testRandomMessage(){ 20 | get("http://localhost:2890/messages/random") 21 | .then().body("message", equalTo("YO!")); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/vorlage/src/main/infrastructure/k8s/consul-rc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | name: consul 5 | spec: 6 | replicas: 1 7 | selector: 8 | app: consul 9 | template: 10 | metadata: 11 | labels: 12 | app: consul 13 | spec: 14 | containers: 15 | - name: consul 16 | command: [ "/bin/start", "-server", "-bootstrap-expect", "1"] 17 | image: progrium/consul:latest 18 | imagePullPolicy: Always 19 | ports: 20 | - containerPort: 8500 21 | name: ui-port 22 | - containerPort: 8400 23 | name: alt-port 24 | - containerPort: 53 25 | name: udp-port 26 | - containerPort: 443 27 | name: https-port 28 | - containerPort: 8080 29 | name: http-port 30 | - containerPort: 8301 31 | name: serflan 32 | - containerPort: 8302 33 | name: serfwan 34 | - containerPort: 8600 35 | name: consuldns 36 | - containerPort: 8300 37 | name: server -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/vorlage/src/main/infrastructure/k8s/consul-svc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: consul-svc 6 | spec: 7 | ports: 8 | - name: http 9 | port: 8500 10 | nodePort: 30850 11 | - name: rpc 12 | port: 8400 13 | - name: serflan 14 | port: 8301 15 | - name: serfwan 16 | port: 8302 17 | - name: server 18 | port: 8300 19 | - name: consuldns 20 | port: 8600 21 | type: LoadBalancer 22 | selector: 23 | app: consul -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/vorlage/src/main/java/edu/qaware/cc/zwitscher/api/entities/ZwitscherMessage.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.zwitscher.api.entities; 2 | 3 | import com.wordnik.swagger.annotations.ApiModel; 4 | import com.wordnik.swagger.annotations.ApiModelProperty; 5 | 6 | import java.util.Date; 7 | 8 | @ApiModel(value = "Eine Nachricht - versendet mit Zwitscher") 9 | public class ZwitscherMessage { 10 | private Date timestamp; 11 | private String message; 12 | 13 | public ZwitscherMessage(String message){ 14 | this.message = message; 15 | this.timestamp = new Date(); 16 | } 17 | 18 | public Date getTimestamp() { 19 | return timestamp; 20 | } 21 | 22 | @ApiModelProperty(value = "Versandzeitpunkt", required=true) 23 | public void setTimestamp(Date timestamp) { 24 | this.timestamp = timestamp; 25 | } 26 | 27 | public String getMessage() { 28 | return message; 29 | } 30 | 31 | @ApiModelProperty(value = "Nachricht", required=true, allowableValues = "Yo!,yo!,YO!") 32 | public void setMessage(String message) { 33 | this.message = message; 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/vorlage/src/main/java/edu/qaware/cc/zwitscher/api/resources/ZwitscherMessageResource.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.zwitscher.api.resources; 2 | 3 | import com.wordnik.swagger.annotations.Api; 4 | import com.wordnik.swagger.annotations.ApiOperation; 5 | import com.wordnik.swagger.annotations.ApiResponse; 6 | import com.wordnik.swagger.annotations.ApiResponses; 7 | import edu.qaware.cc.zwitscher.api.entities.ZwitscherMessage; 8 | 9 | import javax.ws.rs.*; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | @Api(value = "/messages", description = "Zwitscher Messages") 14 | @Path("/messages") 15 | public class ZwitscherMessageResource { 16 | 17 | @Path("/random") 18 | @GET 19 | @Produces("application/json") 20 | @ApiOperation(value = "Eine beliebige Nachricht zurückgeben", 21 | notes = "Diese Methode dient nur zu Demonstrationszwecken. " 22 | + "Sie gibt eine beliebige Nachricht zurück.") 23 | @ApiResponses(value = { 24 | @ApiResponse(code = 400, message = "Es kann keine vernünftige Nachricht generiert werden"), 25 | @ApiResponse(code = 404, message = "Die generierte Nachricht ist unvernünftig") 26 | }) 27 | public ZwitscherMessage getRandomMessage(){ 28 | return new ZwitscherMessage("YO!"); 29 | } 30 | 31 | @GET 32 | @Produces("application/json") 33 | @ApiOperation(value = "Den aktuellen Nachrichtenstrom zurückgeben", 34 | response = ZwitscherMessage.class, 35 | responseContainer = "List") 36 | @ApiResponses(value = { 37 | @ApiResponse(code = 404, message = "Es können keine Nachrichten geholt werden") 38 | }) 39 | public List getMessageStream( 40 | @DefaultValue("") @QueryParam("keyword") String keyword){ 41 | List messages = new ArrayList(); 42 | messages.add(new ZwitscherMessage("yo")); 43 | return messages; 44 | } 45 | } -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/vorlage/src/main/java/edu/qaware/cc/zwitscher/core/ZwitscherConfiguration.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.zwitscher.core; 2 | 3 | import io.dropwizard.Configuration; 4 | 5 | public class ZwitscherConfiguration extends Configuration { 6 | //vorerst haben wir keine applikationsspezifischen Konfigurationsparameter 7 | } 8 | -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/vorlage/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _______ _ _______ ______ _______ _______ _______ _______ __________________ _ _______ 2 | ( ____ \( \ ( ___ )|\ /|( __ \ ( ____ \( ___ )( )( ____ )|\ /|\__ __/\__ __/( ( /|( ____ \ 3 | | ( \/| ( | ( ) || ) ( || ( \ ) | ( \/| ( ) || () () || ( )|| ) ( | ) ( ) ( | \ ( || ( \/ 4 | | | | | | | | || | | || | ) | | | | | | || || || || (____)|| | | | | | | | | \ | || | 5 | | | | | | | | || | | || | | | | | | | | || |(_)| || _____)| | | | | | | | | (\ \) || | ____ 6 | | | | | | | | || | | || | ) | | | | | | || | | || ( | | | | | | | | | | \ || | \_ ) 7 | | (____/\| (____/\| (___) || (___) || (__/ ) | (____/\| (___) || ) ( || ) | (___) | | | ___) (___| ) \ || (___) | 8 | (_______/(_______/(_______)(_______)(______/ (_______/(_______)|/ \||/ (_______) )_( \_______/|/ )_)(_______) 9 | -------------------------------------------------------------------------------- /06-cloud-architecture/beispiele/vorlage/src/main/resources/zwitscher-config.yml: -------------------------------------------------------------------------------- 1 | server: 2 | applicationConnectors: 3 | - type: http 4 | port: 0 5 | adminConnectors: 6 | - type: http 7 | port: 0 8 | logging: 9 | level: INFO -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/book-service/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/book-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/06-cloud-architecture/loesung/book-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/book-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=bin 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar 5 | -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/book-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8u151-jre-slim 2 | 3 | COPY target/book-service-1.1.0.jar /app/ 4 | RUN chmod +x /app/book-service-1.1.0.jar 5 | 6 | ENTRYPOINT ["/app/book-service-1.1.0.jar"] 7 | -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/book-service/src/main/java/de/qaware/edu/cc/bookservice/BookNotFoundException.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | /** 4 | * Custom exception class in case a book was not found. 5 | */ 6 | public class BookNotFoundException extends RuntimeException { 7 | /** 8 | * Construct message with given ISBN. 9 | * 10 | * @param isbn the ISBN 11 | */ 12 | public BookNotFoundException(String isbn) { 13 | super("Book with ISBN " + isbn + " not found."); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/book-service/src/main/java/de/qaware/edu/cc/bookservice/BookServiceApplication.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 6 | 7 | /** 8 | * The main Spring boot application class. 9 | */ 10 | @SpringBootApplication 11 | @EnableSwagger2 12 | public class BookServiceApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(BookServiceApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/book-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=18080 2 | 3 | # assign a unique instance ID 4 | spring.cloud.consul.discovery.instance-id=${spring.application.name}:${spring.application.instance_id:${random.value}} 5 | 6 | # required by Docker compose and Consul to run the health check 7 | # register IP address and heartbeats 8 | spring.cloud.consul.discovery.prefer-ip-address=true 9 | spring.cloud.consul.discovery.heartbeat.enabled=true 10 | 11 | spring.cloud.consul.discovery.tags=traefik.enable=true,traefik.frontend.rule=PathPrefixStrip:/book-service,traefik.tags=api,traefik.frontend.entrypoint=http 12 | -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/book-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=book-service 2 | 3 | # specify Consul host and port 4 | # we use the CONSUL_HOST and CONSUL_PORT env variables 5 | # later set in docker compose as well as Kubernetes 6 | spring.cloud.consul.host=${consul.host:localhost} 7 | spring.cloud.consul.port=${consul.port:8500} 8 | 9 | spring.cloud.consul.config.enabled=true 10 | spring.cloud.consul.config.prefix=configuration 11 | spring.cloud.consul.config.default-context=application 12 | 13 | # do not fail at startup if Consul is not there 14 | spring.cloud.consul.config.fail-fast=false 15 | 16 | # store properties as blob in property syntax 17 | # e.g. configuration/book-service/data 18 | spring.cloud.consul.config.format=properties 19 | spring.cloud.consul.config.data-key=data -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/book-service/src/test/java/de/qaware/edu/cc/bookservice/BookServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class BookServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /06-cloud-architecture/loesung/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | consul: 4 | image: consul:1.14.1 5 | command: consul agent -server -dev -client=0.0.0.0 -ui -bootstrap -log-level warn 6 | ports: 7 | - "8400:8400" 8 | - "8500:8500" 9 | - "8600:53/udp" 10 | networks: 11 | - cloud-architecture 12 | 13 | reverse-proxy: 14 | image: traefik:v2.9 15 | command: --providers.consulcatalog.endpoint.address="consul:8500" --api.insecure=true 16 | ports: 17 | - 80:80 18 | - 8080:8080 19 | depends_on: 20 | - consul 21 | links: 22 | - consul 23 | networks: 24 | - cloud-architecture 25 | 26 | book-service: 27 | build: ./book-service 28 | image: book-service:1.1.0 29 | ports: 30 | - 18080:18080 31 | depends_on: 32 | - consul 33 | networks: 34 | - cloud-architecture 35 | environment: 36 | - SPRING_CLOUD_CONSUL_HOST=consul 37 | 38 | networks: 39 | cloud-architecture: -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/.dockerignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/06-cloud-architecture/uebung/book-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=bin 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar 5 | -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM maven:3.5-jdk-8-alpine as build 2 | 3 | COPY . /src 4 | RUN cd /src && mvn package 5 | 6 | FROM openjdk:8u151-jre-slim 7 | 8 | COPY --from=build /src/target/book-service-*.jar /app/book-service.jar 9 | RUN chmod +x /app/book-service.jar 10 | 11 | ENTRYPOINT ["/app/book-service.jar"] 12 | -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/src/main/java/de/qaware/edu/cc/bookservice/BookNotFoundException.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | /** 4 | * Custom exception class in case a book was not found. 5 | */ 6 | public class BookNotFoundException extends RuntimeException { 7 | /** 8 | * Construct message with given ISBN. 9 | * 10 | * @param isbn the ISBN 11 | */ 12 | public BookNotFoundException(String isbn) { 13 | super("Book with ISBN " + isbn + " not found."); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/src/main/java/de/qaware/edu/cc/bookservice/BookServiceApplication.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 6 | 7 | /** 8 | * The main Spring boot application class. 9 | */ 10 | @SpringBootApplication 11 | @EnableSwagger2 12 | public class BookServiceApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(BookServiceApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=18080 2 | -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=book-service 2 | -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/book-service/src/test/java/de/qaware/edu/cc/bookservice/BookServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package de.qaware.edu.cc.bookservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class BookServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /06-cloud-architecture/uebung/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | book-service: 4 | build: ./book-service 5 | image: book-service:1.1.0 6 | ports: 7 | - 18080:18080 8 | networks: 9 | - cloud-architecture 10 | environment: 11 | - SPRING_CLOUD_CONSUL_HOST=consul 12 | 13 | networks: 14 | cloud-architecture: -------------------------------------------------------------------------------- /06-cloud-architecture/vorlesung/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /06-cloud-architecture/vorlesung/06 Cloud Architecture.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/06-cloud-architecture/vorlesung/06 Cloud Architecture.pdf -------------------------------------------------------------------------------- /07-orchestration/exercise/.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | -------------------------------------------------------------------------------- /07-orchestration/exercise/02_exercise_probes_resources.md: -------------------------------------------------------------------------------- 1 | # Exercise 2. Probes and Resource Constraints 2 | 3 | Infos: 4 | 5 | - [Cheat-Sheet](cheat-sheet.md) 6 | 7 | Tasks: 8 | 9 | 1. Include liveness and readiness probes in the deployment of the 'Hello-Service' app 10 | , see 11 | [HTTP Probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-http-request). 12 | 2. Assign 13 | [Resource Requests and Limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-units-in-kubernetes). 14 | 3. Use k9s to check whether the app starts correctly. 15 | 16 | Bonus: 17 | 18 | 4. Check what happens when the readiness or liveness probes fail. 19 | 5. Check what happens when too few or too many resources are requested. 20 | 1. Verify that no pod can be scheduled (pending). 21 | 2. Use the Describe function in k9s to view the pod's events. 22 | 6. Build a 23 | [Startup-Probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes) 24 | . 25 | 26 | 7. calculate probe delays 27 | 28 | Assumed: 29 | 30 | - the liveness probe of the container is working and 31 | - the request to the endpoint `/actuator/health/readiness` times out. 32 | 33 | How long does it take for an app to be marked as “Not Ready” with the subsequent readiness probe? 34 | 35 | ```yaml 36 | readinessProbe: 37 | httpGet: 38 | path: /actuator/health/readiness 39 | port: 8000 40 | initialDelaySeconds: 10 41 | periodSeconds: 20 42 | failureThreshold: 3 43 | timeoutSeconds: 5 44 | ``` 45 | 46 | -------------------------------------------------------------------------------- /07-orchestration/exercise/03_exercise_services.md: -------------------------------------------------------------------------------- 1 | # Exercise 3. Services 2 | 3 | Infos: 4 | 5 | - [Cheat-Sheet](cheat-sheet.md) 6 | 7 | Tasks: 8 | 9 | 1. Create a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service) for the Hello Service app . 10 | 2. Start a temporary pod and use it to check that the service for the 11 | Hello Service can be accessed via curl using its host name. 12 | 13 | Launching a shell in a temporary pod: 14 | 15 | ```shell script 16 | kubectl run my-shell --rm -i --tty --image byrnedo/alpine-curl --command sh 17 | ``` 18 | 19 | Bonus: 20 | 21 | 3. Load Balancing 22 | 23 | - Change the Hello service so that the /hello endpoint returns the local IP address (in the body or as a header). 24 | 25 | ```java 26 | import org.springframework.web.bind.annotation.GetMapping; 27 | import org.springframework.web.bind.annotation.RestController; 28 | 29 | import javax.servlet.http.HttpServletRequest; 30 | 31 | @RestController 32 | public class HelloWorldController { 33 | @GetMapping("/hello") 34 | public String hello(HttpServletRequest clientRequest) { 35 | String localIp = clientRequest.getLocalAddr(); 36 | // ... 37 | } 38 | } 39 | ``` 40 | 41 | Build a new version of the 'helloservice' Docker image (see 'build-to-kubernetes.sh'). 42 | Deploy the 'Hello-Service' with two replicas in the Kubernetes cluster and verify that both pods are addressed by checking the response to a 'curl' to the service. 43 | 44 | -------------------------------------------------------------------------------- /07-orchestration/exercise/04_exercise_config_maps.md: -------------------------------------------------------------------------------- 1 | # Exercise 4. Config Maps 2 | 3 | Infos: 4 | 5 | - [Cheat-Sheet](cheat-sheet.md) 6 | 7 | Tasks: 8 | 9 | 1. Create a 10 | [Config Map](https://kubernetes.io/docs/concepts/configuration/configmap/#configmaps-and-pods) 11 | for the Hello-Service app. Store a suitable configuration so that 12 | the greeting is loaded from the config. 13 | 2. Bind the 14 | [Config Map Key as an environment variable](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#define-container-environment-variables-using-configmap-data) 15 | in the deployment of the Hello service. 16 | 17 | Tip: See how the environment variable GREETING is used in 18 | HelloWorldController. 19 | 20 | Bonus: 21 | 22 | 3. As an alternative to explicitly integrating individual keys as 23 | environment variables: Integrate all 24 | [config map keys at once](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#configure-all-key-value-pairs-in-a-configmap-as-container- environment-variableshttps://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#configure-all-key-value-pairs-in-a-configmap-as-container-environment-variables) 25 | ein. Keyword: `envFrom`. 26 | 4. (Previous knowledge: Volumes) As an alternative to environment variables: Bind the 27 | [keys of a config map as files](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#populate-a-volume-with-data-stored-in-a-configmap) 28 | into the container. Note: This also requires a code adjustment, of course. 29 | 30 | 31 | -------------------------------------------------------------------------------- /07-orchestration/exercise/05_bonus_exercise_ingress.md: -------------------------------------------------------------------------------- 1 | # Bonus Übung 5. Ingress 2 | 3 | Infos: 4 | 5 | - [Cheat-Sheet](cheat-sheet.md) 6 | In the first exercise of this semester, you installed the nginx ingress controller. 7 | 8 | Tasks: 9 | 10 | 1. Create an [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/#the-ingress-resource) for the 'Hello service'. 11 | 2. Check whether the service can be accessed from outside the cluster. 12 | -------------------------------------------------------------------------------- /07-orchestration/exercise/06_bonus_exercise_persistent_volumes.md: -------------------------------------------------------------------------------- 1 | # Exercise 6. Persistent Volumes (Bonus) 2 | 3 | Infos: 4 | 5 | - [Cheat-Sheet](cheat-sheet.md) 6 | 7 | Tasks: 8 | 9 | 1. Create a 10 | [Persistent Volume Claim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reserving-a-persistentvolume) 11 | for a new volume. 12 | 2. Bind the persistent volume claim to a volume and mount it in the 13 | container of the `Hello-Service` app. See 14 | [Claims as Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reserving-a-persistentvolume) 15 | 3. Open a shell in the container via `k9s`. 16 | 1. Check that the volume has been mounted in the desired location. 17 | 2. Place a file in the volume. 18 | 4. Test whether the file in this volume survives a container restart. 19 | -------------------------------------------------------------------------------- /07-orchestration/exercise/07_bonus_tilt_kustomize.md: -------------------------------------------------------------------------------- 1 | # Exercise 7. Tilt / Kustomize (Bonus) 2 | 3 | Infos: 4 | 5 | - [Cheat-Sheet](cheat-sheet.md) 6 | 7 | Tasks: 8 | 9 | 1. Use Kustomize to deploy the previous YAML files to Kubernetes with just one command. 10 | 2. Create a `tilt file` that you can use to deploy the Kustomize files to the cluster. 11 | -------------------------------------------------------------------------------- /07-orchestration/exercise/08_bonus_dashboard.md: -------------------------------------------------------------------------------- 1 | # Übung 8. Dashboard (Bonus) 2 | 3 | Infos: 4 | 5 | - [Cheat-Sheet](cheat-sheet.md) 6 | 7 | Tasks: 8 | 9 | 1. Start the dashboard from kubernetes with the command `kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml`. 10 | 2. Take a look around the dashboard and familiarize yourself with the functions. 11 | -------------------------------------------------------------------------------- /07-orchestration/exercise/README.md: -------------------------------------------------------------------------------- 1 | # Exercise Orchestration 2 | 3 | - [Cheat-Sheet](cheat-sheet.md) 4 | 5 | ### Exercise 1 - Pods & Deployments 6 | 7 | - [Description](01_exercise_pods_deployments) 8 | 9 | ### Exercise 2 - Probes und Resource Constraints 10 | 11 | - [Description](02_exercise_probes_resources) 12 | 13 | ### Exercise 3 - Services 14 | 15 | - [Description](03_exercise_services) 16 | 17 | ### Exercise 4 - Config Maps 18 | 19 | - [Description](04_exercise_config_maps) 20 | 21 | ### Exercise 5 - Ingress 22 | 23 | - [Description](05_bonus_exercise_ingress) 24 | 25 | ### Exercise 6 - Persistent Volumes (Bonus) 26 | 27 | - [Description](06_bonus_exercise_persistent_volumes) 28 | 29 | ### Exercise 7 - Dashboard (Bonus) 30 | 31 | - [Description](08_bonus_dashboard.md) 32 | 33 | -------------------------------------------------------------------------------- /07-orchestration/exercise/cheat-sheet.md: -------------------------------------------------------------------------------- 1 | # Cheat Sheet 2 | 3 | - [kubectl](#kubectl) 4 | - [k9s](#k9s) 5 | - [docker](#docker) 6 | 7 | ## kubectl 8 | 9 | Apply Kubernetes YAML (do whatever is necessary to make the cluster look like this) 10 | 11 | ```shell script 12 | kubectl apply -f path/to/file.yaml 13 | kubectl apply -f path/to/dir 14 | ``` 15 | 16 | Print Version 17 | 18 | ```shell script 19 | kubectl version 20 | ``` 21 | 22 | ## k9s 23 | 24 | Start 25 | 26 | ```shell script 27 | k9s 28 | ``` 29 | 30 | Navigation 31 | 32 | - `?` Show keyboard shortcuts 33 | - `:deployment` Show Kubernetes resource (e.g.: `:deployments`, `:services`, `:pods`, `:ingress`, ...) 34 | - `/` Filter current screen 35 | - `enter` Intelligent sub resource / show concept (`service` -> `pods` -> `containers` -> `logs`) 36 | - `esc` Get out of: View / Command / Filter 37 | - `d,v,e,l,…` Describe, View, Edit, Logs, ... 38 | 39 | Show version 40 | 41 | ```shell script 42 | k9s version 43 | ``` 44 | 45 | ## docker 46 | 47 | Build container image 48 | 49 | ```shell script 50 | # docker build -t 51 | docker build -t my-app:1 . 52 | ``` 53 | 54 | Start Shell in a running container 55 | 56 | ```shell script 57 | # docker exec -it /bin/bash 58 | docker exec -it 066c891518fa /bin/bash 59 | ``` 60 | 61 | Start a new container and open a shell 62 | 63 | ```shell script 64 | # docker run -it --entrypoint 65 | docker run --rm -it --entrypoint bash my-app 66 | ``` 67 | 68 | Print version 69 | 70 | ```shell script 71 | docker version 72 | ``` 73 | -------------------------------------------------------------------------------- /07-orchestration/exercise/code/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/07-orchestration/exercise/code/.gitkeep -------------------------------------------------------------------------------- /07-orchestration/exercise/code/hello-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/07-orchestration/exercise/code/hello-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /07-orchestration/exercise/code/hello-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=bin 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar 5 | -------------------------------------------------------------------------------- /07-orchestration/exercise/code/hello-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:15 2 | 3 | COPY target/hello-service-*.jar /app.jar 4 | EXPOSE 8000 5 | 6 | ENTRYPOINT ["java", "-jar", "/app.jar"] 7 | -------------------------------------------------------------------------------- /07-orchestration/exercise/code/hello-service/build-to-kubernetes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | # Package our service 6 | ./mvnw package 7 | 8 | # Build container image 9 | VERSION="1" 10 | docker build -t "helloservice:${VERSION}" . 11 | 12 | kind load docker-image "helloservice:${VERSION}" --name=kind 13 | -------------------------------------------------------------------------------- /07-orchestration/exercise/code/hello-service/k8s/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/07-orchestration/exercise/code/hello-service/k8s/.gitkeep -------------------------------------------------------------------------------- /07-orchestration/exercise/code/hello-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.4.RELEASE 9 | 10 | 11 | de.qaware.edu.cc.k8s-demo 12 | hello-service 13 | 0.0.1-SNAPSHOT 14 | 15 | 16 | 1.8 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-actuator 27 | 28 | 29 | org.apache.commons 30 | commons-lang3 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-maven-plugin 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /07-orchestration/exercise/code/hello-service/src/main/java/com/example/demo/HelloApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class HelloApplication { 8 | public static void main(String[] args) { 9 | SpringApplication.run(HelloApplication.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /07-orchestration/exercise/code/hello-service/src/main/java/com/example/demo/HelloWorldController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.MediaType; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | public class HelloWorldController { 11 | 12 | private static final Logger LOGGER = LoggerFactory.getLogger(HelloWorldController.class); 13 | 14 | @GetMapping(value = "/hello", produces = MediaType.TEXT_PLAIN_VALUE) 15 | public String hello() { 16 | LOGGER.info("hello() called"); 17 | 18 | final String greeting = System.getenv("GREETING"); 19 | return (greeting == null ? "Hello" : greeting) + ", World!"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /07-orchestration/exercise/code/hello-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: "helloservice" 4 | server: 5 | port: 8000 6 | management: 7 | endpoint: 8 | health: 9 | probes: 10 | enabled: true 11 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/01_loesungen_pods_deployments/01_deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: helloservice-deployment 5 | labels: 6 | app: helloservice 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: helloservice 12 | template: 13 | metadata: 14 | labels: 15 | app: helloservice 16 | spec: 17 | containers: 18 | - name: helloservice-container 19 | image: helloservice:1 20 | ports: 21 | - containerPort: 8000 22 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/01_loesungen_pods_deployments/01_loesung_pods_deployments.md: -------------------------------------------------------------------------------- 1 | # Lösung 1. Pods & Deployments 2 | 3 | Aufgaben: 4 | 5 | 4. Schreibt ein Kubernetes Deployment 6 | 7 | siehe `01_deployment.yaml` 8 | 9 | Bonus: 10 | 11 | 9. Ändert die Anzahl der Replikas des Deployments 12 | 13 | 2. über `kubectl scale` 14 | ```shell script 15 | kubectl scale --replicas=2 deployment/helloservice-deployment 16 | ``` 17 | 18 | 3. In welcher Reihenfolge passiert das Rolling Upgrade? (z.B. Zug-um-Zug oder wird erst komplett die neue Version ausgerollt und dann die alte heruntergefahren?) 19 | - Zug-um-Zug / Inkrementell: 20 | - Starten Neu-1 21 | - Runterfahren Alt-1 22 | - Starten Neu-2 23 | - Runterfahren Alt-2 24 | 25 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/02_loesungen_probes_resources/01_deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: helloservice-deployment 5 | labels: 6 | app: helloservice 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: helloservice 12 | template: 13 | metadata: 14 | labels: 15 | app: helloservice 16 | spec: 17 | containers: 18 | - name: helloservice-container 19 | image: helloservice:1 20 | ports: 21 | - containerPort: 8000 22 | readinessProbe: 23 | httpGet: 24 | path: /actuator/health/readiness 25 | port: 8000 26 | initialDelaySeconds: 15 27 | periodSeconds: 3 28 | livenessProbe: 29 | httpGet: 30 | path: /actuator/health/liveness 31 | port: 8000 32 | initialDelaySeconds: 30 33 | periodSeconds: 3 34 | resources: 35 | requests: 36 | memory: "256Mi" 37 | cpu: "250m" 38 | limits: 39 | memory: "512Mi" 40 | cpu: "0.5" 41 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/02_loesungen_probes_resources/02_loesung_probes_resources.md: -------------------------------------------------------------------------------- 1 | # Lösung 2. Probes und Resource Constraints 2 | 3 | Aufgaben: 4 | 5 | 1. Liveness und Readiness Probes 6 | 7 | siehe `01_deployment.yaml` 8 | 9 | 2. Resource Requests und Limits 10 | 11 | siehe `01_deployment.yaml` 12 | 13 | Bonus: 14 | 15 | 4. Prüft, was passiert, wenn die Readiness oder Liveness Probes 16 | fehlschlagen 17 | 18 | - Liveness Probe: Container wird neu gestartet. Restarts Counter wird inkrementiert. 19 | - Readiness: Container+Pod wird als "Not Ready" markiert 20 | 21 | 5. Zu wenige oder zu viele Ressourcen 22 | 23 | - zu wenige: Container startet nicht / crasht / wird restarted 24 | - zu viele: Pod kann nicht gescheduled werden (Pending) 25 | 26 | 6. Startup Probe 27 | 28 | ```yaml 29 | startupProbe: 30 | httpGet: 31 | path: /actuator/health/liveness 32 | port: 8000 33 | failureThreshold: 30 34 | periodSeconds: 10 35 | ``` 36 | 37 | 7. Probe Zeit berechnen 38 | 39 | - 10 Sekunden warten (`initialDelaySeconds`) 40 | - Readiness Check 1/3 -> nach 5 Sekunden (`timeoutSeconds`) Ergebnis da: fehlgeschlagen 41 | - 20 Sekunden warten (`periodSeconds`) 42 | - Readiness Check 2/3 -> nach 5 Sekunden Ergebnis da: fehlgeschlagen 43 | - 20 Sekunden warten 44 | - Readiness check 3/3 (`failureThreshold`) -> nach 5 Sekunden Ergebnis da, fehlgeschlagen 45 | 46 | Ergebnis: "Not Ready" nach 10 + (20 * 2) + 5 = 55 sec 47 | 48 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/03_loesungen_services/02_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: helloservice-service 5 | labels: 6 | app: helloservice 7 | spec: 8 | selector: 9 | app: helloservice 10 | ports: 11 | - protocol: TCP 12 | port: 8000 13 | targetPort: 8000 14 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/03_loesungen_services/03_loesung_services.md: -------------------------------------------------------------------------------- 1 | # Lösung 3. Services 2 | 3 | Aufgaben: 4 | 5 | 1. Legt für die App `Hello-Service` einen Service an 6 | 7 | - siehe `02_service.yaml` 8 | - deployment: `kubectl apply -f 02_service.yaml` 9 | 10 | 2. Startet einen temporären Pod und überprüft, dass der Service erreichbar ist. 11 | 12 | ```shell script 13 | ❯ kubectl run my-shell --rm -i --tty --image byrnedo/alpine-curl --command sh 14 | If you don't see a command prompt, try pressing enter. 15 | / # curl helloservice-service:8000/hello 16 | Howdy, World!/ # 17 | ``` 18 | 19 | Bonus: 20 | 21 | 3. Load Balancing testen 22 | 23 | Kommt bald ... 24 | 25 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/04_loesungen_config_maps/01_deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: helloservice-deployment 5 | labels: 6 | app: helloservice 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: helloservice 12 | template: 13 | metadata: 14 | labels: 15 | app: helloservice 16 | spec: 17 | containers: 18 | - name: helloservice-container 19 | image: helloservice:1 20 | ports: 21 | - containerPort: 8000 22 | readinessProbe: 23 | httpGet: 24 | path: /actuator/health/readiness 25 | port: 8000 26 | initialDelaySeconds: 15 27 | periodSeconds: 3 28 | livenessProbe: 29 | httpGet: 30 | path: /actuator/health/liveness 31 | port: 8000 32 | initialDelaySeconds: 30 33 | periodSeconds: 3 34 | resources: 35 | requests: 36 | memory: "256Mi" 37 | cpu: "250m" 38 | limits: 39 | memory: "512Mi" 40 | cpu: "0.5" 41 | env: 42 | - name: GREETING 43 | valueFrom: 44 | configMapKeyRef: 45 | name: helloservice-config 46 | key: greeting 47 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/04_loesungen_config_maps/03_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: helloservice-config 5 | labels: 6 | app: helloservice 7 | data: 8 | greeting: "Howdy" 9 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/04_loesungen_config_maps/04_loesung_config_maps.md: -------------------------------------------------------------------------------- 1 | # Lösung 4. Config Maps 2 | 3 | Aufgaben: 4 | 5 | 1. Erstellt eine Config Map 6 | 7 | siehe `03_config.yaml` 8 | 9 | 2. Bindet die Config Map ein 10 | 11 | siehe `01_deployment.yaml` 12 | 13 | Bonus: 14 | 15 | 3. Als Alternative zum expliziten Einbinden einzelner Keys als 16 | Umgebungsvariable: Bindet alle 17 | [Keys der Config Map auf einmal](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#configure-all-key-value-pairs-in-a-configmap-as-container-environment-variableshttps://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#configure-all-key-value-pairs-in-a-configmap-as-container-environment-variables) 18 | ein. Stichwort: `envFrom`. 19 | 20 | in `01_deployment.yaml`: 21 | 22 | ```yaml 23 | envFrom: 24 | - configMapRef: 25 | name: helloservice-config 26 | ``` 27 | 28 | Dann muss die Config Map die Keys so enthalten, wie sie als Umgebungsvariablen erwartet werden: 29 | 30 | ```yaml 31 | apiVersion: v1 32 | kind: ConfigMap 33 | metadata: 34 | name: helloservice-config 35 | labels: 36 | app: helloservice 37 | data: 38 | GREETING: "Howdy" 39 | ``` 40 | 41 | 42 | 4. Config Map als Files 43 | 44 | Kommt bald :) 45 | 46 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/05_loesung_ingress/04_ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: helloservice-ingress 5 | spec: 6 | rules: 7 | - http: 8 | paths: 9 | - path: / 10 | pathType: Prefix 11 | backend: 12 | service: 13 | name: helloservice-service 14 | port: 15 | number: 8000 16 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/05_loesung_ingress/05_loesung_ingress.md: -------------------------------------------------------------------------------- 1 | # Lösung Bonus Übung 5. Ingress 2 | 3 | Aufgaben: 4 | 5 | 1. Legt für den `Hello-Service` einen 6 | 7 | siehe `04_ingress.yaml` 8 | 9 | 2. Prüft, ob euer Service von außerhalb des Clusters erreichbar ist 10 | 11 | ```shell script 12 | http $(minikube ip)/hello 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/06_loesung_persistent_volumes/01_deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: helloservice-deployment 5 | labels: 6 | app: helloservice 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: helloservice 12 | template: 13 | metadata: 14 | labels: 15 | app: helloservice 16 | spec: 17 | containers: 18 | - name: helloservice-container 19 | image: helloservice:1 20 | ports: 21 | - containerPort: 8000 22 | readinessProbe: 23 | httpGet: 24 | path: /actuator/health/readiness 25 | port: 8000 26 | initialDelaySeconds: 15 27 | periodSeconds: 3 28 | livenessProbe: 29 | httpGet: 30 | path: /actuator/health/liveness 31 | port: 8000 32 | initialDelaySeconds: 30 33 | periodSeconds: 3 34 | resources: 35 | requests: 36 | memory: "256Mi" 37 | cpu: "250m" 38 | limits: 39 | memory: "512Mi" 40 | cpu: "0.5" 41 | env: 42 | - name: GREETING 43 | valueFrom: 44 | configMapKeyRef: 45 | name: helloservice-config 46 | key: greeting 47 | volumeMounts: 48 | - mountPath: "/data" 49 | name: helloservice-volume 50 | volumes: 51 | - name: helloservice-volume 52 | persistentVolumeClaim: 53 | claimName: helloservice-pvc 54 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/06_loesung_persistent_volumes/05_pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: helloservice-pvc 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce 8 | volumeMode: Filesystem 9 | resources: 10 | requests: 11 | storage: 100Mi 12 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/06_loesung_persistent_volumes/06_loesung_persistent_volumes.md: -------------------------------------------------------------------------------- 1 | # Lösung Bonus Übung 6. Persistent Volumes (Bonus) 2 | 3 | Aufgaben: 4 | 5 | 1. Erstellt einen 6 | 7 | siehe `05_pvc.yaml` 8 | 9 | 2. PVC anbinden und im Container bereitstellen 10 | 11 | siehe `01_deployment.yaml` 12 | 13 | 14 | -------------------------------------------------------------------------------- /07-orchestration/exercise/loesung/README.md: -------------------------------------------------------------------------------- 1 | # Lösungen 2 | 3 | ### Lösung Übung 1 - Pods & Deployments 4 | 5 | - [Beschreibung](01_loesungen_pods_deployments/01_loesung_pods_deployments.md) 6 | - [deployment.yaml](01_loesungen_pods_deployments/01_deployment.yaml) 7 | 8 | ### Lösung Übung 2 - Probes und Resource Constraints 9 | 10 | - [Beschreibung](02_loesungen_probes_resources/02_loesung_probes_resources.md) 11 | - [Angepasste deployment.yaml](02_loesungen_probes_resources/01_deployment.yaml) 12 | 13 | ### Lösung Übung 3 - Services 14 | 15 | - [Beschreibung](03_loesungen_services/03_loesung_services.md) 16 | - [service.yaml](03_loesungen_services/02_service.yaml) 17 | 18 | ### Lösung Übung 4 - Config Maps 19 | 20 | - [Beschreibung](04_loesungen_config_maps/04_loesung_config_maps.md) 21 | - [Angepasste deployment.yaml](04_loesungen_config_maps/01_deployment.yaml) 22 | - [config.yaml](04_loesungen_config_maps/03_config.yaml) 23 | 24 | ### Lösung Übung 5 - Ingress 25 | 26 | - [Beschreibung](05_loesung_ingress/05_loesung_ingress.md) 27 | - [ingress.yaml](05_loesung_ingress/04_ingress.yaml) 28 | 29 | ### Lösung Übung 6 - Persistent Volumes (Bonus) 30 | 31 | - [Beschreibung](06_loesung_persistent_volumes/06_loesung_persistent_volumes.md) 32 | - [Angepasste deployment.yaml](06_loesung_persistent_volumes/01_deployment.yaml) 33 | - [pvc.yaml](06_loesung_persistent_volumes/05_pvc.yaml) 34 | 35 | -------------------------------------------------------------------------------- /07-orchestration/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /07-orchestration/lecture/07 Orchestration.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/07-orchestration/lecture/07 Orchestration.pdf -------------------------------------------------------------------------------- /08-service-meshes/exercise/code/clusterconfig/kind-cluster-config.yaml: -------------------------------------------------------------------------------- 1 | # three node (two workers) cluster config 2 | kind: Cluster 3 | apiVersion: kind.x-k8s.io/v1alpha4 4 | nodes: 5 | - role: control-plane 6 | kubeadmConfigPatches: 7 | - | 8 | kind: InitConfiguration 9 | nodeRegistration: 10 | kubeletExtraArgs: 11 | node-labels: "ingress-ready=true" 12 | extraPortMappings: 13 | - containerPort: 80 14 | hostPort: 9999 15 | protocol: TCP 16 | # if your machine has enough resources, enable additional workers 17 | # - role: worker 18 | # - role: worker -------------------------------------------------------------------------------- /08-service-meshes/exercise/code/dashboard/admin-user-cluster-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: admin-user 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: cluster-admin 9 | subjects: 10 | - kind: ServiceAccount 11 | name: admin-user 12 | namespace: kubernetes-dashboard -------------------------------------------------------------------------------- /08-service-meshes/exercise/code/dashboard/admin-user-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: admin-user 5 | namespace: kubernetes-dashboard -------------------------------------------------------------------------------- /08-service-meshes/exercise/code/dashboard/dashboard-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | namespace: kubernetes-dashboard 5 | name: kubernetes-dashboard-ingress 6 | annotations: 7 | kubernetes.io/ingressClassName: "nginx" 8 | nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" 9 | spec: 10 | rules: 11 | - host: localhost 12 | http: 13 | paths: 14 | - path: / 15 | pathType: Prefix 16 | backend: 17 | service: 18 | name: kubernetes-dashboard-kong-proxy 19 | port: 20 | number: 443 -------------------------------------------------------------------------------- /08-service-meshes/exercise/code/linkerd/server-authorization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.linkerd.io/v1beta1 2 | kind: ServerAuthorization 3 | metadata: 4 | namespace: emojivoto 5 | name: voting-grpc 6 | labels: 7 | app.kubernetes.io/part-of: emojivoto 8 | app.kubernetes.io/name: voting 9 | app.kubernetes.io/version: v11 10 | spec: 11 | server: 12 | name: voting-grpc 13 | # The voting service only allows requests from the web service. 14 | client: 15 | meshTLS: 16 | serviceAccounts: 17 | - name: web -------------------------------------------------------------------------------- /08-service-meshes/exercise/code/linkerd/server-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.linkerd.io/v1beta1 2 | kind: Server 3 | metadata: 4 | namespace: emojivoto 5 | name: voting-grpc 6 | labels: 7 | app: voting-svc 8 | spec: 9 | podSelector: 10 | matchLabels: 11 | app: voting-svc 12 | port: grpc 13 | proxyProtocol: gRPC -------------------------------------------------------------------------------- /08-service-meshes/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /08-service-meshes/lecture/08 Service Meshes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/08-service-meshes/lecture/08 Service Meshes.pdf -------------------------------------------------------------------------------- /09-devops&ci-cd/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /09-devops&ci-cd/lecture/09 DevOps & Continuous Delivery.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/09-devops&ci-cd/lecture/09 DevOps & Continuous Delivery.pdf -------------------------------------------------------------------------------- /09-devops&ci-cd/solution/Readme.md: -------------------------------------------------------------------------------- 1 | # Deployment 2 | 3 | Create a new repository on github and push the contents of the `solution` directory. 4 | 5 | Then create a personal access token with the proper permissions. 6 | It needs read-write access for the contents and permission to setup a ssh deploy key. 7 | 8 | With fine grained tokens set the following permissions (not production ready!!!): 9 | - Administration => read and write 10 | - Contents => read and write 11 | 12 | Replace the variables and then run: 13 | ```shell 14 | flux bootstrap github --private=false \ 15 | --personal=true \ 16 | --owner=$your-github-user \ 17 | --repository=$your-repository\ 18 | --branch=main \ 19 | --path=clusters/my-cluster 20 | ``` 21 | 22 | The credentials for the flux dashboard are username `admin` and password `admin`. -------------------------------------------------------------------------------- /09-devops&ci-cd/solution/clusters/my-cluster/flux-system/gotk-sync.yaml: -------------------------------------------------------------------------------- 1 | # This manifest was generated by flux. DO NOT EDIT. 2 | --- 3 | apiVersion: source.toolkit.fluxcd.io/v1 4 | kind: GitRepository 5 | metadata: 6 | name: flux-system 7 | namespace: flux-system 8 | spec: 9 | interval: 1m0s 10 | ref: 11 | branch: main 12 | secretRef: 13 | name: flux-system 14 | url: ssh://git@github.com/CryoCodec/flux-getting-started 15 | --- 16 | apiVersion: kustomize.toolkit.fluxcd.io/v1 17 | kind: Kustomization 18 | metadata: 19 | name: flux-system 20 | namespace: flux-system 21 | spec: 22 | interval: 10m0s 23 | path: ./clusters/my-cluster 24 | prune: true 25 | sourceRef: 26 | kind: GitRepository 27 | name: flux-system 28 | -------------------------------------------------------------------------------- /09-devops&ci-cd/solution/clusters/my-cluster/flux-system/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - gotk-components.yaml 5 | - gotk-sync.yaml 6 | -------------------------------------------------------------------------------- /09-devops&ci-cd/solution/clusters/my-cluster/podinfo-kustomization.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1 3 | kind: Kustomization 4 | metadata: 5 | name: podinfo 6 | namespace: flux-system 7 | spec: 8 | interval: 30m0s 9 | path: ./kustomize 10 | prune: true 11 | retryInterval: 2m0s 12 | sourceRef: 13 | kind: GitRepository 14 | name: podinfo 15 | targetNamespace: default 16 | timeout: 3m0s 17 | wait: true 18 | patches: 19 | - patch: |- 20 | apiVersion: autoscaling/v2 21 | kind: HorizontalPodAutoscaler 22 | metadata: 23 | name: podinfo 24 | spec: 25 | minReplicas: 3 26 | target: 27 | name: podinfo 28 | kind: HorizontalPodAutoscaler 29 | -------------------------------------------------------------------------------- /09-devops&ci-cd/solution/clusters/my-cluster/podinfo-source.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: source.toolkit.fluxcd.io/v1 3 | kind: GitRepository 4 | metadata: 5 | name: podinfo 6 | namespace: flux-system 7 | spec: 8 | interval: 1m0s 9 | ref: 10 | branch: master 11 | url: https://github.com/stefanprodan/podinfo 12 | -------------------------------------------------------------------------------- /09-devops&ci-cd/solution/clusters/my-cluster/weave-gitops-dashboard.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: source.toolkit.fluxcd.io/v1beta2 3 | kind: HelmRepository 4 | metadata: 5 | annotations: 6 | metadata.weave.works/description: This is the source location for the Weave GitOps 7 | Dashboard's helm chart. 8 | labels: 9 | app.kubernetes.io/component: ui 10 | app.kubernetes.io/created-by: weave-gitops-cli 11 | app.kubernetes.io/name: weave-gitops-dashboard 12 | app.kubernetes.io/part-of: weave-gitops 13 | name: ww-gitops 14 | namespace: flux-system 15 | spec: 16 | interval: 1h0m0s 17 | type: oci 18 | url: oci://ghcr.io/weaveworks/charts 19 | --- 20 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 21 | kind: HelmRelease 22 | metadata: 23 | annotations: 24 | metadata.weave.works/description: This is the Weave GitOps Dashboard. It provides 25 | a simple way to get insights into your GitOps workloads. 26 | name: ww-gitops 27 | namespace: flux-system 28 | spec: 29 | chart: 30 | spec: 31 | chart: weave-gitops 32 | sourceRef: 33 | kind: HelmRepository 34 | name: ww-gitops 35 | interval: 1h0m0s 36 | values: 37 | adminUser: 38 | create: true 39 | passwordHash: $2a$10$CRQa1nxASFyE6o7p4XNKGuiEP60xAGKFd71sof9jfqK0mS5kVjVE2 40 | username: admin 41 | 42 | -------------------------------------------------------------------------------- /10-paas/exercise/README.md: -------------------------------------------------------------------------------- 1 | # Exercise: PaaS with Vercel 2 | 3 | Vercel is a serverless PaaS specializing in modern web frontends. 4 | You can use a variety of frameworks and set up automated deployment and hosting with just a few clicks. 5 | 6 | ## Task 1 7 | 8 | Create a [free Vercel account](https://vercel.com/signup/). 9 | 10 | ## Task 2 11 | 12 | Use Vercel to create a GitHub repository and deploy a template of your choice. 13 | Ensure the deployment was successful. You can now access the deployed website in your browser. 14 | The domain can be found directly in Vercel. 15 | 16 | ## Task 3 17 | 18 | Clone the generated repository. Modify the JavaScript/TypeScript files in the repository. 19 | Commit the changes and push the updates. 20 | You should be able to track the build process in Vercel. 21 | Within minutes, your updated version should be live under the same domain. 22 | 23 | ### (Optional) Storage 24 | 25 | Vercel also offers integrated storage solutions through partners, 26 | making it easy to build smaller yet fully functional products entirely on Vercel. 27 | Try out options like Redis or Postgres: 28 | [https://vercel.com/blog/vercel-storage](https://vercel.com/blog/vercel-storage) -------------------------------------------------------------------------------- /10-paas/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /10-paas/lecture/10 Paas & IdP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/10-paas/lecture/10 Paas & IdP.pdf -------------------------------------------------------------------------------- /11-observability/exercise/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !build/*-runner 3 | !build/*-runner.jar 4 | !build/lib/* 5 | !build/quarkus-app/* -------------------------------------------------------------------------------- /11-observability/exercise/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | max_line_length = 160 10 | tab_width = 4 11 | 12 | [*.{yml,yaml}] 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /11-observability/exercise/LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Lukas Buchner and Franz Wimmer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /11-observability/exercise/alloy/alloy.river: -------------------------------------------------------------------------------- 1 | // Create a prometheus.scrape component labeled "default." 2 | prometheus.scrape "default" { 3 | targets = [ 4 | // TODO: Scrape-Configs 5 | ] 6 | 7 | forward_to = [prometheus.remote_write.mimir.receiver] 8 | } 9 | 10 | // Send metrics to a Prometheus remote_write endpoint. 11 | prometheus.remote_write "mimir" { 12 | endpoint { 13 | url = "http://mimir:9009/api/v1/push" 14 | headers = { 15 | "X-Scope-OrgID" = "1", 16 | } 17 | } 18 | } 19 | 20 | logging { 21 | level = "info" 22 | format = "logfmt" 23 | } 24 | -------------------------------------------------------------------------------- /11-observability/exercise/gradle.properties: -------------------------------------------------------------------------------- 1 | #Gradle properties 2 | quarkusPluginId=io.quarkus 3 | quarkusPluginVersion=3.27.0 4 | quarkusPlatformGroupId=io.quarkus 5 | quarkusPlatformArtifactId=quarkus-universe-bom 6 | quarkusPlatformVersion=3.27.0 7 | -------------------------------------------------------------------------------- /11-observability/exercise/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/11-observability/exercise/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /11-observability/exercise/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=a17ddd85a26b6a7f5ddb71ff8b05fc5104c0202c6e64782429790c933686c806 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /11-observability/exercise/grafana/grafana.ini: -------------------------------------------------------------------------------- 1 | [server] 2 | root_url = http://localhost:8080 3 | 4 | [analytics] 5 | reporting_enabled = false 6 | check_for_updates = true 7 | 8 | [security] 9 | admin_user = admin 10 | admin_password = password123 11 | 12 | [unified_alerting] 13 | enabled = true 14 | -------------------------------------------------------------------------------- /11-observability/exercise/grafana/provisioning/dashboards/dashboards.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | # an unique provider name. Required 5 | - name: 'a unique provider name' 6 | # Org id. Default to 1 7 | orgId: 1 8 | # name of the dashboard folder. 9 | folder: '' 10 | # folder UID. will be automatically generated if not specified 11 | folderUid: '' 12 | # provider type. Default to 'file' 13 | type: file 14 | # disable dashboard deletion 15 | disableDeletion: false 16 | # how often Grafana will scan for changed dashboards 17 | updateIntervalSeconds: 10 18 | # allow updating provisioned dashboards from the UI 19 | allowUiUpdates: false 20 | options: 21 | # path to dashboard files on disk. Required when using the 'file' type 22 | path: /var/lib/grafana/dashboards 23 | # use folder names from filesystem to create folders in Grafana 24 | foldersFromFilesStructure: true 25 | -------------------------------------------------------------------------------- /11-observability/exercise/grafana/provisioning/datasources/loki.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 2 2 | 3 | datasources: 4 | - name: Loki 5 | type: loki 6 | access: proxy 7 | url: http://loki:3100 8 | jsonData: 9 | maxLines: 1000 10 | -------------------------------------------------------------------------------- /11-observability/exercise/grafana/provisioning/datasources/mimir.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 2 2 | 3 | datasources: 4 | - name: Mimir 5 | type: prometheus 6 | access: proxy 7 | url: http://mimir:9009/prometheus 8 | jsonData: 9 | httpHeaderName1: 'X-Scope-OrgID' 10 | secureJsonData: 11 | httpHeaderValue1: '1' 12 | -------------------------------------------------------------------------------- /11-observability/exercise/grafana/provisioning/datasources/tempo.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: Tempo 5 | type: tempo 6 | access: proxy 7 | url: http://tempo:3100 8 | jsonData: 9 | maxLines: 1000 10 | -------------------------------------------------------------------------------- /11-observability/exercise/loki/loki.yaml: -------------------------------------------------------------------------------- 1 | auth_enabled: false 2 | 3 | server: 4 | http_listen_port: 3100 5 | 6 | ingester: 7 | lifecycler: 8 | address: 127.0.0.1 9 | ring: 10 | kvstore: 11 | store: inmemory 12 | replication_factor: 1 13 | final_sleep: 0s 14 | chunk_idle_period: 5m 15 | chunk_retain_period: 30s 16 | 17 | schema_config: 18 | configs: 19 | - from: 2020-05-15 20 | store: boltdb 21 | object_store: filesystem 22 | schema: v11 23 | index: 24 | prefix: index_ 25 | period: 168h 26 | 27 | storage_config: 28 | boltdb: 29 | directory: /loki/index 30 | 31 | filesystem: 32 | directory: /loki/chunks 33 | 34 | limits_config: 35 | enforce_metric_name: false 36 | reject_old_samples: true 37 | reject_old_samples_max_age: 168h 38 | -------------------------------------------------------------------------------- /11-observability/exercise/mimir/mimir.yaml: -------------------------------------------------------------------------------- 1 | target: all,overrides-exporter 2 | 3 | common: 4 | storage: 5 | backend: s3 6 | s3: 7 | endpoint: minio:9000 8 | access_key_id: root 9 | secret_access_key: password123 10 | insecure: true 11 | 12 | limits: 13 | # Delete from storage metrics data older than 14 days. 14 | compactor_blocks_retention_period: 14d 15 | 16 | blocks_storage: 17 | s3: 18 | bucket_name: mimir-blocks 19 | tsdb: 20 | dir: /mimir/tsdb 21 | bucket_store: 22 | sync_dir: /mimir/bucket_store_sync 23 | 24 | alertmanager_storage: 25 | s3: 26 | bucket_name: mimir-alertmanager 27 | 28 | ruler_storage: 29 | s3: 30 | bucket_name: mimir-ruler 31 | 32 | ruler: 33 | rule_path: /mimir/rules 34 | 35 | compactor: 36 | data_dir: /mimir/compactor 37 | sharding_ring: 38 | kvstore: 39 | store: memberlist 40 | 41 | distributor: 42 | ring: 43 | instance_addr: 127.0.0.1 44 | kvstore: 45 | store: memberlist 46 | 47 | ingester: 48 | ring: 49 | instance_addr: 127.0.0.1 50 | kvstore: 51 | store: memberlist 52 | replication_factor: 1 53 | 54 | server: 55 | log_level: info 56 | http_listen_port: 9009 57 | 58 | store_gateway: 59 | sharding_ring: 60 | replication_factor: 1 61 | 62 | activity_tracker: 63 | # File where ongoing activities are stored. If empty, activity tracking is 64 | # disabled. 65 | filepath: /var/log/mimir/metrics-activity.log 66 | 67 | usage_stats: 68 | enabled: false 69 | -------------------------------------------------------------------------------- /11-observability/exercise/promtail/promtail.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | http_listen_port: 0 3 | grpc_listen_port: 0 4 | 5 | positions: 6 | filename: /tmp/positions.yaml 7 | 8 | clients: 9 | - url: "http://loki:3100/loki/api/v1/push" 10 | 11 | scrape_configs: 12 | - job_name: "Quarkus application logs" 13 | static_configs: 14 | - # TODO: Collect logs of tle-fetcher service 15 | - # TODO: Collect logs of sky-map service 16 | pipeline_stages: 17 | - # TODO: parse Json 18 | - timestamp: 19 | source: timestamp 20 | format: RFC3339Nano 21 | -------------------------------------------------------------------------------- /11-observability/exercise/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | val quarkusPluginVersion: String by settings 3 | val quarkusPluginId: String by settings 4 | repositories { 5 | mavenCentral() 6 | gradlePluginPortal() 7 | mavenLocal() 8 | } 9 | plugins { 10 | id(quarkusPluginId) version quarkusPluginVersion 11 | } 12 | } 13 | rootProject.name="observability-from-scratch" 14 | include("tle-fetcher") 15 | include("sky-map") 16 | 17 | -------------------------------------------------------------------------------- /11-observability/exercise/sky-map/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | java 3 | id("io.quarkus") 4 | } 5 | 6 | repositories { 7 | mavenCentral() 8 | mavenLocal() 9 | } 10 | 11 | val quarkusPlatformGroupId: String by project 12 | val quarkusPlatformArtifactId: String by project 13 | val quarkusPlatformVersion: String by project 14 | 15 | dependencies { 16 | implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")) 17 | 18 | implementation("io.quarkus:quarkus-arc") 19 | implementation("io.quarkus:quarkus-container-image-jib") 20 | implementation("io.quarkus:quarkus-hibernate-validator") 21 | implementation("io.quarkus:quarkus-rest-client-jsonb") 22 | implementation("io.quarkus:quarkus-rest-client") 23 | implementation("io.quarkus:quarkus-rest-jsonb") 24 | implementation("io.quarkus:quarkus-rest") 25 | implementation("io.quarkus:quarkus-smallrye-health") 26 | implementation("io.quarkus:quarkus-smallrye-openapi") 27 | implementation("io.quarkus:quarkus-logging-json") 28 | 29 | implementation("io.quarkus:quarkus-micrometer-registry-prometheus") 30 | 31 | compileOnly("org.projectlombok:lombok:1.18.42") 32 | annotationProcessor("org.projectlombok:lombok:1.18.42") 33 | 34 | implementation("com.github.davidmoten:predict4java:1.3.1") 35 | implementation("org.apache.commons:commons-math3:3.6.1") 36 | 37 | implementation("io.quarkus:quarkus-opentelemetry") 38 | } 39 | 40 | group = "de.qaware.cloudcomputing" 41 | version = "1.0.0" 42 | 43 | java { 44 | toolchain { 45 | languageVersion = JavaLanguageVersion.of("21") 46 | } 47 | } 48 | 49 | tasks.withType { 50 | systemProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager") 51 | } 52 | tasks.withType { 53 | options.encoding = "UTF-8" 54 | options.compilerArgs.add("-parameters") 55 | } 56 | -------------------------------------------------------------------------------- /11-observability/exercise/sky-map/src/main/java/de/qaware/cloudcomputing/health/LivenessProbe.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.health; 2 | 3 | import org.eclipse.microprofile.health.HealthCheck; 4 | import org.eclipse.microprofile.health.HealthCheckResponse; 5 | import org.eclipse.microprofile.health.Liveness; 6 | 7 | @Liveness 8 | public class LivenessProbe implements HealthCheck { 9 | 10 | @Override 11 | public HealthCheckResponse call() { 12 | return HealthCheckResponse.up("alive"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /11-observability/exercise/sky-map/src/main/java/de/qaware/cloudcomputing/parser/SatPosCalculator.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.parser; 2 | 3 | import com.github.amsacode.predict4java.*; 4 | import de.qaware.cloudcomputing.tle.TleMember; 5 | import io.opentelemetry.instrumentation.annotations.WithSpan; 6 | 7 | import jakarta.enterprise.context.ApplicationScoped; 8 | import jakarta.inject.Inject; 9 | import java.sql.Date; 10 | import java.time.LocalDate; 11 | 12 | @ApplicationScoped 13 | public class SatPosCalculator { 14 | 15 | @Inject 16 | TleParser tleParser; 17 | 18 | @WithSpan 19 | public SatPassTime getNextPass(TleMember tleRecord) throws SatNotFoundException { 20 | PassPredictor passPredictor = getPassPredictor(tleRecord); 21 | return passPredictor.nextSatPass(getNow()); 22 | } 23 | 24 | @WithSpan 25 | public SatPos getSatPos(TleMember tleRecord) throws SatNotFoundException { 26 | PassPredictor passPredictor = getPassPredictor(tleRecord); 27 | return passPredictor.getSatPos(getNow()); 28 | } 29 | 30 | private PassPredictor getPassPredictor(TleMember tleRecord) throws SatNotFoundException { 31 | TLE tle = tleParser.parseTLE(tleRecord); 32 | GroundStationPosition groundStationPosition = new GroundStationPosition(47, 12, 400, "Rosenheim"); 33 | return new PassPredictor(tle, groundStationPosition); 34 | } 35 | 36 | private static Date getNow() { 37 | return Date.valueOf(LocalDate.now()); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /11-observability/exercise/sky-map/src/main/java/de/qaware/cloudcomputing/parser/TleParser.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.parser; 2 | 3 | import com.github.amsacode.predict4java.TLE; 4 | import de.qaware.cloudcomputing.tle.TleMember; 5 | 6 | import jakarta.enterprise.context.ApplicationScoped; 7 | 8 | @ApplicationScoped 9 | public class TleParser { 10 | 11 | public TLE parseTLE(TleMember tleMember) { 12 | if (tleMember == null) { 13 | throw new IllegalArgumentException("tleMember"); 14 | } 15 | 16 | return new TLE(new String[]{tleMember.getName(), tleMember.getLine1(), tleMember.getLine2()}); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /11-observability/exercise/sky-map/src/main/java/de/qaware/cloudcomputing/tle/TleClient.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.tle; 2 | 3 | import io.opentelemetry.instrumentation.annotations.SpanAttribute; 4 | import io.opentelemetry.instrumentation.annotations.WithSpan; 5 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 6 | 7 | import jakarta.ws.rs.GET; 8 | import jakarta.ws.rs.Path; 9 | import jakarta.ws.rs.PathParam; 10 | 11 | @Path("/tle") 12 | @RegisterRestClient(configKey="tle-fetcher") 13 | public interface TleClient { 14 | 15 | @GET 16 | @Path("/{satelliteId}") 17 | @WithSpan 18 | TleMember getRecord(@PathParam("satelliteId") @SpanAttribute int satelliteId); 19 | } 20 | -------------------------------------------------------------------------------- /11-observability/exercise/sky-map/src/main/java/de/qaware/cloudcomputing/tle/TleMember.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.tle; 2 | 3 | import lombok.Data; 4 | 5 | import jakarta.json.bind.annotation.JsonbProperty; 6 | import java.util.Date; 7 | 8 | @Data 9 | public class TleMember { 10 | 11 | @JsonbProperty("@context") 12 | private String context; 13 | 14 | @JsonbProperty("@id") 15 | private String id; 16 | 17 | @JsonbProperty("@type") 18 | private String type; 19 | 20 | private int satelliteId; 21 | 22 | private String name; 23 | 24 | private Date date; 25 | 26 | private String line1; 27 | 28 | private String line2; 29 | } 30 | -------------------------------------------------------------------------------- /11-observability/exercise/sky-map/src/main/resources/META-INF/resources/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | } 4 | -------------------------------------------------------------------------------- /11-observability/exercise/sky-map/src/main/resources/META-INF/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /11-observability/exercise/sky-map/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.application.name=sky-map 2 | quarkus.application.version=1.0.0 3 | 4 | quarkus.container-image.additional-tags=latest 5 | quarkus.container-image.build=true 6 | quarkus.container-image.group=qaware 7 | quarkus.container-image.push=false 8 | 9 | quarkus.http.port=8088 10 | 11 | quarkus.jib.user=root 12 | quarkus.jib.platforms=linux/amd64,linux/arm64/v8 13 | 14 | quarkus.swagger-ui.always-include=true 15 | 16 | quarkus.log.console.enable=true 17 | quarkus.log.console.json=false 18 | quarkus.log.console.level=DEBUG 19 | 20 | quarkus.log.file.enable=true 21 | quarkus.log.file.json.exception-output-type=formatted 22 | quarkus.log.file.json=true 23 | quarkus.log.file.level=TRACE 24 | quarkus.log.file.path=/logs/application.log 25 | 26 | quarkus.log.file.json.additional-field."service.name".value=${quarkus.application.name} 27 | quarkus.log.file.json.additional-field."service.version".value=${quarkus.application.version} 28 | quarkus.log.file.json.additional-field."service.environment".value=local 29 | 30 | quarkus.micrometer.export.prometheus.path=/metrics 31 | 32 | quarkus.log.level=DEBUG 33 | 34 | quarkus.otel.enabled=true 35 | quarkus.otel.exporter.otlp.traces.endpoint=http://tempo:4317 36 | -------------------------------------------------------------------------------- /11-observability/exercise/solution/alloy.river: -------------------------------------------------------------------------------- 1 | // Create a prometheus.scrape component labeled "default." 2 | prometheus.scrape "default" { 3 | targets = [ 4 | {"__address__" = "tle-fetcher:8080"}, 5 | {"__address__" = "sky-map:8088"}, 6 | ] 7 | 8 | forward_to = [prometheus.remote_write.mimir.receiver] 9 | } 10 | 11 | // Send metrics to a Prometheus remote_write endpoint. 12 | prometheus.remote_write "mimir" { 13 | endpoint { 14 | url = "http://mimir:9009/api/v1/push" 15 | headers = { 16 | "X-Scope-OrgID" = "1", 17 | } 18 | } 19 | } 20 | 21 | logging { 22 | level = "info" 23 | format = "logfmt" 24 | } 25 | -------------------------------------------------------------------------------- /11-observability/exercise/tle-fetcher/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | java 3 | id("io.quarkus") 4 | } 5 | 6 | repositories { 7 | mavenCentral() 8 | mavenLocal() 9 | } 10 | 11 | val quarkusPlatformGroupId: String by project 12 | val quarkusPlatformArtifactId: String by project 13 | val quarkusPlatformVersion: String by project 14 | 15 | dependencies { 16 | implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")) 17 | 18 | implementation("io.quarkus:quarkus-rest-client-jsonb") 19 | implementation("io.quarkus:quarkus-rest-client") 20 | implementation("io.quarkus:quarkus-rest-jsonb") 21 | implementation("io.quarkus:quarkus-rest") 22 | implementation("io.quarkus:quarkus-smallrye-health") 23 | implementation("io.quarkus:quarkus-arc") 24 | implementation("io.quarkus:quarkus-container-image-jib") 25 | implementation("io.quarkus:quarkus-smallrye-openapi") 26 | implementation("io.quarkus:quarkus-logging-json") 27 | 28 | implementation("io.quarkus:quarkus-micrometer-registry-prometheus") 29 | 30 | implementation("io.quarkus:quarkus-opentelemetry") 31 | 32 | compileOnly("org.projectlombok:lombok:1.18.36") 33 | annotationProcessor("org.projectlombok:lombok:1.18.36") 34 | } 35 | 36 | group = "de.qaware.cloudcomputing" 37 | version = "1.0.0" 38 | 39 | java { 40 | sourceCompatibility = JavaVersion.VERSION_21 41 | targetCompatibility = JavaVersion.VERSION_21 42 | } 43 | 44 | tasks.withType { 45 | systemProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager") 46 | } 47 | tasks.withType { 48 | options.encoding = "UTF-8" 49 | options.compilerArgs.add("-parameters") 50 | } 51 | -------------------------------------------------------------------------------- /11-observability/exercise/tle-fetcher/src/main/java/de/qaware/cloudcomputing/TleResource.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing; 2 | 3 | import de.qaware.cloudcomputing.tle.TleMember; 4 | import de.qaware.cloudcomputing.tle.TleSearchResult; 5 | import de.qaware.cloudcomputing.tle.TleService; 6 | import io.opentelemetry.instrumentation.annotations.WithSpan; 7 | import lombok.extern.jbosslog.JBossLog; 8 | import org.eclipse.microprofile.rest.client.inject.RestClient; 9 | 10 | import jakarta.inject.Inject; 11 | import jakarta.ws.rs.GET; 12 | import jakarta.ws.rs.Path; 13 | import jakarta.ws.rs.PathParam; 14 | import jakarta.ws.rs.Produces; 15 | import jakarta.ws.rs.QueryParam; 16 | import jakarta.ws.rs.core.MediaType; 17 | 18 | @JBossLog 19 | @Path("/tle") 20 | public class TleResource { 21 | 22 | @Inject 23 | @RestClient 24 | TleService tleService; 25 | 26 | @GET 27 | @Produces(MediaType.APPLICATION_JSON) 28 | @WithSpan 29 | public TleSearchResult search(@QueryParam("searchString") String searchString) { 30 | log.tracev("Processing request GET /tle?searchString with parameter {0}", searchString); 31 | 32 | TleSearchResult searchResult = tleService.search(searchString); 33 | 34 | log.debugv("Retrieved search result {0} with {1} items", searchResult.getId(), searchResult.getTotalItems()); 35 | 36 | return searchResult; 37 | } 38 | 39 | @GET 40 | @Path("/{satelliteId}") 41 | @WithSpan 42 | public TleMember getRecord(@PathParam("satelliteId") int satelliteId) { 43 | log.tracev("Processing request GET /tle/{satelliteId} with parameter {0}", satelliteId); 44 | 45 | TleMember record = tleService.getRecord(satelliteId); 46 | 47 | log.debugv("Retrieved TLE record for satellite {0} (ID {1})", record.getName(), record.getSatelliteId()); 48 | 49 | return record; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /11-observability/exercise/tle-fetcher/src/main/java/de/qaware/cloudcomputing/health/LivenessProbe.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.health; 2 | 3 | import org.eclipse.microprofile.health.HealthCheck; 4 | import org.eclipse.microprofile.health.HealthCheckResponse; 5 | import org.eclipse.microprofile.health.Liveness; 6 | 7 | @Liveness 8 | public class LivenessProbe implements HealthCheck { 9 | 10 | @Override 11 | public HealthCheckResponse call() { 12 | return HealthCheckResponse.up("alive"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /11-observability/exercise/tle-fetcher/src/main/java/de/qaware/cloudcomputing/tle/TleMember.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.tle; 2 | 3 | import lombok.Data; 4 | 5 | import jakarta.json.bind.annotation.JsonbProperty; 6 | import java.util.Date; 7 | 8 | @Data 9 | public class TleMember { 10 | 11 | @JsonbProperty("@id") 12 | String id; 13 | 14 | @JsonbProperty("@type") 15 | String type; 16 | 17 | int satelliteId; 18 | 19 | String name; 20 | 21 | Date date; 22 | 23 | String line1; 24 | 25 | String line2; 26 | } 27 | -------------------------------------------------------------------------------- /11-observability/exercise/tle-fetcher/src/main/java/de/qaware/cloudcomputing/tle/TleSearchResult.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.tle; 2 | 3 | import lombok.Data; 4 | 5 | import jakarta.json.bind.annotation.JsonbProperty; 6 | import java.util.List; 7 | 8 | @Data 9 | public class TleSearchResult { 10 | 11 | @JsonbProperty("@context") 12 | String context; 13 | 14 | @JsonbProperty("@id") 15 | String id; 16 | 17 | @JsonbProperty("@type") 18 | String type; 19 | 20 | int totalItems; 21 | 22 | List member; 23 | } 24 | -------------------------------------------------------------------------------- /11-observability/exercise/tle-fetcher/src/main/java/de/qaware/cloudcomputing/tle/TleService.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.tle; 2 | 3 | import io.opentelemetry.instrumentation.annotations.WithSpan; 4 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 5 | 6 | import jakarta.ws.rs.GET; 7 | import jakarta.ws.rs.Path; 8 | import jakarta.ws.rs.PathParam; 9 | import jakarta.ws.rs.QueryParam; 10 | 11 | @RegisterRestClient(baseUri = "https://tle.ivanstanojevic.me/api") 12 | public interface TleService { 13 | 14 | @GET 15 | @Path("/tle/") 16 | @WithSpan 17 | TleSearchResult search(@QueryParam("search") String search); 18 | 19 | @GET 20 | @Path("/tle/{satelliteId}") 21 | @WithSpan 22 | TleMember getRecord(@PathParam("satelliteId") int satelliteId); 23 | } 24 | -------------------------------------------------------------------------------- /11-observability/exercise/tle-fetcher/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.application.name=tle-fetcher 2 | quarkus.application.version=1.0.0 3 | 4 | quarkus.container-image.additional-tags=latest 5 | quarkus.container-image.build=true 6 | quarkus.container-image.group=qaware 7 | quarkus.container-image.push=false 8 | 9 | quarkus.jib.user=root 10 | quarkus.jib.platforms=linux/amd64,linux/arm64/v8 11 | 12 | quarkus.swagger-ui.always-include=true 13 | 14 | quarkus.log.console.enable=true 15 | quarkus.log.console.json=false 16 | quarkus.log.console.level=DEBUG 17 | 18 | quarkus.log.file.enable=true 19 | quarkus.log.file.json.exception-output-type=formatted 20 | quarkus.log.file.json=true 21 | quarkus.log.file.level=TRACE 22 | quarkus.log.file.path=/logs/application.log 23 | 24 | quarkus.log.file.json.additional-field."service.name".value=${quarkus.application.name} 25 | quarkus.log.file.json.additional-field."service.version".value=${quarkus.application.version} 26 | quarkus.log.file.json.additional-field."service.environment".value=local 27 | 28 | quarkus.micrometer.export.prometheus.path=/metrics 29 | 30 | quarkus.log.level=DEBUG 31 | 32 | quarkus.otel.enabled=true 33 | quarkus.otel.exporter.otlp.traces.endpoint=http://tempo:4317 34 | -------------------------------------------------------------------------------- /11-observability/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text 2 | m09-observability.pdf filter=lfs diff=lfs merge=lfs -text 3 | -------------------------------------------------------------------------------- /11-observability/lecture/11 Observability.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/11-observability/lecture/11 Observability.pdf -------------------------------------------------------------------------------- /12-serverless/exercise/src/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/terraform 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=terraform 3 | 4 | ### Terraform ### 5 | # Local .terraform directories 6 | **/.terraform/* 7 | 8 | # .tfstate files 9 | *.tfstate 10 | *.tfstate.* 11 | 12 | # Crash log files 13 | crash.log 14 | crash.*.log 15 | 16 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 17 | # password, private keys, and other secrets. These should not be part of version 18 | # control as they are data points which are potentially sensitive and subject 19 | # to change depending on the environment. 20 | *.tfvars 21 | *.tfvars.json 22 | 23 | # Ignore override files as they are usually used to override resources locally and so 24 | # are not checked in 25 | override.tf 26 | override.tf.json 27 | *_override.tf 28 | *_override.tf.json 29 | 30 | # Include override files you do wish to add to version control using negated pattern 31 | # !example_override.tf 32 | 33 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 34 | # example: *tfplan* 35 | 36 | # Ignore CLI configuration files 37 | .terraformrc 38 | terraform.rc 39 | 40 | # End of https://www.toptal.com/developers/gitignore/api/terraform -------------------------------------------------------------------------------- /12-serverless/exercise/src/hello.mjs: -------------------------------------------------------------------------------- 1 | export const handler = async (event) => { 2 | // TODO implement 3 | const response = { 4 | statusCode: 200, 5 | body: JSON.stringify('Hello from terraform Lambda!'), 6 | }; 7 | return response; 8 | }; -------------------------------------------------------------------------------- /12-serverless/exercise/src/lambda.tf: -------------------------------------------------------------------------------- 1 | ### Searches for an existing role named `BasicLambdaExecutionRole` 2 | data aws_iam_role iam_for_lambda { 3 | name = "BasicLambdaExecutionRole" 4 | } 5 | 6 | ### Terraform's way of packaging files into an archive - in this case we are packaging the JS source code 7 | ### for the lambda function. 8 | data "archive_file" "lambda" { 9 | type = "zip" 10 | source_file = "hello.mjs" 11 | output_path = "lambda_function_payload.zip" 12 | } 13 | 14 | ### Creates the lambda function 15 | resource "aws_lambda_function" "hello_world" { 16 | filename = "lambda_function_payload.zip" 17 | function_name = "" ### TODO enter a unique name here 18 | # references the role, that is queried above 19 | role = data.aws_iam_role.iam_for_lambda.arn 20 | # reference into the js file, format is ${filename}.{export-name} 21 | handler = "hello.handler" 22 | 23 | source_code_hash = data.archive_file.lambda.output_base64sha256 24 | 25 | runtime = "nodejs20.x" 26 | } 27 | 28 | ### Creates a cloudwatch log group for the lambda. 29 | ### While not referenced anywhere else, the lambda function will log in there based on its name. 30 | resource "aws_cloudwatch_log_group" "hello_world" { 31 | name = "/aws/lambda/${aws_lambda_function.hello_world.function_name}" 32 | 33 | retention_in_days = 7 34 | } -------------------------------------------------------------------------------- /12-serverless/exercise/src/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.8.0" 3 | 4 | required_providers { 5 | aws = { 6 | # https://github.com/hashicorp/terraform-provider-aws/blob/main/CHANGELOG.md 7 | source = "hashicorp/aws" 8 | version = "5.50.0" 9 | } 10 | } 11 | } 12 | 13 | provider "aws" { 14 | region = "eu-central-1" 15 | } 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /12-serverless/exercise/src/outputs.tf: -------------------------------------------------------------------------------- 1 | output "function_name" { 2 | description = "Name of the Lambda function." 3 | 4 | value = aws_lambda_function.hello_world.function_name 5 | } 6 | 7 | output "gateway_domain" { 8 | description = "Host of the provisioned API gateway" 9 | 10 | value = aws_apigatewayv2_api.lambda.api_endpoint 11 | } -------------------------------------------------------------------------------- /12-serverless/lecture/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /12-serverless/lecture/12 Serverless.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/12-serverless/lecture/12 Serverless.pdf -------------------------------------------------------------------------------- /13-summary/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /13-summary/Cloud Computing 2024_25 - Summary.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/13-summary/Cloud Computing 2024_25 - Summary.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Josef Adersberger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /WiSe2425-Cloud-Computing.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/WiSe2425-Cloud-Computing.pptx -------------------------------------------------------------------------------- /archive/100-project-template/.env: -------------------------------------------------------------------------------- 1 | MASTODON_INSTANCE_HOSTNAME= # enter your mastodon instance host name 2 | MASTODON_ACCESS_TOKEN= # enter your mastodon access token here 3 | -------------------------------------------------------------------------------- /archive/100-project-template/Tiltfile: -------------------------------------------------------------------------------- 1 | load('ext://dotenv', 'dotenv') 2 | dotenv() 3 | 4 | # Installing the nginx ingress controller 5 | k8s_yaml('nginx-ingress-controller.yaml') 6 | # Labelling the resources for prettier grouping in the UI 7 | k8s_resource(workload='ingress-nginx-controller', labels=['nginx-ingress-controller']) 8 | k8s_resource(workload='ingress-nginx-admission-create', labels=['nginx-ingress-controller']) 9 | k8s_resource(workload='ingress-nginx-admission-patch', labels=['nginx-ingress-controller']) 10 | 11 | # Load the 'secret' extension 12 | load('ext://secret', 'secret_create_generic', 'secret_from_dict') 13 | # Create a secret from a dict 14 | k8s_yaml(secret_from_dict("troetbot-secrets", inputs={'MASTODON_ACCESS_TOKEN': os.getenv('MASTODON_ACCESS_TOKEN')})) 15 | 16 | # Load the 'configmap' extension 17 | load('ext://configmap', 'configmap_from_dict') 18 | # Create a configmap from a dict 19 | k8s_yaml(configmap_from_dict('troetbot-config', inputs={'MASTODON_INSTANCE_HOSTNAME': os.getenv('MASTODON_INSTANCE_HOSTNAME')})) 20 | 21 | # Deploy the troetbot 22 | load_dynamic('../troetbot/Tiltfile') 23 | -------------------------------------------------------------------------------- /archive/99-big-data/loesung/README.md: -------------------------------------------------------------------------------- 1 | # Übung 1: MapReduce 2 | 3 | Schritt 1: Normalize 4 | 5 | ``` 6 | "o tannenbaum o tannenbaum" 7 | "wie grün sind deine blätter" 8 | "du grünst nicht nur zur sommerszeit" 9 | "nein auch im winter wenn es schneit" 10 | "o tannenbaum o tannenbaum" 11 | "wie grün sind deine blätter" 12 | ``` 13 | 14 | Schritt 2: Map 15 | 16 | ``` 17 | 1: [("o", 1), ("tannenbaum", 1), ("o", 1), ("tannenbaum", 1)] 18 | 2: [("wie", 1), ("grün", 1), ("sind", 1), ("deine", 1), ("blätter", 1)] 19 | 3: [("du", 1), ("grünst", 1), ("nicht", 1), ("nur", 1), ("zur", 1), ("sommerszeit", 1)] 20 | 4: [("nein", 1), ("auch", 1), ("im", 1), ("winter", 1), ("wenn", 1), ("es", 1), ("schneit", 1)] 21 | 5: [("o", 1), ("tannenbaum", 1), ("o", 1), ("tannenbaum", 1)] 22 | 6: [("wie", 1), ("grün", 1), ("sind", 1), ("deine", 1), ("blätter", 1)] 23 | ``` 24 | 25 | Schritt 3: Reduce 26 | 27 | ``` 28 | ("o", 4) 29 | ("tannenbaum", 4) 30 | ("wie", 2) 31 | ("grün", 2) 32 | ("sind", 2) 33 | ("deine", 2) 34 | ("blätter", 2) 35 | ("du", 1) 36 | ("grünst", 1) 37 | ("nicht", 1) 38 | ("nur", 1) 39 | ("zur", 1) 40 | ("sommerszeit", 1) 41 | ("nein", 1) 42 | ("auch", 1) 43 | ("im", 1) 44 | ("winter", 1) 45 | ("wenn", 1) 46 | ("es", 1) 47 | ("schneit", 1) 48 | ``` 49 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # These are explicitly windows files and should use crlf 5 | *.bat text eol=crlf 6 | 7 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/.run/HelloWorld.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/.run/WordCountMapReduce.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/.run/WordCountStreaming.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/.run/WordStreamCounter.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/build.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * This generated file contains a sample Java application project to get you started. 5 | * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle 6 | * User Manual available at https://docs.gradle.org/7.3/userguide/building_java_projects.html 7 | * This project uses @Incubating APIs which are subject to change. 8 | */ 9 | 10 | plugins { 11 | // Apply the groovy plugin to also add support for Groovy (needed for Spock) 12 | groovy 13 | 14 | // Apply the application plugin to add support for building a CLI application in Java. 15 | application 16 | } 17 | 18 | repositories { 19 | // Use Maven Central for resolving dependencies. 20 | mavenCentral() 21 | } 22 | 23 | dependencies { 24 | // Apache Ignite 25 | implementation("org.apache.ignite:ignite-core:2.15.0") 26 | implementation("org.apache.ignite:ignite-indexing:2.15.0") 27 | 28 | // Apache Commons 29 | implementation("org.apache.commons:commons-collections4:4.4") 30 | implementation("commons-io:commons-io:2.15.1") 31 | implementation("org.apache.commons:commons-lang3:3.14.0") 32 | } 33 | 34 | application { 35 | // Define the main class for the application. 36 | mainClass.set("de.qaware.cloudcomputing.bigdata.HelloWorld") 37 | 38 | applicationDefaultJvmArgs = listOf("--add-opens", "java.base/java.nio=ALL-UNNAMED") 39 | } 40 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | ignite: 4 | build: "src/main/ignite" 5 | entrypoint: 6 | - "/usr/share/apache-ignite/bin/ignite.sh" 7 | - "/config/ignite.xml" 8 | environment: 9 | - "JVM_OPTS=-Xms1g -Xmx1g -Djava.net.preferIPv4Stack=true" 10 | ports: 11 | - "8787:8787" 12 | - "11211:11211" 13 | - "47100:47100" 14 | - "47500:47500" 15 | - "49112:49112" 16 | - "49113:49113" 17 | - "49114:49114" 18 | volumes: 19 | - "./src/main/ignite/config:/config" 20 | networks: 21 | - ignitenet 22 | 23 | networks: 24 | ignitenet: 25 | driver: bridge 26 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-big-data/uebung/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /archive/99-big-data/uebung/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/7.3/userguide/multi_project_builds.html 8 | * This project uses @Incubating APIs which are subject to change. 9 | */ 10 | 11 | rootProject.name = "cloud-computing-big-data" 12 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/src/main/ignite/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y gnupg ca-certificates && \ 5 | echo "deb http://apache.org/dist/ignite/deb/ apache-ignite main" > /etc/apt/sources.list.d/ignite.list && \ 6 | apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0EE62FB37A00258D && \ 7 | apt-get update && \ 8 | apt-get install -y --no-install-recommends openjdk-11-jdk apache-ignite && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | ENTRYPOINT /usr/share/apache-ignite/bin/ignite.sh 12 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/src/main/ignite/config/ignite.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /archive/99-big-data/uebung/src/main/java/de/qaware/cloudcomputing/bigdata/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package de.qaware.cloudcomputing.bigdata.util; 2 | 3 | import de.qaware.cloudcomputing.bigdata.WordCountMapReduce; 4 | import org.apache.commons.io.IOUtils; 5 | import org.apache.commons.lang3.StringUtils; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.net.URL; 10 | import java.nio.charset.StandardCharsets; 11 | 12 | public class FileUtil { 13 | 14 | public static String readFileFromResources(String fileName) { 15 | if (StringUtils.isEmpty(fileName)) { 16 | throw new IllegalArgumentException("fileName must not be empty!"); 17 | } 18 | 19 | try { 20 | URL url = WordCountMapReduce.class.getClassLoader().getResource(fileName); 21 | return IOUtils.toString(url, StandardCharsets.UTF_8); 22 | } catch (IOException e) { 23 | throw new RuntimeException(e); 24 | } 25 | } 26 | 27 | public static InputStream readFileFromResourcesAsStream(String fileName) { 28 | if (StringUtils.isEmpty(fileName)) { 29 | throw new IllegalArgumentException("fileName must not be empty!"); 30 | } 31 | 32 | return WordCountMapReduce.class.getClassLoader().getResourceAsStream(fileName); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /archive/99-big-data/vorlesung/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /archive/99-big-data/vorlesung/m11-bigdata.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-big-data/vorlesung/m11-bigdata.pdf -------------------------------------------------------------------------------- /archive/99-ci-cd_serverless/uebung/README.md: -------------------------------------------------------------------------------- 1 | # Übung: Continuous Deployment mit GitHub Actions 2 | 3 | 1. Suchen Sie sich einen fertigen Service aus Ihrem Fundus aus, für den Sie eine Deployment-Pipeline bauen möchten. Alternativ können Sie auch das [Neinhorn](https://github.com/zalintyre/neinhorn) forken. 4 | 2. Schreiben Sie eine Pipeline, die GitHub Actions verwendet, um den Service zu bauen. Die Dokumentation dazu finden Sie [hier](https://docs.github.com/de/actions). 5 | 3. Integrieren Sie ein [Deployment auf Heroku](https://github.com/marketplace/actions/deploy-to-heroku) in die Pipeline. 6 | -------------------------------------------------------------------------------- /archive/99-ci-cd_serverless/vorlesung/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /archive/99-ci-cd_serverless/vorlesung/11 DevOps & Continuous Delivery.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-ci-cd_serverless/vorlesung/11 DevOps & Continuous Delivery.pdf -------------------------------------------------------------------------------- /archive/99-cluster-scheduling/uebung/binpacking/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /archive/99-cluster-scheduling/uebung/binpacking/First Fit DecreasingV2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-cluster-scheduling/uebung/binpacking/First Fit DecreasingV2.pdf -------------------------------------------------------------------------------- /archive/99-cluster-scheduling/uebung/binpacking/Scheduling – Next Fit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-cluster-scheduling/uebung/binpacking/Scheduling – Next Fit.pdf -------------------------------------------------------------------------------- /archive/99-cluster-scheduling/uebung/binpacking/Worst Fit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-cluster-scheduling/uebung/binpacking/Worst Fit.pdf -------------------------------------------------------------------------------- /archive/99-cluster-scheduling/uebung/binpacking/cloudcomputing_scheduling_best_fit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-cluster-scheduling/uebung/binpacking/cloudcomputing_scheduling_best_fit.pdf -------------------------------------------------------------------------------- /archive/99-cluster-scheduling/vorlesung/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /archive/99-cluster-scheduling/vorlesung/m05-cluster-scheduling.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-cluster-scheduling/vorlesung/m05-cluster-scheduling.pdf -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-programmiermodelle/uebung-optional/loesung/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=bin 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar 5 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/src/main/java/edu/qaware/cc/reactive/Main.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive; 2 | 3 | import edu.qaware.cc.reactive.connector.openlibrary.OpenLibraryConnector; 4 | import edu.qaware.cc.reactive.connector.wikipedia.WikipediaConnector; 5 | 6 | import java.time.Duration; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Sammelt aus Wikipedia und bestimmten Feedzilla-Kategorien Meldungen 12 | * sequenziell zusammen und gibt diese dann auf der Konsole aus. 13 | * 14 | * @author Josef Adersberger 15 | */ 16 | public class Main { 17 | /** 18 | * Die Einstiegsmethode 19 | * 20 | * @param args es werden keine Kommandozeilen-Argumente ausgewertet 21 | */ 22 | public static void main(String[] args) { 23 | String term = "Reactive"; 24 | long start = System.nanoTime(); 25 | 26 | WikipediaConnector connector = new WikipediaConnector(); 27 | List results = new ArrayList<>(connector.getArticleTitlesFor(term)); 28 | 29 | OpenLibraryConnector openLibrary = new OpenLibraryConnector(); 30 | results.addAll(openLibrary.getBooksWithTitleContaining(term)); 31 | 32 | System.out.println(results.size() + " items found"); 33 | for (String s : results) { 34 | System.out.println(s); 35 | } 36 | 37 | System.out.println("Duration to collect results: " + Duration.ofNanos(System.nanoTime() - start).toMillis() + " ms"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/src/main/java/edu/qaware/cc/reactive/actor/OpenLibraryActor.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive.actor; 2 | 3 | import akka.actor.UntypedAbstractActor; 4 | import edu.qaware.cc.reactive.connector.openlibrary.OpenLibraryConnector; 5 | import edu.qaware.cc.reactive.message.SearchMessage; 6 | import edu.qaware.cc.reactive.message.SearchResultMessage; 7 | 8 | import java.util.List; 9 | 10 | public class OpenLibraryActor extends UntypedAbstractActor { 11 | private final OpenLibraryConnector connector = new OpenLibraryConnector(); 12 | 13 | @Override 14 | public void onReceive(Object message) { 15 | if (message instanceof SearchMessage) { 16 | // This message is sent from MessageCollectorActor 17 | handleSearchMessage((SearchMessage) message); 18 | } else { 19 | unhandled(message); 20 | } 21 | } 22 | 23 | private void handleSearchMessage(SearchMessage message) { 24 | List results = connector.getBooksWithTitleContaining(message.getTerm()); 25 | 26 | getSender().tell(new SearchResultMessage(results), self()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/src/main/java/edu/qaware/cc/reactive/actor/WikipediaActor.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive.actor; 2 | 3 | import akka.actor.UntypedAbstractActor; 4 | import edu.qaware.cc.reactive.connector.wikipedia.WikipediaConnector; 5 | import edu.qaware.cc.reactive.message.SearchMessage; 6 | import edu.qaware.cc.reactive.message.SearchResultMessage; 7 | 8 | import java.util.List; 9 | 10 | public class WikipediaActor extends UntypedAbstractActor { 11 | private final WikipediaConnector connector = new WikipediaConnector(); 12 | 13 | @Override 14 | public void onReceive(Object message) { 15 | if (message instanceof SearchMessage) { 16 | // This message is sent from MessageCollectorActor 17 | handleSearchMessage((SearchMessage) message); 18 | } else { 19 | unhandled(message); 20 | } 21 | } 22 | 23 | private void handleSearchMessage(SearchMessage message) { 24 | List results = connector.getArticleTitlesFor(message.getTerm()); 25 | 26 | getSender().tell(new SearchResultMessage(results), self()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/src/main/java/edu/qaware/cc/reactive/message/SearchMessage.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive.message; 2 | 3 | /** 4 | * Message which is sent from MainWithActors to MessageCollectorActor 5 | * and from MessageCollectorActor to OpenLibraryActor and WikipediaActor. 6 | */ 7 | public class SearchMessage { 8 | private final String term; 9 | 10 | public SearchMessage(String term) { 11 | this.term = term; 12 | } 13 | 14 | public String getTerm() { 15 | return term; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/src/main/java/edu/qaware/cc/reactive/message/SearchResultMessage.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive.message; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Message which is sent from OpenLibraryActor and WikipediaActor to MessageCollectorActor and 7 | * from MessageCollectorActor to MainWithActors. 8 | */ 9 | public class SearchResultMessage { 10 | private final List results; 11 | 12 | public SearchResultMessage(List results) { 13 | this.results = List.copyOf(results); 14 | } 15 | 16 | public List getResults() { 17 | return results; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = "DEBUG" 3 | actor { 4 | debug { 5 | receive = on 6 | autoreceive = on 7 | lifecycle = on 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/src/test/java/edu/qaware/cc/reactive/OpenLibraryConnectorTest.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive; 2 | 3 | import edu.qaware.cc.reactive.connector.openlibrary.OpenLibraryConnector; 4 | import org.junit.Test; 5 | 6 | import java.util.List; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | public class OpenLibraryConnectorTest { 11 | 12 | @Test 13 | public void testFetchBooksWithTitle() { 14 | OpenLibraryConnector connector = new OpenLibraryConnector(); 15 | List result = connector.getBooksWithTitleContaining("Java Programming"); 16 | 17 | assertThat(result).isNotEmpty(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/loesung/src/test/java/edu/qaware/cc/reactive/WikipediaConnectorTest.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive; 2 | 3 | import edu.qaware.cc.reactive.connector.wikipedia.WikipediaConnector; 4 | import org.junit.Test; 5 | 6 | import java.util.List; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | public class WikipediaConnectorTest { 11 | @Test 12 | public void testConnector() { 13 | WikipediaConnector connector = new WikipediaConnector(); 14 | List result = connector.getArticleTitlesFor("Java"); 15 | assertThat(result).isNotEmpty(); 16 | } 17 | } -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-programmiermodelle/uebung-optional/vorlage/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=bin 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar 5 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/src/main/java/edu/qaware/cc/reactive/Main.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive; 2 | 3 | import edu.qaware.cc.reactive.connectors.openlibrary.OpenLibraryConnector; 4 | import edu.qaware.cc.reactive.connectors.wikipedia.WikipediaConnector; 5 | 6 | import java.time.Duration; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Sammelt aus Wikipedia und bestimmten Feedzilla-Kategorien Meldungen 12 | * sequenziell zusammen und gibt diese dann auf der Konsole aus. 13 | * 14 | * @author Josef Adersberger 15 | */ 16 | public class Main { 17 | 18 | /** 19 | * Die Einstiegsmethode 20 | * 21 | * @param args es werden keine Kommandozeilen-Argumente ausgewertet 22 | */ 23 | public static void main(String[] args) { 24 | String term = "Reactive"; 25 | long start = System.nanoTime(); 26 | 27 | WikipediaConnector connector = new WikipediaConnector(); 28 | List results = new ArrayList<>(connector.getArticleTitlesFor(term)); 29 | 30 | OpenLibraryConnector openLibrary = new OpenLibraryConnector(); 31 | results.addAll(openLibrary.getBooksWithTitleContaining(term)); 32 | 33 | System.out.println(results.size() + " items found"); 34 | for (String s : results) { 35 | System.out.println(s); 36 | } 37 | 38 | System.out.println("Duration to collect results: " + Duration.ofNanos(System.nanoTime() - start).toMillis() + " ms"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/src/main/java/edu/qaware/cc/reactive/MainWithActors.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.ActorSystem; 5 | import akka.actor.Props; 6 | import akka.util.Timeout; 7 | import edu.qaware.cc.reactive.actors.MessageCollectorActor; 8 | import scala.concurrent.Await; 9 | 10 | import java.time.Duration; 11 | import java.util.List; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | import static akka.japi.Util.classTag; 15 | import static akka.pattern.Patterns.ask; 16 | 17 | /** 18 | * Sammelt die Nachrichten über ein akka Aktorensystem zusammen 19 | */ 20 | public class MainWithActors { 21 | @SuppressWarnings("unchecked") 22 | public static void main(String[] args) throws Exception { 23 | ActorSystem actorSystem = ActorSystem.create("Reactive"); 24 | ActorRef messageCollector = actorSystem.actorOf(Props.create(MessageCollectorActor.class), "Message-Collector"); 25 | 26 | long start = System.nanoTime(); 27 | Timeout timeout = new Timeout(30, TimeUnit.SECONDS); 28 | var resultFuture = ask(messageCollector, "Reactive", timeout).mapTo(classTag(List.class)); 29 | List result = (List) Await.result(resultFuture, timeout.duration()); 30 | 31 | System.out.println(result.size() + " items found"); 32 | for (String message : result) { 33 | System.out.println(message); 34 | } 35 | 36 | System.out.println("Duration to collect results (reactive): " + Duration.ofNanos(System.nanoTime() - start).toMillis() + " ms"); 37 | 38 | Await.ready(actorSystem.terminate(), scala.concurrent.duration.Duration.Inf()); 39 | } 40 | } -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/src/main/java/edu/qaware/cc/reactive/actors/MessageCollectorActor.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive.actors; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.actor.UntypedAbstractActor; 6 | 7 | public class MessageCollectorActor extends UntypedAbstractActor { 8 | private ActorRef wikipedia; 9 | private ActorRef openlibrary; 10 | 11 | @Override 12 | public void preStart() throws Exception { 13 | wikipedia = getContext().actorOf(Props.create(WikipediaActor.class), "Wikipedia"); 14 | openlibrary = getContext().actorOf(Props.create(OpenLibraryActor.class), "OpenLibrary"); 15 | } 16 | 17 | @Override 18 | public void onReceive(Object message) throws Exception { 19 | //TODO 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/src/main/java/edu/qaware/cc/reactive/actors/OpenLibraryActor.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive.actors; 2 | 3 | import akka.actor.UntypedAbstractActor; 4 | import edu.qaware.cc.reactive.connectors.openlibrary.OpenLibraryConnector; 5 | 6 | public class OpenLibraryActor extends UntypedAbstractActor { 7 | 8 | private final OpenLibraryConnector connector = new OpenLibraryConnector(); 9 | 10 | @Override 11 | public void onReceive(Object message) throws Exception { 12 | //TODO 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/src/main/java/edu/qaware/cc/reactive/actors/WikipediaActor.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive.actors; 2 | 3 | import akka.actor.UntypedAbstractActor; 4 | import edu.qaware.cc.reactive.connectors.wikipedia.WikipediaConnector; 5 | 6 | public class WikipediaActor extends UntypedAbstractActor { 7 | 8 | private final WikipediaConnector connector = new WikipediaConnector(); 9 | 10 | @Override 11 | public void onReceive(Object message) throws Exception { 12 | //TODO 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = "DEBUG" 3 | actor { 4 | debug { 5 | receive = on 6 | autoreceive = on 7 | lifecycle = on 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/src/test/java/edu/qaware/cc/reactive/OpenLibraryConnectorTest.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive; 2 | 3 | import edu.qaware.cc.reactive.connectors.openlibrary.OpenLibraryConnector; 4 | import org.junit.Test; 5 | 6 | import java.util.List; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | public class OpenLibraryConnectorTest { 11 | 12 | @Test 13 | public void testFetchBooksWithTitle() { 14 | OpenLibraryConnector connector = new OpenLibraryConnector(); 15 | List result = connector.getBooksWithTitleContaining("Java Programming"); 16 | 17 | assertThat(result).isNotEmpty(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/vorlage/src/test/java/edu/qaware/cc/reactive/WikipediaConnectorTest.java: -------------------------------------------------------------------------------- 1 | package edu.qaware.cc.reactive; 2 | 3 | import edu.qaware.cc.reactive.connectors.wikipedia.WikipediaConnector; 4 | import org.junit.Test; 5 | 6 | import java.util.List; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | public class WikipediaConnectorTest { 11 | @Test 12 | public void testConnector() { 13 | WikipediaConnector connector = new WikipediaConnector(); 14 | List result = connector.getArticleTitlesFor("Java"); 15 | assertThat(result).isNotEmpty(); 16 | } 17 | } -------------------------------------------------------------------------------- /archive/99-programmiermodelle/uebung-optional/ziel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-programmiermodelle/uebung-optional/ziel.png -------------------------------------------------------------------------------- /archive/99-programmiermodelle/vorlesung/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /archive/99-programmiermodelle/vorlesung/m12-programmiermodelle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/99-programmiermodelle/vorlesung/m12-programmiermodelle.pdf -------------------------------------------------------------------------------- /archive/projektarbeit/.gitattributes: -------------------------------------------------------------------------------- 1 | *.{png,,jpg,jpeg,gif,pdf,doc,docx,ppt,pptx,xls,xlsx} filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /archive/projektarbeit/Projekt.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/archive/projektarbeit/Projekt.pdf -------------------------------------------------------------------------------- /cloud-computing.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": {} 8 | } -------------------------------------------------------------------------------- /vl-cc-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/vl-cc-logo.jpg -------------------------------------------------------------------------------- /vl-cc-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qaware/cloud-computing-th-rosenheim/a8bfb567cf429c94151b36cda7d46d7fde919708/vl-cc-logo.png --------------------------------------------------------------------------------