Update to go 1.18, added Garbage collection for badger
continuous-integration/drone/push Build is passing Details

This commit is contained in:
DataHoarder 2022-02-08 18:27:27 +01:00
parent 6730dd54b1
commit 73c2443d25
7 changed files with 219 additions and 186 deletions

View File

@ -5,7 +5,7 @@ name: default
steps:
- name: backend
image: golang:1.17-bullseye
image: golang:1.18-rc-bullseye
commands:
- go build -v -o fcmm .

View File

@ -1,4 +1,4 @@
FROM golang:1.17-bullseye
FROM golang:1.18-rc-bullseye
COPY . /src

View File

@ -76,6 +76,160 @@ func setCORSHeaders(ctx *httputils.RequestContext) {
ctx.SetResponseHeader("Cross-Origin-Opener-Policy", "unsafe-none")
}
func handleHexHash(pathElements []string, ctx *httputils.RequestContext, host string) {
if len(pathElements) < 3 {
ctx.SetResponseCode(http.StatusBadRequest)
return
}
hashType := strings.ToLower(pathElements[1])
hash, err := hex.DecodeString(pathElements[2])
if err != nil {
ctx.SetResponseCode(http.StatusBadRequest)
return
}
var mh multihash.Multihash
if hashType == "sha256" && len(hash) == 32 {
mh, _ = multihash.Encode(hash, multihash.SHA2_256)
} else if hashType == "md5" && len(hash) == 16 {
mh, _ = multihash.Encode(hash, multihash.MD5)
} else {
ctx.SetResponseCode(http.StatusNotImplemented)
return
}
key := content.NewHashIdentifierFromMultihash(mh)
var skip []int
entry := getContentEntry(key)
if len(pathElements) > 3 {
if pathElements[3] == "information" {
ctx.SetResponseCode(http.StatusOK)
ctx.SetResponseHeader("Content-Type", "application/json")
if entry != nil {
b, _ := json.Marshal(struct {
Known bool `json:"known"`
CID string `json:"cid"`
AccessTime int64 `json:"accessTime"`
CheckTime int64 `json:"checkTime"`
InvalidCount int `json:"invalidCount"`
}{
Known: true,
CID: entry.CID().String(),
AccessTime: entry.AccessTime,
CheckTime: entry.CheckTime,
InvalidCount: len(entry.InvalidList),
})
ctx.ServeBytes(b)
} else {
b, _ := json.Marshal(struct {
Known bool `json:"known"`
CID string `json:"cid"`
}{
Known: false,
CID: key.CID().String(),
})
ctx.ServeBytes(b)
}
return
} else if pathElements[3] == "drop" { //Drop key from cache
ctx.SetResponseCode(http.StatusOK)
ctx.SetResponseHeader("Content-Type", "text/plain")
_ = db.RemoveEntry(key)
if entry != nil && !entry.Key.Equals(key) {
_ = db.RemoveEntry(&entry.Key)
}
ctx.ServeBytes([]byte{})
return
}
//TODO: update entries with these instant returns
data, err := MakyuuIchaival.Bech32Encoding.DecodeString(pathElements[3])
if err != nil {
ctx.SetResponseCode(http.StatusBadRequest)
return
}
skip = utilities.DecodeIntegerList(data)
}
if entry != nil {
oldSkip := skip
skip = entry.InvalidList
for _, ci := range oldSkip {
if !entry.InInvalidList(ci) {
skip = append(skip, ci)
}
}
contentServer := selectNextContentServer(skip)
if contentServer == nil {
ctx.SetResponseCode(http.StatusNotFound)
return
}
ctx.DoRedirect(contentServer.GetContentURL(entry, privateKey, skip)+host, http.StatusFound)
} else {
contentServer := selectNextContentServer(skip)
if contentServer == nil {
ctx.SetResponseCode(http.StatusNotFound)
return
}
//TODO: only trigger this when we don't get a 404
go func() {
var newInvalidList []int
var e *content.Entry
for _, c := range contentServers {
if !c.GetCheckResult() {
continue
}
result, err := c.CheckEntryKey(key, privateKey)
if result != nil {
if e == nil {
e = &content.Entry{
Key: *result,
Version: 0,
AccessTime: time.Now().UTC().Unix(),
CheckTime: time.Now().UTC().Unix() + 3600*24*3, // Check sooner after addition, not all servers might have it yet
}
}
} else if err == nil {
newInvalidList = append(newInvalidList, c.Index)
}
}
if e != nil {
if !key.IsKey() { //Check for entry already existing
entry := getContentEntry(&e.Key)
if entry != nil {
e = entry
}
//Add alias mapping
_ = db.SetAlias(&content.Alias{
Key: *key,
Identifier: e.Key,
})
}
e.AccessTime = time.Now().UTC().Unix()
e.InvalidList = newInvalidList
_ = db.SetEntry(e)
}
}()
ctx.DoRedirect(contentServer.GetHashURL(mh, privateKey, skip)+host, http.StatusFound)
}
}
func handle(ctx *httputils.RequestContext) {
if len(ctx.GetRequestHeader("Host")) > 0 && ctx.GetRequestHeader("Host") == ctx.GetTLSServerName() { //Prevents rebinding / DNS stuff
ctx.SetResponseCode(http.StatusNotFound)
@ -98,155 +252,9 @@ func handle(ctx *httputils.RequestContext) {
setOtherHeaders(ctx)
setCORSHeaders(ctx)
pathElements := strings.Split(ctx.GetPath(), "/")
if len(pathElements) < 3 {
ctx.SetResponseCode(http.StatusBadRequest)
return
}
hashType := strings.ToLower(pathElements[1])
hash, err := hex.DecodeString(pathElements[2])
if err != nil {
ctx.SetResponseCode(http.StatusBadRequest)
return
}
var mh multihash.Multihash
if hashType == "sha256" && len(hash) == 32 {
mh, _ = multihash.Encode(hash, multihash.SHA2_256)
} else if hashType == "md5" && len(hash) == 16 {
mh, _ = multihash.Encode(hash, multihash.MD5)
} else {
ctx.SetResponseCode(http.StatusNotImplemented)
return
}
key := content.NewHashIdentifierFromMultihash(mh)
var skip []int
entry := getContentEntry(key)
if len(pathElements) > 3 {
if pathElements[3] == "information" {
ctx.SetResponseCode(http.StatusOK)
ctx.SetResponseHeader("Content-Type", "application/json")
if entry != nil {
b, _ := json.Marshal(struct {
Known bool `json:"known"`
CID string `json:"cid"`
AccessTime int64 `json:"accessTime"`
CheckTime int64 `json:"checkTime"`
InvalidCount int `json:"invalidCount"`
}{
Known: true,
CID: entry.CID().String(),
AccessTime: entry.AccessTime,
CheckTime: entry.CheckTime,
InvalidCount: len(entry.InvalidList),
})
ctx.ServeBytes(b)
} else {
b, _ := json.Marshal(struct {
Known bool `json:"known"`
CID string `json:"cid"`
}{
Known: false,
CID: key.CID().String(),
})
ctx.ServeBytes(b)
}
return
} else if pathElements[3] == "drop" { //Drop key from cache
ctx.SetResponseCode(http.StatusNoContent)
_ = db.RemoveEntry(key)
if entry != nil && !entry.Key.Equals(key) {
_ = db.RemoveEntry(&entry.Key)
}
ctx.ServeBytes([]byte{})
return
}
//TODO: update entries with these instant returns
data, err := MakyuuIchaival.Bech32Encoding.DecodeString(pathElements[3])
if err != nil {
ctx.SetResponseCode(http.StatusBadRequest)
return
}
skip = utilities.DecodeIntegerList(data)
}
if entry != nil {
oldSkip := skip
skip = entry.InvalidList
for _, ci := range oldSkip {
if !entry.InInvalidList(ci) {
skip = append(skip, ci)
}
}
contentServer := selectNextContentServer(skip)
if contentServer == nil {
ctx.SetResponseCode(http.StatusNotFound)
return
}
ctx.DoRedirect(contentServer.GetContentURL(entry, privateKey, skip)+host, http.StatusFound)
} else {
contentServer := selectNextContentServer(skip)
if contentServer == nil {
ctx.SetResponseCode(http.StatusNotFound)
return
}
//TODO: only trigger this when we don't get a 404
go func() {
var newInvalidList []int
var e *content.Entry
for _, c := range contentServers {
if !c.GetCheckResult() {
continue
}
result, err := c.CheckEntryKey(key, privateKey)
if result != nil {
if e == nil {
e = &content.Entry{
Key: *result,
Version: 0,
AccessTime: time.Now().UTC().Unix(),
CheckTime: time.Now().UTC().Unix() + 3600*24*3, // Check sooner after addition, not all servers might have it yet
}
}
} else if err == nil {
newInvalidList = append(newInvalidList, c.Index)
}
}
if e != nil {
if !key.IsKey() { //Check for entry already existing
entry := getContentEntry(&e.Key)
if entry != nil {
e = entry
}
//Add alias mapping
_ = db.SetAlias(&content.Alias{
Key: *key,
Identifier: e.Key,
})
}
e.AccessTime = time.Now().UTC().Unix()
e.InvalidList = newInvalidList
_ = db.SetEntry(e)
}
}()
ctx.DoRedirect(contentServer.GetHashURL(mh, privateKey, skip)+host, http.StatusFound)
}
//TODO: handle ni RFC 6920
handleHexHash(pathElements, ctx, host)
} else if ctx.IsOptions() {
setOtherHeaders(ctx)
setCORSHeaders(ctx)

View File

@ -5,6 +5,9 @@ Content-addressable storage redirector.
## Usage
* `$ PRIVATE_KEY=<private key> ./fcmm -servers "server1:7777/100,server2:7777/100, -certificate example.crt -keypair example.key`
* Running without `PRIVATE_KEY` will generate an Ed25519 keypair first time, then exit.
`$ go run .`
Build via `$ go build -o fcmm`
@ -13,7 +16,7 @@ Build via `$ go build -o fcmm`
* Use pip certbot
* Edit .env to add paths to certificates
```
```bash
$ certbot certonly \
--standalone \
--key-type=ecdsa --elliptic-curve=secp256r1 \

View File

@ -3,10 +3,13 @@ package content
import (
"fmt"
"github.com/dgraph-io/badger/v3"
"time"
)
type Database struct {
handle *badger.DB
handle *badger.DB
closeChannel chan bool
gcTicker *time.Ticker
}
func OpenDatabase(path string) (*Database, error) {
@ -17,9 +20,28 @@ func OpenDatabase(path string) (*Database, error) {
return nil, err
}
return &Database{
handle: db,
}, nil
database := &Database{
handle: db,
gcTicker: time.NewTicker(time.Minute * 5),
closeChannel: make(chan bool),
}
go func() {
defer database.gcTicker.Stop()
for {
select {
case <-database.gcTicker.C:
for database.handle.RunValueLogGC(0.5) == nil {
}
case <-database.closeChannel:
return
}
}
}()
return database, nil
}
func (db *Database) GetEntry(key HashIdentifier) *Entry {
@ -83,5 +105,6 @@ func (db *Database) getChain(txn *badger.Txn, key HashIdentifier) (*Entry, error
}
func (db *Database) Close() error {
db.closeChannel <- true
return db.handle.Close()
}

20
go.mod
View File

@ -1,9 +1,9 @@
module git.gammaspectra.live/S.O.N.G/FinalCommander
go 1.17
go 1.18
require (
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220119201433-39050c16549d
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220208171845-da95775a33e7
github.com/cloudflare/circl v1.1.0
github.com/dgraph-io/badger/v3 v3.2103.2
github.com/ipfs/go-cid v0.1.0
@ -17,7 +17,7 @@ require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/dgraph-io/ristretto v0.1.0 // indirect
github.com/dgrr/http2 v0.3.3 // indirect
github.com/dgrr/http2 v0.3.4 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
@ -27,8 +27,8 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/flatbuffers v2.0.5+incompatible // indirect
github.com/klauspost/compress v1.14.1 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/klauspost/compress v1.14.2 // indirect
github.com/klauspost/cpuid/v2 v2.0.11 // indirect
github.com/lucas-clemente/quic-go v0.25.0 // indirect
github.com/marten-seemann/qpack v0.2.1 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect
@ -46,15 +46,15 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.32.0 // indirect
github.com/valyala/fasthttp v1.33.0 // indirect
github.com/valyala/fastrand v1.1.0 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce // indirect
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d // indirect
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.8 // indirect
golang.org/x/tools v0.1.9 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect

41
go.sum
View File

@ -7,10 +7,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220118183219-7bfcd667a183 h1:wF+oxs88n5p2O5ixy/vJN4KYefYOgwVmx+8a0xB7TPc=
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220118183219-7bfcd667a183/go.mod h1:z6KcP5RPhMxDJaVU48sBhiYRCJ6ZJBbx1iIhkUrrhfY=
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220119201433-39050c16549d h1:hgO2pPDG/cSFmCh7uzvbqvWHzSdPfO7sk2GuY929JyA=
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220119201433-39050c16549d/go.mod h1:z6KcP5RPhMxDJaVU48sBhiYRCJ6ZJBbx1iIhkUrrhfY=
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220208171845-da95775a33e7 h1:4n8x8qK1YwRQX3CotVqiuYG7v7TbrSNECxTUwTfGppM=
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220208171845-da95775a33e7/go.mod h1:Z2MpldBF7zZIAFVVXkbHa/VbZWqMFj/6FqIgR73l+VE=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@ -47,8 +45,8 @@ github.com/dgraph-io/badger/v3 v3.2103.2 h1:dpyM5eCJAtQCBcMCZcT4UBZchuTJgCywerHH
github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M=
github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI=
github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug=
github.com/dgrr/http2 v0.3.3 h1:F5BlR5CCMCSoEuD6oQcUk9fercKwg01LoArgUP1ycJ4=
github.com/dgrr/http2 v0.3.3/go.mod h1:OrmrVjQp6qa+E3VEiNB+fqpfl+8D9k1ZbBfK4RKU8D0=
github.com/dgrr/http2 v0.3.4 h1:yFiuwKV+SaGcySqsw4FsbdOswfZfSU7sgVXPN1zmykU=
github.com/dgrr/http2 v0.3.4/go.mod h1:OrmrVjQp6qa+E3VEiNB+fqpfl+8D9k1ZbBfK4RKU8D0=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
@ -137,12 +135,13 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.14.1 h1:hLQYb23E8/fO+1u53d02A97a8UnsddcvYzq4ERRU4ds=
github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.11 h1:i2lw1Pm7Yi/4O6XCSyJWqEHI2MDw2FzUK6o/D21xn2A=
github.com/klauspost/cpuid/v2 v2.0.11/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
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.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -267,8 +266,8 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.28.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
github.com/valyala/fasthttp v1.32.0 h1:keswgWzyKyNIIjz2a7JmCYHOOIkRp6HMx9oTV6QrZWY=
github.com/valyala/fasthttp v1.32.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
github.com/valyala/fasthttp v1.33.0 h1:mHBKd98J5NcXuBddgjvim1i3kWzlng1SzLhrnBOU9g8=
github.com/valyala/fasthttp v1.33.0/go.mod h1:KJRK/MXx0J+yd0c5hlR+s1tIHD72sniU8ZJjl97LIw4=
github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8=
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
@ -279,7 +278,6 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
@ -297,8 +295,9 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab h1:lnZ4LoV0UMdibeCUfIB2a4uFwRu491WX/VB2reB8xNc=
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -329,10 +328,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d h1:1n1fc535VhN8SYtD4cDUyNlfpAF2ROMM9+11equK3hs=
golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -374,9 +373,9 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220207234003-57398862261d h1:Bm7BNOQt2Qv7ZqysjeLjgCBanX+88Z/OtdvsrEv1Djc=
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -401,8 +400,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=