Skip to content

Commit

Permalink
Changes for CRON and Email Queue Table added (#136)
Browse files Browse the repository at this point in the history
* Changes for CRON (#131)

* fixed CI errors
  • Loading branch information
saravanpa-aot authored Nov 4, 2024
1 parent 588c816 commit a517709
Show file tree
Hide file tree
Showing 47 changed files with 1,911 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
.DS_Store
96 changes: 96 additions & 0 deletions deployment/build-config/cron.bc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
kind: Template
apiVersion: template.openshift.io/v1
metadata:
annotations:
description: Build template for the Submit Cron job runner.
tags: flask
iconClass: icon-python
name: "${NAME}-build-template"
objects:
- kind: ImageStream
apiVersion: image.openshift.io/v1
metadata:
name: "${NAME}"
- kind: BuildConfig
apiVersion: build.openshift.io/v1
metadata:
name: "${NAME}"
labels:
app: "${NAME}"
app-group: "${APP_GROUP}"
template: "${NAME}-build"
spec:
source:
type: Git
git:
uri: "${GIT_REPO_URL}"
ref: "${GIT_REF}"
contextDir: "${SOURCE_CONTEXT_DIR}"
strategy:
type: Docker
dockerStrategy:
dockerfilePath: "${DOCKER_FILE_PATH}"
output:
to:
kind: ImageStreamTag
name: "${NAME}:${OUTPUT_IMAGE_TAG}"
triggers:
- type: ConfigChange
parameters:
- name: NAME
displayName: Name
description:
The name assigned to all of the objects defined in this template. You
should keep this as default unless you know what you're doing.
required: true
value: submit-cron
- name: APP_GROUP
displayName: App Group
description: The name assigned to all of the deployments in this project.
required: true
value: submit-app
- name: GIT_REPO_URL
displayName: Git Repo URL
description:
The URL to your GIT repo, don't use the this default unless you're just
experimenting.
required: true
value: https://github.com/bcgov/EPIC.submit.git
- name: GIT_REF
displayName: Git Reference
description: The git reference or branch.
required: true
value: cron
- name: SOURCE_CONTEXT_DIR
displayName: Source Context Directory
description: The source context directory.
required: true
value: submit-cron
- name: SOURCE_IMAGE_KIND
displayName: Source Image Kind
required: true
description:
The 'kind' (type) of the source image; typically ImageStreamTag, or
DockerImage.
value: ImageStreamTag
- name: SOURCE_IMAGE_NAME_SPACE
displayName: Source Image Name Space
required: true
description: The name space of the source image.
value: c8b80a-tools
- name: SOURCE_IMAGE_NAME
displayName: Source Image Name
required: true
description: The name of the source image.
value: python
- name: OUTPUT_IMAGE_TAG
displayName: Output Image Tag
description: The tag given to the built image.
required: true
value: latest
- name: DOCKER_FILE_PATH
displayName: Docker File Path
description: The path to the docker file defining the build.
required: false
value: Dockerfile
179 changes: 179 additions & 0 deletions deployment/cron.dc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
apiVersion: template.openshift.io/v1
kind: Template
metadata:
name: cron-deploy-template
annotations:
description: "Deployment Configuration Template for the Submit Cron job Project"
tags: "submit, cron, python"
objects:
- kind: DeploymentConfig
apiVersion: apps.openshift.io/v1
metadata:
name: ${NAME}
labels:
app: ${NAME}
app-group: submit-app
template: ${NAME}-deploy
spec:
strategy:
type: Rolling
rollingParams:
updatePeriodSeconds: 1
intervalSeconds: 1
timeoutSeconds: 600
maxUnavailable: 25%
maxSurge: 25%
pre:
execNewPod:
command:
- /submit-cron/pre-hook-update-db.sh
containerName: ${NAME}
failurePolicy: Abort
triggers:
- type: ImageChange
imageChangeParams:
automatic: true
containerNames:
- ${NAME}
from:
kind: ImageStreamTag
namespace: ${IMAGE_NAMESPACE}
name: ${NAME}:${IMAGE_TAG}
- type: ConfigChange
replicas: 1
test: false
selector:
app: ${NAME}
deploymentconfig: ${NAME}
template:
metadata:
labels:
app: ${NAME}
app-group: submit-app
environment: ${ENV}
deploymentconfig: ${NAME}
template: ${NAME}-deploy
spec:
volumes:
- name: cron-config
configMap:
name: ${NAME}-config
defaultMode: 420
containers:
- name: ${NAME}
image: image-registry.openshift-image-registry.svc:5000/${IMAGE_NAMESPACE}/${NAME}:${IMAGE_TAG}
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- name: cron-config
readOnly: true
mountPath: /submit-cron/cron/
env:
- name: DATABASE_USERNAME
valueFrom:
secretKeyRef:
key: app-db-username
name: submit-patroni
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: submit-patroni
key: app-db-password
- name: DATABASE_NAME
valueFrom:
secretKeyRef:
name: ${DATABASE_HOST}
key: app-db-username
- name: DATABASE_HOST
value: ${DATABASE_HOST}
- name: DATABASE_PORT
value: ${DATABASE_PORT}
resources:
requests:
cpu: ${CPU_REQUEST}
memory: ${MEMORY_REQUEST}
limits:
cpu: ${CPU_LIMIT}
memory: ${MEMORY_LIMIT}
terminationMessagePath: "/dev/termination-log"
terminationMessagePolicy: File
imagePullPolicy: Always
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext: {}
schedulerName: default-scheduler
- kind: Service
apiVersion: v1
metadata:
name: ${NAME}
creationTimestamp:
labels:
app: ${NAME}
app-group: submit-app
template: ${NAME}-deploy
spec:
ports:
- name: 8080-tcp
protocol: TCP
port: 8080
targetPort: 8080
selector:
deploymentconfig: ${NAME}
type: ClusterIP
sessionAffinity: None
status:
loadBalancer: {}
- apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: ${NAME}
app-group: submit-app
name: ${NAME}
data:
parameters:
- name: NAME
description: "The name assigned to all of the OpenShift resources associated to the server instance."
required: true
value: submit-cron
- name: IMAGE_NAMESPACE
required: true
description: "The namespace of the OpenShift project containing the imagestream for the application."
value: c8b80a-tools
- name: ENV
description: "The TAG name for this environment, e.g.(dev, test, prod)."
required: true
value: dev
- name: DATABASE_HOST
description: "The analytics postgresql application name."
required: true
value: submit-patroni
- name: DATABASE_PORT
description: "The analytics postgresql application port."
required: true
value: '5432'
- name: CPU_REQUEST
description: "The resources CPU request (in cores) for this build."
required: true
value: 100m
- name: CPU_LIMIT
description: "The resources CPU limit (in cores) for this build."
required: true
value: 750m
- name: MEMORY_REQUEST
description: "The resources Memory request (in Mi, Gi, etc) for this build."
required: true
value: 100Mi
- name: MEMORY_LIMIT
description: "The resources Memory limit (in Mi, Gi, etc) for this build."
required: true
value: 2Gi
- name: REPLICAS
description: "The number of replicas to run in this environment."
required: true
value: '1'
- name: IMAGE_TAG
description: "The image tag to deploy"
value: latest
42 changes: 42 additions & 0 deletions submit-api/migrations/versions/5bf7b1f9a81c_email_queue_added.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Email queue added
Revision ID: 5bf7b1f9a81c
Revises: e1e1b81ad5c8
Create Date: 2024-10-30 07:23:40.214720
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '5bf7b1f9a81c'
down_revision = '075df7d4f03b'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('email_queue',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('entity_id', sa.Integer(), nullable=False),
sa.Column('entity_type', sa.String(length=50), nullable=False),
sa.Column('template_name', sa.String(length=50), nullable=False),
sa.Column('status', sa.String(length=50), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('sent_at', sa.DateTime(), nullable=True),
sa.Column('error_message', sa.String(length=500), nullable=True),
sa.Column('created_date', sa.DateTime(), nullable=False),
sa.Column('updated_date', sa.DateTime(), nullable=True),
sa.Column('created_by', sa.String(length=50), nullable=True),
sa.Column('updated_by', sa.String(length=50), nullable=True),
sa.PrimaryKeyConstraint('id')
)

# ### end Alembic commands ###


def downgrade():
op.drop_table('email_queue')
# ### end Alembic commands ###
2 changes: 2 additions & 0 deletions submit-api/src/submit_api/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .item import Item
from .item_type import ItemType
from .package import Package
from .package_metadata import PackageMetadata
from .package_item_type import PackageItemType
from .package_type import PackageType
from .project import Project
Expand All @@ -32,3 +33,4 @@
from .submitted_document import SubmittedDocument
from .submitted_form import SubmittedForm
from .user import User
from .email_queue import EmailQueue
44 changes: 44 additions & 0 deletions submit-api/src/submit_api/models/email_queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Email queue model."""
from __future__ import annotations

from datetime import datetime
from typing import List

from sqlalchemy import Column, DateTime

from .base_model import BaseModel
from .db import db


class EmailQueue(BaseModel):
"""Model class for email queue."""

__tablename__ = 'email_queue'

id = Column(db.Integer, primary_key=True, autoincrement=True)
entity_id = Column(db.Integer, nullable=False)
entity_type = Column(db.String(50), nullable=False)
template_name = Column(db.String(100), nullable=False)
# Status can be one of: 'PENDING', 'SENT', 'FAILED'
status = Column(db.String(50), nullable=False, default='PENDING')
created_at = Column(DateTime, nullable=False, default=datetime.utcnow)
sent_at = Column(DateTime, nullable=True)
error_message = Column(db.String(500), nullable=True)

@classmethod
def find_pending(cls):
"""Find all pending emails in the queue.
Returns:
list[EmailQueue]: List of pending email queue entries
"""
return cls.query.filter_by(status='PENDING').all()

@classmethod
def find_all(cls) -> List[EmailQueue]:
"""Find all entries in the email queue.
Returns:
list[EmailQueue]: List of all email queue entries.
"""
return cls.query.all()
Loading

0 comments on commit a517709

Please sign in to comment.