├── .github └── PULL_REQUEST_TEMPLATE.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── main.go ├── main_test.go ├── manual-deployment.yaml ├── release.md ├── sample-microservice-0.1.0.tgz ├── sample-microservice ├── .helmignore ├── Chart.yaml ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── ingress.yaml │ └── service.yaml └── values.yaml └── values ├── dev.yaml └── prod.yaml /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/aws-samples/sample-microservice-with-spinnaker/issues), or [recently closed](https://github.com/aws-samples/sample-microservice-with-spinnaker/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/sample-microservice-with-spinnaker/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/aws-samples/sample-microservice-with-spinnaker/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # A Go multistage docker file 2 | FROM golang:alpine as builder 3 | RUN mkdir /build 4 | ADD . /build/ 5 | WORKDIR /build 6 | RUN go build -o main . 7 | FROM alpine 8 | ENV PORT 8080 9 | EXPOSE 8080 10 | RUN adduser -S -D -H -h /app appuser 11 | USER appuser 12 | COPY --from=builder /build/main /app/ 13 | WORKDIR /app 14 | CMD ["./main"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Build a Deployment Pipeline with Spinnaker on Kubernetes 2 | 3 | A sample microservice for use with Spinnaker 4 | 5 | ## License Summary 6 | 7 | This sample code is made available under the MIT-0 license. See the LICENSE file. 8 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | // HandlerFunc1 handles basic calls 10 | func HandlerFunc1(w http.ResponseWriter, r *http.Request) { 11 | fmt.Fprintf(w, "\nRelease 1.011") 12 | } 13 | 14 | func main() { 15 | http.HandleFunc("/", HandlerFunc1) 16 | log.Fatal(http.ListenAndServe(":8080", nil)) 17 | } 18 | -------------------------------------------------------------------------------- /main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | ) 8 | 9 | //TestServer will test if server returns correct values 10 | func TestHandlerFunc1(t *testing.T) { 11 | 12 | // Create a request to pass to our handler. We don't have any query parameters for now, so we'll 13 | // pass 'nil' as the third parameter. 14 | req, err := http.NewRequest("GET", "/", nil) 15 | if err != nil { 16 | t.Fatal(err) 17 | } 18 | 19 | // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response. 20 | rr := httptest.NewRecorder() 21 | handler := http.HandlerFunc(HandlerFunc1) 22 | 23 | // Our handlers satisfy http.Handler, so we can call their ServeHTTP method 24 | // directly and pass in our Request and ResponseRecorder. 25 | handler.ServeHTTP(rr, req) 26 | 27 | // Check the status code is what we expect. 28 | if status := rr.Code; status != http.StatusOK { 29 | t.Errorf("handler returned wrong status code: got %v want %v", 30 | status, http.StatusOK) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /manual-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: sample-microservice 5 | namespace: sample-microservice 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: sample-microservice 10 | template: 11 | metadata: 12 | labels: 13 | app: sample-microservice 14 | spec: 15 | containers: 16 | - name: sample-microservice 17 | image: 107995894928.dkr.ecr.us-west-2.amazonaws.com/sample-microservice:latest 18 | resources: 19 | limits: 20 | memory: "128Mi" 21 | cpu: "500m" 22 | ports: 23 | - containerPort: 8080 24 | 25 | --- 26 | 27 | apiVersion: v1 28 | kind: Service 29 | metadata: 30 | name: sample-microservice 31 | namespace: sample-microservice 32 | spec: 33 | selector: 34 | app: sample-microservice 35 | ports: 36 | - port: 8080 37 | targetPort: 8080 38 | 39 | -------------------------------------------------------------------------------- /release.md: -------------------------------------------------------------------------------- 1 | release 3 -------------------------------------------------------------------------------- /sample-microservice-0.1.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/sample-microservice-with-spinnaker/9c34b8ecd799be5bdf6b0101d24a9706c2d2ac90/sample-microservice-0.1.0.tgz -------------------------------------------------------------------------------- /sample-microservice/.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 | -------------------------------------------------------------------------------- /sample-microservice/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: "1.0" 3 | description: A Helm chart for Kubernetes 4 | name: sample-microservice 5 | version: 0.1.0 6 | -------------------------------------------------------------------------------- /sample-microservice/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range .Values.ingress.hosts }} 4 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} 5 | {{- end }} 6 | {{- else if contains "NodePort" .Values.service.type }} 7 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "sample-microservice.fullname" . }}) 8 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 9 | echo http://$NODE_IP:$NODE_PORT 10 | {{- else if contains "LoadBalancer" .Values.service.type }} 11 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 12 | You can watch the status of by running 'kubectl get svc -w {{ include "sample-microservice.fullname" . }}' 13 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "sample-microservice.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 14 | echo http://$SERVICE_IP:{{ .Values.service.port }} 15 | {{- else if contains "ClusterIP" .Values.service.type }} 16 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "sample-microservice.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 17 | echo "Visit http://127.0.0.1:8080 to use your application" 18 | kubectl port-forward $POD_NAME 8080:80 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /sample-microservice/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "sample-microservice.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 "sample-microservice.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 "sample-microservice.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | -------------------------------------------------------------------------------- /sample-microservice/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1beta2 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "sample-microservice.fullname" . }} 5 | namespace: {{ .Release.Namespace}} 6 | labels: 7 | app.kubernetes.io/name: {{ include "sample-microservice.name" . }} 8 | helm.sh/chart: {{ include "sample-microservice.chart" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/managed-by: {{ .Release.Service }} 11 | spec: 12 | replicas: {{ .Values.replicaCount }} 13 | selector: 14 | matchLabels: 15 | app.kubernetes.io/name: {{ include "sample-microservice.name" . }} 16 | app.kubernetes.io/instance: {{ .Release.Name }} 17 | template: 18 | metadata: 19 | labels: 20 | app.kubernetes.io/name: {{ include "sample-microservice.name" . }} 21 | app.kubernetes.io/instance: {{ .Release.Name }} 22 | spec: 23 | containers: 24 | - name: {{ .Chart.Name }} 25 | image: {{ .Values.image.repository }} 26 | imagePullPolicy: {{ .Values.image.pullPolicy }} 27 | ports: 28 | - name: http 29 | containerPort: 8080 30 | protocol: TCP 31 | livenessProbe: 32 | httpGet: 33 | path: / 34 | port: http 35 | readinessProbe: 36 | httpGet: 37 | path: / 38 | port: http 39 | resources: 40 | {{ toYaml .Values.resources | indent 12 }} 41 | {{- with .Values.nodeSelector }} 42 | nodeSelector: 43 | {{ toYaml . | indent 8 }} 44 | {{- end }} 45 | {{- with .Values.affinity }} 46 | affinity: 47 | {{ toYaml . | indent 8 }} 48 | {{- end }} 49 | {{- with .Values.tolerations }} 50 | tolerations: 51 | {{ toYaml . | indent 8 }} 52 | {{- end }} 53 | -------------------------------------------------------------------------------- /sample-microservice/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "sample-microservice.fullname" . -}} 3 | {{- $ingressPath := .Values.ingress.path -}} 4 | apiVersion: extensions/v1beta1 5 | kind: Ingress 6 | metadata: 7 | name: {{ $fullName }} 8 | labels: 9 | app.kubernetes.io/name: {{ include "sample-microservice.name" . }} 10 | helm.sh/chart: {{ include "sample-microservice.chart" . }} 11 | app.kubernetes.io/instance: {{ .Release.Name }} 12 | app.kubernetes.io/managed-by: {{ .Release.Service }} 13 | {{- with .Values.ingress.annotations }} 14 | annotations: 15 | {{ toYaml . | indent 4 }} 16 | {{- end }} 17 | spec: 18 | {{- if .Values.ingress.tls }} 19 | tls: 20 | {{- range .Values.ingress.tls }} 21 | - hosts: 22 | {{- range .hosts }} 23 | - {{ . | quote }} 24 | {{- end }} 25 | secretName: {{ .secretName }} 26 | {{- end }} 27 | {{- end }} 28 | rules: 29 | {{- range .Values.ingress.hosts }} 30 | - host: {{ . | quote }} 31 | http: 32 | paths: 33 | - path: {{ $ingressPath }} 34 | backend: 35 | serviceName: {{ $fullName }} 36 | servicePort: http 37 | {{- end }} 38 | {{- end }} 39 | -------------------------------------------------------------------------------- /sample-microservice/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "sample-microservice.fullname" . }} 5 | labels: 6 | app.kubernetes.io/name: {{ include "sample-microservice.name" . }} 7 | helm.sh/chart: {{ include "sample-microservice.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | spec: 11 | type: {{ .Values.service.type }} 12 | ports: 13 | - port: {{ .Values.service.port }} 14 | targetPort: http 15 | protocol: TCP 16 | name: http 17 | selector: 18 | app.kubernetes.io/name: {{ include "sample-microservice.name" . }} 19 | app.kubernetes.io/instance: {{ .Release.Name }} 20 | -------------------------------------------------------------------------------- /sample-microservice/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for sample-microservice. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: nginx 9 | tag: stable 10 | pullPolicy: IfNotPresent 11 | 12 | nameOverride: "" 13 | fullnameOverride: "" 14 | 15 | service: 16 | type: ClusterIP 17 | port: 80 18 | 19 | ingress: 20 | enabled: false 21 | annotations: {} 22 | # kubernetes.io/ingress.class: nginx 23 | # kubernetes.io/tls-acme: "true" 24 | path: / 25 | hosts: 26 | - chart-example.local 27 | tls: [] 28 | # - secretName: chart-example-tls 29 | # hosts: 30 | # - chart-example.local 31 | 32 | resources: {} 33 | # We usually recommend not to specify default resources and to leave this as a conscious 34 | # choice for the user. This also increases chances charts run on environments with little 35 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 36 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 37 | # limits: 38 | # cpu: 100m 39 | # memory: 128Mi 40 | # requests: 41 | # cpu: 100m 42 | # memory: 128Mi 43 | 44 | nodeSelector: {} 45 | 46 | tolerations: [] 47 | 48 | affinity: {} 49 | -------------------------------------------------------------------------------- /values/dev.yaml: -------------------------------------------------------------------------------- 1 | replicaCount: 1 2 | 3 | image: 4 | repository: 107995894928.dkr.ecr.us-west-2.amazonaws.com/sample-microservice 5 | tag: latest 6 | pullPolicy: Always 7 | 8 | service: 9 | type: ClusterIP 10 | port: 8080 -------------------------------------------------------------------------------- /values/prod.yaml: -------------------------------------------------------------------------------- 1 | replicaCount: 4 2 | 3 | image: 4 | repository: 107995894928.dkr.ecr.us-west-2.amazonaws.com/sample-microservice 5 | tag: latest 6 | pullPolicy: Always 7 | 8 | service: 9 | type: ClusterIP 10 | port: 8080 --------------------------------------------------------------------------------