mirror of
https://github.com/stefanprodan/podinfo.git
synced 2026-03-03 18:40:21 +00:00
Merge pull request #29 from stefanprodan/swagger
Implement Swagger support
This commit is contained in:
8
Makefile
8
Makefile
@@ -34,9 +34,13 @@ test-container:
|
||||
curl -sH "Authorization: Bearer $${TOKEN}" localhost:9898/token/validate | grep test
|
||||
|
||||
push-container:
|
||||
docker tag $(DOCKER_IMAGE_NAME):$(VERSION) $(DOCKER_IMAGE_NAME):latest
|
||||
docker push $(DOCKER_IMAGE_NAME):$(VERSION)
|
||||
docker push $(DOCKER_IMAGE_NAME):latest
|
||||
docker tag $(DOCKER_IMAGE_NAME):$(VERSION) quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)
|
||||
docker tag $(DOCKER_IMAGE_NAME):$(VERSION) quay.io/$(DOCKER_IMAGE_NAME):latest
|
||||
docker push quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)
|
||||
docker push quay.io/$(DOCKER_IMAGE_NAME):latest
|
||||
|
||||
version-set:
|
||||
@next="$(TAG)" && \
|
||||
@@ -51,3 +55,7 @@ version-set:
|
||||
release:
|
||||
git tag $(VERSION)
|
||||
git push origin $(VERSION)
|
||||
|
||||
swagger:
|
||||
GO111MODULE=on go get github.com/swaggo/swag/cmd/swag
|
||||
cd pkg/api && $$(go env GOPATH)/bin/swag init -g server.go
|
||||
10
README.md
10
README.md
@@ -16,6 +16,7 @@ Specifications:
|
||||
* Structured logging with zap
|
||||
* 12-factor app with viper
|
||||
* Fault injection (random errors and latency)
|
||||
* Swagger docs
|
||||
* Helm and Kustomize installers
|
||||
* End-to-End testing with Kubernetes Kind and Helm
|
||||
|
||||
@@ -41,11 +42,14 @@ Web API:
|
||||
* `GET /store/{hash}` returns the content of the file /data/hash if exists
|
||||
* `GET /ws/echo` echos content via websockets `podcli ws ws://localhost:9898/ws/echo`
|
||||
* `GET /chunked/{seconds}` uses `transfer-encoding` type `chunked` to give a partial response and then waits for the specified period
|
||||
* `GET /swagger.json` returns the API Swagger docs, used for Linkerd service profiling and Gloo routes discovery
|
||||
|
||||
Web UI:
|
||||
|
||||

|
||||
|
||||
To access the Swagger UI open `<podinfo-host>/swagger/index.html` in a browser.
|
||||
|
||||
### Guides
|
||||
|
||||
* [Automated canary deployments with Flagger and Istio](https://medium.com/google-cloud/automated-canary-deployments-with-flagger-and-istio-ac747827f9d1)
|
||||
@@ -79,3 +83,9 @@ Kustomize:
|
||||
```bash
|
||||
kubectl apply -k github.com/stefanprodan/podinfo//kustomize
|
||||
```
|
||||
|
||||
Docker:
|
||||
|
||||
```bash
|
||||
docker run -dp 9898:9898 stefanprodan/podinfo
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v1
|
||||
version: 2.0.2
|
||||
appVersion: 2.0.2
|
||||
version: 2.1.0
|
||||
appVersion: 2.1.0
|
||||
name: podinfo
|
||||
engine: gotpl
|
||||
description: Podinfo Helm chart for Kubernetes
|
||||
|
||||
@@ -12,7 +12,7 @@ faults:
|
||||
|
||||
image:
|
||||
repository: quay.io/stefanprodan/podinfo
|
||||
tag: 2.0.2
|
||||
tag: 2.1.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
service:
|
||||
|
||||
9
go.mod
9
go.mod
@@ -4,13 +4,13 @@ go 1.12
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||
github.com/aws/aws-sdk-go v1.15.63 // indirect
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/chzyer/logex v1.1.10 // indirect
|
||||
github.com/chzyer/readline v0.0.0-20160726135117-62c6fe619375
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/fsnotify/fsnotify v1.4.7
|
||||
@@ -31,7 +31,6 @@ require (
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699 // indirect
|
||||
github.com/pelletier/go-toml v1.2.0 // indirect
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/prometheus/client_golang v0.8.0
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e // indirect
|
||||
@@ -42,12 +41,12 @@ require (
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20180814060501-14d3d4c51834 // indirect
|
||||
github.com/spf13/pflag v1.0.2
|
||||
github.com/spf13/viper v1.1.0
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 // indirect
|
||||
github.com/swaggo/http-swagger v0.0.0-20190614090009-c2865af9083e
|
||||
github.com/swaggo/swag v1.6.2
|
||||
github.com/ulikunitz/xz v0.5.4 // indirect
|
||||
go.uber.org/atomic v1.3.2 // indirect
|
||||
go.uber.org/multierr v1.1.0 // indirect
|
||||
go.uber.org/zap v1.9.1
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.1 // indirect
|
||||
)
|
||||
|
||||
34
go.sum
34
go.sum
@@ -1,5 +1,13 @@
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/aws/aws-sdk-go v1.15.63 h1:rPr7eEm/FSK23DoDKhbd9oLMYGT7JU9pkyfBUVOHXUo=
|
||||
github.com/aws/aws-sdk-go v1.15.63/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
@@ -21,6 +29,17 @@ github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0=
|
||||
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/jsonreference v0.19.0 h1:BqWKpV1dFd+AuiKlgtddwVIFQsuMpxfBDBHGfM2yNpk=
|
||||
github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/spec v0.19.0 h1:A4SZ6IWh3lnjH0rG0Z5lkxazMGBECtrZcbyYQi+64k4=
|
||||
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||
github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi880=
|
||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||
@@ -43,6 +62,8 @@ github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Ao
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||
@@ -82,10 +103,19 @@ github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
||||
github.com/spf13/viper v1.1.0 h1:V7OZpY8i3C1x/pDmU0zNNlfVoDz112fSYvtWMjjS3f4=
|
||||
github.com/spf13/viper v1.1.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM=
|
||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
|
||||
github.com/swaggo/http-swagger v0.0.0-20190614090009-c2865af9083e h1:m5sYJ43teIUlESuKRFQRRm7kqi6ExiYwVKfoXNuRgHU=
|
||||
github.com/swaggo/http-swagger v0.0.0-20190614090009-c2865af9083e/go.mod h1:eycbshptIv+tqTMlLEaGC2noPNcetbrcYEelLafrIDI=
|
||||
github.com/swaggo/swag v1.6.2 h1:WQMAtT/FmMBb7g0rAuHDhG3vvdtHKJ3WZ+Ssb0p4Y6E=
|
||||
github.com/swaggo/swag v1.6.2/go.mod h1:YyZstMc22WYm6GEDx/CYWxq+faBbjQ5EqwQcrjREDBo=
|
||||
github.com/ulikunitz/xz v0.5.4 h1:zATC2OoZ8H1TZll3FpbX+ikwmadbO699PE06cIkm9oU=
|
||||
github.com/ulikunitz/xz v0.5.4/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
@@ -93,6 +123,8 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/
|
||||
go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
@@ -101,6 +133,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468 h1:fTfk6GjmihJbK0mSUFgPPgYpsdmApQ86Mcd4GuKax9U=
|
||||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
|
||||
@@ -24,7 +24,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: podinfod
|
||||
image: quay.io/stefanprodan/podinfo:2.0.2
|
||||
image: quay.io/stefanprodan/podinfo:2.1.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 9898
|
||||
|
||||
@@ -9,6 +9,14 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// Chunked godoc
|
||||
// @Summary Chunked transfer encoding
|
||||
// @Description uses transfer-encoding type chunked to give a partial response and then waits for the specified period
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /chunked/{seconds} [get]
|
||||
// @Success 200 {object} api.MapResponse
|
||||
func (s *Server) chunkedHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
|
||||
|
||||
@@ -8,6 +8,14 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Delay godoc
|
||||
// @Summary Delay
|
||||
// @Description waits for the specified period
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /delay/{seconds} [get]
|
||||
// @Success 200 {object} api.MapResponse
|
||||
func (s *Server) delayHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
|
||||
|
||||
594
pkg/api/docs/docs.go
Normal file
594
pkg/api/docs/docs.go
Normal file
@@ -0,0 +1,594 @@
|
||||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
// This file was generated by swaggo/swag at
|
||||
// 2019-08-07 15:52:23.918713 +0300 EEST m=+0.023438272
|
||||
|
||||
package docs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/alecthomas/template"
|
||||
"github.com/swaggo/swag"
|
||||
)
|
||||
|
||||
var doc = `{
|
||||
"schemes": {{ marshal .Schemes }},
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "Go microservice template for Kubernetes.",
|
||||
"title": "Podinfo API",
|
||||
"contact": {
|
||||
"name": "Source Code",
|
||||
"url": "https://github.com/stefanprodan/podinfo"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT License",
|
||||
"url": "https://github.com/stefanprodan/podinfo/blob/master/LICENSE"
|
||||
},
|
||||
"version": "2.0"
|
||||
},
|
||||
"host": "localhost:9898",
|
||||
"basePath": "/",
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"description": "renders podinfo UI",
|
||||
"produces": [
|
||||
"text/html"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Index",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/echo": {
|
||||
"post": {
|
||||
"description": "forwards the call to the backend service and echos the posted content",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Echo",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Accepted",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/info": {
|
||||
"get": {
|
||||
"description": "returns the runtime information",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Runtime information",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.RuntimeResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/chunked/{seconds}": {
|
||||
"get": {
|
||||
"description": "uses transfer-encoding type chunked to give a partial response and then waits for the specified period",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Chunked transfer encoding",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/delay/{seconds}": {
|
||||
"get": {
|
||||
"description": "waits for the specified period",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Delay",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/env": {
|
||||
"get": {
|
||||
"description": "returns the environment variables as a JSON array",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Environment",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.ArrayResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/headers": {
|
||||
"get": {
|
||||
"description": "returns a JSON array with the request HTTP headers",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Headers",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.ArrayResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/healthz": {
|
||||
"get": {
|
||||
"description": "used by Kubernetes liveness probe",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Liveness check",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/metrics": {
|
||||
"get": {
|
||||
"description": "returns HTTP requests duration and Go runtime metrics",
|
||||
"produces": [
|
||||
"text/plain"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Prometheus metrics",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/panic": {
|
||||
"get": {
|
||||
"description": "crashes the process with exit code 255",
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Panic"
|
||||
}
|
||||
},
|
||||
"/readyz": {
|
||||
"get": {
|
||||
"description": "used by Kubernetes readiness probe",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Readiness check",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/readyz/disable": {
|
||||
"post": {
|
||||
"description": "signals the Kubernetes LB to stop sending requests to this instance",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Disable ready state",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/readyz/enable": {
|
||||
"post": {
|
||||
"description": "signals the Kubernetes LB that this instance is ready to receive traffic",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Enable ready state",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/status/{code}": {
|
||||
"get": {
|
||||
"description": "sets the response status code to the specified code",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Status code",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/store": {
|
||||
"post": {
|
||||
"description": "writes the posted content to disk at /data/hash and returns the SHA1 hash of the content",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Upload file",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/store/{hash}": {
|
||||
"get": {
|
||||
"description": "returns the content of the file /data/hash if exists",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"text/plain"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Download file",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "file",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/token": {
|
||||
"post": {
|
||||
"description": "issues a JWT token valid for one minute",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Generate JWT token",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.TokenResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/token/validate": {
|
||||
"post": {
|
||||
"description": "validates the JWT token",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Validate JWT token",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.TokenValidationResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/version": {
|
||||
"get": {
|
||||
"description": "returns podinfo version and git commit hash",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Version",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ws/echo": {
|
||||
"post": {
|
||||
"description": "echos content via websockets",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Echo over websockets",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Accepted",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"api.ArrayResponse": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
"api.MapResponse": {
|
||||
"type": "object",
|
||||
"additionalProperties": {}
|
||||
},
|
||||
"api.RuntimeResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"goarch": {
|
||||
"type": "string"
|
||||
},
|
||||
"goos": {
|
||||
"type": "string"
|
||||
},
|
||||
"hostname": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"num_cpu": {
|
||||
"type": "string"
|
||||
},
|
||||
"num_goroutine": {
|
||||
"type": "string"
|
||||
},
|
||||
"revision": {
|
||||
"type": "string"
|
||||
},
|
||||
"runtime": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.TokenResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expires_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.TokenValidationResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expires_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"token_name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
type swaggerInfo struct {
|
||||
Version string
|
||||
Host string
|
||||
BasePath string
|
||||
Schemes []string
|
||||
Title string
|
||||
Description string
|
||||
}
|
||||
|
||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||
var SwaggerInfo = swaggerInfo{Schemes: []string{"http", "https"}}
|
||||
|
||||
type s struct{}
|
||||
|
||||
func (s *s) ReadDoc() string {
|
||||
t, err := template.New("swagger_info").Funcs(template.FuncMap{
|
||||
"marshal": func(v interface{}) string {
|
||||
a, _ := json.Marshal(v)
|
||||
return string(a)
|
||||
},
|
||||
}).Parse(doc)
|
||||
if err != nil {
|
||||
return doc
|
||||
}
|
||||
|
||||
var tpl bytes.Buffer
|
||||
if err := t.Execute(&tpl, SwaggerInfo); err != nil {
|
||||
return doc
|
||||
}
|
||||
|
||||
return tpl.String()
|
||||
}
|
||||
|
||||
func init() {
|
||||
swag.Register(swag.Name, &s{})
|
||||
}
|
||||
542
pkg/api/docs/swagger.json
Normal file
542
pkg/api/docs/swagger.json
Normal file
@@ -0,0 +1,542 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "Go microservice template for Kubernetes.",
|
||||
"title": "Podinfo API",
|
||||
"contact": {
|
||||
"name": "Source Code",
|
||||
"url": "https://github.com/stefanprodan/podinfo"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT License",
|
||||
"url": "https://github.com/stefanprodan/podinfo/blob/master/LICENSE"
|
||||
},
|
||||
"version": "2.0"
|
||||
},
|
||||
"host": "localhost:9898",
|
||||
"basePath": "/",
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"description": "renders podinfo UI",
|
||||
"produces": [
|
||||
"text/html"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Index",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/echo": {
|
||||
"post": {
|
||||
"description": "forwards the call to the backend service and echos the posted content",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Echo",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Accepted",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/info": {
|
||||
"get": {
|
||||
"description": "returns the runtime information",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Runtime information",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.RuntimeResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/chunked/{seconds}": {
|
||||
"get": {
|
||||
"description": "uses transfer-encoding type chunked to give a partial response and then waits for the specified period",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Chunked transfer encoding",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/delay/{seconds}": {
|
||||
"get": {
|
||||
"description": "waits for the specified period",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Delay",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/env": {
|
||||
"get": {
|
||||
"description": "returns the environment variables as a JSON array",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Environment",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.ArrayResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/headers": {
|
||||
"get": {
|
||||
"description": "returns a JSON array with the request HTTP headers",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Headers",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.ArrayResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/healthz": {
|
||||
"get": {
|
||||
"description": "used by Kubernetes liveness probe",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Liveness check",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/metrics": {
|
||||
"get": {
|
||||
"description": "returns HTTP requests duration and Go runtime metrics",
|
||||
"produces": [
|
||||
"text/plain"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Prometheus metrics",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/panic": {
|
||||
"get": {
|
||||
"description": "crashes the process with exit code 255",
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Panic"
|
||||
}
|
||||
},
|
||||
"/readyz": {
|
||||
"get": {
|
||||
"description": "used by Kubernetes readiness probe",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Readiness check",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/readyz/disable": {
|
||||
"post": {
|
||||
"description": "signals the Kubernetes LB to stop sending requests to this instance",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Disable ready state",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/readyz/enable": {
|
||||
"post": {
|
||||
"description": "signals the Kubernetes LB that this instance is ready to receive traffic",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"summary": "Enable ready state",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/status/{code}": {
|
||||
"get": {
|
||||
"description": "sets the response status code to the specified code",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Status code",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/store": {
|
||||
"post": {
|
||||
"description": "writes the posted content to disk at /data/hash and returns the SHA1 hash of the content",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Upload file",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/store/{hash}": {
|
||||
"get": {
|
||||
"description": "returns the content of the file /data/hash if exists",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"text/plain"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Download file",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "file",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/token": {
|
||||
"post": {
|
||||
"description": "issues a JWT token valid for one minute",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Generate JWT token",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.TokenResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/token/validate": {
|
||||
"post": {
|
||||
"description": "validates the JWT token",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Validate JWT token",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.TokenValidationResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/version": {
|
||||
"get": {
|
||||
"description": "returns podinfo version and git commit hash",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Version",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ws/echo": {
|
||||
"post": {
|
||||
"description": "echos content via websockets",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"HTTP API"
|
||||
],
|
||||
"summary": "Echo over websockets",
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Accepted",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/api.MapResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"api.ArrayResponse": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
"api.MapResponse": {
|
||||
"type": "object",
|
||||
"additionalProperties": {}
|
||||
},
|
||||
"api.RuntimeResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"goarch": {
|
||||
"type": "string"
|
||||
},
|
||||
"goos": {
|
||||
"type": "string"
|
||||
},
|
||||
"hostname": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"num_cpu": {
|
||||
"type": "string"
|
||||
},
|
||||
"num_goroutine": {
|
||||
"type": "string"
|
||||
},
|
||||
"revision": {
|
||||
"type": "string"
|
||||
},
|
||||
"runtime": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.TokenResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expires_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.TokenValidationResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expires_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"token_name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
362
pkg/api/docs/swagger.yaml
Normal file
362
pkg/api/docs/swagger.yaml
Normal file
@@ -0,0 +1,362 @@
|
||||
basePath: /
|
||||
definitions:
|
||||
api.ArrayResponse:
|
||||
items: {}
|
||||
type: array
|
||||
api.MapResponse:
|
||||
additionalProperties: {}
|
||||
type: object
|
||||
api.RuntimeResponse:
|
||||
properties:
|
||||
color:
|
||||
type: string
|
||||
goarch:
|
||||
type: string
|
||||
goos:
|
||||
type: string
|
||||
hostname:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
num_cpu:
|
||||
type: string
|
||||
num_goroutine:
|
||||
type: string
|
||||
revision:
|
||||
type: string
|
||||
runtime:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
type: object
|
||||
api.TokenResponse:
|
||||
properties:
|
||||
expires_at:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
type: object
|
||||
api.TokenValidationResponse:
|
||||
properties:
|
||||
expires_at:
|
||||
type: string
|
||||
token_name:
|
||||
type: string
|
||||
type: object
|
||||
host: localhost:9898
|
||||
info:
|
||||
contact:
|
||||
name: Source Code
|
||||
url: https://github.com/stefanprodan/podinfo
|
||||
description: Go microservice template for Kubernetes.
|
||||
license:
|
||||
name: MIT License
|
||||
url: https://github.com/stefanprodan/podinfo/blob/master/LICENSE
|
||||
title: Podinfo API
|
||||
version: "2.0"
|
||||
paths:
|
||||
/:
|
||||
get:
|
||||
description: renders podinfo UI
|
||||
produces:
|
||||
- text/html
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
summary: Index
|
||||
tags:
|
||||
- HTTP API
|
||||
/api/echo:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: forwards the call to the backend service and echos the posted content
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"202":
|
||||
description: Accepted
|
||||
schema:
|
||||
$ref: '#/definitions/api.MapResponse'
|
||||
type: object
|
||||
summary: Echo
|
||||
tags:
|
||||
- HTTP API
|
||||
/api/info:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: returns the runtime information
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.RuntimeResponse'
|
||||
type: object
|
||||
summary: Runtime information
|
||||
tags:
|
||||
- HTTP API
|
||||
/chunked/{seconds}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: uses transfer-encoding type chunked to give a partial response
|
||||
and then waits for the specified period
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.MapResponse'
|
||||
type: object
|
||||
summary: Chunked transfer encoding
|
||||
tags:
|
||||
- HTTP API
|
||||
/delay/{seconds}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: waits for the specified period
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.MapResponse'
|
||||
type: object
|
||||
summary: Delay
|
||||
tags:
|
||||
- HTTP API
|
||||
/env:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: returns the environment variables as a JSON array
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.ArrayResponse'
|
||||
type: object
|
||||
summary: Environment
|
||||
tags:
|
||||
- HTTP API
|
||||
/headers:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: returns a JSON array with the request HTTP headers
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.ArrayResponse'
|
||||
type: object
|
||||
summary: Headers
|
||||
tags:
|
||||
- HTTP API
|
||||
/healthz:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: used by Kubernetes liveness probe
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
summary: Liveness check
|
||||
tags:
|
||||
- Kubernetes
|
||||
/metrics:
|
||||
get:
|
||||
description: returns HTTP requests duration and Go runtime metrics
|
||||
produces:
|
||||
- text/plain
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
summary: Prometheus metrics
|
||||
tags:
|
||||
- Kubernetes
|
||||
/panic:
|
||||
get:
|
||||
description: crashes the process with exit code 255
|
||||
summary: Panic
|
||||
tags:
|
||||
- HTTP API
|
||||
/readyz:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: used by Kubernetes readiness probe
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
summary: Readiness check
|
||||
tags:
|
||||
- Kubernetes
|
||||
/readyz/disable:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: signals the Kubernetes LB to stop sending requests to this instance
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"202":
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
summary: Disable ready state
|
||||
tags:
|
||||
- Kubernetes
|
||||
/readyz/enable:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: signals the Kubernetes LB that this instance is ready to receive
|
||||
traffic
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"202":
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
summary: Enable ready state
|
||||
tags:
|
||||
- Kubernetes
|
||||
/status/{code}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: sets the response status code to the specified code
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.MapResponse'
|
||||
type: object
|
||||
summary: Status code
|
||||
tags:
|
||||
- HTTP API
|
||||
/store:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: writes the posted content to disk at /data/hash and returns the
|
||||
SHA1 hash of the content
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.MapResponse'
|
||||
type: object
|
||||
summary: Upload file
|
||||
tags:
|
||||
- HTTP API
|
||||
/store/{hash}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: returns the content of the file /data/hash if exists
|
||||
produces:
|
||||
- text/plain
|
||||
responses:
|
||||
"200":
|
||||
description: file
|
||||
schema:
|
||||
type: string
|
||||
summary: Download file
|
||||
tags:
|
||||
- HTTP API
|
||||
/token:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: issues a JWT token valid for one minute
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.TokenResponse'
|
||||
type: object
|
||||
summary: Generate JWT token
|
||||
tags:
|
||||
- HTTP API
|
||||
/token/validate:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: validates the JWT token
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.TokenValidationResponse'
|
||||
type: object
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
type: string
|
||||
summary: Validate JWT token
|
||||
tags:
|
||||
- HTTP API
|
||||
/version:
|
||||
get:
|
||||
description: returns podinfo version and git commit hash
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/api.MapResponse'
|
||||
type: object
|
||||
summary: Version
|
||||
tags:
|
||||
- HTTP API
|
||||
/ws/echo:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: echos content via websockets
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"202":
|
||||
description: Accepted
|
||||
schema:
|
||||
$ref: '#/definitions/api.MapResponse'
|
||||
type: object
|
||||
summary: Echo over websockets
|
||||
tags:
|
||||
- HTTP API
|
||||
swagger: "2.0"
|
||||
@@ -10,6 +10,14 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Echo godoc
|
||||
// @Summary Echo
|
||||
// @Description forwards the call to the backend service and echos the posted content
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /api/echo [post]
|
||||
// @Success 202 {object} api.MapResponse
|
||||
func (s *Server) echoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
|
||||
@@ -11,6 +11,14 @@ import (
|
||||
|
||||
var wsCon = websocket.Upgrader{}
|
||||
|
||||
// EchoWS godoc
|
||||
// @Summary Echo over websockets
|
||||
// @Description echos content via websockets
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /ws/echo [post]
|
||||
// @Success 202 {object} api.MapResponse
|
||||
// Test: go run ./cmd/podcli/* ws localhost:9898/ws/echo
|
||||
func (s *Server) echoWsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
c, err := wsCon.Upgrade(w, r, nil)
|
||||
|
||||
@@ -6,6 +6,14 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Env godoc
|
||||
// @Summary Environment
|
||||
// @Description returns the environment variables as a JSON array
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /env [get]
|
||||
// @Success 200 {object} api.ArrayResponse
|
||||
func (s *Server) envHandler(w http.ResponseWriter, r *http.Request) {
|
||||
s.JSONResponse(w, r, os.Environ())
|
||||
}
|
||||
|
||||
@@ -4,6 +4,14 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Headers godoc
|
||||
// @Summary Headers
|
||||
// @Description returns a JSON array with the request HTTP headers
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /headers [get]
|
||||
// @Success 200 {object} api.ArrayResponse
|
||||
func (s *Server) echoHeadersHandler(w http.ResponseWriter, r *http.Request) {
|
||||
s.JSONResponse(w, r, r.Header)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,14 @@ import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Healthz godoc
|
||||
// @Summary Liveness check
|
||||
// @Description used by Kubernetes liveness probe
|
||||
// @Tags Kubernetes
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /healthz [get]
|
||||
// @Success 200 {string} string "OK"
|
||||
func (s *Server) healthzHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if atomic.LoadInt32(&healthy) == 1 {
|
||||
s.JSONResponse(w, r, map[string]string{"status": "OK"})
|
||||
@@ -13,6 +21,14 @@ func (s *Server) healthzHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
}
|
||||
|
||||
// Readyz godoc
|
||||
// @Summary Readiness check
|
||||
// @Description used by Kubernetes readiness probe
|
||||
// @Tags Kubernetes
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /readyz [get]
|
||||
// @Success 200 {string} string "OK"
|
||||
func (s *Server) readyzHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if atomic.LoadInt32(&ready) == 1 {
|
||||
s.JSONResponse(w, r, map[string]string{"status": "OK"})
|
||||
@@ -21,11 +37,27 @@ func (s *Server) readyzHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
}
|
||||
|
||||
// EnableReady godoc
|
||||
// @Summary Enable ready state
|
||||
// @Description signals the Kubernetes LB that this instance is ready to receive traffic
|
||||
// @Tags Kubernetes
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /readyz/enable [post]
|
||||
// @Success 202 {string} string "OK"
|
||||
func (s *Server) enableReadyHandler(w http.ResponseWriter, r *http.Request) {
|
||||
atomic.StoreInt32(&ready, 1)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
// DisableReady godoc
|
||||
// @Summary Disable ready state
|
||||
// @Description signals the Kubernetes LB to stop sending requests to this instance
|
||||
// @Tags Kubernetes
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /readyz/disable [post]
|
||||
// @Success 202 {string} string "OK"
|
||||
func (s *Server) disableReadyHandler(w http.ResponseWriter, r *http.Request) {
|
||||
atomic.StoreInt32(&ready, 0)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
|
||||
@@ -6,6 +6,13 @@ import (
|
||||
"path"
|
||||
)
|
||||
|
||||
// Index godoc
|
||||
// @Summary Index
|
||||
// @Description renders podinfo UI
|
||||
// @Tags HTTP API
|
||||
// @Produce html
|
||||
// @Router / [get]
|
||||
// @Success 200 {string} string "OK"
|
||||
func (s *Server) indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
tmpl, err := template.New("vue.html").ParseFiles(path.Join(s.config.UIPath, "vue.html"))
|
||||
if err != nil {
|
||||
|
||||
@@ -9,19 +9,16 @@ import (
|
||||
"github.com/stefanprodan/podinfo/pkg/version"
|
||||
)
|
||||
|
||||
// Info godoc
|
||||
// @Summary Runtime information
|
||||
// @Description returns the runtime information
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} api.RuntimeResponse
|
||||
// @Router /api/info [get]
|
||||
func (s *Server) infoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data := struct {
|
||||
Hostname string `json:"hostname"`
|
||||
Version string `json:"version"`
|
||||
Revision string `json:"revision"`
|
||||
Color string `json:"color"`
|
||||
Message string `json:"message"`
|
||||
GOOS string `json:"goos"`
|
||||
GOARCH string `json:"goarch"`
|
||||
Runtime string `json:"runtime"`
|
||||
NumGoroutine string `json:"num_goroutine"`
|
||||
NumCPU string `json:"num_cpu"`
|
||||
}{
|
||||
data := RuntimeResponse{
|
||||
Hostname: s.config.Hostname,
|
||||
Version: version.VERSION,
|
||||
Revision: version.REVISION,
|
||||
@@ -36,3 +33,16 @@ func (s *Server) infoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
s.JSONResponse(w, r, data)
|
||||
}
|
||||
|
||||
type RuntimeResponse struct {
|
||||
Hostname string `json:"hostname"`
|
||||
Version string `json:"version"`
|
||||
Revision string `json:"revision"`
|
||||
Color string `json:"color"`
|
||||
Message string `json:"message"`
|
||||
GOOS string `json:"goos"`
|
||||
GOARCH string `json:"goarch"`
|
||||
Runtime string `json:"runtime"`
|
||||
NumGoroutine string `json:"num_goroutine"`
|
||||
NumCPU string `json:"num_cpu"`
|
||||
}
|
||||
|
||||
@@ -47,6 +47,13 @@ func NewPrometheusMiddleware() *PrometheusMiddleware {
|
||||
}
|
||||
}
|
||||
|
||||
// Metrics godoc
|
||||
// @Summary Prometheus metrics
|
||||
// @Description returns HTTP requests duration and Go runtime metrics
|
||||
// @Tags Kubernetes
|
||||
// @Produce plain
|
||||
// @Router /metrics [get]
|
||||
// @Success 200 {string} string "OK"
|
||||
func (p *PrometheusMiddleware) Handler(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
begin := time.Now()
|
||||
|
||||
@@ -4,6 +4,11 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Panic godoc
|
||||
// @Summary Panic
|
||||
// @Description crashes the process with exit code 255
|
||||
// @Tags HTTP API
|
||||
// @Router /panic [get]
|
||||
func (s *Server) panicHandler(w http.ResponseWriter, r *http.Request) {
|
||||
s.logger.Panic("Panic command received")
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/swaggo/swag"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
@@ -13,10 +14,26 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/spf13/viper"
|
||||
_ "github.com/stefanprodan/podinfo/pkg/api/docs"
|
||||
"github.com/stefanprodan/podinfo/pkg/fscache"
|
||||
"github.com/swaggo/http-swagger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// @title Podinfo API
|
||||
// @version 2.0
|
||||
// @description Go microservice template for Kubernetes.
|
||||
|
||||
// @contact.name Source Code
|
||||
// @contact.url https://github.com/stefanprodan/podinfo
|
||||
|
||||
// @license.name MIT License
|
||||
// @license.url https://github.com/stefanprodan/podinfo/blob/master/LICENSE
|
||||
|
||||
// @host localhost:9898
|
||||
// @BasePath /
|
||||
// @schemes http https
|
||||
|
||||
var (
|
||||
healthy int32
|
||||
ready int32
|
||||
@@ -83,6 +100,19 @@ func (s *Server) registerHandlers() {
|
||||
s.router.HandleFunc("/ws/echo", s.echoWsHandler)
|
||||
s.router.HandleFunc("/chunked", s.chunkedHandler)
|
||||
s.router.HandleFunc("/chunked/{wait:[0-9]+}", s.chunkedHandler)
|
||||
s.router.PathPrefix("/swagger/").Handler(httpSwagger.Handler(
|
||||
httpSwagger.URL("/swagger/doc.json"),
|
||||
))
|
||||
s.router.PathPrefix("/swagger/").Handler(httpSwagger.Handler(
|
||||
httpSwagger.URL("/swagger/doc.json"),
|
||||
))
|
||||
s.router.HandleFunc("/swagger.json", func(w http.ResponseWriter, r *http.Request) {
|
||||
doc, err := swag.ReadDoc()
|
||||
if err != nil {
|
||||
s.logger.Error("swagger error", zap.Error(err), zap.String("path", "/swagger.json"))
|
||||
}
|
||||
w.Write([]byte(doc))
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) registerMiddlewares() {
|
||||
@@ -206,3 +236,6 @@ func (s *Server) printRoutes() {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
type ArrayResponse []string
|
||||
type MapResponse map[string]string
|
||||
|
||||
@@ -7,6 +7,14 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Status godoc
|
||||
// @Summary Status code
|
||||
// @Description sets the response status code to the specified code
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /status/{code} [get]
|
||||
// @Success 200 {object} api.MapResponse
|
||||
func (s *Server) statusHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
|
||||
|
||||
@@ -11,6 +11,14 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Store godoc
|
||||
// @Summary Upload file
|
||||
// @Description writes the posted content to disk at /data/hash and returns the SHA1 hash of the content
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /store [post]
|
||||
// @Success 200 {object} api.MapResponse
|
||||
func (s *Server) storeWriteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
@@ -29,6 +37,14 @@ func (s *Server) storeWriteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
s.JSONResponseCode(w, r, map[string]string{"hash": hash}, http.StatusAccepted)
|
||||
}
|
||||
|
||||
// Store godoc
|
||||
// @Summary Download file
|
||||
// @Description returns the content of the file /data/hash if exists
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce plain
|
||||
// @Router /store/{hash} [get]
|
||||
// @Success 200 {string} string "file"
|
||||
func (s *Server) storeReadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
hash := mux.Vars(r)["hash"]
|
||||
content, err := ioutil.ReadFile(path.Join(s.config.DataPath, hash))
|
||||
|
||||
@@ -17,6 +17,14 @@ type jwtCustomClaims struct {
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
// Token godoc
|
||||
// @Summary Generate JWT token
|
||||
// @Description issues a JWT token valid for one minute
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /token [post]
|
||||
// @Success 200 {object} api.TokenResponse
|
||||
func (s *Server) tokenGenerateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
@@ -46,10 +54,7 @@ func (s *Server) tokenGenerateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var result = struct {
|
||||
Token string `json:"token"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}{
|
||||
var result = TokenResponse{
|
||||
Token: t,
|
||||
ExpiresAt: time.Unix(claims.StandardClaims.ExpiresAt, 0),
|
||||
}
|
||||
@@ -57,6 +62,15 @@ func (s *Server) tokenGenerateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
s.JSONResponse(w, r, result)
|
||||
}
|
||||
|
||||
// TokenValidate godoc
|
||||
// @Summary Validate JWT token
|
||||
// @Description validates the JWT token
|
||||
// @Tags HTTP API
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /token/validate [post]
|
||||
// @Success 200 {object} api.TokenValidationResponse
|
||||
// @Failure 401 {string} string "Unauthorized"
|
||||
// Get: JWT=$(curl -s -d 'test' localhost:9898/token | jq -r .token)
|
||||
// Post: curl -H "Authorization: Bearer ${JWT}" localhost:9898/token/validate
|
||||
func (s *Server) tokenValidateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -87,10 +101,7 @@ func (s *Server) tokenValidateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if claims.StandardClaims.Issuer != "podinfo" {
|
||||
s.ErrorResponse(w, r, "invalid issuer", http.StatusUnauthorized)
|
||||
} else {
|
||||
var result = struct {
|
||||
TokenName string `json:"token_name"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}{
|
||||
var result = TokenValidationResponse{
|
||||
TokenName: claims.Name,
|
||||
ExpiresAt: time.Unix(claims.StandardClaims.ExpiresAt, 0),
|
||||
}
|
||||
@@ -100,3 +111,13 @@ func (s *Server) tokenValidateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
s.ErrorResponse(w, r, "Invalid authorization token", http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
type TokenResponse struct {
|
||||
Token string `json:"token"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
|
||||
type TokenValidationResponse struct {
|
||||
TokenName string `json:"token_name"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
|
||||
@@ -6,6 +6,13 @@ import (
|
||||
"github.com/stefanprodan/podinfo/pkg/version"
|
||||
)
|
||||
|
||||
// Version godoc
|
||||
// @Summary Version
|
||||
// @Description returns podinfo version and git commit hash
|
||||
// @Tags HTTP API
|
||||
// @Produce json
|
||||
// @Router /version [get]
|
||||
// @Success 200 {object} api.MapResponse
|
||||
func (s *Server) versionHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := map[string]string{
|
||||
"version": version.VERSION,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package version
|
||||
|
||||
var VERSION = "2.0.2"
|
||||
var VERSION = "2.1.0"
|
||||
var REVISION = "unknown"
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
Powered
|
||||
by <a class="white--text" href="https://github.com/stefanprodan/podinfo" target="_blank">podinfo</a>
|
||||
version ${ info.version } revision ${ info.revision }
|
||||
Swagger <a class="white--text" href="swagger/">docs</a>
|
||||
</div>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
|
||||
Reference in New Issue
Block a user