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_UID=4583
|
||||
|
@ -7,11 +7,8 @@ RUN addgroup -g $RUNTIME_USER_UID $RUNTIME_USER && \
|
|||
adduser --disabled-password --no-create-home --gecos "" \
|
||||
--home /app --ingroup $RUNTIME_USER --uid $RUNTIME_USER_UID $RUNTIME_USER
|
||||
|
||||
COPY entrypoint.sh \
|
||||
bin/hugo-mx-gateway \
|
||||
templates \
|
||||
LICENSE \
|
||||
/app/
|
||||
COPY entrypoint.sh bin/hugo-mx-gateway LICENSE /app/
|
||||
COPY templates /app/templates
|
||||
|
||||
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)
|
||||
GOCMD=GO111MODULE=on go
|
||||
GOBUILD=$(GOCMD) build
|
||||
GOBUILD_FLAGS=-a -tags netgo -ldflags '-w -extldflags "-static"'
|
||||
GOCLEAN=$(GOCMD) clean
|
||||
GOTEST=$(GOCMD) test
|
||||
GOVENDOR=$(GOCMD) mod vendor
|
||||
|
@ -16,7 +17,7 @@ vendor:
|
|||
$(GOVENDOR)
|
||||
|
||||
build:
|
||||
$(GOBUILD) -o $(PACKAGE_NAME) -v
|
||||
$(GOBUILD) $(GOBUILD_FLAGS) -o $(PACKAGE_NAME) -v
|
||||
|
||||
build-ci:
|
||||
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
|
||||
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_CLIENT_USERNAME`: Set the username 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_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/`).
|
||||
* `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
|
||||
|
||||
|
@ -95,7 +97,7 @@ Either way, check the [values.yaml](./helm/values.yaml) file to set the [configu
|
|||
> **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`.
|
||||
|
||||
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)
|
||||
<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.
|
||||
|
||||
```bash
|
||||
helm upgrade \
|
||||
--namespace hugo-mx-gateway \
|
||||
--install hugo-mx-gateway \
|
||||
helm/hugo-mx-gateway/
|
||||
```
|
||||
helm upgrade --namespace hugo-mx-gateway --install hugo-mx-gateway helm/
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
```
|
||||
$ helm template \
|
||||
--namespace hugo-mx-gateway \
|
||||
--name hugo-mx-gateway \
|
||||
helm/hugo-mx-gateway/ | kubectl apply -f -
|
||||
$ helm template hugo-mx-gateway --namespace hugo-mx-gateway helm/ | kubectl apply -f -
|
||||
```
|
||||
|
||||
## Deployment on Docker
|
||||
|
@ -129,7 +125,7 @@ $ helm template \
|
|||
$ docker run -d \
|
||||
--publish 8080:8080 \
|
||||
--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_CLIENT_USERNAME="postmaster@example.com" \
|
||||
-e SMTP_CLIENT_PASSWORD="postmasterSecretPassWord" \
|
||||
|
|
|
@ -16,4 +16,4 @@
|
|||
# CONDITIONS OF ANY KIND, either express or implied. See the License for the #
|
||||
# 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
|
||||
description: Helm chart for hugo-mx-gateway
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: 1.16.0
|
||||
version: 1.0.0
|
||||
appVersion: 1590272682
|
||||
|
|
|
@ -36,15 +36,17 @@ spec:
|
|||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 60
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
path: /healthz
|
||||
port: http
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
|
|
|
@ -8,7 +8,7 @@ spec:
|
|||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
|
|
|
@ -28,15 +28,15 @@ serviceAccount:
|
|||
name:
|
||||
|
||||
podSecurityContext: {}
|
||||
# fsGroup: 2000
|
||||
# fsGroup: 4583
|
||||
|
||||
securityContext: {}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 4583
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
|
|
37
main.go
37
main.go
|
@ -18,12 +18,12 @@ package main
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/gorilla/mux"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Route struct {
|
||||
|
@ -36,29 +36,34 @@ type Route struct {
|
|||
type Routes []Route
|
||||
|
||||
var routes = Routes{
|
||||
Route {
|
||||
Route{
|
||||
"SendMail",
|
||||
"POST",
|
||||
"/sendmail",
|
||||
SendMail,
|
||||
},
|
||||
Route{
|
||||
"Healthz",
|
||||
"GET",
|
||||
"/healthz",
|
||||
Healthz,
|
||||
},
|
||||
}
|
||||
|
||||
func MuxLoggerHandler(inner http.Handler, name string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
inner.ServeHTTP(w, r)
|
||||
log.Printf(
|
||||
"%s %s %s %s",
|
||||
r.Method,
|
||||
r.RequestURI,
|
||||
name,
|
||||
time.Since(start),
|
||||
)
|
||||
})
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
inner.ServeHTTP(w, r)
|
||||
log.Printf(
|
||||
"%s %s %s %s",
|
||||
r.Method,
|
||||
r.RequestURI,
|
||||
name,
|
||||
time.Since(start),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
func NewRouter() *mux.Router {
|
||||
router := mux.NewRouter().StrictSlash(true)
|
||||
for _, route := range routes {
|
||||
|
@ -99,5 +104,3 @@ func main() {
|
|||
|
||||
log.Fatal(http.ListenAndServe(":"+port, router))
|
||||
}
|
||||
|
||||
|
||||
|
|
13
sendmail.go
13
sendmail.go
|
@ -224,12 +224,19 @@ func SendMail(httpResp http.ResponseWriter, httpReq *http.Request) {
|
|||
contactRequest.Subject,
|
||||
)
|
||||
|
||||
err := error(nil)
|
||||
replyTplFile := ""
|
||||
if contactRequest.RequestTarget == "demo" {
|
||||
err = sendMailReq.ParseTemplate(viper.GetString("TEMPLATE_DEMO_REQUEST_REPLY"), templateData)
|
||||
replyTplFile = viper.GetString("TEMPLATE_DEMO_REQUEST_REPLY");
|
||||
if replyTplFile == "" {
|
||||
replyTplFile = "./templates/template_reply_demo_request.html"
|
||||
}
|
||||
} else {
|
||||
err = sendMailReq.ParseTemplate(viper.GetString("TEMPLATE_CONTACT_REQUEST_REPLY"), templateData)
|
||||
replyTplFile = viper.GetString("TEMPLATE_CONTACT_REQUEST_REPLY");
|
||||
if replyTplFile == "" {
|
||||
replyTplFile = "./templates/template_reply_contact_request.html"
|
||||
}
|
||||
}
|
||||
err := sendMailReq.ParseTemplate(replyTplFile, templateData)
|
||||
|
||||
if err == nil {
|
||||
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