Compare commits
93 commits
Author | SHA1 | Date | |
---|---|---|---|
d1dfeb092f | |||
d171ef0102 | |||
|
9501120d88 | ||
|
2e7de036a5 | ||
a8e1dae976 | |||
89cd45fdd3 | |||
b593ac8b7c | |||
87a18c4010 | |||
84646748f2 | |||
1f8ced4e6d | |||
76882ba196 | |||
a84ef439cb | |||
457b106829 | |||
f78e089639 | |||
86f3bd94fb | |||
b07191d9d5 | |||
3524b2209e | |||
d43cad692a | |||
0cd0225918 | |||
07cea8cfeb | |||
|
a1803e79a6 | ||
|
e1d43cddc5 | ||
|
3944c28562 | ||
|
56a08653e9 | ||
|
889b95f572 | ||
|
9e8af08ec2 | ||
|
26a687c488 | ||
|
d1764c64ed | ||
|
7e146a3463 | ||
|
164f66d4b7 | ||
|
ebca7a3454 | ||
|
548dd14091 | ||
|
f1e41b3333 | ||
|
9e75c22337 | ||
|
e02f4949fc | ||
|
e923c9d5c3 | ||
|
248c33613a | ||
|
600dd1c30a | ||
d496ba28f6 | |||
e69c9e87bd | |||
2dff50f7b8 | |||
d7be8aa730 | |||
9efbf4dbc4 | |||
1b1d316653 | |||
20401c20b7 | |||
f16ee34782 | |||
18ec39549e | |||
e97fc0d675 | |||
800f4e6bb0 | |||
8b2e14277a | |||
0d5d10d64c | |||
2582bcfb10 | |||
5389003d6b | |||
b4feea06cf | |||
ac57564e0f | |||
a0bf9064ed | |||
3a216d52df | |||
b4ec6d16b3 | |||
d396e3abae | |||
9c5ca90eef | |||
6504668953 | |||
68c4f02344 | |||
e785833304 | |||
3d5864f944 | |||
740bd021f2 | |||
53fc7a990d | |||
1790487d6e | |||
3257d332dc | |||
5d3621f6f8 | |||
9cb0e50853 | |||
0cf35755f9 | |||
93f3618a86 | |||
4d7928f244 | |||
375f11c0d9 | |||
cc97cae0d0 | |||
7fc494c1df | |||
2770883473 | |||
8af984c079 | |||
209f1bd9ca | |||
f0ed84822b | |||
04377f0daf | |||
5d904697c5 | |||
1cb78ec68b | |||
a9c9f51fa3 | |||
b0516e1943 | |||
0bb8704b0f | |||
e295deb0b8 | |||
f323306c9c | |||
c5780d04a7 | |||
03ac969aa9 | |||
c8a86192ca | |||
e7aed2c4c2 | |||
9e16cc38e0 |
32 changed files with 1027 additions and 1361 deletions
|
@ -6,7 +6,7 @@ stages:
|
||||||
- image
|
- image
|
||||||
|
|
||||||
.img: &img
|
.img: &img
|
||||||
image: "domaindrivenarchitecture/ddadevops-dind:4.10.5"
|
image: "domaindrivenarchitecture/ddadevops-dind:4.11.4"
|
||||||
services:
|
services:
|
||||||
- docker:dind
|
- docker:dind
|
||||||
before_script:
|
before_script:
|
||||||
|
@ -16,7 +16,7 @@ stages:
|
||||||
- export IMAGE_TAG=$CI_COMMIT_TAG
|
- export IMAGE_TAG=$CI_COMMIT_TAG
|
||||||
|
|
||||||
.cljs-job: &cljs
|
.cljs-job: &cljs
|
||||||
image: "domaindrivenarchitecture/ddadevops-clj-cljs:4.10.5"
|
image: "domaindrivenarchitecture/ddadevops-clj-cljs:4.11.4"
|
||||||
cache:
|
cache:
|
||||||
key: ${CI_COMMIT_REF_SLUG}
|
key: ${CI_COMMIT_REF_SLUG}
|
||||||
paths:
|
paths:
|
||||||
|
@ -29,7 +29,7 @@ stages:
|
||||||
- npm install
|
- npm install
|
||||||
|
|
||||||
.clj-job: &clj
|
.clj-job: &clj
|
||||||
image: "domaindrivenarchitecture/ddadevops-clj-cljs:4.10.5"
|
image: "domaindrivenarchitecture/ddadevops-clj:4.11.4"
|
||||||
cache:
|
cache:
|
||||||
key: ${CI_COMMIT_REF_SLUG}
|
key: ${CI_COMMIT_REF_SLUG}
|
||||||
paths:
|
paths:
|
||||||
|
@ -93,6 +93,15 @@ package-uberjar:
|
||||||
paths:
|
paths:
|
||||||
- target/uberjar
|
- target/uberjar
|
||||||
|
|
||||||
|
package-native:
|
||||||
|
<<: *clj
|
||||||
|
stage: package
|
||||||
|
script:
|
||||||
|
- pyb package_native
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- target/graalvm
|
||||||
|
|
||||||
release-to-clojars:
|
release-to-clojars:
|
||||||
<<: *clj
|
<<: *clj
|
||||||
<<: *tag_only
|
<<: *tag_only
|
||||||
|
|
109
README.md
109
README.md
|
@ -2,27 +2,66 @@
|
||||||
|
|
||||||
[![Clojars Project](https://img.shields.io/clojars/v/org.domaindrivenarchitecture/c4k-website.svg)](https://clojars.org/org.domaindrivenarchitecture/c4k-website) [![pipeline status](https://gitlab.com/domaindrivenarchitecture/c4k-website/badges/master/pipeline.svg)](https://gitlab.com/domaindrivenarchitecture/c4k-website/-/commits/main)
|
[![Clojars Project](https://img.shields.io/clojars/v/org.domaindrivenarchitecture/c4k-website.svg)](https://clojars.org/org.domaindrivenarchitecture/c4k-website) [![pipeline status](https://gitlab.com/domaindrivenarchitecture/c4k-website/badges/master/pipeline.svg)](https://gitlab.com/domaindrivenarchitecture/c4k-website/-/commits/main)
|
||||||
|
|
||||||
[<img src="https://domaindrivenarchitecture.org/img/delta-chat.svg" width=20 alt="DeltaChat"> chat over e-mail](mailto:buero@meissa-gmbh.de?subject=community-chat) | [<img src="https://meissa-gmbh.de/img/community/Mastodon_Logotype.svg" width=20 alt="team@social.meissa-gmbh.de"> team@social.meissa-gmbh.de](https://social.meissa-gmbh.de/@team) | [Website & Blog](https://domaindrivenarchitecture.org)
|
[<img src="https://domaindrivenarchitecture.org/img/delta-chat.svg" width=20 alt="DeltaChat"> chat over e-mail](mailto:buero@meissa-gmbh.de?subject=community-chat) | [<img src="https://meissa.de/images/parts/contact/mastodon36_hue9b2464f10b18e134322af482b9c915e_5501_filter_14705073121015236177.png" width=20 alt="M"> meissa@social.meissa-gmbh.de](https://social.meissa-gmbh.de/@meissa) | [Blog](https://domaindrivenarchitecture.org) | [Website](https://meissa.de)
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
Delivering cryogen generated static sites with the push of a few buttons.
|
**GitOps for static generated Websites.**
|
||||||
|
|
||||||
c4k-website generates configuration files for multiple nginx webservers, and
|
c4k-website generates k8s-manifest for a webserver serving static html.
|
||||||
corresponding cryogen static site generator build containers. This automatically downloads a `<branch>.zip` from a specified gitea API url. You need an authorization token to access the specified gitea user account. The build container is based on clojure:lein.
|
|
||||||
|
|
||||||
Following the example in valid-config.edn and valid-auth.edn you can add as many websites as you like (provided you have the DNS Routes set up). One set of configmaps, deployment, services etc will be created for each element in the :websites and :auth list.
|
c4k-website is an example how to create k8s manifests for OneShotDeployments with https://repo.prod.meissa.de/meissa/c4k-common.
|
||||||
|
|
||||||
Configs generated by c4k-website consists of the following parts:
|
## Features
|
||||||
|
|
||||||
* nginx deployment + configmap + service + ingress + certificate definitions
|
- [convention 4 kubernetes: c4k-website](#convention-4-kubernetes-c4k-website)
|
||||||
* nginx deployment has init container, building the website at startup time
|
- [Purpose](#purpose)
|
||||||
* cron job for building and build secret for storing auth data
|
- [Features](#features)
|
||||||
* respective volume claims
|
- [Serving multiple websites](#serving-multiple-websites)
|
||||||
|
- [https \& Letsencrypt Certificates](#https--letsencrypt-certificates)
|
||||||
|
- [Ratelimiting](#ratelimiting)
|
||||||
|
- [Monitoring](#monitoring)
|
||||||
|
- [GitOps your Websites](#gitops-your-websites)
|
||||||
|
- [Support Hugo and Cryogene](#support-hugo-and-cryogene)
|
||||||
|
- [Try out](#try-out)
|
||||||
|
- [Usage](#usage)
|
||||||
|
- [Development \& mirrors](#development--mirrors)
|
||||||
|
- [License](#license)
|
||||||
|
|
||||||
## Status
|
### Serving multiple websites
|
||||||
|
|
||||||
Stable - we use this setup on production.
|
You can serve many websites, each of can listen to a list of domain names. E.g.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Config example
|
||||||
|
websites:
|
||||||
|
- unique-name: "test.io"
|
||||||
|
fqdns: ["test.de", "test.org", "www.test.de", "www.test.org"]
|
||||||
|
- unique-name: "example.io"
|
||||||
|
fqdns: ["example.org", "www.example.com"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### https & Letsencrypt Certificates
|
||||||
|
|
||||||
|
The domain names listed will get their certificates from letsencrypt out of the box.
|
||||||
|
|
||||||
|
### Ratelimiting
|
||||||
|
|
||||||
|
There is a Ratelimit included for each website. This makes it harder to DOS one or all websites served.
|
||||||
|
|
||||||
|
### Monitoring
|
||||||
|
|
||||||
|
Monitoring on GrafanaCloud (or any other grafana) is included out of the box.
|
||||||
|
|
||||||
|
### GitOps your Websites
|
||||||
|
|
||||||
|
If your repository is on a frogejo or gitea repo, we included GitOps. We ask every ten minutes the repo api for new pushed content.
|
||||||
|
|
||||||
|
If there is new content we generate the new static html & serve it.
|
||||||
|
|
||||||
|
### Support Hugo and Cryogene
|
||||||
|
|
||||||
|
For static html generation we support cryogen & hugo.
|
||||||
|
|
||||||
## Try out
|
## Try out
|
||||||
|
|
||||||
|
@ -34,48 +73,18 @@ Your input will stay in your browser. No server interaction is required.
|
||||||
|
|
||||||
You will also be able to try out on cli:
|
You will also be able to try out on cli:
|
||||||
```
|
```
|
||||||
target/graalvm/c4k-website src/test/resources/website-test/valid-config.yaml src/test/resources/website-test/valid-auth.yaml | kubeval -
|
c4k-website src/test/resources/valid-config.yaml src/test/resources/valid-auth.yaml
|
||||||
target/graalvm/c4k-website src/test/resources/website-test/valid-config.yaml src/test/resources/website-test/valid-auth.yaml | kubectl apply -f -
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
You need:
|
Prerequisites:
|
||||||
|
* DNS routes pointing to your k8s cluster.
|
||||||
|
* frogejo or gitea instance for your website repo. In doubt use https://codeberg.org
|
||||||
|
* A git repository with your hugo / cryogene website
|
||||||
|
* the project provides a `generate.sh` (maybe your generatoin needs some preprocessing)
|
||||||
|
* `generate.sh` deliver its static generated html to `target/html`
|
||||||
|
|
||||||
* DNS routes matching the fqdns in the lists
|
|
||||||
* cryogen as a static site generator
|
|
||||||
* a cryogen project ready to build
|
|
||||||
* a gitea account which holds the buildable project
|
|
||||||
* an authorization token for that account
|
|
||||||
* and a kubernetes cluster provisioned by [provs]
|
|
||||||
|
|
||||||
Add a unique identifier for each website to config.edn and auth.edn (e.g. domain-name).
|
|
||||||
Add the list of fqdns, your gitea host, name of the website repo and the respective branch name (usually "main") to config.edn.
|
|
||||||
Add auth token and gitea user with access to the website repo to auth.edn.
|
|
||||||
Let c4k-website generate your .yaml file.
|
|
||||||
Apply this file on your cluster with `kubectl apply -f yourApp.yaml`.
|
|
||||||
Done.
|
|
||||||
|
|
||||||
### Script Execution
|
|
||||||
|
|
||||||
Optionally you can specify a trusted script in your config.edn.
|
|
||||||
|
|
||||||
1. `sha256sum` "/path/to/your/script/file"
|
|
||||||
2. copy the output of this command
|
|
||||||
3. add the :sha256-output "hash-of-file file.name" :key value pair to the respective collection in :websites.
|
|
||||||
|
|
||||||
Also, see the example in valid-config.edn. The script file needs to exist in the `<branch>.zip` and path specification to the script file should be relative to the root of the unzipped folder. Scripts can be of any type - as long as an according shebang exists in the first line.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sha256sum your-script-file # use output of this call
|
|
||||||
sha256sum scripts/your-script-file # or this
|
|
||||||
sha256sum scripts/foo/bar/your-script-file # or this
|
|
||||||
```
|
|
||||||
|
|
||||||
### resource requests and limits
|
|
||||||
|
|
||||||
You may want to adjust the resource requests and limits of the build and init containers to your specific scenario.
|
|
||||||
|
|
||||||
## Development & mirrors
|
## Development & mirrors
|
||||||
|
|
||||||
|
@ -90,7 +99,7 @@ For more details about our repository model see: https://repo.prod.meissa.de/mei
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright © 2022 meissa GmbH
|
Copyright © 2022, 2023, 2024 meissa GmbH
|
||||||
Licensed under the [Apache License, Version 2.0](LICENSE) (the "License")
|
Licensed under the [Apache License, Version 2.0](LICENSE) (the "License")
|
||||||
Pls. find licenses of our subcomponents [here](doc/SUBCOMPONENT_LICENSE)
|
Pls. find licenses of our subcomponents [here](doc/SUBCOMPONENT_LICENSE)
|
||||||
|
|
||||||
|
|
61
build.py
61
build.py
|
@ -28,8 +28,9 @@ def initialize(project):
|
||||||
"release_organisation": "meissa",
|
"release_organisation": "meissa",
|
||||||
"release_repository_name": name,
|
"release_repository_name": name,
|
||||||
"release_artifacts": [
|
"release_artifacts": [
|
||||||
"target/uberjar/c4k-website-standalone.jar",
|
"target/graalvm/" + name,
|
||||||
"target/frontend-build/c4k-website.js",
|
"target/uberjar/" + name + "-standalone.jar",
|
||||||
|
"target/frontend-build/" + name + ".js"
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ def test_schema(project):
|
||||||
"java -jar target/uberjar/c4k-website-standalone.jar "
|
"java -jar target/uberjar/c4k-website-standalone.jar "
|
||||||
+ "src/test/resources/website-test/valid-config.yaml "
|
+ "src/test/resources/website-test/valid-config.yaml "
|
||||||
+ "src/test/resources/website-test/valid-auth.yaml | "
|
+ "src/test/resources/website-test/valid-auth.yaml | "
|
||||||
+ "kubeconform --kubernetes-version 1.23.0 --strict --skip Certificate -",
|
+ """kubeconform --kubernetes-version 1.23.0 --strict --skip "Certificate,Middleware" -""",
|
||||||
shell=True,
|
shell=True,
|
||||||
check=True,
|
check=True,
|
||||||
)
|
)
|
||||||
|
@ -105,6 +106,60 @@ def package_uberjar(project):
|
||||||
check=True,
|
check=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@task
|
||||||
|
def package_native(project):
|
||||||
|
run(
|
||||||
|
"mkdir -p target/graalvm",
|
||||||
|
shell=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
run(
|
||||||
|
"native-image " +
|
||||||
|
"--native-image-info " +
|
||||||
|
"--report-unsupported-elements-at-runtime " +
|
||||||
|
"--no-server " +
|
||||||
|
"--no-fallback " +
|
||||||
|
"--features=clj_easy.graal_build_time.InitClojureClasses " +
|
||||||
|
"-jar target/uberjar/" + project.name + "-standalone.jar " +
|
||||||
|
"-march=compatibility " +
|
||||||
|
"-H:IncludeResources=.*.yaml " +
|
||||||
|
"-H:IncludeResources=logback.xml " +
|
||||||
|
"-H:Log=registerResource:verbose " +
|
||||||
|
"-H:Name=target/graalvm/" + project.name + "",
|
||||||
|
shell=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
run(
|
||||||
|
"sha256sum target/graalvm/" + project.name + " > target/graalvm/" + project.name + ".sha256",
|
||||||
|
shell=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
run(
|
||||||
|
"sha512sum target/graalvm/" + project.name + " > target/graalvm/" + project.name + ".sha512",
|
||||||
|
shell=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def inst(project):
|
||||||
|
run(
|
||||||
|
"lein uberjar",
|
||||||
|
shell=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
package_native(project)
|
||||||
|
run(
|
||||||
|
"sudo install -m=755 target/uberjar/" + project.name + "-standalone.jar /usr/local/bin/" + project.name + "-standalone.jar",
|
||||||
|
shell=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
run(
|
||||||
|
"sudo install -m=755 target/graalvm/" + project.name + " /usr/local/bin/" + project.name + "",
|
||||||
|
shell=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@task
|
@task
|
||||||
def upload_clj(project):
|
def upload_clj(project):
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
# Release process
|
|
||||||
|
|
||||||
## ... for testing (snapshots)
|
|
||||||
|
|
||||||
Make sure your clojars.org credentials are correctly set in your ~/.lein/profiles.clj file.
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
git add .
|
|
||||||
git commit
|
|
||||||
```
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
lein deploy # or lein deploy clojars
|
|
||||||
```
|
|
||||||
|
|
||||||
## ... for stable release patch version
|
|
||||||
|
|
||||||
Make sure tags are protected in gitlab:
|
|
||||||
Repository Settings -> Protected Tags -> set \*.\*.\* as tag and save.
|
|
||||||
|
|
||||||
Make sure all your changes are committed:
|
|
||||||
``` bash
|
|
||||||
git checkout main # for old projects replace main with master
|
|
||||||
git add .
|
|
||||||
git commit
|
|
||||||
```
|
|
||||||
|
|
||||||
Open package.json, find "version" keyword and remove "-SNAPSHOT" from version number.
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
git add .
|
|
||||||
# REPLACE x.x.x with the correct version
|
|
||||||
git commit -m "Release vx.x.x"
|
|
||||||
lein release
|
|
||||||
git push --follow-tags
|
|
||||||
```
|
|
||||||
|
|
||||||
Open package.json again, increase version increment by one and add "-SNAPSHOT".
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
git commit -am "[Skip-CI] version bump"
|
|
||||||
git push
|
|
||||||
```
|
|
||||||
|
|
||||||
## ... for stable release minor version
|
|
||||||
|
|
||||||
Make sure tags are protected in gitlab:
|
|
||||||
Repository Settings -> Protected Tags -> set \*.\*.\* as tag and save.
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
git checkout main # for old projects replace main with master
|
|
||||||
git add .
|
|
||||||
git commit
|
|
||||||
```
|
|
||||||
|
|
||||||
In package.json, find "version" keyword and remove "-SNAPSHOT" from version number.
|
|
||||||
Increment minor version by one, set patch version to zero.
|
|
||||||
|
|
||||||
Open project.clj, find ":version" keyword, increment minor version by one, set patch version to zero.
|
|
||||||
Leave "-SNAPSHOT" be.
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
git add .
|
|
||||||
# REPLACE x.x.x with the correct version
|
|
||||||
git commit -m "Release vx.x.x"
|
|
||||||
lein release
|
|
||||||
git push --follow-tags
|
|
||||||
```
|
|
||||||
|
|
||||||
Open package.json again, increase version increment by one and add "-SNAPSHOT".
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
git commit -am "[Skip-CI] version bump"
|
|
||||||
git push
|
|
||||||
```
|
|
||||||
|
|
||||||
Done.
|
|
|
@ -1,26 +1,81 @@
|
||||||
|
# GitOps for Websites
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
Actor a as Website Author
|
||||||
|
participant j as Job triggerd by Cron
|
||||||
|
participant f as Forgejo Instance
|
||||||
|
participant g as Your Git Repo for Website
|
||||||
|
|
||||||
|
a ->> g: commit & push some new content
|
||||||
|
j ->> f: check repo hash for new commits
|
||||||
|
activate j
|
||||||
|
f ->> g: get lates commit hash
|
||||||
|
f -->> j:
|
||||||
|
j ->> f: download repo
|
||||||
|
j ->> j: generate.sh
|
||||||
|
j ->> j: cp /target/html to website
|
||||||
|
deactivate j
|
||||||
|
```
|
||||||
|
|
||||||
|
# Runtime view
|
||||||
|
|
||||||
|
For the example configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
issuer: "staging"
|
||||||
|
websiteconfigs:
|
||||||
|
- unique-name: "test.io"
|
||||||
|
fqdns: ["test.de", "test.org", "www.test.de", "www.test.org"]
|
||||||
|
forgejo-host: "codeberg.org"
|
||||||
|
repo-name: "repo"
|
||||||
|
branchname: "main"
|
||||||
|
- unique-name: "example.io"
|
||||||
|
fqdns: ["example.org", "www.example.com"]
|
||||||
|
forgejo-host: "fineForgejoHost.net"
|
||||||
|
repo-name: "repo"
|
||||||
|
branchname: "main"
|
||||||
|
mon-cfg:
|
||||||
|
grafana-cloud-url: "url-for-your-prom-remote-write-endpoint"
|
||||||
|
cluster-name: "website"
|
||||||
|
cluster-stage: "test"
|
||||||
|
```
|
||||||
|
|
||||||
|
the website runtime looks like:
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
C4Context
|
C4Context
|
||||||
title c4k-webserver
|
title c4k-webserver
|
||||||
Boundary(website, "website") {
|
Boundary(k8s, "cluster") {
|
||||||
System(website_ing1, "ingress f. host meissa-gmbh.de")
|
Boundary(test_io, "namespace test-io"){
|
||||||
System(website_ing2, "ingress f. host meissa.de")
|
System(website_ingt, "ingress f. test.de")
|
||||||
Boundary(website_pod, "website pod"){
|
Boundary(test_de_srv_t, "webserver") {
|
||||||
Boundary(aaa, "website container") {
|
System(wst, "webserver")
|
||||||
System(ws, "webserver")
|
SystemDb(file_htmlt, "static html")
|
||||||
SystemDb(file_html, "static html")
|
Rel(wst, file_htmlt, "file ro")
|
||||||
Rel(ws, file_html, "file ro")
|
|
||||||
}
|
}
|
||||||
Boundary(aab, "cron build website") {
|
Boundary(aab, "cron generate website") {
|
||||||
System(git_clone, "git clone/pull & lein ring server & copy to static html")
|
System(git_clonet, "git clone/pull & generate.sh & copy to static html")
|
||||||
SystemDb(file_git, "git repo")
|
SystemDb(file_gitt, "git repo for test.io")
|
||||||
Rel(git_clone, file_git, "file rw")
|
Rel(git_clonet, file_gitt, "file rw")
|
||||||
Rel(git_clone, file_html, "file rw")
|
Rel(file_gitt, file_htmlt, "file rw")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rel(website_ing1, ws, "http")
|
Rel(website_ingt, wst, "http")
|
||||||
Rel(website_ing2, ws, "http")
|
Boundary(example_io, "namespace example-io"){
|
||||||
|
System(website_inge, "ingress f. example.org")
|
||||||
|
Boundary(test_de_srv_e, "webserver") {
|
||||||
|
System(wse, "webserver")
|
||||||
|
SystemDb(file_htmle, "static html")
|
||||||
|
Rel(wse, file_htmle, "file ro")
|
||||||
|
}
|
||||||
|
Boundary(aeb, "cron generate website") {
|
||||||
|
System(git_clonee, "git clone/pull & generate.sh & copy to static html")
|
||||||
|
SystemDb(file_gite, "git repo for example.io")
|
||||||
|
Rel(git_clonee, file_gite, "file rw")
|
||||||
|
Rel(file_gite, file_htmle, "file rw")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rel(website_inge, wse, "http")
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
[![](https://mermaid.ink/img/pako:eNqNU8tugzAQ_JWVD1UqJaka5cSxSX-guSIhgxewamxkL01RxL_XQFExSdr6gtee2ccMvrDMCGQRO-wPRhN-UqzBL5KkELL9--aMqUP7gXa8eDGNFty2q_5cEq4hZt_bmD3CZUT169Q6wmrCJVIXzz3Yfy06B_kWSuMIKpTO8U1RpeVW9Dl-y7C7n2FJXjaa1EbMmgUfevys34DEOZ-DM68Nl9qLEM647NRNpFGxeT8h9JiucqkwKalSPccRJ5lBH95kvaEasgekPgBrrgjd3aHSnpZZoyFtpBJw27nFVIWkJFNGD177AIbgqW6UggdQKDVY7wmMQ_ujzNQtkIG_hgql8JmnAhZrc1eGWTtz3ijG-d-0UMRrXjfb_9zMpB0sCX7u0f6SqA6yLYC7BTAs4guwNavQVlwK_y4HW2JGJVbepshvBea8URSzWHce2tSCE74KScayKOfK4Zrxhsyp1RmLyDY4gY6SF5ZX42H3BTITMPU)](https://mermaid.live/edit#pako:eNqNU8tugzAQ_JWVD1UqJaka5cSxSX-guSIhgxewamxkL01RxL_XQFExSdr6gtee2ccMvrDMCGQRO-wPRhN-UqzBL5KkELL9--aMqUP7gXa8eDGNFty2q_5cEq4hZt_bmD3CZUT169Q6wmrCJVIXzz3Yfy06B_kWSuMIKpTO8U1RpeVW9Dl-y7C7n2FJXjaa1EbMmgUfevys34DEOZ-DM68Nl9qLEM647NRNpFGxeT8h9JiucqkwKalSPccRJ5lBH95kvaEasgekPgBrrgjd3aHSnpZZoyFtpBJw27nFVIWkJFNGD177AIbgqW6UggdQKDVY7wmMQ_ujzNQtkIG_hgql8JmnAhZrc1eGWTtz3ijG-d-0UMRrXjfb_9zMpB0sCX7u0f6SqA6yLYC7BTAs4guwNavQVlwK_y4HW2JGJVbepshvBea8URSzWHce2tSCE74KScayKOfK4Zrxhsyp1RmLyDY4gY6SF5ZX42H3BTITMPU)
|
|
|
@ -1,632 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
|
|
||||||
<!--Created by yEd 3.22-->
|
|
||||||
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
|
|
||||||
<key for="port" id="d1" yfiles.type="portgraphics"/>
|
|
||||||
<key for="port" id="d2" yfiles.type="portgeometry"/>
|
|
||||||
<key for="port" id="d3" yfiles.type="portuserdata"/>
|
|
||||||
<key attr.name="url" attr.type="string" for="node" id="d4"/>
|
|
||||||
<key attr.name="description" attr.type="string" for="node" id="d5"/>
|
|
||||||
<key for="node" id="d6" yfiles.type="nodegraphics"/>
|
|
||||||
<key for="graphml" id="d7" yfiles.type="resources"/>
|
|
||||||
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
|
|
||||||
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
|
|
||||||
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
|
|
||||||
<graph edgedefault="directed" id="G">
|
|
||||||
<data key="d0" xml:space="preserve"/>
|
|
||||||
<node id="n0">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="154.25" width="221.25" x="674.8125" y="-212.076171875"/>
|
|
||||||
<y:Fill color="#C0C0C0" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" textColor="#000000" verticalTextPosition="bottom" visible="true" width="36.292236328125" x="4.0" xml:space="preserve" y="4.0">Client</y:NodeLabel>
|
|
||||||
<y:Shape type="roundrectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n1">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="514.0" width="1041.25" x="-97.5625" y="-35.638671875"/>
|
|
||||||
<y:Fill color="#3366FF" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="28.515846252441406" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" textColor="#000000" verticalTextPosition="bottom" visible="true" width="131.1511993408203" x="4.0" xml:space="preserve" y="4.0">Hetzner-Server</y:NodeLabel>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="518.625" y="266.69427546920065">
|
|
||||||
<y:LabelModel>
|
|
||||||
<y:SmartNodeLabelModel distance="4.0"/>
|
|
||||||
</y:LabelModel>
|
|
||||||
<y:ModelParameter>
|
|
||||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.022751508694942912" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
|
||||||
</y:ModelParameter>
|
|
||||||
</y:NodeLabel>
|
|
||||||
<y:Shape type="rectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n2">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="426.5" width="691.75" x="-57.5" y="10.111328125"/>
|
|
||||||
<y:Fill color="#33CCCC" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" textColor="#000000" verticalTextPosition="bottom" visible="true" width="39.61585998535156" x="4.0" xml:space="preserve" y="4.0">Node</y:NodeLabel>
|
|
||||||
<y:Shape type="roundrectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n3">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="85.0" width="93.75" x="290.0" y="60.548828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="86.34767150878906" x="3.7011642456054688" xml:space="preserve" y="30.966041564941406">Webserver 1<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="octagon"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n4">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="98.75" width="78.75" x="128.9375" y="53.673828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="61.10578918457031" x="8.822105407714844" xml:space="preserve" y="37.841041564941406">Ingress1<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="fatarrow2"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n5">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="98.75" width="78.75" x="128.9375" y="182.423828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="61.10578918457031" x="8.822105407714844" xml:space="preserve" y="37.841041564941406">Ingress2<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="fatarrow2"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n6">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="85.0" width="93.75" x="290.0" y="189.298828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="86.34767150878906" x="3.7011642456054688" xml:space="preserve" y="30.966041564941406">Webserver 2<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="octagon"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n7">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="112.5" width="123.75" x="-47.5" y="175.548828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="53.3358154296875" x="35.20709228515625" xml:space="preserve" y="44.716041564941406">Metallb<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="octagon"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n8">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="153.75" width="148.75" x="-1048.8125" y="-1.1875"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="28.515846252441406" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="84.38749694824219" x="32.181251525878906" xml:space="preserve" y="62.6170768737793">pybuilder<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="rectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n9">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="160.0" width="148.75" x="-680.0625" y="266.25"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="28.515846252441406" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.15971374511719" x="48.795143127441406" xml:space="preserve" y="65.7420768737793">provs<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="rectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n10">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="160.0" width="148.75" x="-1048.8125" y="266.25"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="28.515846252441406" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="32.547821044921875" x="58.10108947753906" xml:space="preserve" y="65.7420768737793">c4k<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="rectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n11">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="153.75" width="148.75" x="-680.0625" y="-1.1875"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="28.515846252441406" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="86.96148681640625" x="30.894256591796875" xml:space="preserve" y="62.6170768737793">terraform<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="rectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n12">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="75.0" width="75.0" x="-643.1875" y="-173.138671875"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="16" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.792043685913086" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="37.8880615234375" x="18.55596923828125" xml:space="preserve" y="24.603978157043457">AWS<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="rectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n13">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="75.0" width="75.0" x="-331.90625" y="38.1875"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="16" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.792043685913086" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.69612121582031" x="5.651939392089844" xml:space="preserve" y="24.603978157043457">Hetzner<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="rectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n14">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="75.0" width="141.25" x="714.8125" y="-172.451171875"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="61.432403564453125" x="39.90879821777344" xml:space="preserve" y="27.327942848205566">local build<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="roundrectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n15">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="63.75" width="118.75" x="456.5" y="71.173828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="47.52583312988281" x="35.612083435058594" xml:space="preserve" y="20.341041564941406">Mount<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="111.3167724609375" x="4.0" xml:space="preserve" y="39.40588569641113">Holds website data
|
|
||||||
<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="-0.5" labelRatioY="0.5" nodeRatioX="-0.5" nodeRatioY="0.5" offsetX="4.0" offsetY="-4.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="roundrectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n16">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="63.75" width="118.75" x="456.5" y="199.923828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="47.52583312988281" x="35.612083435058594" xml:space="preserve" y="20.341041564941406">Mount<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="111.3167724609375" x="4.0" xml:space="preserve" y="39.40588569641113">Holds website data
|
|
||||||
<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="-0.5" labelRatioY="0.5" nodeRatioX="-0.5" nodeRatioY="0.5" offsetX="4.0" offsetY="-4.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="roundrectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n17">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="98.75" width="78.75" x="128.9375" y="311.173828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="15.255950927734375" x="31.747024536132812" xml:space="preserve" y="37.841041564941406">...<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="fatarrow2"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n18">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="85.0" width="93.75" x="290.0" y="318.048828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="15.255950927734375" x="39.24702453613281" xml:space="preserve" y="30.966041564941406">...<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="octagon"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n19">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="63.75" width="118.75" x="456.5" y="328.673828125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="15.255950927734375" x="51.74702453613281" xml:space="preserve" y="20.341041564941406">...<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="111.3167724609375" x="4.0" xml:space="preserve" y="39.40588569641113">Holds website data
|
|
||||||
<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="-0.5" labelRatioY="0.5" nodeRatioX="-0.5" nodeRatioY="0.5" offsetX="4.0" offsetY="-4.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="roundrectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n20">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="74.375" width="255.5" x="657.6875" y="65.861328125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="250.9450225830078" x="2.2774887084960938" xml:space="preserve" y="25.653541564941406">Folder in /var/www/fqdn-folder-name<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="roundrectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n21">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="74.375" width="255.5" x="657.6875" y="194.611328125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="250.9450225830078" x="2.2774887084960938" xml:space="preserve" y="25.653541564941406">Folder in /var/www/fqdn-folder-name<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="roundrectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<node id="n22">
|
|
||||||
<data key="d6">
|
|
||||||
<y:ShapeNode>
|
|
||||||
<y:Geometry height="74.375" width="255.5" x="657.6875" y="323.361328125"/>
|
|
||||||
<y:Fill color="#FFCC00" transparent="false"/>
|
|
||||||
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
|
|
||||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="23.067916870117188" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="250.9450225830078" x="2.2774887084960938" xml:space="preserve" y="25.653541564941406">Folder in /var/www/fqdn-folder-name<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
|
|
||||||
<y:Shape type="roundrectangle"/>
|
|
||||||
</y:ShapeNode>
|
|
||||||
</data>
|
|
||||||
</node>
|
|
||||||
<edge id="e0" source="n7" target="n7">
|
|
||||||
<data key="d10">
|
|
||||||
<y:ArcEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
|
|
||||||
<y:Point x="14.375" y="231.798828125"/>
|
|
||||||
</y:Path>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:Arc height="0.0" ratio="1.0" type="fixedRatio"/>
|
|
||||||
</y:ArcEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e1" source="n7" target="n4">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e2" source="n7" target="n5">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e3" source="n4" target="n2">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e4" source="n8" target="n11">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="39.41203308105469" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="85.26309204101562" x="67.36845397949219" xml:space="preserve" y="10.293983459472656">out_conf.edn
|
|
||||||
out_auth.edn<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e5" source="n11" target="n9">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="39.41203308105469" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="40.27003479003906" x="8.364982604980469" xml:space="preserve" y="31.418983459472656">IP
|
|
||||||
FQDN<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e6" source="n11" target="n12">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
|
|
||||||
<y:Point x="-625.0275" y="-58.35633333333334"/>
|
|
||||||
</y:Path>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="21.706016540527344" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.841064453125" x="-76.92666845703047" xml:space="preserve" y="-69.5675916035971">DNS Entry<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e7" source="n11" target="n13">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
|
|
||||||
<y:Point x="-441.69499999999994" y="98.875"/>
|
|
||||||
</y:Path>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="39.41203308105469" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="68.63603210449219" x="65.34923394775524" xml:space="preserve" y="18.702248697916332">ssh keys
|
|
||||||
server size<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e8" source="n13" target="n1">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="57.11804962158203" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="108.4290771484375" x="11.446461425783014" xml:space="preserve" y="19.35144684855112">spin up server
|
|
||||||
of requested size
|
|
||||||
with ssh keys<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e9" source="n9" target="n1">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e10" source="n9" target="n1">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e11" source="n9" target="n1">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="39.41203308105469" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="95.46807861328125" x="124.88346069335978" xml:space="preserve" y="-5.053327657063903">k3s and
|
|
||||||
c4k application<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e12" source="n9" target="n10">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
|
|
||||||
<y:Point x="-787.3125" y="291.125"/>
|
|
||||||
</y:Path>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="39.41203308105469" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="85.26309204101562" x="-102.75654602050781" xml:space="preserve" y="-76.6949691772461">out_conf.edn
|
|
||||||
out_auth.edn<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e13" source="n10" target="n9">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
|
|
||||||
<y:Point x="-793.8125" y="404.125"/>
|
|
||||||
</y:Path>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="21.706016540527344" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="132.40110778808594" x="18.766946105956777" xml:space="preserve" y="44.647786814371784">application yaml files<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e14" source="n4" target="n3">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e15" source="n5" target="n6">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e16" source="n6" target="n2">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e17" source="n17" target="n18">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e18" source="n15" target="n3">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e19" source="n20" target="n15">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e20" source="n16" target="n6">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e21" source="n19" target="n18">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e22" source="n4" target="n2">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e23" source="n2" target="n1">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e24" source="n7" target="n17">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e25" source="n6" target="n2">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e26" source="n22" target="n19">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e27" source="n21" target="n16">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e28" source="n14" target="n20">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="36.688228607177734" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="76.39651489257812" x="4.9553675537108575" xml:space="preserve" y="75.47775874328613">copy to
|
|
||||||
via scp/rsync<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e29" source="n13" target="n11">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
|
|
||||||
<y:Point x="-438.44499999999994" y="62.251666666666665"/>
|
|
||||||
</y:Path>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="39.41203308105469" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="30.31201171875" x="-116.9447558593746" xml:space="preserve" y="-49.27187929280607">IPv4
|
|
||||||
IPv6<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
<edge id="e30" source="n12" target="n11">
|
|
||||||
<data key="d10">
|
|
||||||
<y:PolyLineEdge>
|
|
||||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
|
|
||||||
<y:Point x="-588.3494999999999" y="-62.498333333333335"/>
|
|
||||||
</y:Path>
|
|
||||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
|
||||||
<y:Arrows source="none" target="standard"/>
|
|
||||||
<y:EdgeLabel alignment="left" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="21.706016540527344" horizontalTextPosition="center" iconTextGap="4" modelName="free" modelPosition="anywhere" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="54.99903869628906" x="13.953326354981414" xml:space="preserve" y="25.047580271402865">ssh keys<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
|
|
||||||
<y:BendStyle smoothed="false"/>
|
|
||||||
</y:PolyLineEdge>
|
|
||||||
</data>
|
|
||||||
</edge>
|
|
||||||
</graph>
|
|
||||||
<data key="d7">
|
|
||||||
<y:Resources/>
|
|
||||||
</data>
|
|
||||||
</graphml>
|
|
Binary file not shown.
Before Width: | Height: | Size: 104 KiB |
Binary file not shown.
Before Width: | Height: | Size: 70 KiB |
|
@ -1,4 +1,4 @@
|
||||||
Aktoren
|
# Aktoren
|
||||||
|
|
||||||
## A1: Der Website-Konsument
|
## A1: Der Website-Konsument
|
||||||
## A2: Der Website-Pfleger
|
## A2: Der Website-Pfleger
|
||||||
|
|
|
@ -7,7 +7,7 @@ import logging
|
||||||
name = 'c4k-website'
|
name = 'c4k-website'
|
||||||
MODULE = 'build'
|
MODULE = 'build'
|
||||||
PROJECT_ROOT_PATH = '../..'
|
PROJECT_ROOT_PATH = '../..'
|
||||||
version = "1.1.7"
|
version = "2.0.4-dev"
|
||||||
|
|
||||||
|
|
||||||
@init
|
@init
|
||||||
|
|
|
@ -3,9 +3,12 @@ FROM clojure:lein
|
||||||
# Prepare Entrypoint Script
|
# Prepare Entrypoint Script
|
||||||
ADD resources /tmp
|
ADD resources /tmp
|
||||||
|
|
||||||
|
ENV HUGO_VERSION="0.125.5"
|
||||||
|
ENV GO_VERSION="1.19.13"
|
||||||
ENV BUILDDIR="/etc/website"
|
ENV BUILDDIR="/etc/website"
|
||||||
ENV SOURCEDIR="/etc/websitesource"
|
ENV SOURCEDIR="/etc/websitesource"
|
||||||
ENV WEBSITEROOT="/var/www/html/website/"
|
ENV WEBSITEROOT="/var/www/html/website/"
|
||||||
ENV HASHFILEDIR="/var/hashfile.d"
|
ENV HASHFILEDIR="/var/hashfile.d"
|
||||||
|
ENV PATH="${PATH}:/usr/local/go/bin"
|
||||||
|
|
||||||
RUN /tmp/install.sh
|
RUN /tmp/install.sh
|
||||||
|
|
|
@ -20,17 +20,13 @@ if [[ $currentHash == $newHash ]]
|
||||||
echo "Nothing to do"
|
echo "Nothing to do"
|
||||||
else
|
else
|
||||||
echo $currentHash > $HASHFILEDIR/$hashfilename
|
echo $currentHash > $HASHFILEDIR/$hashfilename
|
||||||
|
echo "Generate .netrc file"
|
||||||
|
generate-netrc-file
|
||||||
echo "Downloading website data"
|
echo "Downloading website data"
|
||||||
get-website-data $filename
|
get-website-data $filename
|
||||||
unzip-website-data $filename
|
unzip-website-data $filename
|
||||||
echo "Executing Custom Scripts, if applicable"
|
|
||||||
execute-scripts-when-existing
|
|
||||||
echo "Building website"
|
echo "Building website"
|
||||||
build-website
|
build-website
|
||||||
echo "Moving files"
|
echo "Moving files"
|
||||||
move-website-files-to-target
|
move-website-files-to-target
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
function generate-netrc-file() {
|
||||||
|
echo "machine $GITHOST password $AUTHTOKEN" > ~/.netrc
|
||||||
|
}
|
||||||
|
|
||||||
function get-website-data() {
|
function get-website-data() {
|
||||||
curl -H "Authorization: token $AUTHTOKEN" -o $SOURCEDIR/$1 $GITREPOURL
|
curl -H "Authorization: token $AUTHTOKEN" -o $SOURCEDIR/$1 $GITREPOURL
|
||||||
}
|
}
|
||||||
|
@ -16,30 +20,50 @@ function unzip-website-data() {
|
||||||
unzip $SOURCEDIR/$1 -d $BUILDDIR
|
unzip $SOURCEDIR/$1 -d $BUILDDIR
|
||||||
}
|
}
|
||||||
|
|
||||||
function execute-scripts-when-existing() {
|
|
||||||
websitedir=$(ls $BUILDDIR)
|
|
||||||
if [[ -f $BUILDDIR/$websitedir/$SCRIPTFILE ]]
|
|
||||||
then
|
|
||||||
checksum="$(sha256sum $BUILDDIR/$websitedir/$SCRIPTFILE | grep -oE "^[a-z0-9]+")"
|
|
||||||
if [[ "$SHA256SUM" == "$checksum" ]]
|
|
||||||
then
|
|
||||||
chmod +x $BUILDDIR/$websitedir/$SCRIPTFILE
|
|
||||||
(cd $BUILDDIR; dir=$(ls); cd $dir; ./$SCRIPTFILE) #make sure paths defined in scriptfile are relative to $dir
|
|
||||||
else
|
|
||||||
printf "Provided SHA256 Sum does not match calculated sum. Exiting."
|
|
||||||
printf "Calculated SHA256: $checksum"
|
|
||||||
printf "Given SHA256: $SHA256SUM"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
printf "No script file provided."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function build-website() {
|
function build-website() {
|
||||||
(cd $BUILDDIR; dir=$(ls); cd $dir; lein run;)
|
(cd $BUILDDIR; dir=$(ls); cd $dir; bash generate.sh;)
|
||||||
}
|
}
|
||||||
|
|
||||||
function move-website-files-to-target() {
|
function move-website-files-to-target() {
|
||||||
(cd $BUILDDIR; dir=$(ls); cd $dir; rsync -ru --exclude-from "/etc/exclude.pattern" --delete resources/public/* $WEBSITEROOT;)
|
(cd $BUILDDIR; dir=$(ls); cd $dir; rsync -ru --exclude-from "/etc/exclude.pattern" --delete target/html/* $WEBSITEROOT;)
|
||||||
|
}
|
||||||
|
|
||||||
|
function install-hugo-from-deb() {
|
||||||
|
curl -L "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb" -o hugo_extended_${HUGO_VERSION}_linux-amd64.deb
|
||||||
|
curl -L "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_checksums.txt" -o checksums.txt
|
||||||
|
EXPECTED_CHECKSUM="$(sha256sum hugo_extended_${HUGO_VERSION}_linux-amd64.deb)"
|
||||||
|
ACTUAL_CHECKSUM="$(grep hugo_extended_${HUGO_VERSION}_linux-amd64.deb checksums.txt)"
|
||||||
|
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
|
||||||
|
then
|
||||||
|
>&2 echo 'ERROR: Invalid installer checksum'
|
||||||
|
rm hugo.deb
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Installing hugo"
|
||||||
|
echo
|
||||||
|
dpkg -i hugo_extended_${HUGO_VERSION}_linux-amd64.deb
|
||||||
|
|
||||||
|
echo "Clean up"
|
||||||
|
rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb
|
||||||
|
rm checksums.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
function install-go-from-tar() {
|
||||||
|
curl -L "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -o go_linux-amd64.tar.gz
|
||||||
|
EXPECTED_CHECKSUM="4643d4c29c55f53fa0349367d7f1bb5ca554ea6ef528c146825b0f8464e2e668 go_linux-amd64.tar.gz"
|
||||||
|
ACTUAL_CHECKSUM="$(sha256sum go_linux-amd64.tar.gz)"
|
||||||
|
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
|
||||||
|
then
|
||||||
|
>&2 echo 'ERROR: Invalid installer checksum'
|
||||||
|
rm go_linux-amd64.tar.gz
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Installing go"
|
||||||
|
echo
|
||||||
|
tar -C /usr/local -xzf go_linux-amd64.tar.gz
|
||||||
|
|
||||||
|
echo "Clean up"
|
||||||
|
rm go_linux-amd64.tar.gz
|
||||||
}
|
}
|
|
@ -6,7 +6,9 @@ function main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
upgradeSystem
|
upgradeSystem
|
||||||
apt-get install -qqy unzip rsync jq imagemagick curl
|
apt-get install -qqy unzip rsync jq imagemagick curl git
|
||||||
|
install-hugo-from-deb
|
||||||
|
install-go-from-tar
|
||||||
|
|
||||||
install -d /etc/lein/
|
install -d /etc/lein/
|
||||||
install -m 0700 /tmp/entrypoint.sh /
|
install -m 0700 /tmp/entrypoint.sh /
|
||||||
|
@ -22,4 +24,5 @@ function main()
|
||||||
}
|
}
|
||||||
|
|
||||||
source /tmp/install_functions_debian.sh
|
source /tmp/install_functions_debian.sh
|
||||||
|
source /tmp/functions.sh
|
||||||
DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main
|
DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "c4k-website",
|
"name": "c4k-website",
|
||||||
"description": "Generate c4k yaml for a website deployment.",
|
"description": "Generate c4k yaml for a website deployment.",
|
||||||
"author": "meissa GmbH",
|
"author": "meissa GmbH",
|
||||||
"version": "1.1.7",
|
"version": "2.0.4-SNAPSHOT",
|
||||||
"homepage": "https://gitlab.com/domaindrivenarchitecture/c4k-website#readme",
|
"homepage": "https://gitlab.com/domaindrivenarchitecture/c4k-website#readme",
|
||||||
"repository": "https://www.npmjs.com/package/c4k-website",
|
"repository": "https://www.npmjs.com/package/c4k-website",
|
||||||
"license": "APACHE2",
|
"license": "APACHE2",
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
"js-yaml": "^4.0.0"
|
"js-yaml": "^4.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"shadow-cljs": "^2.11.18",
|
"shadow-cljs": "^2.27.4",
|
||||||
"source-map-support": "^0.5.21"
|
"source-map-support": "^0.5.21"
|
||||||
}
|
}
|
||||||
}
|
}
|
28
project.clj
28
project.clj
|
@ -1,11 +1,11 @@
|
||||||
(defproject org.domaindrivenarchitecture/c4k-website "1.1.7"
|
(defproject org.domaindrivenarchitecture/c4k-website "2.0.4-SNAPSHOT"
|
||||||
:description "website c4k-installation package"
|
:description "website c4k-installation package"
|
||||||
:url "https://domaindrivenarchitecture.org"
|
:url "https://domaindrivenarchitecture.org"
|
||||||
:license {:name "Apache License, Version 2.0"
|
:license {:name "Apache License, Version 2.0"
|
||||||
:url "https://www.apache.org/licenses/LICENSE-2.0.html"}
|
:url "https://www.apache.org/licenses/LICENSE-2.0.html"}
|
||||||
:dependencies [[org.clojure/clojure "1.11.1"]
|
:dependencies [[org.clojure/clojure "1.11.3"]
|
||||||
[org.clojure/tools.reader "1.3.7"]
|
[org.clojure/tools.reader "1.4.2"]
|
||||||
[org.domaindrivenarchitecture/c4k-common-clj "6.1.0"]
|
[org.domaindrivenarchitecture/c4k-common-clj "6.2.3"]
|
||||||
[hickory "0.7.1" :exclusions [viebel/codox-klipse-theme]]]
|
[hickory "0.7.1" :exclusions [viebel/codox-klipse-theme]]]
|
||||||
:target-path "target/%s/"
|
:target-path "target/%s/"
|
||||||
:source-paths ["src/main/cljc"
|
:source-paths ["src/main/cljc"
|
||||||
|
@ -22,25 +22,15 @@
|
||||||
:uberjar {:aot :all
|
:uberjar {:aot :all
|
||||||
:main dda.c4k-website.uberjar
|
:main dda.c4k-website.uberjar
|
||||||
:uberjar-name "c4k-website-standalone.jar"
|
:uberjar-name "c4k-website-standalone.jar"
|
||||||
:dependencies [[org.clojure/tools.cli "1.0.219"]
|
:dependencies [[org.clojure/tools.cli "1.1.230"]
|
||||||
[ch.qos.logback/logback-classic "1.4.14"
|
[ch.qos.logback/logback-classic "1.5.6"
|
||||||
:exclusions [com.sun.mail/javax.mail]]
|
:exclusions [com.sun.mail/javax.mail]]
|
||||||
[org.slf4j/jcl-over-slf4j "2.0.9"]]}}
|
[org.slf4j/jcl-over-slf4j "2.0.13"]
|
||||||
|
[com.github.clj-easy/graal-build-time "1.0.5"]]}}
|
||||||
:release-tasks [["test"]
|
:release-tasks [["test"]
|
||||||
["vcs" "assert-committed"]
|
["vcs" "assert-committed"]
|
||||||
["change" "version" "leiningen.release/bump-version" "release"]
|
["change" "version" "leiningen.release/bump-version" "release"]
|
||||||
["vcs" "commit"]
|
["vcs" "commit"]
|
||||||
["vcs" "tag" "v" "--no-sign"]
|
["vcs" "tag" "v" "--no-sign"]
|
||||||
["change" "version" "leiningen.release/bump-version"]]
|
["change" "version" "leiningen.release/bump-version"]]
|
||||||
:aliases {"native" ["shell"
|
)
|
||||||
"native-image"
|
|
||||||
"--report-unsupported-elements-at-runtime"
|
|
||||||
"--initialize-at-build-time"
|
|
||||||
"-jar" "target/uberjar/c4k-website-standalone.jar"
|
|
||||||
"-H:ResourceConfigurationFiles=graalvm-resource-config.json"
|
|
||||||
"-H:Log=registerResource"
|
|
||||||
"-H:Name=target/graalvm/${:name}"]
|
|
||||||
"inst" ["shell"
|
|
||||||
"sh"
|
|
||||||
"-c"
|
|
||||||
"lein uberjar && sudo install -m=755 target/uberjar/c4k-website-standalone.jar /usr/local/bin/c4k-website-standalone.jar"]})
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"src/test/cljc"
|
"src/test/cljc"
|
||||||
"src/test/cljs"
|
"src/test/cljs"
|
||||||
"src/test/resources"]
|
"src/test/resources"]
|
||||||
:dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "6.1.0"]
|
:dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "6.2.3"]
|
||||||
[hickory "0.7.1"]]
|
[hickory "0.7.1"]]
|
||||||
:builds {:frontend {:target :browser
|
:builds {:frontend {:target :browser
|
||||||
:modules {:main {:init-fn dda.c4k-website.browser/init}}
|
:modules {:main {:init-fn dda.c4k-website.browser/init}}
|
||||||
|
|
|
@ -7,71 +7,143 @@
|
||||||
[dda.c4k-common.common :as cm]
|
[dda.c4k-common.common :as cm]
|
||||||
[dda.c4k-common.predicate :as cp]
|
[dda.c4k-common.predicate :as cp]
|
||||||
[dda.c4k-common.monitoring :as mon]
|
[dda.c4k-common.monitoring :as mon]
|
||||||
[dda.c4k-website.website :as website]))
|
[dda.c4k-common.namespace :as ns]
|
||||||
|
[dda.c4k-common.ingress :as ing]
|
||||||
(def config-defaults {:issuer "staging"
|
[dda.c4k-website.website :as web]))
|
||||||
:volume-size "3"})
|
|
||||||
|
|
||||||
(s/def ::mon-cfg ::mon/mon-cfg)
|
(s/def ::mon-cfg ::mon/mon-cfg)
|
||||||
(s/def ::mon-auth ::mon/mon-auth)
|
(s/def ::mon-auth ::mon/mon-auth)
|
||||||
|
(s/def ::unique-name ::web/unique-name)
|
||||||
|
(s/def ::issuer ::web/issuer)
|
||||||
|
(s/def ::volume-size ::web/volume-size)
|
||||||
|
(s/def ::average-rate ::ing/average-rate)
|
||||||
|
(s/def ::burst-rate ::ing/burst-rate)
|
||||||
|
|
||||||
(def config? (s/keys :req-un [::website/websites]
|
(s/def ::authtoken ::web/authtoken)
|
||||||
:opt-un [::website/issuer
|
(s/def ::fqdns ::web/fqdns)
|
||||||
::website/volume-size
|
(s/def ::forgejo-host ::web/forgejo-host)
|
||||||
::mon-cfg]))
|
(s/def ::repo-owner ::web/repo-owner)
|
||||||
|
(s/def ::repo-name ::web/repo-name)
|
||||||
|
(s/def ::branchname ::web/branchname)
|
||||||
|
(s/def ::build-cpu-request ::web/build-cpu-request)
|
||||||
|
(s/def ::build-memory-request ::web/build-memory-request)
|
||||||
|
(s/def ::build-cpu-limit ::web/build-cpu-limit)
|
||||||
|
(s/def ::build-memory-limit ::web/build-memory-limit)
|
||||||
|
(s/def ::redirects ::web/redirects)
|
||||||
|
|
||||||
(def auth? (s/keys :req-un [::website/auth]
|
(def websiteconfig? (s/keys :req-un [::unique-name
|
||||||
|
::fqdns
|
||||||
|
::forgejo-host
|
||||||
|
::repo-owner
|
||||||
|
::repo-name
|
||||||
|
::branchname]
|
||||||
|
:opt-un [::issuer
|
||||||
|
::volume-size
|
||||||
|
::build-cpu-request
|
||||||
|
::build-cpu-limit
|
||||||
|
::build-memory-request
|
||||||
|
::build-memory-limit
|
||||||
|
::redirects]))
|
||||||
|
(def websiteauth? web/websiteauth?)
|
||||||
|
(def websiteauths? (s/keys :req-un [::websiteauths]))
|
||||||
|
|
||||||
|
(s/def ::websiteconfigs (s/coll-of websiteconfig?))
|
||||||
|
(s/def ::websiteauths (s/coll-of websiteauth?))
|
||||||
|
|
||||||
|
(def config? (s/keys :req-un [::websiteconfigs]
|
||||||
|
:opt-un [::issuer
|
||||||
|
::volume-size
|
||||||
|
::mon-cfg
|
||||||
|
::average-rate
|
||||||
|
::burst-rate]))
|
||||||
|
|
||||||
|
(def auth? (s/keys :req-un [::websiteauths]
|
||||||
:opt-un [::mon-auth]))
|
:opt-un [::mon-auth]))
|
||||||
|
|
||||||
(defn-spec sort-config cp/map-or-seq?
|
(def config-defaults {:issuer "staging"})
|
||||||
|
|
||||||
|
|
||||||
|
(def website-config-defaults {:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:redirects []
|
||||||
|
:average-rate 20
|
||||||
|
:burst-rate 40})
|
||||||
|
|
||||||
|
(defn-spec sort-config map?
|
||||||
[unsorted-config config?]
|
[unsorted-config config?]
|
||||||
(let [sorted-websites (into [] (sort-by :unique-name (unsorted-config :websites)))]
|
(let [sorted-websiteconfigs (into [] (sort-by :unique-name (unsorted-config :websiteconfigs)))]
|
||||||
(-> unsorted-config
|
(-> unsorted-config
|
||||||
(assoc-in [:websites] sorted-websites))))
|
(assoc-in [:websiteconfigs] sorted-websiteconfigs))))
|
||||||
|
|
||||||
(defn-spec sort-auth cp/map-or-seq?
|
(defn-spec sort-auth map?
|
||||||
[unsorted-auth auth?]
|
[unsorted-auth auth?]
|
||||||
(let [sorted-auth (into [] (sort-by :unique-name (unsorted-auth :auth)))]
|
(let [sorted-auth (into [] (sort-by :unique-name (unsorted-auth :websiteauths)))]
|
||||||
(-> unsorted-auth
|
(-> unsorted-auth
|
||||||
(assoc-in [:auth] sorted-auth))))
|
(assoc-in [:websiteauths] sorted-auth))))
|
||||||
|
|
||||||
(defn-spec flatten-and-reduce-config cp/map-or-seq?
|
(defn-spec flatten-and-reduce-config map?
|
||||||
[config config?]
|
[config config?]
|
||||||
(let
|
(let
|
||||||
[first-entry (first (:websites config))]
|
[first-entry (first (:websiteconfigs config))]
|
||||||
(conj first-entry
|
(conj first-entry
|
||||||
(when (contains? config :issuer)
|
(when (contains? config :issuer)
|
||||||
{:issuer (config :issuer)})
|
{:issuer (config :issuer)})
|
||||||
(when (contains? config :volume-size)
|
(when (contains? config :volume-size)
|
||||||
{:volume-size (config :volume-size)}))))
|
{:volume-size (config :volume-size)})
|
||||||
|
(when (contains? config :average-rate)
|
||||||
|
{:average-rate (config :average-rate)})
|
||||||
|
(when (contains? config :burst-rate)
|
||||||
|
{:burst-rate (config :burst-rate)}))))
|
||||||
|
|
||||||
(defn-spec flatten-and-reduce-auth cp/map-or-seq?
|
(defn-spec flatten-and-reduce-auth map?
|
||||||
[auth auth?]
|
[auth auth?]
|
||||||
(-> auth :auth first))
|
(-> auth :websiteauths first))
|
||||||
|
|
||||||
(defn generate-configs [config auth]
|
(defn-spec generate-ingress seq?
|
||||||
(loop [config (sort-config config)
|
[config websiteconfig?]
|
||||||
auth (sort-auth auth)
|
(let [name (web/replace-dots-by-minus (:unique-name config))
|
||||||
|
final-config (merge website-config-defaults
|
||||||
|
{:service-name name
|
||||||
|
:service-port 80
|
||||||
|
:namespace name}
|
||||||
|
config)]
|
||||||
|
(ing/generate-simple-ingress final-config)))
|
||||||
|
|
||||||
|
(defn-spec generate seq?
|
||||||
|
[config config?
|
||||||
|
auth auth?]
|
||||||
|
(loop [sorted-config (sort-config config)
|
||||||
|
sorted-auth (sort-auth auth)
|
||||||
result []]
|
result []]
|
||||||
|
|
||||||
(if (and (empty? (config :websites)) (empty? (auth :auth)))
|
(if (and (empty? (sorted-config :websiteconfigs)) (empty? (sorted-auth :websiteauths)))
|
||||||
result
|
result
|
||||||
(recur (->
|
(recur (->
|
||||||
config
|
sorted-config
|
||||||
(assoc-in [:websites] (rest (config :websites))))
|
(assoc-in [:websiteconfigs] (rest (sorted-config :websiteconfigs))))
|
||||||
(->
|
(->
|
||||||
auth
|
sorted-auth
|
||||||
(assoc-in [:auth] (rest (auth :auth))))
|
(assoc-in [:websiteauths] (rest (sorted-auth :websiteauths))))
|
||||||
(conj result
|
(let [curr-flat-websiteconfig
|
||||||
(website/generate-nginx-deployment (flatten-and-reduce-config config))
|
(merge
|
||||||
(website/generate-nginx-configmap (flatten-and-reduce-config config))
|
website-config-defaults
|
||||||
(website/generate-nginx-service (flatten-and-reduce-config config))
|
(flatten-and-reduce-config sorted-config))
|
||||||
(website/generate-website-content-volume (flatten-and-reduce-config config))
|
name (web/replace-dots-by-minus (:unique-name curr-flat-websiteconfig))]
|
||||||
(website/generate-hashfile-volume (flatten-and-reduce-config config))
|
(cm/concat-vec
|
||||||
(website/generate-website-ingress (flatten-and-reduce-config config))
|
result
|
||||||
(website/generate-website-certificate (flatten-and-reduce-config config))
|
(ns/generate (merge {:namespace name} curr-flat-websiteconfig))
|
||||||
(website/generate-website-build-cron (flatten-and-reduce-config config))
|
[(web/generate-nginx-deployment curr-flat-websiteconfig)
|
||||||
(website/generate-website-build-secret (flatten-and-reduce-config config) (flatten-and-reduce-auth auth)))))))
|
(web/generate-nginx-configmap curr-flat-websiteconfig)
|
||||||
|
(web/generate-nginx-service curr-flat-websiteconfig)
|
||||||
|
(web/generate-content-pvc curr-flat-websiteconfig)
|
||||||
|
(web/generate-hash-state-pvc curr-flat-websiteconfig)
|
||||||
|
(web/generate-build-cron curr-flat-websiteconfig)
|
||||||
|
(web/generate-build-configmap curr-flat-websiteconfig)
|
||||||
|
(web/generate-build-secret (flatten-and-reduce-auth sorted-auth))]
|
||||||
|
(generate-ingress curr-flat-websiteconfig)))))))
|
||||||
|
|
||||||
(defn-spec k8s-objects cp/map-or-seq?
|
(defn-spec k8s-objects cp/map-or-seq?
|
||||||
[config config?
|
[config config?
|
||||||
|
@ -81,6 +153,6 @@
|
||||||
(filter
|
(filter
|
||||||
#(not (nil? %))
|
#(not (nil? %))
|
||||||
(cm/concat-vec
|
(cm/concat-vec
|
||||||
(generate-configs config auth)
|
(generate config auth)
|
||||||
(when (:contains? config :mon-cfg)
|
(when (:contains? config :mon-cfg)
|
||||||
(mon/generate (:mon-cfg config) (:mon-auth auth))))))))
|
(mon/generate (:mon-cfg config) (:mon-auth auth))))))))
|
||||||
|
|
|
@ -1,109 +1,73 @@
|
||||||
(ns dda.c4k-website.website
|
(ns dda.c4k-website.website
|
||||||
(:require
|
(:require
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
#?(:cljs [shadow.resource :as rc])
|
[clojure.string :as str]
|
||||||
#?(:clj [orchestra.core :refer [defn-spec]]
|
#?(:clj [orchestra.core :refer [defn-spec]]
|
||||||
:cljs [orchestra.core :refer-macros [defn-spec]])
|
:cljs [orchestra.core :refer-macros [defn-spec]])
|
||||||
#?(:clj [clojure.edn :as edn]
|
#?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])
|
||||||
:cljs [cljs.reader :as edn])
|
|
||||||
[dda.c4k-common.yaml :as yaml]
|
[dda.c4k-common.yaml :as yaml]
|
||||||
[dda.c4k-common.common :as cm]
|
[dda.c4k-common.common :as cm]
|
||||||
[dda.c4k-common.base64 :as b64]
|
[dda.c4k-common.base64 :as b64]
|
||||||
[dda.c4k-common.predicate :as pred]
|
[dda.c4k-common.predicate :as pred]))
|
||||||
[dda.c4k-common.ingress :as ing]
|
|
||||||
[clojure.string :as str]))
|
|
||||||
|
|
||||||
(defn fqdn-list?
|
(defn fqdn-list?
|
||||||
[input]
|
[input]
|
||||||
(every? true? (map pred/fqdn-string? input)))
|
(every? true? (map pred/fqdn-string? input)))
|
||||||
|
|
||||||
(s/def ::unique-name string?)
|
(s/def ::unique-name string?)
|
||||||
(s/def ::sha256sum-output string?)
|
|
||||||
(s/def ::issuer pred/letsencrypt-issuer?)
|
(s/def ::issuer pred/letsencrypt-issuer?)
|
||||||
(s/def ::volume-size pred/integer-string?)
|
(s/def ::volume-size pred/integer-string?)
|
||||||
(s/def ::authtoken pred/bash-env-string?)
|
(s/def ::authtoken pred/bash-env-string?)
|
||||||
(s/def ::fqdns (s/coll-of pred/fqdn-string?))
|
(s/def ::fqdns (s/coll-of pred/fqdn-string?))
|
||||||
(s/def ::gitea-host pred/fqdn-string?)
|
(s/def ::forgejo-host pred/fqdn-string?)
|
||||||
(s/def ::gitea-repo string?)
|
(s/def ::repo-name string?)
|
||||||
(s/def ::branchname string?)
|
(s/def ::branchname string?)
|
||||||
(s/def ::username string?)
|
(s/def ::repo-owner string?)
|
||||||
(s/def ::build-cpu-request string?)
|
(s/def ::build-cpu-request string?)
|
||||||
(s/def ::build-memory-request string?)
|
(s/def ::build-memory-request string?)
|
||||||
(s/def ::build-cpu-limit string?)
|
(s/def ::build-cpu-limit string?)
|
||||||
(s/def ::build-memory-limit string?)
|
(s/def ::build-memory-limit string?)
|
||||||
|
(s/def ::redirect (s/tuple string? string?))
|
||||||
|
(s/def ::redirects (s/coll-of ::redirect))
|
||||||
|
|
||||||
(def websiteconfig? (s/keys :req-un [::unique-name
|
(def websiteconfig? (s/keys :req-un [::unique-name
|
||||||
::fqdns
|
::fqdns
|
||||||
::gitea-host
|
::forgejo-host
|
||||||
::gitea-repo
|
::repo-owner
|
||||||
::branchname]
|
::repo-name
|
||||||
:opt-un [::issuer
|
::branchname
|
||||||
::volume-size
|
|
||||||
::sha256sum-output
|
|
||||||
::build-cpu-request
|
::build-cpu-request
|
||||||
::build-cpu-limit
|
::build-cpu-limit
|
||||||
::build-memory-request
|
::build-memory-request
|
||||||
::build-memory-limit]))
|
::build-memory-limit
|
||||||
|
::issuer
|
||||||
|
::volume-size
|
||||||
|
::redirects]))
|
||||||
|
|
||||||
(def websiteauth? (s/keys :req-un [::unique-name ::username ::authtoken]))
|
(def websiteauth? (s/keys :req-un [::unique-name ::authtoken]))
|
||||||
|
|
||||||
(s/def ::websites (s/coll-of websiteconfig?))
|
|
||||||
|
|
||||||
(s/def ::auth (s/coll-of websiteauth?))
|
|
||||||
|
|
||||||
(def websites? (s/keys :req-un [::websites]))
|
|
||||||
|
|
||||||
(def auth? (s/keys :req-un [::auth]))
|
|
||||||
|
|
||||||
(defn-spec get-hash-from-sha256sum-output string?
|
|
||||||
[sha256sum-output string?]
|
|
||||||
(if (nil? sha256sum-output)
|
|
||||||
nil
|
|
||||||
(first (str/split sha256sum-output #"\ +"))))
|
|
||||||
|
|
||||||
(defn-spec get-file-name-from-sha256sum-output string?
|
|
||||||
[sha256sum-output string?]
|
|
||||||
(if (nil? sha256sum-output)
|
|
||||||
nil
|
|
||||||
(second (str/split (str/trim sha256sum-output) #"\ +"))))
|
|
||||||
|
|
||||||
(defn-spec replace-dots-by-minus string?
|
(defn-spec replace-dots-by-minus string?
|
||||||
[fqdn pred/fqdn-string?]
|
[fqdn pred/fqdn-string?]
|
||||||
(str/replace fqdn #"\." "-"))
|
(str/replace fqdn #"\." "-"))
|
||||||
|
|
||||||
(defn-spec generate-app-name string?
|
|
||||||
[unique-name pred/fqdn-string?]
|
|
||||||
(str (replace-dots-by-minus unique-name) "-website"))
|
|
||||||
|
|
||||||
(defn-spec generate-service-name string?
|
|
||||||
[unique-name pred/fqdn-string?]
|
|
||||||
(str (replace-dots-by-minus unique-name) "-service"))
|
|
||||||
|
|
||||||
(defn-spec generate-cert-name string?
|
|
||||||
[unique-name pred/fqdn-string?]
|
|
||||||
(str (replace-dots-by-minus unique-name) "-cert"))
|
|
||||||
|
|
||||||
(defn-spec generate-ingress-name string?
|
|
||||||
[unique-name pred/fqdn-string?]
|
|
||||||
(str (replace-dots-by-minus unique-name) "-ingress"))
|
|
||||||
|
|
||||||
; https://your.gitea.host/api/v1/repos/<owner>/<repo>/archive/<branch>.zip
|
; https://your.gitea.host/api/v1/repos/<owner>/<repo>/archive/<branch>.zip
|
||||||
(defn-spec generate-gitrepourl string?
|
(defn-spec generate-gitrepourl string?
|
||||||
[host pred/fqdn-string?
|
[host pred/fqdn-string?
|
||||||
|
owner string?
|
||||||
repo string?
|
repo string?
|
||||||
user string?
|
|
||||||
branch string?]
|
branch string?]
|
||||||
(str "https://" host "/api/v1/repos/" user "/" repo "/archive/" branch ".zip"))
|
(str "https://" host "/api/v1/repos/" owner "/" repo "/archive/" branch ".zip"))
|
||||||
|
|
||||||
; https://your.gitea.host/api/v1/repos/<owner>/<repo>/git/commits/HEAD
|
; https://your.gitea.host/api/v1/repos/<owner>/<repo>/git/commits/HEAD
|
||||||
(defn-spec generate-gitcommiturl string?
|
(defn-spec generate-gitcommiturl string?
|
||||||
[host pred/fqdn-string?
|
[host pred/fqdn-string?
|
||||||
repo string?
|
owner string?
|
||||||
user string?]
|
repo string?]
|
||||||
(str "https://" host "/api/v1/repos/" user "/" repo "/git/" "commits/" "HEAD"))
|
(str "https://" host "/api/v1/repos/" owner "/" repo "/git/" "commits/" "HEAD"))
|
||||||
|
|
||||||
(defn-spec replace-all-matching-substrings-beginning-with pred/map-or-seq?
|
|
||||||
[col pred/map-or-seq?
|
(defn-spec replace-all-matching-prefixes map?
|
||||||
|
[col map?
|
||||||
value-to-partly-match string?
|
value-to-partly-match string?
|
||||||
value-to-inplace string?]
|
value-to-inplace string?]
|
||||||
(clojure.walk/postwalk #(if (and (= (type value-to-partly-match) (type %))
|
(clojure.walk/postwalk #(if (and (= (type value-to-partly-match) (type %))
|
||||||
|
@ -111,114 +75,128 @@
|
||||||
(str/replace % value-to-partly-match value-to-inplace) %)
|
(str/replace % value-to-partly-match value-to-inplace) %)
|
||||||
col))
|
col))
|
||||||
|
|
||||||
(defn-spec replace-common-data pred/map-or-seq?
|
|
||||||
[resource-file string?
|
|
||||||
config websiteconfig?]
|
|
||||||
(let [{:keys [unique-name]} config]
|
|
||||||
(->
|
|
||||||
(yaml/load-as-edn resource-file)
|
|
||||||
(assoc-in [:metadata :labels :app.kubernetes.part-of] (generate-app-name unique-name))
|
|
||||||
(replace-all-matching-substrings-beginning-with "NAME" (replace-dots-by-minus unique-name)))))
|
|
||||||
|
|
||||||
(defn-spec replace-build-data pred/map-or-seq?
|
(defn-spec generate-redirects string?
|
||||||
[resource-file string?
|
[config websiteconfig?
|
||||||
config websiteconfig?]
|
indent (s/or :pos pos-int? :zero zero?)]
|
||||||
(let [{:keys [sha256sum-output build-cpu-request build-cpu-limit build-memory-request build-memory-limit]
|
(let [{:keys [redirects]} config]
|
||||||
:or {build-cpu-request "500m" build-cpu-limit "1700m" build-memory-request "256Mi" build-memory-limit "512Mi"}} config]
|
(str/join
|
||||||
|
(str "\n" (str/join (take indent (repeat " "))))
|
||||||
|
(map
|
||||||
|
#(str "rewrite ^" (first %1) "\\$ " (second %1) " permanent;")
|
||||||
|
redirects))))
|
||||||
|
|
||||||
|
(defn-spec generate-nginx-configmap map?
|
||||||
|
[config websiteconfig?]
|
||||||
|
(let [{:keys [fqdns unique-name]} config
|
||||||
|
name (replace-dots-by-minus unique-name)]
|
||||||
(->
|
(->
|
||||||
(replace-common-data resource-file config)
|
(yaml/load-as-edn "website/nginx-configmap.yaml")
|
||||||
(cm/replace-all-matching-values-by-new-value "CHECK_SUM" (get-hash-from-sha256sum-output sha256sum-output))
|
(replace-all-matching-prefixes "NAME" name)
|
||||||
(cm/replace-all-matching-values-by-new-value "SCRIPT_FILE" (get-file-name-from-sha256sum-output sha256sum-output))
|
(#(assoc-in % [:data :website.conf]
|
||||||
|
(str/replace
|
||||||
|
(-> % :data :website.conf)
|
||||||
|
#"FQDN"
|
||||||
|
(str (str/join " " fqdns) ";"))))
|
||||||
|
(#(assoc-in % [:data :website.conf]
|
||||||
|
(str/replace
|
||||||
|
(-> % :data :website.conf)
|
||||||
|
#"REDIRECTS"
|
||||||
|
(generate-redirects config 2)))))))
|
||||||
|
|
||||||
|
(defn-spec generate-build-configmap pred/map-or-seq?
|
||||||
|
[config websiteconfig?]
|
||||||
|
(let [{:keys [unique-name
|
||||||
|
forgejo-host
|
||||||
|
repo-owner
|
||||||
|
repo-name
|
||||||
|
branchname]} config
|
||||||
|
name (replace-dots-by-minus unique-name)]
|
||||||
|
(->
|
||||||
|
(yaml/load-as-edn "website/build-configmap.yaml")
|
||||||
|
(replace-all-matching-prefixes "NAME" name)
|
||||||
|
(cm/replace-all-matching-values-by-new-value "GITHOST" forgejo-host)
|
||||||
|
(cm/replace-all-matching-values-by-new-value "REPOURL" (generate-gitrepourl
|
||||||
|
forgejo-host
|
||||||
|
repo-owner
|
||||||
|
repo-name
|
||||||
|
branchname))
|
||||||
|
(cm/replace-all-matching-values-by-new-value "COMMITURL" (generate-gitcommiturl
|
||||||
|
forgejo-host
|
||||||
|
repo-owner
|
||||||
|
repo-name)))))
|
||||||
|
|
||||||
|
(defn-spec generate-build-secret pred/map-or-seq?
|
||||||
|
[auth websiteauth?]
|
||||||
|
(let [{:keys [unique-name
|
||||||
|
authtoken]} auth
|
||||||
|
name (replace-dots-by-minus unique-name)]
|
||||||
|
(->
|
||||||
|
(yaml/load-as-edn "website/build-secret.yaml")
|
||||||
|
(replace-all-matching-prefixes "NAME" name)
|
||||||
|
(cm/replace-all-matching-values-by-new-value "TOKEN" (b64/encode authtoken)))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn-spec generate-content-pvc map?
|
||||||
|
[config websiteconfig?]
|
||||||
|
(let [{:keys [unique-name volume-size]} config
|
||||||
|
name (replace-dots-by-minus unique-name)]
|
||||||
|
(->
|
||||||
|
(yaml/load-as-edn "website/content-pvc.yaml")
|
||||||
|
(replace-all-matching-prefixes "NAME" name)
|
||||||
|
(cm/replace-all-matching-values-by-new-value "WEBSITESTORAGESIZE" (str volume-size "Gi")))))
|
||||||
|
|
||||||
|
|
||||||
|
; TODO: Non-Secret-Parts should be config map
|
||||||
|
(defn-spec generate-hash-state-pvc map?
|
||||||
|
[config websiteconfig?]
|
||||||
|
(let [{:keys [unique-name]} config
|
||||||
|
name (replace-dots-by-minus unique-name)]
|
||||||
|
(->
|
||||||
|
(yaml/load-as-edn "website/hash-state-pvc.yaml")
|
||||||
|
(replace-all-matching-prefixes "NAME" name))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn-spec generate-nginx-deployment map?
|
||||||
|
[config websiteconfig?]
|
||||||
|
(let [{:keys [unique-name build-cpu-request build-cpu-limit
|
||||||
|
build-memory-request build-memory-limit]} config
|
||||||
|
name (replace-dots-by-minus unique-name)]
|
||||||
|
(->
|
||||||
|
(yaml/load-as-edn "website/nginx-deployment.yaml")
|
||||||
|
(assoc-in [:metadata :namespace] name)
|
||||||
|
(replace-all-matching-prefixes "NAME" name)
|
||||||
(cm/replace-all-matching-values-by-new-value "BUILD_CPU_REQUEST" build-cpu-request)
|
(cm/replace-all-matching-values-by-new-value "BUILD_CPU_REQUEST" build-cpu-request)
|
||||||
(cm/replace-all-matching-values-by-new-value "BUILD_CPU_LIMIT" build-cpu-limit)
|
(cm/replace-all-matching-values-by-new-value "BUILD_CPU_LIMIT" build-cpu-limit)
|
||||||
(cm/replace-all-matching-values-by-new-value "BUILD_MEMORY_REQUEST" build-memory-request)
|
(cm/replace-all-matching-values-by-new-value "BUILD_MEMORY_REQUEST" build-memory-request)
|
||||||
(cm/replace-all-matching-values-by-new-value "BUILD_MEMORY_LIMIT" build-memory-limit))))
|
(cm/replace-all-matching-values-by-new-value "BUILD_MEMORY_LIMIT" build-memory-limit))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn-spec generate-build-cron map?
|
||||||
|
[config websiteconfig?]
|
||||||
|
(let [{:keys [unique-name build-cpu-request build-cpu-limit build-memory-request
|
||||||
|
build-memory-limit]} config
|
||||||
|
name (replace-dots-by-minus unique-name)]
|
||||||
|
(->
|
||||||
|
(yaml/load-as-edn "website/build-cron.yaml")
|
||||||
|
(replace-all-matching-prefixes "NAME" name)
|
||||||
|
(cm/replace-all-matching-values-by-new-value "BUILD_CPU_REQUEST" build-cpu-request)
|
||||||
|
(cm/replace-all-matching-values-by-new-value "BUILD_CPU_LIMIT" build-cpu-limit)
|
||||||
|
(cm/replace-all-matching-values-by-new-value "BUILD_MEMORY_REQUEST" build-memory-request)
|
||||||
|
(cm/replace-all-matching-values-by-new-value "BUILD_MEMORY_LIMIT" build-memory-limit))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn-spec generate-nginx-service map?
|
||||||
|
[config websiteconfig?]
|
||||||
|
(let [{:keys [unique-name]} config
|
||||||
|
name (replace-dots-by-minus unique-name)]
|
||||||
|
(->
|
||||||
|
(yaml/load-as-edn "website/nginx-service.yaml")
|
||||||
|
(assoc-in [:metadata :namespace] name)
|
||||||
|
(replace-all-matching-prefixes "NAME" name))))
|
||||||
|
|
||||||
|
|
||||||
#?(:cljs
|
#?(:cljs
|
||||||
(defmethod yaml/load-resource :website [resource-name]
|
(defmethod yaml/load-resource :website [resource-name]
|
||||||
(case resource-name
|
(get (inline-resources "website") resource-name)))
|
||||||
"website/nginx-configmap.yaml" (rc/inline "website/nginx-configmap.yaml")
|
|
||||||
"website/nginx-deployment.yaml" (rc/inline "website/nginx-deployment.yaml")
|
|
||||||
"website/nginx-service.yaml" (rc/inline "website/nginx-service.yaml")
|
|
||||||
"website/website-build-cron.yaml" (rc/inline "website/website-build-cron.yaml")
|
|
||||||
"website/website-build-secret.yaml" (rc/inline "website/website-build-secret.yaml")
|
|
||||||
"website/website-content-volume.yaml" (rc/inline "website/website-content-volume.yaml")
|
|
||||||
"website/hashfile-volume.yaml" (rc/inline "website/hashfile-volume.yaml")
|
|
||||||
(throw (js/Error. "Undefined Resource!")))))
|
|
||||||
|
|
||||||
(defn-spec generate-nginx-deployment pred/map-or-seq?
|
|
||||||
[config websiteconfig?]
|
|
||||||
(replace-build-data "website/nginx-deployment.yaml" config))
|
|
||||||
|
|
||||||
(defn-spec generate-nginx-configmap pred/map-or-seq?
|
|
||||||
[config websiteconfig?]
|
|
||||||
(let [{:keys [fqdns]} config]
|
|
||||||
(->
|
|
||||||
(replace-common-data "website/nginx-configmap.yaml" config)
|
|
||||||
(#(assoc-in %
|
|
||||||
[:data :website.conf]
|
|
||||||
(str/replace
|
|
||||||
(-> % :data :website.conf) #"FQDN" (str (str/join " " fqdns) ";")))))))
|
|
||||||
|
|
||||||
(defn-spec generate-nginx-service pred/map-or-seq?
|
|
||||||
[config websiteconfig?]
|
|
||||||
(replace-common-data "website/nginx-service.yaml" config))
|
|
||||||
|
|
||||||
(defn-spec generate-website-content-volume pred/map-or-seq?
|
|
||||||
[config websiteconfig?]
|
|
||||||
(let [{:keys [volume-size]
|
|
||||||
:or {volume-size "3"}} config]
|
|
||||||
(->
|
|
||||||
(replace-common-data "website/website-content-volume.yaml" config)
|
|
||||||
(cm/replace-all-matching-values-by-new-value "WEBSITESTORAGESIZE" (str volume-size "Gi")))))
|
|
||||||
|
|
||||||
(defn-spec generate-hashfile-volume pred/map-or-seq?
|
|
||||||
[config websiteconfig?]
|
|
||||||
(replace-common-data "website/hashfile-volume.yaml" config))
|
|
||||||
|
|
||||||
|
|
||||||
(defn-spec generate-website-ingress pred/map-or-seq?
|
|
||||||
[config websiteconfig?]
|
|
||||||
(let [{:keys [unique-name fqdns]} config]
|
|
||||||
(ing/generate-ingress {:fqdns fqdns
|
|
||||||
:app-name (generate-app-name unique-name)
|
|
||||||
:ingress-name (generate-ingress-name unique-name)
|
|
||||||
:service-name (generate-service-name unique-name)
|
|
||||||
:service-port 80})))
|
|
||||||
|
|
||||||
(defn-spec generate-website-certificate pred/map-or-seq?
|
|
||||||
[config websiteconfig?]
|
|
||||||
(let [{:keys [unique-name issuer fqdns]
|
|
||||||
:or {issuer "staging"}} config]
|
|
||||||
(ing/generate-certificate {:fqdns fqdns
|
|
||||||
:app-name (generate-app-name unique-name)
|
|
||||||
:cert-name (generate-cert-name unique-name)
|
|
||||||
:issuer issuer})))
|
|
||||||
|
|
||||||
(defn-spec generate-website-build-cron pred/map-or-seq?
|
|
||||||
[config websiteconfig?]
|
|
||||||
(replace-build-data "website/website-build-cron.yaml" config))
|
|
||||||
|
|
||||||
(defn-spec generate-website-build-secret pred/map-or-seq?
|
|
||||||
[config websiteconfig?
|
|
||||||
auth websiteauth?]
|
|
||||||
(let [{:keys [gitea-host
|
|
||||||
gitea-repo
|
|
||||||
branchname]} config
|
|
||||||
{:keys [authtoken
|
|
||||||
username]} auth]
|
|
||||||
(->
|
|
||||||
(replace-common-data "website/website-build-secret.yaml" config)
|
|
||||||
(cm/replace-all-matching-values-by-new-value "TOKEN" (b64/encode authtoken))
|
|
||||||
(cm/replace-all-matching-values-by-new-value "REPOURL" (b64/encode
|
|
||||||
(generate-gitrepourl
|
|
||||||
gitea-host
|
|
||||||
gitea-repo
|
|
||||||
username
|
|
||||||
branchname)))
|
|
||||||
(cm/replace-all-matching-values-by-new-value "COMMITURL" (b64/encode
|
|
||||||
(generate-gitcommiturl
|
|
||||||
gitea-host
|
|
||||||
gitea-repo
|
|
||||||
username))))))
|
|
||||||
|
|
||||||
|
|
|
@ -24,18 +24,20 @@
|
||||||
(br/generate-group
|
(br/generate-group
|
||||||
"website-data"
|
"website-data"
|
||||||
(br/generate-text-area
|
(br/generate-text-area
|
||||||
"websites" "Contains fqdns, repo infos, an optional sha256sum-output for script execution for each website:"
|
"websiteconfigs" "Contains fqdns, repo infos, an optional sha256sum-output for script execution for each website:"
|
||||||
"{ :websites
|
"{ :websiteconfigs
|
||||||
[{:unique-name \"test.io\",
|
[{:unique-name \"test.io\",
|
||||||
:fqdns [\"test.de\" \"www.test.de\"],
|
:fqdns [\"test.de\" \"www.test.de\"],
|
||||||
:gitea-host \"githost.de\",
|
:forgejo-host \"githost.de\",
|
||||||
:gitea-repo \"repo\",
|
:repo-owner \"someuser\",
|
||||||
|
:repo-name \"repo\",
|
||||||
:branchname \"main\",
|
:branchname \"main\",
|
||||||
:sha256sum-output \"123456789ab123cd345de script-file-name.sh\"}
|
:sha256sum-output \"123456789ab123cd345de script-file-name.sh\"}
|
||||||
{:unique-name \"example.io \",
|
{:unique-name \"example.io \",
|
||||||
:fqdns [\"example.org\" \"www.example.org\"],
|
:fqdns [\"example.org\" \"www.example.org\"],
|
||||||
:gitea-host \"githost.org\",
|
:forgejo-host \"githost.org\",
|
||||||
:gitea-repo \"repo\",
|
:repo-owner \"someuser\",
|
||||||
|
:repo-name \"repo\",
|
||||||
:branchname \"main\",
|
:branchname \"main\",
|
||||||
:build-cpu-request \"1500m\",
|
:build-cpu-request \"1500m\",
|
||||||
:build-cpu-limit \"3000m\",
|
:build-cpu-limit \"3000m\",
|
||||||
|
@ -49,12 +51,10 @@
|
||||||
"{:mon-auth
|
"{:mon-auth
|
||||||
{:grafana-cloud-user \"your-user-id\"
|
{:grafana-cloud-user \"your-user-id\"
|
||||||
:grafana-cloud-password \"your-cloud-password\"}
|
:grafana-cloud-password \"your-cloud-password\"}
|
||||||
:auth
|
:websiteauths
|
||||||
[{:unique-name \"test.io\",
|
[{:unique-name \"test.io\",
|
||||||
:username \"someuser\",
|
|
||||||
:authtoken \"abedjgbasdodj\"}
|
:authtoken \"abedjgbasdodj\"}
|
||||||
{:unique-name \"example.io\",
|
{:unique-name \"example.io\",
|
||||||
:username \"someuser\",
|
|
||||||
:authtoken \"abedjgbasdodj\"}]}"
|
:authtoken \"abedjgbasdodj\"}]}"
|
||||||
"7"))
|
"7"))
|
||||||
[(br/generate-br)]
|
[(br/generate-br)]
|
||||||
|
@ -70,12 +70,12 @@
|
||||||
|
|
||||||
(defn config-from-document []
|
(defn config-from-document []
|
||||||
(let [issuer (br/get-content-from-element "issuer" :optional true)
|
(let [issuer (br/get-content-from-element "issuer" :optional true)
|
||||||
websites (br/get-content-from-element "websites" :deserializer edn/read-string)
|
websiteconfigs (br/get-content-from-element "websiteconfigs" :deserializer edn/read-string)
|
||||||
mon-cluster-name (br/get-content-from-element "mon-cluster-name" :optional true)
|
mon-cluster-name (br/get-content-from-element "mon-cluster-name" :optional true)
|
||||||
mon-cluster-stage (br/get-content-from-element "mon-cluster-stage" :optional true)
|
mon-cluster-stage (br/get-content-from-element "mon-cluster-stage" :optional true)
|
||||||
mon-cloud-url (br/get-content-from-element "mon-cloud-url" :optional true)]
|
mon-cloud-url (br/get-content-from-element "mon-cloud-url" :optional true)]
|
||||||
(merge
|
(merge
|
||||||
{:websites websites}
|
{:websiteconfigs websiteconfigs}
|
||||||
(when (not (st/blank? issuer))
|
(when (not (st/blank? issuer))
|
||||||
{:issuer issuer})
|
{:issuer issuer})
|
||||||
(when (some? mon-cluster-name)
|
(when (some? mon-cluster-name)
|
||||||
|
@ -84,12 +84,12 @@
|
||||||
:grafana-cloud-url mon-cloud-url}}))))
|
:grafana-cloud-url mon-cloud-url}}))))
|
||||||
|
|
||||||
(defn validate-all! []
|
(defn validate-all! []
|
||||||
(br/validate! "websites" website/websites? :deserializer edn/read-string)
|
(br/validate! "websiteconfigs" core/websiteconfigs? :deserializer edn/read-string)
|
||||||
(br/validate! "issuer" ::website/issuer :optional true)
|
(br/validate! "issuer" ::core/issuer :optional true)
|
||||||
(br/validate! "mon-cluster-name" ::mon/cluster-name :optional true)
|
(br/validate! "mon-cluster-name" ::mon/cluster-name :optional true)
|
||||||
(br/validate! "mon-cluster-stage" ::mon/cluster-stage :optional true)
|
(br/validate! "mon-cluster-stage" ::mon/cluster-stage :optional true)
|
||||||
(br/validate! "mon-cloud-url" ::mon/grafana-cloud-url :optional true)
|
(br/validate! "mon-cloud-url" ::mon/grafana-cloud-url :optional true)
|
||||||
(br/validate! "auth" website/auth? :deserializer edn/read-string)
|
(br/validate! "auth" core/websiteauths? :deserializer edn/read-string)
|
||||||
(br/set-form-validated!))
|
(br/set-form-validated!))
|
||||||
|
|
||||||
(defn add-validate-listener [name]
|
(defn add-validate-listener [name]
|
||||||
|
@ -108,7 +108,7 @@
|
||||||
core/config-defaults
|
core/config-defaults
|
||||||
core/k8s-objects)
|
core/k8s-objects)
|
||||||
(br/set-output!)))))
|
(br/set-output!)))))
|
||||||
(add-validate-listener "websites")
|
(add-validate-listener "websiteconfigs")
|
||||||
(add-validate-listener "issuer")
|
(add-validate-listener "issuer")
|
||||||
(add-validate-listener "mon-cluster-name")
|
(add-validate-listener "mon-cluster-name")
|
||||||
(add-validate-listener "mon-cluster-stage")
|
(add-validate-listener "mon-cluster-stage")
|
||||||
|
|
11
src/main/resources/website/build-configmap.yaml
Normal file
11
src/main/resources/website/build-configmap.yaml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: build-configmap
|
||||||
|
namespace: NAME
|
||||||
|
labels:
|
||||||
|
app.kubernetes.part-of: NAME-website
|
||||||
|
data:
|
||||||
|
GITHOST: GITHOST
|
||||||
|
GITREPOURL: REPOURL
|
||||||
|
GITCOMMITURL: COMMITURL
|
|
@ -1,7 +1,8 @@
|
||||||
apiVersion: batch/v1
|
apiVersion: batch/v1
|
||||||
kind: CronJob
|
kind: CronJob
|
||||||
metadata:
|
metadata:
|
||||||
name: NAME-build-cron
|
name: build-cron
|
||||||
|
namespace: NAME
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.part-of: NAME-website
|
app.kubernetes.part-of: NAME-website
|
||||||
spec:
|
spec:
|
||||||
|
@ -10,11 +11,17 @@ spec:
|
||||||
failedJobsHistoryLimit: 1
|
failedJobsHistoryLimit: 1
|
||||||
jobTemplate:
|
jobTemplate:
|
||||||
spec:
|
spec:
|
||||||
|
activeDeadlineSeconds: 415
|
||||||
template:
|
template:
|
||||||
|
metadata:
|
||||||
|
namespace: NAME
|
||||||
|
labels:
|
||||||
|
app: build-cron
|
||||||
|
app.kubernetes.part-of: NAME-website
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- image: domaindrivenarchitecture/c4k-website-build
|
- image: domaindrivenarchitecture/c4k-website-build
|
||||||
name: NAME-build-app
|
name: build-cron-container
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
|
@ -25,24 +32,21 @@ spec:
|
||||||
memory: BUILD_MEMORY_LIMIT
|
memory: BUILD_MEMORY_LIMIT
|
||||||
command: ["/entrypoint.sh"]
|
command: ["/entrypoint.sh"]
|
||||||
envFrom:
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: build-configmap
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: NAME-secret
|
name: build-secret
|
||||||
env:
|
|
||||||
- name: SHA256SUM
|
|
||||||
value: CHECK_SUM
|
|
||||||
- name: SCRIPTFILE
|
|
||||||
value: SCRIPT_FILE
|
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: content-volume
|
- name: content-volume
|
||||||
mountPath: /var/www/html/website
|
mountPath: /var/www/html/website
|
||||||
- name: hashfile-volume
|
- name: hash-state-volume
|
||||||
mountPath: /var/hashfile.d
|
mountPath: /var/hashfile.d
|
||||||
volumes:
|
volumes:
|
||||||
- name: content-volume
|
- name: content-volume
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: NAME-content-volume
|
claimName: content-volume
|
||||||
- name: hashfile-volume
|
- name: hash-state-volume
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: NAME-hashfile-volume
|
claimName: hash-state-volume
|
||||||
restartPolicy: OnFailure
|
restartPolicy: OnFailure
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
name: NAME-secret
|
name: build-secret
|
||||||
|
namespace: NAME
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.part-of: NAME-website
|
app.kubernetes.part-of: NAME-website
|
||||||
data:
|
data:
|
||||||
AUTHTOKEN: TOKEN
|
AUTHTOKEN: TOKEN
|
||||||
GITREPOURL: REPOURL
|
|
||||||
GITCOMMITURL: COMMITURL
|
|
|
@ -1,10 +1,9 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
name: NAME-content-volume
|
name: content-volume
|
||||||
namespace: default
|
namespace: NAME
|
||||||
labels:
|
labels:
|
||||||
app: NAME-nginx
|
|
||||||
app.kubernetes.part-of: NAME-website
|
app.kubernetes.part-of: NAME-website
|
||||||
spec:
|
spec:
|
||||||
storageClassName: local-path
|
storageClassName: local-path
|
||||||
|
@ -13,4 +12,3 @@ spec:
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: WEBSITESTORAGESIZE
|
storage: WEBSITESTORAGESIZE
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
name: NAME-hashfile-volume
|
name: hash-state-volume
|
||||||
namespace: default
|
namespace: NAME
|
||||||
labels:
|
labels:
|
||||||
app: NAME-nginx
|
|
||||||
app.kubernetes.part-of: NAME-website
|
app.kubernetes.part-of: NAME-website
|
||||||
spec:
|
spec:
|
||||||
storageClassName: local-path
|
storageClassName: local-path
|
||||||
|
@ -13,4 +12,3 @@ spec:
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 16Mi
|
storage: 16Mi
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
name: NAME-configmap
|
name: etc-nginx
|
||||||
namespace: default
|
namespace: NAME
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.part-of: NAME-website
|
app.kubernetes.part-of: NAME-website
|
||||||
data:
|
data:
|
||||||
nginx.conf: |
|
nginx.conf: |
|
||||||
user nginx;
|
user nginx;
|
||||||
worker_processes 3;
|
worker_processes 3;
|
||||||
error_log /var/log/nginx/error.log;
|
error_log /var/log/nginx/error.log info;
|
||||||
pid /var/log/nginx/nginx.pid;
|
pid /var/log/nginx/nginx.pid;
|
||||||
worker_rlimit_nofile 8192;
|
worker_rlimit_nofile 8192;
|
||||||
events {
|
events {
|
||||||
|
@ -93,5 +93,6 @@ data:
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html =404;
|
try_files $uri $uri/ /index.html =404;
|
||||||
}
|
}
|
||||||
|
# redirects
|
||||||
|
REDIRECTS
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,41 @@
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: NAME-deployment
|
name: nginx
|
||||||
|
namespace: NAME
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.part-of: NAME-website
|
app.kubernetes.part-of: NAME-website
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: NAME-nginx
|
app: nginx
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
|
namespace: NAME
|
||||||
labels:
|
labels:
|
||||||
app: NAME-nginx
|
app: nginx
|
||||||
|
app.kubernetes.part-of: NAME-website
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: NAME-nginx
|
- name: nginx
|
||||||
image: nginx:latest
|
image: nginx:latest
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 80
|
- containerPort: 80
|
||||||
|
command: [ "/bin/bash", "-c", "nginx -g 'daemon off;'" ]
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /etc/nginx
|
- mountPath: /etc/nginx
|
||||||
readOnly: true
|
readOnly: true
|
||||||
name: nginx-config-volume
|
name: etc-nginx
|
||||||
- mountPath: /var/log/nginx
|
- mountPath: /tmp
|
||||||
name: log
|
name: tmp
|
||||||
- mountPath: /var/www/html/website
|
- mountPath: /var/www/html/website
|
||||||
name: content-volume
|
name: content-volume
|
||||||
readOnly: true
|
readOnly: true
|
||||||
initContainers:
|
initContainers:
|
||||||
- image: domaindrivenarchitecture/c4k-website-build
|
- image: domaindrivenarchitecture/c4k-website-build
|
||||||
name: NAME-init-build-container
|
name: init-build-container
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
|
@ -42,22 +46,19 @@ spec:
|
||||||
memory: BUILD_MEMORY_LIMIT
|
memory: BUILD_MEMORY_LIMIT
|
||||||
command: ["/entrypoint.sh"]
|
command: ["/entrypoint.sh"]
|
||||||
envFrom:
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: build-configmap
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: NAME-secret
|
name: build-secret
|
||||||
env:
|
|
||||||
- name: SHA256SUM
|
|
||||||
value: CHECK_SUM
|
|
||||||
- name: SCRIPTFILE
|
|
||||||
value: SCRIPT_FILE
|
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: content-volume
|
- name: content-volume
|
||||||
mountPath: /var/www/html/website
|
mountPath: /var/www/html/website
|
||||||
- name: hashfile-volume
|
- name: hash-state-volume
|
||||||
mountPath: /var/hashfile.d
|
mountPath: /var/hashfile.d
|
||||||
volumes:
|
volumes:
|
||||||
- name: nginx-config-volume
|
- name: etc-nginx
|
||||||
configMap:
|
configMap:
|
||||||
name: NAME-configmap
|
name: etc-nginx
|
||||||
items:
|
items:
|
||||||
- key: nginx.conf
|
- key: nginx.conf
|
||||||
path: nginx.conf
|
path: nginx.conf
|
||||||
|
@ -65,12 +66,11 @@ spec:
|
||||||
path: conf.d/website.conf
|
path: conf.d/website.conf
|
||||||
- key: mime.types
|
- key: mime.types
|
||||||
path: mime.types
|
path: mime.types
|
||||||
- name: log
|
- name: tmp
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
- name: content-volume
|
- name: content-volume
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: NAME-content-volume
|
claimName: content-volume
|
||||||
- name: hashfile-volume
|
- name: hash-state-volume
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: NAME-hashfile-volume
|
claimName: hash-state-volume
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
kind: Service
|
kind: Service
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
metadata:
|
metadata:
|
||||||
name: NAME-service
|
name: NAME
|
||||||
labels:
|
|
||||||
app: NAME-nginx
|
|
||||||
app.kubernetes.part-of: NAME-website
|
|
||||||
namespace: default
|
namespace: default
|
||||||
|
labels:
|
||||||
|
app: NAME
|
||||||
|
app.kubernetes.part-of: NAME-website
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: NAME-nginx
|
app: nginx
|
||||||
ports:
|
ports:
|
||||||
- name: nginx-http
|
- name: nginx-http
|
||||||
port: 80
|
port: 80
|
||||||
|
|
|
@ -4,9 +4,15 @@
|
||||||
#?(:clj [clojure.test :refer [deftest is are testing run-tests]]
|
#?(:clj [clojure.test :refer [deftest is are testing run-tests]]
|
||||||
:cljs [cljs.test :refer-macros [deftest is are testing run-tests]])
|
:cljs [cljs.test :refer-macros [deftest is are testing run-tests]])
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
|
[clojure.spec.test.alpha :as st]
|
||||||
[dda.c4k-common.yaml :as yaml]
|
[dda.c4k-common.yaml :as yaml]
|
||||||
[dda.c4k-website.core :as cut]
|
[dda.c4k-website.core :as cut]))
|
||||||
[clojure.spec.alpha :as s]))
|
|
||||||
|
(st/instrument `cut/sort-config)
|
||||||
|
(st/instrument `cut/flattened-and-reduced-config)
|
||||||
|
(st/instrument `cut/flatten-and-reduce-auth)
|
||||||
|
(st/instrument `cut/generate-ingress)
|
||||||
|
(st/instrument `cut/generate)
|
||||||
|
|
||||||
#?(:cljs
|
#?(:cljs
|
||||||
(defmethod yaml/load-resource :website-test [resource-name]
|
(defmethod yaml/load-resource :website-test [resource-name]
|
||||||
|
@ -20,89 +26,93 @@
|
||||||
(is (s/valid? cut/auth? (yaml/load-as-edn "website-test/valid-auth.yaml"))))
|
(is (s/valid? cut/auth? (yaml/load-as-edn "website-test/valid-auth.yaml"))))
|
||||||
|
|
||||||
(def websites1
|
(def websites1
|
||||||
{:websites
|
{:websiteconfigs
|
||||||
[{:unique-name "example.io"
|
[{:unique-name "example.io"
|
||||||
:fqdns ["example.org", "www.example.com"]
|
:fqdns ["example.org", "www.example.com"]
|
||||||
:gitea-host "finegitehost.net"
|
:forgejo-host "finegitehost.net"
|
||||||
:gitea-repo "repo"
|
:repo-owner "someuser"
|
||||||
|
:repo-name "repo"
|
||||||
:branchname "main"}
|
:branchname "main"}
|
||||||
{:unique-name "test.io"
|
{:unique-name "test.io"
|
||||||
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"]
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"]
|
||||||
:gitea-host "gitlab.de"
|
:forgejo-host "gitlab.de"
|
||||||
:gitea-repo "repo"
|
:repo-owner "someuser"
|
||||||
|
:repo-name "repo"
|
||||||
:branchname "main"}]})
|
:branchname "main"}]})
|
||||||
|
|
||||||
(def websites2
|
(def websites2
|
||||||
{:websites
|
{:websiteconfigs
|
||||||
[{:unique-name "test.io"
|
[{:unique-name "test.io"
|
||||||
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"]
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"]
|
||||||
:gitea-host "gitlab.de"
|
:forgejo-host "gitlab.de"
|
||||||
:gitea-repo "repo"
|
:repo-owner "someuser"
|
||||||
|
:repo-name "repo"
|
||||||
:branchname "main"}
|
:branchname "main"}
|
||||||
{:unique-name "example.io"
|
{:unique-name "example.io"
|
||||||
:fqdns ["example.org", "www.example.com"]
|
:fqdns ["example.org", "www.example.com"]
|
||||||
:gitea-host "finegitehost.net"
|
:forgejo-host "finegitehost.net"
|
||||||
:gitea-repo "repo"
|
:repo-owner "someuser"
|
||||||
|
:repo-name "repo"
|
||||||
:branchname "main"}]})
|
:branchname "main"}]})
|
||||||
|
|
||||||
(def auth1
|
(def auth1
|
||||||
{:auth
|
{:websiteauths
|
||||||
[{:unique-name "example.io"
|
[{:unique-name "example.io"
|
||||||
:username "someuser"
|
|
||||||
:authtoken "abedjgbasdodj"}
|
:authtoken "abedjgbasdodj"}
|
||||||
{:unique-name "test.io"
|
{:unique-name "test.io"
|
||||||
:username "someuser"
|
|
||||||
:authtoken "abedjgbasdodj"}]})
|
:authtoken "abedjgbasdodj"}]})
|
||||||
|
|
||||||
(def auth2
|
(def auth2
|
||||||
{:auth
|
{:websiteauths
|
||||||
[{:unique-name "test.io"
|
[{:unique-name "test.io"
|
||||||
:username "someuser"
|
|
||||||
:authtoken "abedjgbasdodj"}
|
:authtoken "abedjgbasdodj"}
|
||||||
{:unique-name "example.io"
|
{:unique-name "example.io"
|
||||||
:username "someuser"
|
|
||||||
:authtoken "abedjgbasdodj"}]})
|
:authtoken "abedjgbasdodj"}]})
|
||||||
|
|
||||||
(def flattened-and-reduced-config
|
(def flattened-and-reduced-config
|
||||||
{:unique-name "example.io",
|
{:unique-name "example.io",
|
||||||
:fqdns ["example.org" "www.example.com"],
|
:fqdns ["example.org" "www.example.com"],
|
||||||
:gitea-host "finegitehost.net",
|
:forgejo-host "finegitehost.net",
|
||||||
:gitea-repo "repo",
|
:repo-owner "someuser",
|
||||||
|
:repo-name "repo",
|
||||||
:branchname "main"})
|
:branchname "main"})
|
||||||
|
|
||||||
(def flattened-and-reduced-auth
|
(def flattened-and-reduced-auth
|
||||||
{:unique-name "example.io",
|
{:unique-name "example.io",
|
||||||
:username "someuser",
|
|
||||||
:authtoken "abedjgbasdodj"})
|
:authtoken "abedjgbasdodj"})
|
||||||
|
|
||||||
(deftest sorts-config
|
(deftest sorts-config
|
||||||
(is (= {:issuer "staging",
|
(is (= {:issuer "staging",
|
||||||
:websites
|
:websiteconfigs
|
||||||
[{:unique-name "example.io",
|
[{:unique-name "example.io",
|
||||||
:fqdns ["example.org" "www.example.com"],
|
:fqdns ["example.org" "www.example.com"],
|
||||||
:gitea-host "finegitehost.net",
|
:forgejo-host "finegitehost.net",
|
||||||
:gitea-repo "repo",
|
:repo-owner "someuser",
|
||||||
|
:repo-name "repo",
|
||||||
:branchname "main"},
|
:branchname "main"},
|
||||||
{:unique-name "test.io",
|
{:unique-name "test.io",
|
||||||
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
||||||
:gitea-host "gitlab.de",
|
:forgejo-host "gitlab.de",
|
||||||
:gitea-repo "repo",
|
:repo-owner "someuser",
|
||||||
|
:repo-name "repo",
|
||||||
:branchname "main",
|
:branchname "main",
|
||||||
:sha256sum-output "123456789ab123cd345de script-file-name.sh"}],
|
:sha256sum-output "123456789ab123cd345de script-file-name.sh"}],
|
||||||
:mon-cfg {:grafana-cloud-url "url-for-your-prom-remote-write-endpoint", :cluster-name "jitsi", :cluster-stage "test"}}
|
:mon-cfg {:grafana-cloud-url "url-for-your-prom-remote-write-endpoint", :cluster-name "jitsi", :cluster-stage "test"}}
|
||||||
(cut/sort-config
|
(cut/sort-config
|
||||||
{:issuer "staging",
|
{:issuer "staging",
|
||||||
:websites
|
:websiteconfigs
|
||||||
[{:unique-name "test.io",
|
[{:unique-name "test.io",
|
||||||
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
||||||
:gitea-host "gitlab.de",
|
:forgejo-host "gitlab.de",
|
||||||
:gitea-repo "repo",
|
:repo-owner "someuser",
|
||||||
|
:repo-name "repo",
|
||||||
:branchname "main",
|
:branchname "main",
|
||||||
:sha256sum-output "123456789ab123cd345de script-file-name.sh"}
|
:sha256sum-output "123456789ab123cd345de script-file-name.sh"}
|
||||||
{:unique-name "example.io",
|
{:unique-name "example.io",
|
||||||
:fqdns ["example.org" "www.example.com"],
|
:fqdns ["example.org" "www.example.com"],
|
||||||
:gitea-host "finegitehost.net",
|
:forgejo-host "finegitehost.net",
|
||||||
:gitea-repo "repo",
|
:repo-owner "someuser",
|
||||||
|
:repo-name "repo",
|
||||||
:branchname "main"}],
|
:branchname "main"}],
|
||||||
:mon-cfg {:grafana-cloud-url "url-for-your-prom-remote-write-endpoint", :cluster-name "jitsi", :cluster-stage "test"}}))))
|
:mon-cfg {:grafana-cloud-url "url-for-your-prom-remote-write-endpoint", :cluster-name "jitsi", :cluster-stage "test"}}))))
|
||||||
|
|
||||||
|
@ -119,3 +129,68 @@
|
||||||
(cut/flatten-and-reduce-auth (cut/sort-auth auth1))))
|
(cut/flatten-and-reduce-auth (cut/sort-auth auth1))))
|
||||||
(is (= flattened-and-reduced-auth
|
(is (= flattened-and-reduced-auth
|
||||||
(cut/flatten-and-reduce-auth (cut/sort-auth auth2)))))
|
(cut/flatten-and-reduce-auth (cut/sort-auth auth2)))))
|
||||||
|
|
||||||
|
(deftest test-generate
|
||||||
|
(is (= 24
|
||||||
|
(count (cut/generate
|
||||||
|
(yaml/load-as-edn "website-test/valid-config.yaml")
|
||||||
|
(yaml/load-as-edn "website-test/valid-auth.yaml"))))))
|
||||||
|
|
||||||
|
(deftest should-generate-ingress
|
||||||
|
(is (= [{:host "test.de",
|
||||||
|
:http
|
||||||
|
{:paths
|
||||||
|
[{:pathType "Prefix",
|
||||||
|
:path "/",
|
||||||
|
:backend {:service {:name "test-io", :port {:number 80}}}}]}}
|
||||||
|
{:host "test.org",
|
||||||
|
:http
|
||||||
|
{:paths
|
||||||
|
[{:pathType "Prefix",
|
||||||
|
:path "/",
|
||||||
|
:backend {:service {:name "test-io", :port {:number 80}}}}]}}
|
||||||
|
{:host "www.test.de",
|
||||||
|
:http
|
||||||
|
{:paths
|
||||||
|
[{:pathType "Prefix",
|
||||||
|
:path "/",
|
||||||
|
:backend {:service {:name "test-io", :port {:number 80}}}}]}}
|
||||||
|
{:host "www.test.org",
|
||||||
|
:http
|
||||||
|
{:paths
|
||||||
|
[{:pathType "Prefix",
|
||||||
|
:path "/",
|
||||||
|
:backend {:service {:name "test-io", :port {:number 80}}}}]}}]
|
||||||
|
(get-in
|
||||||
|
(cut/generate-ingress {:unique-name "test.io",
|
||||||
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
||||||
|
:forgejo-host "gitlab.de",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:repo-name "repo",
|
||||||
|
:sha256sum-output "123456789ab123cd345de script-file-name.sh",
|
||||||
|
:issuer "staging",
|
||||||
|
:branchname "main",
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:redirects []})
|
||||||
|
[2 :spec :rules])))
|
||||||
|
(is (= "test-io"
|
||||||
|
(get-in
|
||||||
|
(cut/generate-ingress {:unique-name "test.io",
|
||||||
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
||||||
|
:forgejo-host "gitlab.de",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:repo-name "repo",
|
||||||
|
:sha256sum-output "123456789ab123cd345de script-file-name.sh",
|
||||||
|
:issuer "staging",
|
||||||
|
:branchname "main",
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:redirects []})
|
||||||
|
[2 :metadata :namespace]))))
|
|
@ -1,223 +1,316 @@
|
||||||
(ns dda.c4k-website.website-test
|
(ns dda.c4k-website.website-test
|
||||||
(:require
|
(:require
|
||||||
|
[clojure.string :as str]
|
||||||
#?(:clj [clojure.test :refer [deftest is are testing run-tests]]
|
#?(:clj [clojure.test :refer [deftest is are testing run-tests]]
|
||||||
:cljs [cljs.test :refer-macros [deftest is are testing run-tests]])
|
:cljs [cljs.test :refer-macros [deftest is are testing run-tests]])
|
||||||
[clojure.spec.test.alpha :as st]
|
[clojure.spec.test.alpha :as st]
|
||||||
[dda.c4k-common.test-helper :as th]
|
[dda.c4k-website.website :as cut]))
|
||||||
[dda.c4k-common.base64 :as b64]
|
|
||||||
[dda.c4k-website.website :as cut]
|
|
||||||
[clojure.spec.alpha :as s]))
|
|
||||||
|
|
||||||
|
(st/instrument `cut/replace-dots-by-minus)
|
||||||
|
(st/instrument `cut/generate-gitrepourl)
|
||||||
|
(st/instrument `cut/generate-gitcommiturl)
|
||||||
|
(st/instrument `cut/replace-all-matching-prefixes)
|
||||||
|
(st/instrument `cut/generate-redirects)
|
||||||
(st/instrument `cut/generate-nginx-configmap)
|
(st/instrument `cut/generate-nginx-configmap)
|
||||||
(st/instrument `cut/generate-nginx-deployment)
|
(st/instrument `cut/generate-build-secret)
|
||||||
|
(st/instrument `cut/generate-content-pvc)
|
||||||
|
(st/instrument `cut/generate-hash-state-pvc)
|
||||||
|
(st/instrument `cut/generate-build-cron)
|
||||||
(st/instrument `cut/generate-nginx-service)
|
(st/instrument `cut/generate-nginx-service)
|
||||||
(st/instrument `cut/generate-website-content-volume)
|
|
||||||
(st/instrument `cut/generate-hashfile-volume)
|
|
||||||
(st/instrument `cut/generate-website-ingress)
|
|
||||||
(st/instrument `cut/generate-website-certificate)
|
|
||||||
(st/instrument `cut/generate-website-build-cron)
|
|
||||||
(st/instrument `cut/generate-website-build-secret)
|
|
||||||
|
|
||||||
(deftest should-generate-nginx-configmap-website
|
|
||||||
(is (= "server {\n listen 80 default_server;\n listen [::]:80 default_server;\n server_name test.de www.test.de test-it.de www.test-it.de;\n add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload'; \n add_header X-Frame-Options \"SAMEORIGIN\";\n add_header X-Content-Type-Options nosniff;\n add_header Referrer-Policy \"strict-origin\";\n # add_header Permissions-Policy \"permissions here\";\n root /var/www/html/website/;\n index index.html;\n location / {\n try_files $uri $uri/ /index.html =404;\n }\n}\n"
|
|
||||||
(:website.conf (:data (cut/generate-nginx-configmap {:unique-name "test.io",
|
|
||||||
:gitea-host "gitea.evilorg",
|
|
||||||
:gitea-repo "none",
|
|
||||||
:branchname "mablain",
|
|
||||||
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))))
|
|
||||||
(is (= "types {\n text/html html htm shtml;\n text/css css;\n text/xml xml rss;\n image/gif gif;\n image/jpeg jpeg jpg;\n application/x-javascript js;\n text/plain txt;\n text/x-component htc;\n text/mathml mml;\n image/svg+xml svg svgz;\n image/png png;\n image/x-icon ico;\n image/x-jng jng;\n image/vnd.wap.wbmp wbmp;\n application/java-archive jar war ear;\n application/mac-binhex40 hqx;\n application/pdf pdf;\n application/x-cocoa cco;\n application/x-java-archive-diff jardiff;\n application/x-java-jnlp-file jnlp;\n application/x-makeself run;\n application/x-perl pl pm;\n application/x-pilot prc pdb;\n application/x-rar-compressed rar;\n application/x-redhat-package-manager rpm;\n application/x-sea sea;\n application/x-shockwave-flash swf;\n application/x-stuffit sit;\n application/x-tcl tcl tk;\n application/x-x509-ca-cert der pem crt;\n application/x-xpinstall xpi;\n application/zip zip;\n application/octet-stream deb;\n application/octet-stream bin exe dll;\n application/octet-stream dmg;\n application/octet-stream eot;\n application/octet-stream iso img;\n application/octet-stream msi msp msm;\n audio/mpeg mp3;\n audio/x-realaudio ra;\n video/mpeg mpeg mpg;\n video/quicktime mov;\n video/x-flv flv;\n video/x-msvideo avi;\n video/x-ms-wmv wmv;\n video/x-ms-asf asx asf;\n video/x-mng mng;\n}\n"
|
|
||||||
(:mime.types (:data (cut/generate-nginx-configmap {:unique-name "test.io",
|
|
||||||
:gitea-host "gitea.evilorg",
|
|
||||||
:gitea-repo "none",
|
|
||||||
:branchname "mablain",
|
|
||||||
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))))
|
|
||||||
(is (= "user nginx;\nworker_processes 3;\nerror_log /var/log/nginx/error.log;\npid /var/log/nginx/nginx.pid;\nworker_rlimit_nofile 8192;\nevents {\n worker_connections 4096;\n}\nhttp {\n include /etc/nginx/mime.types;\n default_type application/octet-stream;\n log_format main '$remote_addr - $remote_user [$time_local] $status'\n '\"$request\" $body_bytes_sent \"$http_referer\"'\n '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n access_log /var/log/nginx/access.log main;\n sendfile on;\n tcp_nopush on;\n keepalive_timeout 65;\n server_names_hash_bucket_size 128;\n include /etc/nginx/conf.d/website.conf;\n}\n"
|
|
||||||
(:nginx.conf (:data (cut/generate-nginx-configmap {:unique-name "test.io",
|
|
||||||
:gitea-host "gitea.evilorg",
|
|
||||||
:gitea-repo "none",
|
|
||||||
:branchname "mablain",
|
|
||||||
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))))
|
|
||||||
(is (= {:apiVersion "v1",
|
|
||||||
:kind "ConfigMap",
|
|
||||||
:metadata {:name "test-io-configmap",
|
|
||||||
:labels {:app.kubernetes.part-of "test-io-website"},
|
|
||||||
:namespace "default"}}
|
|
||||||
(dissoc (cut/generate-nginx-configmap {:unique-name "test.io",
|
|
||||||
:gitea-host "gitea.evilorg",
|
|
||||||
:gitea-repo "none",
|
|
||||||
:branchname "mablain",
|
|
||||||
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}) :data))))
|
|
||||||
|
|
||||||
(deftest should-generate-nginx-deployment
|
(deftest should-generate-gitrepourl
|
||||||
(is (= {:apiVersion "apps/v1",
|
(is (= "https://mygit.de/api/v1/repos/someuser/repo/archive/main.zip"
|
||||||
:kind "Deployment",
|
(cut/generate-gitrepourl "mygit.de" "someuser" "repo" "main"))))
|
||||||
:metadata {:name "test-io-deployment", :labels {:app.kubernetes.part-of "test-io-website"}},
|
|
||||||
:spec
|
(deftest should-generate-gitcommiturl
|
||||||
{:replicas 1,
|
(is (= "https://mygit.de/api/v1/repos/someuser/repo/git/commits/HEAD"
|
||||||
:selector {:matchLabels {:app "test-io-nginx"}},
|
(cut/generate-gitcommiturl "mygit.de" "someuser" "repo"))))
|
||||||
:template
|
|
||||||
{:metadata {:labels {:app "test-io-nginx"}},
|
(deftest should-generate-redirects
|
||||||
:spec
|
(is (= "rewrite ^/products.html\\$ /offer.html permanent;\n rewrite ^/one-more\\$ /redirect permanent;"
|
||||||
{:containers
|
(cut/generate-redirects {:issuer "staging"
|
||||||
[{:name "test-io-nginx",
|
:build-cpu-request "500m"
|
||||||
:image "nginx:latest",
|
:build-cpu-limit "1700m"
|
||||||
:imagePullPolicy "IfNotPresent",
|
:build-memory-request "256Mi"
|
||||||
:ports [{:containerPort 80}],
|
:build-memory-limit "512Mi"
|
||||||
:volumeMounts
|
:volume-size "3"
|
||||||
[{:mountPath "/etc/nginx", :readOnly true, :name "nginx-config-volume"}
|
:unique-name "test.io",
|
||||||
{:mountPath "/var/log/nginx", :name "log"}
|
:redirects [["/products.html", "/offer.html"]
|
||||||
{:mountPath "/var/www/html/website", :name "content-volume", :readOnly true}]}],
|
["/one-more", "/redirect"]]
|
||||||
:initContainers
|
:forgejo-host "gitea.evilorg",
|
||||||
[{:image "domaindrivenarchitecture/c4k-website-build",
|
:repo-owner "someuser",
|
||||||
:name "test-io-init-build-container",
|
:repo-name "none",
|
||||||
:imagePullPolicy "IfNotPresent",
|
:branchname "mablain",
|
||||||
:resources {:requests {:cpu "500m", :memory "256Mi"}, :limits {:cpu "1700m", :memory "512Mi"}},
|
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}
|
||||||
:command ["/entrypoint.sh"],
|
2)))
|
||||||
:envFrom [{:secretRef {:name "test-io-secret"}}],
|
(is (= ""
|
||||||
:env [{:name "SHA256SUM", :value "123456789ab123cd345de"} {:name "SCRIPTFILE", :value "script-file-name.sh"}],
|
(cut/generate-redirects {:issuer "staging"
|
||||||
:volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}
|
:build-cpu-request "500m"
|
||||||
{:name "hashfile-volume", :mountPath "/var/hashfile.d"}]}],
|
:build-cpu-limit "1700m"
|
||||||
:volumes
|
:build-memory-request "256Mi"
|
||||||
[{:name "nginx-config-volume",
|
:build-memory-limit "512Mi"
|
||||||
:configMap
|
:volume-size "3"
|
||||||
{:name "test-io-configmap",
|
:unique-name "test.io",
|
||||||
:items
|
:redirects []
|
||||||
[{:key "nginx.conf", :path "nginx.conf"}
|
:forgejo-host "gitea.evilorg",
|
||||||
{:key "website.conf", :path "conf.d/website.conf"}
|
:repo-owner "someuser",
|
||||||
{:key "mime.types", :path "mime.types"}]}}
|
:repo-name "none",
|
||||||
{:name "log", :emptyDir {}}
|
:branchname "mablain",
|
||||||
{:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}
|
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}
|
||||||
{:name "hashfile-volume", :persistentVolumeClaim {:claimName "test-io-hashfile-volume"}}]}}}}
|
0))))
|
||||||
(cut/generate-nginx-deployment {:gitea-host "gitlab.de",
|
|
||||||
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
|
||||||
:gitea-repo "repo",
|
|
||||||
:sha256sum-output "123456789ab123cd345de script-file-name.sh",
|
|
||||||
:issuer "staging",
|
|
||||||
:branchname "main",
|
|
||||||
:unique-name "test.io"}))))
|
|
||||||
|
|
||||||
(deftest should-generate-resource-requests
|
(deftest should-generate-resource-requests
|
||||||
(is (= {:requests {:cpu "500m", :memory "256Mi"}, :limits {:cpu "1700m", :memory "512Mi"}}
|
|
||||||
(-> (cut/generate-nginx-deployment {:gitea-host "gitlab.de",
|
|
||||||
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
|
||||||
:gitea-repo "repo",
|
|
||||||
:sha256sum-output "123456789ab123cd345de script-file-name.sh",
|
|
||||||
:issuer "staging",
|
|
||||||
:branchname "main",
|
|
||||||
:unique-name "test.io"})
|
|
||||||
:spec :template :spec :initContainers first :resources )))
|
|
||||||
(is (= {:requests {:cpu "1500m", :memory "512Mi"}, :limits {:cpu "3000m", :memory "1024Mi"}}
|
(is (= {:requests {:cpu "1500m", :memory "512Mi"}, :limits {:cpu "3000m", :memory "1024Mi"}}
|
||||||
(-> (cut/generate-nginx-deployment {:gitea-host "gitlab.de",
|
(-> (cut/generate-nginx-deployment {:forgejo-host "gitlab.de",
|
||||||
|
:repo-owner "someuser",
|
||||||
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
||||||
:gitea-repo "repo",
|
:repo-name "repo",
|
||||||
:sha256sum-output "123456789ab123cd345de script-file-name.sh",
|
|
||||||
:issuer "staging",
|
:issuer "staging",
|
||||||
:branchname "main",
|
:branchname "main",
|
||||||
:unique-name "test.io"
|
:unique-name "test.io",
|
||||||
|
:redirects [],
|
||||||
:build-cpu-request "1500m"
|
:build-cpu-request "1500m"
|
||||||
:build-cpu-limit "3000m"
|
:build-cpu-limit "3000m"
|
||||||
:build-memory-request "512Mi"
|
:build-memory-request "512Mi"
|
||||||
:build-memory-limit "1024Mi"})
|
:build-memory-limit "1024Mi"
|
||||||
:spec :template :spec :initContainers first :resources))))
|
:volume-size 3})
|
||||||
|
:spec :template :spec :initContainers first :resources)))
|
||||||
(deftest should-generate-nginx-service
|
(is (= "test-io"
|
||||||
(is (= {:name-c1 "test-io-service",
|
(-> (cut/generate-nginx-deployment {:forgejo-host "gitlab.de",
|
||||||
:name-c2 "test-org-service",
|
:repo-owner "someuser",
|
||||||
:app-c1 "test-io-nginx",
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
||||||
:app-c2 "test-org-nginx",
|
:repo-name "repo",
|
||||||
:app.kubernetes.part-of-c1 "test-io-website",
|
:issuer "staging",
|
||||||
:app.kubernetes.part-of-c2 "test-org-website"}
|
:branchname "main",
|
||||||
(th/map-diff (cut/generate-nginx-service {:unique-name "test.io",
|
:unique-name "test.io",
|
||||||
:gitea-host "gitea.evilorg",
|
:redirects [],
|
||||||
:gitea-repo "none",
|
:build-cpu-request "1500m"
|
||||||
|
:build-cpu-limit "3000m"
|
||||||
|
:build-memory-request "512Mi"
|
||||||
|
:build-memory-limit "1024Mi"
|
||||||
|
:volume-size 3})
|
||||||
|
:metadata :namespace))))
|
||||||
|
(deftest should-generate-nginx-configmap-website
|
||||||
|
(is (str/includes?
|
||||||
|
(:website.conf (:data (cut/generate-nginx-configmap {:issuer "staging"
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:unique-name "test.io",
|
||||||
|
:redirects [["/products.html", "/offer.html"]
|
||||||
|
["/one-more", "/redirect"]]
|
||||||
|
:forgejo-host "gitea.evilorg",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:repo-name "none",
|
||||||
|
:branchname "mablain",
|
||||||
|
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))
|
||||||
|
" /offer.html permanent;\n"))
|
||||||
|
(is (str/includes?
|
||||||
|
(:website.conf (:data (cut/generate-nginx-configmap {:issuer "staging"
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:unique-name "test.io",
|
||||||
|
:redirects [["/products.html", "/offer.html"]
|
||||||
|
["/one-more", "/redirect"]]
|
||||||
|
:forgejo-host "gitea.evilorg",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:repo-name "none",
|
||||||
|
:branchname "mablain",
|
||||||
|
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))
|
||||||
|
" /redirect permanent;\n"))
|
||||||
|
(is (str/includes?
|
||||||
|
(:website.conf (:data (cut/generate-nginx-configmap {:issuer "staging"
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:unique-name "test.io",
|
||||||
|
:redirects [],
|
||||||
|
:forgejo-host "gitea.evilorg",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:repo-name "none",
|
||||||
|
:branchname "mablain",
|
||||||
|
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))
|
||||||
|
"server_name test.de www.test.de test-it.de www.test-it.de;"))
|
||||||
|
(is (= {:apiVersion "v1",
|
||||||
|
:kind "ConfigMap",
|
||||||
|
:metadata {:labels {:app.kubernetes.part-of "test-io-website"},
|
||||||
|
:namespace "test-io",
|
||||||
|
:name "etc-nginx"}}
|
||||||
|
(dissoc (cut/generate-nginx-configmap {:issuer "staging"
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:unique-name "test.io",
|
||||||
|
:redirects [],
|
||||||
|
:forgejo-host "gitea.evilorg",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:repo-name "none",
|
||||||
:branchname "mablain",
|
:branchname "mablain",
|
||||||
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})
|
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})
|
||||||
(cut/generate-nginx-service {:unique-name "test.org",
|
:data))))
|
||||||
:gitea-host "gitea.evilorg",
|
|
||||||
:gitea-repo "none",
|
|
||||||
:branchname "mablain",
|
|
||||||
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))))
|
|
||||||
|
|
||||||
(deftest should-generate-website-build-cron
|
(deftest should-generate-nginx-service
|
||||||
|
(is (= {:kind "Service",
|
||||||
|
:apiVersion "v1",
|
||||||
|
:metadata
|
||||||
|
{:name "test-io",
|
||||||
|
:namespace "test-io",
|
||||||
|
:labels {:app "test-io", :app.kubernetes.part-of "test-io-website"}},
|
||||||
|
:spec
|
||||||
|
{:selector {:app "nginx"}, :ports [{:name "nginx-http", :port 80}]}}
|
||||||
|
(cut/generate-nginx-service {:issuer "staging"
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:unique-name "test.io",
|
||||||
|
:redirects [],
|
||||||
|
:forgejo-host "gitea.evilorg",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:repo-name "none",
|
||||||
|
:branchname "mablain",
|
||||||
|
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}))))
|
||||||
|
|
||||||
|
|
||||||
|
(deftest should-generate-build-cron
|
||||||
(is (= {:apiVersion "batch/v1",
|
(is (= {:apiVersion "batch/v1",
|
||||||
:kind "CronJob",
|
:kind "CronJob",
|
||||||
:metadata {:name "test-io-build-cron", :labels {:app.kubernetes.part-of "test-io-website"}},
|
:metadata {:name "build-cron",
|
||||||
|
:namespace "test-io",
|
||||||
|
:labels {:app.kubernetes.part-of "test-io-website"}},
|
||||||
:spec
|
:spec
|
||||||
{:schedule "0/7 * * * *",
|
{:schedule "0/7 * * * *",
|
||||||
:successfulJobsHistoryLimit 1,
|
:successfulJobsHistoryLimit 1,
|
||||||
:failedJobsHistoryLimit 1,
|
:failedJobsHistoryLimit 1,
|
||||||
:jobTemplate
|
:jobTemplate
|
||||||
{:spec
|
{:spec
|
||||||
{:template
|
{:activeDeadlineSeconds 415,
|
||||||
{:spec
|
:template
|
||||||
|
{:metadata
|
||||||
|
{:namespace "test-io",
|
||||||
|
:labels
|
||||||
|
{:app "build-cron", :app.kubernetes.part-of "test-io-website"}}
|
||||||
|
:spec
|
||||||
{:containers
|
{:containers
|
||||||
[{:image "domaindrivenarchitecture/c4k-website-build",
|
[{:image "domaindrivenarchitecture/c4k-website-build",
|
||||||
:name "test-io-build-app",
|
:name "build-cron-container",
|
||||||
:imagePullPolicy "IfNotPresent",
|
:imagePullPolicy "IfNotPresent",
|
||||||
:resources {:requests {:cpu "500m", :memory "256Mi"}, :limits {:cpu "1700m", :memory "512Mi"}},
|
:resources {:requests {:cpu "500m", :memory "256Mi"}, :limits {:cpu "1700m", :memory "512Mi"}},
|
||||||
:command ["/entrypoint.sh"],
|
:command ["/entrypoint.sh"],
|
||||||
:envFrom [{:secretRef {:name "test-io-secret"}}],
|
:envFrom [{:configMapRef {:name "build-configmap"}}
|
||||||
:env [{:name "SHA256SUM", :value "123456789ab123cd345de"} {:name "SCRIPTFILE", :value "script-file-name.sh"}],
|
{:secretRef {:name "build-secret"}}],
|
||||||
:volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}
|
:volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}
|
||||||
{:name "hashfile-volume", :mountPath "/var/hashfile.d"}]}],
|
{:name "hash-state-volume", :mountPath "/var/hashfile.d"}]}],
|
||||||
:volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}
|
:volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "content-volume"}}
|
||||||
{:name "hashfile-volume", :persistentVolumeClaim {:claimName "test-io-hashfile-volume"}}],
|
{:name "hash-state-volume", :persistentVolumeClaim {:claimName "hash-state-volume"}}],
|
||||||
:restartPolicy "OnFailure"}}}}}}
|
:restartPolicy "OnFailure"}}}}}}
|
||||||
(cut/generate-website-build-cron {:gitea-host "gitlab.de",
|
(cut/generate-build-cron {:issuer "staging"
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:forgejo-host "gitlab.de",
|
||||||
|
:repo-owner "someuser",
|
||||||
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
||||||
:gitea-repo "repo",
|
:repo-name "repo",
|
||||||
:sha256sum-output "123456789ab123cd345de script-file-name.sh",
|
|
||||||
:issuer "staging",
|
|
||||||
:branchname "main",
|
|
||||||
:unique-name "test.io"}))))
|
|
||||||
|
|
||||||
(deftest should-generate-website-build-secret
|
|
||||||
(is (= {:apiVersion "v1",
|
|
||||||
:kind "Secret",
|
|
||||||
:metadata {:name "test-io-secret", :labels {:app.kubernetes.part-of "test-io-website"}},
|
|
||||||
:data
|
|
||||||
{:AUTHTOKEN "YWJlZGpnYmFzZG9kag==",
|
|
||||||
:GITREPOURL "aHR0cHM6Ly9naXRsYWIuZGUvYXBpL3YxL3JlcG9zL3NvbWV1c2VyL3JlcG8vYXJjaGl2ZS9tYWluLnppcA==",
|
|
||||||
:GITCOMMITURL "aHR0cHM6Ly9naXRsYWIuZGUvYXBpL3YxL3JlcG9zL3NvbWV1c2VyL3JlcG8vZ2l0L2NvbW1pdHMvSEVBRA=="}}
|
|
||||||
(cut/generate-website-build-secret {:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
|
||||||
:gitea-repo "repo",
|
|
||||||
:sha256sum-output "123456789ab123cd345de script-file-name.sh",
|
|
||||||
:issuer "staging",
|
|
||||||
:branchname "main",
|
:branchname "main",
|
||||||
:unique-name "test.io",
|
:unique-name "test.io",
|
||||||
:gitea-host "gitlab.de"}
|
:redirects []}))))
|
||||||
{:unique-name "test.io",
|
|
||||||
:authtoken "abedjgbasdodj",
|
|
||||||
:username "someuser"}))))
|
|
||||||
|
|
||||||
(deftest should-generate-website-content-volume
|
(deftest should-generate-build-configmap
|
||||||
(is (= {:name-c1 "test-io-content-volume",
|
(is (= {:apiVersion "v1",
|
||||||
:name-c2 "test-org-content-volume",
|
:kind "ConfigMap",
|
||||||
:app-c1 "test-io-nginx",
|
:metadata {:name "build-configmap",
|
||||||
:app-c2 "test-org-nginx",
|
:namespace "test-io",
|
||||||
:app.kubernetes.part-of-c1 "test-io-website",
|
:labels {:app.kubernetes.part-of "test-io-website"}},
|
||||||
:app.kubernetes.part-of-c2 "test-org-website"}
|
:data
|
||||||
(th/map-diff (cut/generate-website-content-volume {:unique-name "test.io",
|
{:GITHOST "mygit.de"
|
||||||
:gitea-host "gitea.evilorg",
|
:GITREPOURL "https://mygit.de/api/v1/repos/someuser/repo/archive/main.zip"
|
||||||
:gitea-repo "none",
|
:GITCOMMITURL "https://mygit.de/api/v1/repos/someuser/repo/git/commits/HEAD"}}
|
||||||
:branchname "mablain",
|
(cut/generate-build-configmap {:issuer "staging"
|
||||||
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})
|
:build-cpu-request "500m"
|
||||||
(cut/generate-website-content-volume {:unique-name "test.org",
|
:build-cpu-limit "1700m"
|
||||||
:gitea-host "gitea.evilorg",
|
:build-memory-request "256Mi"
|
||||||
:gitea-repo "none",
|
:build-memory-limit "512Mi"
|
||||||
:branchname "mablain",
|
:volume-size "3"
|
||||||
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))))
|
:forgejo-host "mygit.de",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:fqdns ["test.de" "test.org" "www.test.de" "www.test.org"],
|
||||||
|
:repo-name "repo",
|
||||||
|
:branchname "main",
|
||||||
|
:unique-name "test.io",
|
||||||
|
:redirects []}))))
|
||||||
|
|
||||||
(deftest should-generate-hashfile-volume
|
(deftest should-generate-build-secret
|
||||||
|
(is (= {:apiVersion "v1",
|
||||||
|
:kind "Secret",
|
||||||
|
:metadata {:name "build-secret",
|
||||||
|
:namespace "test-io",
|
||||||
|
:labels {:app.kubernetes.part-of "test-io-website"}},
|
||||||
|
:data
|
||||||
|
{:AUTHTOKEN "YWJlZGpnYmFzZG9kag=="}}
|
||||||
|
(cut/generate-build-secret {:unique-name "test.io",
|
||||||
|
:authtoken "abedjgbasdodj"}))))
|
||||||
|
|
||||||
|
(deftest should-generate-content-pvc
|
||||||
(is (= {:apiVersion "v1",
|
(is (= {:apiVersion "v1",
|
||||||
:kind "PersistentVolumeClaim",
|
:kind "PersistentVolumeClaim",
|
||||||
:metadata
|
:metadata
|
||||||
{:name "test-io-hashfile-volume",
|
{:name "content-volume",
|
||||||
:namespace "default",
|
:namespace "test-io",
|
||||||
:labels {:app "test-io-nginx", :app.kubernetes.part-of "test-io-website"}},
|
:labels {:app.kubernetes.part-of "test-io-website"}},
|
||||||
:spec {:storageClassName "local-path", :accessModes ["ReadWriteOnce"], :resources {:requests {:storage "16Mi"}}}}
|
:spec
|
||||||
(cut/generate-hashfile-volume {:unique-name "test.io",
|
{:storageClassName "local-path",
|
||||||
:gitea-host "gitea.evilorg",
|
:accessModes ["ReadWriteOnce"],
|
||||||
:gitea-repo "none",
|
:resources {:requests {:storage "3Gi"}}}}
|
||||||
|
(cut/generate-content-pvc {:issuer "staging"
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:unique-name "test.io",
|
||||||
|
:redirects [],
|
||||||
|
:forgejo-host "gitea.evilorg",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:repo-name "none",
|
||||||
|
:branchname "mablain",
|
||||||
|
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}))))
|
||||||
|
|
||||||
|
|
||||||
|
(deftest should-generate-hash-state-pvc
|
||||||
|
(is (= {:apiVersion "v1",
|
||||||
|
:kind "PersistentVolumeClaim",
|
||||||
|
:metadata
|
||||||
|
{:name "hash-state-volume",
|
||||||
|
:namespace "test-io",
|
||||||
|
:labels {:app.kubernetes.part-of "test-io-website"}},
|
||||||
|
:spec {:storageClassName "local-path",
|
||||||
|
:accessModes ["ReadWriteOnce"],
|
||||||
|
:resources {:requests {:storage "16Mi"}}}}
|
||||||
|
(cut/generate-hash-state-pvc {:issuer "staging"
|
||||||
|
:build-cpu-request "500m"
|
||||||
|
:build-cpu-limit "1700m"
|
||||||
|
:build-memory-request "256Mi"
|
||||||
|
:build-memory-limit "512Mi"
|
||||||
|
:volume-size "3"
|
||||||
|
:unique-name "test.io",
|
||||||
|
:redirects [],
|
||||||
|
:forgejo-host "gitea.evilorg",
|
||||||
|
:repo-owner "someuser",
|
||||||
|
:repo-name "none",
|
||||||
:branchname "mablain",
|
:branchname "mablain",
|
||||||
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}))))
|
:fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}))))
|
|
@ -1,9 +1,7 @@
|
||||||
auth:
|
websiteauths:
|
||||||
- unique-name: "test.io"
|
- unique-name: "test.io"
|
||||||
username: "someuser"
|
|
||||||
authtoken: "abedjgbasdodj"
|
authtoken: "abedjgbasdodj"
|
||||||
- unique-name: "example.io"
|
- unique-name: "example.io"
|
||||||
username: "someuser"
|
|
||||||
authtoken: "abedjgbasdodj"
|
authtoken: "abedjgbasdodj"
|
||||||
mon-auth:
|
mon-auth:
|
||||||
grafana-cloud-user: "user"
|
grafana-cloud-user: "user"
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
issuer: "staging"
|
issuer: "staging"
|
||||||
websites:
|
websiteconfigs:
|
||||||
- unique-name: "test.io"
|
- unique-name: "test.io"
|
||||||
fqdns: ["test.de", "test.org", "www.test.de", "www.test.org"]
|
fqdns: ["test.de", "test.org", "www.test.de", "www.test.org"]
|
||||||
gitea-host: "gitlab.de"
|
forgejo-host: "codeberg.org"
|
||||||
gitea-repo: "repo"
|
repo-owner: "someuser"
|
||||||
|
repo-name: "repo"
|
||||||
branchname: "main"
|
branchname: "main"
|
||||||
sha256sum-output: "123456789ab123cd345de script-file-name.sh"
|
redirects:
|
||||||
|
- ["/products.html", "/offer.html"]
|
||||||
|
- ["/one-more", "/redirect"]
|
||||||
- unique-name: "example.io"
|
- unique-name: "example.io"
|
||||||
fqdns: ["example.org", "www.example.com"]
|
fqdns: ["example.org", "www.example.com"]
|
||||||
gitea-host: "finegitehost.net"
|
forgejo-host: "fineForgejoHost.net"
|
||||||
gitea-repo: "repo"
|
repo-owner: "someotheruser"
|
||||||
|
repo-name: "repo"
|
||||||
branchname: "main"
|
branchname: "main"
|
||||||
mon-cfg:
|
mon-cfg:
|
||||||
grafana-cloud-url: "url-for-your-prom-remote-write-endpoint"
|
grafana-cloud-url: "url-for-your-prom-remote-write-endpoint"
|
||||||
cluster-name: "jitsi"
|
cluster-name: "website"
|
||||||
cluster-stage: "test"
|
cluster-stage: "test"
|
||||||
|
average-rate: 50
|
||||||
|
|
Loading…
Reference in a new issue