Customers Service - Representation of the Customers Accounts along with their Addresses at the eCommerce Website
In this project, we have created a Customer Resource along with its subordinate - Address Resource as a part of an e-commerce website for the final project of the CSCI-GA-2820-SP23-003 - DevOps and Agile Methodologies course at NYU taught by Professor John Rofrano. Each customer will have address(es) corresponding to it.
To run the service, please use the command honcho start
. The service is available at localhost: http://127.0.0.1:8080
To run the all the test cases locally, please use the command nosetests
. The test cases have 99% coverage currently.
To run the BDD tests, first start the service in a terminal by running honcho start
and then run behave
in another terminal.
The service is currently hosted on a Kubernetes Cluster on IBM Cloud.
Dev: http://159.122.179.165:31001/
Prod: http://159.122.179.165:31002/
The /service
folder contains the models.py
file for the model and a routes.py
file for the Customer service. The /tests
folder has test cases code for testing the model and the service separately. The /features
folder contains the code for BDD testing of the service. And the /deploy
folder contains the yaml files that can be used for deploying the file to a Kubernetes cluster.
The project contains the following:
.gitignore - this will ignore vagrant and other metadata files
.flaskenv - Environment variables to configure Flask
.gitattributes - File to fix Windows CRLF issues
.devcontainers/ - Folder with support for VSCode Remote Containers
dot-env-example - copy to .env to use environment variables
requirements.txt - list of Python libraries required by your code
setup.cfg - configuration parameters
service/ - service python package
├── __init__.py - package initializer
├── config.py - configs for the app
├── models.py - module with business models
├── routes.py - module with service routes
└── common - common code package
├── cli_commands - custom commands to use with flask
├── error_handlers.py - HTTP error handling code
├── log_handlers.py - logging setup code
└── status.py - HTTP status constants
└── static - code for UI of the homepage
tests/ - test cases package
├── __init__.py - package initializer
├── factories.py - factory to generate instances of model
├── test_cli_commands - tests custom flask cli commands
├── test_models.py - test suite for business models
└── test_routes.py - test suite for service routes
features/ - bdd test cases package
├── customers.feature - customers and address test scenarios
├── environment.py - environment for bdd tests
└── steps - code for describing bdd steps
├── steps.py - steps for customers.feature
├── web_steps.py - steps for web interaction with selenium
deploy/ - yaml files for kubernetes deployment
├── deployment.yaml - Deployment for customers api
├── postgresql.yaml - StatefulSet, Service, Secret for postgres db
├── service.yaml - Service for customers api
We've used Postgres for our database that stores the Customer and Address Tables.
GET /
Description | Endpoint |
---|---|
Create a Customer | POST /customers |
Read/Get a Customer | GET /customers/{int:customer_id} |
Update a Customer | PUT /customers/{int:customer_id} |
Delete a Customer | DELETE /customers/{int:customer_id} |
List Customers | GET /customers |
Activate Customer | PUT /customers/{int:customer_id}/activate |
Deactivate Customer | PUT /customers/{int:customer_id}/deactivate |
Search Customers and Addresses | GET /customers?<query_field>=<query_value> |
Description | Endpoint |
---|---|
Create an Address | POST /customers/{int:customer_id}/addresses |
Read/Get an Address | GET /customers/{int:customer_id}/addresses/{int:address_id} |
Update an Address | PUT /customers/{int:customer_id}/addresses/{int:address_id} |
Delete an Address | DELETE /customers/{int:customer_id}/addresses/{int:address_id} |
List Addresses | GET /customers/{int:customer_id}/addresses |
URL : http://127.0.0.1:8080/customers
Method : POST
Auth required : No
Permissions required : None
Create a customer according to the provided first name, last name, email, password.
Example:
Request Body (JSON)
{
"first_name": "Akshama",
"last_name": "AJ",
"password": "aks",
"email": "akshama@gmail.com",
"active": true,
"addresses": [
]
}
Success Response : HTTP_201_CREATED
[
{
"id": 4,
"first_name": "Akshama",
"last_name": "AJ",
"password": "b075b18d6e273c802744f832e3f4cb807b72922e92f203af671a45d3bbe3c658",
"email": "akshama@gmail.com",
"active": true,
"addresses": []
}
]
URL : http://127.0.0.1:8080/customers/{int:customer_id}
Method : GET
Auth required : No
Permissions required : None
Gets/Reads a customer with id == customer_id provided in the URL
Example:
Success Response : HTTP_200_OK
{
"id": 4,
"first_name": "Akshama",
"last_name": "AJ",
"password": "b075b18d6e273c802744f832e3f4cb807b72922e92f203af671a45d3bbe3c658",
"email": "akshama@gmail.com",
"active": true,
"addresses": []
}
Failure Response : HTTP_404_NOT_FOUND
{
"message": "Customer with id '5' was not found."
}
URL : http://127.0.0.1:8080/customers/{int:customer_id}
Method : PUT
Auth required : No
Permissions required : None
Updates a customer with id == customer_id provided in the URL according to the updated fields provided in the body
Example:
Request Body (JSON)
{
"first_name": "Akshama",
"last_name": "Akshama",
"password": "aks",
"email": "akshama@gmail.com",
"active": true,
"addresses": [
],
"id": 0
}
Success Response : HTTP_200_OK
{
"id": 4,
"first_name": "Akshama",
"last_name": "Akshama",
"password": "b075b18d6e273c802744f832e3f4cb807b72922e92f203af671a45d3bbe3c658",
"email": "akshama@gmail.com",
"active": true,
"addresses": []
}
Failure Response : HTTP_404_NOT_FOUND
{
"message": "Customer with id '5' was not found."
}
URL : http://127.0.0.1:8080/customers/{int:customer_id}
Method : DELETE
Auth required : No
Permissions required : None
Deletes a customer with id == customer_id
Example:
Success Response : 204 NO CONTENT
URL : http://127.0.0.1:8080/customers
Method : GET
Auth required : No
Permissions required : None
Lists all the Customers
Example:
Success Response : HTTP_200_OK
[
{
"id": 4,
"first_name": "Akshama",
"last_name": "Akshama",
"password": "b075b18d6e273c802744f832e3f4cb807b72922e92f203af671a45d3bbe3c658",
"email": "akshama@gmail.com",
"active": true,
"addresses": []
}
]
URL : http://127.0.0.1:8080/customers/{customer_id}/activate
Method : PUT
Auth required : No
Permissions required : None
Activates a customer with id == customer_id
Example:
Success Response : HTTP_200_OK
{
"id": 4,
"first_name": "Akshama",
"last_name": "Akshama",
"email": "akshama@gmail.com",
"password": "b075b18d6e273c802744f832e3f4cb807b72922e92f203af671a45d3bbe3c658",
"active": true,
"addresses": []
}
Failure Response : HTTP_404_NOT_FOUND
{
"message": "Customer with id [5] was not found."
}
URL : http://127.0.0.1:8080/customers/{customer_id}/deactivate
Method : PUT
Auth required : No
Permissions required : None
Deactivates a customer with id == customer_id
Example:
Success Response : HTTP_200_OK
{
"id": 4,
"first_name": "Akshama",
"last_name": "Akshama",
"email": "akshama@gmail.com",
"password": "b075b18d6e273c802744f832e3f4cb807b72922e92f203af671a45d3bbe3c658",
"active": false,
"addresses": []
}
Failure Response : HTTP_404_NOT_FOUND
{
"message": "Customer with id [5] was not found."
}
URL : http://127.0.0.1:8080/customers/{int:customer_id}/addresses
Method : POST
Auth required : No
Permissions required : None
Create an address according to the provided street, city, state, country, pin code and customer ID.
Example:
Request Body (JSON)
{
"street": "40 Pavonia Ave",
"city": "Jersey City",
"state": "NJ",
"country": "USA",
"pin_code": "07310",
"customer_id": 4
}
Success Response : HTTP_201_CREATED
{
"address_id": 3,
"street": "40 Pavonia Ave",
"city": "Jersey City",
"state": "NJ",
"country": "USA",
"pin_code": "07310",
"customer_id": 4
}
Failure Response (When invalid Customer ID is provided in the URL) : HTTP_404_NOT_FOUND
{
"message": "Customer with id '5' was not found."
}
URL : http://127.0.0.1:8080/customers/{int:customer_id}/addresses/{int:address_id}
Method : GET
Auth required : No
Permissions required : None
Gets/Reads an address with id == address_id and customer id == customer_id provided in the URL
Example:
Success Response : HTTP_200_OK
{
"address_id": 3,
"street": "40 Pavonia Ave",
"city": "Jersey City",
"state": "NJ",
"country": "USA",
"pin_code": "07310",
"customer_id": 4
}
Failure Response : HTTP_404_NOT_FOUND
{
"message": "Customer with id '5' was not found."
}
{
"message": "Address with id '4' could not be found for the customer with id 4."
}
URL : http://127.0.0.1:8080/customers/{int:customer_id}/addresses/{int:address_id}
Method : PUT
Auth required : No
Permissions required : None
Updates an address with id == address_id and customer id == customer_id provided in the URL according to the updated fields provided in the body
Example:
Request Body (JSON)
{
"street": "40 Newport Pkwy",
"city": "Jersey City",
"state": "NJ",
"country": "USA",
"pin_code": "07310",
"customer_id": 4,
"address_id": 3
}
Success Response : HTTP_200_OK
{
"address_id": 3,
"street": "40 Newport Pkwy",
"city": "Jersey City",
"state": "NJ",
"country": "USA",
"pin_code": "07310",
"customer_id": 4
}
Failure Response : HTTP_404_NOT_FOUND
{
"message": "Customer with id '5' was not found."
}
{
"message": "Address id '4' not found for customer '4'."
}
URL : http://127.0.0.1:8080/customers/{int:customer_id}/addresses/{int:address_id}
Method : DELETE
Auth required : No
Permissions required : None
Deletes an address with id == address_id and customer id == customer_id.
Example:
Success Response : 204 NO CONTENT
URL : http://127.0.0.1:8080/customers/{int:customer_id}/addresses
Method : GET
Auth required : No
Permissions required : None
Lists all the Addresses for a particular customer.
Example:
Success Response : HTTP_200_OK
[
{
"address_id": 3,
"street": "40 Newport Pkwy",
"city": "Jersey City",
"state": "NJ",
"country": "USA",
"pin_code": "07310",
"customer_id": 4
}
]
Failure Response : HTTP_404_NOT_FOUND
{
"message": "Customer with id '5' was not found."
}
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.