Ship Slightly Better Microservices.
Tags: microservices, docker, devops, infrastructureascode
Published: 2023-09-04 12:58:33

## Introducing env_should_be

In the fast-paced oblate spheroid we call home, building microservices and multi-environment deployments, ensuring the integrity, security, and compatibility of containers is a monumental challenge. Battling with microservices and incremental development, I've seen firsthand the complexities and frustrations that arise with maintaining consistency across different deployment environments. I was trying to solve this problem and, in doing so, created env_should_be—a PyPI package that might change your approach to building containers… (We’ll see about that!)

## The Motivation Behind env_should_be

Microservices architecture, with its flexibility and scalability, has become the standard for modern software development. However, it also brings a new set of challenges, one of which is ensuring that containers are running in environments that are compatible and secure. Traditional methods often involve extensive coordination between developers and operations teams, leading to bottlenecks, configurations, and security vulnerabilities.

The need for a more efficient, automated, and developer-friendly approach became evident. env_should_be was created to address these challenges by allowing developers to define deployment environment requirements using simple JSON or YAML descriptions. This empowers developers to specify the exact conditions under which a container can run, mitigating compatibility issues and enforcing security standards seamlessly… This environment description can either be one or multiple files and can also be a combination for each type of environment…

## env_should_be in Action

So, how does env_should_be work, and what sets it apart? At its core, env_should_be is a command-line interface (CLI) tool that you can effortlessly integrate into your container deployment pipelines. It takes deployment environment descriptions in JSON or YAML format as input, allowing you to specify requirements for various environment variables, file paths, and even execution callbacks…. It also can be shipped as part of the actual container or be used as a pipeline stage, to validate the environment before deploying…

### Environment Descriptions

Imagine you have a flask microservice that relies on a database and cache, and you want to ensure that certain environment variables meet specific criteria each time before the app starts, Here's an example YAML description:

```yaml
DB_USER:
  length: 8
  regex: "^[a-zA-Z0-9]+$"
DB_PASSWORD:
  length: 12
  regex: "^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\\$%\\^&\\*])(?=.{8,})"
DB_HOST:
  option:
    - localhost
    - 127.0.0.1
DB_PORT:
  length: 4
  regex: "^[0-9]+$"
  is_int: True
  is_float: False
CACHE: # sure that it has the same value across whatever env?
  constant: "redis://container_name:6379/1"
APP_ENV:
  option:
    - dev
    - prod
  required: false # only get's validated if it is set (not None)
```

then a compose file:

```yaml
version: '3'
services:
  app:
    build:
      context: .
    expose:
      - 5000
    environment:
    command: >
      sh -c '
        env_should_be -d "/app/descriptions/app.json" && \
        flask run --host=0.0.0.0 --port 5000'
```

env_should_be will check these conditions before allowing the container to run. If any condition is not met, it can either block the container from running or using the **-fs** argument, let it start and log the errors, depending on your preference…

### Callback Scripts

But that's not all—env_should_be also provides the ability to execute callback scripts whenever a container attempts to start with an environment that doesn't match the defined description. This feature is incredibly powerful because it enables you to take immediate corrective actions or trigger notifications when something is amiss.

## Why env_should_be Matters

env_should_be offers a multifaceted solution to the challenges of microservices and multi-environment deployments:

### 1. Consistency and Compatibility

By specifying environmental requirements, it ensures that containers only run in environments that can support them. This eliminates compatibility issues, reducing the likelihood of runtime errors and downtime.

### 2. Security and Compliance

It empowers you to enforce security standards by defining strict criteria for environment variables. You can rest assured that your microservices are operating in a secure environment, mitigating potential security vulnerabilities.

### 3. Developer-Operations Collaboration

With it, developers can define deployment requirements independently, reducing the need for constant coordination with operations teams. This fosters a more efficient and autonomous development workflow.

### 4. Error Handling and Notifications

Error-handling options allow you to choose whether to block containers or let them start with errors logged. Additionally, the ability to trigger callback scripts ensures swift responses to deployment issues.

## Getting Started

To get started, you can easily install it via PyPI and integrate it into your Docker containers. 

```sh
# I believe you are using a venv, right?  
python -m pip install env_should_be
```
## full list of possible descriptions:

```
(
  "boolean",
  "length",
  "min_length",
  "max_length",
  "regex",
  "option",
  "constant",
  "is_int",
  "is_str",
  "is_float",
  "is_number",
  "is_greater_than_eq",
  "is_lower_than_eq",
  "is_http",
  "is_https",
  "is_ipv4",
  "is_ipv6",
  "is_email",
  "is_uuid",
)
```

Feel free, to try it/ break it, and open PR.

[source code
](https://github.com/wassef911/env_should_be)
[latest version
](https://pypi.org/project/env-should-be/)