added healthz endpoint, misc improvements and docs review
update use default templates where there are not user-specific settings improved Dockerfile renamed healthz endoint delete deprecated file fixed healthz endpoint improved build and deployment updated docs
This commit is contained in:
parent
fa73d0a6f8
commit
250b9aeb03
|
@ -1,4 +1,4 @@
|
||||||
FROM alpine:3.9.6
|
FROM alpine:3.11.6
|
||||||
|
|
||||||
ARG RUNTIME_USER="mxgateway"
|
ARG RUNTIME_USER="mxgateway"
|
||||||
ARG RUNTIME_USER_UID=4583
|
ARG RUNTIME_USER_UID=4583
|
||||||
|
@ -7,11 +7,8 @@ RUN addgroup -g $RUNTIME_USER_UID $RUNTIME_USER && \
|
||||||
adduser --disabled-password --no-create-home --gecos "" \
|
adduser --disabled-password --no-create-home --gecos "" \
|
||||||
--home /app --ingroup $RUNTIME_USER --uid $RUNTIME_USER_UID $RUNTIME_USER
|
--home /app --ingroup $RUNTIME_USER --uid $RUNTIME_USER_UID $RUNTIME_USER
|
||||||
|
|
||||||
COPY entrypoint.sh \
|
COPY entrypoint.sh bin/hugo-mx-gateway LICENSE /app/
|
||||||
bin/hugo-mx-gateway \
|
COPY templates /app/templates
|
||||||
templates \
|
|
||||||
LICENSE \
|
|
||||||
/app/
|
|
||||||
|
|
||||||
RUN chown -R $RUNTIME_USER:$RUNTIME_USER /app
|
RUN chown -R $RUNTIME_USER:$RUNTIME_USER /app
|
||||||
|
|
||||||
|
|
3
Makefile
3
Makefile
|
@ -3,6 +3,7 @@ DOCKER_IMAGE_REPO=rchakode/hugo-mx-gateway
|
||||||
ARCH=$$(uname -m)
|
ARCH=$$(uname -m)
|
||||||
GOCMD=GO111MODULE=on go
|
GOCMD=GO111MODULE=on go
|
||||||
GOBUILD=$(GOCMD) build
|
GOBUILD=$(GOCMD) build
|
||||||
|
GOBUILD_FLAGS=-a -tags netgo -ldflags '-w -extldflags "-static"'
|
||||||
GOCLEAN=$(GOCMD) clean
|
GOCLEAN=$(GOCMD) clean
|
||||||
GOTEST=$(GOCMD) test
|
GOTEST=$(GOCMD) test
|
||||||
GOVENDOR=$(GOCMD) mod vendor
|
GOVENDOR=$(GOCMD) mod vendor
|
||||||
|
@ -16,7 +17,7 @@ vendor:
|
||||||
$(GOVENDOR)
|
$(GOVENDOR)
|
||||||
|
|
||||||
build:
|
build:
|
||||||
$(GOBUILD) -o $(PACKAGE_NAME) -v
|
$(GOBUILD) $(GOBUILD_FLAGS) -o $(PACKAGE_NAME) -v
|
||||||
|
|
||||||
build-ci:
|
build-ci:
|
||||||
docker run --rm -it \
|
docker run --rm -it \
|
||||||
|
|
22
README.md
22
README.md
|
@ -46,14 +46,16 @@ This screenshot show an example of a form successfully submitted and handled by
|
||||||
# Configuration variables
|
# Configuration variables
|
||||||
According to your deployment approach (Google App Engine, Kubernetes or Docker), you must provide the following configuration parameters as environment variables:
|
According to your deployment approach (Google App Engine, Kubernetes or Docker), you must provide the following configuration parameters as environment variables:
|
||||||
|
|
||||||
* `SMTP_SERVER_ADDR`: set the IP or the hostname of the SMTP server. Currently, it's required that the SMTP server being supporting TLS.
|
* `SMTP_SERVER_ADDR`: Set the address of the SMTP server in the form of `host:port`. It's required that the SMTP server being supporting TLS.
|
||||||
* `SMTP_VERITY_CERT`: Tell if the `hugo-mx-gateway` App should validate the SMTP certificate against valid authorities. If you're using a self-signed certificate on the SMTP server, this value must be set to `false`.
|
* `SMTP_VERITY_CERT`: Tell if the `hugo-mx-gateway` App should validate the SMTP certificate against valid authorities. If you're using a self-signed certificate on the SMTP server, this value must be set to `false`.
|
||||||
* `SMTP_CLIENT_USERNAME`: Set the username to connect to the SMTP server.
|
* `SMTP_CLIENT_USERNAME`: Set the username to connect to the SMTP server.
|
||||||
* `SMTP_CLIENT_PASSWORD`: Set the password to connect to the SMTP server.
|
* `SMTP_CLIENT_PASSWORD`: Set the password to connect to the SMTP server.
|
||||||
* `CONTACT_REPLY_EMAIL`: Set an email address for the reply email. It's not necessary a valid email address, for example if don't want the user to reply you can use something like `noreply@example.com`.
|
* `CONTACT_REPLY_EMAIL`: Set an email address for the reply email. It's not necessary a valid email address, for example if don't want the user to reply you can use something like `noreply@example.com`.
|
||||||
* `CONTACT_REPLY_BCC_EMAIL`: Set an email address for bcc copy of the email sent to the user. This is useful for tracking and follow up.
|
* `CONTACT_REPLY_BCC_EMAIL`: Sets an email address for bcc copy of the email sent to the user. This is useful for tracking and follow up.
|
||||||
* `DEMO_URL`: Specific for demo forms, it can be used to set the URL of the demo site that will be included to the user reply email (e.g. `https://demo.example.com/`).
|
* `DEMO_URL`: Specific for demo forms, it can be used to set the URL of the demo site that will be included to the user reply email (e.g. `https://demo.example.com/`).
|
||||||
* `ALLOWED_ORIGINS`: Set a list of comma-separated domains that the `hugo-mx-gateway` App shoudl trust. This is for security reason to filter requests. Only requests with an `Origin` header belonging to the defined origins will be accepted, through it's only required that the request has a valid `Referer` header. It's expected in the future to these request filtering and admission rules.
|
* `ALLOWED_ORIGINS`: Set a list of comma-separated domains that the `hugo-mx-gateway` App shoudl trust. This is for security reason to filter requests. Only requests with an `Origin` header belonging to the defined origins will be accepted, through it's only required that the request has a valid `Referer` header. It's expected in the future to these request filtering and admission rules.
|
||||||
|
* `TEMPLATE_DEMO_REQUEST_REPLY`: Specify the path of the email template to reply to demo requests. The default templare used in described in the file `templates/template_reply_demo_request.html`
|
||||||
|
* `TEMPLATE_CONTACT_REQUEST_REPLY`: Specify the path of the email template to reply to contact requests. The default templare used in described in the file `templates/template_reply_contact_request.html`.
|
||||||
|
|
||||||
# Deployment options
|
# Deployment options
|
||||||
|
|
||||||
|
@ -95,7 +97,7 @@ Either way, check the [values.yaml](./helm/values.yaml) file to set the [configu
|
||||||
> **Security Context:**
|
> **Security Context:**
|
||||||
> `hugo-mx-gateway`'s pod is deployed with a unprivileged security context by default. However, if needed, it's possible to launch the pod in privileged mode by setting the Helm configuration value `securityContext.enabled` to `false`.
|
> `hugo-mx-gateway`'s pod is deployed with a unprivileged security context by default. However, if needed, it's possible to launch the pod in privileged mode by setting the Helm configuration value `securityContext.enabled` to `false`.
|
||||||
|
|
||||||
In the next deployment commands, it's assumed that the target namespace `hugo-mx-gateway` do exist. If not create it first, or, alternatively, adapt the commands to use any other namespace of your choice.
|
In the next deployment commands, it's assumed that the target namespace `hugo-mx-gateway` does exist. Otherwise create it first, or, alternatively, adapt the commands to use any other namespace of your choice.
|
||||||
|
|
||||||
### Installation using Helm 3 (i.e. without tiller)
|
### Installation using Helm 3 (i.e. without tiller)
|
||||||
<a name="installation-using-helm-3-ie-without-tiller"></a>
|
<a name="installation-using-helm-3-ie-without-tiller"></a>
|
||||||
|
@ -104,11 +106,8 @@ Helm 3 does not longer require to have [`tiller`](https://v2.helm.sh/docs/instal
|
||||||
|
|
||||||
As a consequence the below command shall work with a fresh installation of `hugo-mx-gateway` or a former version installed with Helm 3. There is a [known issue](https://github.com/helm/helm/issues/6850) when there is already a version **not** installed with Helm 3.
|
As a consequence the below command shall work with a fresh installation of `hugo-mx-gateway` or a former version installed with Helm 3. There is a [known issue](https://github.com/helm/helm/issues/6850) when there is already a version **not** installed with Helm 3.
|
||||||
|
|
||||||
```bash
|
```
|
||||||
helm upgrade \
|
helm upgrade --namespace hugo-mx-gateway --install hugo-mx-gateway helm/
|
||||||
--namespace hugo-mx-gateway \
|
|
||||||
--install hugo-mx-gateway \
|
|
||||||
helm/hugo-mx-gateway/
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Installation using Kubectl
|
### Installation using Kubectl
|
||||||
|
@ -116,10 +115,7 @@ helm upgrade \
|
||||||
This approach requires to have the Helm client (version 2 or 3) installed to generate a raw template for kubectl.
|
This approach requires to have the Helm client (version 2 or 3) installed to generate a raw template for kubectl.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ helm template \
|
$ helm template hugo-mx-gateway --namespace hugo-mx-gateway helm/ | kubectl apply -f -
|
||||||
--namespace hugo-mx-gateway \
|
|
||||||
--name hugo-mx-gateway \
|
|
||||||
helm/hugo-mx-gateway/ | kubectl apply -f -
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployment on Docker
|
## Deployment on Docker
|
||||||
|
@ -129,7 +125,7 @@ $ helm template \
|
||||||
$ docker run -d \
|
$ docker run -d \
|
||||||
--publish 8080:8080 \
|
--publish 8080:8080 \
|
||||||
--name 'hugo-mx-gateway' \
|
--name 'hugo-mx-gateway' \
|
||||||
-e SMTP_SERVER_ADDR="smtp.mailgun.org:587" \
|
-e SMTP_SERVER_ADDR="smtp.example.com:465" \
|
||||||
-e SMTP_VERITY_CERT=true \
|
-e SMTP_VERITY_CERT=true \
|
||||||
-e SMTP_CLIENT_USERNAME="postmaster@example.com" \
|
-e SMTP_CLIENT_USERNAME="postmaster@example.com" \
|
||||||
-e SMTP_CLIENT_PASSWORD="postmasterSecretPassWord" \
|
-e SMTP_CLIENT_PASSWORD="postmasterSecretPassWord" \
|
||||||
|
|
|
@ -16,4 +16,4 @@
|
||||||
# CONDITIONS OF ANY KIND, either express or implied. See the License for the #
|
# CONDITIONS OF ANY KIND, either express or implied. See the License for the #
|
||||||
# specific language governing permissions and limitations under the License. #
|
# specific language governing permissions and limitations under the License. #
|
||||||
|
|
||||||
/app/hugo-mx-gateway
|
cd /app && ./hugo-mx-gateway
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 Rodrigue Chakode and contributors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Healthz performs health check
|
||||||
|
func Healthz(httpResp http.ResponseWriter, httpReq *http.Request) {
|
||||||
|
httpResp.WriteHeader(http.StatusOK)
|
||||||
|
httpResp.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||||
|
httpResp.Write([]byte(`{"status": "ok"}`))
|
||||||
|
}
|
|
@ -2,5 +2,5 @@ apiVersion: v2
|
||||||
name: hugo-mx-gateway
|
name: hugo-mx-gateway
|
||||||
description: Helm chart for hugo-mx-gateway
|
description: Helm chart for hugo-mx-gateway
|
||||||
type: application
|
type: application
|
||||||
version: 0.1.0
|
version: 1.0.0
|
||||||
appVersion: 1.16.0
|
appVersion: 1590272682
|
||||||
|
|
|
@ -36,15 +36,17 @@ spec:
|
||||||
{{- end }}
|
{{- end }}
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 80
|
containerPort: 8080
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /
|
path: /healthz
|
||||||
port: http
|
port: http
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
periodSeconds: 60
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /
|
path: /healthz
|
||||||
port: http
|
port: http
|
||||||
resources:
|
resources:
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
|
|
@ -8,7 +8,7 @@ spec:
|
||||||
type: {{ .Values.service.type }}
|
type: {{ .Values.service.type }}
|
||||||
ports:
|
ports:
|
||||||
- port: {{ .Values.service.port }}
|
- port: {{ .Values.service.port }}
|
||||||
targetPort: http
|
targetPort: 8080
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
name: http
|
name: http
|
||||||
selector:
|
selector:
|
||||||
|
|
|
@ -28,15 +28,15 @@ serviceAccount:
|
||||||
name:
|
name:
|
||||||
|
|
||||||
podSecurityContext: {}
|
podSecurityContext: {}
|
||||||
# fsGroup: 2000
|
# fsGroup: 4583
|
||||||
|
|
||||||
securityContext: {}
|
securityContext:
|
||||||
# capabilities:
|
capabilities:
|
||||||
# drop:
|
drop:
|
||||||
# - ALL
|
- ALL
|
||||||
# readOnlyRootFilesystem: true
|
readOnlyRootFilesystem: true
|
||||||
# runAsNonRoot: true
|
runAsNonRoot: true
|
||||||
# runAsUser: 1000
|
runAsUser: 4583
|
||||||
|
|
||||||
service:
|
service:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
|
13
main.go
13
main.go
|
@ -18,12 +18,12 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Route struct {
|
type Route struct {
|
||||||
|
@ -42,6 +42,12 @@ var routes = Routes{
|
||||||
"/sendmail",
|
"/sendmail",
|
||||||
SendMail,
|
SendMail,
|
||||||
},
|
},
|
||||||
|
Route{
|
||||||
|
"Healthz",
|
||||||
|
"GET",
|
||||||
|
"/healthz",
|
||||||
|
Healthz,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func MuxLoggerHandler(inner http.Handler, name string) http.Handler {
|
func MuxLoggerHandler(inner http.Handler, name string) http.Handler {
|
||||||
|
@ -58,7 +64,6 @@ func MuxLoggerHandler(inner http.Handler, name string) http.Handler {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func NewRouter() *mux.Router {
|
func NewRouter() *mux.Router {
|
||||||
router := mux.NewRouter().StrictSlash(true)
|
router := mux.NewRouter().StrictSlash(true)
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
|
@ -99,5 +104,3 @@ func main() {
|
||||||
|
|
||||||
log.Fatal(http.ListenAndServe(":"+port, router))
|
log.Fatal(http.ListenAndServe(":"+port, router))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
15
sendmail.go
15
sendmail.go
|
@ -224,12 +224,19 @@ func SendMail(httpResp http.ResponseWriter, httpReq *http.Request) {
|
||||||
contactRequest.Subject,
|
contactRequest.Subject,
|
||||||
)
|
)
|
||||||
|
|
||||||
err := error(nil)
|
replyTplFile := ""
|
||||||
if contactRequest.RequestTarget == "demo" {
|
if contactRequest.RequestTarget == "demo" {
|
||||||
err = sendMailReq.ParseTemplate(viper.GetString("TEMPLATE_DEMO_REQUEST_REPLY"), templateData)
|
replyTplFile = viper.GetString("TEMPLATE_DEMO_REQUEST_REPLY");
|
||||||
} else {
|
if replyTplFile == "" {
|
||||||
err = sendMailReq.ParseTemplate(viper.GetString("TEMPLATE_CONTACT_REQUEST_REPLY"), templateData)
|
replyTplFile = "./templates/template_reply_demo_request.html"
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
replyTplFile = viper.GetString("TEMPLATE_CONTACT_REQUEST_REPLY");
|
||||||
|
if replyTplFile == "" {
|
||||||
|
replyTplFile = "./templates/template_reply_contact_request.html"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := sendMailReq.ParseTemplate(replyTplFile, templateData)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err := sendMailReq.Execute()
|
err := sendMailReq.Execute()
|
||||||
|
|
73
swagger.yaml
73
swagger.yaml
|
@ -1,73 +0,0 @@
|
||||||
swagger: "2.0"
|
|
||||||
info:
|
|
||||||
description: "Emailer for Hugo contact form"
|
|
||||||
version: "1.0.0"
|
|
||||||
title: "Emailer for Hugo contact form"
|
|
||||||
contact:
|
|
||||||
email: "rodrigue.chakode at gmail.com"
|
|
||||||
license:
|
|
||||||
name: "Apache 2.0"
|
|
||||||
url: "http://www.apache.org/licenses/LICENSE-2.0.html"
|
|
||||||
host: "mail.example.com"
|
|
||||||
basePath: "/v1"
|
|
||||||
tags:
|
|
||||||
- name: "email"
|
|
||||||
description: "API to handle email"
|
|
||||||
schemes:
|
|
||||||
- "https"
|
|
||||||
- "http"
|
|
||||||
paths:
|
|
||||||
/send:
|
|
||||||
post:
|
|
||||||
tags:
|
|
||||||
- "email"
|
|
||||||
summary: "Send an email using details provided in the request body"
|
|
||||||
description: ""
|
|
||||||
operationId: "sendMail"
|
|
||||||
consumes:
|
|
||||||
- "application/json"
|
|
||||||
produces:
|
|
||||||
- "application/json"
|
|
||||||
parameters:
|
|
||||||
- in: "body"
|
|
||||||
name: "body"
|
|
||||||
description: "Email object containing, the recipient, the subject and the content"
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
$ref: "#/definitions/EmailRequest"
|
|
||||||
responses:
|
|
||||||
405:
|
|
||||||
description: "Invalid input"
|
|
||||||
500:
|
|
||||||
description: "Internal server error"
|
|
||||||
security:
|
|
||||||
- petstore_auth:
|
|
||||||
- "send:emails"
|
|
||||||
|
|
||||||
securityDefinitions:
|
|
||||||
petstore_auth:
|
|
||||||
type: "oauth2"
|
|
||||||
authorizationUrl: "http://auth.example.com/oauth/dialog"
|
|
||||||
flow: "implicit"
|
|
||||||
scopes:
|
|
||||||
send:emails: "send email"
|
|
||||||
api_key:
|
|
||||||
type: "apiKey"
|
|
||||||
name: "api_key"
|
|
||||||
in: "header"
|
|
||||||
definitions:
|
|
||||||
EmailRequest:
|
|
||||||
type: "object"
|
|
||||||
properties:
|
|
||||||
recipient:
|
|
||||||
type: "string"
|
|
||||||
format: "email"
|
|
||||||
subject:
|
|
||||||
type: "string"
|
|
||||||
body:
|
|
||||||
type: "string"
|
|
||||||
xml:
|
|
||||||
name: "Order"
|
|
||||||
externalDocs:
|
|
||||||
description: "Learn more"
|
|
||||||
url: "https://github.com/rchakode/hugo-mx-gateway"
|
|
Loading…
Reference in New Issue