This commit is contained in:
2026-02-18 01:05:05 +01:00
commit 490fad15c6
19 changed files with 558 additions and 0 deletions

149
s3_api/Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,149 @@
def vaultConfig() {
return [
vaultUrl: '172.17.0.3:8200',
credentialsId: 'vault-approle',
engineVersion: 2
]
}
def vaultSecrets() {
return [[
path: 'secret/data/companyTransferMoneyService',
secretValues: [
[envVar: 'API_KEY', vaultKey: 'api_key'],
[envVar: 'SELENIUM_GRID', vaultKey: 'selenium_grid_url']
]
]]
}
pipeline {
agent {
docker {
image 'python:3.12-slim'
label 'python3.12'
args '-v /tmp:/tmp' // Optional: Mount /tmp for caching, etc.
}
}
environment {
PYTHON_VERSION = "3.12"
AWS_REGION = "eu-central-1"
S3_BUCKET = "Company-ci-executions"
SERVICE_NAME = "companyTransferMoneyService"
}
options {
timestamps()
buildDiscarder(logRotator(numToKeepStr: '20'))
}
stages {
stage('Checkout') {
agent { label 'ubuntu' }
steps {
checkout scm
}
}
stage('Setup Environment') {
steps {
sh '''
python3.12 -m venv venv
. venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
mkdir -p reports
'''
}
}
stage('Unit Tests (Parallel)') {
parallel {
stage('Unit Batch 1') {
steps {
sh '''
. venv/bin/activate
pytest tests/unit -n auto \
--junitxml=reports/unit1.xml \
--cov=app --cov-report=xml:reports/coverage1.xml
'''
}
}
stage('Unit Batch 2') {
steps {
sh '''
. venv/bin/activate
pytest tests/unit -n auto \
--junitxml=reports/unit2.xml \
--cov=app --cov-report=xml:reports/coverage2.xml
'''
}
}
}
post {
always {
junit 'reports/unit*.xml'
publishCoverage adapters: [coberturaAdapter('reports/coverage*.xml')]
}
}
}
stage('Integration Tests') {
steps {
withVault(configuration: vaultConfig(), vaultSecrets: vaultSecrets()) {
sh '''
. venv/bin/activate
export API_KEY=$API_KEY
export ENV=staging
pytest tests/integration \
--junitxml=reports/integration.xml
'''
}
}
post {
always {
junit 'reports/integration.xml'
}
}
}
stage('E2E Tests (Selenium Grid)') {
steps {
withVault(configuration: vaultConfig(), vaultSecrets: vaultSecrets()) {
sh '''
. venv/bin/activate
export API_KEY=$API_KEY
export SELENIUM_GRID_URL=$SELENIUM_GRID
# Start Flask app in background
nohup python app.py &
FLASK_PID=$!
# Give Flask a few seconds to start
sleep 5
pytest tests/e2e/test_selenium.py \
--junitxml=reports/e2e_selenium.xml
kill $FLASK_PID
'''
}
}
post {
always {
junit 'reports/e2e_selenium.xml'
}
}
}
stage('Upload Reports to S3') {
steps {
withAWS(region: "${AWS_REGION}", credentials: 'aws-jenkins-credentials') {
sh '''
aws s3 cp reports/ \
s3://${S3_BUCKET}/${SERVICE_NAME}/${BUILD_NUMBER}/ \
--recursive
'''
}
}
}
}
}

0
s3_api/requirements.txt Normal file
View File

62
s3_api/s3api.py Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests, json, os
from dotenv import load_dotenv
from marshmallow import Schema, fields, ValidationError
from flask import Flask, request, Response, jsonify
from python_terraform import Terraform
load_dotenv()
API_KEY = os.getenv('API_KEY')
app = Flask(__name__)
class BucketSchema(Schema):
environment = fields.Str(required=True)
bucket_name = fields.Str(required=True)
versioning = fields.Str(required=True)
encryption = fields.Str(required=True)
api_key = fields.Str(required=True)
def create_bucket(ENVIRONMENT, ENCRYPTED, BUCKET_NAME, VERSIONING):
tfstate_bucket = os.getenv("TFSTATE_BUCKET", "company-s3-tfstate-bucket-eu-central-1")
tfstate_region = os.getenv("AWS_REGION", "eu-central-1")
with open("terraform/backend.tf", "w") as f:
f.write('terraform {\n')
f.write('backend "s3" {\n')
f.write(f'bucket = "{tfstate_bucket}"\n')
f.write(f'region = "{tfstate_region}"\n')
f.write(f'key = "s3-{ENVIRONMENT}-{BUCKET_NAME}"\n')
f.write('}\n}')
tf = Terraform(working_dir='terraform',
variables={'ENCRYPTED': ENCRYPTED, 'VERSIONING': VERSIONING, 'BUCKET_NAME': BUCKET_NAME, 'ENVIRONMENT': ENVIRONMENT}
)
return tf.apply(capture_output=True, skip_plan=True, auto_approve=True, var={'ENCRYPTED': ENCRYPTED, 'VERSIONING': VERSIONING, 'BUCKET_NAME': BUCKET_NAME, 'ENVIRONMENT': ENVIRONMENT})
@app.route('/', methods = ['GET'])
def ping():
return ["Pong"]
@app.route('/create_bucket', methods = ['POST'])
def bucket_data():
request_data = BucketSchema().load(request.json)
if request_data["api_key"] == API_KEY:
try:
ENVIRONMENT = request_data["environment"]
BUCKET_NAME = request_data["bucket_name"]
ENCRYPTED = request_data["encryption"]
VERSIONING = request_data["versioning"]
if create_bucket(ENVIRONMENT, ENCRYPTED, BUCKET_NAME, VERSIONING)[0] == 1:
return "Something went wrong trying to create the bucket"
return f"Creating bucket {BUCKET_NAME} in {ENVIRONMENT} with encryption={ENCRYPTED} and versioning={VERSIONING}"
except ValidationError as err:
return jsonify(err.messages), 400
else:
return "Authentication error", 403
if __name__ == '__main__':
app.run(port = 8080, host="0.0.0.0")

3
s3_api/terraform/aws.tf Normal file
View File

@@ -0,0 +1,3 @@
provider "aws" {
region = "eu-central-1"
}

View File

@@ -0,0 +1,7 @@
terraform {
backend "s3" {
bucket = "company-s3-tfstate-bucket-eu-central-1"
region = "eu-central-1"
key = "s3-prod-mybucket-python-testing-1234999"
}
}

50
s3_api/terraform/main.tf Normal file
View File

@@ -0,0 +1,50 @@
resource "aws_s3_bucket" "bucket" {
bucket = var.BUCKET_NAME
tags = {
Name = var.BUCKET_NAME
Environment = var.ENVIRONMENT
}
}
resource "aws_s3_bucket_versioning" "versioning" {
bucket = aws_s3_bucket.bucket.id
versioning_configuration {
status = var.ENCRYPTED
}
}
resource "aws_s3_bucket_public_access_block" "block_public" {
bucket = aws_s3_bucket.bucket.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
data "aws_iam_policy_document" "bucket_policy" {
statement {
sid = "AllowUserReadAccess"
effect = "Allow"
principals {
type = "AWS"
identifiers = ["arn:aws:iam::848173547540:user/dummy_user"]
}
actions = [
"s3:GetObject"
]
resources = [
"${aws_s3_bucket.bucket.arn}/*"
]
}
}
resource "aws_s3_bucket_policy" "bucket_policy" {
bucket = aws_s3_bucket.bucket.id
policy = data.aws_iam_policy_document.bucket_policy.json
}

19
s3_api/terraform/vars.tf Normal file
View File

@@ -0,0 +1,19 @@
variable "BUCKET_NAME" {
description = "Name of the bucket to create"
type = string
}
variable "ENCRYPTED" {
description = "S3 encryption enabled?"
type = string
}
variable "VERSIONING" {
description = "S3 versioning enabled?"
type = string
}
variable "ENVIRONMENT" {
description = "Staging or production env?"
type = string
}

View File

@@ -0,0 +1,19 @@
import os
import pytest
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
SELENIUM_GRID_URL = os.getenv('SELENIUM_GRID_URL')
@pytest.mark.e2e
def test_ping_endpoint():
if not SELENIUM_GRID_URL:
pytest.skip("No Selenium Grid URL set")
driver = webdriver.Remote(
command_executor=SELENIUM_GRID_URL,
desired_capabilities=DesiredCapabilities.CHROME
)
driver.get("http://host.docker.internal:8080/")
assert "Pong" in driver.page_source
driver.quit()

View File