diff --git a/deployment.yaml b/deployment.yaml new file mode 100644 index 000000000..df1e242a1 --- /dev/null +++ b/deployment.yaml @@ -0,0 +1,68 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: atlantis + labels: + app: atlantis +spec: + replicas: 1 + selector: + matchLabels: + app: atlantis + template: + metadata: + labels: + app: atlantis + spec: + containers: + - name: atlantis + image: runatlantis/atlantis:v0.4.0 + env: + - name: ATLANTIS_REPO_WHITELIST + value: github.com/lkysow/* + + ### GitHub Config ### + - name: ATLANTIS_GH_USER + value: lkysow + - name: ATLANTIS_GH_TOKEN + value: test + - name: ATLANTIS_PORT + value: "4141" # Kubernetes sets an ATLANTIS_PORT variable so we need to override. + ports: + - name: atlantis + containerPort: 4141 + resources: + requests: + memory: 256Mi + cpu: 100m + limits: + memory: 256Mi + cpu: 100m + livenessProbe: + # We only need to check every 60s since Atlantis is not a + # high-throughput service. + periodSeconds: 60 + httpGet: + path: /healthz + port: 4141 + # If using https, change this. + scheme: HTTP + readinessProbe: + periodSeconds: 60 + httpGet: + path: /healthz + port: 4141 + # If using https, change this. + scheme: HTTP +--- +apiVersion: v1 +kind: Service +metadata: + name: atlantis +spec: + ports: + - name: atlantis + port: 80 + targetPort: 4141 + selector: + app: atlantis diff --git a/runatlantis.io/docs/deployment.md b/runatlantis.io/docs/deployment.md index d40dcb91c..14b65a5a2 100644 --- a/runatlantis.io/docs/deployment.md +++ b/runatlantis.io/docs/deployment.md @@ -160,7 +160,7 @@ Next, edit the manifests below as follows: * NOTE: You never want to run with `:latest` because if your Pod moves to a new node, Kubernetes will pull the latest image and you might end up upgrading Atlantis by accident! 2. Replace `value: github.com/yourorg/*` under `name: ATLANTIS_REPO_WHITELIST` with the whitelist pattern -for your Terraform repos. See [--repo-whitelist](#--repo-whitelist) for more details. +for your Terraform repos. See [--repo-whitelist](/docs/security.html#repo-whitelist) for more details. 3. If you're using GitHub: 1. Replace `` with the username of your Atlantis GitHub user without the `@`. 2. Delete all the `ATLANTIS_GITLAB_*` environment variables. @@ -201,7 +201,7 @@ spec: - name: ATLANTIS_REPO_WHITELIST value: github.com/yourorg/* # 2. Replace this with your own repo whitelist. - ## GitHub Config ### + ### GitHub Config ### - name: ATLANTIS_GH_USER value: # 3i. If you're using GitHub replace with the username of your Atlantis GitHub user without the `@`. - name: ATLANTIS_GH_TOKEN @@ -214,8 +214,9 @@ spec: secretKeyRef: name: atlantis-vcs key: webhook-secret + ### End GitHub Config ### - ## GitLab Config ### + ### GitLab Config ### - name: ATLANTIS_GITLAB_USER value: # 4i. If you're using GitLab replace with the username of your Atlantis GitLab user without the `@`. - name: ATLANTIS_GITLAB_TOKEN @@ -228,6 +229,7 @@ spec: secretKeyRef: name: atlantis-vcs key: webhook-secret + ### End GitLab Config ### - name: ATLANTIS_DATA_DIR value: /atlantis @@ -246,6 +248,22 @@ spec: limits: memory: 256Mi cpu: 100m + livenessProbe: + # We only need to check every 60s since Atlantis is not a + # high-throughput service. + periodSeconds: 60 + httpGet: + path: /healthz + port: 4141 + # If using https, change this to HTTPS + scheme: HTTP + readinessProbe: + periodSeconds: 60 + httpGet: + path: /healthz + port: 4141 + # If using https, change this to HTTPS + scheme: HTTP volumeClaimTemplates: - metadata: name: atlantis-data @@ -300,7 +318,7 @@ spec: - name: ATLANTIS_REPO_WHITELIST value: github.com/yourorg/* # 2. Replace this with your own repo whitelist. - ## GitHub Config ### + ### GitHub Config ### - name: ATLANTIS_GH_USER value: # 3i. If you're using GitHub replace with the username of your Atlantis GitHub user without the `@`. - name: ATLANTIS_GH_TOKEN @@ -313,8 +331,9 @@ spec: secretKeyRef: name: atlantis-vcs key: webhook-secret + ### End GitHub Config ### - ## GitLab Config ### + ### GitLab Config ### - name: ATLANTIS_GITLAB_USER value: # 4i. If you're using GitLab replace with the username of your Atlantis GitLab user without the `@`. - name: ATLANTIS_GITLAB_TOKEN @@ -327,6 +346,8 @@ spec: secretKeyRef: name: atlantis-vcs key: webhook-secret + ### End GitLab Config ### + - name: ATLANTIS_PORT value: "4141" # Kubernetes sets an ATLANTIS_PORT variable so we need to override. ports: @@ -339,6 +360,22 @@ spec: limits: memory: 256Mi cpu: 100m + livenessProbe: + # We only need to check every 60s since Atlantis is not a + # high-throughput service. + periodSeconds: 60 + httpGet: + path: /healthz + port: 4141 + # If using https, change this to HTTPS + scheme: HTTP + readinessProbe: + periodSeconds: 60 + httpGet: + path: /healthz + port: 4141 + # If using https, change this to HTTPS + scheme: HTTP --- apiVersion: v1 kind: Service diff --git a/server/server.go b/server/server.go index 7eaceb7e2..e51e36dc1 100644 --- a/server/server.go +++ b/server/server.go @@ -17,6 +17,7 @@ package server import ( "context" + "encoding/json" "flag" "fmt" "log" @@ -314,6 +315,7 @@ func (s *Server) Start() error { s.Router.HandleFunc("/", s.Index).Methods("GET").MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool { return r.URL.Path == "/" || r.URL.Path == "/index.html" }) + s.Router.HandleFunc("/healthz", s.Healthz).Methods("GET") s.Router.PathPrefix("/static/").Handler(http.FileServer(&assetfs.AssetFS{Asset: static.Asset, AssetDir: static.AssetDir, AssetInfo: static.AssetInfo})) s.Router.HandleFunc("/events", s.EventsController.Post).Methods("POST") s.Router.HandleFunc("/locks", s.LocksController.DeleteLock).Methods("DELETE").Queries("id", "{id:.*}") @@ -383,3 +385,19 @@ func (s *Server) Index(w http.ResponseWriter, _ *http.Request) { AtlantisVersion: s.AtlantisVersion, }) } + +// Healthz returns the health check response. It always returns a 200 currently. +func (s *Server) Healthz(w http.ResponseWriter, _ *http.Request) { + data, err := json.MarshalIndent(&struct { + Status string `json:"status"` + }{ + Status: "ok", + }, "", " ") + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Error creating status json response: %s", err) + return + } + w.Header().Set("Content-Type", "application/json") + w.Write(data) // nolint: errcheck +} diff --git a/server/server_test.go b/server/server_test.go index cec7a4fcb..054328d16 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -102,6 +102,20 @@ func TestIndex_Success(t *testing.T) { responseContains(t, w, http.StatusOK, "") } +func TestHealthz(t *testing.T) { + s := server.Server{} + req, _ := http.NewRequest("GET", "/healthz", bytes.NewBuffer(nil)) + w := httptest.NewRecorder() + s.Healthz(w, req) + Equals(t, http.StatusOK, w.Result().StatusCode) + body, _ := ioutil.ReadAll(w.Result().Body) + Equals(t, "application/json", w.Result().Header["Content-Type"][0]) + Equals(t, + `{ + "status": "ok" +}`, string(body)) +} + func responseContains(t *testing.T, r *httptest.ResponseRecorder, status int, bodySubstr string) { t.Helper() Equals(t, status, r.Result().StatusCode)