The project contains the following:
.gitignore - this will ignore vagrant and other metadata files
.flaskenv - Environment variables to configure Flask
.gitattributes - File to gix Windows CRLF issues
.devcontainers/ - Folder with support for VSCode Remote Containers
dot-env-example - copy to .env to use environment variables
requirements.txt - list if Python libraries required by your code
Dockerfile - instructions for building a Docker image for the application
setup.cfg - configuration file for automated tasks like linting, testing, etc.
.coverage - Coverage report file
service/ - service python package
├── __init__.py - package initializer
├── models.py - module with business models
├── routes.py - module with service routes
└── common - common code package
├── __init__.py - package initializer
├── cli_commands.py - Flask CLI extension for database management commands
├── error_handlers.py - HTTP error handling code
├── log_handlers.py - logging setup code
└── status.py - HTTP status constants
tests/ - test cases package
├── __init__.py - package initializer
├── factories.py - factories for creating mock objects in tests
├── test_cli_commands.py - test suite for CLI command extensions
├── test_models.py - test suite for business models
└── test_routes.py - test suite for service routes
features/ - BDD feature files and accompanying test steps
├── steps/ - Step definition modules for feature tests
│ ├── promotions_steps.py - Step definitions for promotions feature tests
│ ├── web_detail_steps.py - Step definitions for web detail feature tests
│ ├── web_steps.py - Step definitions for web feature tests
│ └── environment.py - Setup and teardown hooks for BDD tests
└── promotions.feature - Feature file describing promotion scenarios
k8s/ - Kubernetes deployment configurations
├── deployment.yaml - Defines the deployment to manage application pods
├── ingress.yaml - Configuration for ingress resource to manage external access to the services
├── postgresql.yaml - Deployment and service configuration for the PostgreSQL database
├── pv.yaml - Defines persistent volumes for durable storage
└── service.yaml - Service configuration to expose the application pods
This service is designed to manage promotions. It offers endpoints to create, retrieve, update, and delete promotions.
Run the tests using green
. The goal is to have 95% coverage with 100% passing tests.
$ green
The project uses honcho which gets it's commands from the Procfile. To start the service simply use:
$ honcho start
Service available at: http://localhost:8000. The port that is used is controlled by an environment variable defined in the .flaskenv file which Flask uses to load it's configuration from the environment by default.
This assumes the Makefile has the below command:
make cluster
make deploy
make show
make delete
make cluster-rm
Field | Type | Description |
---|---|---|
id | int | The promotion id |
code | str | The Promotion code |
name | str | The Promotion label (description) |
start | date | Active date |
expired | date | Expired date |
available | int | Code available to use |
whole_store | bool | Whether is whole store promotion |
promo_type | int | The Promotion type |
value | double | Promotion value according to the type |
created_at | Date | Date the Promotion was created |
updated_at | Date | Model lasted updated timestamp |
Note: promotion_type is an integer value that represents the type of promotion. The value can be one of the following:
- 1: Percentage
- 2: Fixed Amount
- 3: Buy X Get Y Free
- 4: Buy X Get Y at Z% Off
- 5: Buy X Get Y at Z% Off (same product)
Field | Type | Description |
---|---|---|
id | int | The Promotion Id |
created_at | str | Date the Promotion applies to the product |
updated_at | Date | Model lasted updated timestamp |
Field | Type | Description |
---|---|---|
promotion_id | int | The Promotion id |
product_id | int | The Product Id |
created_at | str | Date the Promotion applies to the product |
updated_at | Date | Model lasted updated timestamp |
/
GET
200 OK
: Returns the service name, version, and the URL for listing promotions.Example Response:
{
"name": "Promotion Demo REST API Service",
"version": "1.0",
"paths": "<URL for listing promotions>"
}
/promotions
POST
JSON
Field Type Required Des code str True The Promotion code name str True The Promotion label (description) start date True Active date expired date True Expired date available int Code available to use whole_store bool False (Default to False) Whether is whole store promotion promo_type int True The Promotion type value double False (Default to 0.0) Promotion value according to the type
Response:
201 Created
: Returns the created promotion JSON
.
Field Type Des id int The promotion id code str The Promotion code name str The Promotion label (description) start date Active date expired date Expired date available int Code available to use whole_store bool Whether is whole store promotion promo_type int The Promotion type value Date Promotion value according to the type created_at str The Promotion code updated_at Date Model lasted updated timestamp Example Response:
{
{
"id": 1234,
"code": "string",
"name": "string",
"start": "2023-12-13",
"expired": "2024-12-13",
"available": 0,
"whole_store": true,
"promo_type": 0,
"value": 0,
"products": [
0
]
}
}
415 Unsupported Media Type
: If the request is not JSON./promotions/<int:promotion_id>
DELETE
404 Not Found
: If the promotion with the given ID doesn't exist.204 No Content
: This status is returned regardless of whether the promotion existed or not. The delete operation is idempotent, ensuring consistent behavior./promotions/<int:promotion_id>
PUT
JSON
Field Type Required Des code str True The Promotion code name str True The Promotion label (description) start date True Active date expired date True Expired date available int Code available to use whole_store bool False (Default to False) Whether is whole store promotion promo_type int True The Promotion type value double False (Default to 0.0) Promotion value according to the type
Response:
200 OK
: Returns the updated promotion JSON
.
Field Type Des id int The promotion id code str The Promotion code name str The Promotion label (description) start date Active date expired date Expired date available int Code available to use whole_store bool Whether is whole store promotion promo_type int The Promotion type value Date Promotion value according to the type created_at str The Promotion code updated_at Date Model lasted updated timestamp Example Response:
{
{
"id": 2637,
"code": "string",
"name": "string",
"start": "2023-12-13T00:00:00",
"expired": "2024-12-13T00:00:00",
"available": 0,
"whole_store": true,
"promo_type": 0,
"value": 0,
"products": []
}
}
400 Bad Request
: For data validation errors.404 Not Found
: If the promotion with the given ID doesn't exist./promotions
GET
name
(optional): Filter promotions by name.code
(optional): Filter promotions by code.promo_type
(optional): Filter promotions by type.Response:
200 OK
: Returns a list of promotions as JSON.
Example Response:[
{
"id": 3025,
"code": "ac2ef65c-309e-4029-af3f-f69985f628d8",
"name": "Updated Promotion Name",
"start": "2023-12-13T00:00:00",
"expired": "2023-12-14T00:00:00",
"available": 10,
"whole_store": false,
"promo_type": 1,
"value": 10,
"products": []
}
]
/promotions/<int:promotion_id>
GET
Response:
200 OK
: Returns the requested promotion as JSON.
Example Response:{
"id": 3025,
"code": "ac2ef65c-309e-4029-af3f-f69985f628d8",
"name": "Updated Promotion Name",
"start": "2023-12-13T00:00:00",
"expired": "2023-12-14T00:00:00",
"available": 10,
"whole_store": false,
"promo_type": 1,
"value": 10,
"products": []
}
404 Not Found
: If the promotion with the given ID doesn't exist./promotions/<int:promotion_id>/apply
POST
200 OK
: Returns the requested promotion as JSON.404 Not Found
: If the promotion with the given ID doesn't exist.405 Method Not Allowed
: If the promotion is already expired or not available./promotions/<int:promotion_id>/cancel
POST
200 OK
: Returns the requested promotion as JSON.404 Not Found
: If the promotion with the given ID doesn't exist.Copyright (c) John Rofrano. All rights reserved.
Licensed under the Apache License. See LICENSE
This repository is part of the NYU masters class: CSCI-GA.2820-001 DevOps and Agile Methodologies created and taught by John Rofrano, Adjunct Instructor, NYU Courant Institute, Graduate Division, Computer Science, and NYU Stern School of Business.