├── .drone.yml ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ └── feature-request.md └── stale.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── build ├── .drone.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── bin │ └── po-diff.sh ├── images │ └── build │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── build-scripts │ │ └── install-packages.sh │ │ └── root │ │ ├── build │ │ ├── rsyncd.sh │ │ └── run.sh │ │ └── usr │ │ └── local │ │ └── bin │ │ ├── setup-credentials-helper.sh │ │ └── xvfb-chrome └── makelib │ ├── cache.mk │ ├── common.mk │ ├── gcp.mk │ ├── gettext.mk │ ├── git-publish.mk │ ├── golang.mk │ ├── helm.mk │ ├── image.mk │ ├── k8s-tools.mk │ ├── kubebuilder-v1.mk │ ├── kubebuilder-v2.mk │ ├── kubebuilder-v3.mk │ ├── nodejs.mk │ ├── php.mk │ ├── protobuf.mk │ ├── react.mk │ ├── utils.mk │ └── wordpress.mk ├── default-backend ├── main.go ├── metrics.go └── templates │ └── html.tmpl ├── demo ├── 02-install-presslabs-stack.sh └── 03-optional-install-dashboard.sh ├── deploy ├── 00-crds.yaml └── charts │ ├── git-webhook │ ├── Chart.yaml │ ├── templates │ │ ├── _helpers.tpl │ │ ├── clusterrole.yaml │ │ ├── clusterrolebinding.yaml │ │ ├── deployment.yaml │ │ ├── ingress.yaml │ │ ├── secret.yaml │ │ ├── service.yaml │ │ └── serviceaccount.yaml │ └── values.yaml │ ├── stack │ ├── .helmignore │ ├── Chart.lock │ ├── Chart.yaml │ ├── icon.png │ ├── templates │ │ ├── NOTES.txt │ │ ├── _docs.tpl │ │ ├── _helpers.tpl │ │ ├── acme-issuer.yaml │ │ └── application.yaml │ └── values.yaml │ └── wordpress-site │ ├── .helmignore │ ├── Chart.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── application.yaml │ ├── bootstrap-secret.yaml │ ├── memcached-service.yaml │ ├── memcached-statefullset.yaml │ ├── mysql-secret.yaml │ ├── mysql.yaml │ ├── secret.yaml │ └── wordpress.yaml │ └── values.yaml ├── docs ├── _index.md ├── about-stack.md ├── concepts │ ├── _index.md │ └── running-wordpress-on-kubernetes.md ├── config.toml ├── contributing.md ├── how-to │ ├── _index.md │ ├── deploy-wordpress-on-stack.md │ ├── development │ │ ├── _index.md │ │ ├── local-development-with-bedrock.md │ │ └── local-development.md │ └── import-site.md ├── images │ └── stack.png ├── quickstarts │ ├── _index.md │ ├── install-stack-on-gke.md │ └── install-stack-on-minikube.md └── reference │ ├── _index.md │ ├── stack-runtime-environment.md │ └── wordpress-site-helm-chart-values.md ├── git-webhook ├── Makefile ├── README.md ├── main.go └── pkg │ └── webhook │ ├── git │ └── git.go │ ├── webhook.go │ ├── webhook_suite_test.go │ └── webhook_test.go ├── go.mod ├── go.sum ├── hack ├── boilerplate.go.txt └── serve-docs.sh ├── images ├── stack-default-backend │ ├── Dockerfile │ ├── Makefile │ └── rootfs │ │ └── etc │ │ └── mime.types └── stack-git-webhook │ ├── Dockerfile │ └── Makefile ├── load-testing ├── README.md └── locust │ └── charts │ └── locust │ ├── Chart.yaml │ ├── README.md │ ├── tasks │ └── locustfile.py │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── configmap.yaml │ ├── master-deployment.yaml │ ├── master-service.yaml │ └── worker-deployment.yaml │ └── values.yaml ├── presets ├── gke.yaml └── minikube.yaml ├── skaffold.yaml └── terraform ├── examples ├── eks │ └── main.tf └── gke │ └── main.tf └── modules ├── eks ├── iam.tf ├── main.tf ├── modules │ └── eks-node │ │ └── main.tf ├── networking.tf ├── nodes.tf ├── security.tf └── variables.tf └── gke ├── main.tf └── variables.tf /.drone.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: pipeline 3 | name: default 4 | 5 | clone: 6 | disable: true 7 | 8 | workspace: 9 | base: /workspace 10 | path: src/github.com/bitpoke/stack 11 | 12 | steps: 13 | - name: git 14 | image: plugins/git 15 | settings: 16 | depth: 0 17 | tags: true 18 | 19 | - name: install dependencies 20 | image: docker.io/bitpoke/build:v0.8.3 21 | commands: 22 | - make -j4 build.tools 23 | 24 | - name: verify generated code 25 | image: docker.io/bitpoke/build:v0.8.3 26 | commands: 27 | - make -j4 generate 28 | - git diff --exit-code 29 | 30 | - name: lint 31 | image: docker.io/bitpoke/build:v0.8.3 32 | commands: 33 | - make -j4 lint 34 | 35 | - name: test 36 | image: docker.io/bitpoke/build:v0.8.3 37 | environment: 38 | ACK_GINKGO_DEPRECATIONS: "1.16.4" 39 | commands: 40 | - make test 41 | 42 | - name: build 43 | image: docker.io/bitpoke/build:v0.8.3 44 | commands: 45 | - make -j4 build 46 | 47 | services: 48 | - name: docker 49 | image: docker:20.10.8-dind-rootless 50 | environment: 51 | DOCKER_TLS_CERTDIR: "" 52 | 53 | trigger: 54 | ref: 55 | - refs/pull/** 56 | - refs/heads/master 57 | - refs/heads/release-* 58 | # CI related changes SHOULD be prefixed with drone- 59 | - refs/heads/drone-* 60 | 61 | --- 62 | kind: pipeline 63 | name: publish 64 | 65 | trigger: 66 | ref: 67 | - refs/tags/** 68 | 69 | clone: 70 | disable: true 71 | 72 | workspace: 73 | base: /workspace 74 | path: src/github.com/bitpoke/mysql-operator 75 | 76 | steps: 77 | - name: git 78 | image: plugins/git 79 | settings: 80 | depth: 0 81 | tags: true 82 | 83 | - name: build 84 | image: docker.io/bitpoke/build:v0.8.3 85 | commands: 86 | - make -j4 build 87 | 88 | - name: publish 89 | image: docker.io/bitpoke/build:v0.8.3 90 | environment: 91 | DOCKER_USERNAME: bitpokebot 92 | DOCKER_PASSWORD: 93 | from_secret: DOCKER_PASSWORD 94 | SSH_KEY: 95 | from_secret: SSH_KEY 96 | commands: 97 | - /usr/local/bin/setup-credentials-helper.sh 98 | - ssh-keyscan -H github.com > /etc/ssh/ssh_known_hosts 99 | - make publish 100 | 101 | services: 102 | - name: docker 103 | image: docker:20.10.8-dind-rootless 104 | environment: 105 | DOCKER_TLS_CERTDIR: "" 106 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug or a defect 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **What happened**: 11 | 12 | **What you expected to happen**: 13 | 14 | **How to reproduce it (as minimally and precisely as possible)**: 15 | 16 | **Anything else?**: 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Request a new feature or an enhancement 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 15 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - security 8 | - lifecycle/frozen 9 | # Label to use when marking an issue as stale 10 | staleLabel: lifecycle/stale 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | 17 | You can add lifecycle/frozen label to indicate that this issue or PR should 18 | not be auto-closed due to inactivity. 19 | # Comment to post when closing a stale issue. Set to `false` to disable 20 | closeComment: > 21 | This issue has been closed due to lack of activity. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # General files for the project 2 | pkg/* 3 | *.pyc 4 | bin/ 5 | .project 6 | /.bin 7 | /_test/secrets/*.json 8 | *.out 9 | 10 | # OSX leaves these everywhere on SMB shares 11 | ._* 12 | 13 | # OSX trash 14 | .DS_Store 15 | 16 | # Files generated by JetBrains IDEs, e.g. IntelliJ IDEA 17 | .idea/ 18 | *.iml 19 | 20 | # Vscode files 21 | .vscode 22 | 23 | # Emacs save files 24 | *~ 25 | \#*\# 26 | .\#* 27 | 28 | # Vim-related files 29 | [._]*.s[a-w][a-z] 30 | [._]s[a-w][a-z] 31 | *.un~ 32 | Session.vim 33 | .netrwhist 34 | 35 | # Chart dependencies 36 | **/charts/*.tgz 37 | 38 | /example-*.yaml 39 | 40 | # Local .terraform directories 41 | **/.terraform/* 42 | 43 | # .tfstate files 44 | *.tfstate 45 | *.tfstate.* 46 | 47 | # Crash log files 48 | crash.log 49 | 50 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 51 | # .tfvars files are managed as part of configuration and so should be included in 52 | # version control. 53 | # 54 | # example.tfvars 55 | override.auto.tfvars 56 | 57 | # Ignore override files as they are usually used to override resources locally and so 58 | # are not checked in 59 | override.tf 60 | override.tf.json 61 | *_override.tf 62 | *_override.tf.json 63 | 64 | # Include override files you do wish to add to version control using negated pattern 65 | # 66 | # !example_override.tf 67 | 68 | v.yaml 69 | 70 | .work 71 | .cache 72 | _output 73 | 74 | build 75 | 76 | *-packr.go 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Issues are being tracked [here](https://github.com/bitpoke/stack/issues). 2 | We will also gladly accept [pull requests](https://github.com/bitpoke/stack/pulls). 3 | 4 | You can find more detailed information about the contributing process on the [docs page](https://www.bitpoke.io/docs/stack/contributing/). 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Project Setup 2 | PROJECT_NAME := bitpoke-stack 3 | PROJECT_REPO := github.com/bitpoke/stack 4 | 5 | PLATFORMS := linux_amd64 darwin_amd64 6 | 7 | ifneq ($(DRONE_TAG),) 8 | VERSION := $(DRONE_TAG) 9 | endif 10 | 11 | include build/makelib/common.mk 12 | 13 | GO111MODULE = on 14 | GO_PROJECT := $(PROJECT_REPO) 15 | GO_SUBDIRS := default-backend git-webhook 16 | GO_STATIC_PACKAGES := $(GO_PROJECT)/git-webhook $(GO_PROJECT)/default-backend 17 | GO_SUPPORTED_VERSIONS = 1.17 18 | GOFMT_VERSION = 1.17 19 | GOLANGCI_LINT_VERSION = 1.42.1 20 | include build/makelib/golang.mk 21 | include build/makelib/kubebuilder-v3.mk 22 | 23 | IMAGES := stack-default-backend stack-git-webhook 24 | DOCKER_REGISTRY ?= docker.io/bitpoke 25 | include build/makelib/image.mk 26 | 27 | HELM_CHARTS := stack wordpress-site 28 | include build/makelib/helm.mk 29 | .PHONY: .helm.publish 30 | .helm.publish: 31 | @$(INFO) publishing helm charts 32 | @rm -rf $(WORK_DIR)/charts 33 | @git clone -q git@github.com:bitpoke/helm-charts.git $(WORK_DIR)/charts 34 | @cp $(HELM_OUTPUT_DIR)/*.tgz $(WORK_DIR)/charts/docs/ 35 | @git -C $(WORK_DIR)/charts add $(WORK_DIR)/charts/docs/*.tgz 36 | @git -C $(WORK_DIR)/charts commit -q -m "Added $(call list-join,$(COMMA)$(SPACE),$(foreach c,$(HELM_CHARTS),$(c)-v$(HELM_CHART_VERSION)))" 37 | @git -C $(WORK_DIR)/charts push -q 38 | @$(OK) publishing helm charts 39 | .publish.run: .helm.publish 40 | 41 | .PHONY: .helm.add-repos 42 | .helm.add-repos: $(HELM) 43 | @$(HELM) repo add bitpoke https://helm-charts.bitpoke.io 44 | @$(HELM) repo add ingress-nginx https://kubernetes.github.io/ingress-nginx 45 | .helm.lint.stack: .helm.add-repos 46 | 47 | # 48 | # custom targets 49 | # 50 | .PHONY: .collect-crds 51 | .collect-crds: helm.dep |$(HELM) 52 | @$(INFO) collecting CRDs from dependent charts 53 | @rm -rf $(WORK_DIR)/collect-crds deploy/00-crds.yaml 54 | @mkdir -p $(WORK_DIR)/collect-crds 55 | @$(HELM) template --include-crds --output-dir $(WORK_DIR)/collect-crds deploy/charts/stack >/dev/null 56 | @for crd in $(WORK_DIR)/collect-crds/stack/charts/*/crds/* ; do \ 57 | echo "---" >> deploy/00-crds.yaml; \ 58 | cat $${crd} >> deploy/00-crds.yaml; \ 59 | done 60 | @$(OK) collecting CRDs from dependent charts 61 | .generate.run: .collect-crds 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bitpoke Stack 2 | **Open-Source WordPress Infrastructure on Kubernetes** 3 | 4 | For a more thorough documentation check [the hosted docs](https://www.bitpoke.io/docs/stack/). 5 | 6 | 7 | ## Components 8 | 9 | * [WordPress Operator](http://github.com/bitpoke/wordpress-operator) 10 | * [MySQL Operator](http://github.com/bitpoke/mysql-operator) 11 | * [Prometheus Operator](https://github.com/coreos/prometheus-operator) 12 | * [Nginx Controller](https://github.com/kubernetes/ingress-nginx) 13 | * [Cert Manager](https://github.com/jetstack/cert-manager) 14 | 15 | ## Project status 16 | The project is actively maintained and developed and has reached stable beta 17 | state. Check the complete list of releases 18 | [here](https://github.com/bitpoke/stack/releases). The Bitpoke Stack currently 19 | runs on Google Cloud Kubernetes Engine and we also have a documented viable 20 | deployment flow for Minikube/Docker on Mac/Docker on Windows. 21 | 22 | ## Installation 23 | 24 | Add the Bitpoke helm charts repo: 25 | 26 | ``` 27 | helm repo add bitpoke https://helm-charts.bitpoke.io 28 | helm repo update 29 | ``` 30 | 31 | ## Requirements 32 | 33 | ### cert-manager 34 | [Cert Manager](https://github.com/jetstack/cert-manager) is a requirement for 35 | Stack because it depends on certificates in order to setup it's the environment. 36 | The official installation documentation can be found 37 | [here](https://cert-manager.io/docs/installation/helm/). 38 | 39 | ```bash 40 | export CERT_MANAGER_VERSION=1.6.1 41 | 42 | helm repo add jetstack https://charts.jetstack.io 43 | helm repo update 44 | 45 | kubectl create namespace cert-manager 46 | kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v${CERT_MANAGER_VERSION}/cert-manager.crds.yaml 47 | 48 | helm install \ 49 | cert-manager jetstack/cert-manager \ 50 | --namespace cert-manager \ 51 | --version v${CERT_MANAGER_VERSION} 52 | ``` 53 | 54 | ### Kubernetes Application CRD 55 | 56 | The Stack also depends on the [Kubernetes 57 | Application](https://github.com/kubernetes-sigs/application) CRD. The following 58 | command will install the application CRD. You may also want (this is optional) 59 | to install the Application Controller, see the install 60 | [guide](https://github.com/kubernetes-sigs/application/blob/master/docs/quickstart.md). 61 | 62 | ``` 63 | kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/application/c8e2959e57a02b3877b394984a288f9178977d8b/config/crd/bases/app.k8s.io_applications.yaml 64 | ``` 65 | 66 | ### Install CRDs 67 | For convenience we collect all necessary CRDs in one place so you can simply install them. 68 | 69 | ``` 70 | export STACK_VERSION=0.12.4 71 | kubectl apply -f https://raw.githubusercontent.com/bitpoke/stack/v${STACK_VERSION}/deploy/00-crds.yaml 72 | ``` 73 | 74 | ### Install Stack 75 | 76 | The rest of the Stack can be installed using helm 3. There are many possible 77 | platforms where it can be installed. We provide presets for production and 78 | development environments. 79 | 80 | #### GKE 81 | 82 | For GKE is required to have at least three nodes for running components and also 83 | have some room for deploying a site. For testing out and playground `e1-small` 84 | should suffice. 85 | 86 | ```bash 87 | export STACK_VERSION=0.12.4 88 | helm install \ 89 | stack bitpoke/stack \ 90 | --create-namespace \ 91 | --namespace bitpoke-stack \ 92 | --version v${STACK_VERSION} \ 93 | -f https://raw.githubusercontent.com/bitpoke/stack/v${STACK_VERSION}/presets/gke.yaml 94 | ``` 95 | 96 | 97 | #### Minikube/Docker for Mac 98 | Ensure a larger Minikube with eg, `minikube start --cpus 4 --memory 8192` to 99 | provide a working local environment. 100 | 101 | ``` 102 | export STACK_VERSION=0.12.4 103 | helm install \ 104 | stack bitpoke/stack \ 105 | --create-namespace \ 106 | --namespace bitpoke-stack \ 107 | --version v${STACK_VERSION} \ 108 | -f https://raw.githubusercontent.com/bitpoke/stack/v${STACK_VERSION}/presets/minikube.yaml 109 | ``` 110 | 111 | ## Usage 112 | 113 | ### Deploying a site 114 | ``` 115 | export STACK_VERSION=0.12.4 116 | helm install \ 117 | mysite bitpoke/wordpress-site \ 118 | --version v${STACK_VERSION} \ 119 | --set 'site.domains[0]=www.example.com' 120 | ``` 121 | 122 | ## Contributing 123 | Issues are being tracked [here](https://github.com/bitpoke/stack/issues). 124 | We also gladly accept [pull requests](https://github.com/bitpoke/stack/pulls). 125 | 126 | You can find more detailed information about the contributing process on the 127 | [docs page](https://www.bitpoke.io/docs/stack/contributing/). 128 | -------------------------------------------------------------------------------- /build/.drone.yml: -------------------------------------------------------------------------------- 1 | kind: pipeline 2 | name: default 3 | 4 | clone: 5 | disable: true 6 | 7 | workspace: 8 | base: /workspace 9 | path: src/github.com/bitpoke/build 10 | 11 | steps: 12 | - name: clone 13 | image: plugins/git 14 | settings: 15 | depth: 0 16 | tags: true 17 | 18 | - name: install dependencies 19 | image: docker.io/bitpoke/build:v0.8.0 20 | commands: 21 | - make -j4 build.tools 22 | 23 | - name: build 24 | pull: true 25 | image: docker.io/bitpoke/build:v0.8.0 26 | commands: 27 | - dockerize -wait http://docker:2375/_ping -timeout 30s 28 | - make V=1 build 29 | 30 | - name: publish 31 | image: docker.io/bitpoke/build:v0.8.0 32 | commands: 33 | - /usr/local/bin/setup-credentials-helper.sh 34 | - make publish 35 | environment: 36 | DOCKER_USERNAME: bitpokebot 37 | DOCKER_PASSWORD: 38 | from_secret: DOCKER_PASSWORD 39 | when: 40 | ref: 41 | - refs/heads/master-* 42 | - refs/heads/release-* 43 | 44 | services: 45 | - name: docker 46 | image: docker:20.10.8-dind-rootless 47 | environment: 48 | DOCKER_TLS_CERTDIR: "" 49 | 50 | trigger: 51 | ref: 52 | - refs/pull/** 53 | - refs/heads/** 54 | -------------------------------------------------------------------------------- /build/.gitignore: -------------------------------------------------------------------------------- 1 | _output 2 | .cache 3 | .work 4 | /bin/ 5 | -------------------------------------------------------------------------------- /build/Makefile: -------------------------------------------------------------------------------- 1 | # Project Setup 2 | PROJECT_NAME := presslabs-build 3 | PROJECT_REPO := github.com/presslabs/build 4 | 5 | PLATFORMS = linux_amd64 6 | 7 | # this is required, since by default, the makelib files are under a ./build path prefix, but here, 8 | # they are under root 9 | ROOT_DIR := $(abspath $(shell cd ./ && pwd -P)) 10 | 11 | include makelib/common.mk 12 | 13 | IMAGES ?= build 14 | DOCKER_REGISTRY ?= docker.io/bitpoke 15 | 16 | include makelib/image.mk 17 | -------------------------------------------------------------------------------- /build/README.md: -------------------------------------------------------------------------------- 1 | # build 2 | bitpoke GNU make based build system 3 | 4 | ## Goals 5 | 6 | 1. Allow building locally the same way the project is build on CI 7 | 2. Provide a sane test, build, publish flow 8 | 3. Provide stable toolchain for building (eg. pinned tool versions) 9 | 4. Enables caching for speeding up builds. 10 | 11 | ## Quickstart 12 | 13 | ```sh 14 | git subtree add -P build https://github.com/bitpoke/build.git 15 | 16 | cat < Makefile 17 | # Project Setup 18 | PROJECT_NAME := mysql-operator 19 | PROJECT_REPO := github.com/bitpoke/mysql-operator 20 | 21 | include build/makelib/common.mk 22 | ``` 23 | 24 | ## Usage 25 | 26 | ``` 27 | Usage: make [make-options] [options] 28 | 29 | Common Targets: 30 | build Build source code and other artifacts for host platform. 31 | build.all Build source code and other artifacts for all platforms. 32 | build.tools Install the required build tools. 33 | clean Remove all files created during the build. 34 | distclean Remove all files created during the build including cached tools. 35 | generate Run code generation tools. 36 | fmt Run code auto-formatting tools. 37 | lint Run lint and code analysis tools. 38 | test Runs unit tests. 39 | e2e Runs end-to-end integration tests. 40 | translate Collect translation strings and post-process the .pot/.po files. 41 | help Show this help info. 42 | ``` 43 | 44 | ## Acknowledgement 45 | 46 | This work is based on https://github.com/upbound/build. 47 | -------------------------------------------------------------------------------- /build/bin/po-diff.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2019 Pressinfra SRL 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | export ROOT_DIR=$(dirname "${BASH_SOURCE}")/../.. 22 | 23 | # Install tools we need, but only from vendor/... 24 | cd "${ROOT_DIR}" 25 | 26 | diff -u \ 27 | <(grep -E '^msgid' "${1}" | sort | sed 's/msgid[[:space:]]*//g') \ 28 | <(grep -E '^msgid' "${2}" | sort | sed 's/msgid[[:space:]]*//g') 29 | 30 | exit 0 31 | -------------------------------------------------------------------------------- /build/images/build/Makefile: -------------------------------------------------------------------------------- 1 | PLATFORMS := linux_amd64 2 | include ../../makelib/common.mk 3 | 4 | # this is required, since by default, the makelib files are under a ./build path prefix, but here, 5 | # they are under root 6 | ROOT_DIR := $(abspath $(shell cd ./../.. && pwd -P)) 7 | 8 | IMAGE = $(BUILD_REGISTRY)/build-$(ARCH) 9 | CACHE_IMAGES = $(IMAGE) 10 | include ../../makelib/image.mk 11 | 12 | img.build: 13 | @$(INFO) docker build $(IMAGE) $(IMAGE_PLATFORM) 14 | @cp -La . $(IMAGE_TEMP_DIR) 15 | @mkdir -p $(IMAGE_TEMP_DIR)/rootfs 16 | @docker buildx build $(BUILD_ARGS) \ 17 | --platform $(IMAGE_PLATFORM) \ 18 | -t $(IMAGE) \ 19 | --build-arg ARCH=$(ARCH) \ 20 | $(IMAGE_TEMP_DIR) 21 | @$(OK) docker build $(IMAGE) 22 | -------------------------------------------------------------------------------- /build/images/build/build-scripts/install-packages.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2019 Pressinfra 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | apt-get update 22 | apt-get install -yy -q --no-install-recommends "${@}" 23 | apt-get clean 24 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 25 | -------------------------------------------------------------------------------- /build/images/build/root/build/rsyncd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2016 The Upbound Authors. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | VOLUME=${VOLUME:-/volume} 18 | ALLOW=${ALLOW:-192.168.0.0/16 172.16.0.0/12 10.0.0.0/8} 19 | OWNER=${OWNER:-nobody} 20 | GROUP=${GROUP:-nogroup} 21 | 22 | if [[ "${GROUP}" != "nogroup" && "${GROUP}" != "root" ]]; then 23 | groupadd -g ${GROUP} rsync 24 | fi 25 | 26 | if [[ "${OWNER}" != "nobody" && "${OWNER}" != "root" ]]; then 27 | groupadd -u ${OWNER} -G rsync rsync 28 | fi 29 | 30 | chown "${OWNER}:${GROUP}" "${VOLUME}" 31 | 32 | [ -f /etc/rsyncd.conf ] || cat < /etc/rsyncd.conf 33 | uid = ${OWNER} 34 | gid = ${GROUP} 35 | use chroot = yes 36 | log file = /dev/stdout 37 | reverse lookup = no 38 | [volume] 39 | hosts deny = * 40 | hosts allow = ${ALLOW} 41 | read only = false 42 | path = ${VOLUME} 43 | comment = volume 44 | EOF 45 | 46 | for dir in ${MKDIRS}; do 47 | mkdir -p ${dir} 48 | chown "${OWNER}:${GROUP}" ${dir} 49 | done 50 | 51 | exec /usr/bin/rsync --no-detach --daemon --config /etc/rsyncd.conf "$@" 52 | -------------------------------------------------------------------------------- /build/images/build/root/build/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2016 The Upbound Authors. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | ARGS="$@" 18 | if [ $# -eq 0 ]; then 19 | ARGS=/bin/bash 20 | fi 21 | 22 | BUILDER_USER=${BUILDER_USER:-upbound} 23 | BUILDER_GROUP=${BUILDER_GROUP:-upbound} 24 | BUILDER_UID=${BUILDER_UID:-1000} 25 | BUILDER_GID=${BUILDER_GID:-1000} 26 | 27 | groupadd -o -g $BUILDER_GID $BUILDER_GROUP 2> /dev/null 28 | useradd -o -m -g $BUILDER_GID -u $BUILDER_UID $BUILDER_USER 2> /dev/null 29 | echo "$BUILDER_USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers 30 | export HOME=/home/${BUILDER_USER} 31 | echo "127.0.0.1 $(cat /etc/hostname)" >> /etc/hosts 32 | [[ -S /var/run/docker.sock ]] && chmod 666 /var/run/docker.sock 33 | chown -R $BUILDER_UID:$BUILDER_GID $HOME 34 | exec chpst -u :$BUILDER_UID:$BUILDER_GID ${ARGS} 35 | -------------------------------------------------------------------------------- /build/images/build/root/usr/local/bin/setup-credentials-helper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | : "${GOOGLE_CREDENTIALS:="$(cat "$PLUGIN_GOOGLE_CREDENTIALS_FILE" 2>/dev/null)"}" 3 | : "${GOOGLE_CLOUD_PROJECT:="$PLUGIN_GOOGLE_CLOUD_PROJECT"}" 4 | : "${GOOGLE_CLOUD_CLUSTER:="$PLUGIN_GOOGLE_CLOUD_CLUSTER"}" 5 | : "${GOOGLE_CLOUD_ZONE:="$PLUGIN_GOOGLE_CLOUD_ZONE"}" 6 | : "${SSH_KEY:="$PLUGIN_SSH_KEY"}" 7 | : "${DOCKER_USERNAME:="$PLUGIN_DOCKER_USERNAME"}" 8 | : "${DOCKER_PASSWORD:="$PLUGIN_DOCKER_PASSWORD"}" 9 | : "${DOCKER_REGISTRY:="${PLUGIN_DOCKER_REGISTRY:-docker.io}"}" 10 | 11 | DOCKER_REGISTRY_HOST="$(echo "${DOCKER_REGISTRY}" | awk 'BEGIN{ FS="/" }{print $1}')" 12 | 13 | export PATH="$CI_WORKSPACE/bin:$PATH" 14 | 15 | require_param() { 16 | declare name="$1" 17 | local env_name 18 | env_name="$(echo "$name" | tr /a-z/ /A-Z/)" 19 | if [ -z "${!env_name}" ] ; then 20 | echo "You must define \"$name\" parameter or define $env_name environment variable" >&2 21 | exit 2 22 | fi 23 | } 24 | 25 | require_google_credentials() { 26 | if [ -z "$GOOGLE_CREDENTIALS" ] ; then 27 | echo "You must define \"google_credentials_file\" parameter or define GOOGLE_CREDENTIALS environment variable" >&2 28 | exit 2 29 | fi 30 | } 31 | 32 | run() { 33 | echo "+" "$@" 34 | "$@" 35 | } 36 | 37 | if [ -n "$DOCKER_PASSWORD" ] ; then 38 | require_param DOCKER_USERNAME 39 | echo "+ docker login $DOCKER_REGISTRY_HOST -u $DOCKER_USERNAME" 40 | echo "$DOCKER_PASSWORD" | docker login "$DOCKER_REGISTRY_HOST" -u "$DOCKER_USERNAME" --password-stdin 41 | fi 42 | 43 | if [ -n "$GOOGLE_CREDENTIALS" ] ; then 44 | echo "$GOOGLE_CREDENTIALS" > /run/google-credentials.json 45 | run gcloud auth activate-service-account --quiet --key-file=/run/google-credentials.json 46 | run gcloud auth configure-docker --quiet 47 | fi 48 | 49 | if [ -n "$GOOGLE_CLOUD_PROJECT" ] ; then 50 | run gcloud config set project "$GOOGLE_CLOUD_PROJECT" 51 | fi 52 | 53 | if [ -n "$GOOGLE_CLOUD_CLUSTER" ] ; then 54 | require_google_credentials 55 | require_param "google_cloud_project" 56 | require_param "google_cloud_zone" 57 | 58 | run gcloud container clusters get-credentials "$GOOGLE_CLOUD_CLUSTER" --project "$GOOGLE_CLOUD_PROJECT" --zone "$GOOGLE_CLOUD_ZONE" 59 | # Display kubernetees versions (usefull for debugging) 60 | run kubectl version 61 | fi 62 | 63 | if [ -n "$SSH_KEY" ] ; then 64 | require_param "home" 65 | test -d "$HOME/.ssh" || mkdir -p "$HOME/.ssh" 66 | echo "$SSH_KEY" > "$HOME/.ssh/id_rsa" 67 | chmod 0400 "$HOME/.ssh/id_rsa" 68 | echo "Installed ssh key into $HOME/.ssh/id_rsa" 69 | run ssh-keygen -y -f "$HOME/.ssh/id_rsa" 70 | fi 71 | 72 | if [[ -n "${GIT_USER}" && -n "${GIT_PASSWORD}" ]] ; then 73 | git config --global user.email "${GIT_EMAIL:-bot@bitpoke.cloud}" 74 | git config --global user.name "$GIT_USER" 75 | 76 | cat <> ~/.netrc 77 | machine ${GIT_HOST:-github.com} 78 | login ${GIT_USER} 79 | password ${GIT_PASSWORD} 80 | EOF 81 | fi 82 | -------------------------------------------------------------------------------- /build/images/build/root/usr/local/bin/xvfb-chrome: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2016 The Upbound Authors. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | _kill_procs() { 18 | kill -TERM $chrome 19 | wait $chrome 20 | } 21 | 22 | # Setup a trap to catch SIGTERM and relay it to child processes 23 | trap _kill_procs SIGTERM 24 | 25 | # Start Chrome inside xvfb 26 | xvfb-run -a -s "-screen 0 1920x1080x24 -nolisten tcp" /opt/google/chrome/chrome --no-sandbox $@ & 27 | chrome=$! 28 | 29 | wait $chrome 30 | -------------------------------------------------------------------------------- /build/makelib/cache.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Pressinfra SRL. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __CACHE_MAKEFILE__ 16 | __CACHE_MAKEFILE__ := included 17 | 18 | RCLONE_BIN ?= RCLONE_VERSION=true rclone 19 | RCLONE_ARGS ?= -q --config /dev/null 20 | 21 | ifeq ($(CACHE_BACKEND),) 22 | $(error You must define CACHE_BACKEND before adding cache support. See format at https://rclone.org/docs/#backend-path-to-dir) 23 | endif 24 | 25 | CACHE_COMPRESSION ?= gzip 26 | 27 | ifneq ($(DRONE_PULL_REQUEST),) 28 | CACHE_NAME ?= $(PROJECT_NAME)-pr$(DRONE_PULL_REQUEST)-cache 29 | else ifneq ($(DRONE_TAG),) 30 | CACHE_NAME ?= $(PROJECT_NAME)-$(DRONE_TAG)-cache 31 | else 32 | CACHE_NAME ?= $(PROJECT_NAME)-$(BRANCH_NAME)-cache 33 | endif 34 | 35 | 36 | RCLONE := $(RCLONE_BIN) $(RCLONE_ARGS) 37 | 38 | ifeq ($(CACHE_COMPRESSION),gzip) 39 | TAR_COMPRESS_ARGS += -z 40 | CACHE_EXTENSION_SUFFIX := .gz 41 | endif 42 | 43 | CACHE_FILE := $(CACHE_NAME).tar$(CACHE_EXTENSION_SUFFIX) 44 | 45 | .PHONY: cache.store cache.restore 46 | 47 | cache.store: 48 | @$(INFO) storing cache $(CACHE_FILE) into $(CACHE_BACKEND) 49 | @$(RCLONE) mkdir $(CACHE_BACKEND) || $(FAIL) 50 | @tar -C $(CACHE_DIR) $(TAR_COMPRESS_ARGS) -cf - ./ | $(RCLONE) rcat $(CACHE_BACKEND)/$(CACHE_FILE) || $(FAIL) 51 | @$(OK) cache store 52 | 53 | cache.restore: |$(CACHE_DIR) 54 | @$(INFO) restoring cache from $(CACHE_BACKEND)/$(CACHE_FILE) 55 | @$(RCLONE) cat $(CACHE_BACKEND)/$(CACHE_FILE) | tar -C $(CACHE_DIR) $(TAR_COMPRESS_ARGS) -x \ 56 | && $(OK) cache restore \ 57 | || $(WARN) cache restore failed 58 | 59 | endif # __CACHE_MAKEFILE__ 60 | -------------------------------------------------------------------------------- /build/makelib/gcp.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Pressinfra SRL. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __GOOGLE_CLOUD_MAKEFILE__ 16 | __GOOGLE_CLOUD_MAKEFILE__ := included 17 | 18 | ifeq ($(origin GOOGLE_CLOUD_PROJECT),undefined) 19 | ifneq ($(GCLOUD_PROJECT),) 20 | GOOGLE_CLOUD_PROJECT := $(GCLOUD_PROJECT) 21 | else 22 | GOOGLE_CLOUD_PROJECT := $(shell gcloud config get-value project) 23 | endif 24 | endif 25 | 26 | ifeq ($(GOOGLE_CLOUD_PROJECT),) 27 | $(error Could not determine current Google Cloud Project. Set the GOOGLE_CLOUD_PROJECT environment variable or set with `gcloud config`) 28 | else 29 | export GOOGLE_CLOUD_PROJECT 30 | endif 31 | 32 | endif # __GOOGLE_CLOUD_MAKEFILE__ 33 | -------------------------------------------------------------------------------- /build/makelib/gettext.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2016 The Upbound Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __GETTEXT_MAKEFILE__ 16 | __GETTEXT_MAKEFILE__ := included 17 | 18 | # ==================================================================================== 19 | # Options 20 | 21 | # ==================================================================================== 22 | # Translations 23 | 24 | # The list of languages to generate translations for 25 | LANGUAGES ?= 26 | 27 | LOCALES_DIR ?= $(ROOT_DIR)/locales 28 | $(LOCALES_DIR): 29 | @mkdir -p $(LOCALES_DIR) 30 | 31 | ifeq ($(LANGUAGES),) 32 | $(error You must specify the LANGUAGES variable in order to handle translations) 33 | endif 34 | 35 | ifeq ($(HOSTOS),darwin) 36 | MSGFMT = /usr/local/opt/gettext/bin/msgfmt 37 | MSGMERGE = /usr/local/opt/gettext/bin/msgmerge 38 | else 39 | MSGFMT = msgfmt 40 | MSGMERGE = msgmerge 41 | endif 42 | 43 | PO_FILES := $(shell find $(LOCALES_DIR) -name '*.po') 44 | POT_FILES := $(shell find $(LOCALES_DIR) -mindepth 1 -maxdepth 1 -name '*.pot') 45 | 46 | # lint the code 47 | $(eval $(call common.target,translations)) 48 | 49 | gettext.lint: 50 | @$(INFO) msgfmt check 51 | $(foreach p,$(PO_FILES),@$(MSGFMT) -c $(p) || $(FAIL) ${\n}) 52 | @$(OK) msgfmt check 53 | 54 | .gettext.merge: 55 | @$(INFO) msgmerge 56 | $(foreach l,$(LANGUAGES),@mkdir -p $(LOCALES_DIR)/$(l) || $(FAIL) ${\n}) 57 | $(foreach pot,$(POT_FILES),$(foreach l,$(LANGUAGES), \ 58 | @touch $(LOCALES_DIR)/$(l)/$(basename $(notdir $(pot))).po || $(FAIL) ${\n} \ 59 | @$(MSGMERGE) -q --no-wrap --sort-output --no-fuzzy-matching --lang=$(l) -U "$(LOCALES_DIR)/$(l)/$(basename $(notdir $(pot))).po" "$(pot)" || $(FAIL) ${\n} \ 60 | )) 61 | @find $(LOCALES_DIR) -name '*.po~' -delete 62 | @find $(LOCALES_DIR) -name '*.pot~' -delete 63 | @$(OK) msgmerge 64 | 65 | .gettext.build: 66 | @$(INFO) copying translations 67 | @rm -rf $(OUTPUT_DIR)/locales 68 | @cp -a $(LOCALES_DIR) $(OUTPUT_DIR)/locales 69 | @$(OK) copying translations 70 | 71 | .PHONY: gettext.lint .gettext.build .gettext.merge 72 | 73 | # ==================================================================================== 74 | # Common Targets 75 | .lint.run: gettext.lint 76 | 77 | .translations.run: .gettext.merge 78 | 79 | .build.code: .gettext.build 80 | 81 | endif # __GETTEXT_MAKEFILE__ 82 | -------------------------------------------------------------------------------- /build/makelib/git-publish.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2019 The Pressinfra Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __GIT_PUBLISH_MAKEFILE__ 16 | __GIT_PUBLISH_MAKEFILE__ := included 17 | 18 | # ==================================================================================== 19 | # Options 20 | 21 | PUBLISH_BRANCH ?= master 22 | PUBLISH_PREFIX ?= / 23 | PUBLISH_TAGS ?= true 24 | 25 | ifeq ($(PUBLISH_DIRS),) 26 | PUBLISH_DIR ?= $(CURDIR:$(abspath $(ROOT_DIR))/%=%) 27 | endif 28 | 29 | PUBLISH_WORK_BRANCH := build/split-$(COMMIT_HASH)/$(PUBLISH_DIR) 30 | PUBLISH_WORK_DIR := $(WORK_DIR)/git-publish/$(PUBLISH_DIR) 31 | PUBLISH_GIT := git -C $(PUBLISH_WORK_DIR) 32 | 33 | GIT_MERGE_ARGS ?= --ff-only 34 | GIT_SUBTREE_MERGE_ARGS ?= --squash 35 | ifeq ($(PUBLISH_TAGS),true) 36 | GIT_PUSH_ARGS := --follow-tags 37 | endif 38 | 39 | PUBLISH_DIRS ?= $(PUBLISH_DIR) 40 | 41 | # ==================================================================================== 42 | # git publish targets 43 | 44 | git.urlize = $(patsubst %,https://%,$(patsubst %.git,%,$(patsubst https://%,%,$(patsubst git@github.com:%,https://github.com/%,$(1))))) 45 | git.workbranch = build/split-$(COMMIT_HASH)/$(1) 46 | 47 | # 1 publish directory 48 | define git.publish 49 | 50 | $(ROOT_DIR)/.git/refs/heads/$(call git.workbranch,$(1)): 51 | @$(INFO) git subtree split $(1) 52 | @cd $(ROOT_DIR) && git subtree split -q -P $(1) -b $(call git.workbranch,$(1)) $(COMMIT_HASH) 53 | @$(OK) git subtree split $(1) 54 | .PHONY: .git.build.artifacts.$(1) 55 | .git.build.artifacts.$(1): $(ROOT_DIR)/.git/refs/heads/$(call git.workbranch,$(1)) 56 | .git.build.artifacts: .git.build.artifacts.$(1) 57 | 58 | .PHONY: .git.clean.$(1) 59 | .git.clean.$(1): 60 | @cd $(ROOT_DIR) && git branch -D $(call git.workbranch,$(1)) || true 61 | .git.clean: .git.clean.$(1) 62 | 63 | .PHONY: .do.git.publish.$(1) 64 | .do.git.publish.$(1): |$(ROOT_DIR)/.git/refs/heads/$(call git.workbranch,$(1)) 65 | @$(MAKE) -C $(1) .git.publish 66 | 67 | endef 68 | 69 | ifeq ($(filter-out $(PUBLISH_DIR),$(PUBLISH_DIRS)),) 70 | .git.publish: |$(ROOT_DIR)/.git/refs/heads/$(PUBLISH_WORK_BRANCH) 71 | @$(INFO) Publishing $(1) to $(PUBLISH_REPO)@$(PUBLISH_BRANCH) under $(PUBLISH_PREFIX) 72 | @rm -rf $(PUBLISH_WORK_DIR) && mkdir -p $(PUBLISH_WORK_DIR) 73 | @$(PUBLISH_GIT) init -q 74 | @$(PUBLISH_GIT) remote add origin $(PUBLISH_REPO) 75 | @$(PUBLISH_GIT) remote add upstream $(ROOT_DIR)/.git 76 | @$(PUBLISH_GIT) fetch -q upstream +refs/heads/$(PUBLISH_WORK_BRANCH): 77 | @$(PUBLISH_GIT) checkout -q -b $(PUBLISH_BRANCH) 78 | @set -e; cd $(PUBLISH_WORK_DIR); if git ls-remote --heads origin | grep -q refs/heads/$(PUBLISH_BRANCH); then \ 79 | $(PUBLISH_GIT) fetch -q origin +refs/heads/$(PUBLISH_BRANCH): ;\ 80 | $(PUBLISH_GIT) reset -q --hard origin/$(PUBLISH_BRANCH) ;\ 81 | $(PUBLISH_GIT) branch -q -u origin/$(PUBLISH_BRANCH) ;\ 82 | fi 83 | ifeq ($(PUBLISH_PREFIX),/) 84 | @set -e; \ 85 | $(PUBLISH_GIT) merge -q $(GIT_MERGE_ARGS) \ 86 | -m "Merge '$(PUBLISH_DIR)' from $(patsubst https://github.com/%,%,$(call git.urlize,$(REMOTE_URL)))@$(COMMIT_HASH)" \ 87 | upstream/$(PUBLISH_WORK_BRANCH) ;\ 88 | if [ "$(PUBLISH_TAGS)" == "true" ] ; then \ 89 | for t in $(TAGS) ; do \ 90 | $(PUBLISH_GIT) tag -a -m "$$t" $$t ;\ 91 | done ;\ 92 | fi 93 | else 94 | @set -e; \ 95 | if [ -d "$(PUBLISH_WORK_DIR)/$(PUBLISH_PREFIX)" ] ; then \ 96 | $(PUBLISH_GIT) subtree -q merge -P $(PUBLISH_PREFIX) $(GIT_SUBTREE_MERGE_ARGS) \ 97 | -m "Merge '$(PUBLISH_DIR)' from $(patsubst https://github.com/%,%,$(call git.urlize,$(REMOTE_URL)))@$(COMMIT_HASH)" \ 98 | upstream/$(PUBLISH_WORK_BRANCH) ;\ 99 | else \ 100 | $(PUBLISH_GIT) subtree add -q -P $(PUBLISH_PREFIX) $(GIT_SUBTREE_MERGE_ARGS) \ 101 | -m "Add '$(PUBLISH_DIR)' from $(patsubst https://github.com/%,%,$(call git.urlize,$(REMOTE_URL)))@$(COMMIT_HASH)" \ 102 | $(ROOT_DIR)/.git $(PUBLISH_WORK_BRANCH) ;\ 103 | fi 104 | endif 105 | @$(PUBLISH_GIT) push -u origin $(GIT_PUSH_ARGS) $(PUBLISH_BRANCH) 106 | @$(OK) Published $(1) to $(PUBLISH_REPO)@$(PUBLISH_BRANCH) 107 | else 108 | .git.publish: $(foreach d,$(PUBLISH_DIRS),.do.git.publish.$(d)) 109 | endif 110 | 111 | $(foreach d,$(PUBLISH_DIRS), $(eval $(call git.publish,$(d)))) 112 | 113 | .PHONY: .git.clean .git.build.artifacts .git.publish 114 | 115 | # ==================================================================================== 116 | # Common Targets 117 | 118 | # if PUBLISH_DIRS is defined the invoke publish for each dir 119 | ifneq ($(filter-out $(PUBLISH_DIR),$(PUBLISH_DIRS)),) 120 | 121 | .publish.init: .git.build.artifacts 122 | clean: .git.clean 123 | 124 | # only publish for master and release branches 125 | # also, if publishing for tags is enabled, 126 | # publish if the current commit is a tag 127 | ifneq ($(filter master release-%,$(BRANCH_NAME)),) 128 | .publish.run: $(addprefix .do.git.publish.,$(PUBLISH_DIRS)) 129 | else ifeq ($(PUBLISH_TAGS),true) 130 | ifneq ($(TAGS),) 131 | .publish.run: $(addprefix .do.git.publish.,$(PUBLISH_DIRS)) 132 | endif 133 | endif 134 | 135 | else # assume this .mk file is being included for a single dir 136 | 137 | ifeq ($(PUBLISH_REPO),) 138 | $(error You must specify the PUBLISH_REPO variable in order to handle git publishing) 139 | endif 140 | 141 | .publish.init: .git.build.artifacts 142 | clean: .git.clean 143 | 144 | endif # PUBLISH_DIRS 145 | 146 | 147 | endif # __GIT_PUBLISH_MAKEFILE__ 148 | -------------------------------------------------------------------------------- /build/makelib/helm.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2016 The Upbound Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __HELM_MAKEFILE__ 16 | __HELM_MAKEFILE__ := included 17 | 18 | include $(COMMON_SELF_DIR)/k8s-tools.mk 19 | 20 | # the charts directory 21 | HELM_CHARTS_DIR ?= deploy/charts 22 | 23 | HELM_CHARTS ?= $(patsubst $(HELM_CHARTS_DIR)/%,%,$(shell find $(HELM_CHARTS_DIR) -mindepth 1 -maxdepth 1 -type d)) 24 | 25 | # the base url where helm charts are published 26 | # ifeq ($(HELM_BASE_URL),) 27 | # $(error the variable HELM_BASE_URL must be set prior to including helm.mk) 28 | # endif 29 | 30 | # the charts output directory 31 | HELM_OUTPUT_DIR ?= $(OUTPUT_DIR)/charts 32 | 33 | # the helm index file 34 | HELM_INDEX := $(HELM_OUTPUT_DIR)/index.yaml 35 | 36 | # helm home 37 | HELM_HOME := $(abspath $(WORK_DIR)/helm) 38 | HELM_CHARTS_WORK_DIR := $(abspath $(WORK_DIR)/charts) 39 | export HELM_HOME 40 | 41 | # remove the leading `v` for helm chart versions 42 | HELM_CHART_VERSION := $(VERSION:v%=%) 43 | HELM_APP_VERSION ?= $(VERSION) 44 | 45 | # ==================================================================================== 46 | # Tools install targets 47 | 48 | HELM_VERSION := 3.6.3 49 | HELM_DOWNLOAD_URL := https://get.helm.sh/helm-v$(HELM_VERSION)-$(HOSTOS)-$(HOSTARCH).tar.gz 50 | $(eval $(call tool.download.tar.gz,helm,$(HELM_VERSION),$(HELM_DOWNLOAD_URL))) 51 | 52 | # ==================================================================================== 53 | # Helm Targets 54 | 55 | $(HELM_HOME): $(HELM) 56 | @mkdir -p $(HELM_HOME) 57 | 58 | $(HELM_OUTPUT_DIR): 59 | @mkdir -p $(HELM_OUTPUT_DIR) 60 | 61 | $(HELM_CHARTS_WORK_DIR): 62 | @mkdir -p $(HELM_CHARTS_WORK_DIR) 63 | 64 | define helm.chart 65 | 66 | .helm.package.init.$(1): $(HELM_CHARTS_WORK_DIR) 67 | @rm -rf $(HELM_CHARTS_WORK_DIR)/$(1) 68 | @cp -a $(abspath $(HELM_CHARTS_DIR)/$(1)) $(HELM_CHARTS_WORK_DIR)/$(1) 69 | .helm.package.run.$(1): $(HELM_OUTPUT_DIR) $(HELM_HOME) 70 | @$(INFO) helm package $(1) $(HELM_CHART_VERSION) 71 | @$(HELM) package --version $(HELM_CHART_VERSION) --app-version $(HELM_APP_VERSION) -d $(HELM_OUTPUT_DIR) $(HELM_CHARTS_WORK_DIR)/$(1) 72 | @$(OK) helm package $(1) $(HELM_CHART_VERSION) 73 | .helm.package.done.$(1): ; @: 74 | .helm.package.$(1): 75 | @$(MAKE) .helm.package.init.$(1) 76 | @$(MAKE) .helm.package.run.$(1) 77 | @$(MAKE) .helm.package.done.$(1) 78 | 79 | .PHONY: .helm.package.init.$(1) .helm.package.run.$(1) .helm.package.done.$(1) .helm.package.$(1) 80 | 81 | $(HELM_OUTPUT_DIR)/$(1)-$(HELM_CHART_VERSION).tgz: $(HELM_HOME) $(HELM_OUTPUT_DIR) $(shell find $(HELM_CHARTS_DIR)/$(1) -type f) 82 | 83 | .PHONY: .helm.lint.$(1) 84 | .helm.lint.$(1): $(HELM_HOME) 85 | @$(INFO) helm lint $(1) 86 | @rm -rf $(abspath $(HELM_CHARTS_DIR)/$(1)/charts) 87 | @$(HELM) dependency build $(abspath $(HELM_CHARTS_DIR)/$(1)) 88 | @$(HELM) lint $(abspath $(HELM_CHARTS_DIR)/$(1)) $(HELM_CHART_LINT_ARGS_$(1)) --strict || $$(FAIL) 89 | @$(OK) helm lint $(1) 90 | 91 | helm.lint: .helm.lint.$(1) 92 | 93 | .PHONY: .helm.dep.$(1) 94 | .helm.dep.$(1): $(HELM_HOME) 95 | @$(INFO) helm dep $(1) $(HELM_CHART_VERSION) 96 | @$(HELM) dependency update $(abspath $(HELM_CHARTS_DIR)/$(1)) 97 | @$(OK) helm dep $(1) $(HELM_CHART_VERSION) 98 | 99 | helm.dep: .helm.dep.$(1) 100 | 101 | $(HELM_INDEX): .helm.package.$(1) 102 | endef 103 | $(foreach p,$(HELM_CHARTS),$(eval $(call helm.chart,$(p)))) 104 | 105 | $(HELM_INDEX): $(HELM_HOME) $(HELM_OUTPUT_DIR) 106 | @$(INFO) helm index 107 | @$(HELM) repo index $(HELM_OUTPUT_DIR) 108 | @$(OK) helm index 109 | 110 | helm.build: $(HELM_INDEX) 111 | 112 | .helm.clean: 113 | @rm -fr $(HELM_OUTPUT_DIR) 114 | 115 | .PHONY: helm.lint helm.build helm.dep .helm.clean 116 | 117 | # ==================================================================================== 118 | # Common Targets 119 | 120 | .build.check: helm.lint 121 | .build.artifacts: helm.build 122 | .lint.run: helm.lint 123 | clean: .helm.clean 124 | 125 | # ==================================================================================== 126 | # Special Targets 127 | 128 | define HELM_HELPTEXT 129 | Helm Targets: 130 | helm.dep Upgrade charts dependencies 131 | 132 | endef 133 | export HELM_HELPTEXT 134 | 135 | .PHONY: .helm.help 136 | .helm.help: 137 | @echo "$$HELM_HELPTEXT" 138 | 139 | .help: .helm.help 140 | 141 | endif # __HELM_MAKEFILE__ 142 | -------------------------------------------------------------------------------- /build/makelib/k8s-tools.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2016 The Upbound Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __K8S_TOOLS_MAKEFILE__ 16 | __K8S_TOOLS_MAKEFILE__ := included 17 | 18 | # ==================================================================================== 19 | # tools 20 | 21 | # kubectl download and install 22 | KUBECTL_VERSION ?= 1.19.13 23 | KUBECTL_DOWNLOAD_URL ?= https://storage.googleapis.com/kubernetes-release/release/v$(KUBECTL_VERSION)/bin/$(HOSTOS)/$(HOSTARCH)/kubectl 24 | $(eval $(call tool.download,kubectl,$(KUBECTL_VERSION),$(KUBECTL_DOWNLOAD_URL))) 25 | 26 | # kind download and install 27 | KIND_VERSION ?= 0.11.1 28 | KIND_DOWNLOAD_URL ?= https://github.com/kubernetes-sigs/kind/releases/download/v$(KIND_VERSION)/kind-$(HOSTOS)-$(HOSTARCH) 29 | $(eval $(call tool.download,kind,$(KIND_VERSION),$(KIND_DOWNLOAD_URL))) 30 | 31 | # kind download and install 32 | KUSTOMIZE_VERSION ?= 4.2.0 33 | KUSTOMIZE_DOWNLOAD_URL ?=https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v$(KUSTOMIZE_VERSION)/kustomize_v$(KUSTOMIZE_VERSION)_$(HOST_PLATFORM).tar.gz 34 | $(eval $(call tool.download.tar.gz,kustomize,$(KUSTOMIZE_VERSION),$(KUSTOMIZE_DOWNLOAD_URL),kustomize,0)) 35 | 36 | endif # __K8S_TOOLS_MAKEFILE__ 37 | 38 | -------------------------------------------------------------------------------- /build/makelib/kubebuilder-v1.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Pressinfra Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __KUBEBUILDERV1_MAKEFILE__ 16 | __KUBEBUILDERV1_MAKEFILE__ := included 17 | 18 | # ==================================================================================== 19 | # Options 20 | 21 | KUBEBUILDER_VERSION ?= 1.0.8 22 | KUBEBUILDER := $(TOOLS_HOST_DIR)/kubebuilder-$(KUBEBUILDER_VERSION) 23 | 24 | CRD_DIR ?= config/crds 25 | API_DIR ?= pkg/apis 26 | 27 | # these are use by the kubebuilder test harness 28 | 29 | TEST_ASSET_KUBE_APISERVER := $(KUBEBUILDER)/kube-apiserver 30 | TEST_ASSET_ETCD := $(KUBEBUILDER)/etcd 31 | TEST_ASSET_KUBECTL := $(KUBEBUILDER)/kubectl 32 | export TEST_ASSET_KUBE_APISERVER TEST_ASSET_ETCD TEST_ASSET_KUBECTL 33 | 34 | # ==================================================================================== 35 | # Setup environment 36 | 37 | include $(COMMON_SELF_DIR)/golang.mk 38 | 39 | # ==================================================================================== 40 | # tools 41 | 42 | # kubebuilder download and install 43 | $(KUBEBUILDER): 44 | @echo ${TIME} ${BLUE}[TOOL]${CNone} installing kubebuilder $(KUBEBUILDER_VERSION) 45 | @mkdir -p $(TOOLS_HOST_DIR)/tmp || $(FAIL) 46 | @curl -fsSL https://github.com/kubernetes-sigs/kubebuilder/releases/download/v$(KUBEBUILDER_VERSION)/kubebuilder_$(KUBEBUILDER_VERSION)_$(GOHOSTOS)_$(GOHOSTARCH).tar.gz | tar -xz -C $(TOOLS_HOST_DIR)/tmp || $(FAIL) 47 | @mv $(TOOLS_HOST_DIR)/tmp/kubebuilder_$(KUBEBUILDER_VERSION)_$(GOHOSTOS)_$(GOHOSTARCH)/bin $(KUBEBUILDER) || $(FAIL) 48 | @rm -fr $(TOOLS_HOST_DIR)/tmp 49 | @$(OK) installing kubebuilder $(KUBEBUILDER_VERSION) 50 | 51 | $(eval $(call tool.go.vendor.install,controller-gen,sigs.k8s.io/controller-tools/cmd/controller-gen)) 52 | 53 | # ==================================================================================== 54 | # Kubebuilder Targets 55 | 56 | $(eval $(call common.target,kubebuilder.manifests)) 57 | 58 | # Generate manifests e.g. CRD, RBAC etc. 59 | .do.kubebuilder.manifests: $(CONTROLLER_GEN) 60 | @$(INFO) Generating Kubebuilder manifests 61 | @# first delete the CRD_DIR, to remove the CRDs of types that no longer exist 62 | @rm -rf $(CRD_DIR) 63 | @$(CONTROLLER_GEN) all 64 | @$(CONTROLLER_GEN) webhook 65 | @$(OK) Generating Kubebuilder manifests 66 | 67 | .PHONY: .do.kubebuilder.manifests 68 | .kubebuilder.manifests.run: .do.kubebuilder.manifests 69 | 70 | # ==================================================================================== 71 | # Common Targets 72 | 73 | build.tools: $(KUBEBUILDER) 74 | .test.init: $(KUBEBUILDER) 75 | go.test.unit: $(KUBEBUILDER) 76 | 77 | # ==================================================================================== 78 | # Special Targets 79 | 80 | define KUBEBULDERV1_HELPTEXT 81 | Kubebuilder Targets: 82 | kubebuilder.manifests Generates Kubernetes custom resources manifests (e.g. CRDs RBACs, ...) 83 | 84 | endef 85 | export KUBEBULDERV1_HELPTEXT 86 | 87 | .kubebuilder.help: 88 | @echo "$$KUBEBULDERV1_HELPTEXT" 89 | 90 | .help: .kubebuilder.help 91 | .generate.run: kubebuilder.manifests 92 | 93 | .PHONY: .kubebuilder.help kubebuilder.manifests 94 | 95 | endif # __KUBEBUILDERV1_MAKEFILE__ 96 | -------------------------------------------------------------------------------- /build/makelib/kubebuilder-v2.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Pressinfra Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __KUBEBUILDERV2_MAKEFILE__ 16 | __KUBEBUILDERV2_MAKEFILE__ := included 17 | 18 | # ==================================================================================== 19 | # Options 20 | 21 | KUBEBUILDER_VERSION ?= 2.3.2 22 | KUBEBUILDER := $(TOOLS_HOST_DIR)/kubebuilder-$(KUBEBUILDER_VERSION) 23 | 24 | CRD_DIR ?= config/crds 25 | API_DIR ?= pkg/apis 26 | RBAC_DIR ?= config/rbac 27 | 28 | BOILERPLATE_FILE ?= ./hack/boilerplate.go.txt 29 | 30 | GEN_CRD_OPTIONS ?= crd:trivialVersions=true 31 | GEN_RBAC_OPTIONS ?= rbac:roleName=manager-role 32 | GEN_WEBHOOK_OPTIONS ?= 33 | GEN_OBJECT_OPTIONS ?= object:headerFile=$(BOILERPLATE_FILE) 34 | GEN_OUTPUTS_OPTIONS ?= output:crd:artifacts:config=$(CRD_DIR) output:rbac:artifacts:config=$(RBAC_DIR) 35 | 36 | # these are use by the kubebuilder test harness 37 | 38 | TEST_ASSET_KUBE_APISERVER := $(KUBEBUILDER)/kube-apiserver 39 | TEST_ASSET_ETCD := $(KUBEBUILDER)/etcd 40 | TEST_ASSET_KUBECTL := $(KUBEBUILDER)/kubectl 41 | export TEST_ASSET_KUBE_APISERVER TEST_ASSET_ETCD TEST_ASSET_KUBECTL 42 | 43 | # ==================================================================================== 44 | # Setup environment 45 | 46 | include $(COMMON_SELF_DIR)/golang.mk 47 | 48 | # ==================================================================================== 49 | # tools 50 | 51 | # kubebuilder download and install 52 | $(KUBEBUILDER): 53 | @echo ${TIME} ${BLUE}[TOOL]${CNone} installing kubebuilder $(KUBEBUILDER_VERSION) 54 | @mkdir -p $(TOOLS_HOST_DIR)/tmp || $(FAIL) 55 | @curl -fsSL https://github.com/kubernetes-sigs/kubebuilder/releases/download/v$(KUBEBUILDER_VERSION)/kubebuilder_$(KUBEBUILDER_VERSION)_$(GOHOSTOS)_$(GOHOSTARCH).tar.gz | tar -xz -C $(TOOLS_HOST_DIR)/tmp || $(FAIL) 56 | @mv $(TOOLS_HOST_DIR)/tmp/kubebuilder_$(KUBEBUILDER_VERSION)_$(GOHOSTOS)_$(GOHOSTARCH)/bin $(KUBEBUILDER) || $(FAIL) 57 | @rm -fr $(TOOLS_HOST_DIR)/tmp 58 | @$(OK) installing kubebuilder $(KUBEBUILDER_VERSION) 59 | 60 | CONTROLLER_GEN_VERSION ?= 0.6.1 61 | CONTROLLER_GEN_URL ?= sigs.k8s.io/controller-tools/cmd/controller-gen 62 | $(eval $(call tool.go.install,controller-gen,v$(CONTROLLER_GEN_VERSION),$(CONTROLLER_GEN_URL))) 63 | 64 | # ==================================================================================== 65 | # Kubebuilder Targets 66 | 67 | $(eval $(call common.target,kubebuilder.manifests)) 68 | 69 | # Generate manifests e.g. CRD, RBAC etc. 70 | .do.kubebuilder.manifests: $(CONTROLLER_GEN) 71 | @$(INFO) Generating Kubebuilder manifests 72 | @# first delete the CRD_DIR, to remove the CRDs of types that no longer exist 73 | 74 | @$(CONTROLLER_GEN) paths="$(call list-join,;,$(foreach p,$(GO_SUBDIRS),./$(p)/... ))" $(GEN_CRD_OPTIONS) $(GEN_RBAC_OPTIONS) $(GEN_WEBHOOK_OPTIONS) $(GEN_OBJECT_OPTIONS) $(GEN_OUTPUTS_OPTIONS) 75 | 76 | @$(OK) Generating Kubebuilder manifests 77 | 78 | .PHONY: .do.kubebuilder.manifests 79 | .kubebuilder.manifests.run: .do.kubebuilder.manifests 80 | 81 | # ==================================================================================== 82 | # Common Targets 83 | 84 | build.tools: $(KUBEBUILDER) 85 | .test.init: $(KUBEBUILDER) 86 | go.test.unit: $(KUBEBUILDER) 87 | 88 | # ==================================================================================== 89 | # Special Targets 90 | 91 | define KUBEBULDERV2_HELPTEXT 92 | Kubebuilder Targets: 93 | kubebuilder.manifests Generates Kubernetes custom resources manifests (e.g. CRDs RBACs, ...) 94 | 95 | endef 96 | export KUBEBULDERV2_HELPTEXT 97 | 98 | .kubebuilder.help: 99 | @echo "$$KUBEBULDERV2_HELPTEXT" 100 | 101 | .help: .kubebuilder.help 102 | go.generate: kubebuilder.manifests 103 | 104 | .PHONY: .kubebuilder.help kubebuilder.manifests 105 | 106 | endif # __KUBEBUILDERV2_MAKEFILE__ 107 | -------------------------------------------------------------------------------- /build/makelib/kubebuilder-v3.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Pressinfra Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __KUBEBUILDERV3_MAKEFILE__ 16 | __KUBEBUILDERV3_MAKEFILE__ := included 17 | 18 | include $(COMMON_SELF_DIR)/golang.mk 19 | 20 | # ==================================================================================== 21 | # Options 22 | 23 | CRD_DIR ?= config/crd/bases 24 | RBAC_DIR ?= config/rbac 25 | 26 | BOILERPLATE_FILE ?= hack/boilerplate.go.txt 27 | 28 | CONTROLLER_GEN_CRD_OPTIONS ?= crd output:crd:artifacts:config=$(CRD_DIR) 29 | CONTROLLER_GEN_RBAC_OPTIONS ?= rbac:roleName=manager-role output:rbac:artifacts:config=$(RBAC_DIR) 30 | CONTROLLER_GEN_WEBHOOK_OPTIONS ?= webhook 31 | CONTROLLER_GEN_OBJECT_OPTIONS ?= object:headerFile=$(BOILERPLATE_FILE) 32 | CONTROLLER_GEN_PATHS ?= $(foreach t,$(GO_SUBDIRS),paths=./$(t)/...) 33 | 34 | KUBEBUILDER_ASSETS_VERSION ?= 1.19.2 35 | KUBEBUILDER_ASSETS = $(CACHE_DIR)/kubebuilder/k8s/$(KUBEBUILDER_ASSETS_VERSION)-$(HOSTOS)-$(HOSTARCH) 36 | export KUBEBUILDER_ASSETS 37 | 38 | # ==================================================================================== 39 | # tools 40 | 41 | # setup-envtest download and install 42 | SETUP_ENVTEST_VERSION ?= 0.0.0-20211206022232-3ffc700bc2a3 43 | SETUP_ENVTEST_DOWNLOAD_URL ?= sigs.k8s.io/controller-runtime/tools/setup-envtest 44 | $(eval $(call tool.go.install,setup-envtest,v$(SETUP_ENVTEST_VERSION),$(SETUP_ENVTEST_DOWNLOAD_URL))) 45 | 46 | # kubebuilder download and install 47 | KUBEBUILDER_VERSION ?= 3.2.0 48 | KUBEBUILDER_DOWNLOAD_URL ?= https://github.com/kubernetes-sigs/kubebuilder/releases/download/v$(KUBEBUILDER_VERSION)/kubebuilder_$(HOST_PLATFORM) 49 | $(eval $(call tool.download,kubebuilder,$(KUBEBUILDER_VERSION),$(KUBEBUILDER_DOWNLOAD_URL))) 50 | 51 | # controller-gen download and install 52 | CONTROLLER_GEN_VERSION ?= 0.7.0 53 | CONTROLLER_GEN_DOWNLOAD_URL ?= sigs.k8s.io/controller-tools/cmd/controller-gen 54 | $(eval $(call tool.go.install,controller-gen,v$(CONTROLLER_GEN_VERSION),$(CONTROLLER_GEN_DOWNLOAD_URL))) 55 | 56 | build.tools: |$(KUBEBUILDER_ASSETS) 57 | $(KUBEBUILDER_ASSETS): $(SETUP_ENVTEST) 58 | @echo ${TIME} ${BLUE}[TOOL]${CNone} installing kubebuilder assets for Kubernetes $(KUBEBUILDER_ASSETS_VERSION) 59 | @$(SETUP_ENVTEST) --bin-dir=$(CACHE_DIR)/kubebuilder --os=$(HOSTOS) --arch=$(HOSTARCH) use $(KUBEBUILDER_ASSETS_VERSION) 60 | @$(OK) installing kubebuilder assets for Kubernetes $(KUBEBUILDER_ASSETS_VERSION) 61 | 62 | # ==================================================================================== 63 | # Kubebuilder Targets 64 | 65 | $(eval $(call common.target,kubebuilder.manifests)) 66 | # Generate manifests e.g. CRD, RBAC etc. 67 | .do.kubebuilder.manifests: $(CONTROLLER_GEN) 68 | @$(INFO) Generating Kubernetes \(CRDs, RBAC, WebhookConfig, etc.\) manifests 69 | @$(CONTROLLER_GEN) \ 70 | $(CONTROLLER_GEN_CRD_OPTIONS) \ 71 | $(CONTROLLER_GEN_RBAC_OPTIONS) \ 72 | $(CONTROLLER_CONTROLLER_GEN_WEBHOOK_OPTIONS) \ 73 | $(CONTROLLER_GEN_PATHS) 74 | @$(OK) Generating Kubernetes \(CRDs, RBAC, WebhookConfig, etc.\) manifests 75 | .PHONY: .do.kubebuilder.manifests 76 | .kubebuilder.manifests.run: .do.kubebuilder.manifests 77 | 78 | $(eval $(call common.target,kubebuilder.code)) 79 | # Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. 80 | .do.kubebuilder.code: $(CONTROLLER_GEN) 81 | @$(INFO) Generating DeepCopy, DeepCopyInto, and DeepCopyObject code 82 | @$(CONTROLLER_GEN) \ 83 | $(CONTROLLER_GEN_OBJECT_OPTIONS) \ 84 | $(CONTROLLER_GEN_PATHS) 85 | @$(OK) Generating DeepCopy, DeepCopyInto, and DeepCopyObject code 86 | .PHONY: .do.kubebuilder.code 87 | .kubebuilder.code.run: .do.kubebuilder.code 88 | 89 | # ==================================================================================== 90 | # Common Targets 91 | 92 | .test.init: |$(KUBEBUILDER_ASSETS) 93 | go.test.unit: |$(KUBEBUILDER_ASSETS) 94 | go.generate: kubebuilder.code 95 | .generate.init: .kubebuilder.manifests.init 96 | .generate.run: .kubebuilder.manifests.run 97 | .generate.done: .kubebuilder.manifests.done 98 | 99 | # ==================================================================================== 100 | # Special Targets 101 | 102 | define KUBEBULDERV3_HELPTEXT 103 | Kubebuilder Targets: 104 | kubebuilder.manifests Generates Kubernetes custom resources manifests (e.g. CRDs RBACs, ...) 105 | kubebuilder.code Generates DeepCopy, DeepCopyInto, and DeepCopyObject code 106 | 107 | endef 108 | export KUBEBULDERV3_HELPTEXT 109 | 110 | .kubebuilder.help: 111 | @echo "$$KUBEBULDERV3_HELPTEXT" 112 | 113 | .help: .kubebuilder.help 114 | .PHONY: .kubebuilder.help 115 | 116 | endif # __KUBEBUILDERV3_MAKEFILE__ 117 | -------------------------------------------------------------------------------- /build/makelib/nodejs.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2016 The Upbound Authors. All rights reserved. 2 | # Copyright 2019 The Pressinfra Authors. All rights reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | ifndef __NODEJS_MAKEFILE__ 17 | __NODEJS_MAKEFILE__ := included 18 | 19 | # ==================================================================================== 20 | # Options 21 | 22 | # supported node versions 23 | NODE_SUPPORTED_VERSIONS ?= 10|12 24 | NODE := node 25 | 26 | SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 27 | 28 | # The location of node application within this git repo. 29 | NODE_ROOT_DIR ?= $(SELF_DIR)/../.. 30 | 31 | # The location of node application source code, relative to the NODE_ROOT_DIR 32 | NODE_SRC_DIR ?= src 33 | 34 | NODE_ENV ?= production 35 | export NODE_ENV 36 | 37 | YARN := yarn 38 | YARN_MODULE_DIR := $(NODE_ROOT_DIR)/node_modules 39 | YARN_BIN_DIR := $(abspath $(NODE_ROOT_DIR)/node_modules/.bin) 40 | YARN_PACKAGE_FILE := $(NODE_ROOT_DIR)/package.json 41 | YARN_PACKAGE_LOCK_FILE := $(NODE_ROOT_DIR)/yarn.lock 42 | 43 | NODE_SRCS ?= $(abspath $(YARN_PACKAGE_FILE)) $(abspath $(YARN_PACKAGE_LOCK_FILE)) $(shell find $(abspath $(NODE_ROOT_DIR)/$(NODE_SRC_DIR)) -type f | grep -v '__tests__') 44 | 45 | YARN_CACHE_FOLDER ?= $(CACHE_DIR)/yarn 46 | export YARN_CACHE_FOLDER 47 | 48 | YARN_OUTDIR ?= $(OUTPUT_DIR)/yarn 49 | export YARN_OUTDIR 50 | 51 | EXTEND_ESLINT ?= true 52 | export EXTEND_ESLINT 53 | 54 | ESLINT_OUTPUT_DIR := $(OUTPUT_DIR)/lint/eslint 55 | 56 | # ==================================================================================== 57 | # NodeJS Tools Targets 58 | 59 | ESLINT := $(YARN_BIN_DIR)/eslint 60 | $(ESLINT): |yarn.install 61 | build.tools: $(ESLINT) 62 | 63 | # ==================================================================================== 64 | # YARN Targets 65 | 66 | .PHONY: .yarn.init 67 | .yarn.init: 68 | @if ! `$(NODE) --version | grep -q -E '^v($(NODE_SUPPORTED_VERSIONS))\.'`; then \ 69 | $(ERR) unsupported node version. Please install one of the following supported version: '$(NODE_SUPPORTED_VERSIONS)' ;\ 70 | exit 1 ;\ 71 | fi 72 | 73 | # some node packages like node-sass require platform/arch specific install. we need 74 | # to run yarn for each platform. As a result we track a stamp file per host 75 | YARN_INSTALL_STAMP := $(YARN_MODULE_DIR)/.yarn.install.$(HOST_PLATFORM).stamp 76 | 77 | # only run "yarn" if the package.json has changed 78 | $(YARN_INSTALL_STAMP): $(YARN_PACKAGE_FILE) $(YARN_PACKAGE_LOCK_FILE) 79 | @echo ${TIME} $(BLUE)[TOOL]$(CNone) yarn install 80 | @cd $(NODE_ROOT_DIR); $(YARN) --silent --frozen-lockfile --non-interactive --production=false || $(FAIL) 81 | @touch $(YARN_INSTALL_STAMP) 82 | @$(OK) yarn install 83 | 84 | yarn.install: .yarn.init $(YARN_INSTALL_STAMP) 85 | 86 | .yarn.clean: 87 | @rm -rf $(YARN_MODULE_DIR) 88 | 89 | .PHONY: yarn.install .yarn.clean 90 | 91 | # ==================================================================================== 92 | # NodeJS Targets 93 | 94 | $(ESLINT_OUTPUT_DIR)/stylecheck.xml: $(ESLINT) $(NODE_SRCS) 95 | @$(INFO) eslint 96 | @mkdir -p $(ESLINT_OUTPUT_DIR) 97 | @cd $(NODE_ROOT_DIR); $(ESLINT) '$(NODE_SRC_DIR)/**/*.{ts,tsx}' --color 98 | @touch $@ 99 | @$(OK) eslint 100 | 101 | js.lint: $(ESLINT_OUTPUT_DIR)/stylecheck.xml 102 | 103 | js.lint.fix: 104 | @$(INFO) eslint fix 105 | @cd $(NODE_ROOT_DIR); $(ESLINT) '$(NODE_SRC_DIR)/**/*.{ts,tsx}' --color 106 | @$(OK) eslint fix 107 | 108 | # common target for building a node js project 109 | $(eval $(call common.target,js.build)) 110 | 111 | # common target for testing a node js project 112 | $(eval $(call common.target,js.test)) 113 | 114 | .PHONY: js.lint js.lint.fix 115 | 116 | # ==================================================================================== 117 | # Common Targets 118 | 119 | .build.init: .yarn.init .js.build.init 120 | .build.check: js.lint 121 | .build.code: .js.build.run 122 | .build.done: .js.build.done 123 | 124 | .test.init: .js.test.init 125 | .test.run: .js.test.run 126 | .test.done: .js.test.done 127 | 128 | clean: .yarn.clean 129 | 130 | .lint.run: js.lint 131 | .fmt.run: js.lint.fix 132 | 133 | # ==================================================================================== 134 | # Special Targets 135 | 136 | define NODEJS_HELPTEXT 137 | nodejs Targets: 138 | yarn.install Installs dependencies in a make friendly manner. 139 | 140 | endef 141 | export NODEJS_HELPTEXT 142 | 143 | .PHONY: .js.help 144 | .js.help: 145 | @echo "$$NODEJS_HELPTEXT" 146 | 147 | .help: .js.help 148 | 149 | endif # __NODEJS_MAKEFILE__ 150 | -------------------------------------------------------------------------------- /build/makelib/php.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2020 The Pressinfra Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __PHP_MAKEFILE__ 16 | __PHP_MAKEFILE__ := included 17 | 18 | # ==================================================================================== 19 | # Options 20 | 21 | # supported php versions 22 | PHP_SUPPORTED_VERSIONS ?= 7.3|7.4 23 | PHP := php 24 | 25 | SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 26 | 27 | # The location of php application within this git repo. 28 | PHP_ROOT_DIR ?= $(SELF_DIR)/../.. 29 | 30 | # The location of php application source code, relative to the PHP_ROOT_DIR 31 | PHP_SRC_DIR ?= src 32 | 33 | COMPOSER_VERSION ?= 1.10.5 34 | COMPOSER_DOWNLOAD_URL ?= https://getcomposer.org/download/$(COMPOSER_VERSION)/composer.phar 35 | $(eval $(call tool.download,composer,$(COMPOSER_VERSION),$(COMPOSER_DOWNLOAD_URL))) 36 | 37 | COMPOSER_INSTALL_ARGS ?= --prefer-dist --classmap-authoritative 38 | COMPOSER_VENDOR_DIR := $(PHP_ROOT_DIR)/vendor 39 | COMPOSER_BIN_DIR := $(abspath $(PHP_ROOT_DIR)/vendor/bin) 40 | COMPOSER_JSON_FILE := $(PHP_ROOT_DIR)/composer.json 41 | COMPOSER_LOCK_FILE := $(PHP_ROOT_DIR)/composer.lock 42 | 43 | COMPOSER_CACHE_DIR := $(CACHE_DIR)/composer 44 | export COMPOSER_CACHE_DIR 45 | 46 | # ==================================================================================== 47 | # PHP Tools Targets 48 | 49 | PHPUNIT := $(COMPOSER_BIN_DIR)/phpunit 50 | $(PHPUNIT): |composer.install 51 | build.tools: $(PHPUNIT) 52 | 53 | PHPCS := $(COMPOSER_BIN_DIR)/phpcs 54 | $(PHPCS): |composer.install 55 | build.tools: $(PHPCS) 56 | 57 | PHPCBF := $(COMPOSER_BIN_DIR)/phpcbf 58 | $(PHPCBF): |composer.install 59 | build.tools: $(PHPCBF) 60 | 61 | # ==================================================================================== 62 | # Composer targets 63 | 64 | .PHONY: .composer.init 65 | .composer.init: 66 | @if ! `$(PHP) --version | grep -q -E '^PHP ($(PHP_SUPPORTED_VERSIONS))\.'`; then \ 67 | $(ERR) unsupported PHP version. Please install one of the following supported version: '$(PHP_SUPPORTED_VERSIONS)' ;\ 68 | exit 1 ;\ 69 | fi 70 | $(COMPOSER): .composer.init 71 | 72 | COMPOSER_INSTALL_STAMP := $(COMPOSER_VENDOR_DIR)/.composer.install.stamp 73 | 74 | # only run "composer" if the composer.json has changed 75 | $(COMPOSER_INSTALL_STAMP): $(COMPOSER) $(COMPOSER_JSON_FILE) $(COMPOSER_LOCK_FILE) 76 | @echo ${TIME} $(BLUE)[TOOL]$(CNone) composer install 77 | @cd $(PHP_ROOT_DIR); $(COMPOSER) install --no-interaction || $(FAIL) 78 | @touch $(COMPOSER_INSTALL_STAMP) 79 | @$(OK) composer install 80 | 81 | composer.install: $(COMPOSER_INSTALL_STAMP) 82 | 83 | composer.update: $(COMPOSER) 84 | @echo ${TIME} $(BLUE)[TOOL]$(CNone) composer update 85 | @cd $(PHP_ROOT_DIR); $(COMPOSER) update || $(FAIL) 86 | @touch $(COMPOSER_INSTALL_STAMP) 87 | @$(OK) composer install 88 | 89 | 90 | .composer.clean: 91 | @rm -rf $(COMPOSER_VENDOR_DIR) 92 | 93 | .PHONY: composer.install composer.update .composer.clean 94 | 95 | # ==================================================================================== 96 | # PHP Targets 97 | 98 | php.lint: 99 | @$(INFO) phpcs $(PHP_SRC_DIR) 100 | @cd $(PHP_ROOT_DIR); $(PHPCS) $(PHP_SRC_DIR) 101 | @$(OK) phpcs $(PHP_SRC_DIR) 102 | 103 | php.lint.fix: 104 | @$(INFO) phpcbf $(PHP_SRC_DIR) 105 | @cd $(PHP_ROOT_DIR); $(PHPCBF) $(PHP_SRC_DIR) 106 | @$(OK) phpcbf $(PHP_SRC_DIR) 107 | .PHONY: php.lint php.lint.fix 108 | 109 | # common target for building a php project 110 | $(eval $(call common.target,php.build)) 111 | 112 | # common target for testing a php project 113 | $(eval $(call common.target,php.test)) 114 | 115 | .PHONY: .do.php.test 116 | .php.test.run: .do.php.test 117 | .do.php.test: $(PHPUNIT) 118 | @$(INFO) phpunit 119 | @$(PHPUNIT) $(PHPUNIT_ARGS) 120 | @$(OK) phpunit 121 | 122 | 123 | # ==================================================================================== 124 | # Common Targets 125 | 126 | .build.init: .composer.init 127 | .build.check: php.lint 128 | .build.code: .php.build.run 129 | .build.done: .php.build.done 130 | 131 | .test.init: .php.test.init 132 | .test.run: .php.test.run 133 | .test.done: .php.test.done 134 | 135 | clean: .composer.clean 136 | 137 | .lint.run: php.lint 138 | .fmt.run: php.lint.fix 139 | 140 | # ==================================================================================== 141 | # Special Targets 142 | 143 | define PHP_HELPTEXT 144 | PHP Targets: 145 | composer.install Installs dependencies in a make friendly manner. 146 | composer.update Updates dependencies in a make friendly manner. 147 | 148 | endef 149 | export PHP_HELPTEXT 150 | 151 | .PHONY: .php.help 152 | .php.help: 153 | @echo "$$PHP_HELPTEXT" 154 | 155 | .help: .php.help 156 | 157 | endif # __PHP_MAKEFILE__ 158 | -------------------------------------------------------------------------------- /build/makelib/protobuf.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2016 The Upbound Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __PROTOBUF_MAKEFILE__ 16 | __PROTOBUF_MAKEFILE__ := included 17 | 18 | # ==================================================================================== 19 | # Setup protobuf environment 20 | 21 | PROTOBUF_DIR ?= proto 22 | PROTOBUF_FILES ?= $(sort $(shell find $(PROTOBUF_DIR) -name "*.proto")) 23 | 24 | PROTOC_VERSION ?= 3.10.1 25 | 26 | # ==================================================================================== 27 | # Tools install targets 28 | 29 | PROTOTOOL_VERSION ?= 1.9.0 30 | PROTOTOOL_CACHE_PATH := $(TOOLS_HOST_DIR)/prototool 31 | export PROTOTOOL_CACHE_PATH 32 | 33 | PROTOTOOL_DOWNLOAD_URL ?= https://github.com/uber/prototool/releases/download/v$(PROTOTOOL_VERSION)/prototool-$(HOSTOS)-x86_64 34 | $(eval $(call tool.download,prototool,$(PROTOTOOL_VERSION),$(PROTOTOOL_DOWNLOAD_URL))) 35 | 36 | # ==================================================================================== 37 | # Protobuf Targets 38 | 39 | build.tools: .pb.prototool.cache.update 40 | .pb.prototool.cache.update: $(PROTOTOOL_CACHE_PATH)/.update 41 | $(PROTOTOOL_CACHE_PATH)/.update: $(PROTOBUF_DIR)/prototool.yaml |$(PROTOTOOL) 42 | @echo ${TIME} $(BLUE)[TOOL]$(CNone) updating prototool cache 43 | @$(PROTOTOOL) cache update $(PROTOBUF_DIR) 44 | @touch $@ 45 | @$(OK) updating prototool cache 46 | 47 | .pb.init: .pb.prototool.cache.update 48 | 49 | pb.lint: $(PROTOTOOL) 50 | @$(INFO) prototool lint 51 | @$(PROTOTOOL) lint $(PROTOBUF_DIR) || $(FAIL) 52 | @$(OK) prototool lint 53 | 54 | pb.fmt.verify: $(PROTOTOOL) 55 | @$(INFO) prototool format verify 56 | @$(PROTOTOOL) format -l $(PROTOBUF_DIR) || $(FAIL) 57 | @$(OK) prototool format verify 58 | 59 | pb.fmt: $(PROTOTOOL) 60 | @$(INFO) prototool format 61 | @$(PROTOTOOL) format -w $(PROTOBUF_DIR) || $(FAIL) 62 | @$(OK) prototool format 63 | 64 | # expose as common target so that we can hook in other generators 65 | # eg. https://github.com/dcodeIO/protobuf.js 66 | $(eval $(call common.target,pb.generate)) 67 | 68 | .pb.prototool.generate: 69 | @$(INFO) prototool generate 70 | @$(PROTOTOOL) generate $(PROTOBUF_DIR) 71 | @$(OK) prototool generate 72 | 73 | .pb.generate.init: .pb.init 74 | .pb.generate.run: .pb.prototool.generate 75 | 76 | .PHONY: .go.init go.lint go.fmt go.generate .pb.clean .pb.distclean 77 | .PHONY: .pb.prototool.cache.update .pb.prototool.generate 78 | 79 | # ==================================================================================== 80 | # Common Targets 81 | 82 | .lint.init: .pb.init 83 | .lint.run: pb.fmt.verify pb.lint 84 | 85 | .fmt.run: pb.fmt 86 | 87 | .generate.init: .pb.init 88 | .generate.run: pb.generate 89 | 90 | # ==================================================================================== 91 | # Special Targets 92 | 93 | define PROTOBUF_HELPTEXT 94 | Protobuf Targets: 95 | pb.generate Generate code from protobuf files in $(PROTOBUF_DIR) 96 | 97 | endef 98 | export PROTOBUF_HELPTEXT 99 | 100 | .PHONY: .go.help 101 | .pb.help: 102 | @echo "$$PROTOBUF_HELPTEXT" 103 | 104 | .help: .pb.help 105 | 106 | 107 | # # we use a consistent version of gofmt even while running different go compilers. 108 | # # see https://github.com/golang/go/issues/26397 for more details 109 | # PROTOC_VERSION ?= 3.10.1 110 | # PROTOC_DOWNLOAD_URL ?= https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-$(HOSTOS)-$(HOSTARCH).zip 111 | # $(eval $(call tool.download.zip,protoc,$(PROTOC_VERSION),$(PROTOC_DOWNLOAD_URL),bin/protoc)) 112 | 113 | endif # __PROTOBUF_MAKEFILE__ 114 | -------------------------------------------------------------------------------- /build/makelib/react.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2019 The Pressinfra Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __REACT_MAKEFILE__ 16 | __REACT_MAKEFILE__ := included 17 | 18 | SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 19 | include $(SELF_DIR)/nodejs.mk 20 | 21 | # ==================================================================================== 22 | # Options 23 | 24 | REACT_OUTPUT_DIR ?= $(OUTPUT_DIR)/react 25 | 26 | REACT_LOCALE_PREFIX ?= messages 27 | 28 | # ==================================================================================== 29 | # React app Targets 30 | 31 | REACT := $(YARN_BIN_DIR)/react-scripts --max_old_space_size=4096 32 | $(REACT): yarn.install 33 | build.tools: $(REACT) 34 | 35 | $(REACT_OUTPUT_DIR)/index.html: $(REACT) $(NODE_SRCS) 36 | @$(INFO) react-scripts build 37 | @cd $(NODE_ROOT_DIR); $(REACT) build 38 | @mkdir -p $(REACT_OUTPUT_DIR) 39 | @rm -rf $(REACT_OUTPUT_DIR) 40 | @mv $(NODE_ROOT_DIR)/build $(REACT_OUTPUT_DIR) 41 | @$(OK) react-scripts build 42 | react.build: $(REACT_OUTPUT_DIR)/index.html 43 | 44 | react.test: $(REACT) 45 | @$(INFO) react-scripts test 46 | @cd $(NODE_ROOT_DIR); TZ='UTC' $(REACT) test --env=jsdom --verbose --colors 47 | @$(OK) react-scripts test 48 | 49 | react.run: $(REACT) 50 | @cd $(NODE_ROOT_DIR); NODE_ENV=development BROWSER=none $(REACT) start 51 | 52 | .react.clean: 53 | @rm -rf $(REACT_OUTPUT_DIR) 54 | 55 | .PHONY: react.build react.test .react.clean 56 | 57 | ifneq ($(LANGUAGES),) 58 | I18NEXT_CONV := $(YARN_BIN_DIR)/i18next-conv 59 | REACT_GETTEXT_PARSER := $(YARN_BIN_DIR)/react-gettext-parser 60 | 61 | $(I18NEXT_CONV): yarn.install 62 | $(REACT_GETTEXT_PARSER): yarn.install 63 | build.tools: $(REACT_GETTEXT_PARSER) $(I18NEXT_CONV) 64 | 65 | .PHONY: react.collect-translations 66 | react.collect-translations: $(REACT_GETTEXT_PARSER) |$(WORK_DIR) 67 | @$(INFO) react-gettext-parser collect translations 68 | @cd $(NODE_ROOT_DIR); $(REACT_GETTEXT_PARSER) --config .gettextparser --no-wrap --output $(abspath $(WORK_DIR))/$(REACT_LOCALE_PREFIX).pot '$(NODE_SRC_DIR)/**/*.{js,ts,tsx}' 69 | # Update the .pot file only if there are changes to actual messages. We need this because the collector always updates 70 | # the POT-Creation-Date 71 | # 72 | @$(MAKELIB_BIN_DIR)/po-diff.sh $(LOCALES_DIR)/$(REACT_LOCALE_PREFIX).pot $(WORK_DIR)/$(REACT_LOCALE_PREFIX).pot || \ 73 | mv $(WORK_DIR)/$(REACT_LOCALE_PREFIX).pot $(LOCALES_DIR)/$(REACT_LOCALE_PREFIX).pot 74 | @rm -f $(WORK_DIR)/$(REACT_LOCALE_PREFIX).pot 75 | # 76 | @$(OK) react-gettext-parser collect translations 77 | 78 | react.convert-translations: $(I18NEXT_CONV) 79 | @$(INFO) i18next convert translations to json 80 | $(foreach l,$(LANGUAGES),@$(I18NEXT_CONV) --language $(l) --skipUntranslated \ 81 | --source $(LOCALES_DIR)/$(l)/$(REACT_LOCALE_PREFIX).po \ 82 | --target $(NODE_ROOT_DIR)/$(NODE_SRC_DIR)/locales/$(l).json \ 83 | > /dev/null || $(FAIL) ${\n}\ 84 | ) 85 | @$(OK) i18next convert translations to json 86 | 87 | .translations.init: react.collect-translations 88 | .translations.done: react.convert-translations 89 | endif 90 | 91 | # ==================================================================================== 92 | # Common Targets 93 | 94 | .js.build.run: react.build 95 | .js.test.run: react.test 96 | clean: .react.clean 97 | 98 | # ==================================================================================== 99 | # Special Targets 100 | 101 | define REACT_HELPTEXT 102 | React Targets: 103 | react.run Run the react application for development. 104 | 105 | endef 106 | export REACT_HELPTEXT 107 | 108 | .PHONY: .react.help 109 | .react.help: 110 | @echo "$$REACT_HELPTEXT" 111 | 112 | .help: .react.help 113 | 114 | endif # __REACT_MAKEFILE__ 115 | -------------------------------------------------------------------------------- /build/makelib/utils.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Pressinfra SRL. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __UTILS_MAKEFILE__ 16 | __UTILS_MAKEFILE__ := included 17 | 18 | COMMA := , 19 | # define literal space character in a way that work with both GNU make 3 and 4 20 | SPACE := $(subst ,, ) 21 | 22 | # define a newline 23 | define \n 24 | 25 | 26 | endef 27 | 28 | # ==================================================================================== 29 | # Colors 30 | 31 | BLACK := $(shell printf "\033[30m") 32 | BLACK_BOLD := $(shell printf "\033[30;1m") 33 | RED := $(shell printf "\033[31m") 34 | RED_BOLD := $(shell printf "\033[31;1m") 35 | GREEN := $(shell printf "\033[32m") 36 | GREEN_BOLD := $(shell printf "\033[32;1m") 37 | YELLOW := $(shell printf "\033[33m") 38 | YELLOW_BOLD := $(shell printf "\033[33;1m") 39 | BLUE := $(shell printf "\033[34m") 40 | BLUE_BOLD := $(shell printf "\033[34;1m") 41 | MAGENTA := $(shell printf "\033[35m") 42 | MAGENTA_BOLD := $(shell printf "\033[35;1m") 43 | CYAN := $(shell printf "\033[36m") 44 | CYAN_BOLD := $(shell printf "\033[36;1m") 45 | WHITE := $(shell printf "\033[37m") 46 | WHITE_BOLD := $(shell printf "\033[37;1m") 47 | CNone := $(shell printf "\033[0m") 48 | 49 | # ==================================================================================== 50 | # Logger 51 | 52 | TIME_LONG = `date +%Y-%m-%d' '%H:%M:%S` 53 | TIME_SHORT = `date +%H:%M:%S` 54 | TIME = $(TIME_SHORT) 55 | 56 | INFO = echo ${TIME} ${BLUE}[ .. ]${CNone} 57 | WARN = echo ${TIME} ${YELLOW}[WARN]${CNone} 58 | ERR = echo ${TIME} ${RED}[FAIL]${CNone} 59 | OK = echo ${TIME} ${GREEN}[ OK ]${CNone} 60 | FAIL = (echo ${TIME} ${RED}[FAIL]${CNone} && false) 61 | 62 | 63 | # ==================================================================================== 64 | # Utility functions 65 | lower = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1)))))))))))))))))))))))))) 66 | upper = $(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$1)))))))))))))))))))))))))) 67 | list-join = $(subst $(SPACE),$(1),$(strip $(2))) 68 | 69 | # ==================================================================================== 70 | # Tools macros 71 | # 72 | # Theses macros are used to install tools in an idempotent, cache friendly way. 73 | 74 | define tool 75 | $(subst -,_,$(call upper,$(1))) := $$(TOOLS_BIN_DIR)/$(1) 76 | 77 | build.tools: $$(TOOLS_BIN_DIR)/$(1) 78 | $$(TOOLS_BIN_DIR)/$(1): $$(TOOLS_HOST_DIR)/$(1)-v$(2) |$$(TOOLS_BIN_DIR) 79 | @ln -sf $$< $$@ 80 | endef 81 | 82 | # Creates a target for downloading a tool from a given url 83 | # 1 tool, 2 version, 3 download url 84 | define tool.download 85 | $(call tool,$(1),$(2)) 86 | 87 | $$(TOOLS_HOST_DIR)/$(1)-v$(2): |$$(TOOLS_HOST_DIR) 88 | @echo ${TIME} ${BLUE}[TOOL]${CNone} installing $(1) version $(2) from $(3) 89 | @curl -fsSLo $$@ $(3) || $$(FAIL) 90 | @chmod +x $$@ 91 | @$$(OK) installing $(1) version $(2) from $(3) 92 | endef # tool.download 93 | 94 | # Creates a target for downloading and unarchiving a tool from a given url 95 | # 1 tool, 2 version, 3 download url, 4 tool path within archive, 5 tar strip components 96 | define tool.download.tar.gz 97 | $(call tool,$(1),$(2)) 98 | 99 | ifeq ($(4),) 100 | $(1)_TOOL_ARCHIVE_PATH = $(1) 101 | else 102 | $(1)_TOOL_ARCHIVE_PATH = $(4) 103 | endif 104 | 105 | 106 | $$(TOOLS_HOST_DIR)/$(1)-v$(2): |$$(TOOLS_HOST_DIR) 107 | @echo ${TIME} ${BLUE}[TOOL]${CNone} installing $(1) version $(2) from $(3) 108 | @mkdir -p $$(TOOLS_HOST_DIR)/tmp-$(1)-v$(2) || $$(FAIL) 109 | ifeq ($(5),) 110 | @curl -fsSL $(3) | tar -xz --strip-components=1 -C $$(TOOLS_HOST_DIR)/tmp-$(1)-v$(2) || $$(FAIL) 111 | else 112 | @curl -fsSL $(3) | tar -xz --strip-components=$(5) -C $$(TOOLS_HOST_DIR)/tmp-$(1)-v$(2) || $$(FAIL) 113 | endif 114 | @mv $$(TOOLS_HOST_DIR)/tmp-$(1)-v$(2)/$$($(1)_TOOL_ARCHIVE_PATH) $$@ || $(FAIL) 115 | @chmod +x $$@ 116 | @rm -rf $$(TOOLS_HOST_DIR)/tmp-$(1)-v$(2) 117 | @$$(OK) installing $(1) version $(2) from $(3) 118 | endef # tool.download.tar.gz 119 | 120 | 121 | endif # __UTILS_MAKEFILE__ 122 | -------------------------------------------------------------------------------- /build/makelib/wordpress.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2020 The Pressinfra Authors. All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef __WORDPRESS_MAKEFILE__ 16 | __WORDPRESS_MAKEFILE__ := included 17 | 18 | SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 19 | include $(SELF_DIR)/php.mk 20 | 21 | # ==================================================================================== 22 | # Options 23 | 24 | WP_VERSION ?= master 25 | 26 | WP_OUTPUT_DIR := $(OUTPUT_DIR)/wordpress-$(WP_VERSION) 27 | 28 | ifeq ($(WP_VERSION),master) 29 | WP_DOWNLOAD_URL ?= https://github.com/WordPress/wordpress-develop/archive/$(WP_VERSION).tar.gz 30 | else 31 | WP_DOWNLOAD_URL ?= https://wordpress.org/wordpress-$(WP_VERSION).tar.gz 32 | endif 33 | WP_ARCHIVE := $(CACHE_DIR)/wordpress-$(WP_VERSION).tar.gz 34 | 35 | 36 | WP_TESTS_VERSION ?= $(WP_VERSION) 37 | WP_TESTS_DIR ?= $(WORK_DIR)/wordpress-develop-$(WP_VERSION) 38 | WP_TESTS_CONFIG ?= $(abspath $(PHP_ROOT_DIR))/tests/wp-tests-config.php 39 | WP_TESTS_DOWNLOAD_URL ?= https://github.com/WordPress/wordpress-develop/archive/$(WP_VERSION).tar.gz 40 | WP_TESTS_ARCHIVE := $(CACHE_DIR)/wordpress-develop-$(WP_VERSION).tar.gz 41 | 42 | # ===================================================================================== 43 | # WordPress Targets 44 | 45 | $(WP_TESTS_ARCHIVE): 46 | @$(INFO) fetching $(notdir $@) from $(WP_TESTS_DOWNLOAD_URL) 47 | @curl -sLo "$@" "$(WP_TESTS_DOWNLOAD_URL)" || $(FAIL) 48 | @$(OK) fetching $(notdir $@) from $(WP_TESTS_DOWNLOAD_URL) 49 | 50 | $(WP_TESTS_DIR)/src/wp-includes/version.php: $(WP_TESTS_ARCHIVE) 51 | @$(INFO) unpacking $< 52 | @rm -rf $(WP_TESTS_DIR) && mkdir -p $(WP_TESTS_DIR) 53 | @tar -zxf $< -C $(WP_TESTS_DIR) --strip-components 1 54 | @cp tests/wp-tests-config.php $(WP_TESTS_DIR) 55 | @mkdir -p $(WP_TESTS_DIR)/src/wp-content/uploads 56 | @test -f $@ && touch $@ || $(FAIL) 57 | @$(OK) unpacking $< 58 | 59 | $(WP_TESTS_DIR)/wp-tests-config.php: $(WP_TESTS_CONFIG) $(WP_TESTS_DIR)/src/wp-includes/version.php 60 | @cp $(WP_TESTS_CONFIG) $@ 61 | 62 | # add WP_TESTS_DIR env var for running tests 63 | .do.php.test: PHPUNIT:=WP_TESTS_DIR=$(WP_TESTS_DIR) $(PHPUNIT) 64 | 65 | $(WP_ARCHIVE): 66 | @$(INFO) fetching $(notdir $@) from $(WP_DOWNLOAD_URL) 67 | @curl -sLo "$@" "$(WP_DOWNLOAD_URL)" || $(FAIL) 68 | @$(OK) fetching $(notdir $@) from $(WP_DOWNLOAD_URL) 69 | 70 | $(WP_OUTPUT_DIR)/wp-includes/version.php: $(WP_ARCHIVE) 71 | @$(INFO) unpacking $< 72 | @rm -rf $(WP_OUTPUT_DIR) && mkdir -p $(WP_OUTPUT_DIR) 73 | @tar -zxf $< -C $(WP_OUTPUT_DIR) --strip-components 1 74 | @test -f $@ && touch $@ || $(FAIL) 75 | @$(OK) unpacking $< 76 | 77 | $(eval $(call common.target,wordpress.build)) 78 | .wordpress.build.init: $(WP_OUTPUT_DIR)/wp-includes/version.php 79 | 80 | # ==================================================================================== 81 | # Common Targets 82 | 83 | .php.test.init: $(WP_TESTS_DIR)/wp-tests-config.php 84 | .build.artifacts: wordpress.build 85 | 86 | endif # __WORDPRESS_MAKEFILE__ 87 | -------------------------------------------------------------------------------- /default-backend/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "embed" 5 | "encoding/json" 6 | "flag" 7 | "fmt" 8 | "html/template" 9 | "io/ioutil" 10 | "log" 11 | "mime" 12 | "net/http" 13 | "os" 14 | "strconv" 15 | "strings" 16 | "time" 17 | 18 | "github.com/prometheus/client_golang/prometheus/promhttp" 19 | ) 20 | 21 | const ( 22 | // FormatHeader name of the header used to extract the format 23 | FormatHeader = "X-Format" 24 | 25 | // CodeHeader name of the header used as source of the HTTP statu code to return 26 | CodeHeader = "X-Code" 27 | 28 | // ContentType name of the header that defines the format of the reply 29 | ContentType = "Content-Type" 30 | 31 | // OriginalURI name of the header with the original URL from NGINX 32 | OriginalURI = "X-Original-URI" 33 | 34 | // Namespace name of the header that contains information about the Ingress namespace 35 | Namespace = "X-Namespace" 36 | 37 | // IngressName name of the header that contains the matched Ingress 38 | IngressName = "X-Ingress-Name" 39 | 40 | // ServiceName name of the header that contains the matched Service in the Ingress 41 | ServiceName = "X-Service-Name" 42 | 43 | // ServicePort name of the header that contains the matched Service port in the Ingress 44 | ServicePort = "X-Service-Port" 45 | 46 | // defaultHTMLTemplate 47 | defaultHTMLTemplate = "

{{ .StatusCode }}

{{ .Message }}

" 48 | ) 49 | 50 | //go:embed templates 51 | var box embed.FS 52 | 53 | var ( 54 | logdest = flag.String("logdest", "/dev/null", "log messages destination") 55 | addr = flag.String("addr", ":8080", "default listening address") 56 | ) 57 | 58 | var T *template.Template 59 | 60 | type Error struct { 61 | StatusCode int `json:"statusCode"` 62 | Message string `json:"message"` 63 | URI string `json:"-"` 64 | Namespace string `json:"-"` 65 | IngressName string `json:"-"` 66 | ServiceName string `json:"-"` 67 | ServicePort int `json:"-"` 68 | } 69 | 70 | func main() { 71 | var err error 72 | flag.Parse() 73 | 74 | log.Printf("Starting default-backend server on %s...", *addr) 75 | 76 | if len(*logdest) > 0 && *logdest != "/dev/null" { 77 | f, err := os.OpenFile(*logdest, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) 78 | if err != nil { 79 | log.Fatal(err) 80 | } 81 | log.SetOutput(f) 82 | defer f.Close() 83 | } else { 84 | log.SetOutput(ioutil.Discard) 85 | } 86 | 87 | T, err = template.ParseFS(box, "templates/*.tmpl") 88 | if err != nil { 89 | panic(err) 90 | } 91 | 92 | if t := T.Lookup("html.tmpl"); t == nil { 93 | if _, err := T.New("html.tmpl").Parse(defaultHTMLTemplate); err != nil { 94 | panic(err) 95 | } 96 | } 97 | 98 | http.HandleFunc("/", errorHandler()) 99 | 100 | http.Handle("/metrics", promhttp.Handler()) 101 | 102 | http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { 103 | w.WriteHeader(http.StatusOK) 104 | }) 105 | 106 | if err := http.ListenAndServe(*addr, nil); err != nil { 107 | panic(err) 108 | } 109 | } 110 | 111 | func NewError(r *http.Request) *Error { 112 | errCode := r.Header.Get(CodeHeader) 113 | code, err := strconv.Atoi(errCode) 114 | if err != nil || len(errCode) == 0 { 115 | code = 404 116 | log.Printf("unexpected error reading return code: %v. Using %v", err, code) 117 | } 118 | 119 | servicePort, err := strconv.Atoi(r.Header.Get(ServicePort)) 120 | if err != nil { 121 | log.Printf("unexpected service port %s", r.Header.Get(ServicePort)) 122 | } 123 | 124 | return &Error{ 125 | StatusCode: code, 126 | Message: http.StatusText(code), 127 | URI: r.Header.Get(OriginalURI), 128 | Namespace: r.Header.Get(Namespace), 129 | IngressName: r.Header.Get(IngressName), 130 | ServiceName: r.Header.Get(ServiceName), 131 | ServicePort: servicePort, 132 | } 133 | } 134 | 135 | func errorHandler() func(http.ResponseWriter, *http.Request) { 136 | return func(w http.ResponseWriter, r *http.Request) { 137 | start := time.Now() 138 | e := NewError(r) 139 | ext := "html" 140 | 141 | format := r.Header.Get(FormatHeader) 142 | if format == "" { 143 | format = "text/html" 144 | log.Printf("format not specified. Using %v", format) 145 | } 146 | 147 | cext, err := mime.ExtensionsByType(format) 148 | if err != nil { 149 | log.Printf("unexpected error reading media type extension: %v. Using %v", err, ext) 150 | } else if len(cext) == 0 { 151 | log.Printf("couldn't get media type extension. Using %v", ext) 152 | } else { 153 | ext = cext[0] 154 | } 155 | ext = strings.TrimPrefix(ext, ".") 156 | 157 | w.Header().Set(ContentType, "text/html") 158 | w.WriteHeader(e.StatusCode) 159 | 160 | if ext == "json" { 161 | w.Header().Set(ContentType, "application/json") 162 | resp, _ := json.Marshal(e) 163 | if _, err := w.Write(resp); err != nil { 164 | panic(err) 165 | } 166 | } else { 167 | t := T.Lookup(ext + ".tmpl") 168 | if t == nil { 169 | t = T.Lookup("html.tmpl") 170 | } 171 | 172 | if err := t.Execute(w, e); err != nil { 173 | log.Printf("%s", err) 174 | } 175 | } 176 | 177 | duration := time.Since(start).Seconds() 178 | 179 | proto := strconv.Itoa(r.ProtoMajor) 180 | proto = fmt.Sprintf("%s.%s", proto, strconv.Itoa(r.ProtoMinor)) 181 | 182 | requestCount.WithLabelValues(proto).Inc() 183 | requestDuration.WithLabelValues(proto).Observe(duration) 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /default-backend/metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Collect and display prometheus metrics 18 | 19 | package main 20 | 21 | import ( 22 | "github.com/prometheus/client_golang/prometheus" 23 | ) 24 | 25 | const ( 26 | namespace = "default_http_backend" 27 | subsystem = "http" 28 | ) 29 | 30 | var ( 31 | requestCount = prometheus.NewCounterVec(prometheus.CounterOpts{ 32 | Namespace: namespace, 33 | Subsystem: subsystem, 34 | Name: "request_count_total", 35 | Help: "Counter of HTTP requests made.", 36 | }, []string{"proto"}) 37 | 38 | requestDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{ 39 | Namespace: namespace, 40 | Subsystem: subsystem, 41 | Name: "request_duration_milliseconds", 42 | Help: "Histogram of the time (in milliseconds) each request took.", 43 | Buckets: append([]float64{.001, .003}, prometheus.DefBuckets...), 44 | }, []string{"proto"}) 45 | ) 46 | -------------------------------------------------------------------------------- /default-backend/templates/html.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Error 6 | 7 | 8 |

{{ .StatusCode }}

9 |

{{ .Message }}

10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /demo/02-install-presslabs-stack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # NOTE: Only for helm 3! 4 | 5 | : ${HELM:=helm} 6 | : ${STACK_CHART:="presslabs/stack"} 7 | : ${CERT_MANAGER_CHART:="jetstack/cert-manager"} 8 | : ${CERT_MANAGER_VERSION:=v1.3.1} 9 | 10 | set -x 11 | 12 | kubectl create ns presslabs-system 13 | 14 | "${HELM}" repo add presslabs https://presslabs.github.io/charts 15 | "${HELM}" repo add jetstack https://charts.jetstack.io 16 | "${HELM}" repo update 17 | 18 | # install cert-manager 19 | "${HELM}" upgrade -i cert-manager "${CERT_MANAGER_CHART}" \ 20 | --namespace presslabs-system \ 21 | --version "${CERT_MANAGER_VERSION}" \ 22 | --set installCRDs=true 23 | 24 | # apply the CRDs 25 | kustomize build github.com/presslabs/stack/deploy/manifests | kubectl apply -f- 26 | 27 | # application CRDs 28 | kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/application/v0.8.3/config/crd/bases/app.k8s.io_applications.yaml 29 | 30 | # install stack 31 | "${HELM}" upgrade -i stack "${STACK_CHART}" \ 32 | --namespace presslabs-system 33 | -------------------------------------------------------------------------------- /demo/03-optional-install-dashboard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | 4 | kubectl create clusterrolebinding kubernetes-dashboard \ 5 | --clusterrole cluster-admin \ 6 | --serviceaccount=kube-system:kubernetes-dashboard 7 | 8 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml 9 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: "master" 3 | description: Git Webhook for the Kubernetes WordPress Infrastructure 4 | name: git-webhook 5 | version: 0.0.1+master 6 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "git-webhook.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "git-webhook.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "git-webhook.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | 34 | {{/* 35 | Create the name of the service account 36 | */}} 37 | {{- define "git-webhook.serviceAccountName" -}} 38 | {{- if .Values.serviceAccount.create -}} 39 | {{ default (include "git-webhook.fullname" .) .Values.serviceAccount.name }} 40 | {{- else -}} 41 | {{ default "default" .Values.serviceAccount.name }} 42 | {{- end -}} 43 | {{- end -}} 44 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/templates/clusterrole.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.rbac.create }} 2 | apiVersion: rbac.authorization.k8s.io/v1beta1 3 | kind: ClusterRole 4 | metadata: 5 | name: {{ template "git-webhook.fullname" . }} 6 | labels: 7 | app: {{ template "git-webhook.name" . }} 8 | chart: {{ template "git-webhook.chart" . }} 9 | heritage: {{ .Release.Service }} 10 | release: {{ .Release.Name }} 11 | rules: 12 | - apiGroups: ['wordpress.presslabs.org'] 13 | resources: ['wordpresses', 'wordpresses/status'] 14 | verbs: ['get', 'list', 'watch', 'update'] 15 | {{- end }} 16 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.rbac.create -}} 2 | apiVersion: rbac.authorization.k8s.io/v1beta1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: {{ template "git-webhook.fullname" . }} 6 | labels: 7 | app: {{ template "git-webhook.name" . }} 8 | chart: {{ template "git-webhook.chart" . }} 9 | heritage: {{ .Release.Service }} 10 | release: {{ .Release.Name }} 11 | roleRef: 12 | apiGroup: rbac.authorization.k8s.io 13 | kind: ClusterRole 14 | name: {{ template "git-webhook.fullname" . }} 15 | subjects: 16 | - kind: ServiceAccount 17 | name: {{ template "git-webhook.serviceAccountName" . }} 18 | namespace: {{ .Release.Namespace }} 19 | {{- end -}} 20 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ template "git-webhook.fullname" . }} 5 | labels: 6 | app: {{ template "git-webhook.name" . }} 7 | chart: {{ template "git-webhook.chart" . }} 8 | release: {{ .Release.Name }} 9 | heritage: {{ .Release.Service }} 10 | {{- with .Values.annotations }} 11 | annotations: 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | spec: 15 | replicas: {{ .Values.replicas }} 16 | selector: 17 | matchLabels: 18 | app: {{ template "git-webhook.name" . }} 19 | release: {{ .Release.Name }} 20 | strategy: 21 | type: {{ .Values.deploymentStrategy }} 22 | template: 23 | metadata: 24 | labels: 25 | app: {{ template "git-webhook.name" . }} 26 | release: {{ .Release.Name }} 27 | {{- with .Values.podAnnotations }} 28 | annotations: 29 | {{- toYaml . | nindent 8 }} 30 | {{- end }} 31 | spec: 32 | serviceAccountName: {{ template "git-webhook.serviceAccountName" . }} 33 | {{- if .Values.schedulerName }} 34 | schedulerName: "{{ .Values.schedulerName }}" 35 | {{- end }} 36 | {{- if .Values.image.pullSecrets }} 37 | imagePullSecrets: 38 | {{- range .Values.image.pullSecrets }} 39 | - name: {{ . }} 40 | {{- end}} 41 | {{- end }} 42 | containers: 43 | - name: {{ .Chart.Name }} 44 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 45 | imagePullPolicy: {{ .Values.image.pullPolicy }} 46 | ports: 47 | - name: http 48 | containerPort: 8080 49 | protocol: TCP 50 | env: 51 | {{- if .Values.webhookSecret }} 52 | - name: WEBHOOK_SECRET 53 | valueFrom: 54 | secretKeyRef: 55 | name: {{ template "git-webhook.fullname" . }} 56 | key: webhook-secret 57 | {{- end}} 58 | {{- range $key, $value := .Values.env }} 59 | - name: "{{ $key }}" 60 | value: "{{ $value }}" 61 | {{- end }} 62 | {{- if .Values.envFromSecret }} 63 | envFrom: 64 | - secretRef: 65 | name: {{ .Values.envFromSecret }} 66 | {{- end }} 67 | livenessProbe: 68 | httpGet: 69 | path: /healthz 70 | port: 8080 71 | readinessProbe: 72 | httpGet: 73 | path: /healthz 74 | port: 8080 75 | resources: 76 | {{- toYaml .Values.resources | nindent 12 }} 77 | {{- with .Values.nodeSelector }} 78 | nodeSelector: 79 | {{- toYaml . | nindent 8 }} 80 | {{- end }} 81 | {{- with .Values.affinity }} 82 | affinity: 83 | {{- toYaml . | nindent 8 }} 84 | {{- end }} 85 | {{- with .Values.tolerations }} 86 | tolerations: 87 | {{- toYaml . | nindent 8 }} 88 | {{- end }} 89 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "git-webhook.fullname" . -}} 3 | {{- $servicePort := .Values.service.port -}} 4 | {{- $ingressPath := .Values.ingress.path -}} 5 | apiVersion: networking.k8s.io/v1beta1 6 | kind: Ingress 7 | metadata: 8 | name: {{ $fullName }} 9 | labels: 10 | app: {{ template "git-webhook.name" . }} 11 | chart: {{ template "git-webhook.chart" . }} 12 | release: {{ .Release.Name }} 13 | heritage: {{ .Release.Service }} 14 | {{- if .Values.ingress.labels }} 15 | {{- toYaml .Values.ingress.labels | nindent 4 }} 16 | {{- end }} 17 | {{- with .Values.ingress.annotations }} 18 | annotations: 19 | {{- toYaml . | nindent 4 }} 20 | {{- end }} 21 | spec: 22 | {{- if .Values.ingress.tls }} 23 | tls: 24 | {{- range .Values.ingress.tls }} 25 | - hosts: 26 | {{- range .hosts }} 27 | - {{ . }} 28 | {{- end }} 29 | secretName: {{ .secretName }} 30 | {{- end }} 31 | {{- end }} 32 | rules: 33 | {{- range .Values.ingress.hosts }} 34 | - host: {{ . }} 35 | http: 36 | paths: 37 | - path: {{ $ingressPath }} 38 | backend: 39 | serviceName: {{ $fullName }} 40 | servicePort: {{ $servicePort }} 41 | {{- end }} 42 | {{- end }} 43 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.webhookSecret }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ template "git-webhook.fullname" . }} 6 | labels: 7 | app: {{ template "git-webhook.name" . }} 8 | chart: {{ template "git-webhook.chart" . }} 9 | release: {{ .Release.Name }} 10 | heritage: {{ .Release.Service }} 11 | type: Opaque 12 | data: 13 | webhookSecret: {{ .Values.webhookSecret | b64enc | quote }} 14 | {{- end }} 15 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ template "git-webhook.fullname" . }} 5 | labels: 6 | app: {{ template "git-webhook.name" . }} 7 | chart: {{ template "git-webhook.chart" . }} 8 | release: {{ .Release.Name }} 9 | heritage: {{ .Release.Service }} 10 | {{- if .Values.service.labels }} 11 | {{- toYaml .Values.service.labels | nindent 4 }} 12 | {{- end }} 13 | {{- with .Values.service.annotations }} 14 | annotations: 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | spec: 18 | {{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} 19 | type: ClusterIP 20 | {{- if .Values.service.clusterIP }} 21 | clusterIP: {{ .Values.service.clusterIP }} 22 | {{end}} 23 | {{- else if eq .Values.service.type "LoadBalancer" }} 24 | type: {{ .Values.service.type }} 25 | {{- if .Values.service.loadBalancerIP }} 26 | loadBalancerIP: {{ .Values.service.loadBalancerIP }} 27 | {{- end }} 28 | {{- if .Values.service.loadBalancerSourceRanges }} 29 | loadBalancerSourceRanges: 30 | {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} 31 | {{- end -}} 32 | {{- else }} 33 | type: {{ .Values.service.type }} 34 | {{- end }} 35 | {{- if .Values.service.externalIPs }} 36 | externalIPs: 37 | {{- toYaml .Values.service.externalIPs | nindent 4 }} 38 | {{- end }} 39 | ports: 40 | - name: http 41 | port: {{ .Values.service.port }} 42 | protocol: TCP 43 | targetPort: 8080 44 | {{ if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} 45 | nodePort: {{.Values.service.nodePort}} 46 | {{ end }} 47 | selector: 48 | app: {{ template "git-webhook.name" . }} 49 | release: {{ .Release.Name }} 50 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | app: {{ template "git-webhook.name" . }} 7 | chart: {{ template "git-webhook.chart" . }} 8 | heritage: {{ .Release.Service }} 9 | release: {{ .Release.Name }} 10 | name: {{ template "git-webhook.serviceAccountName" . }} 11 | namespace: {{ .Release.Namespace }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /deploy/charts/git-webhook/values.yaml: -------------------------------------------------------------------------------- 1 | rbac: 2 | create: true 3 | serviceAccount: 4 | create: true 5 | name: 6 | 7 | replicas: 1 8 | 9 | deploymentStrategy: RollingUpdate 10 | 11 | image: 12 | repository: quay.io/presslabs/git-webhook 13 | tag: latest 14 | pullPolicy: Always 15 | 16 | ## Optionally specify an array of imagePullSecrets. 17 | ## Secrets must be manually created in the namespace. 18 | ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ 19 | ## 20 | # pullSecrets: 21 | # - myRegistryKeySecretName 22 | 23 | ## Pod Annotations 24 | # podAnnotations: {} 25 | 26 | ## Deployment annotations 27 | # annotations: {} 28 | 29 | # Webhook Secret 30 | # webhookSecret: your-secret-key-here 31 | 32 | ## Expose the git-webhook service to be accessed from outside the cluster (LoadBalancer service). 33 | ## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. 34 | ## ref: http://kubernetes.io/docs/user-guide/services/ 35 | ## 36 | service: 37 | type: ClusterIP 38 | port: 80 39 | annotations: {} 40 | labels: {} 41 | 42 | ingress: 43 | enabled: true 44 | annotations: 45 | kubernetes.io/ingress.class: nginx 46 | # kubernetes.io/tls-acme: "true" 47 | labels: {} 48 | path: / 49 | hosts: 50 | - "git-webhook.local" 51 | tls: [] 52 | # - secretName: chart-example-tls 53 | # hosts: 54 | # - chart-example.local 55 | 56 | resources: {} 57 | # limits: 58 | # cpu: 100m 59 | # memory: 128Mi 60 | # requests: 61 | # cpu: 100m 62 | # memory: 128Mi 63 | 64 | ## Node labels for pod assignment 65 | ## ref: https://kubernetes.io/docs/user-guide/node-selection/ 66 | # 67 | nodeSelector: {} 68 | 69 | ## Tolerations for pod assignment 70 | ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ 71 | ## 72 | tolerations: [] 73 | 74 | ## Affinity for pod assignment 75 | ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity 76 | ## 77 | affinity: {} 78 | 79 | ## Use an alternate scheduler, e.g. "stork". 80 | ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ 81 | ## 82 | # schedulerName: 83 | 84 | ## Extra environment variables that will be pass onto deployment pods 85 | env: {} 86 | 87 | ## The name of a secret in the same kubernetes namespace which contain values to be added to the environment 88 | ## This can be useful for auth tokens, etc 89 | envFromSecret: "" 90 | -------------------------------------------------------------------------------- /deploy/charts/stack/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /deploy/charts/stack/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: mysql-operator 3 | repository: https://helm-charts.bitpoke.io 4 | version: 0.6.3 5 | - name: wordpress-operator 6 | repository: https://helm-charts.bitpoke.io 7 | version: 0.12.2 8 | - name: ingress-nginx 9 | repository: https://kubernetes.github.io/ingress-nginx 10 | version: 4.2.5 11 | - name: git-webhook 12 | repository: file://../git-webhook 13 | version: 0.0.1+master 14 | digest: sha256:23a215179bc478512043bd5e2db21a1fdd70fbca35e1e514f5260319e95e5323 15 | generated: "2023-05-23T13:14:51.552009+03:00" 16 | -------------------------------------------------------------------------------- /deploy/charts/stack/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: stack 3 | description: Your Open-Source, Cloud-Native WordPress Infrastructure 4 | icon: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAATlBMVEX///+hoaodIyfz8/StrbXQ0NRPUllvcXnb29++vsPt7e/n5+rW1tnExMm4uL6zs7qEhY1nanFfYmjc3N+srLWZmaKRkZlwcnktMjclKy/obea+AAAA60lEQVRYw+3PyQ3CQBQE0Z5vG7wv7OSfKDKX5jgj6ugK4Emlo6O9YbotUy+sMX1rBNWkZJHxLEKeRcqzCHiMaI8R7TGiPUa0x4j2GNEeI9pDxWtKrLgkWHwkWDwlWAxaDFoMWgxaDFoMWgxaDFoMWgxaDFoMWozfLhniWAK+7xliVQDG8//pKH7uSsCNBtcMsC0AXxlerQJwzfCqAvAMeKI90Z5oT7Qn2hPtifZEe6I90Z5oTxvsifY0w56qmvIsUp5FyrNIeRYpzyLlWaQ8i5RnkfUs2mNEe4xojxHtQWK3e3Mlrr5tBx0duQ8QNA2W1DHZ9QAAAABJRU5ErkJggg== 5 | appVersion: latest 6 | kubeVersion: ">= 1.19.0-0" 7 | keywords: 8 | - wordpress 9 | - bitpoke 10 | - Integration and Delivery 11 | version: 0.0.0 12 | home: https://www.bitpoke.io/stack/ 13 | sources: 14 | - https://github.com/bitpoke/stack 15 | maintainers: 16 | - name: Bitpoke 17 | email: hello@bitpoke.io 18 | url: https://www.bitpoke.io 19 | annotations: 20 | artifacthub.io/license: "Apache-2.0" 21 | artifacthub.io/operator: "true" 22 | dependencies: 23 | - name: mysql-operator 24 | version: 0.6.3 25 | repository: https://helm-charts.bitpoke.io 26 | condition: mysql-operator.enabled 27 | 28 | - name: wordpress-operator 29 | version: 0.12.2 30 | repository: https://helm-charts.bitpoke.io 31 | condition: wordpress-operator.enabled 32 | 33 | - name: ingress-nginx 34 | alias: nginx-ingress 35 | version: 4.2.5 36 | repository: https://kubernetes.github.io/ingress-nginx 37 | condition: nginx-ingress.enabled 38 | 39 | - name: git-webhook 40 | version: 0.0.1+master 41 | repository: "file://../git-webhook" 42 | condition: git-webhook.enabled 43 | -------------------------------------------------------------------------------- /deploy/charts/stack/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitpoke/stack/4fe1d1978425cb47a11e355ad4e71616b7e3f01c/deploy/charts/stack/icon.png -------------------------------------------------------------------------------- /deploy/charts/stack/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Bitpoke Stack, your open-source, cloud native WordPress infrastructure has been successfully deployed. 2 | 3 | Create your first site by running: 4 | 5 | # helm install mysite bitpoke/wordpress-site --set site.domains[0]=www.example.com 6 | 7 | Then point your DNS to the Ingres IP. You can find the ingress IP by running: 8 | 9 | # kubectl get ingress mysite -o jsonpath='{.status.loadBalancer.ingress[*].ip}{"\n"}' 10 | -------------------------------------------------------------------------------- /deploy/charts/stack/templates/_docs.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=markdown: */}} 2 | {{- define "stack.docs" -}} 3 | How to deploy a site: 4 | 5 | 1. Install the site using helm 6 | ``` 7 | helm install -n example bitpoke/wordpress-site \ 8 | --set site.domains[0]=www.example.com 9 | ``` 10 | 2. Point `www.example.com` DNS to the `Ingress IP`. You can find the ingress ip 11 | either in the Google Cloud Console under `Kubernetes Engine > Applications` 12 | or by issuing: 13 | ``` 14 | kubectl get ingress example \ 15 | -o jsonpath='{.status.loadBalancer.ingress[*].ip}{"\n"}' 16 | ``` 17 | {{- end -}} 18 | -------------------------------------------------------------------------------- /deploy/charts/stack/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=gotexttmpl: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "stack.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 7 | {{- end }} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "stack.fullname" -}} 15 | {{- if .Values.fullnameOverride }} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 17 | {{- else }} 18 | {{- $name := default .Chart.Name .Values.nameOverride }} 19 | {{- if contains $name .Release.Name }} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 21 | {{- else }} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 23 | {{- end }} 24 | {{- end }} 25 | {{- end }} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "stack.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 32 | {{- end }} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "stack.labels" -}} 38 | helm.sh/chart: {{ include "stack.chart" . }} 39 | {{ include "stack.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end }} 45 | 46 | {{/* 47 | Selector labels 48 | */}} 49 | {{- define "stack.selectorLabels" -}} 50 | app.kubernetes.io/name: {{ include "stack.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end }} 53 | -------------------------------------------------------------------------------- /deploy/charts/stack/templates/acme-issuer.yaml: -------------------------------------------------------------------------------- 1 | {{- $nginxIngress := index .Values "nginx-ingress" -}} 2 | apiVersion: cert-manager.io/v1 3 | kind: ClusterIssuer 4 | metadata: 5 | name: {{ template "stack.fullname" . }}-default-certificate-issuer 6 | labels: 7 | {{- include "stack.labels" . | nindent 4 }} 8 | spec: 9 | {{- if .Values.letsencrypt.enabled }} 10 | acme: 11 | # You must replace this email address with your own. 12 | # Let's Encrypt will use this to contact you about expiring 13 | # certificates, and issues related to your account. 14 | email: {{ required "A valid .letsencrypt.email is required." .Values.letsencrypt.email }} 15 | server: {{ .Values.letsencrypt.server }} 16 | privateKeySecretRef: 17 | # Secret resource used to store the account's private key. 18 | name: {{ template "stack.fullname" . }}-letsencrypt 19 | # Enable the HTTP01 challenge mechanism for this Issuer 20 | solvers: 21 | - http01: 22 | ingress: 23 | class: {{ $nginxIngress.controller.ingressClassResource.name }} 24 | podTemplate: 25 | metadata: 26 | annotations: 27 | cluster-autoscaler.kubernetes.io/safe-to-evict: "true" 28 | {{ else }} 29 | ca: 30 | secretName: {{ template "stack.fullname" . }}-ca 31 | {{- end }} 32 | --- 33 | apiVersion: cert-manager.io/v1 34 | kind: Certificate 35 | metadata: 36 | name: {{ template "stack.fullname" . }}-ingress-default 37 | labels: 38 | {{- include "stack.labels" . | nindent 4 }} 39 | spec: 40 | secretName: {{ template "stack.fullname" . }}-ingress-default 41 | commonName: "ingress.local" 42 | issuerRef: 43 | name: {{ template "stack.fullname" . }}-ca-issuer 44 | kind: Issuer 45 | 46 | --- 47 | apiVersion: cert-manager.io/v1 48 | kind: Issuer 49 | metadata: 50 | name: {{ template "stack.fullname" . }}-ca-issuer 51 | labels: 52 | {{- include "stack.labels" . | nindent 4 }} 53 | spec: 54 | selfSigned: {} 55 | 56 | {{- if not .Values.letsencrypt.enabled }} 57 | --- 58 | apiVersion: cert-manager.io/v1 59 | kind: Certificate 60 | metadata: 61 | name: {{ template "stack.fullname" . }}-ca 62 | labels: 63 | {{- include "stack.labels" . | nindent 4 }} 64 | spec: 65 | secretName: {{ template "stack.fullname" . }}-ca 66 | commonName: "Bitpoke Stack - Root CA ({{ .Release.Name }})" 67 | dnsNames: 68 | - stack.bitpoke.io 69 | duration: "87600h" 70 | isCA: true 71 | issuerRef: 72 | name: {{ template "stack.fullname" . }}-ca-issuer 73 | kind: Issuer 74 | {{- end }} 75 | -------------------------------------------------------------------------------- /deploy/charts/stack/templates/application.yaml: -------------------------------------------------------------------------------- 1 | {{- if (.Capabilities.APIVersions.Has "app.k8s.io/v1beta1") }} 2 | apiVersion: app.k8s.io/v1beta1 3 | kind: Application 4 | metadata: 5 | name: {{ include "stack.fullname" . }} 6 | annotations: 7 | kubernetes-engine.cloud.google.com/icon: data:image/png;base64,{{ .Files.Get "icon.png" | b64enc }} 8 | labels: 9 | {{- include "stack.labels" . | nindent 4 }} 10 | spec: 11 | componentKinds: 12 | - group: v1 13 | kind: Secret 14 | - group: v1 15 | kind: ConfigMap 16 | - group: v1 17 | kind: PersistentVolumeClaim 18 | # temporarily remove Service from component kinds list 19 | # due to: https://github.com/kubernetes-sigs/application/issues/209 20 | # - group: v1 21 | # kind: Service 22 | - group: apps 23 | kind: Deployment 24 | - group: apps 25 | kind: StatefulSet 26 | - group: batch 27 | kind: Job 28 | - group: batch 29 | kind: CronJob 30 | # cert manager operator 31 | - group: cert-manager.io 32 | kind: Certificate 33 | - group: cert-manager.io 34 | kind: Issuer 35 | - group: cert-manager.io 36 | kind: ClusterIssuer 37 | # prometheus operator 38 | - group: monitoring.coreos.com 39 | kind: Prometheus 40 | - group: monitoring.coreos.com 41 | kind: ServiceMonitor 42 | - group: monitoring.coreos.com 43 | kind: PrometheusRule 44 | - group: monitoring.coreos.com 45 | kind: Alertmanager 46 | 47 | selector: 48 | matchLabels: 49 | app.kubernetes.io/instance: {{ .Release.Name }} 50 | 51 | descriptor: 52 | type: Bitpoke Stack 53 | version: {{ .Chart.AppVersion }} 54 | description: {{ .Chart.Description }} 55 | maintainers: 56 | - name: Bitpoke 57 | url: https://www.bitpoke.io/stack 58 | email: hello@bitpoke.io 59 | links: 60 | - description: Bitpoke Stack 61 | url: https://www.bitpoke.io/stack 62 | - description: Bitpoke Stack Github Repository 63 | url: https://github.com/bitpoke/stack 64 | notes: {{ include "stack.docs" . | quote }} 65 | info: 66 | - name: Ingress IP 67 | type: Reference 68 | valueFrom: 69 | serviceRef: 70 | name: {{ .Release.Name }}-nginx-ingress-controller 71 | {{- if .Values.letsencrypt.enabled }} 72 | - name: Ingress Let's Encrypt configured email 73 | value: {{ .Values.letsencrypt.email }} 74 | - name: Ingress Let's Encrypt configured URL 75 | value: {{ .Values.letsencrypt.server }} 76 | {{- else }} 77 | - name: Ingress Certificate Authority 78 | type: Reference 79 | valueFrom: 80 | type: SecretKeyRef 81 | secretKeyRef: 82 | name: {{ template "stack.fullname" . }}-ingress-default 83 | key: ca.crt 84 | {{- end }} 85 | {{- end }} 86 | -------------------------------------------------------------------------------- /deploy/charts/stack/values.yaml: -------------------------------------------------------------------------------- 1 | letsencrypt: 2 | enabled: false 3 | email: "" 4 | server: "https://acme-v02.api.letsencrypt.org/directory" 5 | 6 | wordpress-operator: 7 | enabled: true 8 | extraArgs: 9 | - --ingress-class=bitpoke-stack 10 | 11 | mysql-operator: 12 | enabled: true 13 | orchestrator: 14 | topologyPassword: this-must-be-set-in-stone-because-of-mysql-operator-bug-75 15 | replicas: 1 16 | 17 | nginx-ingress: 18 | enabled: true 19 | controller: 20 | ingressClassResource: 21 | name: bitpoke-stack 22 | controllerValue: "bitpoke.io/stack" 23 | config: 24 | proxy-buffer-size: 64k 25 | custom-http-errors: 502,503,504 26 | hsts-preload: "true" 27 | addHeaders: 28 | server: "nginx" 29 | publishService: 30 | enabled: true 31 | extraArgs: 32 | ingress-class: bitpoke-stack 33 | default-ssl-certificate: bitpoke-stack/stack-ingress-default 34 | defaultBackend: 35 | enabled: true 36 | image: 37 | registry: docker.io 38 | image: bitpoke/stack-default-backend 39 | tag: latest 40 | pullPolicy: Always 41 | 42 | git-webhook: 43 | enabled: false 44 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: wordpress-site 3 | description: Helm chart for deploying a WordPress site on Bitpoke Stack 4 | appVersion: "master" 5 | kubeVersion: ">= 1.16.0-0" 6 | keywords: 7 | - wordpress 8 | - bitpoke 9 | - CMS 10 | - Web Application 11 | - application 12 | - web 13 | - http 14 | - php 15 | version: 0.0.1+master 16 | sources: 17 | - https://github.com/bitpoke/stack 18 | maintainers: 19 | - name: Bitpoke 20 | email: hello@bitpoke.io 21 | url: https://www.bitpoke.io 22 | annotations: 23 | artifacthub.io/license: "Apache-2.0" 24 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | {{- if len .Values.site.domains -}} 2 | 1. Change your DNS records to point {{ index .Values.site.domains 0 }} at the ingress 3 | controller endpoints 4 | 5 | 2. Visit the site at: 6 | http://{{ index .Values.site.domains 0 }} 7 | 8 | 3. That's it! 9 | {{- end -}} 10 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "wordpress-site.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | */}} 13 | {{- define "wordpress-site.fullname" -}} 14 | {{- if .Values.fullnameOverride -}} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 16 | {{- else -}} 17 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 18 | {{- end -}} 19 | {{- end -}} 20 | 21 | {{/* 22 | Create chart name and version as used by the chart label. 23 | */}} 24 | {{- define "wordpress-site.chart" -}} 25 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 26 | {{- end -}} 27 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/templates/bootstrap-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.site.bootstrap }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ include "wordpress-site.fullname" . }}-bootstrap 6 | labels: 7 | app.kubernetes.io/name: wordpress 8 | app.kubernetes.io/part-of: wordpress 9 | helm.sh/chart: {{ include "wordpress-site.chart" . }} 10 | app.kubernetes.io/instance: {{ .Release.Name }} 11 | app.kubernetes.io/managed-by: {{ .Release.Service }} 12 | type: Opaque 13 | data: 14 | WORDPRESS_BOOTSTRAP_TITLE: {{ required ".site.boostrap.title" .Values.site.bootstrap.title | b64enc | quote }} 15 | WORDPRESS_BOOTSTRAP_EMAIL: {{ required ".site.bootstrap.email" .Values.site.bootstrap.email | b64enc | quote }} 16 | WORDPRESS_BOOTSTRAP_USER: {{ required ".site.boostrap.user is required" .Values.site.bootstrap.user | b64enc | quote }} 17 | WORDPRESS_BOOTSTRAP_PASSWORD: {{ required ".site.boostrap.password is required" .Values.site.bootstrap.password | b64enc | quote }} 18 | {{- end }} 19 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/templates/memcached-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "wordpress-site.fullname" . }}-memcached 5 | labels: 6 | app.kubernetes.io/name: memcached 7 | app.kubernetes.io/component: cache 8 | helm.sh/chart: {{ include "wordpress-site.chart" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/part-of: wordpress 11 | app.kubernetes.io/managed-by: {{ .Release.Service }} 12 | spec: 13 | ports: 14 | - port: 11211 15 | name: memcached 16 | clusterIP: None 17 | selector: 18 | app.kubernetes.io/component: cache 19 | app.kubernetes.io/instance: {{ .Release.Name }} 20 | app.kubernetes.io/name: memcached 21 | app.kubernetes.io/part-of: wordpress 22 | 23 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/templates/memcached-statefullset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: {{ include "wordpress-site.fullname" . }}-memcached 5 | labels: 6 | app.kubernetes.io/name: memcached 7 | app.kubernetes.io/component: cache 8 | helm.sh/chart: {{ include "wordpress-site.chart" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/part-of: wordpress 11 | app.kubernetes.io/managed-by: {{ .Release.Service }} 12 | spec: 13 | replicas: {{ .Values.memcached.replicaCount }} 14 | selector: 15 | matchLabels: 16 | app.kubernetes.io/component: cache 17 | app.kubernetes.io/instance: {{ .Release.Name }} 18 | app.kubernetes.io/name: memcached 19 | app.kubernetes.io/part-of: wordpress 20 | serviceName: {{ include "wordpress-site.fullname" . }}-memcached 21 | template: 22 | metadata: 23 | labels: 24 | app.kubernetes.io/component: cache 25 | app.kubernetes.io/instance: {{ .Release.Name }} 26 | app.kubernetes.io/name: memcached 27 | app.kubernetes.io/part-of: wordpress 28 | spec: 29 | containers: 30 | - name: memcached 31 | command: 32 | - memcached 33 | args: 34 | - "-m" 35 | - "128" 36 | image: docker.io/library/memcached:1.5.12 37 | ports: 38 | - containerPort: 11211 39 | name: memcached 40 | - name: memcached-exporter 41 | image: quay.io/prometheus/memcached-exporter:v0.5.0 42 | ports: 43 | - containerPort: 9150 44 | name: prometheus 45 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/templates/mysql-secret.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ include "wordpress-site.fullname" . }}-db 6 | labels: 7 | app.kubernetes.io/name: mysql 8 | app.kubernetes.io/part-of: wordpress 9 | helm.sh/chart: {{ include "wordpress-site.chart" . }} 10 | app.kubernetes.io/instance: {{ .Release.Name }} 11 | app.kubernetes.io/managed-by: {{ .Release.Service }} 12 | annotations: 13 | "helm.sh/hook": pre-install 14 | "helm.sh/hook-delete-policy": "before-hook-creation" 15 | type: Opaque 16 | data: 17 | ROOT_PASSWORD: {{ randAlphaNum 16 | b64enc | quote }} 18 | USER: {{ "wordpress" | b64enc | quote }} 19 | PASSWORD: {{ randAlphaNum 16 | b64enc | quote }} 20 | DATABASE: {{ "wordpress" | b64enc | quote }} 21 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/templates/mysql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: mysql.presslabs.org/v1alpha1 2 | kind: MysqlCluster 3 | metadata: 4 | name: {{ include "wordpress-site.fullname" . }} 5 | labels: 6 | app.kubernetes.io/name: mysql 7 | app.kubernetes.io/part-of: wordpress 8 | helm.sh/chart: {{ include "wordpress-site.chart" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/managed-by: {{ .Release.Service }} 11 | spec: 12 | replicas: {{ .Values.mysql.replicaCount }} 13 | secretName: {{ include "wordpress-site.fullname" . }}-db 14 | mysqlConf: 15 | {{ toYaml .Values.mysql.mysqlConf | nindent 4 }} 16 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ include "wordpress-site.fullname" . }} 6 | labels: 7 | app.kubernetes.io/name: wordpress 8 | app.kubernetes.io/part-of: wordpress 9 | helm.sh/chart: {{ include "wordpress-site.chart" . }} 10 | app.kubernetes.io/instance: {{ .Release.Name }} 11 | app.kubernetes.io/managed-by: {{ .Release.Service }} 12 | type: Opaque 13 | data: 14 | {{- if and .Values.code .Values.code.git }} 15 | {{- if .Values.code.git.ssh_private_key }} 16 | id_rsa: {{ .Values.code.git.ssh_private_key | b64enc | quote }} 17 | {{- end }} 18 | {{- end }} 19 | 20 | {{- if and .Values.media .Values.media.gcs }} 21 | google_application_credentials.json: {{ required "A valid media.gcs.google_credentials entry required!" .Values.media.gcs.google_credentials | b64enc | quote}} 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/templates/wordpress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: wordpress.presslabs.org/v1alpha1 2 | kind: Wordpress 3 | metadata: 4 | name: {{ include "wordpress-site.fullname" . }} 5 | labels: 6 | app.kubernetes.io/name: wordpress 7 | app.kubernetes.io/part-of: wordpress 8 | helm.sh/chart: {{ include "wordpress-site.chart" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/managed-by: {{ .Release.Service }} 11 | spec: 12 | replicas: {{ .Values.replicaCount }} 13 | {{- if .Values.image.repository }} 14 | {{- if (hasPrefix "@sha1" (default "latest" .Values.image.tag)) }} 15 | image: {{ .Values.image.repository }}{{ .Values.image.tag }} 16 | {{- else }} 17 | image: {{ .Values.image.repository }}:{{ default "latest" .Values.image.tag }} 18 | {{- end }} 19 | {{- end }} 20 | {{ if .Values.image.pullPolicy }} 21 | imagePullPolicy: {{ .Values.image.pullPolicy }} 22 | {{- end }} 23 | {{- if .Values.image.imagePullSecrets }} 24 | imagePullSecrets: {{ .Values.image.imagePullSecrets }} 25 | {{- end }} 26 | domains: 27 | {{- toYaml .Values.site.domains | nindent 4 }} 28 | tlsSecretRef: {{ include "wordpress-site.fullname" . }}-tls 29 | {{- if .Values.code }} 30 | code: 31 | readOnly: {{ .Values.code.readOnly }} 32 | contentSubPath: {{ .Values.code.contentSubPath }} 33 | {{- if .Values.code.git }} 34 | git: 35 | repository: {{ required "A valid code.git.repository is required!" .Values.code.git.repository | quote }} 36 | reference: {{ default "master" .Values.code.git.reference }} 37 | env: 38 | - name: SSH_RSA_PRIVATE_KEY 39 | valueFrom: 40 | secretKeyRef: 41 | name: {{ include "wordpress-site.fullname" . }} 42 | key: id_rsa 43 | optional: true 44 | {{- end }} 45 | {{- end }} 46 | {{- if and .Values.media .Values.media.gcs }} 47 | media: 48 | gcs: 49 | bucket: {{ required "A valid media.gcs.bucket is required!" .Values.media.gcs.bucket | quote }} 50 | prefix: {{ default "" .Values.media.gcs.prefix | quote }} 51 | env: 52 | - name: GOOGLE_CREDENTIALS 53 | valueFrom: 54 | secretKeyRef: 55 | name: {{ include "wordpress-site.fullname" . }} 56 | key: google_application_credentials.json 57 | - name: GOOGLE_PROJECT_ID 58 | value: {{ required "A valid media.gcs.project is required!" .Values.media.gcs.project | quote }} 59 | {{- end }} 60 | env: 61 | - name: MEMCACHED_DISCOVERY_HOST 62 | value: {{ include "wordpress-site.fullname" . }}-memcached 63 | - name: DB_HOST 64 | value: {{ include "wordpress-site.fullname" . }}-mysql-master 65 | - name: DB_USER 66 | valueFrom: 67 | secretKeyRef: 68 | name: {{ include "wordpress-site.fullname" . }}-db 69 | key: USER 70 | - name: DB_PASSWORD 71 | valueFrom: 72 | secretKeyRef: 73 | name: {{ include "wordpress-site.fullname" . }}-db 74 | key: PASSWORD 75 | - name: DB_NAME 76 | valueFrom: 77 | secretKeyRef: 78 | name: {{ include "wordpress-site.fullname" . }}-db 79 | key: DATABASE 80 | {{- if .Values.site.env }} 81 | {{- toYaml .Values.site.env | nindent 4 }} 82 | {{- end }} 83 | {{- if .Values.site.envFrom }} 84 | envFrom: 85 | {{- toYaml .Values.site.envFrom | nindent 4 }} 86 | {{- end }} 87 | {{- if .Values.site.resources }} 88 | resources: 89 | {{- toYaml .Values.site.resources | nindent 4 }} 90 | {{- end }} 91 | 92 | {{- if .Values.site.bootstrap }} 93 | bootstrap: 94 | envFrom: 95 | - secretRef: 96 | name: {{ include "wordpress-site.fullname" . }}-bootstrap 97 | {{- end }} 98 | 99 | affinity: 100 | nodeAffinity: 101 | preferredDuringSchedulingIgnoredDuringExecution: 102 | - weight: 1 103 | preference: 104 | matchExpressions: 105 | - key: node-role.stack.bitpoke.org/wordpress 106 | operator: Exists 107 | podAntiAffinity: 108 | preferredDuringSchedulingIgnoredDuringExecution: 109 | - weight: 100 110 | podAffinityTerm: 111 | topologyKey: kubernetes.io/hostname 112 | labelSelector: 113 | matchLabels: 114 | app.kubernetes.io/name: wordpress 115 | app.kubernetes.io/instance: {{ .Release.Name }} 116 | app.kubernetes.io/part-of: wordpress 117 | tolerations: 118 | - key: "cloud.google.com/gke-preemptible" 119 | operator: "Exists" 120 | ingressAnnotations: 121 | nginx.ingress.kubernetes.io/proxy-body-size: "10m" 122 | {{- if eq "ClusterIssuer" (default "ClusterIssuer" .Values.tls.issuerKind) }} 123 | certmanager.k8s.io/cluster-issuer: {{ default "stack-default-certificate-issuer" .Values.tls.issuerName }} 124 | cert-manager.io/cluster-issuer: {{ default "stack-default-certificate-issuer" .Values.tls.issuerName }} 125 | {{- else if eq "Issuer" (default "ClusterIssuer" .Values.tls.issuerKind) }} 126 | certmanager.k8s.io/issuer: {{ default "stack-default-certificate-issuer" .Values.tls.issuerName }} 127 | cert-manager.io/issuer: {{ default "stack-default-certificate-issuer" .Values.tls.issuerName }} 128 | {{- end }} 129 | certmanager.k8s.io/acme-challenge-type: {{ default "http01" .Values.tls.acmeChallengeType }} 130 | -------------------------------------------------------------------------------- /deploy/charts/wordpress-site/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for wordpress-site. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | # Uncomment to use a custom image 8 | image: {} 9 | # repository: docker.io/bitpoke/wordpress-runtime 10 | # tag: latest 11 | # pullPolicy: IfNotPresent 12 | # imagePullSecrets: ImagePullSecretName 13 | 14 | site: 15 | domains: [] 16 | env: [] 17 | envFrom: [] 18 | resources: {} 19 | # to automatically install wordpress 20 | # bootstrap: 21 | # title: Demo site 22 | # email: ping@ 23 | # user: 24 | # password: 25 | 26 | tls: {} 27 | # issuerKind: ClusterIssuer 28 | # issuerName: stack-default-certificate-issuer 29 | # acmeChallengeType: http01 30 | 31 | code: 32 | # when true, the code is mounted read-only inside the runtime container 33 | readOnly: false 34 | 35 | # the path, within the code volume (git repo), where the 'wp-content' is 36 | # available 37 | contentSubPath: wp-content/ 38 | 39 | # git: 40 | # repository: git@github.com/bitpoke/wordpress-basic-demo 41 | # reference: "3df6701bd06d97a3954b18625926753f6246c266" 42 | # # it is not recommended to use a 'moving' target for deployment like a 43 | # # branch name. You should use a specific commit or a git tag. 44 | # # reference: master 45 | 46 | media: {} 47 | # Store media library in a Google Cloud Storage bucket 48 | # gcs: 49 | # # google cloud project 50 | # project: staging 51 | # # bucket name 52 | # bucket: calins-wordpress-runtime-playground 53 | # # use a prefix inside the bucket to store the media files 54 | # prefix: mysite/ 55 | # # credentials to access Google Cloud Storage 56 | # google_credentials: > 57 | 58 | mysql: 59 | mysqlConf: {} 60 | replicaCount: 1 61 | 62 | memcached: 63 | replicaCount: 1 64 | -------------------------------------------------------------------------------- /docs/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Welcome to Stack Docs! 3 | linktitle: Stack Docs 4 | description: "Here you can find Presslabs Stack's documentation, the first open-source serverless hosting platform that bridges two major technologies: WordPress and Kubernetes." 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes'] 6 | --- 7 | 8 | # Welcome to Stack Docs! 9 | 10 | Here you can find Presslabs Stack's documentation, the first open-source serverless hosting platform that bridges two major technologies: WordPress and Kubernetes. 11 | -------------------------------------------------------------------------------- /docs/about-stack.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About Stack 3 | linktitle: About Stack 4 | description: "Stack is a collection of Kubernetes operators that are used to manage and operate WordPress on top of Kubernetes. 5 | Those operators are cloud agnostic, meaning that Stack can run on any Kubernetes cluster." 6 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes'] 7 | --- 8 | 9 | The [Presslabs Stack](https://www.presslabs.com/stack/) is an [open-source project](https://github.com/presslabs/stack) on Github. 10 | 11 | All the components of Stack can be viewed in the picture below: 12 | 13 | ![stack-architecture](./images/stack.png) 14 | 15 | It has a control plane made up of: 16 | 17 | - [WordPress Operator](https://github.com/presslabs/wordpress-operator) - manages WordPress related operations. From installation and autoscaling, to cronjobs, backups, and upgrades. 18 | - [MySQL Operator](https://www.presslabs.com/code/mysqloperator/) - takes care of all the database operations, from scaling and failovers to backups. Depending on your use-case, you can have one cluster per site or one cluster for multiple sites. 19 | - [Let's Encrypt Cert Manager](https://github.com/jetstack/cert-manager) - takes care of automatically generating TLS certifications and accommodate their renewal 20 | - [NGINX Operator](https://github.com/kubernetes/ingress-nginx) - manages all the NGINX instances that are user-facing 21 | 22 | Going further, the data plane represents the actual pods running and its underlying storage. We recommend starting with [presslabs/stack-wordpress](https://github.com/presslabs/stack-wordpress), but we'll get further into the Runtime a little bit later, since it's tight with deployment. 23 | 24 | A system like Stack, with a lot of moving pieces, needs a monitoring system. We chose [Prometheus](https://github.com/coreos/prometheus-operator/compare?expand=1) for metrics storage (managed by the Prometheus operator) and Grafana for visualizations and alerting. 25 | -------------------------------------------------------------------------------- /docs/concepts/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Concepts 3 | linktitle: Concepts 4 | description: "Dive into the concepts of a WordPress site running on Stack for a better understanding of how your site should look." 5 | keywords: [concepts] 6 | --- 7 | -------------------------------------------------------------------------------- /docs/concepts/running-wordpress-on-kubernetes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Running WordPress on Kubernetes 3 | linktitle: "Running WordPress on Kubernetes" 4 | description: "There are multiple parts that make a site running on Kubernetes via Stack, and we'll take them one by one below." 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes'] 6 | menu: 7 | global: 8 | parent: concepts 9 | slug: running-wordpress-on-kubernetes 10 | --- 11 | 12 | A good reference about how a WordPress site looks on Stack is the [WordPress Spec](https://github.com/presslabs/wordpress-operator#deploying-a-wordpress-site). 13 | 14 | ## Domains 15 | 16 | Each site needs to have at least one domain. When a request comes to the NGINX Ingress, it'll get routed to the appropriate pods, based on the `Host` header. 17 | 18 | Even if you can have multiple domains answering to the same site, you still need the main domain that will be responsible for the `WP_HOME` and `WP_SITEURL` constants. 19 | 20 | Those domains are syncing in the ingress controller. Also, [cert-manager](https://github.com/jetstack/cert-manager) will bundle those domains into one single certificate. 21 | 22 | ## Media files 23 | 24 | Uploads are hard to manage in WordPress because they tend to get big and use a lot of computation power to generate different size. 25 | We found that we can scale them by using buckets (Google Cloud Storage / S3 etc). You also can use other traditional ways of storing and serving media files, via [persistent volume claims](https://kubernetes.io/docs/concepts/storage/persistent-volumes/), [hostPath](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) or simple [emptyDir](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir). 26 | 27 | ### Buckets 28 | 29 | For now, we support only GCS, but contributions are welcome in order to extend support for S3 as well. 30 | Handling media can be split into two main parts: writing and reading. All of them include some sort of optimizations, in order to increase performance or to allow for better testing. 31 | 32 | In all situations, we'll need some sort of authorization. On GCS this is achieved by using a [Google Service Account](https://cloud.google.com/iam/docs/service-accounts). 33 | 34 | ### Upload a file 35 | 36 | File uploads to object storage services are handled by [stack-mu-plugin](https://github.com/presslabs/stack-mu-plugin). Write access to media is implemented trough a PHP stream wrapper which allows basic operations like `fopen` and `file_get_contents` but lacks support for some features, like directory traversals. 37 | 38 | To get access to the the media bucket you need to call `wp_get_upload_dir()` or `wp_upload_dir()` as direct writes to `wp-content/uploads` folder are ephemeral and are lost when you stop the container. 39 | 40 | ### Read a file 41 | 42 | The NGINX provided by the base `quay.io/presslabs/wordpress-runtime` allows out-of-the-box integration for serving files from media buckets. This is convenient, but if you create your custom docker image from scratch you'll probably want to deal with media serving on your own. 43 | -------------------------------------------------------------------------------- /docs/config.toml: -------------------------------------------------------------------------------- 1 | baseURL = "https://www.presslabs.com/docs/stack" 2 | pygmentsCodeFences = true 3 | pygmentsCodeFencesGuessSyntax = true 4 | pygmentsUseClasses = true 5 | theme = "hugo-docs-theme" 6 | languageCode = "en-us" 7 | title = "Presslabs Stack DOCS" 8 | 9 | [markup] 10 | defaultMarkdownHandler = "goldmark" 11 | 12 | [params] 13 | related = true 14 | logo_text = "DOCS" 15 | versions = false 16 | 17 | [params.algolia] 18 | appId = "0TS6NFHDBC" 19 | apiKey = "b2efcfd6516eed7a2f19269f9cb13acb" 20 | indexName = "Stack Docs" 21 | vars = ["title", "description", "content", "date", "lastmod", "permalink", "text", "lvl0", "lvl1", "url"] 22 | 23 | [outputs] 24 | home = [ "HTML", "RSS", "JSON" ] 25 | 26 | [related] 27 | threshold = 80 28 | includeNewer = true 29 | toLower = false 30 | 31 | [[related.indices]] 32 | name = "menu.global.parent" 33 | weight = 150 34 | 35 | [[menu.global]] 36 | name = "About Stack" 37 | url = "/about-stack" 38 | weight = 1 39 | 40 | [[menu.global]] 41 | name = "Quickstart" 42 | identifier = "quickstart" 43 | weight = 2 44 | 45 | [[menu.global]] 46 | name = "How-to guides" 47 | identifier = "how-to" 48 | weight = 3 49 | 50 | [[menu.global]] 51 | name = "Development" 52 | identifier = "development" 53 | parent = "how-to" 54 | weight = 1 55 | 56 | [[menu.global]] 57 | name = "Concepts" 58 | identifier = "concepts" 59 | weight = 4 60 | 61 | [[menu.global]] 62 | name = "References" 63 | identifier = "references" 64 | weight = 5 65 | 66 | [[menu.global]] 67 | name = "Contributing" 68 | url = "/contributing" 69 | weight = 6 70 | -------------------------------------------------------------------------------- /docs/contributing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Contributing 3 | linktitle: Contributing 4 | description: "How to contribute to Stack" 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes', 'contributing', 'development', 'issues'] 6 | --- 7 | 8 | ## Issues 9 | 10 | Issues are being tracked at https://github.com/presslabs/stack/issues. 11 | They can range from bug reports to questions about development, installation process and other stuff related to the project. 12 | 13 | ## Development 14 | 15 | > ###### NOTE 16 | > 17 | > Before making a change to this repository, please open an issue to discuss why the change is needed, and how it should be implemented if necessary. 18 | 19 | 1. Clone the repository: 20 | Optionally you could [fork the repo](https://github.com/presslabs/stack/fork) first. 21 | `git clone https://github.com/presslabs/stack.git && cd stack` 22 | 23 | 2. Install dependencies: 24 | `make dependencies` 25 | 26 | 3. Implement your changes. Remember to lint your code with `make lint`. 27 | 28 | 4. Deploy to your cluster with [skaffold](https://skaffold.dev/docs/getting-started/#installing-skaffold): 29 | 30 | If you want to develop locally, use [minikube](https://github.com/kubernetes/minikube#installation) to get a locally running cluster. You can follow the steps described [here](./quickstarts/install-stack-on-minikube.md), except for the ones explaining how to install the stack. 31 | 32 | If you want to have your changes constantly deployed run: 33 | `skaffold dev` 34 | 35 | If you want to manually deploy your changes run: 36 | `skaffold run` 37 | 38 | 5. Test your changes. 39 | There's not much written code in stack, except for a few components (default-backend, git-webhook...) which might have their own Makefile and tests that can be run with `make test`. 40 | So most of the times testing will mean just running the stack with your changes and poking around. 41 | 42 | If you need to run a site for your use-case, read the [related documentation](./concepts/running-wordpress-on-kubernetes.md). 43 | 44 | 6. Open a pull request at https://github.com/presslabs/stack/compare. 45 | We'll review the pull request and assist you on getting it merged. 46 | -------------------------------------------------------------------------------- /docs/how-to/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How-to guides 3 | linktitle: How-to guides 4 | description: "Detailed guides about local site development, how to deploy a WordPress site on Stack and also how to import an existing site." 5 | keywords: [how-to] 6 | --- 7 | -------------------------------------------------------------------------------- /docs/how-to/deploy-wordpress-on-stack.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deploy WordPress to Presslabs Stack 3 | linktitle: "Deploy to Stack" 4 | description: "Find out how to deploy your WordPress code to the Presslabs Stack." 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes', 'how-to', 'development'] 6 | menu: 7 | global: 8 | parent: how-to 9 | slug: deploy-wordpress-on-stack 10 | --- 11 | 12 | ## Requirements 13 | 14 | - [helm](https://helm.sh) 15 | 16 | ## Getting started 17 | 18 | Deploying a site is as simple as following these three steps: 19 | 20 | 1. Add the Presslabs helm chart repository 21 | 22 | ```shell 23 | $ helm repo add presslabs https://presslabs.github.io/charts 24 | $ helm repo update 25 | ``` 26 | 27 | 2. Deploy a site, with main domain pointing to `example.com` 28 | 29 | ```shell 30 | $ helm upgrade -i my-site presslabs/wordpress-site --set site.domains[0]=example.com 31 | ``` 32 | 33 | 3. Point the domain to the ingress IP 34 | 35 | ```shell 36 | $ kubectl get -n presslabs-system service stack-nginx-ingress-controller 37 | ``` 38 | 39 | ## Deploy a site from a git repository 40 | 41 | > ###### NOTE 42 | > 43 | > Deploying from git repository requires that your `WP_CONTENT_DIR` is checked 44 | > in. If you want to use Bedrock it is highly recommended that you deploy using 45 | > a docker image. 46 | 47 | Deploying from git is as simple as: 48 | 49 | ```shell 50 | $ helm upgrade -i my-site presslabs/wordpress-site --set site.domains[0]=example.com \ 51 | --set code.git.repository=https://github.com/presslabs/stack-example-wordpress.git \ 52 | --set code.git.reference=master 53 | ``` 54 | 55 | * `code.git.repository` is a valid git repository origin. It supports HTTP, HTTPS, GIT and the SSH protocol. 56 | * `code.git.reference` reference to deploy. It can be a commit, branch or tag and defaults to `master` 57 | 58 | ### Using a private repository 59 | 60 | In order to use a private repository, you must generate a SSH key pair and set 61 | the **private** to the deployment. To do that, you need to add 62 | `--set-file code.git.ssh_private_key=PATH_TO_THE_PRIVATE_KEY`: 63 | 64 | ```shell 65 | $ ssh-keygen -f id_rsa -P '' 66 | $ helm upgrade -i my-site presslabs/wordpress-site --set site.domains[0]=example.com \ 67 | --set code.git.repository=https://github.com/presslabs/stack-example-wordpress.git \ 68 | --set code.git.reference=master \ 69 | --set-file code.git.ssh_private_key=id_rsa 70 | ``` 71 | 72 | ## Deploy a custom Docker image 73 | 74 | You can run a custom image, bundled with your own code and dependencies. You can 75 | specify it when deploying by setting `image.repository` and `image.tag`. 76 | 77 | ```shell 78 | $ helm upgrade my-site presslabs/wordpress-site --reuse-values \ 79 | --set image.repository=quay.io/presslabs/wordpress-runtime 80 | --set image.tag=5.2.2 81 | ``` 82 | 83 | ## What's next? 84 | 85 | * [How to import a site](./import-site.md) 86 | * Check [helm chart values reference](../reference/wordpress-site-helm-chart-values.md) 87 | -------------------------------------------------------------------------------- /docs/how-to/development/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Development 3 | linktitle: Development 4 | description: "Detailed guides about local site development, how to deploy a WordPress site on Stack and also how to import an existing site." 5 | keywords: [how-to] 6 | --- 7 | -------------------------------------------------------------------------------- /docs/how-to/development/local-development-with-bedrock.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Local development with Bedrock 3 | linktitle: "Using Bedrock" 4 | description: "This how-to will guide you through creating a Bedrock WordPress project, containerising it and running it locally using docker compose." 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes', 'how-to', 'local-development'] 6 | menu: 7 | global: 8 | parent: development 9 | slug: local-development-with-bedrock 10 | --- 11 | 12 | ## Why starting with Bedrock? 13 | 14 | `roots/bedrock` offers a standard structure and allows you to work with 15 | `composer`, thus providing better dependency management and enabling some 16 | software engineering good practices. You can install/uninstall plugins and 17 | themes via `composer`, use it's autoload functionality and other goodies. 18 | 19 | ## Requirements 20 | 21 | * [composer](https://getcomposer.org/) 22 | * [docker-compose](https://docs.docker.com/compose/install/) 23 | 24 | ## Bootstrap the project 25 | 26 | First let's create a project via `composer` starting from [roots/bedrock](https://github.com/roots/bedrock). 27 | 28 | ``` shell 29 | $ composer create-project roots/bedrock my-site 30 | $ cd my-site 31 | ``` 32 | 33 | Then we need to install the Presslabs Stack must-use plugin for WordPress. 34 | ``` shell 35 | $ composer require presslabs/stack-mu-plugin 36 | ``` 37 | 38 | In order to use the external object cache, we need to place it into our `WP_CONTENT_DIR/object-cache.php`. 39 | 40 | ``` shell 41 | $ ln -sf mu-plugins/stack-mu-plugin/src/object-cache.php web/app/object-cache.php 42 | ``` 43 | 44 | ## Create the Dockerfile 45 | 46 | Presslabs Stack provides a base image for building and developing WordPress sites using Bedrock. 47 | [`quay.io/presslabs/wordpress-runtime:bedrock-build`](https://quay.io/presslabs/wordpress-runtime) 48 | is used as a builder image and is optimized for build speed. 49 | [`quay.io/presslabs/wordpress-runtime:bedrock`](https://quay.io/presslabs/wordpress-runtime) 50 | it's optimized for running Bedrock enabled sites. 51 | 52 | The Dockerfile is as simple as: 53 | 54 | ``` Dockerfile 55 | FROM quay.io/presslabs/wordpress-runtime:bedrock-build as builder 56 | FROM quay.io/presslabs/wordpress:bedrock 57 | COPY --from=builder --chown=www-data:www-data /app /app 58 | ``` 59 | 60 | ## Run using docker-compose 61 | 62 | This `docker-compose.yaml` is a good starting point for local development using docker. 63 | 64 | ```yaml 65 | version: '3.3' 66 | 67 | services: 68 | wordpress: 69 | depends_on: 70 | - db 71 | - memcached 72 | image: quay.io/presslabs/wordpress-runtime:bedrock 73 | volumes: 74 | - ./:/app 75 | ports: 76 | - "8080:8080" 77 | restart: always 78 | environment: 79 | DB_HOST: db:3306 80 | DB_USER: wordpress 81 | DB_PASSWORD: not-so-secure 82 | DB_NAME: wordpress 83 | MEMCACHED_HOST: memcached:11211 84 | WP_HOME: http://localhost:8080 85 | WP_SITEURL: http://localhost:8080/wp 86 | WP_ENV: development 87 | 88 | db: 89 | image: percona:5.7 90 | volumes: 91 | - db_data:/var/lib/mysql 92 | restart: always 93 | environment: 94 | MYSQL_ROOT_PASSWORD: not-so-secure 95 | MYSQL_DATABASE: wordpress 96 | MYSQL_USER: wordpress 97 | MYSQL_PASSWORD: not-so-secure 98 | 99 | memcached: 100 | image: memcached:1.5 101 | 102 | volumes: 103 | db_data: {} 104 | ``` 105 | 106 | To boot up WordPress and MySQL server run: 107 | ``` shell 108 | docker-compose up -d 109 | ``` 110 | 111 | ## Installing a plugin (optional) 112 | 113 | To install a plugin you can just: 114 | ``` shell 115 | docker-compose run wordpress composer require wpackagist-plugin/debug-bar 116 | ``` 117 | 118 | This site should be available at http://localhost:8080. 119 | 120 | ## What's next 121 | 122 | * [Deploy WordPress on Stack](../deploy-wordpress-on-stack.md) 123 | * Customize NGINX 124 | * An example project can be found at [github.com/presslabs/stack-example-bedrock](https://github.com/presslabs/stack-example-bedrock) 125 | 126 | 127 | ## VIDEO Tutorial: Create a Bedrock WordPress project 128 | 129 | 134 | -------------------------------------------------------------------------------- /docs/how-to/development/local-development.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Local development 3 | linktitle: "Local development" 4 | description: "This how-to will guide you trough creating a classic WordPress project, containerising it and running it locally using docker compose" 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes', 'how-to', 'local-development'] 6 | menu: 7 | global: 8 | parent: development 9 | slug: local-development 10 | --- 11 | 12 | ## Requirements 13 | 14 | * [wp-cli](https://wp-cli.org/#installing) 15 | * [docker-compose](https://docs.docker.com/compose/install/) 16 | 17 | ## Bootstrap the project 18 | 19 | First let's create a project via `wp-cli`. 20 | 21 | ```shell 22 | $ mkdir -p my-site/wp-content/{plugins,themes,mu-plugins,uploads} 23 | $ cd my-site 24 | ``` 25 | 26 | Then we need to install the Presslabs Stack must use plugin for WordPress from [GitHub](https://github.com/presslabs/stack-mu-plugin/releases/latest/download/stack-mu-plugin.zip). 27 | 28 | In order to enable the external object cache, we need to place it into our `WP_CONTENT_DIR/object-cache.php`. 29 | 30 | ```shell 31 | $ ln -sf mu-plugins/stack-mu-plugin/src/object-cache.php web/app/object-cache.php 32 | ``` 33 | 34 | ## Create the Dockerfile 35 | 36 | Presslabs Stack provides a base image for building and developing WordPress sites. 37 | [`quay.io/presslabs/wordpress-runtime`](https://quay.io/presslabs/wordpress-runtime) 38 | is used as a builder and runtime image. 39 | 40 | The Dockerfile is as simple as: 41 | 42 | ```Dockerfile 43 | FROM quay.io/presslabs/wordpress-runtime:5.2.2 44 | ``` 45 | 46 | ## Run using docker-compose 47 | 48 | This `docker-compose.yaml` is a good starting point for local development using docker. 49 | 50 | ```yaml 51 | version: '3.3' 52 | 53 | services: 54 | wordpress: 55 | depends_on: 56 | - db 57 | - memcached 58 | image: quay.io/presslabs/wordpress-runtime:5.2.2 59 | volumes: 60 | - ./config:/app/config 61 | - ./wp-content:/app/web/wp-content 62 | ports: 63 | - "8080:8080" 64 | restart: always 65 | environment: 66 | DB_HOST: db:3306 67 | DB_USER: wordpress 68 | DB_PASSWORD: not-so-secure 69 | DB_NAME: wordpress 70 | MEMCACHED_HOST: memcached:11211 71 | WP_HOME: http://localhost:8080 72 | WP_SITEURL: http://localhost:8080/wp 73 | WP_ENV: development 74 | 75 | db: 76 | image: percona:5.7 77 | volumes: 78 | - db_data:/var/lib/mysql 79 | restart: always 80 | environment: 81 | MYSQL_ROOT_PASSWORD: not-so-secure 82 | MYSQL_DATABASE: wordpress 83 | MYSQL_USER: wordpress 84 | MYSQL_PASSWORD: not-so-secure 85 | 86 | memcached: 87 | image: memcached:1.5 88 | 89 | volumes: 90 | db_data: {} 91 | ``` 92 | 93 | To boot up WordPress and MySQL server run: 94 | 95 | ```shell 96 | docker-compose up -d 97 | ``` 98 | 99 | This site should be available at http://localhost:8080. 100 | 101 | ## Installing a plugin (optional) 102 | 103 | To install a plugin you can just: 104 | 105 | ```shell 106 | docker-compose run wordpress wp plugin install debug-bar 107 | ``` 108 | 109 | ## What's next 110 | 111 | - [Deploy WordPress on Stack](../deploy-wordpress-on-stack.md) 112 | - Customize NGINX 113 | - An example project can be found at [github.com/presslabs/stack-example-wordpress](https://github.com/presslabs/stack-example-wordpress) 114 | 115 | ## VIDEO Tutorial: Create a WordPress project with Docker Compose 116 | 117 | 122 | -------------------------------------------------------------------------------- /docs/how-to/import-site.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Import data into a site running on Stack 3 | linktitle: "Import data" 4 | description: "Find out how to import database and media files into your Presslabs Stack site." 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes'] 6 | menu: 7 | global: 8 | parent: how-to 9 | slug: import-site 10 | --- 11 | 12 | ## Database import 13 | 14 | In order to import the database, you'll need to `port-forward` MySQL's port. 15 | 16 | ``` shell 17 | $ kubectl get pods 18 | $ kubectl port-forward -mysql-0 3307:3306 19 | ``` 20 | 21 | Furthermore, you'll need to connect to it via a user and password. All database 22 | related credentials are stored in the `-db` secret. 23 | 24 | ``` shell 25 | $ kubectl get secret -db -o yaml 26 | ``` 27 | 28 | You'll need the `USER` and `PASSWORD` secret. Those are base64 encoded and in 29 | order to decode them you can `echo | base64 -D`. Since you have 30 | the credentials and the port forwarded, you just have to connect using your 31 | favorite client. 32 | 33 | ``` shell 34 | $ mysql -u USER -p -h 127.0.0.1 -P 3307 35 | ``` 36 | 37 | ## Uploads import 38 | 39 | We recommend using buckets to handle media files and in order to import all 40 | those media files, we recommend using [rclone](https://rclone.org/). You'll just 41 | need to config your service account and you're ready to go. 42 | 43 | > ###### WARNING 44 | > 45 | > This will delete existing files under that google cloud storage folder. 46 | 47 | ``` shell 48 | $ rclone -v sync uploads gcs://wp-content/uploads/ 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/images/stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitpoke/stack/4fe1d1978425cb47a11e355ad4e71616b7e3f01c/docs/images/stack.png -------------------------------------------------------------------------------- /docs/quickstarts/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Quickstart 3 | linktitle: Quickstart 4 | description: "Quickstart guides to walk you through creating the necessary clusters and installing the Presslabs Stack on them." 5 | keywords: [quickstarts] 6 | --- 7 | -------------------------------------------------------------------------------- /docs/quickstarts/install-stack-on-minikube.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to install Stack on Minikube 3 | linktitle: Install on Minikube 4 | description: "Installing Stack on Minikube is no different then installing it on another Kubernetes cluster." 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes'] 6 | menu: 7 | global: 8 | parent: "quickstart" 9 | slug: install-stack-on-minikube 10 | --- 11 | 12 | We recommend to start Minikube with a little bit more resources: 13 | 14 | ```shell 15 | minikube start --cpus 4 --memory 8192 16 | ``` 17 | 18 | Next, you'll need to install `helm`. 19 | 20 | ``` shell 21 | $ kubectl --namespace kube-system create sa tiller 22 | 23 | $ kubectl create clusterrolebinding tiller \ 24 | --clusterrole cluster-admin \ 25 | --serviceaccount=kube-system:tiller 26 | 27 | $ helm init --service-account tiller \ 28 | --history-max 10 \ 29 | --override 'spec.template.spec.containers[0].command'='{/tiller,--storage=secret}' \ 30 | --override 'spec.template.spec.tolerations[0].key'='CriticalAddonsOnly' \ 31 | --override 'spec.template.spec.tolerations[0].operator'='Exists' \ 32 | --wait 33 | ``` 34 | 35 | After that, we're ready to install `Stack`. 36 | 37 | ``` shell 38 | 39 | $ kubectl apply -f https://raw.githubusercontent.com/presslabs/stack/master/deploy/manifests/00-crds.yaml 40 | 41 | $ kubectl create ns presslabs-system 42 | 43 | $ kubectl label namespace presslabs-system certmanager.k8s.io/disable-validation=true 44 | 45 | $ helm repo add presslabs https://presslabs.github.io/charts 46 | 47 | $ helm repo update 48 | 49 | $ helm upgrade -i stack presslabs/stack --namespace presslabs-system \ 50 | -f "https://raw.githubusercontent.com/presslabs/stack/master/presets/minikube.yaml" 51 | ``` 52 | 53 | 54 | ## VIDEO Tutorial: How to install Stack on Minikube 55 | 56 | 61 | -------------------------------------------------------------------------------- /docs/reference/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Reference 3 | linktitle: Reference 4 | description: "The go-to place for setting up your Runtime environment variables and Helm Chart values for running a WordPress one." 5 | keywords: [reference] 6 | --- 7 | -------------------------------------------------------------------------------- /docs/reference/stack-runtime-environment.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Stack runtime environment 3 | linktitle: Runtime environment 4 | description: "Sites on Stack run in docker images. This describes the reference environment that docker images should implement in order to integrate with Stack." 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes'] 6 | menu: 7 | global: 8 | parent: references 9 | slug: runtime-environment 10 | --- 11 | 12 | ## HTTP server 13 | 14 | * `PORT` (default to `8080`) - the port your app 15 | * `MAX_BODY_SIZE` (default to `10`) - the size in megabytes for the maximum 16 | client request body size. (this controls NGINX `client_max_body_size` and 17 | php 18 | `upload_max_filesize` and `post_max_size`) 19 | * `NGINX_ACCESS_LOG` (default to `off`) - where to write NGINX's access log 20 | * `NGINX_ERROR_LOG` (default to `/dev/stderr`) - where to write NGINX's error 21 | log 22 | 23 | ## Media Library 24 | 25 | * `STACK_MEDIA_PATH` (default to `/wp-content/uploads`) 26 | * `STACK_MEDIA_BUCKET` - if set serves the `STACK_MEDIA_PATH` from this media bucket 27 | (eg. `gs://my-google-cloud-storage-bucket/prefix` or `s3://my-aws-s3-bucket`) 28 | 29 | ## PHP runtime 30 | 31 | * `PHP_MEMORY_LIMIT` (default to `128`). PHP request memory limit in megabytes 32 | * `PHP_REQUEST_TIMEOUT` (default to `30`) - Time in seconds for serving a 33 | single request. PHP `max_execution_time` is set to this value and can only 34 | be set to a lower value. If set to a higher one, the request will still be 35 | killed after this timeout. 36 | * `PHP_MAX_CHILDREN` (default to `5`) 37 | * `PHP_MAX_REQUESTS` (default to `500`) 38 | * `PHP_MAX_SPARE_SERVERS` (default to `PHP_MAX_CHILDREN / 2 + 1`) 39 | * `PHP_MIN_SPARE_SERVERS` (default to `PHP_MAX_CHILDREN / 3`) 40 | * `PHP_START_SERVERS` (default to `(PHP_MAX_SPARE_SERVERS - PHP_MIN_SPARE_SERVERS) / 2 + PHP_MIN_SPARE_SERVERS`) 41 | * `PHP_PROCESS_IDLE_TIMEOUT` (default to `10`) - time in seconds to wait until 42 | killing an idle worker (used only when `PHP_PM` is set to `ondemand`) 43 | * `PHP_SLOW_REQUEST_TIMEOUT` (default to `0`) - Time in seconds after which a 44 | request is logged as slow. Set to `0` to disable slow logging. 45 | 46 | ## SMTP settings 47 | 48 | * `SMTP_HOST` (default to `localhost`) 49 | * `SMTP_USER` 50 | * `SMTP_PASS` 51 | * `SMTP_PORT` (default to `587`) 52 | * `SMTP_TLS` (default to `yes`) 53 | -------------------------------------------------------------------------------- /docs/reference/wordpress-site-helm-chart-values.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: WordPress site helm chart values 3 | linktitle: Helm chart values 4 | description: "This describes the reference values file for running a WordPress site." 5 | keywords: ['stack', 'docs', 'wordpress', 'kubernetes'] 6 | menu: 7 | global: 8 | parent: references 9 | slug: wordpress-site-helm-chart-values 10 | --- 11 | 12 | ## Helm chart values 13 | 14 | ```yaml 15 | # Default values for wordpress-site. 16 | # This is a YAML-formatted file. 17 | # Declare variables to be passed into your templates. 18 | 19 | replicaCount: 1 20 | 21 | # to use a custom wordpress runtime image 22 | image: 23 | repository: quay.io/presslabs/wordpress-runtime 24 | tag: 5.2.2 25 | pullPolicy: IfNotPresent 26 | imagePullSecrets: ImagePullSecretName 27 | 28 | site: 29 | domains: [] 30 | env: [] 31 | envFrom: [] 32 | resources: {} 33 | # to automatically install wordpress 34 | bootstrap: 35 | title: My Stack Enabled site 36 | email: ping@example.com 37 | user: admin 38 | password: change-password-afer-login 39 | 40 | tls: 41 | issuerKind: ClusterIssuer 42 | issuerName: stack-default-certificate-issuer 43 | acmeChallengeType: http01 44 | 45 | code: 46 | # when true, the code is mounted read-only inside the runtime container 47 | readOnly: false 48 | 49 | # the path, within the code volume (git repo), where the 'wp-content' is 50 | # available 51 | contentSubPath: wp-content/ 52 | 53 | git: 54 | repository: https://github.com/presslabs/stack-example-wordpress 55 | # it is not recommended to use a 'moving' target for deployment like a 56 | # branch name. You should use a specific commit or a git tag. 57 | reference: master 58 | 59 | media: 60 | # Store media library in a Google Cloud Storage bucket 61 | gcs: 62 | # bucket name 63 | bucket: my-gcs-bucket 64 | # use a prefix inside the bucket to store the media files 65 | prefix: my-site/ 66 | # add a service account key with access the specified bucket 67 | # https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating_service_account_keys 68 | google_credentials: > 69 | 70 | mysql: 71 | mysqlConf: {} 72 | replicaCount: 1 73 | 74 | memcached: 75 | replicaCount: 1 76 | ``` 77 | -------------------------------------------------------------------------------- /git-webhook/Makefile: -------------------------------------------------------------------------------- 1 | BINDIR ?= $(CURDIR)/../bin 2 | 3 | # Run tests 4 | test: 5 | $(BINDIR)/ginkgo version 6 | $(BINDIR)/ginkgo \ 7 | --randomizeAllSpecs --randomizeSuites --failOnPending \ 8 | --cover --coverprofile cover.out --trace --race \ 9 | ./pkg/... 10 | 11 | # Build git-webhook binary 12 | build: fmt vet 13 | go build -o bin/git-webhook . 14 | 15 | # Run against the configured Kubernetes cluster in ~/.kube/config 16 | run: fmt vet 17 | go run ./main.go 18 | 19 | # Run go fmt against code 20 | fmt: 21 | go fmt ./pkg/... 22 | 23 | # Run go vet against code 24 | vet: 25 | go vet ./pkg/... 26 | 27 | lint: 28 | $(BINDIR)/golangci-lint version 29 | GOGC=off $(BINDIR)/golangci-lint run ./pkg/... 30 | -------------------------------------------------------------------------------- /git-webhook/README.md: -------------------------------------------------------------------------------- 1 | git-webhook 2 | === 3 | 4 | It's a simple HTTP server that can be feed with github events and updates 5 | WordPress sites references. It updates all WordPress resources with proper 6 | annotations. 7 | 8 | ## Annotations 9 | 10 | | Annotation | Description | 11 | | --- | --- | 12 | | `stack.presslabs.org/git-follow-name` | The git reference to follow. Usually a branch name | 13 | 14 | ## Quirks 15 | * When setting up a GitHub webhook you must choose to receive JSON data payloads, otherwise the git-webhook server won't know how to decode the message. 16 | -------------------------------------------------------------------------------- /git-webhook/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Pressinfa SRL 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "flag" 21 | "os" 22 | 23 | "github.com/go-logr/zapr" 24 | logf "github.com/presslabs/controller-util/log" 25 | _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" 26 | "sigs.k8s.io/controller-runtime/pkg/client/config" 27 | "sigs.k8s.io/controller-runtime/pkg/manager" 28 | "sigs.k8s.io/controller-runtime/pkg/manager/signals" 29 | 30 | wordpressv1alpha1 "github.com/bitpoke/wordpress-operator/pkg/apis/wordpress/v1alpha1" 31 | 32 | "github.com/bitpoke/stack/git-webhook/pkg/webhook" 33 | ) 34 | 35 | var log = logf.Log.WithName("git-webhook") 36 | 37 | func main() { 38 | devMode := os.Getenv("DEVELOPMENT") == "true" 39 | flag.Parse() 40 | zapLogger := logf.RawStackdriverZapLoggerTo(os.Stderr, devMode) 41 | logf.SetLogger(zapr.NewLogger(zapLogger)) 42 | entryLog := log.WithName("entrypoint") 43 | 44 | // Setup a Manager 45 | entryLog.Info("setting up manager") 46 | mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{}) 47 | if err != nil { 48 | entryLog.Error(err, "unable to set up overall controller manager") 49 | os.Exit(1) 50 | } 51 | 52 | // Setup Scheme for all resources 53 | entryLog.Info("setting up scheme") 54 | if err := wordpressv1alpha1.SchemeBuilder.AddToScheme(mgr.GetScheme()); err != nil { 55 | log.Error(err, "unable add APIs to scheme") 56 | os.Exit(1) 57 | } 58 | 59 | entryLog.Info("setting up webhook server") 60 | if err := webhook.Add(mgr); err != nil { 61 | entryLog.Error(err, "unable to set up webhook server") 62 | os.Exit(1) 63 | } 64 | 65 | entryLog.Info("starting manager") 66 | if err := mgr.Start(signals.SetupSignalHandler()); err != nil { 67 | entryLog.Error(err, "unable to run manager") 68 | os.Exit(1) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /git-webhook/pkg/webhook/git/git.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | "regexp" 5 | 6 | "github.com/pkg/errors" 7 | ) 8 | 9 | var regex = regexp.MustCompile(`(github\.com\/[a-zA-Z0-9-_]+\/[a-zA-Z0-9-_]+)`) 10 | 11 | func NormalizeGitRepoUrl(repoUrl string) (string, error) { 12 | submatch := regex.FindStringSubmatch(repoUrl) 13 | if len(submatch) == 0 { 14 | return "", errors.New("invalid git repository url") 15 | } 16 | return submatch[0], nil 17 | } 18 | 19 | func GitRepoFollowedRef(repoUrl, branch string) (string, error) { 20 | gitUrl, err := NormalizeGitRepoUrl(repoUrl) 21 | if err != nil { 22 | return "", err 23 | } 24 | 25 | return gitUrl + "." + branch, nil 26 | } 27 | -------------------------------------------------------------------------------- /git-webhook/pkg/webhook/webhook_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Pressinfra SRL. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package webhook 18 | 19 | import ( 20 | "context" 21 | "path/filepath" 22 | "testing" 23 | 24 | . "github.com/onsi/ginkgo" 25 | . "github.com/onsi/gomega" 26 | 27 | wordpressv1alpha1 "github.com/bitpoke/wordpress-operator/pkg/apis/wordpress/v1alpha1" 28 | "github.com/go-logr/zapr" 29 | logf "github.com/presslabs/controller-util/log" 30 | "k8s.io/client-go/kubernetes/scheme" 31 | "k8s.io/client-go/rest" 32 | "sigs.k8s.io/controller-runtime/pkg/envtest" 33 | "sigs.k8s.io/controller-runtime/pkg/envtest/printer" 34 | "sigs.k8s.io/controller-runtime/pkg/manager" 35 | ) 36 | 37 | var cfg *rest.Config 38 | var t *envtest.Environment 39 | 40 | func TestWebhook(t *testing.T) { 41 | RegisterFailHandler(Fail) 42 | RunSpecsWithDefaultAndCustomReporters(t, "Webhook Suite", []Reporter{printer.NewlineReporter{}}) 43 | } 44 | 45 | var _ = BeforeSuite(func() { 46 | var err error 47 | 48 | zapLogger := logf.RawStackdriverZapLoggerTo(GinkgoWriter, true) 49 | logf.SetLogger(zapr.NewLogger(zapLogger)) 50 | 51 | t = &envtest.Environment{ 52 | CRDDirectoryPaths: []string{ 53 | filepath.Join("..", "..", "..", "deploy"), 54 | }, 55 | } 56 | Expect(wordpressv1alpha1.SchemeBuilder.AddToScheme(scheme.Scheme)).To(Succeed()) 57 | 58 | cfg, err = t.Start() 59 | Expect(err).NotTo(HaveOccurred()) 60 | }) 61 | 62 | var _ = AfterSuite(func() { 63 | Expect(t.Stop()).To(Succeed()) 64 | }) 65 | 66 | // StartTestManager adds recFn 67 | func StartTestManager(mgr manager.Manager) context.CancelFunc { 68 | ctx, stop := context.WithCancel(context.Background()) 69 | 70 | go func() { 71 | defer GinkgoRecover() 72 | Expect(mgr.Start(ctx)).To(Succeed()) 73 | }() 74 | 75 | return stop 76 | } 77 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/bitpoke/stack 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/bitpoke/wordpress-operator v0.12.0 7 | github.com/drone/go-scm v0.0.0 8 | github.com/go-logr/logr v0.4.0 9 | github.com/go-logr/zapr v0.4.0 10 | github.com/onsi/ginkgo v1.16.4 11 | github.com/onsi/gomega v1.15.0 12 | github.com/pkg/errors v0.9.1 13 | github.com/presslabs/controller-util v0.3.0 14 | github.com/prometheus/client_golang v1.11.1 15 | k8s.io/apimachinery v0.21.4 16 | k8s.io/client-go v0.21.4 17 | sigs.k8s.io/controller-runtime v0.9.7 18 | ) 19 | 20 | require ( 21 | cloud.google.com/go v0.54.0 // indirect 22 | github.com/beorn7/perks v1.0.1 // indirect 23 | github.com/blendle/zapdriver v1.3.1 // indirect 24 | github.com/cespare/xxhash/v2 v2.1.1 // indirect 25 | github.com/davecgh/go-spew v1.1.1 // indirect 26 | github.com/evanphx/json-patch v4.11.0+incompatible // indirect 27 | github.com/fsnotify/fsnotify v1.4.9 // indirect 28 | github.com/gogo/protobuf v1.3.2 // indirect 29 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect 30 | github.com/golang/protobuf v1.5.2 // indirect 31 | github.com/google/go-cmp v0.5.5 // indirect 32 | github.com/google/gofuzz v1.1.0 // indirect 33 | github.com/google/uuid v1.1.2 // indirect 34 | github.com/googleapis/gnostic v0.5.5 // indirect 35 | github.com/hashicorp/golang-lru v0.5.4 // indirect 36 | github.com/imdario/mergo v0.3.12 // indirect 37 | github.com/json-iterator/go v1.1.11 // indirect 38 | github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect 39 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 40 | github.com/modern-go/reflect2 v1.0.1 // indirect 41 | github.com/nxadm/tail v1.4.8 // indirect 42 | github.com/prometheus/client_model v0.2.0 // indirect 43 | github.com/prometheus/common v0.26.0 // indirect 44 | github.com/prometheus/procfs v0.6.0 // indirect 45 | github.com/spf13/pflag v1.0.5 // indirect 46 | go.uber.org/atomic v1.7.0 // indirect 47 | go.uber.org/multierr v1.6.0 // indirect 48 | go.uber.org/zap v1.19.0 // indirect 49 | golang.org/x/net v0.8.0 // indirect 50 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect 51 | golang.org/x/sys v0.8.0 // indirect 52 | golang.org/x/term v0.6.0 // indirect 53 | golang.org/x/text v0.8.0 // indirect 54 | golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect 55 | gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect 56 | google.golang.org/appengine v1.6.7 // indirect 57 | google.golang.org/protobuf v1.26.0 // indirect 58 | gopkg.in/inf.v0 v0.9.1 // indirect 59 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 60 | gopkg.in/yaml.v2 v2.4.0 // indirect 61 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 62 | k8s.io/api v0.21.4 // indirect 63 | k8s.io/apiextensions-apiserver v0.21.4 // indirect 64 | k8s.io/component-base v0.21.4 // indirect 65 | k8s.io/klog/v2 v2.10.0 // indirect 66 | k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 // indirect 67 | k8s.io/utils v0.0.0-20210802155522-efc7438f0176 // indirect 68 | sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect 69 | sigs.k8s.io/yaml v1.2.0 // indirect 70 | ) 71 | 72 | replace github.com/drone/go-scm v0.0.0 => github.com/bitpoke/go-scm v1.5.1-0.20200708152012-713e9c5029bc 73 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Bitpoke Soft SRL 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /hack/serve-docs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2019 Pressinfra SRL 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | ROOT_DIR="$(dirname "${BASH_SOURCE[0]}")/.." 22 | 23 | cd "${ROOT_DIR}" 24 | 25 | PWD=$(pwd) 26 | 27 | set -x 28 | 29 | docker run --rm -p 1313:1313 \ 30 | -v "$PWD/docs:/site/content" \ 31 | -v "$PWD/public:/site/public" \ 32 | -v "$PWD/.git:/site/.git" \ 33 | gcr.io/pl-infra/hugo:latest \ 34 | --config=/site/content/config.toml \ 35 | --bind 0.0.0.0 -b http://localhost:1313/ \ 36 | --enableGitInfo server 37 | -------------------------------------------------------------------------------- /images/stack-default-backend/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copy Bitpoke Stack's default-bakend binary into a thin image 2 | # The image is pinned to the nonroot tag 3 | FROM gcr.io/distroless/base-debian11@sha256:46d4514c17aca7a68559ee03975983339fc548e6d1014e2d7633f9123f2d3c59 4 | COPY rootfs / 5 | ENTRYPOINT ["/default-backend"] 6 | -------------------------------------------------------------------------------- /images/stack-default-backend/Makefile: -------------------------------------------------------------------------------- 1 | PLATFORMS := linux_amd64 2 | include ../../build/makelib/common.mk 3 | 4 | IMAGE = $(BUILD_REGISTRY)/stack-default-backend-$(ARCH) 5 | CACHE_IMAGES = $(IMAGE) 6 | include ../../build/makelib/image.mk 7 | 8 | img.build: 9 | @$(INFO) docker build $(IMAGE) $(IMAGE_PLATFORM) 10 | @cp -La . $(IMAGE_TEMP_DIR) 11 | @cp -La ./rootfs $(IMAGE_TEMP_DIR) 12 | @cp $(OUTPUT_DIR)/bin/linux_$(ARCH)/default-backend $(IMAGE_TEMP_DIR)/rootfs/default-backend 13 | @docker buildx build $(BUILD_ARGS) \ 14 | --platform $(IMAGE_PLATFORM) \ 15 | -t $(IMAGE) \ 16 | --build-arg ARCH=$(ARCH) \ 17 | $(IMAGE_TEMP_DIR) 18 | @$(OK) docker build $(IMAGE) 19 | 20 | -------------------------------------------------------------------------------- /images/stack-git-webhook/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copy Bitpoke Stack's default-bakend binary into a thin image 2 | # The image is pinned to the nonroot tag 3 | FROM gcr.io/distroless/base-debian11@sha256:46d4514c17aca7a68559ee03975983339fc548e6d1014e2d7633f9123f2d3c59 4 | COPY rootfs / 5 | ENTRYPOINT ["/git-webhook"] 6 | -------------------------------------------------------------------------------- /images/stack-git-webhook/Makefile: -------------------------------------------------------------------------------- 1 | PLATFORMS := linux_amd64 2 | include ../../build/makelib/common.mk 3 | 4 | IMAGE = $(BUILD_REGISTRY)/stack-git-webhook-$(ARCH) 5 | CACHE_IMAGES = $(IMAGE) 6 | include ../../build/makelib/image.mk 7 | 8 | img.build: 9 | @$(INFO) docker build $(IMAGE) $(IMAGE_PLATFORM) 10 | @cp -La . $(IMAGE_TEMP_DIR) 11 | @mkdir -p $(IMAGE_TEMP_DIR)/rootfs 12 | @cp $(OUTPUT_DIR)/bin/linux_$(ARCH)/git-webhook $(IMAGE_TEMP_DIR)/rootfs 13 | @docker buildx build $(BUILD_ARGS) \ 14 | --platform $(IMAGE_PLATFORM) \ 15 | -t $(IMAGE) \ 16 | --build-arg ARCH=$(ARCH) \ 17 | $(IMAGE_TEMP_DIR) 18 | @$(OK) docker build $(IMAGE) 19 | 20 | -------------------------------------------------------------------------------- /load-testing/README.md: -------------------------------------------------------------------------------- 1 | Load Testing 2 | === 3 | 4 | Here is the load testing scenarios for a stack deployed wordpress site 5 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/Chart.yaml: -------------------------------------------------------------------------------- 1 | name: locust 2 | description: A modern load testing framework 3 | version: 0.2.0 4 | appVersion: 0.7.5 5 | maintainers: 6 | - name: Vincent De Smet 7 | email: vincent.drl@gmail.com 8 | home: http://locust.io 9 | icon: https://pbs.twimg.com/profile_images/1867636195/locust-logo-orignal.png 10 | sources: 11 | - https://github.com/honestbee/distributed-load-testing 12 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/README.md: -------------------------------------------------------------------------------- 1 | # Locust Helm Chart 2 | 3 | This is a templated deployment of [Locust](http://locust.io) for Distributed Load 4 | testing using Kubernetes. 5 | 6 | ## Pre Requisites: 7 | 8 | * Requires (and tested with) helm `v2.1.2` or above. 9 | 10 | ## Chart details 11 | 12 | This chart will do the following: 13 | 14 | * Convert all files in `tasks/` folder into a configmap 15 | * Create a Locust master and Locust worker deployment with the Target host 16 | and Tasks file specified. 17 | 18 | 19 | ### Installing the chart 20 | 21 | To install the chart with the release name `locust-nymph` in the default namespace: 22 | 23 | ```bash 24 | helm install -n locust-nymph --set master.config.target-host=http://site.example.com stable/locust 25 | ``` 26 | 27 | | Parameter | Description | Default | 28 | | ---------------------------- | ---------------------------------- | ----------------------------------------------------- | 29 | | `Name` | Locust master name | `locust` | 30 | | `image.repository` | Locust container image name | `quay.io/honestbee/locust` | 31 | | `image.tag` | Locust Container image tag | `0.7.5` | 32 | | `service.type` | k8s service type exposing master | `NodePort` | 33 | | `service.nodePort` | Port on cluster to expose master | `0` | 34 | | `service.annotations` | KV containing custom annotations | `{}` | 35 | | `service.extraLabels` | KV containing extra labels | `{}` | 36 | | `master.config.target-host` | locust target host | `http://site.example.com` | 37 | | `worker.config.locust-script`| locust script to run | `/locust-tasks/tasks.py` | 38 | | `worker.replicaCount` | Number of workers to run | `2` | 39 | 40 | Specify parameters using `--set key=value[,key=value]` argument to `helm install` 41 | 42 | Alternatively a YAML file that specifies the values for the parameters can be provided like this: 43 | 44 | ```bash 45 | $ helm install --name my-release -f values.yaml stable/locust 46 | ``` 47 | 48 | You can start the swarm from the command line using Port forwarding as follows: 49 | 50 | Get the Locust URL following the Post Installation notes. 51 | 52 | for example: 53 | ```bash 54 | export LOCUST_URL=http://127.0.0.1:8089 55 | ``` 56 | 57 | Start / Monitor & Stop the Locust swarm via the web panel or with following commands: 58 | 59 | Start: 60 | ```bash 61 | curl -XPOST $LOCUST_URL/swarm -d"locust_count=100&hatch_rate=10" 62 | ``` 63 | 64 | Monitor: 65 | ```bash 66 | watch -n 1 "curl -s $LOCUST_URL/stats/requests | jq -r '[.user_count, .total_rps, .state] | @tsv'" 67 | ``` 68 | 69 | Stop: 70 | ```bash 71 | curl $LOCUST_URL/stop 72 | ``` 73 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/tasks/locustfile.py: -------------------------------------------------------------------------------- 1 | from locust import HttpLocust, TaskSet, task 2 | 3 | class LocustTasks(TaskSet): 4 | @task 5 | def index(self): 6 | self.client.get("/") 7 | 8 | class Locust(HttpLocust): 9 | task_set = LocustTasks 10 | min_wait = 1000 11 | max_wait = 3000 12 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | {{ .Chart.Name }} installed! 2 | 3 | Get the Locust URL to visit by running these commands in the same shell: 4 | 5 | {{- if contains "NodePort" .Values.master.service.type }} 6 | export NODE_PORT=$(kubectl get svc -n {{ .Release.Namespace }} {{ template "locust.fullname" . }} -o jsonpath='{.spec.ports[?(@.name=="{{ .Values.master.service.name }}")].nodePort}') 7 | export NODE_IP=$(kubectl get no -o jsonpath="{.items[0].status.addresses[0].address}") 8 | export LOCUST_URL=http://$NODE_IP:$NODE_PORT/ 9 | 10 | {{- else if contains "LoadBalancer" .Values.master.service.type }} 11 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 12 | You can watch the status by running 'kubectl get svc -n {{ .Release.Namespace }} -w {{ template "locust.fullname" . }}' 13 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "locust.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") 14 | export LOCUST_URL=http://$SERVICE_IP:{{ .Values.master.service.externalPort }}/ 15 | 16 | {{- else if contains "ClusterIP" .Values.master.service.type }} 17 | export POD_NAME=$(kubectl get po --namespace {{ .Release.Namespace }} -l "app={{ template "locust.fullname" . }},component=master" -o jsonpath="{.items[0].metadata.name}") 18 | export LOCUST_URL=http://127.0.0.1:{{ .Values.master.service.externalPort }} 19 | kubectl port-forward $POD_NAME {{ .Values.master.service.externalPort }}:{{ .Values.master.service.externalPort }} & 20 | 21 | {{- end }} 22 | 23 | For more information on Distributed load testing on Kubernetes using Locust, visit: 24 | https://cloud.google.com/solutions/distributed-load-testing-using-kubernetes 25 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "locust.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | */}} 13 | {{- define "locust.fullname" -}} 14 | {{- if .Values.fullnameOverride -}} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 16 | {{- else -}} 17 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 18 | {{- end -}} 19 | {{- end -}} 20 | 21 | {{/* 22 | Create chart name and version as used by the chart label. 23 | */}} 24 | {{- define "locust.chart" -}} 25 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 26 | {{- end -}} 27 | 28 | {{- define "locust.workerName" -}} 29 | {{- printf "%s-worker" (include "locust.fullname" .) | trunc 63 | trimSuffix "-" -}} 30 | {{- end -}} 31 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ include "locust.fullname" . }} 5 | labels: 6 | app.kubernetes.io/name: locust-master 7 | app.kubernetes.io/part-of: locust 8 | helm.sh/chart: {{ include "locust.chart" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/managed-by: {{ .Release.Service }} 11 | name: {{ include "locust.fullname" . }} 12 | data: 13 | {{ (.Files.Glob "tasks/*").AsConfig | indent 2 }} 14 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/templates/master-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "locust.fullname" . }} 5 | labels: 6 | app.kubernetes.io/name: locust-master 7 | app.kubernetes.io/part-of: locust 8 | helm.sh/chart: {{ include "locust.chart" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/managed-by: {{ .Release.Service }} 11 | spec: 12 | replicas: 1 13 | strategy: 14 | type: Recreate 15 | selector: 16 | matchLabels: 17 | app.kubernetes.io/name: locust-master 18 | app.kubernetes.io/instance: {{ .Release.Name }} 19 | app.kubernetes.io/part-of: locust 20 | template: 21 | metadata: 22 | annotations: 23 | checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} 24 | labels: 25 | app.kubernetes.io/name: locust-master 26 | app.kubernetes.io/instance: {{ .Release.Name }} 27 | app.kubernetes.io/part-of: locust 28 | spec: 29 | containers: 30 | - name: locust 31 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 32 | imagePullPolicy: {{ .Values.image.pullPolicy }} 33 | env: 34 | {{- if eq .Values.config.mode "standalone" }} 35 | - name: LOCUST_MODE 36 | value: "standalone" 37 | {{- else }} 38 | - name: LOCUST_MODE 39 | value: "master" 40 | {{- end }} 41 | - name: LOCUST_TARGET_HOST 42 | value: {{ required "A valid .config.target url is required!" .Values.config.target }} 43 | - name: LOCUST_LOCUSTFILE_PATH 44 | value: /locust-tasks/{{ .Values.config.locustfile }} 45 | ports: 46 | - containerPort: {{ .Values.master.service.internalPort }} 47 | name: http 48 | protocol: TCP 49 | - containerPort: 5557 50 | name: master-p1 51 | protocol: TCP 52 | - containerPort: 5558 53 | name: master-p2 54 | protocol: TCP 55 | volumeMounts: 56 | - name: locust-tasks 57 | mountPath: /locust-tasks/ 58 | livenessProbe: 59 | periodSeconds: 30 60 | httpGet: 61 | path: / 62 | port: {{ .Values.master.service.internalPort }} 63 | readinessProbe: 64 | periodSeconds: 30 65 | httpGet: 66 | path: / 67 | port: {{ .Values.master.service.internalPort }} 68 | resources: 69 | {{ toYaml .Values.worker.resources | indent 10 }} 70 | restartPolicy: Always 71 | volumes: 72 | - name: "locust-tasks" 73 | configMap: 74 | name: {{ include "locust.fullname" . }} 75 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/templates/master-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "locust.fullname" . }} 5 | labels: 6 | app.kubernetes.io/name: locust-master 7 | app.kubernetes.io/part-of: locust 8 | helm.sh/chart: {{ include "locust.chart" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/managed-by: {{ .Release.Service }} 11 | spec: 12 | type: {{ .Values.master.service.type }} 13 | ports: 14 | - name: http 15 | port: {{ .Values.master.service.externalPort }} 16 | targetPort: {{ .Values.master.service.internalPort }} 17 | protocol: TCP 18 | - name: master-p1 19 | port: 5557 20 | protocol: TCP 21 | targetPort: 5557 22 | - name: master-p2 23 | port: 5558 24 | protocol: TCP 25 | targetPort: 5558 26 | selector: 27 | app.kubernetes.io/name: locust-master 28 | app.kubernetes.io/part-of: locust 29 | app.kubernetes.io/instance: {{ .Release.Name }} 30 | sessionAffinity: None 31 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/templates/worker-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- if not (eq .Values.config.mode "standalone") }} 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ include "locust.workerName" . }} 6 | labels: 7 | app.kubernetes.io/name: locust-worker 8 | app.kubernetes.io/part-of: locust 9 | helm.sh/chart: {{ include "locust.chart" . }} 10 | app.kubernetes.io/instance: {{ .Release.Name }} 11 | app.kubernetes.io/managed-by: {{ .Release.Service }} 12 | spec: 13 | replicas: {{ default 2 .Values.worker.replicaCount }} 14 | strategy: 15 | type: RollingUpdate 16 | rollingUpdate: 17 | maxSurge: {{ default 1 .Values.worker.maxSurge }} 18 | maxUnavailable: {{ default 1 .Values.worker.maxUnavailable }} 19 | selector: 20 | matchLabels: 21 | app.kubernetes.io/name: locust-worker 22 | app.kubernetes.io/instance: {{ .Release.Name }} 23 | app.kubernetes.io/part-of: locust 24 | template: 25 | metadata: 26 | annotations: 27 | checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} 28 | helm.sh/release-revision: {{ .Release.Revision | quote }} 29 | labels: 30 | app.kubernetes.io/name: locust-worker 31 | app.kubernetes.io/instance: {{ .Release.Name }} 32 | app.kubernetes.io/part-of: locust 33 | spec: 34 | containers: 35 | - name: locust 36 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 37 | imagePullPolicy: {{ .Values.image.pullPolicy }} 38 | volumeMounts: 39 | - name: locust-tasks 40 | mountPath: /locust-tasks/ 41 | env: 42 | - name: LOCUST_MODE 43 | value: "slave" 44 | - name: LOCUST_TARGET_HOST 45 | value: {{ required "A valid .config.target url is required!" .Values.config.target }} 46 | - name: LOCUST_MASTER 47 | value: {{ include "locust.fullname" . }} 48 | - name: LOCUST_LOCUSTFILE_PATH 49 | value: /locust-tasks/{{ .Values.config.locustfile }} 50 | resources: 51 | {{ toYaml .Values.worker.resources | indent 10 }} 52 | restartPolicy: Always 53 | volumes: 54 | - name: "locust-tasks" 55 | configMap: 56 | name: {{ include "locust.fullname" . }} 57 | {{- end }} 58 | -------------------------------------------------------------------------------- /load-testing/locust/charts/locust/values.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | repository: docker.io/peterevans/locust 3 | tag: 1.2.1 4 | pullPolicy: IfNotPresent 5 | 6 | config: 7 | mode: distributed 8 | target: "" 9 | locustfile: locustfile.py 10 | 11 | master: 12 | service: 13 | type: ClusterIP 14 | externalPort: 8089 15 | internalPort: 8089 16 | nodePort: 0 17 | resources: 18 | limits: 19 | cpu: 100m 20 | memory: 128Mi 21 | requests: 22 | cpu: 100m 23 | memory: 128Mi 24 | 25 | worker: 26 | replicaCount: 1 27 | resources: 28 | requests: 29 | cpu: 1 30 | memory: 3Gi 31 | -------------------------------------------------------------------------------- /presets/gke.yaml: -------------------------------------------------------------------------------- 1 | component_default: &component_default 2 | resources: 3 | requests: 4 | memory: "256Mi" 5 | cpu: "100m" 6 | nodeSelector: 7 | "node-role.stack.presslabs.org/presslabs-sys": "" 8 | tolerations: 9 | - key: "CriticalAddonsOnly" 10 | operator: "Exists" 11 | 12 | wordpress-operator: 13 | <<: *component_default 14 | 15 | mysql-operator: 16 | <<: *component_default 17 | orchestrator: 18 | <<: *component_default 19 | 20 | nginx-ingress: 21 | controller: 22 | <<: *component_default 23 | config: 24 | proxy-buffer-size: 64k 25 | custom-http-errors: 502,503,504 26 | hsts-preload: "true" 27 | log-format-escape-json: "true" 28 | log-format-upstream: '{ 29 | "time": "$time_iso8601", 30 | "httpRequest": { 31 | "requestMethod": "$request_method", 32 | "requestUrl": "$scheme://$host$request_uri", 33 | "requestSize": "$request_length", 34 | "status": $status, 35 | "responseSize": "$bytes_sent", 36 | "userAgent": "$http_user_agent", 37 | "remoteIp": "$remote_addr", 38 | "referer": "$http_referer", 39 | "latency": "${request_time}s", 40 | "protocol": "$server_protocol" 41 | }, 42 | "trace": "$req_id", 43 | "upstream": "$proxy_upstream_name" 44 | }' 45 | replicaCount: 2 46 | minAvailable: 1 47 | resources: 48 | requests: 49 | memory: "768Mi" 50 | cpu: "500m" 51 | service: 52 | externalTrafficPolicy: Local 53 | 54 | defaultBackend: 55 | <<: *component_default 56 | replicaCount: 2 57 | minAvailable: 1 58 | 59 | prometheus-operator: 60 | prometheusOperator: 61 | <<: *component_default 62 | grafana: 63 | <<: *component_default 64 | kube-state-metrics: 65 | <<: *component_default 66 | prometheus-node-exporter: 67 | tolerations: 68 | - operator: "Exists" 69 | 70 | cert-manager: 71 | <<: *component_default 72 | cainjector: 73 | <<: *component_default 74 | webhook: 75 | <<: *component_default 76 | -------------------------------------------------------------------------------- /presets/minikube.yaml: -------------------------------------------------------------------------------- 1 | mysql-operator: 2 | orchestrator: 3 | antiAffinity: soft 4 | replicas: 1 5 | -------------------------------------------------------------------------------- /skaffold.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: skaffold/v2beta5 2 | kind: Config 3 | build: 4 | artifacts: 5 | - image: quay.io/presslabs/default-backend 6 | docker: 7 | dockerfile: Dockerfile.default-backend 8 | - image: quay.io/presslabs/git-webhook 9 | docker: 10 | dockerfile: Dockerfile.git-webhook 11 | tagPolicy: 12 | sha256: {} 13 | deploy: 14 | helm: 15 | releases: 16 | - name: stack 17 | chartPath: charts/stack 18 | artifactOverrides: 19 | git-webhook.image: quay.io/presslabs/git-webhook 20 | nginx-ingress.defaultBackend.image: quay.io/presslabs/default-backend 21 | namespace: presslabs-system 22 | setValues: 23 | mysql-operator.enabled: "true" 24 | prometheus-operator.enabled: "true" 25 | wordpress-operator.enabled: "true" 26 | imageStrategy: 27 | helm: {} 28 | -------------------------------------------------------------------------------- /terraform/examples/eks/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | version = "~> 2.0" 3 | region = "${var.region}" 4 | } 5 | 6 | variable "cluster_name" { 7 | type = "string" 8 | } 9 | 10 | variable "region" { 11 | type = "string" 12 | default = "eu-central-1" 13 | } 14 | 15 | variable "zones" { 16 | type = "list" 17 | default = ["eu-central-1a", "eu-central-1b"] 18 | } 19 | 20 | variable "system_instance_type" { 21 | type = "string" 22 | default = "m5.large" 23 | } 24 | 25 | variable "database_instance_type" { 26 | type = "string" 27 | default = "m5.xlarge" 28 | } 29 | 30 | variable "wordpress_instance_type" { 31 | type = "string" 32 | default = "m5.xlarge" 33 | } 34 | 35 | variable "wordpress_spot_price" { 36 | type = "string" 37 | default = "0.14" 38 | } 39 | 40 | variable "system_spot_price" { 41 | type = "string" 42 | default = "" 43 | } 44 | 45 | variable "database_spot_price" { 46 | type = "string" 47 | default = "" 48 | } 49 | 50 | variable "wordpress_spot_only" { 51 | default = false 52 | } 53 | 54 | module "stack" { 55 | source = "../../modules/eks" 56 | cluster_name = "${var.cluster_name}" 57 | zones = "${var.zones}" 58 | 59 | system_instance_type = "${var.system_instance_type}" 60 | system_spot_price = "${var.system_spot_price}" 61 | 62 | database_instance_type = "${var.database_instance_type}" 63 | database_spot_price = "${var.database_spot_price}" 64 | 65 | wordpress_instance_type = "${var.wordpress_instance_type}" 66 | wordpress_spot_price = "${var.wordpress_spot_price}" 67 | wordpress_spot_only = "${var.wordpress_spot_only}" 68 | } 69 | -------------------------------------------------------------------------------- /terraform/examples/gke/main.tf: -------------------------------------------------------------------------------- 1 | provider "google-beta" { 2 | version = "~> 2.0" 3 | project = "${var.project}" 4 | region = "${var.region}" 5 | zone = "${var.zone}" 6 | } 7 | 8 | variable "project" { 9 | type = "string" 10 | } 11 | 12 | variable "region" { 13 | type = "string" 14 | default = "europe-west3" 15 | } 16 | 17 | variable "zone" { 18 | type = "string" 19 | default = "europe-west3-a" 20 | } 21 | 22 | variable "zones" { 23 | type = "list" 24 | default = ["europe-west3-a", "europe-west3-b"] 25 | } 26 | 27 | variable "preemptible" { 28 | default = false 29 | } 30 | 31 | variable "cluster_name" { 32 | type = "string" 33 | } 34 | 35 | variable "system_node_type" { 36 | type = "string" 37 | default = "n1-standard-2" 38 | } 39 | 40 | variable "database_node_type" { 41 | type = "string" 42 | default = "n1-standard-2" 43 | } 44 | 45 | variable "wordpress_node_type" { 46 | type = "string" 47 | default = "n1-standard-4" 48 | } 49 | 50 | module "stack" { 51 | source = "../../modules/gke" 52 | cluster_name = "${var.cluster_name}" 53 | project = "${var.project}" 54 | region = "${var.region}" 55 | zones = "${var.zones}" 56 | preemptible = "${var.preemptible}" 57 | system_node_type = "${var.system_node_type}" 58 | database_node_type = "${var.database_node_type}" 59 | wordpress_node_type = "${var.wordpress_node_type}" 60 | } 61 | -------------------------------------------------------------------------------- /terraform/modules/eks/iam.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_policy" "stack-ClusterAutoscaler" { 2 | name = "${var.cluster_name}-autoscaler" 3 | description = "Allow access to ASGs for cluster-autoscaler" 4 | 5 | policy = <