Exercises part 2


Exercise 1 - Zoo

Create an API that will help a zoo by suggesting new animals to add to their existing collection of animals.

Create the script zoo.py and first of all add the following list with animals your API can suggest:

all_animals = ["badger", "lion", "wolf", "porcupine", "cheetah", "giraffe", "panda", "gorilla", "tiger", "koala", "jaguar", "elephant", "blue-and-yellow macaw", "hornbill", "rhinoceros", "kangaroo", "ostridge", "bison", "wallaby"]

Create the endpoint /zoo and make sure it will send back a number of randomly chosen animals. Of these animals, their sex will also be randomly chosen.

The application or user addressing this endpoint might choose how many animals should be returned/suggested by the API. If that number is not determined, the API should provide exactly 5 animals. In case the endpoint is addressed and more or less than 5 animals should be returned, it will be called in the following manner:

http://127.0.0.1:8000/zoo?number=2open in new window

The following JSON will be returned in that case:

{
    "animals": [
        {
            "number": 1,
            "species": "hornbill",
            "sex": "male"
        },
        {
            "number": 2,
            "species": "bison",
            "sex": "male"
        }
    ]
}

Note

The value corresponding with the number key in each animal object will be increased by 1 with every animal shown. So in case you have 10 animal objects, the value for the last animal will be 10.

Pay attention

Please beware that your result will have different animals and sexes than the example above as the animals and sexes are randomly chosen each time you address the API endpoint. The sex of these animals can either be male or female.

Make sure that:

  • The number parameter is larger than 0. If not, use the built-in functionality of FastAPI to show an error.
  • The documentation in OpenAPI is the same as shown below.

Zoo exercise - docs

Exercise 2 - Business cards

Create the file businesscard.py in which you will make this exercise.

Keep track of your personal information to create a business card.

No database yet...

Because we don't have a database connection yet, we cannot make our data persistent. That means that we can only store something locally at this point. We will be using a dictionary with int as key to store our business cards.

Create a dictionary named cards which already holds one card under the key 0 to start off with, the following:

business_card_brent = {
    "first_name": "Brent",
    "last_name": "Pulmans",
    "street": "Kleinhoefstraat",
    "number": "4",
    "zip": 2440,
    "city": "Geel"
}

Step 1

Create a POST request which allows the user to create an object containing business card information. This POST request should be addressed using the endpoint /cards. You should be able to store the following information, similar to the example:

  • First name
  • Last name
  • Street
  • Number
  • Addition (= bus)
  • Zip code (= postcode)
  • City

All fields are required, except for the 'Addition' field. As this API is meant specifically for Belgian business cards, the zip code will always be a number (no letters will be used in it).

Make use of a Pydantic model to create the structure of your data. In your model you should prevent the 'number' from becoming too long. 10 characters should be the maximum.

Make sure this new business card gets added to the general dictionary you made to hold all cards and make sure you use a new key for each card. As per usual, this POST should return the inserted card to the user to check.

Step 2

Create a GET request with the endpoint /cards which will return all business cards presently stored.

Step 3

Create a PUT request with the endpoint /cards/{id} which will update the business card information of the card matching that id in the dictionary, using the body sent along with the request. As per usual, this PUT should return the updated card to the user to check.

Exercise 3 - Machines

We have the following machine information to start off with:

[
    {
        "name": "sLaptop",
        "ip": "192.168.0.1",
        "user": "John"
    },
    {
        "name": "sDesktop",
        "ip": "192.168.0.2",
        "user": "Will"
    }
]

Create an API in machines.py which provides the following endpoints:

  • GET /machine: Returns the entire list of present machines, showing IP address and name. The user must be left out for privacy reasons.
  • POST /machine: Insert a new machine into the API. Name, IP address and user all have to be provided. The IP address must be in a valid IPv4 format. The name of the machine must be at least 3 characters long. Return the entire inserted machine information to the user to check.

Make use of Pydantic models.

Exercise 4 - Device usage warnings

For this exercise, create the file deviceusage.py.

Create an API that will give you readings about the usage of certain parts of your system. We will cover the CPU percentage, virtual memory percentage and swap memory percentage.

psutil

Just like with previous exercises we made earlier, we will make use of functionality of the psutil libraryopen in new window here. Have a look in the psutil library documentation to find what you need.

Step 1

Create 3 endpoints which will return the following information:

  • Endpoint 1: CPU %
  • Endpoint 2: virtual memory %
  • Endpoint 3: swap memory %

You are free to choose your own names for these endpoints, but make sure the names are meaningful. Each endpoint should return a simple JSON containing one key-value pair which gives the necessary information. For example, for the CPU percentage, the following JSON could be returned:

{
    "CPU %": 52
}

Step 2

Create an endpoint /warnings that will check whether the above mentioned percentages are within desired limits. There are 3 limits to check: CPU %, virtual memory % and swap memory %. Make sure these limits can be chosen when the API is called, but in case no value is given, a default limit of 50% will be taken into account.

Create a JSON with the exact structure as the one shown below that will be given back in the response body.

{
    "warnings": true,
    "readings": {
        "CPU limit": 50,
        "CPU %": 22.9,
        "virtual memory limit": 50,
        "virtual memory %": 79.7,
        "swap memory limit": 50,
        "swap memory %": 24.8
    }
}

Please note that:

  • warnings will become true if either the CPU % is above its limit, or the virtual memory % is above its limit, or the same applies for the swap memory %.
  • the value of the keys containing the limit equals the requested limit. In the example above, the default values of 50% have been applied (so no alternative limit has been asked for).

In case the virtual memory % limit should be set to 80, the endpoint should be called in the following manner:

http://127.0.0.1:8000/warnings?max_virtual_memory_percentage=80open in new window

The JSON response would in that case look like this:

{
    "warnings": false,
    "readings": {
        "CPU limit": 50,
        "CPU %": 22.9,
        "virtual memory limit": 80,
        "virtual memory %": 79.7,
        "swap memory limit": 50,
        "swap memory %": 24.8
    }
}

Prevent the entered limits from being negative or more than 100%. You should make sure this check is performed before your function is entered in the API.

In case a limit of 107% is asked for example, the following error message should be returned:

{
    "detail": [
        {
            "loc": [
                "query",
                "max_virtual_memory_percentage"
            ],
            "msg": "ensure this value is less than 100",
            "type": "value_error.number.not_lt",
            "ctx": {
                "limit_value": 100
            }
        }
    ]
}

Exercise 2bis - Business cards EXTRA

Edit the file businesscard.py in which used in a previous exercise.

Change the a GET request endpoint /cards so that it can also take a query parameter secure. When we perform a GET request to /cards?secure=on it should return the business cards but only containing the first name and last name values:

{
    "0": {
        "first_name": "Brent",
        "last_name": "Pulmans"
    }
}

This can be achieved with or without an extra Pydantic model class. First try it without and then try to complete this with creating a new model class. Check out the following links to help you:

Last update: 10/10/2022, 11:27:04 PM