Skip to main content

Project Manifest

A Project Manifest defines the components, configurations, all bits and pieces required by a project in order to automatically build, deploy, run and operate it on the Pergola Pipeline.

The pergola.yaml file​

version: v1

components:
- name: web-api
docker:
file: Dockerfile
build-args:
- name: ARG1
value: MY_VALUE1
- name: ARG2
value: MY_VALUE2
build-context: . # default is .
env:
# static env variable
- name: API_VERSION
value: v1
# variable from required config
- name: PUBLIC_FQDN_ROOT
config-ref: public_hostname
# variable from optional config with default
- name: LOG_LEVEL
config-ref: loglevel
value: info #default
- name: DB_HOST
component-ref: db
- name: DB_PORT
value: "5432"
- name: DB_USER
config-ref: db.user
- name: DB_PWD
config-ref: db.pwd
files:
# map file from required config
- path: /etc/web-api/config.json
config-ref: web-api-config.json
# map file providing inline (static) content
- path: /var/lib/web-api/static-content.xml
content: |
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
# scaling defaults
scaling:
min: 2
max: 5
ports:
- 8080
- 9091

- name: db
docker:
image: postgres:13.3
ports:
- 5432
env:
- name: POSTGRES_PASSWORD
config-ref: postgres_initial_pwd
resources:
cpu: 500m
memory: 2Gi
storage:
- name: pgdata
path: /var/lib/postgresql/data
size: 50Gi

- name: job-regularly
docker:
file: job1/Dockerfile
command: ["./run.sh"]
args: ["--db=$DB_HOST:$DB_PORT", "crunch"]
env:
- name: DB_HOST
component-ref: db
- name: DB_PORT
value: "5432"
scheduled: "0 2 * * *"

- name: job-once
docker:
file: job2/Dockerfile
scheduled: "@release"

Components​

Every project consists of different components, so we declare them one by one under the components section. The components always need the fields name and docker.

    components:
- name: web-api
docker:
image: python:3.10.0-alpine

Docker​

In the docker field you have to define either a Docker image or a Docker file to build an image from.

    docker:
image: python:3.10.0-alpine

If you want to build the image from Dockerfile you also can optionally provide custom build-args and a build-context:

    docker:
file: Dockerfile
build-args:
- name: ARG1
value: MY_VALUE1
- name: ARG2
value: MY_VALUE2
build-context: .
Build-Args​

The build-args field is a key-value list to define build-time variables when building the docker image for example:

    build-args:
- name: HTTP_PROXY
value: http://10.20.30.2:1234
- name: FTP_PROXY
value: http://40.50.60.5:4567
Build-Context​

The build-context field is a string that specifies the path to the directory that contains the files to be sent to the Docker daemon.

Command​

With the command field you can override the EntryPoint field of the Dockerfile

    "command": [
"./run.sh"
]

Args​

With the args field you can override the CMD field of the Dockerfile

    "args": [
"--db=$DB_HOST:$DB_PORT",
"crunch"
]

Environment Variables​

You can declare environment variables (env) that are then available per component on the stage. As usual you declare a key and a value. Keys are represented by name and values by value.

    - name: API_VERSION
value: v1

The value can also be a reference to config values via config-ref

    - name: PUBLIC_FQDN_ROOT
config-ref: public_hostname

or the components hostname via component-ref

    - name: DB_HOST
component-ref: db

If you are not sure if a reference exists or want a fallback default value you can declare it side to side.

    - name: LOG_LEVEL
config-ref: loglevel
value: info

Files​

It is also possible to map files to a certain path inside the component. You can either use a config reference with config-ref

    files:
- path: /etc/web-api/config.json
config-ref: web-api-config.json

or provide static content via the content field.

    files:
- path: /var/lib/web-api/static-content.xml
content: |
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

Storage​

It is possible to create storage volumes per component. These are then available on the stage and are persistent. name declares the name of the storage, path the location where the storage can be found and size the reserved size for the storage.

Storage units are defined by kubernetes storage units, for example:

5Gi is equivalent to 5 gigabyte, 1Ti is equivalent to terabyte or 1000 gigabyte

    storage:
- name: pgdata
path: /var/lib/postgresql/data
size: 50Gi

Ports​

If your component needs some ports to be opened, this is possible by passing a port list. You can open as many ports as you need.

    ports:
- 8080
- 9091

Resources​

You can also define how much cpu power and memory storage you need. The fields cpu and memory can be used. CPU and memory resource units are defined as kubernetes resource units, for example:

1.0 is equivalent to 1 physical or virtual core. 0.5 CPU unit or 500m is equivalent to half a physical or virtual core. 4096Mi or 4Gi is equivalent to 4 gigabyte of memory. 400m is equivalent to 0.4 bytes.

    resources:
cpu: 500m
memory: 2Gi

Scaling​

If you need more than one instance of your component you can define scaling boundaries. Depending on the usage of system resources, it will dynamically scale within given boundaries. Given that, the scaling is only reliable if you also defined resources. The field min represents the minimum amount of instances of your application running and the field max is the maximum amount of instances running.

    scaling:
min: 2
max: 5

Ingresses​

With ingresses you can expose your application to the web on port 80 or 443. host will be the prefix of the url followed by the project-name, the project-stage and the domain in the format: <component.ingress.host>-<project-name>-<stage-name>.<domain> The port field is optional, but mandatory if your component has more than one port. Also your component needs at least one port for this option to work. path will be the path behind the TLD. This is useful for APIs (i.e my-ingress-my-new-project-my-new-stage.pergola.cloud/v1) The combination of host and path must be unique.

    ingresses:
- host: pgweb
port: 8080
path: v1

Scheduled​

You can schedule components, so they don't run like a daemon but are executed once in the scheduler's rhythm. For scheduling you can use the scheduled field and use the standard cron syntax.

    scheduled: "0 2 * * *"

With pergola you can also schedule it to run once every release with the special tag @release

    scheduled: "@release"

Possible use cases would be e.g. database alterations. For testing purposes you can try cronitor.

Identity​

An identity enables access from within a Pergola component to cloud resources (e.g. GCP resources, like BigQuery) via cloud provider’s native IAM entities (e.g. a GCP Service Account) at runtime. The identity defined within Pergola Manifest is a logical name linked to that component at build time. In order to link an identity to a provider's native IAM you need to add that link to your stage configuration See CLI-Usage

    identity: "my-identity"