In diesem Artikel untersuchen wir, wie AWS CloudFormation die Einrichtung und Verwaltung der Cloud-Infrastruktur vereinfacht. Anstatt Ressourcen wie Server oder Datenbanken manuell zu erstellen, können Sie Ihre Anforderungen in einer Datei aufschreiben und CloudFormation übernimmt die schwere Arbeit für Sie. Dieser als Infrastructure as Code (IaC) bekannte Ansatz spart Zeit, reduziert Fehler und stellt sicher, dass alles konsistent ist.

Wir werden uns auch ansehen, wie Docker- und GitHub-Aktionen in den Prozess passen. Docker erleichtert das Packen und Ausführen Ihrer Anwendung, während GitHub Actions Aufgaben wie Checks und Bereitstellung automatisiert. Zusammen mit CloudFormation erstellen diese Instruments einen leistungsstarken Workflow für die Erstellung und Bereitstellung von Anwendungen in der Cloud.

Lernziele

  • Erfahren Sie, wie Sie die Cloud-Infrastrukturverwaltung mit AWS CloudFormation mithilfe von Infrastructure as Code (IaC) vereinfachen.
  • Verstehen Sie, wie Docker- und GitHub-Aktionen für eine optimierte Anwendungsbereitstellung in AWS CloudFormation integriert werden.
  • Entdecken Sie ein Beispielprojekt, das die Python-Dokumentationserstellung mithilfe von KI-Instruments wie automatisiert LangChain und GPT-4.
  • Erfahren Sie, wie Sie Anwendungen mit Docker containerisieren, die Bereitstellung mit GitHub Actions automatisieren und über AWS CloudFormation bereitstellen.
  • Erfahren Sie, wie Sie AWS-Ressourcen wie EC2, ECR und Sicherheitsgruppen mithilfe von CloudFormation-Vorlagen einrichten und verwalten.

Dieser Artikel wurde im Rahmen der veröffentlicht Knowledge Science-Blogathon.

Was ist AWS Cloud-Formation?

In der Welt des Cloud Computing ist die effiziente Verwaltung der Infrastruktur von entscheidender Bedeutung. Daher kommt AWS CloudFormation ins Spiel, das die Einrichtung und Verwaltung Ihrer Cloud-Ressourcen erleichtert. Damit können Sie alles, was Sie benötigen – Server, Speicher und Netzwerk – in einer einfachen Datei definieren.

AWS CloudFormation ist ein Service, der Sie bei der Definition und Verwaltung Ihrer Cloud-Ressourcen mithilfe von in YAML oder JSON geschriebenen Vorlagen unterstützt. Betrachten Sie es als die Erstellung eines Entwurfs für Ihre Infrastruktur. Sobald Sie diesen Entwurf übergeben, kümmert sich CloudFormation Schritt für Schritt darum, alles genau so einzurichten, wie Sie es beschrieben haben.

Infrastructure as Code (IaC) ist so, als würden Sie Ihre Cloud in etwas verwandeln, das Sie mit nur wenigen Codezeilen erstellen, umbauen und sogar verbessern können. Kein manuelles Herumklicken mehr, kein Rätselraten mehr – einfach konsistente, zuverlässige Bereitstellungen, die Ihnen Zeit sparen und Fehler reduzieren.

BeispielprojektPraktische Umsetzung: Ein praxisnahes Projektbeispiel

Optimierung der Codedokumentation mit KI: Das Dokumentgenerierungsprojekt:

Um Cloud Formation zu starten, benötigen wir ein Beispielprojekt, um es in AWS bereitzustellen.

Ich habe bereits ein Projekt mit Lang-Chain und OPEN AI GPT-4 erstellt. Lassen Sie uns über dieses Projekt sprechen und dann einen Blick darauf werfen, wie dieses Projekt mithilfe von Cloud Formation in AWS bereitgestellt wird.

GitHub-Code-Hyperlink: https://github.com/Harshitha-GH/CloudFormation

In der Welt der Softwareentwicklung spielt die Dokumentation eine wichtige Rolle, um sicherzustellen, dass Codebasen verständlich und wartbar sind. Allerdings ist die Erstellung einer detaillierten Dokumentation oft eine zeitaufwändige und langweilige Aufgabe. Aber wir sind Technikfreaks, wir wollen in allem Automatisierung. Um ein Projekt in AWS mit CloudFormation bereitzustellen, habe ich ein Automatisierungsprojekt mit KI (Lang-Chain und Open AI GPT-4) entwickelt, um das Doc Technology Undertaking zu erstellen – eine revolutionary Lösung, die KI nutzt, um den Dokumentationsprozess für Python-Code zu automatisieren.

Hier finden Sie eine Aufschlüsselung, wie wir dieses Device entwickelt haben und welche Wirkung es erzielen soll. Um dieses Projekt zu erstellen, befolgen wir einige Schritte.

Bevor wir ein neues Projekt starten, müssen wir eine Python-Umgebung erstellen, um alle erforderlichen Pakete zu installieren. Dies wird uns helfen, die notwendigen Pakete aufrechtzuerhalten.

Ich habe eine Funktion zum Parsen der Eingabedatei geschrieben, die normalerweise eine Python-Datei als Eingabe verwendet und die Namen aller Funktionen ausgibt.

Dokumentation aus Code generieren

Sobald die Funktionsdetails extrahiert sind, besteht der nächste Schritt darin, sie in das GPT-4-Modell von OpenAI einzuspeisen, um eine detaillierte Dokumentation zu erstellen. Mithilfe von Lang-Chain erstellen wir eine Eingabeaufforderung, die die Aufgabe erklärt, die GPT-4 ausführen soll.

prompt_template = PromptTemplate(
        input_variables=("function_name", "arguments", "docstring"),
        template=(
            "Generate detailed documentation for the next Python perform:nn"
            "Perform Identify: {function_name}n"
            "Arguments: {arguments}n"
            "Docstring: {docstring}nn"
            "Present a transparent description of what the perform does, its parameters, and the return worth."
        )
    )#import csv

Mit Hilfe dieser Eingabeaufforderung übernimmt die Doc Generator-Funktion die analysierten Particulars und generiert eine vollständige, für Menschen lesbare Erklärung für jede Funktion.

Flask-API-Integration

Um das Device benutzerfreundlich zu gestalten, habe ich eine Flask-API erstellt, über die Benutzer Inhalte hochladen können Python Dateien. Die API analysiert die Datei, generiert die Dokumentation mit GPT-4 und gibt sie im JSON-Format zurück.

Wir können diese Flask-API mit Postman testen, um unsere Ausgabe zu überprüfen.

Flask-API-Integration

Dockerisierung der Anwendung

Um in AWS bereitzustellen und unsere Anwendung zu verwenden, müssen wir unsere Anwendung mithilfe von Docker containerisieren und dann GitHub-Aktionen verwenden, um den Bereitstellungsprozess zu automatisieren. Wir werden AWS CloudFormation für die Automatisierung in AWS verwenden. In Bezug auf den Service werden wir Elastic Container Registry zum Speichern unserer Container und EC2 zum Bereitstellen unserer Anwendung verwenden. Lassen Sie uns dies Schritt für Schritt sehen.

Erstellung von Docker Compose

Wir werden die Docker-Datei erstellen. Die Docker-Datei ist für das Hochfahren unserer jeweiligen Container verantwortlich

# Use the official Python 3.11-slim picture as the bottom picture
FROM python:3.11-slim

# Set atmosphere variables to forestall Python from writing .pyc information and buffering output
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# Set the working listing contained in the container
WORKDIR /app

# Set up system dependencies required for Python packages and clear up apt cache afterwards
RUN apt-get replace && apt-get set up -y --no-install-recommends 
    gcc 
    libffi-dev 
    libpq-dev 
    python3-dev 
    build-essential 
    && rm -rf /var/lib/apt/lists/*

# Copy the necessities file to the working listing
COPY necessities.txt /app/

# Improve pip and set up Python dependencies with out cache
RUN pip set up --no-cache-dir --upgrade pip && 
    pip set up --no-cache-dir -r necessities.txt

# Copy the complete software code to the working listing
COPY . /app/

# Expose port 5000 for the appliance
EXPOSE 5000

# Run the appliance utilizing Python
CMD ("python", "app.py")#import csv

Docker Compose

Sobald die Docker-Dateien erstellt sind, erstellen wir eine Docker-Compose-Datei, die den Container startet.

model: '3.8'

providers:
  app:
    construct:
      context: .
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    volumes:
      - .:/app
    atmosphere:
      - PYTHONDONTWRITEBYTECODE=1
      - PYTHONUNBUFFERED=1
    command: ("python", "app.py")#import csv

Sie können dies testen, indem Sie den Befehl ausführen

docker-compose up –construct#import csv

Nachdem der Befehl erfolgreich ausgeführt wurde, funktioniert der Code genauso wie zuvor.

Erstellen von AWS Providers für Cloud-Formation Stack

Erstellen von AWS Services für Cloud-Formation Stack

Ich erstelle ein ECR-Repository. Darüber hinaus werden wir später GitHub-Aktionen durchführen, um alle unsere anderen erforderlichen Dienste zu erstellen.

Das von mir erstellte Repository hat als Demo den Namespace cloud_formation repo identify. Dann werde ich mit dem CloudFormationtemplate fortfahren, einer Yaml-Datei, die beim Hochfahren der erforderlichen Instanz hilft und die Bilder aus ECR und anderen Ressourcen abruft.

Anstatt Server manuell einzurichten und alles zu verbinden, wird AWS CloudFormation verwendet, um Cloud-Ressourcen (wie Server oder Datenbanken) automatisch mithilfe eines Skripts einzurichten und zu verwalten. Es ist, als ob Sie einen Bauplan zum Erstellen und Organisieren Ihrer Cloud-Inhalte vorgeben würden, ohne dies manuell tun zu müssen!

Stellen Sie sich CloudFormation als das Verfassen einer einfachen Bedienungsanleitung für AWS vor. Dieses als „Vorlage“ bezeichnete Handbuch weist AWS an:

  • Starten Sie die für das Projekt erforderlichen Server.
  • Ziehen Sie die Container-Photos des Projekts aus dem ECR-Speicher-Repository.
  • Richten Sie alle anderen Abhängigkeiten und Konfigurationen ein, die für die Ausführung des Projekts erforderlich sind.

Durch die Verwendung dieser automatisierten Einrichtung muss ich nicht jedes Mal dieselben Schritte wiederholen, wenn ich das Projekt bereitstelle oder aktualisiere – alles wird von AWS automatisch erledigt.

Wolkenbildungsvorlage

AWS CloudFormation-Vorlagen sind deklarative JSON- oder YAML-Skripte, die die Ressourcen und Konfigurationen beschreiben, die zum Einrichten Ihrer Infrastruktur in AWS erforderlich sind. Sie ermöglichen es Ihnen, Ihre Infrastruktur als Code zu automatisieren und zu verwalten und so Konsistenz und Wiederholbarkeit in allen Umgebungen sicherzustellen.

# CloudFormation Template
AWSTemplateFormatVersion: "2010-09-09"
Description: Deploy EC2 with Docker Compose pulling photos from ECR

Sources:
  BackendECRRepository:
    Kind: AWS::ECR::Repository
    Properties:
      RepositoryName: backend


  EC2InstanceProfile:
    Kind: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref EC2InstanceRole

  EC2InstanceRole:
    Kind: AWS::IAM::Position
    Properties:
      AssumeRolePolicyDocument:
        Model: "2012-10-17"
        Assertion:
          - Impact: Enable
            Principal:
              Service: ec2.amazonaws.com
            Motion: sts:AssumeRole
      Insurance policies:
        - PolicyName: ECROpsPolicy
          PolicyDocument:
            Model: "2012-10-17"
            Assertion:
              - Impact: Enable
                Motion:
                  - ecr:GetAuthorizationToken
                  - ecr:BatchGetImage
                  - ecr:GetDownloadUrlForLayer
                Useful resource: "*"
        - PolicyName: SecretsManagerPolicy
          PolicyDocument:
            Model: "2012-10-17"
            Assertion:
              - Impact: Enable
                Motion:
                  - secretsmanager:GetSecretValue
                Useful resource: "*"

  EC2SecurityGroup:
    Kind: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable SSH, HTTP, HTTPS, and application-specific ports
      SecurityGroupIngress:
        # SSH Entry
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
        # Ping (ICMP)
        - IpProtocol: icmp
          FromPort: -1
          ToPort: -1
          CidrIp: 0.0.0.0/0
        # HTTP
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        # HTTPS
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
        # Backend Port
        - IpProtocol: tcp
          FromPort: 5000
          ToPort: 5000
          CidrIp: 0.0.0.0/0

  EC2Instance:
    Kind: AWS::EC2::Occasion
    Properties:
      InstanceType: t2.micro
      KeyName: demo
      ImageId: ami-0c02fb55956c7d316
      IamInstanceProfile: !Ref EC2InstanceProfile
      SecurityGroupIds:
        - !Ref EC2SecurityGroup
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          set -e  # Exit script on error
          yum replace -y
          yum set up docker git python3 -y
          pip3 set up boto3
          service docker begin
          usermod -aG docker ec2-user

          # Set up Docker Compose
          curl -L "https://github.com/docker/compose/releases/obtain/$(curl -s https://api.github.com/repos/docker/compose/releases/newest | grep tag_name | lower -d '"' -f 4)/docker-compose-$(uname -s)-$(uname -m)" -o /usr/native/bin/docker-compose
          chmod +x /usr/native/bin/docker-compose

          # Retrieve secrets and techniques from AWS Secrets and techniques Supervisor
          SECRET_NAME="backend-config"
          REGION="us-east-1"
          SECRET_JSON=$(aws secretsmanager get-secret-value --secret-id $SECRET_NAME --region $REGION --query SecretString --output textual content)
          echo "$SECRET_JSON" > /tmp/secrets and techniques.json

          # Create config.py dynamically
          mkdir -p /backend
          cat <<EOL > /backend/config.py
          import json
          secrets and techniques = json.load(open('/tmp/secrets and techniques.json'))
          OPENAI_API_KEY = secrets and techniques("OPENAI_API_KEY")
          EOL

        

          # Authenticate with ECR
          aws ecr get-login-password --region ${AWS::Area} | docker login --username AWS --password-stdin ${AWS::AccountId}.dkr.ecr.${AWS::Area}.amazonaws.com

          # Pull photos from ECR
          docker pull ${AWS::AccountId}.dkr.ecr.${AWS::Area}.amazonaws.com/personage/dodge-challenger:backend-latest

          # Create Docker Compose file
          cat <<EOL > docker-compose.yml
          model: "3.9"
          providers:
            backend:
              picture: ${AWS::AccountId}.dkr.ecr.${AWS::Area}.amazonaws.com/personage/dodge-challenger:backend-latest
              ports:
                - "5000:5000"
              volumes:
                - /backend/config.py:/app/config.py
                - /tmp/secrets and techniques.json:/tmp/secrets and techniques.json
              atmosphere:
                - PYTHONUNBUFFERED=1

            
          EOL

          # Begin Docker Compose
          docker-compose -p demo up -d

Outputs:
  EC2PublicIP:
    Description: Public IP of the EC2 occasion
    Worth: !GetAtt EC2Instance.PublicIp#import csv

Lassen Sie uns die aktualisierte Vorlage Schritt für Schritt entschlüsseln:

Wir definieren eine einzelne ECR-Ressource, das Repository, in dem unser Docker-Picture gespeichert ist.

Als nächstes erstellen wir eine EC2-Instanz. Wir werden ihm wesentliche Richtlinien beifügen, hauptsächlich für die Interaktion mit dem ECR und AWS Secrets and techniques Supervisor. Zusätzlich fügen wir eine Sicherheitsgruppe hinzu, um den Netzwerkzugriff zu kontrollieren. Für dieses Setup öffnen wir:

  • Port 22 für SSH-Zugriff.
  • Port 80 für HTTP-Zugriff.
  • Port 5000 für den Backend-Anwendungszugriff.

Es wird eine t2.micro-Instanz verwendet, und im Abschnitt „Benutzerdaten“ definieren wir die Anweisungen zum Konfigurieren der Instanz:

  • Installieren Sie notwendige Abhängigkeiten wie Python, boto3 und Docker.
  • Greifen Sie auf im AWS Secrets and techniques Supervisor gespeicherte Geheimnisse zu und speichern Sie sie in einer config.py-Datei.
  • Melden Sie sich bei ECR an, rufen Sie das Docker-Picture ab und führen Sie es mit Docker aus.

Da nur ein Docker-Container verwendet wird, vereinfacht diese Konfiguration den Bereitstellungsprozess und stellt gleichzeitig sicher, dass der Backend-Dienst zugänglich und ordnungsgemäß konfiguriert ist.

Hochladen und Speichern von Geheimnissen in AWS Secret Supervisor

Bisher haben wir die Geheimnisse wie den Open AI-Schlüssel in der Datei config.py gespeichert. Wir können diese Datei jedoch nicht auf GitHub übertragen, da sie Geheimnisse enthält. Daher verwenden wir den AWS Secrets and techniques Supervisor, um unsere Geheimnisse zu speichern und sie dann über unsere CloudFormation-Vorlage abzurufen.

Bisher haben wir die Geheimnisse wie den Open AI-Schlüssel in der Datei config.py gespeichert. Wir können diese Datei jedoch nicht auf GitHub übertragen, da sie Geheimnisse enthält. Daher verwenden wir den AWS Secrets and techniques Supervisor, um unsere Geheimnisse zu speichern und sie dann über unsere CloudFormation-Vorlage abzurufen.

Hochladen und Speichern von Geheimnissen in AWS Secret Manager
Hochladen und Speichern von Geheimnissen in AWS Secret Manager

GitHub-Aktionen erstellen

GitHub-Aktionen erstellen

GitHub Actions wird verwendet, um Aufgaben wie das Testen von Code, das Erstellen von Apps oder das Bereitstellen von Projekten zu automatisieren, wann immer Sie Änderungen vornehmen. Es ist, als würde man einen Roboter einrichten, der sich wiederholende Arbeiten für Sie erledigt!

Unsere Hauptabsicht hier ist, dass, wenn wir zu einem bestimmten Github-Zweig pushen, automatisch die Bereitstellung auf AWS beginnen sollte. Dazu wählen wir den Zweig „Haupt“ aus.

Speichern der Geheimnisse in GitHub

Melden Sie sich bei Ihrem Github an und folgen Sie dem folgenden Pfad:

Repository > Einstellungen > Geheimnisse und Variablen > Aktionen

Anschließend müssen Sie Ihre aus Ihrem AWS-Konto extrahierten AWS-Geheimnisse hinzufügen, wie im folgenden Bild dargestellt.

Speichern der Geheimnisse in GitHub

Initiieren des Workflows

Nach dem Speichern erstellen wir einen .github-Ordner und darin einen Workflows-Ordner. Im Ordner „Workflows“ fügen wir eine Datei „deploy.yaml“ hinzu.

identify: Deploy to AWS

on:
  push:
    branches:
      - predominant

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      # Step 1: Checkout the repository
      - identify: Checkout code
        makes use of: actions/checkout@v3
      
      - identify: Configure AWS credentials
        makes use of: aws-actions/configure-aws-credentials@v4 # Configure AWS credentials
        with:
          aws-access-key-id: ${{ secrets and techniques.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets and techniques.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets and techniques.AWS_REGION }}

      # Step 2: Log in to Amazon ECR
      - identify: Log in to Amazon ECR
        id: login-ecr
        makes use of: aws-actions/amazon-ecr-login@v2

      # Step 3: Construct and Push Backend Picture to ECR
      - identify: Construct and Push Backend Picture
        run: |
          docker construct -t backend .
          docker tag backend:newest ${{ secrets and techniques.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets and techniques.AWS_REGION }}.amazonaws.com/personage/dodge-challenger:backend-latest
          docker push ${{ secrets and techniques.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets and techniques.AWS_REGION }}.amazonaws.com/personage/dodge-challenger:backend-latest

      
      
      # Step 5: Delete Current CloudFormation Stack
      - identify: Delete Current CloudFormation Stack
        run: |
          aws cloudformation delete-stack --stack-name docker-ecr-ec2-stack
          echo "Ready for stack deletion to finish..."
          aws cloudformation wait stack-delete-complete --stack-name docker-ecr-ec2-stack || echo "Stack doesn't exist or already deleted."

      # Step 6: Deploy CloudFormation Stack
      - identify: Deploy CloudFormation Stack
        makes use of: aws-actions/aws-cloudformation-github-deploy@v1
        with:
          identify: docker-ecr-ec2-stack
          template: cloud-formation.yaml
          capabilities: CAPABILITY_NAMED_IAM

Hier ist eine vereinfachte Erklärung des Ablaufs:

  • Wir rufen den Code aus dem Repository ab und richten AWS-Anmeldeinformationen mithilfe der in GitHub gespeicherten Geheimnisse ein.
  • Dann melden wir uns bei ECR an und erstellen/pushen das Docker-Picture der Anwendung.
  • Wir prüfen, ob ein CloudFormation-Stack mit demselben Namen vorhanden ist. Wenn ja, löschen Sie es.
  • Schließlich verwenden wir die CloudFormation-Vorlage, um die Ressourcen zu starten und alles einzurichten.

Testen

Sobald alles bereitgestellt ist, notieren Sie sich die IP-Adresse der Instanz und rufen Sie sie dann einfach über Postman an, um zu überprüfen, ob alles einwandfrei funktioniert.

Endausgabe testen

Abschluss

In diesem Artikel haben wir untersucht, wie Sie AWS CloudFormation verwenden können, um die Verwaltung der Cloud-Infrastruktur zu vereinfachen. Wir haben gelernt, wie man ein ECR-Repository erstellt, eine Docker-Anwendung auf einer EC2-Instanz bereitstellt und den gesamten Prozess mithilfe von GitHub Actions für CI/CD automatisiert. Dieser Ansatz spart nicht nur Zeit, sondern sorgt auch für Konsistenz und Zuverlässigkeit bei der Bereitstellung.

Wichtige Erkenntnisse

  • AWS CloudFormation vereinfacht die Cloud-Ressourcenverwaltung mit Infrastructure as Code.
  • Docker-Container optimieren die Anwendungsbereitstellung auf einer von AWS verwalteten Infrastruktur.
  • GitHub Actions automatisiert Construct- und Bereitstellungspipelines für eine nahtlose Integration.
  • LangChain und GPT-4 verbessern die Automatisierung der Python-Dokumentation in Projekten.
  • Durch die Kombination von IaC, Docker und CI/CD entstehen skalierbare, effiziente und moderne Arbeitsabläufe.

Häufig gestellte Fragen

Q1. Was ist AWS CloudFormation?

A. AWS CloudFormation ist ein Service, der es Ihnen ermöglicht, AWS-Ressourcen mithilfe von Infrastructure as Code (IaC) zu modellieren und bereitzustellen.

Q2. Wie lässt sich Docker in AWS CloudFormation integrieren?

A. Docker packt Anwendungen in Container, die auf von CloudFormation verwalteten AWS-Ressourcen bereitgestellt werden können.

Q3. Welche Rolle spielen GitHub-Aktionen in diesem Workflow?

A. GitHub Actions automatisiert CI/CD-Pipelines, einschließlich Erstellen, Testen und Bereitstellen von Anwendungen in AWS.

This fall. Kann ich die Erstellung der Python-Dokumentation mit LangChain automatisieren?

A. Ja, LangChain und GPT-4 können Python-Dokumentation als Teil Ihres Workflows generieren und aktualisieren.

F5. Welche Vorteile bietet die Verwendung von IaC mit AWS CloudFormation?

A. IaC gewährleistet eine konsistente, wiederholbare und skalierbare Ressourcenverwaltung in Ihrer gesamten Infrastruktur.

Die in diesem Artikel gezeigten Medien sind nicht Eigentum von Analytics Vidhya und werden nach Ermessen des Autors verwendet.

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert