previewd
is a daemon that is designed to be deployed into a kubernetes cluster to facilitate previewing and hosting of static websites built using a static site generator such as Jekyll, Hugo or Publish.
graph LR
client([browser])-..->ingress[Ingress];
webhook([git webhook])-..->hookingress[webhook receiver<BR>ingress];
ingress-->service[Service];
hookingress-->previewdservice
repo-->webhook
subgraph git
repo
end
subgraph cluster
hookingress;
ingress[Web<BR>frontend<BR>ingress];
previewdservice-->pod3[previewd<BR>jobmanager pod]
repo-..pull content..->pod3
pod3-->renderjob
renderjob[RenderJob<BR>Jekyll image]
pod3-->source
source-->renderjob
renderjob-->render
pod1-->render
pod2-->render
source[Source<BR>volume]
render[Render<BR>volume]
service-->pod1[nginx replica 1];
service-->pod2[inginx replica 2];
end
classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000;
classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff;
classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5;
classDef volume fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5;
class ingress,hookingress,service,pod1,pod2,pod3,previewdservice, k8s;
class client plain;
class cluster cluster;
class source volume
class render volume
Previewd is currently at MVP level of maturity with the basic end-to-end scenario working as of release 0.4. Previewd can be deployed into a kubernetes cluster, will clone a static website source from github.com or a gitea repo, perform an initial markdown->html render by scheduling a kubernetes job, and will then listen for webhook triggered by a push to the repo. When the webhook fires, a rebuild job will be scheduled in the cluster. The resulting html output can be hosted using an instance of nginx
. A set of sample manifests are included in the k8s directory of this repo. Instructions below show how these can be applied to play with the basic scenario.
apiVersion: apps/v1
kind: Deployment
metadata:
name: previewddeployment
namespace: previewdtest
labels:
app: previewdtest
spec:
selector:
matchLabels:
app: previewdtest
template:
metadata:
labels:
app: previewdtest
spec:
serviceAccountName: previewd-sa
containers:
- name: previewd-server
image: registry.hub.docker.com/clarkezone/previewd:0.0.4
imagePullPolicy: Always
args: ["runwebhookserver"]
env:
- name: TARGETREPO
value: https://github.com/clarkezone/selfhostinfrablog.git
- name: LOCALDIR
value: /src
- name: LOGLEVEL
value: debug
- name: NAMESPACE
value: previewdtest
volumeMounts:
- mountPath: /src
name: blogsource
ports:
- containerPort: 8090
volumes:
- name: blogsource
persistentVolumeClaim:
claimName: blogsource-pvc
- name: blogrender
persistentVolumeClaim:
claimName: blogrender-pvc
The backlog is maintained in docs/workbacklog.md. The current focus for the project is building out a production ready set of kubernetes manifests and infrastructure to enable selfhosting of a site leveraging previewd on a home cluster including metrics, monitoring, alerting and high availability. Once that step is complete, work will resume to start tackling the feature backlog.
- Apply manifests:
kubectl apply -f .
- port-forward the ngnix container:
kubectl port-forward -n previewdtest pod/nginxdeployment-7f5454bbdb-gxc5n 8080:80 --address=0.0.0.0
- Point browser at exposed endpoint to view resulting website: e.g.
http://305.15.17.207:8080/
- Port-forward webhook pod
kubectl port-forward -n previewdtest pod/previewddeployment-5fd9dfd86c-blzph 8081:8090 --address=0.0.0.0
- In a separate window, start watching jobs:
kubectl get jobs -w
- Post dummy payload simulating a webhook firing:
curl -X POST http://0.0.0.0:8081/postreceive \
-H 'Content-Type: application/json' -H 'X-GitHub-Event: push' \
-d @k8s/simple/webhooktest/webhook.json
You should see a job get created, proceed and be completed successfully indicating a re-fetch and render triggered by the simulated webhook.
TODO: coming soon
- Install a recent version of golang, we recommend 1.17 or greater. https://go.dev/doc/install
- ensure that your path includes:
export PATH=$PATH:$HOME/go/bin
so that tools installed withgo install
work correctly - Install
make
(debian linux:sudo apt install make
) - Install
gcc
(debian linux:sudo apt install build-essential
) - Install
pre-commit
(debian linux:sudo apt install precommit
) - If you are planning on submitting a PR to this repo, install the git pre-commit hook (
pre-commit install
) - Install
shellcheck
(sudo apt install shellcheck
e - Install tools other golang based linting tools
make install-tools
- If you are planning to use VSCode, ensure you have all of the golang tooling installed
Unless you have access to an existing Kubernetes test cluster with a default storage volume provider,
- Install
k3s
:curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644
- Install a block storage provider such as
Longhorn
:kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.3.0/deploy/longhorn.yaml
. - You will also need to install support for rwx-workloads on longhorn by way of installing nfs mounting tools:
apt install nfs-common
. - Finally, ensure there is only one default storageclass (longhorn):
kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
-
Configure environment variables in shell. There is a .env file in the scripts directory to establish environment variables needed for unit tests. These need to be applied in your shell and in vscode. You can add the following to your .bashrc or manually.
export $(cat scripts/.previewd_test.env | xargs)
-
(optional) if you are planning to debug tests in vscode, you'll need to tell VScode about the environment variables and also enable integration tests. In VS code, go to the command palette and search for
Preferences: Open Remote settings (JSON)
and add the following snippet:{ "go.buildFlags": ["-tags=unit,integration"], "go.buildTags": "-tags=unit,integration", "go.testTags": "-tags=unit,integration" }
Then search for
User Settings
and add the following snippet for environment variables:"go.testEnvFile": "/home/james/.previewd_test.env",
-
Edit
internal/testutils.go
and change the value returned byGetTestConfigPath()
to point to a valid kubeconfig for your test cluster (eg~/.kube.config
in typical setups or/etc/rancher/k3s/k3s.yaml
if you followed the instructions above and installed k3s)
To compile the main previewd executable:
make build
Which will produce a binary at /bin/previewd
To build the docker container
docker build .
This project comes with both unit and integration tests. Unit tests run standalone with no dependencies other than test environment configuration. Integration tests require a kubernetes cluster.
For unit tests, use:
make test
For integration test, since these depend on having a valid k8s cluster to work properly, make sure you followed step 3 in the dev setup list above. Then use:
make integration
Finally, for end-to-end tests that exercise the initial MVP
make end2end
TODO: run tests in VS (exports)