From 1d9ed2c93c5185e66259356a75f30f8ce0a9876e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:06:19 +0000 Subject: [PATCH 1/3] Initial plan From 42e782964315e9230bf55ef2cbcfd6b5eac656c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:10:12 +0000 Subject: [PATCH 2/3] Initial analysis and plan for CONTRIBUTING.md creation Co-authored-by: lbeckman314 <15309567+lbeckman314@users.noreply.github.com> --- src/backup/__pycache__/main.cpython-312.pyc | Bin 0 -> 7893 bytes src/backup/__pycache__/options.cpython-312.pyc | Bin 0 -> 3042 bytes .../grip/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5441 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5634 bytes .../s3/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3261 bytes .../conftest.cpython-312-pytest-8.4.2.pyc | Bin 0 -> 2932 bytes .../test_backups.cpython-312-pytest-8.4.2.pyc | Bin 0 -> 6124 bytes 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/backup/__pycache__/main.cpython-312.pyc create mode 100644 src/backup/__pycache__/options.cpython-312.pyc create mode 100644 src/backup/grip/__pycache__/__init__.cpython-312.pyc create mode 100644 src/backup/postgres/__pycache__/__init__.cpython-312.pyc create mode 100644 src/backup/s3/__pycache__/__init__.cpython-312.pyc create mode 100644 tests/__pycache__/conftest.cpython-312-pytest-8.4.2.pyc create mode 100644 tests/__pycache__/test_backups.cpython-312-pytest-8.4.2.pyc diff --git a/src/backup/__pycache__/main.cpython-312.pyc b/src/backup/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3d4d33abc6c175a56816f59a97a97591299c9d89 GIT binary patch literal 7893 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 E8%yY?e*gdg literal 0 HcmV?d00001 diff --git a/src/backup/__pycache__/options.cpython-312.pyc b/src/backup/__pycache__/options.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..566e4453d130d4d902bc59bcc3c4dcd0a0e2b360 GIT binary patch literal 3042 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 Ccywa` literal 0 HcmV?d00001 diff --git a/src/backup/postgres/__pycache__/__init__.cpython-312.pyc b/src/backup/postgres/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..695433cafc5b0f35ea22596b565a25f80467b194 GIT binary patch literal 5634 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 literal 0 HcmV?d00001 diff --git a/src/backup/s3/__pycache__/__init__.cpython-312.pyc b/src/backup/s3/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4788a6a363d71db362e1969de24f43fdb1a81b0a GIT binary patch literal 3261 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 QZ06yJEM_+cfw0f}4^@T2@Bjb+ literal 0 HcmV?d00001 From 9d6762e218bd651fd6babcbb17cb90103b586a56 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:13:41 +0000 Subject: [PATCH 3/3] Create comprehensive CONTRIBUTING.md with CLI, Helm, and S3 verification instructions Co-authored-by: lbeckman314 <15309567+lbeckman314@users.noreply.github.com> --- .gitignore | 5 + CONTRIBUTING.md | 477 ++++++++++++++++++ src/backup/__pycache__/main.cpython-312.pyc | Bin 7893 -> 0 bytes .../__pycache__/options.cpython-312.pyc | Bin 3042 -> 0 bytes .../conftest.cpython-312-pytest-8.4.2.pyc | Bin 2932 -> 0 bytes .../test_backups.cpython-312-pytest-8.4.2.pyc | Bin 6124 -> 0 bytes 6 files changed, 482 insertions(+) create mode 100644 CONTRIBUTING.md delete mode 100644 src/backup/__pycache__/main.cpython-312.pyc delete mode 100644 src/backup/__pycache__/options.cpython-312.pyc delete mode 100644 tests/__pycache__/conftest.cpython-312-pytest-8.4.2.pyc delete mode 100644 tests/__pycache__/test_backups.cpython-312-pytest-8.4.2.pyc diff --git a/.gitignore b/.gitignore index 99dbb2e..1a7820e 100644 --- a/.gitignore +++ b/.gitignore @@ -113,3 +113,8 @@ venv.bak/ # SQL files .sql + +# Python cache files +__pycache__/ +*.pyc +*.pyo diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..082559b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,477 @@ +# Contributing to Backup Service + +Welcome to the backup-service project! This guide will help you get started with installing, running, and deploying the backup service for CALYPR systems. 🔄 + +## Table of Contents + +- [Manual Installation & CLI Usage](#manual-installation--cli-usage) +- [Kubernetes Deployment with Helm](#kubernetes-deployment-with-helm) +- [Verifying S3 Backups](#verifying-s3-backups) +- [Development Setup](#development-setup) +- [Contributing Guidelines](#contributing-guidelines) + +## Manual Installation & CLI Usage + +### Prerequisites + +- **Python 3.12+** is required +- **PostgreSQL client tools** (for database operations) +- **Docker** (optional, for containerized usage) + +### Installation Steps + +1. **Clone the repository:** + ```bash + git clone https://github.com/calypr/backup-service.git + cd backup-service + ``` + +2. **Create and activate a virtual environment:** + ```bash + python3 -m venv venv + source venv/bin/activate # On Windows: venv\Scripts\activate + ``` + +3. **Install dependencies:** + ```bash + pip install --upgrade pip + pip install -r requirements.txt + ``` + +4. **Install the backup service:** + ```bash + pip install -e . + ``` + +5. **Verify installation:** + ```bash + bak --help + ``` + +### CLI Usage Examples + +#### PostgreSQL Operations + +**List databases:** +```bash +bak pg ls \ + --host localhost \ + --port 5432 \ + --user postgres \ + --password your_password +``` + +**Dump all databases to local directory:** +```bash +bak pg dump \ + --host localhost \ + --port 5432 \ + --user postgres \ + --password your_password \ + --dir /path/to/backup/directory +``` + +**Restore databases from local directory:** +```bash +bak pg restore \ + --host localhost \ + --port 5432 \ + --user postgres \ + --password your_password \ + --dir /path/to/backup/directory +``` + +#### S3 Operations + +**Upload backups to S3:** +```bash +bak s3 upload \ + --endpoint https://s3.amazonaws.com \ + --bucket your-backup-bucket \ + --key your-access-key \ + --secret your-secret-key \ + --dir /path/to/backup/directory +``` + +**Download backups from S3:** +```bash +bak s3 download \ + --endpoint https://s3.amazonaws.com \ + --bucket your-backup-bucket \ + --key your-access-key \ + --secret your-secret-key \ + --dir /path/to/restore/directory +``` + +#### GRIP Operations + +**Backup GRIP database:** +```bash +bak grip backup \ + --host localhost \ + --port 8201 \ + --graph your-graph-name \ + --dir /path/to/backup/directory \ + --vertices \ + --edges +``` + +**Restore GRIP database:** +```bash +bak grip restore \ + --host localhost \ + --port 8201 \ + --graph your-graph-name \ + --dir /path/to/backup/directory +``` + +### Docker Usage + +You can also run the backup service using Docker: + +```bash +# Build the Docker image +docker build -t backup-service . + +# Run a backup operation +docker run --rm \ + -v /host/backup/path:/backups \ + backup-service bak pg dump \ + --host database-host \ + --port 5432 \ + --user postgres \ + --password password \ + --dir /backups +``` + +## Kubernetes Deployment with Helm + +### Prerequisites + +- **kubectl** configured with access to your Kubernetes cluster +- **Helm 3.x** installed +- Access to the **ohsu-comp-bio/helm-charts** repository + +### Helm Installation Steps + +1. **Add the Helm repository:** + ```bash + helm repo add ohsu-comp-bio https://ohsu-comp-bio.github.io/helm-charts + helm repo update + ``` + +2. **Create a values file for your deployment:** + ```bash + cat > backup-values.yaml << EOF + image: + repository: quay.io/ohsu-comp-bio/backup-service + tag: "latest" + pullPolicy: Always + + # Configure backup schedule as a CronJob + schedule: "0 2 * * *" # Daily at 2 AM + + # Environment variables for database connection + env: + - name: POSTGRES_HOST + value: "postgres-service.default.svc.cluster.local" + - name: POSTGRES_PORT + value: "5432" + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: username + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: password + + # S3 configuration + - name: S3_ENDPOINT + value: "s3.amazonaws.com" + - name: S3_BUCKET + value: "your-backup-bucket" + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: s3-secret + key: access-key + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: s3-secret + key: secret-key + + # Resource limits + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 128Mi + + # Persistent volume for temporary backup storage + persistence: + enabled: true + size: 10Gi + storageClass: "standard" + EOF + ``` + +3. **Create necessary secrets:** + ```bash + # PostgreSQL credentials + kubectl create secret generic postgres-secret \ + --from-literal=username=postgres \ + --from-literal=password=your-postgres-password + + # S3 credentials + kubectl create secret generic s3-secret \ + --from-literal=access-key=your-access-key \ + --from-literal=secret-key=your-secret-key + ``` + +4. **Install the Helm chart:** + ```bash + helm install backup-service ohsu-comp-bio/backups \ + --values backup-values.yaml \ + --namespace backup-system \ + --create-namespace + ``` + +5. **Verify the deployment:** + ```bash + kubectl get pods -n backup-system + kubectl get cronjobs -n backup-system + kubectl logs -n backup-system deployment/backup-service + ``` + +### Helm Chart Configuration + +The backup service Helm chart supports the following key configurations: + +- **Schedule**: Configure CronJob schedule for automated backups +- **Image**: Specify the backup service container image +- **Environment**: Database and S3 connection parameters +- **Resources**: CPU and memory limits/requests +- **Persistence**: Temporary storage for backup files +- **Security**: Pod security context and service account configuration + +For complete configuration options, see: https://github.com/ohsu-comp-bio/helm-charts/tree/main/charts/backups + +## Verifying S3 Backups + +### Using AWS CLI + +1. **Install AWS CLI:** + ```bash + pip install awscli + ``` + +2. **Configure AWS credentials:** + ```bash + aws configure + # Enter your Access Key ID, Secret Access Key, region, and output format + ``` + +3. **List backup files:** + ```bash + # List all backups in your bucket + aws s3 ls s3://your-backup-bucket/ + + # List backups with timestamps + aws s3 ls s3://your-backup-bucket/ --recursive --human-readable + + # List specific database backups + aws s3 ls s3://your-backup-bucket/postgres/ --recursive + ``` + +4. **Download and verify backup content:** + ```bash + # Download a specific backup + aws s3 cp s3://your-backup-bucket/postgres/database-2024-01-15.sql.gz ./ + + # Verify the backup file + gunzip database-2024-01-15.sql.gz + head -50 database-2024-01-15.sql # Check backup contents + ``` + +5. **Check backup sizes and dates:** + ```bash + # Get detailed information about backups + aws s3api list-objects-v2 \ + --bucket your-backup-bucket \ + --prefix postgres/ \ + --query 'Contents[?Size>`1000000`].[Key,Size,LastModified]' \ + --output table + ``` + +### Using MinIO Client (mc) + +1. **Install MinIO client:** + ```bash + # Linux/macOS + curl https://dl.min.io/client/mc/release/linux-amd64/mc \ + --create-dirs -o ~/bin/mc + chmod +x ~/bin/mc + + # Or via package manager + brew install minio/stable/mc # macOS + ``` + +2. **Configure MinIO client:** + ```bash + # For AWS S3 + mc alias set aws https://s3.amazonaws.com your-access-key your-secret-key + + # For MinIO server + mc alias set minio https://your-minio-server.com your-access-key your-secret-key + ``` + +3. **List and verify backups:** + ```bash + # List all backups + mc ls aws/your-backup-bucket/ + + # List with details + mc ls --recursive --summarize aws/your-backup-bucket/ + + # Find backups by date + mc find aws/your-backup-bucket/ --name "*2024-01*" --print + ``` + +4. **Download and verify backup content:** + ```bash + # Download a backup + mc cp aws/your-backup-bucket/postgres/database-2024-01-15.sql.gz ./ + + # Compare backup sizes + mc stat aws/your-backup-bucket/postgres/database-2024-01-15.sql.gz + ``` + +5. **Monitor backup health:** + ```bash + # Check for recent backups (last 7 days) + mc find aws/your-backup-bucket/ --newer-than 7d --print + + # Verify backup integrity with checksums + mc cat aws/your-backup-bucket/postgres/database-2024-01-15.sql.gz | md5sum + ``` + +### Backup Verification Checklist + +- ✅ Backups are created on schedule +- ✅ Backup files are properly named with timestamps +- ✅ Backup files are not empty (check file sizes) +- ✅ Recent backups exist (within expected time frame) +- ✅ Backup files can be downloaded successfully +- ✅ Backup content is valid (can be opened/restored) +- ✅ Old backups are cleaned up according to retention policy + +## Development Setup + +### Setting up for Development + +1. **Clone and install in development mode:** + ```bash + git clone https://github.com/calypr/backup-service.git + cd backup-service + python3 -m venv venv + source venv/bin/activate + pip install --upgrade pip + pip install -r requirements.txt + pip install -e . + ``` + +2. **Run tests:** + ```bash + # Run all tests + pytest + + # Run with verbose output + pytest -v + + # Run specific test file + pytest tests/test_backups.py + + # Run with debug logging + pytest -v --log-cli-level=DEBUG + ``` + +### Code Structure + +``` +backup-service/ +├── src/backup/ # Main package +│ ├── main.py # CLI entry point +│ ├── options.py # Click command options +│ ├── postgres/ # PostgreSQL backup logic +│ ├── s3/ # S3 upload/download logic +│ └── grip/ # GRIP database backup logic +├── tests/ # Test suite +├── examples/ # Usage examples +├── Dockerfile # Container image +└── pyproject.toml # Package configuration +``` + +### Testing with Docker + +```bash +# Build development image +docker build -t backup-service:dev . + +# Run tests in container +docker run --rm backup-service:dev pytest + +# Interactive development +docker run -it --rm \ + -v $(pwd):/app \ + backup-service:dev bash +``` + +## Contributing Guidelines + +### Code Style + +- Follow **PEP 8** Python style guidelines +- Use **type hints** where possible +- Add **docstrings** for public functions and classes +- Keep functions focused and well-named + +### Making Changes + +1. **Fork the repository** and create a feature branch +2. **Write tests** for new functionality +3. **Ensure all tests pass** before submitting +4. **Update documentation** if needed +5. **Submit a pull request** with a clear description + +### Testing Requirements + +- All new features must include tests +- Tests should use **testcontainers** for integration testing +- Maintain or improve test coverage +- Test both success and failure scenarios + +### Pull Request Process + +1. Create a descriptive PR title and description +2. Reference any related issues +3. Ensure CI/CD pipelines pass +4. Request review from maintainers +5. Address any feedback promptly + +### Release Process + +This project uses **semantic-release** for automated versioning and releases: + +- Commits follow [Conventional Commits](https://conventionalcommits.org/) +- Releases are automatically created on merge to main +- Docker images are automatically built and published + +--- + +For questions or support, please open an issue in the [GitHub repository](https://github.com/calypr/backup-service/issues). \ No newline at end of file diff --git a/src/backup/__pycache__/main.cpython-312.pyc b/src/backup/__pycache__/main.cpython-312.pyc deleted file mode 100644 index 3d4d33abc6c175a56816f59a97a97591299c9d89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7893 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 E8%yY?e*gdg diff --git a/src/backup/__pycache__/options.cpython-312.pyc b/src/backup/__pycache__/options.cpython-312.pyc deleted file mode 100644 index 566e4453d130d4d902bc59bcc3c4dcd0a0e2b360..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3042 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 QZ06yJEM_+cfw0f}4^@T2@Bjb+