Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,7 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Helm
helm/*.tgz
helm/Chart.lock
23 changes: 23 additions & 0 deletions helm/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
23 changes: 23 additions & 0 deletions helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: v2
name: pygeoapi
version: 0.1.0
description: |-
pygeoapi is a Python server implementation of the OGC API suite of standards.
The project emerged as part of the next generation OGC API efforts in 2018
and provides the capability for organizations to deploy a RESTful OGC API
endpoint using OpenAPI, GeoJSON, and HTML.
type: application
keywords:
- GIS
- FOSS4G
- OGC API
- python
home: https://pygeoapi.io/
sources:
- https://github.com/geopython/pygeoapi
- https://github.com/geopython/pygeoapi-examples
maintainers:
- name: Carlos Eduardo Mota
email: [email protected]
icon: "https://pygeoapi.io/img/pygeoapi-logo.png"
appVersion: "0.21.0"
206 changes: 206 additions & 0 deletions helm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# pygeoapi Helm Chart
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add section Requirements, with link to install Helm.


This Helm chart deploys a **pygeoapi** instance, a server that publishes geospatial data using Open Geospatial Consortium (OGC) standards and the OGC API Features. This chart is designed to be flexible and easy to configure, allowing you to customize the deployment to fit your needs. 🚀
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update to publishes geospatial data using the OGC API - Features Standard from the Open Geospatial Consortium (OGC).



## **Local Installation**

To install this chart locally, you'll need a Kubernetes cluster running on your machine, such as **kind**, **minikube**, **CRC/OpenShift Local**, or **Docker Desktop** with Kubernetes enabled. Once your local cluster is up and running, you can install the chart directly from your local file system.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


First, navigate to the chart's directory:

```bash
cd path/to/your/pygeoapi-helm-chart
```

### Default deploy install
Next, use the `helm install` command, specifying the release name and the local chart path (`.`) :

```bash
helm install [YOUR_RELEASE_NAME] .
```

### Install with custom values.yaml
To customize the installation, you can create a custom `values.yaml` file and pass it during installation:

```yaml
# custom values.yaml example
ingress:
enabled: true
hosts:
- host: "ogcapi-pygeoapi.minikube.local"
paths:
- path: /
pathType: ImplementationSpecific

service:
type: NodePort # minikube single node

settings:
config:
enabled: true
name: pygeoapi-custom-config
isEncrypted: true # false -> configMap, true -> secret
serverAdmin: false
hotReload: True
wsgi:
workers: 5
workerTimeout: 6000
workerClass: gevent
```
To modify pygeoapi's behavior, check the "pygeoapi settings"session below.

Now, to deploy pygeoapi with custom values.yaml, just run the lines below

```bash
# first create a configmap with pygeoapi config file
# if config.enabled=true and config.isEncrypted=false
kubectl create configmap pygeoapi-custom-config --from-file=local.config.yml=path/to/custom/pygeoapi-config.yml

# ... or create a secret, if you have sensitive information
# (config.enabled=true and config.isEncrypted=true)
kubectl create secret generic pygeoapi-custom-config --from-file=local.config.yml=path/to/custom/pygeoapi-config.yml

# then install
helm install [YOUR_RELEASE_NAME] . -f my-custom-values.yaml
```

### Openshift-specific setiings
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setiings -> settings


In OpenShift some additional config needs to be set, because pygeoapi still has issues running as non-root user. Three additional steps needs to be set before helm install

1. Add serviceAccount
```yaml
# custom values.yaml example
# We have to define a ServiceAccount for deployment
...
serviceAccount:
create: true
name: pygeoapi
...
```

2. Create a RoleBinding allowing the service account (-z parameter) to run pods as AnyUID, on pygeoapi's project (-n parameter). See below

```bash
# run as kubeadmin or any user capable
oc adm policy add-scc-to-user anyuid -z pygeoapi -n teste
```

3. Create configmap or secret, if necessary, like kubectl but changing it to oc.

```bash
# first create a configmap with pygeoapi config file
# if config.enabled=true and config.isEncrypted=false
oc create configmap pygeoapi-custom-config --from-file=local.config.yml=path/to/custom/pygeoapi-config.yml

# ... or create a secret, if you have sensitive information
# (config.enabled=true and config.isEncrypted=true)
oc create secret generic pygeoapi-custom-config --from-file=local.config.yml=path/to/custom/pygeoapi-config.yml

# then install
helm install [YOUR_RELEASE_NAME] . -f my-custom-values.yaml
```

* In *deploys* directory, **there's an example of a customized values for minikube and CRC/OpenShift Local**.

This will deploy the pygeoapi application to your local cluster, allowing you to test configurations and verify functionality before pushing it to a production environment.


## Configuration Parameters

This chart is configured via the `values.yaml` file. Below is a detailed description of each available parameter.

### Application Image

| Parameter | Description | Default Value |
| :--- | :--- | :--- |
| `replicaCount` | The number of pygeoapi replicas. Increase for higher availability and processing capacity. | `1` |
| `image.repository` | The Docker image repository for pygeoapi to be used. | `docker.io/ndscprm/pygeoapi` |
| `image.pullPolicy` | The image pull policy. `IfNotPresent` prevents downloading if the image already exists locally. | `IfNotPresent` |
| `image.tag` | The specific Docker image tag for the pygeoapi version. | `"0.21.0-rootless"` |
| `imagePullSecrets` | A list of authentication secrets for pulling images from private repositories. | `[]` |
| `nameOverride` | Overrides the chart name when creating Kubernetes resources. | `""` |
| `fullnameOverride` | Overrides the full chart name when creating Kubernetes resources. | `""` |

* This helm chart uses a modified pygeoapi image, because of OpenShift's security requirements. To use official pygeoapi image (v0.21.0), it's required to run the container as root.

### Service Account

| Parameter | Description | Default Value |
| :--- | :--- | :--- |
| `serviceAccount.create` | If `true`, a Service Account is created for the application. | `true` |
| `serviceAccount.automount` | If `true`, automatically mounts the Service Account's credentials. | `true` |
| `serviceAccount.annotations` | Annotations to be added to the Service Account. | `{}` |
| `serviceAccount.name` | The name of the Service Account to use. If empty, a name is generated. | `""` |

### Pod Security and Context

| Parameter | Description | Default Value |
| :--- | :--- | :--- |
| `podAnnotations` | Annotations to be added to the Pod. | `{}` |
| `podLabels` | Labels to be added to the Pod. | `{}` |
| `podSecurityContext` | The security context for the Pod. For example, `fsGroup` to define the filesystem group ID. | `{}` |
| `securityContext` | The security context for the container. For example, `runAsNonRoot` to ensure the process does not run as root. | `{}` |

### Service and Exposure

| Parameter | Description | Default Value |
| :--- | :--- | :--- |
| `service.type` | The Kubernetes service type to expose pygeoapi. | `ClusterIP` |
| `service.port` | The service port where pygeoapi will be exposed. | `8080` |

### Ingress

| Parameter | Description | Default Value |
| :--- | :--- | :--- |
| `ingress.enabled` | If `true`, an Ingress is created to expose pygeoapi externally. | `false` |
| `ingress.className` | The name of the Ingress class to be used. | `""` |
| `ingress.annotations` | Additional annotations for the Ingress. Useful for integrations like `cert-manager`. | `{}` |
| `ingress.hosts` | A list of hosts and paths to route traffic to pygeoapi. | `[]` |
| `ingress.tls` | A list of TLS secrets and associated hosts to encrypt traffic. | `[]` |

### pygeoapi Settings

| Parameter | Description | Default Value |
| :--- | :--- | :--- |
| `settings.config.enabled` | If `true`, mounts the pygeoapi configuration file (`local.config.yml`). | `true` |
| `settings.config.name` | The name of the ConfigMap or Secret containing the configuration. | `pygeoapi-config` |
| `settings.config.isEncrypted` | If `true`, reads the configuration from a Secret; otherwise, from a ConfigMap. | `false` |
| `settings.config.mountPath` | The full path where the configuration file will be mounted inside the container. | `/pygeoapi/local.config.yml` |
| `settings.config.readOnly` | If `true`, mounts the file as read-only. | `true` |
| `settings.openapi` | The path to the pygeoapi OpenAPI file. | `/tmp/pygeoapi-openapi.yml` |
| `settings.serverAdmin` | Enables or disables the server's administration interface. | `false` |
| `settings.hotReload` | Enables hot-reloading of the server. | `false` |
| `settings.wsgi.workers` | The number of workers for the WSGI server (Gunicorn). | `3` |
| `settings.wsgi.workerTimeout` | The worker timeout (in milliseconds). | `6000` |
| `settings.wsgi.workerClass` | The worker class to be used by the WSGI server. | `gevent` |

### Resources and Scaling

| Parameter | Description | Default Value |
| :--- | :--- | :--- |
| `resources` | Definition of resource limits and requests (CPU and memory) for the container. | `{}` |
| `autoscaling.enabled` | If `true`, enables the Horizontal Pod Autoscaler (HPA) to manage the number of replicas. | `false` |
| `autoscaling.minReplicas` | The minimum number of replicas when autoscaling is enabled. | `1` |
| `autoscaling.maxReplicas` | The maximum number of replicas when autoscaling is enabled. | `5` |
| `autoscaling.targetCPUUtilizationPercentage` | The CPU utilization percentage the HPA will try to maintain. | `80` |
| `autoscaling.targetMemoryUtilizationPercentage` | The memory utilization percentage the HPA will try to maintain. | `80` |

### Additional Volumes

| Parameter | Description | Default Value |
| :--- | :--- | :--- |
| `volumes` | A list of additional volumes to be added to the Deployment definition. | `[]` |
| `volumeMounts` | A list of additional volume mounts for the containers. | `[]` |

### Scheduling Configurations

| Parameter | Description | Default Value |
| :--- | :--- | :--- |
| `nodeSelector` | Node labels for selecting which nodes the Pod will be scheduled on. | `{}` |
| `tolerations` | Tolerations to schedule the Pod on nodes with taints. | `[]` |
| `affinity` | Affinity and anti-affinity rules to control Pod scheduling. | `{}` |

For a complete list of all parameters and their default values, please refer to the `values.yaml` file in the chart repository.

31 changes: 31 additions & 0 deletions helm/deploys/values.crc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
ingress:
enabled: true
hosts:
- host: "ogcapi.pygeoapi.apps-crc.testing"
paths:
- path: /
pathType: ImplementationSpecific

serviceAccount:
create: true
name: pygeoapi

settings:
config:
enabled: true
name: pygeoapi-custom-config
isEncrypted: true # false -> configMap, true -> secret
# mountPath: /pygeoapi/local.config.yml
# readOnly: true
# openapi: /tmp/pygeoapi-openapi.yml
serverAdmin: false
hotReload: false
wsgi:
workers: 3
workerTimeout: 6000
workerClass: gevent

# resources:
# limits:
# cpu: 1
# # memory: 128Mi
43 changes: 43 additions & 0 deletions helm/deploys/values.minikube.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
ingress:
enabled: true
hosts:
- host: "ogcapi-pygeoapi.minikube.local" # Change to defined minikube ingress URL
paths:
- path: /
pathType: ImplementationSpecific

# overrides image: registry and tag. Default is official image, last numbered release
image:
pullPolicy: Always # force to pull image on every deploy
tag: latest # force to pull latest

service:
type: NodePort # minikube single node

# securityContext:
# # capabilities:
# # drop:
# # - ALL
# # readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# runAsGroup: 0

settings:
config:
enabled: true
name: pygeoapi-test
isEncrypted: true # false -> configMap, true -> secret
# mountPath: /pygeoapi/local.config.yml
# readOnly: true
serverAdmin: false
hotReload: True
wsgi:
workers: 5
workerTimeout: 6000
workerClass: gevent

# resources:
# limits:
# cpu: 1
# # memory: 128Mi
22 changes: 22 additions & 0 deletions helm/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "pygeoapi.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "pygeoapi.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "pygeoapi.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "pygeoapi.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}
Loading