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 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/archive/99-big-data/uebung/.run/WordCountMapReduce.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/archive/99-big-data/uebung/.run/WordCountStreaming.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/archive/99-big-data/uebung/.run/WordStreamCounter.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
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
--------------------------------------------------------------------------------