diff --git a/.github/workflows/master.yaml b/.github/workflows/master.yaml new file mode 100644 index 0000000..d25d8c1 --- /dev/null +++ b/.github/workflows/master.yaml @@ -0,0 +1,30 @@ +name: Docker Image + +on: + push: + branches: + - master + tags: + - "v*" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v1 + - name: Lint code + uses: actions-contrib/golangci-lint@master + with: + args: run + - name: Set up Go 1.13 + uses: actions/setup-go@v1.1.2 + with: + go-version: '1.13.x' + - name: Test + run: make test + - name: Build and Push Docker Image + run: | + docker login -u metalstackci -p ${{ secrets.DOCKER_HUB_TOKEN }} + make dockerimage + make dockerpush diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07aa75c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin +metal-api + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3e2c5ee --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM metalstack/builder:latest as builder + +FROM registry.fi-ts.io/metal/supermicro:2.4.0 as sum +FROM debian:10 + +RUN apt update \ + && apt install --yes --no-install-recommends \ + ca-certificates +COPY --from=builder /work/bin/ipmi-catcher / +COPY --from=sum /usr/bin/sum /sum + +CMD ["/ipmi-catcher"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1979cb6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 The Metal Stack Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7495ec7 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +.ONESHELL: +BINARY := ipmi-catcher +COMMONDIR := $(or ${COMMONDIR},../common) +DOCKER_TAG := $(or ${GITHUB_TAG_NAME}, latest) + +include $(COMMONDIR)/Makefile.inc + +release:: clean-local-dirs generate-client test all; + +.PHONY: clean-local-dirs +clean-local-dirs: + rm -rf metal-api + mkdir metal-api + +.PHONY: clean-client +clean-client: clean-local-dirs + cp ../metal-api/spec/metal-api.json metal-api.json + +.PHONY: fmt +fmt: + GO111MODULE=off go fmt ./... + +.PHONY: generate-client +generate-client: clean-local-dirs fmt + GO111MODULE=off swagger generate client --target=metal-api -f metal-api.json --skip-validation + +.PHONY: dockerimage +dockerimage: + docker build -t metalstack/ipmi-catcher:${DOCKER_TAG} . + +.PHONY: dockerpush +dockerpush: + docker push metalstack/ipmi-catcher:${DOCKER_TAG} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..2114202 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# ipmi-catcher + +Reports the ip addresses that are leased to ipmi devices together with their machine uuids to the `metal-api`. + +Therewith it is possible to have knowledge about new machines very early in the `metal-api` and also get knowledge about possibly changing ipmi ip addresses. + +`ipmi-catcher` parses the DHCPD lease file and reports the mapping of machine uuids to ipmi ip address to the `metal-api`. diff --git a/dhcpd.leases b/dhcpd.leases new file mode 100644 index 0000000..70f0749 --- /dev/null +++ b/dhcpd.leases @@ -0,0 +1,22 @@ +lease 192.168.2.27 { + starts 4 2019/06/27 06:40:21; + ends 4 2020/06/27 06:50:21; + cltt 4 2020/06/27 06:40:21; + binding state active; + next binding state free; + rewind binding state free; + hardware ethernet ac:1f:6b:35:ac:62; + uid "\001\254\037k5\254b"; + set vendor-class-identifier = "udhcp 1.23.1"; +} +lease 192.168.2.30 { + starts 4 2019/06/27 06:40:06; + ends 4 2020/06/27 06:50:06; + cltt 4 2019/06/27 06:40:06; + binding state active; + next binding state free; + rewind binding state free; + hardware ethernet ac:1f:6b:35:ab:2d; + uid "\001\254\037k5\253-"; + set vendor-class-identifier = "udhcp 1.23.1"; +} \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..1486f49 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,18 @@ +--- +version: '3.7' + +services: + ipmi-catcher: + build: + context: . + image: metalstack/ipmi-catcher:latest + network_mode: host + volumes: + - ${PWD}/dhcpd.leases:/dhcpd.leases + environment: + IPMI_CATCHER_LEASE_FILE: /dhcpd.leases + IPMI_CATCHER_PARTITION_ID: partition + IPMI_CATCHER_METAL_API_URL: http://localhost:8080 + IPMI_CATCHER_METAL_API_HMAC_KEY: test + IPMI_CATCHER_IGNORE_MACS: "aa:aa:aa:aa:aa:aa" + diff --git a/domain/config.go b/domain/config.go new file mode 100644 index 0000000..ca1b099 --- /dev/null +++ b/domain/config.go @@ -0,0 +1,27 @@ +package domain + +import ( + "fmt" + "net/url" + "time" +) + +type Config struct { + // Valid log levels are: DEBUG, INFO, WARN, ERROR, FATAL and PANIC + LogLevel string `required:"false" default:"debug" desc:"set log level" split_words:"true"` + PartitionID string `required:"true" desc:"set the partition ID" envconfig:"partition_id"` + LeaseFile string `required:"false" default:"/var/lib/dhcp/dhcpd.leases" desc:"the dhcp lease file to read" split_words:"true"` + DebounceInterval time.Duration `required:"false" default:"20s" desc:"the duration to debounce dhcp events" split_words:"true"` + ReportInterval time.Duration `required:"false" default:"5m" desc:"the interval for periodical reports" split_words:"true"` + MetalAPIURL *url.URL `required:"true" desc:"endpoint for the metal-api" envconfig:"metal_api_url"` + MetalAPIHMACKey string `required:"true" desc:"the preshared key for the hmac calculation" envconfig:"metal_api_hmac_key"` + IpmiUser string `required:"false" default:"ADMIN" desc:"the ipmi user" split_words:"true"` + IpmiPassword string `required:"false" default:"ADMIN" desc:"the ipmi password" split_words:"true"` + SumBin string `required:"false" default:"/sum" desc:"the sum binary" split_words:"true"` + IgnoreMacs []string `required:"false" desc:"mac addresses to ignore" split_words:"true"` +} + +func (c Config) String() string { + return fmt.Sprintf("loglevel:%s partition:%s leasefile:%s debounce interval:%s report interval:%s metal-api url:%s ipmiuser:%s sum:%s", + c.LogLevel, c.PartitionID, c.LeaseFile, c.DebounceInterval, c.ReportInterval, c.MetalAPIURL, c.IpmiUser, c.SumBin) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d030a22 --- /dev/null +++ b/go.mod @@ -0,0 +1,28 @@ +module github.com/metal-stack/ipmi-catcher + +go 1.13 + +require ( + github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 // indirect + github.com/go-openapi/analysis v0.19.7 // indirect + github.com/go-openapi/errors v0.19.3 + github.com/go-openapi/runtime v0.19.11 + github.com/go-openapi/spec v0.19.6 // indirect + github.com/go-openapi/strfmt v0.19.4 + github.com/go-openapi/swag v0.19.7 + github.com/go-openapi/validate v0.19.6 + github.com/kelseyhightower/envconfig v1.4.0 + github.com/metal-stack/security v0.0.0-20200207131443-5520f3976826 + github.com/metal-stack/v v1.0.1 + github.com/pkg/errors v0.9.1 // indirect + github.com/stretchr/testify v1.4.0 + go.mongodb.org/mongo-driver v1.3.0 // indirect + go.uber.org/atomic v1.5.1 // indirect + go.uber.org/multierr v1.4.0 // indirect + go.uber.org/zap v1.13.0 + go.universe.tf/netboot v0.0.0-20200205210610-68743c67a60c + golang.org/x/lint v0.0.0-20200130185559-910be7a94367 // indirect + golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect + golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 // indirect + golang.org/x/tools v0.0.0-20200211205636-11eff242d136 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b72a5ca --- /dev/null +++ b/go.sum @@ -0,0 +1,411 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/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/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0= +github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.18.0 h1:hRMEymXOgwo7KLPqqFmw6t3jLO2/zxUe/TXjAHPq9Gc= +github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/analysis v0.19.7 h1:OcMMVVJBRiSsAkXQwSVL4sRrVaqeqPnOcy1Kw0JI47w= +github.com/go-openapi/analysis v0.19.7/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.18.0 h1:+RnmJ5MQccF7jwWAoMzwOpzJEspZ18ZIWfg9Z2eiXq8= +github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/errors v0.19.3 h1:7MGZI1ibQDLasvAz8HuhvYk9eNJbJkCOXWsSjjMS+Zc= +github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.18.0 h1:KVRzjXpMzgdM4GEMDmDTnGcY5yBwGWreJwmmk4k35yU= +github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.18.0 h1:oP2OUNdG1l2r5kYhrfVMXO54gWmzcfAwP/GFuHpNTkE= +github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.18.0 h1:2A3goxrC4KuN8ZrMKHCqAAugtq6A6WfXVfOIKUbZ4n0= +github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI= +github.com/go-openapi/loads v0.19.4 h1:5I4CCSqoWzT+82bBkNIvmLc0UOsoKKQ4Fz+3VxOB7SY= +github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.19.0 h1:sU6pp4dSV2sGlNKKyHxZzi1m1kG4WnYtWcJ+HYbygjE= +github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= +github.com/go-openapi/runtime v0.19.11 h1:6J11dQiIV+BOLlMbk2YmM8RvGaOU38syeqy62qhh3W8= +github.com/go-openapi/runtime v0.19.11/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.18.0 h1:aIjeyG5mo5/FrvDkpKKEGZPmF9MPHahS72mzfVqeQXQ= +github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.6 h1:rMMMj8cV38KVXK7SFc+I2MWClbEfbK705+j+dyqun5g= +github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.18.0 h1:FqqmmVCKn3di+ilU/+1m957T1CnMz3IteVUcV3aGXWA= +github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.4 h1:eRvaqAhpL0IL6Trh5fDsGnGhiXndzHFuA05w6sXH6/g= +github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.18.0 h1:1DU8Km1MRGv9Pj7BNLmkA+umwTStwDHttXvx3NhJA70= +github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.7 h1:VRuXN2EnMSsZdauzdss6JBC29YotDqG59BZ+tdlIL1s= +github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= +github.com/go-openapi/validate v0.18.0 h1:PVXYcP1GkTl+XIAJnyJxOmK6CSG5Q1UcvoCvNO++5Kg= +github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= +github.com/go-openapi/validate v0.19.6 h1:WsKw9J1WzYBVxWRYwLqEk3325RL6G0SSWksuamkk6q0= +github.com/go-openapi/validate v0.19.6/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lestrrat-go/jwx v0.9.0 h1:Fnd0EWzTm0kFrBPzE/PEPp9nzllES5buMkksPMjEKpM= +github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe h1:W/GaMY0y69G4cFlmsC6B9sbuo2fP8OFP1ABjt4kPz+w= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/metal-stack/security v0.0.0-20200207131443-5520f3976826 h1:ZshjLMAhpb9z6JkcDtAR1JQxQbhMgF8glRNTYzhB0js= +github.com/metal-stack/security v0.0.0-20200207131443-5520f3976826/go.mod h1:xa0eka4HttrfhDTJPzcSDBGgaFyNBGXhz0B5YGqtKuU= +github.com/metal-stack/v v1.0.1 h1:N0dy3N8drkarX2b7RiwzzjEBoO1t7dGY03o+m4cEv1U= +github.com/metal-stack/v v1.0.1/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= +github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +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/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA= +go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.3.0 h1:ew6uUIeJOo+qdUUv7LxFCUhtWmVv7ZV/Xuy4FAUsw2E= +go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.5.1 h1:rsqfU5vBkVknbhUGbAUwQKR2H4ItV8tjJ+6kJX4cxHM= +go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.universe.tf/netboot v0.0.0-20200205210610-68743c67a60c h1:nxMYuDEgVAWf662sIrwipBsCUvj5uPhvg7FgVJiDtpM= +go.universe.tf/netboot v0.0.0-20200205210610-68743c67a60c/go.mod h1:bm5r5Be3Bb7PPjUGBfGWOFeAKj63GC5pWXDAzIDVM3c= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367 h1:0IiAsCRByjO2QjX7ZPkw5oU9x+n1YqRL802rjC0c3Aw= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 h1:sfkvUWPNGwSV+8/fNqctR5lS2AqCSqYwXdrjCxp/dXo= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200211205636-11eff242d136 h1:yFWeDNMOyrJIQNtXrNR5smCrv+Y4IN6Ul42TzAXxd9k= +golang.org/x/tools v0.0.0-20200211205636-11eff242d136/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/internal/ipmi/uuid.go b/internal/ipmi/uuid.go new file mode 100644 index 0000000..ea53b8b --- /dev/null +++ b/internal/ipmi/uuid.go @@ -0,0 +1,118 @@ +package ipmi + +import ( + "bufio" + "fmt" + "os/exec" + "regexp" + "strings" + "sync" + + "go.uber.org/zap" +) + +const ( + uuidRegex = `([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})` +) + +var ( + uuidRegexCompiled = regexp.MustCompile(uuidRegex) +) + +type UUIDCache struct { + macToUUID map[string]string + ipmiUser string + ipmiPassword string + sumBin string + log *zap.SugaredLogger +} + +type entry struct { + mac string + uuid string +} + +func NewUUIDCache(ipmiUser, ipmiPassword, sumBin string) UUIDCache { + z, _ := zap.NewProduction() + return UUIDCache{ + macToUUID: map[string]string{}, + ipmiUser: ipmiUser, + ipmiPassword: ipmiPassword, + sumBin: sumBin, + log: z.Sugar(), + } +} + +// Warmup fetches uuids of given ips +func (u UUIDCache) Warmup(macToIps map[string]string) { + var wg sync.WaitGroup + ch := make(chan entry) + for mac, ip := range macToIps { + wg.Add(1) + go u.warmupWorker(&wg, mac, ip, ch) + } + go func() { + wg.Wait() + close(ch) + }() + for e := range ch { + u.macToUUID[e.mac] = e.uuid + } +} + +func (u UUIDCache) warmupWorker(wg *sync.WaitGroup, mac, ip string, ch chan entry) { + defer wg.Done() + uuid, err := u.loadUUID(ip, u.ipmiUser, u.ipmiPassword, u.sumBin) + if err != nil { + u.log.Errorw("warmupWorker", "error during loadUUID", err) + return + } + ch <- entry{ + uuid: uuid, + mac: mac, + } +} + +// Get lazy fetch a machine uuid from a warm cache, if not present fetch it. +func (u UUIDCache) Get(mac, ip string) (*string, error) { + if uuid, ok := u.macToUUID[mac]; ok { + return &uuid, nil + } + uuid, err := u.loadUUID(ip, u.ipmiUser, u.ipmiPassword, u.sumBin) + if err != nil { + return nil, err + } + u.macToUUID[mac] = uuid + return &uuid, nil +} + +func parseUUIDLine(l string) string { + return strings.ToLower(uuidRegexCompiled.FindString(l)) +} + +func (u UUIDCache) loadUUID(ip, user, password, sum string) (string, error) { + args := []string{"--no_banner", "--no_progress", "--journal_level", "0", "-i", ip, "-u", user, "-p", password, "-c", "GetDmiInfo"} + cmd := exec.Command(sum, args...) + out, err := cmd.StdoutPipe() + if err != nil { + return "", fmt.Errorf("could not initiate sum command to get dmi data from ip:%s, err: %v", ip, err) + } + err = cmd.Start() + if err != nil { + return "", fmt.Errorf("could not start sum command to get dmi data from ip:%s, err: %v", ip, err) + } + go func() { + err = cmd.Wait() + if err != nil { + u.log.Errorw("loadUUID", "ip", ip, "wait error", err) + } + }() + s := bufio.NewScanner(out) + for s.Scan() { + l := s.Text() + if strings.HasPrefix(l, "UUID") { + return parseUUIDLine(l), nil + } + } + return "", fmt.Errorf("could not find UUID in dmi data for ip:%s", ip) +} diff --git a/internal/ipmi/uuid_test.go b/internal/ipmi/uuid_test.go new file mode 100644 index 0000000..fa2f913 --- /dev/null +++ b/internal/ipmi/uuid_test.go @@ -0,0 +1,14 @@ +package ipmi + +import ( + "testing" +) + +func TestPrseUUIDLine(t *testing.T) { + l := "UUID {SYUU} = 00000000-0000-0000-0000-AC1F6B7AEB76 // 4-2-2-2-6 formatted 16-byte hex values" + e := "00000000-0000-0000-0000-ac1f6b7aeb76" + a := parseUUIDLine(l) + if e != a { + t.Fail() + } +} diff --git a/internal/leases/leases.go b/internal/leases/leases.go new file mode 100644 index 0000000..b156db2 --- /dev/null +++ b/internal/leases/leases.go @@ -0,0 +1,48 @@ +package leases + +import ( + "fmt" + "io/ioutil" + "time" +) + +func (l Leases) FilterActive() Leases { + active := Leases{} + now := time.Now() + for _, lease := range l { + if lease.End.Before(now) { + continue + } + active = append(active, lease) + } + return active +} + +func (l Leases) LatestByMac() map[string]Lease { + byMac := map[string]Lease{} + for _, lease := range l { + if e, ok := byMac[lease.Mac]; !ok { + byMac[lease.Mac] = lease + } else if lease.End.After(e.End) { + byMac[lease.Mac] = lease + } + } + return byMac +} + +func ReadLeases(leaseFile string) (Leases, error) { + leasesContent := mustRead(leaseFile) + leases, err := Parse(leasesContent) + if err != nil { + return nil, fmt.Errorf("could not parse leases file, err: %v", err) + } + return leases, nil +} + +func mustRead(name string) string { + c, err := ioutil.ReadFile(name) + if err != nil { + panic(err) + } + return string(c) +} diff --git a/internal/leases/leases_test.go b/internal/leases/leases_test.go new file mode 100644 index 0000000..f33d0c5 --- /dev/null +++ b/internal/leases/leases_test.go @@ -0,0 +1,35 @@ +package leases + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestFilterActive(t *testing.T) { + assert := assert.New(t) + l, err := Parse(LEASES_CONTENT) + assert.NoError(err) + assert.Equal(Leases{}, l.FilterActive()) +} + +func TestLatestByMac(t *testing.T) { + assert := assert.New(t) + l1 := Lease{ + Mac: "aa:aa", + End: time.Now(), + } + l2 := Lease{ + Mac: "bb:bb", + End: time.Now(), + } + l3 := Lease{ + Mac: "aa:aa", + End: time.Now().AddDate(0, 0, -1), + } + leases := Leases{l1, l2, l3} + byMac := leases.LatestByMac() + expected := map[string]Lease{"aa:aa": l1, "bb:bb": l2} + assert.Equal(expected, byMac) +} diff --git a/internal/leases/parser.go b/internal/leases/parser.go new file mode 100644 index 0000000..e96c3ac --- /dev/null +++ b/internal/leases/parser.go @@ -0,0 +1,40 @@ +package leases + +import ( + "regexp" + "time" +) + +const DATE_FORMAT = "2006/01/02 15:04:05" +const LEASE_REGEX = `(?ms)lease\s+(?P[^\s]+)\s+{.*?starts\s\d+\s(?P[\d\/]+\s[\d\:]+);.*?ends\s\d+\s(?P[\d\/]+\s[\d\:]+);.*?hardware\sethernet\s(?P[\w\:]+);.*?}` + +func Parse(contents string) (Leases, error) { + leases := Leases{} + var re = regexp.MustCompile(LEASE_REGEX) + matches := re.FindAllStringSubmatch(contents, -1) + for _, m := range matches { + rm := make(map[string]string) + for i, name := range re.SubexpNames() { + if i != 0 && name != "" { + rm[name] = m[i] + } + } + begin, err := time.Parse(DATE_FORMAT, rm["begin"]) + if err != nil { + panic(err) + } + end, err := time.Parse(DATE_FORMAT, rm["end"]) + if err != nil { + panic(err) + } + + l := Lease{ + Mac: rm["mac"], + Ip: rm["ip"], + Begin: begin, + End: end, + } + leases = append(leases, l) + } + return leases, nil +} diff --git a/internal/leases/parser_test.go b/internal/leases/parser_test.go new file mode 100644 index 0000000..1480fe4 --- /dev/null +++ b/internal/leases/parser_test.go @@ -0,0 +1,59 @@ +package leases + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +var LEASES_CONTENT = ` +lease 192.168.2.27 { + starts 4 2019/06/27 13:30:21; + ends 4 2019/06/27 13:40:21; + cltt 4 2019/06/27 13:30:21; + binding state active; + next binding state free; + rewind binding state free; + hardware ethernet ac:1f:6b:35:ac:62; + uid "\001\254\037k5\254b"; + set vendor-class-identifier = "udhcp 1.23.1"; +} +lease 192.168.2.30 { + starts 4 2019/06/27 06:40:06; + ends 4 2019/06/27 06:50:06; + cltt 4 2019/06/27 06:40:06; + binding state active; + next binding state free; + rewind binding state free; + hardware ethernet ac:1f:6b:35:ab:2d; + uid "\001\254\037k5\253-"; + set vendor-class-identifier = "udhcp 1.23.1"; +} +` + +func TestParse(t *testing.T) { + assert := assert.New(t) + l, err := Parse(LEASES_CONTENT) + assert.NoError(err) + + b, _ := time.Parse(DATE_FORMAT, "2019/06/27 13:30:21") + e, _ := time.Parse(DATE_FORMAT, "2019/06/27 13:40:21") + lease1 := Lease{ + Mac: "ac:1f:6b:35:ac:62", + Ip: "192.168.2.27", + Begin: b, + End: e, + } + + b, _ = time.Parse(DATE_FORMAT, "2019/06/27 06:40:06") + e, _ = time.Parse(DATE_FORMAT, "2019/06/27 06:50:06") + lease2 := Lease{ + Mac: "ac:1f:6b:35:ab:2d", + Ip: "192.168.2.30", + Begin: b, + End: e, + } + + assert.Equal(Leases{lease1, lease2}, l) +} diff --git a/internal/leases/types.go b/internal/leases/types.go new file mode 100644 index 0000000..f889d14 --- /dev/null +++ b/internal/leases/types.go @@ -0,0 +1,12 @@ +package leases + +import "time" + +type Lease struct { + Mac string + Ip string + Begin time.Time + End time.Time +} + +type Leases []Lease diff --git a/internal/reporter/driver.go b/internal/reporter/driver.go new file mode 100644 index 0000000..83d4b07 --- /dev/null +++ b/internal/reporter/driver.go @@ -0,0 +1,46 @@ +package reporter + +import ( + "fmt" + "net/url" + "time" + + "github.com/go-openapi/runtime" + httptransport "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" + "github.com/metal-stack/ipmi-catcher/metal-api/client/machine" + "github.com/metal-stack/security" +) + +type driver struct { + machine *machine.Client + auth runtime.ClientAuthInfoWriter + hmac *security.HMACAuth +} + +func newDriver(rawurl, hmac string) (*driver, error) { + parsedurl, err := url.Parse(rawurl) + if err != nil { + return nil, err + } + if parsedurl.Host == "" { + return nil, fmt.Errorf("invalid url:%s, must be in the form scheme://host[:port]/basepath", rawurl) + } + transport := httptransport.New(parsedurl.Host, parsedurl.Path, []string{parsedurl.Scheme}) + driver := &driver{ + machine: machine.New(transport, strfmt.Default), + } + if hmac != "" { + auth := security.NewHMACAuth("Metal-Edit", []byte(hmac)) + driver.hmac = &auth + } + driver.auth = runtime.ClientAuthInfoWriterFunc(driver.auther) + return driver, nil +} + +func (d *driver) auther(rq runtime.ClientRequest, rg strfmt.Registry) error { + if d.hmac != nil { + d.hmac.AddAuthToClientRequest(rq, time.Now()) + } + return nil +} diff --git a/internal/reporter/reporter.go b/internal/reporter/reporter.go new file mode 100644 index 0000000..4762ce6 --- /dev/null +++ b/internal/reporter/reporter.go @@ -0,0 +1,73 @@ +package reporter + +import ( + "github.com/metal-stack/ipmi-catcher/domain" + "github.com/metal-stack/ipmi-catcher/internal/ipmi" + "github.com/metal-stack/ipmi-catcher/internal/leases" + "github.com/metal-stack/ipmi-catcher/metal-api/client/machine" + "github.com/metal-stack/ipmi-catcher/metal-api/models" + "go.uber.org/zap" +) + +type Reporter struct { + cfg *domain.Config + log *zap.SugaredLogger + driver *driver + mc *machine.Client + uuidCache *ipmi.UUIDCache +} + +func NewReporter(cfg *domain.Config, uuidCache *ipmi.UUIDCache, log *zap.SugaredLogger) (*Reporter, error) { + driver, err := newDriver(cfg.MetalAPIURL.String(), cfg.MetalAPIHMACKey) + mc := driver.machine + if err != nil { + return nil, err + } + return &Reporter{ + cfg: cfg, + log: log, + driver: driver, + mc: mc, + uuidCache: uuidCache, + }, nil +} + +func (r Reporter) Report(ls leases.Leases) error { + active := ls.FilterActive() + byMac := active.LatestByMac() + r.log.Infow("reporting leases to metal-api", "all", len(ls), "active", len(active), "uniqueActive", len(byMac)) + partitionID := r.cfg.PartitionID + l := map[string]string{} +outer: + for mac, v := range byMac { + for _, m := range r.cfg.IgnoreMacs { + if m == mac { + continue outer + } + } + uuid, err := r.uuidCache.Get(mac, v.Ip) + if err != nil { + r.log.Errorw("could not determine uuid of device", "mac", mac, "ip", v.Ip, "err", err) + continue + } + l[*uuid] = v.Ip + } + params := machine.NewIPMIReportParams() + req := &models.V1MachineIPMIReport{ + Partitionid: &partitionID, + Leases: l, + } + params.SetBody(req) + ok, err := r.mc.IPMIReport(params, r.driver.auth) + if err != nil { + return err + } + r.log.Infof("updated ipmi ips of %d machines", len(ok.Payload.Updated)) + for uuid, ip := range ok.Payload.Updated { + r.log.Infow("ipmi ip address was updated for machine", "id", uuid, "ip", ip) + } + for uuid, ip := range ok.Payload.Created { + r.log.Infow("ipmi ip address was set and machine was created", "id", uuid, "ip", ip) + } + return nil +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..0d25c4c --- /dev/null +++ b/main.go @@ -0,0 +1,100 @@ +package main + +import ( + "os" + "os/signal" + "syscall" + "time" + + "github.com/metal-stack/ipmi-catcher/domain" + "github.com/metal-stack/ipmi-catcher/internal/ipmi" + "github.com/metal-stack/ipmi-catcher/internal/leases" + "github.com/metal-stack/ipmi-catcher/internal/reporter" + "github.com/metal-stack/v" + + "github.com/kelseyhightower/envconfig" + "go.uber.org/zap" + "go.universe.tf/netboot/dhcp4" +) + +func main() { + logger, _ := zap.NewProduction() + log := logger.Sugar() + log.Infof("running app version: %s", v.V.String()) + var cfg domain.Config + if err := envconfig.Process("IPMI_CATCHER", &cfg); err != nil { + log.Fatalf("bad configuration: %v", err) + } + + log.Infow("loaded configuration", "config", cfg) + l, err := leases.ReadLeases(cfg.LeaseFile) + if err != nil { + log.Fatalf("could not parse leases file, err: %v", err) + } + + log.Info("warming up cache") + leasesByMac := l.LatestByMac() + macToIps := map[string]string{} + for m, l := range leasesByMac { + macToIps[m] = l.Ip + } + uuidCache := ipmi.NewUUIDCache(cfg.IpmiUser, cfg.IpmiPassword, cfg.SumBin) + uuidCache.Warmup(macToIps) + + r, err := reporter.NewReporter(&cfg, &uuidCache, log) + if err != nil { + log.Fatalf("could not start reporter, err: %v", err) + } + err = r.Report(l) + if err != nil { + log.Fatalf("could not send initial report of ipmi addresses, err: %v", err) + } + + periodic := time.NewTicker(cfg.ReportInterval) + dhcpEvents, err := snoopDhcpEvents() + if err != nil { + log.Fatalf("could not initialize dhcp snooper: %v", err) + } + debounced := time.NewTimer(cfg.DebounceInterval) + debounced.Stop() + signals := make(chan os.Signal, 1) + signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) + +outer: + for { + select { + case <-periodic.C: + debounced.Reset(cfg.DebounceInterval) + case <-dhcpEvents: + debounced.Reset(cfg.DebounceInterval) + case <-debounced.C: + l, err := leases.ReadLeases(cfg.LeaseFile) + if err != nil { + log.Fatalf("could not parse leases file, err: %v", err) + } + err = r.Report(l) + if err != nil { + log.Warnf("could not report ipmi addresses, err: %v", err) + } + case <-signals: + break outer + } + } +} + +func snoopDhcpEvents() (chan dhcp4.Packet, error) { + c := make(chan dhcp4.Packet, 10) + dhcp, err := dhcp4.NewSnooperConn("0.0.0.0:67") + if err != nil { + return nil, err + } + go func() { + for { + p, _, err := dhcp.RecvDHCP() + if err == nil { + c <- *p + } + } + }() + return c, nil +} diff --git a/metal-api.json b/metal-api.json new file mode 100644 index 0000000..8979a05 --- /dev/null +++ b/metal-api.json @@ -0,0 +1,5555 @@ +{ + "basePath": "/", + "definitions": { + "httperrors.HTTPErrorResponse": { + "properties": { + "message": { + "description": "error message", + "type": "string" + }, + "statuscode": { + "description": "http status code", + "format": "int32", + "type": "integer" + } + }, + "required": [ + "message", + "statuscode" + ] + }, + "rest.status": { + "properties": { + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "message", + "status" + ] + }, + "rest.version": { + "properties": { + "builddate": { + "type": "string" + }, + "gitsha1": { + "type": "string" + }, + "name": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "builddate", + "gitsha1", + "name", + "revision", + "version" + ] + }, + "timestamp.Timestamp": { + "properties": { + "nanos": { + "format": "int32", + "type": "integer" + }, + "seconds": { + "format": "int64", + "type": "integer" + } + } + }, + "v1.BGPFilter": { + "properties": { + "cidrs": { + "description": "the cidr addresses that are allowed to be announced at this switch port", + "items": { + "type": "string" + }, + "type": "array" + }, + "vnis": { + "description": "the virtual networks that are exposed at this switch port", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "cidrs" + ] + }, + "v1.ChassisIdentifyLEDState": { + "properties": { + "description": { + "description": "a description why this chassis identify LED is in the given state", + "type": "string" + }, + "value": { + "description": "the state of this chassis identify LED. empty means LED-OFF", + "type": "string" + } + }, + "required": [ + "description", + "value" + ] + }, + "v1.EmptyBody": {}, + "v1.FirewallCreateRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "ha": { + "description": "if set to true, this firewall is set up in a High Available manner", + "type": "boolean" + }, + "hostname": { + "description": "the hostname for the allocated machine (defaults to metal)", + "type": "string" + }, + "imageid": { + "description": "the image id to assign this machine to", + "type": "string" + }, + "ips": { + "description": "the ips to attach to this machine additionally", + "items": { + "type": "string" + }, + "type": "array" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "networks": { + "description": "the networks that this machine will be placed in.", + "items": { + "$ref": "#/definitions/v1.MachineAllocationNetwork" + }, + "type": "array" + }, + "partitionid": { + "description": "the partition id to assign this machine to", + "type": "string" + }, + "projectid": { + "description": "the project id to assign this machine to", + "type": "string" + }, + "sizeid": { + "description": "the size id to assign this machine to", + "type": "string" + }, + "ssh_pub_keys": { + "description": "the public ssh keys to access the machine with", + "items": { + "type": "string" + }, + "type": "array" + }, + "tags": { + "description": "tags for this machine", + "items": { + "type": "string" + }, + "type": "array" + }, + "user_data": { + "description": "cloud-init.io compatible userdata must be base64 encoded", + "type": "string" + }, + "uuid": { + "description": "if this field is set, this specific machine will be allocated if it is not in available state and not currently allocated. this field overrules size and partition", + "type": "string" + } + }, + "required": [ + "imageid", + "partitionid", + "projectid", + "sizeid", + "ssh_pub_keys" + ] + }, + "v1.FirewallFindRequest": { + "properties": { + "allocation_hostname": { + "type": "string" + }, + "allocation_image_id": { + "type": "string" + }, + "allocation_name": { + "type": "string" + }, + "allocation_project": { + "type": "string" + }, + "allocation_succeeded": { + "type": "boolean" + }, + "disk_names": { + "items": { + "type": "string" + }, + "type": "array" + }, + "disk_sizes": { + "items": { + "type": "integer" + }, + "type": "array" + }, + "fru_board_mfg": { + "type": "string" + }, + "fru_board_mfg_serial": { + "type": "string" + }, + "fru_board_part_number": { + "type": "string" + }, + "fru_chassis_part_number": { + "type": "string" + }, + "fru_chassis_part_serial": { + "type": "string" + }, + "fru_product_manufacturer": { + "type": "string" + }, + "fru_product_part_number": { + "type": "string" + }, + "fru_product_serial": { + "type": "string" + }, + "hardware_cpu_cores": { + "format": "int64", + "type": "integer" + }, + "hardware_memory": { + "format": "int64", + "type": "integer" + }, + "id": { + "type": "string" + }, + "ipmi_address": { + "type": "string" + }, + "ipmi_interface": { + "type": "string" + }, + "ipmi_mac_address": { + "type": "string" + }, + "ipmi_user": { + "type": "string" + }, + "liveliness": { + "type": "string" + }, + "name": { + "type": "string" + }, + "network_asns": { + "items": { + "type": "integer" + }, + "type": "array" + }, + "network_destination_prefixes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "network_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "network_ips": { + "items": { + "type": "string" + }, + "type": "array" + }, + "network_nat": { + "type": "boolean" + }, + "network_prefixes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "network_private": { + "type": "boolean" + }, + "network_underlay": { + "type": "boolean" + }, + "network_vrfs": { + "items": { + "type": "integer" + }, + "type": "array" + }, + "nics_mac_addresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_names": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_neighbor_mac_addresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_neighbor_names": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_neighbor_vrfs": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_vrfs": { + "items": { + "type": "string" + }, + "type": "array" + }, + "partition_id": { + "type": "string" + }, + "rackid": { + "type": "string" + }, + "sizeid": { + "type": "string" + }, + "state_value": { + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "allocation_hostname", + "allocation_image_id", + "allocation_name", + "allocation_project", + "allocation_succeeded", + "disk_names", + "disk_sizes", + "fru_board_mfg", + "fru_board_mfg_serial", + "fru_board_part_number", + "fru_chassis_part_number", + "fru_chassis_part_serial", + "fru_product_manufacturer", + "fru_product_part_number", + "fru_product_serial", + "hardware_cpu_cores", + "hardware_memory", + "id", + "ipmi_address", + "ipmi_interface", + "ipmi_mac_address", + "ipmi_user", + "liveliness", + "name", + "network_asns", + "network_destination_prefixes", + "network_ids", + "network_ips", + "network_nat", + "network_prefixes", + "network_private", + "network_underlay", + "network_vrfs", + "nics_mac_addresses", + "nics_names", + "nics_neighbor_mac_addresses", + "nics_neighbor_names", + "nics_neighbor_vrfs", + "nics_vrfs", + "partition_id", + "rackid", + "sizeid", + "state_value", + "tags" + ] + }, + "v1.FirewallResponse": { + "properties": { + "allocation": { + "$ref": "#/definitions/v1.MachineAllocation", + "description": "the allocation data of an allocated machine" + }, + "bios": { + "$ref": "#/definitions/v1.MachineBIOS", + "description": "bios information of this machine" + }, + "changed": { + "description": "the last changed timestamp of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "created": { + "description": "the creation time of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "events": { + "$ref": "#/definitions/v1.MachineRecentProvisioningEvents", + "description": "recent events of this machine during provisioning" + }, + "hardware": { + "$ref": "#/definitions/v1.MachineHardware", + "description": "the hardware of this machine" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "ledstate": { + "$ref": "#/definitions/v1.ChassisIdentifyLEDState", + "description": "the state of this chassis identify LED" + }, + "liveliness": { + "description": "the liveliness of this machine", + "type": "string" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "partition": { + "$ref": "#/definitions/v1.PartitionResponse", + "description": "the partition assigned to this machine", + "readOnly": true + }, + "rackid": { + "description": "the rack assigned to this machine", + "readOnly": true, + "type": "string" + }, + "size": { + "$ref": "#/definitions/v1.SizeResponse", + "description": "the size of this machine", + "readOnly": true + }, + "state": { + "$ref": "#/definitions/v1.MachineState", + "description": "the state of this machine" + }, + "tags": { + "description": "tags for this machine", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "allocation", + "bios", + "changed", + "created", + "events", + "hardware", + "id", + "ledstate", + "liveliness", + "partition", + "rackid", + "size", + "state", + "tags" + ] + }, + "v1.IPAllocateRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "machineid": { + "description": "the machine id this ip should be associated with", + "type": "string" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "networkid": { + "description": "the network this ip allocate request address belongs to", + "type": "string" + }, + "projectid": { + "description": "the project this ip address belongs to", + "type": "string" + }, + "tags": { + "description": "free tags that you associate with this ip.", + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "default": "static", + "description": "the ip type, ephemeral leads to automatic cleanup of the ip address, static will enable re-use of the ip at a later point in time", + "enum": [ + "ephemeral", + "static" + ], + "type": "string" + } + }, + "required": [ + "machineid", + "networkid", + "projectid", + "tags", + "type" + ] + }, + "v1.IPFindRequest": { + "properties": { + "ipaddress": { + "description": "the address (ipv4 or ipv6) of this ip", + "type": "string" + }, + "machineid": { + "description": "the machine an ip address is associated to", + "type": "string" + }, + "networkid": { + "description": "the network this ip allocate request address belongs to", + "type": "string" + }, + "networkprefix": { + "description": "the prefix of the network this ip address belongs to", + "type": "string" + }, + "projectid": { + "description": "the project this ip address belongs to, empty if not strong coupled", + "type": "string" + }, + "tags": { + "description": "the tags that are assigned to this ip address", + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "description": "the type of the ip address, ephemeral or static", + "type": "string" + } + }, + "required": [ + "ipaddress", + "machineid", + "networkid", + "networkprefix", + "projectid", + "tags", + "type" + ] + }, + "v1.IPResponse": { + "properties": { + "changed": { + "description": "the last changed timestamp of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "created": { + "description": "the creation time of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "ipaddress": { + "description": "the address (ipv4 or ipv6) of this ip", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "networkid": { + "description": "the network this ip allocate request address belongs to", + "type": "string" + }, + "projectid": { + "description": "the project this ip address belongs to", + "type": "string" + }, + "tags": { + "description": "free tags that you associate with this ip.", + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "default": "static", + "description": "the ip type, ephemeral leads to automatic cleanup of the ip address, static will enable re-use of the ip at a later point in time", + "enum": [ + "ephemeral", + "static" + ], + "type": "string" + } + }, + "required": [ + "changed", + "created", + "ipaddress", + "networkid", + "projectid", + "tags", + "type" + ] + }, + "v1.IPUpdateRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "ipaddress": { + "description": "the address (ipv4 or ipv6) of this ip", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "tags": { + "description": "free tags that you associate with this ip.", + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "description": "the ip type, ephemeral leads to automatic cleanup of the ip address, static will enable re-use of the ip at a later point in time", + "enum": [ + "ephemeral", + "static" + ], + "type": "string" + } + }, + "required": [ + "ipaddress", + "tags", + "type" + ] + }, + "v1.ImageCreateRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "features": { + "description": "features of this image", + "items": { + "type": "string" + }, + "type": "array" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "url": { + "description": "the url of this image", + "type": "string" + } + }, + "required": [ + "id", + "url" + ] + }, + "v1.ImageResponse": { + "properties": { + "changed": { + "description": "the last changed timestamp of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "created": { + "description": "the creation time of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "features": { + "description": "features of this image", + "items": { + "type": "string" + }, + "type": "array" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "url": { + "description": "the url of this image", + "type": "string" + } + }, + "required": [ + "changed", + "created", + "id" + ] + }, + "v1.ImageUpdateRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "features": { + "description": "features of this image", + "items": { + "type": "string" + }, + "type": "array" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "url": { + "description": "the url of this image", + "type": "string" + } + }, + "required": [ + "id" + ] + }, + "v1.MachineAllocateRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "hostname": { + "description": "the hostname for the allocated machine (defaults to metal)", + "type": "string" + }, + "imageid": { + "description": "the image id to assign this machine to", + "type": "string" + }, + "ips": { + "description": "the ips to attach to this machine additionally", + "items": { + "type": "string" + }, + "type": "array" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "networks": { + "description": "the networks that this machine will be placed in.", + "items": { + "$ref": "#/definitions/v1.MachineAllocationNetwork" + }, + "type": "array" + }, + "partitionid": { + "description": "the partition id to assign this machine to", + "type": "string" + }, + "projectid": { + "description": "the project id to assign this machine to", + "type": "string" + }, + "sizeid": { + "description": "the size id to assign this machine to", + "type": "string" + }, + "ssh_pub_keys": { + "description": "the public ssh keys to access the machine with", + "items": { + "type": "string" + }, + "type": "array" + }, + "tags": { + "description": "tags for this machine", + "items": { + "type": "string" + }, + "type": "array" + }, + "user_data": { + "description": "cloud-init.io compatible userdata must be base64 encoded", + "type": "string" + }, + "uuid": { + "description": "if this field is set, this specific machine will be allocated if it is not in available state and not currently allocated. this field overrules size and partition", + "type": "string" + } + }, + "required": [ + "imageid", + "partitionid", + "projectid", + "sizeid", + "ssh_pub_keys" + ] + }, + "v1.MachineAllocation": { + "properties": { + "console_password": { + "description": "the console password which was generated while provisioning", + "type": "string" + }, + "created": { + "description": "the time when the machine was created", + "format": "date-time", + "type": "string" + }, + "description": { + "description": "a description for this machine", + "type": "string" + }, + "hostname": { + "description": "the hostname which will be used when creating the machine", + "type": "string" + }, + "image": { + "$ref": "#/definitions/v1.ImageResponse", + "description": "the image assigned to this machine", + "readOnly": true + }, + "name": { + "description": "the name of the machine", + "type": "string" + }, + "networks": { + "description": "the networks of this machine", + "items": { + "$ref": "#/definitions/v1.MachineNetwork" + }, + "type": "array" + }, + "project": { + "description": "the project id that this machine is assigned to", + "type": "string" + }, + "ssh_pub_keys": { + "description": "the public ssh keys to access the machine with", + "items": { + "type": "string" + }, + "type": "array" + }, + "succeeded": { + "description": "if the allocation of the machine was successful, this is set to true", + "type": "boolean" + }, + "user_data": { + "description": "userdata to execute post installation tasks", + "type": "string" + } + }, + "required": [ + "created", + "hostname", + "name", + "networks", + "project", + "ssh_pub_keys", + "succeeded" + ] + }, + "v1.MachineAllocationNetwork": { + "properties": { + "autoacquire": { + "description": "will automatically acquire an ip in this network if set to true, default is true", + "type": "boolean" + }, + "networkid": { + "description": "the id of the network that this machine will be placed in", + "type": "string" + } + }, + "required": [ + "autoacquire", + "networkid" + ] + }, + "v1.MachineBIOS": { + "description": "The bios version", + "properties": { + "date": { + "description": "the bios date", + "type": "string" + }, + "vendor": { + "description": "the bios vendor", + "type": "string" + }, + "version": { + "description": "the bios version", + "type": "string" + } + }, + "required": [ + "date", + "vendor", + "version" + ] + }, + "v1.MachineBlockDevice": { + "properties": { + "name": { + "description": "the name of this block device", + "type": "string" + }, + "size": { + "description": "the size of this block device", + "type": "integer" + } + }, + "required": [ + "name", + "size" + ] + }, + "v1.MachineFinalizeAllocationRequest": { + "properties": { + "console_password": { + "description": "the console password which was generated while provisioning", + "type": "string" + } + }, + "required": [ + "console_password" + ] + }, + "v1.MachineFindRequest": { + "properties": { + "allocation_hostname": { + "type": "string" + }, + "allocation_image_id": { + "type": "string" + }, + "allocation_name": { + "type": "string" + }, + "allocation_project": { + "type": "string" + }, + "allocation_succeeded": { + "type": "boolean" + }, + "disk_names": { + "items": { + "type": "string" + }, + "type": "array" + }, + "disk_sizes": { + "items": { + "type": "integer" + }, + "type": "array" + }, + "fru_board_mfg": { + "type": "string" + }, + "fru_board_mfg_serial": { + "type": "string" + }, + "fru_board_part_number": { + "type": "string" + }, + "fru_chassis_part_number": { + "type": "string" + }, + "fru_chassis_part_serial": { + "type": "string" + }, + "fru_product_manufacturer": { + "type": "string" + }, + "fru_product_part_number": { + "type": "string" + }, + "fru_product_serial": { + "type": "string" + }, + "hardware_cpu_cores": { + "format": "int64", + "type": "integer" + }, + "hardware_memory": { + "format": "int64", + "type": "integer" + }, + "id": { + "type": "string" + }, + "ipmi_address": { + "type": "string" + }, + "ipmi_interface": { + "type": "string" + }, + "ipmi_mac_address": { + "type": "string" + }, + "ipmi_user": { + "type": "string" + }, + "liveliness": { + "type": "string" + }, + "name": { + "type": "string" + }, + "network_asns": { + "items": { + "type": "integer" + }, + "type": "array" + }, + "network_destination_prefixes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "network_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "network_ips": { + "items": { + "type": "string" + }, + "type": "array" + }, + "network_nat": { + "type": "boolean" + }, + "network_prefixes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "network_private": { + "type": "boolean" + }, + "network_underlay": { + "type": "boolean" + }, + "network_vrfs": { + "items": { + "type": "integer" + }, + "type": "array" + }, + "nics_mac_addresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_names": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_neighbor_mac_addresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_neighbor_names": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_neighbor_vrfs": { + "items": { + "type": "string" + }, + "type": "array" + }, + "nics_vrfs": { + "items": { + "type": "string" + }, + "type": "array" + }, + "partition_id": { + "type": "string" + }, + "rackid": { + "type": "string" + }, + "sizeid": { + "type": "string" + }, + "state_value": { + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "allocation_hostname", + "allocation_image_id", + "allocation_name", + "allocation_project", + "allocation_succeeded", + "disk_names", + "disk_sizes", + "fru_board_mfg", + "fru_board_mfg_serial", + "fru_board_part_number", + "fru_chassis_part_number", + "fru_chassis_part_serial", + "fru_product_manufacturer", + "fru_product_part_number", + "fru_product_serial", + "hardware_cpu_cores", + "hardware_memory", + "id", + "ipmi_address", + "ipmi_interface", + "ipmi_mac_address", + "ipmi_user", + "liveliness", + "name", + "network_asns", + "network_destination_prefixes", + "network_ids", + "network_ips", + "network_nat", + "network_prefixes", + "network_private", + "network_underlay", + "network_vrfs", + "nics_mac_addresses", + "nics_names", + "nics_neighbor_mac_addresses", + "nics_neighbor_names", + "nics_neighbor_vrfs", + "nics_vrfs", + "partition_id", + "rackid", + "sizeid", + "state_value", + "tags" + ] + }, + "v1.MachineFru": { + "description": "The Field Replaceable Unit data", + "properties": { + "board_mfg": { + "description": "the board mfg", + "type": "string" + }, + "board_mfg_serial": { + "description": "the board mfg serial", + "type": "string" + }, + "board_part_number": { + "description": "the board part number", + "type": "string" + }, + "chassis_part_number": { + "description": "the chassis part number", + "type": "string" + }, + "chassis_part_serial": { + "description": "the chassis part serial", + "type": "string" + }, + "product_manufacturer": { + "description": "the product manufacturer", + "type": "string" + }, + "product_part_number": { + "description": "the product part number", + "type": "string" + }, + "product_serial": { + "description": "the product serial", + "type": "string" + } + } + }, + "v1.MachineHardware": { + "properties": { + "cpu_cores": { + "description": "the number of cpu cores", + "format": "int32", + "type": "integer" + }, + "disks": { + "description": "the list of block devices of this machine", + "items": { + "$ref": "#/definitions/v1.MachineBlockDevice" + }, + "type": "array" + }, + "memory": { + "description": "the total memory of the machine", + "type": "integer" + }, + "nics": { + "description": "the list of network interfaces of this machine", + "items": { + "$ref": "#/definitions/v1.MachineNic" + }, + "type": "array" + } + }, + "required": [ + "cpu_cores", + "disks", + "memory", + "nics" + ] + }, + "v1.MachineHardwareExtended": { + "properties": { + "cpu_cores": { + "description": "the number of cpu cores", + "format": "int32", + "type": "integer" + }, + "disks": { + "description": "the list of block devices of this machine", + "items": { + "$ref": "#/definitions/v1.MachineBlockDevice" + }, + "type": "array" + }, + "memory": { + "description": "the total memory of the machine", + "type": "integer" + }, + "nics": { + "description": "the list of network interfaces of this machine with extended information", + "items": { + "$ref": "#/definitions/v1.MachineNicExtended" + }, + "type": "array" + } + }, + "required": [ + "cpu_cores", + "disks", + "memory", + "nics" + ] + }, + "v1.MachineIPMI": { + "description": "The IPMI connection data", + "properties": { + "address": { + "type": "string" + }, + "bmcversion": { + "type": "string" + }, + "fru": { + "$ref": "#/definitions/v1.MachineFru" + }, + "interface": { + "type": "string" + }, + "mac": { + "type": "string" + }, + "password": { + "type": "string" + }, + "user": { + "type": "string" + } + }, + "required": [ + "address", + "bmcversion", + "fru", + "interface", + "mac", + "password", + "user" + ] + }, + "v1.MachineIPMIResponse": { + "properties": { + "allocation": { + "$ref": "#/definitions/v1.MachineAllocation", + "description": "the allocation data of an allocated machine" + }, + "bios": { + "$ref": "#/definitions/v1.MachineBIOS", + "description": "bios information of this machine" + }, + "changed": { + "description": "the last changed timestamp of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "created": { + "description": "the creation time of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "events": { + "$ref": "#/definitions/v1.MachineRecentProvisioningEvents", + "description": "recent events of this machine during provisioning" + }, + "hardware": { + "$ref": "#/definitions/v1.MachineHardware", + "description": "the hardware of this machine" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "ipmi": { + "$ref": "#/definitions/v1.MachineIPMI", + "description": "ipmi information of this machine" + }, + "ledstate": { + "$ref": "#/definitions/v1.ChassisIdentifyLEDState", + "description": "the state of this chassis identify LED" + }, + "liveliness": { + "description": "the liveliness of this machine", + "type": "string" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "partition": { + "$ref": "#/definitions/v1.PartitionResponse", + "description": "the partition assigned to this machine", + "readOnly": true + }, + "rackid": { + "description": "the rack assigned to this machine", + "readOnly": true, + "type": "string" + }, + "size": { + "$ref": "#/definitions/v1.SizeResponse", + "description": "the size of this machine", + "readOnly": true + }, + "state": { + "$ref": "#/definitions/v1.MachineState", + "description": "the state of this machine" + }, + "tags": { + "description": "tags for this machine", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "allocation", + "bios", + "changed", + "created", + "events", + "hardware", + "id", + "ipmi", + "ledstate", + "liveliness", + "partition", + "rackid", + "size", + "state", + "tags" + ] + }, + "v1.MachineIpmiReport": { + "properties": { + "leases": { + "additionalProperties": { + "type": "string" + }, + "description": "the active leases to be reported by a management server", + "type": "object" + }, + "partitionid": { + "description": "the partition id for the ipmi report", + "type": "string" + } + }, + "required": [ + "leases", + "partitionid" + ] + }, + "v1.MachineIpmiReportResponse": { + "properties": { + "created": { + "additionalProperties": { + "type": "string" + }, + "description": "the leases that triggered a creation of a machine entity", + "type": "object" + }, + "updated": { + "additionalProperties": { + "type": "string" + }, + "description": "the leases that triggered an update of ipmi data", + "type": "object" + } + }, + "required": [ + "created", + "updated" + ] + }, + "v1.MachineLivelinessReport": { + "properties": { + "alive_count": { + "description": "the number of machines alive", + "format": "int32", + "type": "integer" + }, + "dead_count": { + "description": "the number of dead machines", + "format": "int32", + "type": "integer" + }, + "unknown_count": { + "description": "the number of machines with unknown liveliness", + "format": "int32", + "type": "integer" + } + }, + "required": [ + "alive_count", + "dead_count", + "unknown_count" + ] + }, + "v1.MachineNetwork": { + "description": "prefixes that are reachable within this network", + "properties": { + "asn": { + "description": "ASN number for this network in the bgp configuration", + "format": "int64", + "type": "integer" + }, + "destinationprefixes": { + "description": "the destination prefixes of this network", + "items": { + "type": "string" + }, + "type": "array" + }, + "ips": { + "description": "the ip addresses of the allocated machine in this vrf", + "items": { + "type": "string" + }, + "type": "array" + }, + "nat": { + "description": "if set to true, packets leaving this network get masqueraded behind interface ip", + "type": "boolean" + }, + "networkid": { + "description": "the networkID of the allocated machine in this vrf", + "type": "string" + }, + "prefixes": { + "description": "the prefixes of this network", + "items": { + "type": "string" + }, + "type": "array" + }, + "private": { + "description": "indicates whether this network is the private network of this machine", + "type": "boolean" + }, + "underlay": { + "description": "if set to true, this network can be used for underlay communication", + "type": "boolean" + }, + "vrf": { + "description": "the vrf of the allocated machine", + "format": "integer", + "type": "integer" + } + }, + "required": [ + "asn", + "destinationprefixes", + "ips", + "nat", + "networkid", + "prefixes", + "private", + "underlay", + "vrf" + ] + }, + "v1.MachineNic": { + "properties": { + "mac": { + "description": "the mac address of this network interface", + "type": "string" + }, + "name": { + "description": "the name of this network interface", + "type": "string" + } + }, + "required": [ + "mac", + "name" + ] + }, + "v1.MachineNicExtended": { + "properties": { + "mac": { + "description": "the mac address of this network interface", + "type": "string" + }, + "name": { + "description": "the name of this network interface", + "type": "string" + }, + "neighbors": { + "description": "the neighbors visible to this network interface", + "items": { + "$ref": "#/definitions/v1.MachineNicExtended" + }, + "type": "array" + } + }, + "required": [ + "mac", + "name", + "neighbors" + ] + }, + "v1.MachineProvisioningEvent": { + "properties": { + "event": { + "description": "the event emitted by the machine", + "type": "string" + }, + "message": { + "description": "an additional message to add to the event", + "type": "string" + }, + "time": { + "description": "the time that this event was received", + "format": "date-time", + "readOnly": true, + "type": "string" + } + }, + "required": [ + "event" + ] + }, + "v1.MachineRecentProvisioningEvents": { + "properties": { + "incomplete_provisioning_cycles": { + "description": "the amount of incomplete provisioning cycles in the event container", + "type": "string" + }, + "last_event_time": { + "description": "the time where the last event was received", + "format": "date-time", + "type": "string" + }, + "log": { + "description": "the log of recent machine provisioning events", + "items": { + "$ref": "#/definitions/v1.MachineProvisioningEvent" + }, + "type": "array" + } + }, + "required": [ + "incomplete_provisioning_cycles", + "last_event_time", + "log" + ] + }, + "v1.MachineRegisterRequest": { + "properties": { + "bios": { + "$ref": "#/definitions/v1.MachineBIOS", + "description": "bios information of this machine" + }, + "hardware": { + "$ref": "#/definitions/v1.MachineHardwareExtended", + "description": "the hardware of this machine" + }, + "ipmi": { + "$ref": "#/definitions/v1.MachineIPMI", + "description": "the ipmi access infos" + }, + "partitionid": { + "description": "the partition id to register this machine with", + "type": "string" + }, + "rackid": { + "description": "the rack id where this machine is connected to", + "type": "string" + }, + "tags": { + "description": "tags for this machine", + "items": { + "type": "string" + }, + "type": "array" + }, + "uuid": { + "description": "the product uuid of the machine to register", + "type": "string" + } + }, + "required": [ + "bios", + "hardware", + "ipmi", + "partitionid", + "rackid", + "tags", + "uuid" + ] + }, + "v1.MachineResponse": { + "properties": { + "allocation": { + "$ref": "#/definitions/v1.MachineAllocation", + "description": "the allocation data of an allocated machine" + }, + "bios": { + "$ref": "#/definitions/v1.MachineBIOS", + "description": "bios information of this machine" + }, + "changed": { + "description": "the last changed timestamp of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "created": { + "description": "the creation time of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "events": { + "$ref": "#/definitions/v1.MachineRecentProvisioningEvents", + "description": "recent events of this machine during provisioning" + }, + "hardware": { + "$ref": "#/definitions/v1.MachineHardware", + "description": "the hardware of this machine" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "ledstate": { + "$ref": "#/definitions/v1.ChassisIdentifyLEDState", + "description": "the state of this chassis identify LED" + }, + "liveliness": { + "description": "the liveliness of this machine", + "type": "string" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "partition": { + "$ref": "#/definitions/v1.PartitionResponse", + "description": "the partition assigned to this machine", + "readOnly": true + }, + "rackid": { + "description": "the rack assigned to this machine", + "readOnly": true, + "type": "string" + }, + "size": { + "$ref": "#/definitions/v1.SizeResponse", + "description": "the size of this machine", + "readOnly": true + }, + "state": { + "$ref": "#/definitions/v1.MachineState", + "description": "the state of this machine" + }, + "tags": { + "description": "tags for this machine", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "allocation", + "bios", + "changed", + "created", + "events", + "hardware", + "id", + "ledstate", + "liveliness", + "partition", + "rackid", + "size", + "state", + "tags" + ] + }, + "v1.MachineState": { + "properties": { + "description": { + "description": "a description why this machine is in the given state", + "type": "string" + }, + "value": { + "description": "the state of this machine. empty means available for all", + "type": "string" + } + }, + "required": [ + "description", + "value" + ] + }, + "v1.Meta": { + "properties": { + "apiversion": { + "type": "string" + }, + "created_time": { + "$ref": "#/definitions/timestamp.Timestamp" + }, + "id": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "updated_time": { + "$ref": "#/definitions/timestamp.Timestamp" + }, + "version": { + "format": "int64", + "type": "integer" + } + } + }, + "v1.NetworkAllocateRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "free labels that you associate with this network.", + "type": "object" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "partitionid": { + "description": "the partition this network belongs to", + "type": "string" + }, + "projectid": { + "description": "the project id this network belongs to, can be empty if globally available", + "type": "string" + } + }, + "required": [ + "labels" + ] + }, + "v1.NetworkCreateRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "destinationprefixes": { + "description": "the destination prefixes of this network", + "items": { + "type": "string" + }, + "type": "array" + }, + "id": { + "description": "the unique ID of this entity, auto-generated if left empty", + "type": "string", + "uniqueItems": true + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "free labels that you associate with this network.", + "type": "object" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "nat": { + "description": "if set to true, packets leaving this network get masqueraded behind interface ip", + "type": "boolean" + }, + "parentnetworkid": { + "description": "the id of the parent network", + "type": "string" + }, + "partitionid": { + "description": "the partition this network belongs to", + "type": "string" + }, + "prefixes": { + "description": "the prefixes of this network", + "items": { + "type": "string" + }, + "type": "array" + }, + "privatesuper": { + "description": "if set to true, this network will serve as a partition's super network for the internal machine networks,there can only be one privatesuper network per partition", + "type": "boolean" + }, + "projectid": { + "description": "the project id this network belongs to, can be empty if globally available", + "type": "string" + }, + "underlay": { + "description": "if set to true, this network can be used for underlay communication", + "type": "boolean" + }, + "vrf": { + "description": "the vrf this network is associated with", + "format": "integer", + "type": "integer" + }, + "vrfshared": { + "description": "if set to true, given vrf can be used by multiple networks, which is sometimes useful for network partioning (default: false)", + "type": "boolean" + } + }, + "required": [ + "destinationprefixes", + "id", + "labels", + "nat", + "parentnetworkid", + "prefixes", + "privatesuper", + "underlay" + ] + }, + "v1.NetworkFindRequest": { + "properties": { + "destinationprefixes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "id": { + "type": "string" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "name": { + "type": "string" + }, + "nat": { + "type": "boolean" + }, + "parentnetworkid": { + "type": "string" + }, + "partitionid": { + "type": "string" + }, + "prefixes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "privatesuper": { + "type": "boolean" + }, + "projectid": { + "type": "string" + }, + "underlay": { + "type": "boolean" + }, + "vrf": { + "format": "int64", + "type": "integer" + } + }, + "required": [ + "destinationprefixes", + "id", + "labels", + "name", + "nat", + "parentnetworkid", + "partitionid", + "prefixes", + "privatesuper", + "projectid", + "underlay", + "vrf" + ] + }, + "v1.NetworkResponse": { + "properties": { + "changed": { + "description": "the last changed timestamp of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "created": { + "description": "the creation time of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "destinationprefixes": { + "description": "the destination prefixes of this network", + "items": { + "type": "string" + }, + "type": "array" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "free labels that you associate with this network.", + "type": "object" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "nat": { + "description": "if set to true, packets leaving this network get masqueraded behind interface ip", + "type": "boolean" + }, + "parentnetworkid": { + "description": "the id of the parent network", + "type": "string" + }, + "partitionid": { + "description": "the partition this network belongs to", + "type": "string" + }, + "prefixes": { + "description": "the prefixes of this network", + "items": { + "type": "string" + }, + "type": "array" + }, + "privatesuper": { + "description": "if set to true, this network will serve as a partition's super network for the internal machine networks,there can only be one privatesuper network per partition", + "type": "boolean" + }, + "projectid": { + "description": "the project id this network belongs to, can be empty if globally available", + "type": "string" + }, + "underlay": { + "description": "if set to true, this network can be used for underlay communication", + "type": "boolean" + }, + "usage": { + "$ref": "#/definitions/v1.NetworkUsage", + "description": "usage of ips and prefixes in this network" + }, + "vrf": { + "description": "the vrf this network is associated with", + "format": "integer", + "type": "integer" + }, + "vrfshared": { + "description": "if set to true, given vrf can be used by multiple networks, which is sometimes useful for network partioning (default: false)", + "type": "boolean" + } + }, + "required": [ + "changed", + "created", + "destinationprefixes", + "id", + "labels", + "nat", + "parentnetworkid", + "prefixes", + "privatesuper", + "underlay", + "usage" + ] + }, + "v1.NetworkUpdateRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "prefixes": { + "description": "the prefixes of this network", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "id" + ] + }, + "v1.NetworkUsage": { + "properties": { + "available_ips": { + "description": "the total available IPs", + "type": "integer" + }, + "available_prefixes": { + "description": "the total available Prefixes", + "type": "integer" + }, + "used_ips": { + "description": "the total used IPs", + "type": "integer" + }, + "used_prefixes": { + "description": "the total used Prefixes", + "type": "integer" + } + }, + "required": [ + "available_ips", + "available_prefixes", + "used_ips", + "used_prefixes" + ] + }, + "v1.PartitionBootConfiguration": { + "description": "a partition has a distinct location in a data center, individual entities belong to a partition", + "properties": { + "commandline": { + "description": "the cmdline to the kernel for the boot image", + "type": "string" + }, + "imageurl": { + "description": "the url to download the initrd for the boot image", + "type": "string" + }, + "kernelurl": { + "description": "the url to download the kernel for the boot image", + "type": "string" + } + } + }, + "v1.PartitionCapacity": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "servers": { + "description": "servers available in this partition", + "items": { + "$ref": "#/definitions/v1.ServerCapacity" + }, + "type": "array" + } + }, + "required": [ + "id", + "servers" + ] + }, + "v1.PartitionCreateRequest": { + "properties": { + "bootconfig": { + "$ref": "#/definitions/v1.PartitionBootConfiguration", + "description": "the boot configuration of this partition" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "mgmtserviceaddress": { + "description": "the address to the management service of this partition", + "type": "string" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "privatenetworkprefixlength": { + "description": "the length of private networks for the machine's child networks in this partition, default 22", + "format": "int32", + "maximum": 30, + "minimum": 16, + "type": "integer" + } + }, + "required": [ + "bootconfig", + "id" + ] + }, + "v1.PartitionResponse": { + "properties": { + "bootconfig": { + "$ref": "#/definitions/v1.PartitionBootConfiguration", + "description": "the boot configuration of this partition" + }, + "changed": { + "description": "the last changed timestamp of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "created": { + "description": "the creation time of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "mgmtserviceaddress": { + "description": "the address to the management service of this partition", + "type": "string" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "privatenetworkprefixlength": { + "description": "the length of private networks for the machine's child networks in this partition, default 22", + "format": "int32", + "maximum": 30, + "minimum": 16, + "type": "integer" + } + }, + "required": [ + "bootconfig", + "changed", + "created", + "id" + ] + }, + "v1.PartitionUpdateRequest": { + "properties": { + "bootconfig": { + "$ref": "#/definitions/v1.PartitionBootConfiguration", + "description": "the boot configuration of this partition" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "mgmtserviceaddress": { + "description": "the address to the management service of this partition", + "type": "string" + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + } + }, + "required": [ + "id" + ] + }, + "v1.ProjectFindRequest": { + "properties": { + "description": { + "$ref": "#/definitions/wrappers.StringValue" + }, + "id": { + "$ref": "#/definitions/wrappers.StringValue" + }, + "name": { + "$ref": "#/definitions/wrappers.StringValue" + }, + "tenant_id": { + "$ref": "#/definitions/wrappers.StringValue" + } + } + }, + "v1.ProjectResponse": { + "properties": { + "description": { + "type": "string" + }, + "meta": { + "$ref": "#/definitions/v1.Meta" + }, + "name": { + "type": "string" + }, + "quotas": { + "$ref": "#/definitions/v1.QuotaSet" + }, + "tenant_id": { + "type": "string" + } + } + }, + "v1.Quota": { + "properties": { + "quota": { + "$ref": "#/definitions/wrappers.Int32Value" + } + } + }, + "v1.QuotaSet": { + "properties": { + "cluster": { + "$ref": "#/definitions/v1.Quota" + }, + "ip": { + "$ref": "#/definitions/v1.Quota" + }, + "machine": { + "$ref": "#/definitions/v1.Quota" + } + } + }, + "v1.ServerCapacity": { + "properties": { + "allocated": { + "description": "allocated servers with this size", + "format": "int32", + "type": "integer" + }, + "faulty": { + "description": "servers with issues with this size", + "format": "int32", + "type": "integer" + }, + "free": { + "description": "free servers with this size", + "format": "int32", + "type": "integer" + }, + "size": { + "description": "the size of the server", + "type": "string" + }, + "total": { + "description": "total amount of servers with this size", + "format": "int32", + "type": "integer" + } + }, + "required": [ + "allocated", + "faulty", + "free", + "size", + "total" + ] + }, + "v1.SizeConstraint": { + "description": "a machine matches to a size in order to make them easier to categorize", + "properties": { + "max": { + "description": "the maximum value of the constraint", + "type": "integer" + }, + "min": { + "description": "the minimum value of the constraint", + "type": "integer" + }, + "type": { + "description": "the type of the constraint", + "enum": [ + "cores", + "memory", + "storage" + ], + "type": "string" + } + }, + "required": [ + "max", + "min", + "type" + ] + }, + "v1.SizeConstraintMatchingLog": { + "properties": { + "constraint": { + "$ref": "#/definitions/v1.SizeConstraint", + "description": "the size constraint to which this log relates to" + }, + "log": { + "description": "a string represention of the matching condition", + "type": "string" + }, + "match": { + "description": "indicates whether the constraint matched or not", + "type": "boolean" + } + }, + "required": [ + "constraint", + "log", + "match" + ] + }, + "v1.SizeCreateRequest": { + "properties": { + "constraints": { + "description": "a list of constraints that defines this size", + "items": { + "$ref": "#/definitions/v1.SizeConstraint" + }, + "type": "array" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + } + }, + "required": [ + "constraints", + "id" + ] + }, + "v1.SizeMatchingLog": { + "properties": { + "constraints": { + "items": { + "$ref": "#/definitions/v1.SizeConstraintMatchingLog" + }, + "type": "array" + }, + "log": { + "type": "string" + }, + "match": { + "type": "boolean" + }, + "name": { + "type": "string" + } + }, + "required": [ + "constraints", + "log", + "match", + "name" + ] + }, + "v1.SizeResponse": { + "properties": { + "changed": { + "description": "the last changed timestamp of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "constraints": { + "description": "a list of constraints that defines this size", + "items": { + "$ref": "#/definitions/v1.SizeConstraint" + }, + "type": "array" + }, + "created": { + "description": "the creation time of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + } + }, + "required": [ + "changed", + "constraints", + "created", + "id" + ] + }, + "v1.SizeUpdateRequest": { + "properties": { + "constraints": { + "description": "a list of constraints that defines this size", + "items": { + "$ref": "#/definitions/v1.SizeConstraint" + }, + "type": "array" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + } + }, + "required": [ + "id" + ] + }, + "v1.SwitchConnection": { + "properties": { + "machine_id": { + "description": "the machine id of the machine connected to the nic", + "type": "string" + }, + "nic": { + "$ref": "#/definitions/v1.SwitchNic", + "description": "a network interface on the switch" + } + }, + "required": [ + "nic" + ] + }, + "v1.SwitchNic": { + "properties": { + "filter": { + "$ref": "#/definitions/v1.BGPFilter", + "description": "configures the bgp filter applied at the switch port" + }, + "mac": { + "description": "the mac address of this network interface", + "type": "string" + }, + "name": { + "description": "the name of this network interface", + "type": "string" + }, + "vrf": { + "description": "the vrf this network interface is part of", + "type": "string" + } + }, + "required": [ + "mac", + "name" + ] + }, + "v1.SwitchRegisterRequest": { + "properties": { + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "nics": { + "description": "the list of network interfaces on the switch", + "items": { + "$ref": "#/definitions/v1.SwitchNic" + }, + "type": "array" + }, + "partition_id": { + "description": "the partition in which this switch is located", + "type": "string" + }, + "rack_id": { + "description": "the id of the rack in which this switch is located", + "type": "string" + } + }, + "required": [ + "id", + "nics", + "partition_id", + "rack_id" + ] + }, + "v1.SwitchResponse": { + "properties": { + "changed": { + "description": "the last changed timestamp of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "connections": { + "description": "a connection between a switch port and a machine", + "items": { + "$ref": "#/definitions/v1.SwitchConnection" + }, + "type": "array" + }, + "created": { + "description": "the creation time of this entity", + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "description": { + "description": "a description for this entity", + "type": "string" + }, + "id": { + "description": "the unique ID of this entity", + "type": "string", + "uniqueItems": true + }, + "name": { + "description": "a readable name for this entity", + "type": "string" + }, + "nics": { + "description": "the list of network interfaces on the switch", + "items": { + "$ref": "#/definitions/v1.SwitchNic" + }, + "type": "array" + }, + "partition": { + "$ref": "#/definitions/v1.PartitionResponse", + "description": "the partition in which this switch is located" + }, + "rack_id": { + "description": "the id of the rack in which this switch is located", + "type": "string" + } + }, + "required": [ + "changed", + "connections", + "created", + "id", + "nics", + "partition", + "rack_id" + ] + }, + "wrappers.Int32Value": { + "properties": { + "value": { + "format": "int32", + "type": "integer" + } + } + }, + "wrappers.StringValue": { + "properties": { + "value": { + "type": "string" + } + } + } + }, + "info": { + "contact": { + "email": "devops@f-i-ts.de", + "name": "Devops Team", + "url": "http://www.f-i-ts.de" + }, + "description": "Resource for managing pure metal", + "license": { + "name": "MIT", + "url": "http://mit.org" + }, + "title": "metal-api", + "version": "1.0.0" + }, + "paths": { + "/v1/firewall": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "listFirewalls", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.FirewallResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all known firewalls", + "tags": [ + "firewall" + ] + } + }, + "/v1/firewall/allocate": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "allocateFirewall", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.FirewallCreateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.FirewallResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "allocate a firewall", + "tags": [ + "firewall" + ] + } + }, + "/v1/firewall/find": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findFirewalls", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.FirewallFindRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.FirewallResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "find firewalls by multiple criteria", + "tags": [ + "firewall" + ] + } + }, + "/v1/firewall/{id}": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findFirewall", + "parameters": [ + { + "description": "identifier of the firewall", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.FirewallResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get firewall by id", + "tags": [ + "firewall" + ] + } + }, + "/v1/health": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "health", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/rest.status" + } + }, + "500": { + "description": "Unhealthy", + "schema": { + "$ref": "#/definitions/rest.status" + } + } + }, + "summary": "perform a healthcheck", + "tags": [ + "health" + ] + } + }, + "/v1/image": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "listImages", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.ImageResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all images", + "tags": [ + "image" + ] + }, + "post": { + "consumes": [ + "application/json" + ], + "operationId": "updateImage", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ImageUpdateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.ImageResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "updates an image. if the image was changed since this one was read, a conflict is returned", + "tags": [ + "image" + ] + }, + "put": { + "consumes": [ + "application/json" + ], + "operationId": "createImage", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ImageCreateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/v1.ImageResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "create an image. if the given ID already exists a conflict is returned", + "tags": [ + "image" + ] + } + }, + "/v1/image/{id}": { + "delete": { + "consumes": [ + "application/json" + ], + "operationId": "deleteImage", + "parameters": [ + { + "description": "identifier of the image", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.ImageResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "deletes an image and returns the deleted entity", + "tags": [ + "image" + ] + }, + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findImage", + "parameters": [ + { + "description": "identifier of the image", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.ImageResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get image by id", + "tags": [ + "image" + ] + } + }, + "/v1/ip": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "listIPs", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.IPResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all ips", + "tags": [ + "ip" + ] + }, + "post": { + "consumes": [ + "application/json" + ], + "operationId": "updateIP", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.IPUpdateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.IPResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "updates an ip. if the ip was changed since this one was read, a conflict is returned", + "tags": [ + "ip" + ] + } + }, + "/v1/ip/allocate": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "allocateIP", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.IPAllocateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/v1.IPResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "allocate an ip in the given network.", + "tags": [ + "ip" + ] + } + }, + "/v1/ip/allocate/{ip}": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "allocateSpecificIP", + "parameters": [ + { + "description": "ip to try to allocate", + "in": "path", + "name": "ip", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.IPAllocateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/v1.IPResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "allocate a specific ip in the given network.", + "tags": [ + "ip" + ] + } + }, + "/v1/ip/find": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "findIPs", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.IPFindRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.IPResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all ips that match given properties", + "tags": [ + "ip" + ] + } + }, + "/v1/ip/free/{id}": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "freeIP", + "parameters": [ + { + "description": "identifier of the ip", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.IPResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "frees an ip", + "tags": [ + "ip" + ] + } + }, + "/v1/ip/{id}": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findIP", + "parameters": [ + { + "description": "identifier of the ip", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.IPResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get ip by id", + "tags": [ + "ip" + ] + } + }, + "/v1/machine": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "listMachines", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.MachineResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all known machines", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/allocate": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "allocateMachine", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.MachineAllocateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "allocate a machine", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/find": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "findMachines", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.MachineFindRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.MachineResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "find machines by multiple criteria", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/ipmi": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "ipmiReport", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.MachineIpmiReport" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineIpmiReportResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "reports IPMI ip addresses leased by a management server for machines", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/ipmi/find": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "findIPMIMachines", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.MachineFindRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.MachineIPMIResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "returns machines including the ipmi connection data", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/liveliness": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "checkMachineLiveliness", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.EmptyBody" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineLivelinessReport" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "external trigger for evaluating machine liveliness", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/register": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "registerMachine", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.MachineRegisterRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "register a machine", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findMachine", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get machine by id", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/chassis-identify-led-state": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "setChassisIdentifyLEDState", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ChassisIdentifyLEDState" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "set the state of a chassis identify LED", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/event": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "getProvisioningEventContainer", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineRecentProvisioningEvents" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get the current machine provisioning event container", + "tags": [ + "machine" + ] + }, + "post": { + "consumes": [ + "application/json" + ], + "operationId": "addProvisioningEvent", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.MachineProvisioningEvent" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineRecentProvisioningEvents" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "adds a machine provisioning event", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/finalize-allocation": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "finalizeAllocation", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.MachineFinalizeAllocationRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "finalize the allocation of the machine by reconfiguring the switch, sent on successful image installation", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/free": { + "delete": { + "consumes": [ + "application/json" + ], + "operationId": "freeMachine", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "free a machine", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/ipmi": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findIPMIMachine", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineIPMIResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "returns a machine including the ipmi connection data", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/power/bios": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "machineBios", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.EmptyBody" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "boots machine into BIOS on next reboot", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/power/chassis-identify-led-off/{description}": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "chassisIdentifyLEDOff", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "reason why the chassis identify LED has been turned off", + "in": "path", + "name": "description", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.EmptyBody" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "sends a power-off to the chassis identify LED", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/power/chassis-identify-led-on": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "chassisIdentifyLEDOn", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.EmptyBody" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "sends a power-on to the chassis identify LED", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/power/chassis-identify-led-on/{description}": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "chassisIdentifyLEDOn", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "reason why the chassis identify LED has been turned on", + "in": "path", + "name": "description", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.EmptyBody" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "sends a power-on to the chassis identify LED", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/power/off": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "machineOff", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.EmptyBody" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "sends a power-off to the machine", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/power/on": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "machineOn", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.EmptyBody" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "sends a power-on to the machine", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/power/reset": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "machineReset", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.EmptyBody" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "sends a reset to the machine", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/state": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "setMachineState", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.MachineState" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "set the state of a machine", + "tags": [ + "machine" + ] + } + }, + "/v1/machine/{id}/wait": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "waitForAllocation", + "parameters": [ + { + "description": "identifier of the machine", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.MachineResponse" + } + }, + "504": { + "description": "Timeout", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "wait for an allocation of this machine", + "tags": [ + "machine" + ] + } + }, + "/v1/network": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "listNetworks", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.NetworkResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all networks", + "tags": [ + "network" + ] + }, + "post": { + "consumes": [ + "application/json" + ], + "operationId": "updateNetwork", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.NetworkUpdateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.NetworkResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "updates a network. if the network was changed since this one was read, a conflict is returned", + "tags": [ + "network" + ] + }, + "put": { + "consumes": [ + "application/json" + ], + "operationId": "createNetwork", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.NetworkCreateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/v1.NetworkResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "create a network. if the given ID already exists a conflict is returned", + "tags": [ + "network" + ] + } + }, + "/v1/network/allocate": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "allocateNetwork", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.NetworkAllocateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/v1.NetworkResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "allocates a child network from a partition's private super network", + "tags": [ + "network" + ] + } + }, + "/v1/network/find": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "findNetworks", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.NetworkFindRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.NetworkResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all networks that match given properties", + "tags": [ + "network" + ] + } + }, + "/v1/network/free/{id}": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "freeNetwork", + "parameters": [ + { + "description": "identifier of the network", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.NetworkResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "free a network", + "tags": [ + "network" + ] + } + }, + "/v1/network/{id}": { + "delete": { + "consumes": [ + "application/json" + ], + "operationId": "deleteNetwork", + "parameters": [ + { + "description": "identifier of the network", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.NetworkResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "deletes a network and returns the deleted entity", + "tags": [ + "network" + ] + }, + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findNetwork", + "parameters": [ + { + "description": "identifier of the network", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.NetworkResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get network by id", + "tags": [ + "network" + ] + } + }, + "/v1/partition": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "listPartitions", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.PartitionResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all Partitions", + "tags": [ + "Partition" + ] + }, + "post": { + "consumes": [ + "application/json" + ], + "operationId": "updatePartition", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.PartitionUpdateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.PartitionResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "updates a Partition. if the Partition was changed since this one was read, a conflict is returned", + "tags": [ + "Partition" + ] + }, + "put": { + "consumes": [ + "application/json" + ], + "operationId": "createPartition", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.PartitionCreateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/v1.PartitionResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "create a Partition. if the given ID already exists a conflict is returned", + "tags": [ + "Partition" + ] + } + }, + "/v1/partition/capacity": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "partitionCapacity", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.PartitionCapacity" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get Partition capacity", + "tags": [ + "Partition" + ] + } + }, + "/v1/partition/{id}": { + "delete": { + "consumes": [ + "application/json" + ], + "operationId": "deletePartition", + "parameters": [ + { + "description": "identifier of the Partition", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.PartitionResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "deletes a Partition and returns the deleted entity", + "tags": [ + "Partition" + ] + }, + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findPartition", + "parameters": [ + { + "description": "identifier of the Partition", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.PartitionResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get Partition by id", + "tags": [ + "Partition" + ] + } + }, + "/v1/project": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "listProjects", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.ProjectResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all projects", + "tags": [ + "project" + ] + } + }, + "/v1/project/find": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "findProjects", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.ProjectFindRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.ProjectResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all projects that match given properties", + "tags": [ + "project" + ] + } + }, + "/v1/project/{id}": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findProject", + "parameters": [ + { + "description": "identifier of the project", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.ProjectResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get project by id", + "tags": [ + "project" + ] + } + }, + "/v1/size": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "listSizes", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.SizeResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all sizes", + "tags": [ + "size" + ] + }, + "post": { + "consumes": [ + "application/json" + ], + "operationId": "updateSize", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.SizeUpdateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.SizeResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "updates a size. if the size was changed since this one was read, a conflict is returned", + "tags": [ + "size" + ] + }, + "put": { + "consumes": [ + "application/json" + ], + "operationId": "createSize", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.SizeCreateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/v1.SizeResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "create a size. if the given ID already exists a conflict is returned", + "tags": [ + "size" + ] + } + }, + "/v1/size/from-hardware": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "fromHardware", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.MachineHardwareExtended" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.SizeMatchingLog" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "Searches all sizes for one to match the given hardwarespecs. If nothing is found, a list of entries is returned which describe the constraint which did not match", + "tags": [ + "size" + ] + } + }, + "/v1/size/{id}": { + "delete": { + "consumes": [ + "application/json" + ], + "operationId": "deleteSize", + "parameters": [ + { + "description": "identifier of the size", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.SizeResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "deletes an size and returns the deleted entity", + "tags": [ + "size" + ] + }, + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findSize", + "parameters": [ + { + "description": "identifier of the size", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.SizeResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get size by id", + "tags": [ + "size" + ] + } + }, + "/v1/switch": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "listSwitches", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "items": { + "$ref": "#/definitions/v1.SwitchResponse" + }, + "type": "array" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get all switches", + "tags": [ + "switch" + ] + } + }, + "/v1/switch/register": { + "post": { + "consumes": [ + "application/json" + ], + "operationId": "registerSwitch", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.SwitchRegisterRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.SwitchResponse" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/v1.SwitchResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "register a switch", + "tags": [ + "switch" + ] + } + }, + "/v1/switch/{id}": { + "delete": { + "consumes": [ + "application/json" + ], + "operationId": "deleteSwitch", + "parameters": [ + { + "description": "identifier of the switch", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.SwitchResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "deletes an switch and returns the deleted entity", + "tags": [ + "switch" + ] + }, + "get": { + "consumes": [ + "application/json" + ], + "operationId": "findSwitch", + "parameters": [ + { + "description": "identifier of the switch", + "in": "path", + "name": "id", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.SwitchResponse" + } + }, + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/httperrors.HTTPErrorResponse" + } + } + }, + "summary": "get switch by id", + "tags": [ + "switch" + ] + } + }, + "/v1/version": { + "get": { + "consumes": [ + "application/json" + ], + "operationId": "info", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/rest.version" + } + } + }, + "summary": "returns the current version information of this module", + "tags": [ + "version" + ] + } + } + }, + "security": [ + { + "Authorization": [ + "HMAC", + "jwt" + ] + } + ], + "securityDefinitions": { + "HMAC": { + "description": "Generate a 'Authorization: Metal xxxx' header where 'xxxx' is a HMAC generated by the Request-Date, the Request-Method and the Body", + "in": "header", + "name": "Authorization", + "type": "apiKey" + }, + "jwt": { + "description": "Add a 'Authorization: Bearer ....' header to the request", + "in": "header", + "name": "Authorization", + "type": "apiKey" + } + }, + "swagger": "2.0", + "tags": [ + { + "description": "Managing image entities", + "name": "image" + }, + { + "description": "Managing ip entities", + "name": "ip" + }, + { + "description": "Managing machine entities", + "name": "machine" + }, + { + "description": "Managing network entities", + "name": "network" + }, + { + "description": "Managing partition entities", + "name": "partition" + }, + { + "description": "Managing project entities", + "name": "project" + }, + { + "description": "Managing size entities", + "name": "size" + }, + { + "description": "Managing switch entities", + "name": "switch" + } + ] +}