Wir haben eine Umgebung zum Ausführen von Komponententests mithilfe der Oracle-Datenbank (oracle12c) auf dem Docker-in-Docker-Image (dind) von GitLab-CI erstellt.

Es ist ein Memorandum, weil ich in meiner Arbeit eine Umgebung wie einen Titel aufgebaut habe und an verschiedenen Stellen gestolpert bin.

Annahme

Erstellen Sie lokal eine Unit-Test-Umgebung

Da es überhaupt keine Unit-Test-Umgebung gibt, haben wir zunächst lokal eine Unit-Test-Umgebung erstellt. Genau wie beim Erstellen einer Unit-Test-Umgebung mit einer gemeinsamen Datenbank können Sie den Unit-Test ausführen, während Sie db mit Docker-Compose starten.

Klicken Sie hier, um ein Docker-Image für oracle12c zu erstellen.

docker-compose.yml


version: '2'

services:
  oracle-database:
    image: oracle/database:12.1.0.2-ee
    container_name: oracle-database
    ports:
      - 1521:1521
    volumes:
      - ./startup:/opt/oracle/scripts/startup
    environment:
      - ORACLE_SID=SID
      - ORACLE_PWD=passw0rd
      - ORACLE_PDB=pdb

Für die Verbindung mit dieser Datenbank sind einige Vorbereitungen erforderlich.

Bei einer Oracle-Datenbank wird die Datenbank im Benutzer (Schema) erstellt, daher muss zuerst der Benutzer erstellt werden. Es ist mühsam, jedes Mal vom Benutzer erstellten Code in den Testcode zu schreiben. Lassen Sie den Benutzer also beim Start der Datenbank erstellen.

startup/startup.sql


ALTER SESSION SET container = pdb;
GRANT DBA TO PDBADMIN;
GRANT UNLIMITED TABLESPACE TO PDBADMIN;

CREATE USER testuser
    IDENTIFIED BY passw0rd
    DEFAULT TABLESPACE users
    TEMPORARY TABLESPACE temp;
GRANT DBA TO testuser;
GRANT UNLIMITED TABLESPACE TO testuser;

Das Oracle-Datenbank-Docker-Image führt die SQL-Datei im Startordner als sysdb-Benutzer aus. Ändern Sie daher die Sitzung, um den Benutzer zur steckbaren Datenbank (PDB) hinzuzufügen. Außerdem verfügt PDBADMIN im Ausgangszustand nicht über die Berechtigung, die admin entspricht (warum?). Daher wird die Berechtigung erteilt.

Hier wird der Benutzer als testuser / passw0rd angelegt. Da es nur für Komponententests verwendet wird, verfügt dieser Benutzer auch über Administratorrechte.

tests/test.py


import unittest

import cx_Oracle
import sqlalchemy

class Test(unittest.TestCase):
    def setUp(self):
        self.sut = ... #Getestete Instanz
        dsn = cx_Oracle.makedsn("oracle-database", 1521, service_name = "pdb")
        self.testuser = sqlalchemy.create_engine(f"oracle+cx_oracle://testuser:passw0rd@{dsn}")
        self.create_testtable()

    def tearDown(self):
        self.drop_testtable()

    def test__testmethod__describe(self):
        # SetUp
        expected = ...
        # Exercise
        self.sut.testmethod(...)
        # Verify
        actual = ...
        self.assertEqual(expected, actual)

    def create_testtable(self):
        self.testuser.execute(f"""
            CREATE TABLE testtable (
                ... define columns ...
            )
        """)

    def drop_testtable(self):
        self.testuser.execute("DROP TABLE testtable")

if __name__ == "__main__":
    unittest.main()

Ich denke, es gibt verschiedene Möglichkeiten, einen Test zu schreiben, also als Beispiel. Der wichtige Teil hier ist der Teil, der mit der setUp-Methode mit oracle12c verbunden ist. Erstellen Sie einen DSN und verwenden Sie diese Informationen, um eine Verbindungs-URL zu erstellen und eine Verbindungsengine zu erstellen. In sqlalchemy werden verschiedene Verbindungsmethoden beschrieben. Um jedoch eine Verbindung zum PDB herzustellen, müssen Sie eine Verbindung über ServiceName (nicht SID) herstellen und dafür einen DSN erstellen. Ordnen Sie den Hostnamen im DSN dem in docker-compose.yml definierten Containernamen zu.

Wenn Sie "__init __. Py" für Tests vorbereiten, wird der Komponententest ausgeführt, indem "pytest" an der Wurzel ausgeführt wird.

docker-compose up -d
pytest

Problem

Dies wird vorerst die Mindestumgebung festlegen. Es gibt jedoch Probleme mit dieser Umgebung.

Wie Sie sehen können, dauert das Erstellen der ursprünglichen Datenbank nach dem Erstellen des Dockers erheblich, und es dauert etwa 5 bis 10 Minuten, bis die Datenbank endgültig geöffnet ist (= connect). Außerdem schlägt die anfängliche Datenbankkonstruktion selten fehl (obwohl sie mit Docker erstellt wurde). In Anbetracht der Umgebung als Komponententest ist die Handhabung ziemlich schlecht.

Sichern Sie die ursprüngliche Datenbank, um dieses Problem zu lösen. Es gibt einen Grund, hier "Backup" zu sagen. Dies liegt daran, dass diese anfängliche Datenbank nach dem Herstellen einer Verbindung über DBMS ständig in Form eines Überschreibspeichers aktualisiert wird. Das Gleiche gilt, wenn die Datenbank durch Ausführen eines Komponententests verschmutzt wird. Selbst wenn nichts unternommen wird, nimmt die Dateigröße zu und wird immer "schmutziger". Da es nicht zu leugnen ist, dass der Test aufgrund solcher externer Faktoren fehlschlägt, muss die ursprüngliche Datenbank wiederhergestellt werden, die unmittelbar vor dem "Docker-Composeup" gesichert wurde, um eine stabile Testumgebung aufzubauen. Gibt es.

Einige Techniken sind erforderlich, um die ursprüngliche Datenbank zu erstellen und eine Sicherung vorzubereiten. Ein Beispiel wird hier gezeigt.

Erstellen Sie zunächst ein Oracle-Datenbankimage, um die ursprüngliche Datenbank zu erstellen. In diesem Beispiel wird Docker-Compose verwendet, Sie können jedoch einen ähnlichen Docker-Befehl verwenden.

docker-compose-oradata.yml


version: '2'

services:
  oracle-database:
    image: oracle/database:12.1.0.2-ee
    container_name: oracle-database
    ports:
      - 1521:1521
    volumes:
      - ./oradata:/opt/oracle/oradata
    environment:
      - ORACLE_SID=SID
      - ORACLE_PWD=passw0rd
      - ORACLE_PDB=pdb
docker-compose -f docker-compose-oradata.yml up

Nach der Ausführung wird die ursprüngliche Datenbank im Ordner oradata erstellt. Diese Konstruktion dauert ca. 5-10 Minuten. Im obigen Beispiel befindet es sich nicht im Trennmodus, um zu überprüfen, ob der Zeitpunkt abgelaufen ist oder nicht.

Von nun an ist es wichtig, die Datenbank sofort nach Abschluss des Builds mit Strg + C herunterzufahren. Wenn Sie sich darauf stützen, wird die ursprüngliche Datenbank übergewichtet (ca. 1,5 GB). Sie können es weiterhin bereitstellen, aber es macht keinen Sinn, wenn die von Ihnen gesicherten Dateien unnötig groß sind. Fahren Sie sie daher sofort nach der Erstellung herunter.

Starting oracle-database ... done
Attaching to oracle-database
oracle-database    | ORACLE PASSWORD FOR SYS, SYSTEM AND PDBADMIN: passw0rd
oracle-database    | 
oracle-database    | LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 15-OCT-2020 12:03:40
oracle-database    | 
oracle-database    | Copyright (c) 1991, 2014, Oracle.  All rights reserved.
oracle-database    | 
oracle-database    | Starting /opt/oracle/product/12.1.0.2/dbhome_1/bin/tnslsnr: please wait...
oracle-database    | 
oracle-database    | TNSLSNR for Linux: Version 12.1.0.2.0 - Production
oracle-database    | System parameter file is /opt/oracle/product/12.1.0.2/dbhome_1/network/admin/listener.ora
oracle-database    | Log messages written to /opt/oracle/diag/tnslsnr/bf429c874900/listener/alert/log.xml
oracle-database    | Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
oracle-database    | Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
oracle-database    | 
oracle-database    | Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1)))
oracle-database    | STATUS of the LISTENER
oracle-database    | ------------------------
oracle-database    | Alias                     LISTENER
oracle-database    | Version                   TNSLSNR for Linux: Version 12.1.0.2.0 - Production
oracle-database    | Start Date                15-OCT-2020 12:03:40
oracle-database    | Uptime                    0 days 0 hr. 0 min. 0 sec
oracle-database    | Trace Level               off
oracle-database    | Security                  ON: Local OS Authentication
oracle-database    | SNMP                      OFF
oracle-database    | Listener Parameter File   /opt/oracle/product/12.1.0.2/dbhome_1/network/admin/listener.ora
oracle-database    | Listener Log File         /opt/oracle/diag/tnslsnr/bf429c874900/listener/alert/log.xml
oracle-database    | Listening Endpoints Summary...
oracle-database    |   (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
oracle-database    |   (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
oracle-database    | The listener supports no services
oracle-database    | The command completed successfully
oracle-database    | Cleaning up failed steps
oracle-database    | 4% complete
oracle-database    | Copying database files
oracle-database    | 5% complete
oracle-database    | 6% complete
oracle-database    | 30% complete
oracle-database    | Creating and starting Oracle instance
oracle-database    | 32% complete
oracle-database    | 35% complete
oracle-database    | 36% complete
oracle-database    | 37% complete
oracle-database    | 41% complete
oracle-database    | 44% complete
oracle-database    | 45% complete
oracle-database    | 48% complete
oracle-database    | Completing Database Creation
oracle-database    | 50% complete
oracle-database    | 53% complete
oracle-database    | 55% complete
oracle-database    | 63% complete
oracle-database    | 66% complete
oracle-database    | 74% complete
oracle-database    | Creating Pluggable Databases
oracle-database    | 79% complete
oracle-database    | 100% complete
oracle-database    | Look at the log file "/opt/oracle/cfgtoollogs/dbca/SID/SID0.log" for further details.
oracle-database    | 
oracle-database    | SQL*Plus: Release 12.1.0.2.0 Production on Thu Oct 15 12:11:34 2020
oracle-database    | 
oracle-database    | Copyright (c) 1982, 2014, Oracle.  All rights reserved.
oracle-database    | 
oracle-database    | 
oracle-database    | Connected to:
oracle-database    | Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
oracle-database    | With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
oracle-database    | 
oracle-database    | SQL> 
oracle-database    | System altered.
oracle-database    | 
oracle-database    | SQL> 
oracle-database    | Pluggable database altered.
oracle-database    | 
oracle-database    | SQL> Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
oracle-database    | With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
oracle-database    | The Oracle base remains unchanged with value /opt/oracle
oracle-database    | #########################
oracle-database    | DATABASE IS READY TO USE!
oracle-database    | #########################
oracle-database    | The following output is now a tail of the alert.log:
oracle-database    | Completed: alter pluggable database PDB open
oracle-database    | Thu Oct 15 12:11:33 2020
oracle-database    | CREATE SMALLFILE TABLESPACE "USERS" LOGGING  DATAFILE  '/opt/oracle/oradata/SID/PDB/PDB_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON NEXT  1280K MAXSIZE UNLIMITED  EXTENT MANAGEMENT LOCAL  SEGMENT SPACE MANAGEMENT  AUTO
oracle-database    | Completed: CREATE SMALLFILE TABLESPACE "USERS" LOGGING  DATAFILE  '/opt/oracle/oradata/SID/PDB/PDB_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON NEXT  1280K MAXSIZE UNLIMITED  EXTENT MANAGEMENT LOCAL  SEGMENT SPACE MANAGEMENT  AUTO
oracle-database    | ALTER DATABASE DEFAULT TABLESPACE "USERS"
oracle-database    | Completed: ALTER DATABASE DEFAULT TABLESPACE "USERS"
oracle-database    | Thu Oct 15 12:11:34 2020
oracle-database    | ALTER SYSTEM SET control_files='/opt/oracle/oradata/SID/control01.ctl' SCOPE=SPFILE;
oracle-database    |    ALTER PLUGGABLE DATABASE PDB SAVE STATE
oracle-database    | Completed:    ALTER PLUGGABLE DATABASE PDB SAVE STATE
^CERROR: Aborting.

Sichern Sie den oradata-Ordner irgendwo, damit der Inhalt dieses oradata-Ordners wiederhergestellt wird, bevor Sie "docker-compose up" ausführen, bevor Sie den Test ausführen (im eigentlichen Geschäft sollte der Inhalt von oradata wiederhergestellt werden. Reißverschluss komprimiert und auf S3 gesichert). Die ursprüngliche Datei docker-compose.yml sollte den Ordner oradata bereitstellen.

docker-compose.yml


version: '2'

services:
  oracle-database:
    image: oracle/database:12.1.0.2-ee
    container_name: oracle-database
    ports:
      - 1521:1521
    volumes:
      - ./oradata:/opt/oracle/oradata
      - ./startup:/opt/oracle/scripts/startup
    environment:
      - ORACLE_SID=SID
      - ORACLE_PWD=passw0rd
      - ORACLE_PDB=pdb

Auf diese Weise konnte die Zeit zum Öffnen der Datenbank auf etwa 1 bis 2 Minuten reduziert werden.

Führen Sie den obigen Komponententest mit GitLab CI aus

Das Hauptthema.

Wenn Sie eine Datenbank für Unit-Tests auf GitLab CI verwenden, ist es ein königlicher Weg, "Dienste" zu verwenden. Das Image der Oracle-Datenbank muss jedoch von einer Art privatem Repository verwaltet werden. Ich habe noch nie ein privates Repository in Services eingerichtet und in der Praxis andere Docker-Images erstellt. Daher werde ich hier Docker in Docker (dind) verwenden. Ich habe eine Umgebung gebaut.

Beim Erstellen einer Dind-Umgebung mit GitLab CI gibt es ein Problem. Das heißt, das Verzeichnis, in dem das Volume bereitgestellt wird, wird zum Hostverzeichnis. Normalerweise (nicht auf GitLab CI beschränkt) erfolgt die Jobausführung selbst im Docker-Container. Wenn Sie also Docker-Compose wie folgt ausführen, befinden sich die Ordner oradata und startup im Docker-Container, in dem der Job ausgeführt wurde. Stattdessen geben Sie am Ende den Ordner auf dem Host an, auf dem dieses Docker ausgeführt wird.

Es gibt verschiedene Lösungen dafür, aber dieses Mal habe ich es vermieden, indem ich ein Docker-Image erstellt habe, das Oradata enthält. Da das Oracle-Datenbank-Image in erster Linie in einem privaten Repository abgelegt werden sollte, wird das Image einschließlich Oradata nur dort vorbereitet, sodass sich an der lokalen Umgebung nicht viel ändert.

Die Docker-Datei, die das Oracle-Datenbank-Image einschließlich der zuvor erstellten Oradata erstellt, sieht folgendermaßen aus.

Dockerfile


FROM oracle/database:12.1.0.2-ee

ENV ORACLE_SID SID
ENV ORACLE_PWD passw0rd
ENV ORACLE_PDB pdb

COPY --chown=oracle:dba oradata/ /opt/oracle/oradata/
COPY startup/ /opt/oracle/scripts/startup/
docker build -t oracle/database:12.1.0.2-ee-with-oradata

Es gibt zwei Punkte zu beachten.

Erstens hängen oradata von den Umgebungsvariablen ORACLE_SID, ORACLE_PWD und ORACLE_PDB ab. Fügen Sie diese Umgebungsvariablen also auch zu Ihrer Docker-Datei hinzu. Wenn sich diese ändern, erstellen Sie auch oradata neu.

Die andere Möglichkeit besteht darin, den Besitzer beim Kopieren von Oradata in "oracle: dba" zu ändern. Wenn Sie es so kopieren, wie es ist, wird es zum Root-Benutzer, und der Oracle-Benutzer kann die ursprüngliche Datenbank nicht bereitstellen.

Verwenden Sie dann dieses Image und führen Sie es in .gitlab-ci.yml aus.

docker-compose.yml


version: '2'

services:
  oracle-database:
    image: oracle/database:12.1.0.2-ee-with-oradata
    container_name: oracle-database
    ports:
      - 1521:1521

yml:.gitlab-ci.yml


pytest:
  stage: test
  image: docker:dind
  script:
    - apk update && apk add bash python3 python3-dev py3-pip docker-compose
    - python3 -m pip install pytest
    - docker-compose up -d
    - sleep 120s
    - pytest

(Ich bin nicht sicher, ob ich eine Ausführungsumgebung für pytest erstellen soll. Ich werde es später überprüfen.)

Da das Öffnen der ursprünglichen Datenbank einige Zeit in Anspruch nimmt, verwenden wir hier als Beispiel "sleep 120s".

Auf diese Weise wurde es vorerst möglich, Unit-Tests mit der Oracle-Datenbank auf GitLab CI durchzuführen.

Zusammenfassung

Recommended Posts

Wir haben eine Umgebung zum Ausführen von Komponententests mithilfe der Oracle-Datenbank (oracle12c) auf dem Docker-in-Docker-Image (dind) von GitLab-CI erstellt.
Ich habe eine Ubuntu-Umgebung unter Windows 10 mit WSL2 erstellt.
So installieren Sie Docker in der lokalen Umgebung einer vorhandenen Rails-App [Rails 6 / MySQL 8]
Ich habe versucht, die Umgebung nach und nach mit Docker aufzubauen
Ich habe versucht, Docker zu verwenden, weil ich die lokale Umgebung bei der Entwicklung der Registerkarte "Microsoft Teams" von MS Learn nicht verschmutzen möchte
Ich habe versucht, eine Umgebung mit WSL2 + Docker + VSCode zu erstellen
Ich möchte den Inhalt von Assets in der mit capistrano erstellten Umgebung von Grund auf neu erstellen
Nachdem ich Progate gelernt hatte, versuchte ich, eine SNS-Anwendung mit Rails in der lokalen Umgebung zu erstellen
Ich habe versucht, mit Docker eine Plant UML Server-Umgebung zu erstellen
So stellen Sie das Bild mithilfe der Symbolschriftart (Symbole) links / rechts von der Schaltfläche auf zeichnbar ein
Ich habe versucht, ein Beispielprogramm mit dem Problem des Datenbankspezialisten für domänengesteuertes Design zu erstellen
Ausführen mit normalen Befehlen für die Entwicklungssprache in der Docker-Entwicklungsumgebung
Ich möchte bei der Registrierung in der Datenbank eine Fehlermeldung anzeigen
Ich habe versucht, das auf Vagrant erstellte Portfolio in die Entwicklungsumgebung von Docker zu migrieren
Versuchen Sie, mit Scala mithilfe der Standardbibliothek von Java Text zu einem Bild hinzuzufügen
Bis zum Start eines Docker-Containers, der mit RedHat Quarkus erstellt wurde
Ein kurzer Hinweis zur Verwendung von jshell mit dem offiziellen Docker-Image des JDK
Schieben Sie das Image mit Jib zum Docker-Hub
Für diejenigen, die MySQL für die Datenbank in der Umgebungskonstruktion von Rails6 ~ verwenden möchten.
Verwendung von git mit der Leistung von jgit in einer Umgebung ohne git-Befehle
Bearbeiten Sie Pixel, um ein Bild eines Mandelbrot-Sets zu erstellen
SSL in der lokalen Umgebung von Docker / Rails / Puma
[Schienen] So zeigen Sie Bilder in der Ansicht an
Beispielcode zum Abrufen der Werte der wichtigsten SQL-Typen in Java + Oracle Database 12c
Ich habe versucht, die Cache-Funktion von Application Container Cloud Service in der lokalen Umgebung zu entwickeln