Merge pull request #1811 from kamijin-fanta/network_route
add network_route collector
This commit is contained in:
commit
0910f1bb71
|
@ -0,0 +1,203 @@
|
||||||
|
// Copyright 2020 The Prometheus Authors
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build !nonetworkroute
|
||||||
|
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/jsimonetti/rtnetlink"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type networkRouteCollector struct {
|
||||||
|
routeDesc *prometheus.Desc
|
||||||
|
routesTotalDesc *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registerCollector("network_route", defaultDisabled, NewNetworkRouteCollector)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSystemdCollector returns a new Collector exposing systemd statistics.
|
||||||
|
func NewNetworkRouteCollector(logger log.Logger) (Collector, error) {
|
||||||
|
const subsystem = "network"
|
||||||
|
|
||||||
|
routeDesc := prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(namespace, subsystem, "route"),
|
||||||
|
"network routing table", []string{"if", "src", "dest", "gw", "priority", "proto", "weight"}, nil,
|
||||||
|
)
|
||||||
|
routeTotalDesc := prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(namespace, subsystem, "routes_total"),
|
||||||
|
"network total routes", []string{"if"}, nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
return &networkRouteCollector{
|
||||||
|
routeDesc: routeDesc,
|
||||||
|
routesTotalDesc: routeTotalDesc,
|
||||||
|
logger: logger,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n networkRouteCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
|
deviceRoutes := make(map[string]int)
|
||||||
|
|
||||||
|
conn, err := rtnetlink.Dial(nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't connect rtnetlink: %w", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
links, err := conn.Link.List()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't get links: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
routes, err := conn.Route.List()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't get routes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, route := range routes {
|
||||||
|
if route.Type != unix.RTA_DST {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(route.Attributes.Multipath) != 0 {
|
||||||
|
for _, nextHop := range route.Attributes.Multipath {
|
||||||
|
ifName := ""
|
||||||
|
for _, link := range links {
|
||||||
|
if link.Index == nextHop.Hop.IfIndex {
|
||||||
|
ifName = link.Attributes.Name
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := []string{
|
||||||
|
ifName, // if
|
||||||
|
networkRouteIPToString(route.Attributes.Src), // src
|
||||||
|
networkRouteIPWithPrefixToString(route.Attributes.Dst, route.DstLength), // dest
|
||||||
|
networkRouteIPToString(nextHop.Gateway), // gw
|
||||||
|
strconv.FormatUint(uint64(route.Attributes.Priority), 10), // priority(metrics)
|
||||||
|
networkRouteProtocolToString(route.Protocol), // proto
|
||||||
|
strconv.Itoa(int(nextHop.Hop.Hops) + 1), // weight
|
||||||
|
}
|
||||||
|
ch <- prometheus.MustNewConstMetric(n.routeDesc, prometheus.GaugeValue, 1, labels...)
|
||||||
|
deviceRoutes[ifName]++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ifName := ""
|
||||||
|
for _, link := range links {
|
||||||
|
if link.Index == route.Attributes.OutIface {
|
||||||
|
ifName = link.Attributes.Name
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := []string{
|
||||||
|
ifName, // if
|
||||||
|
networkRouteIPToString(route.Attributes.Src), // src
|
||||||
|
networkRouteIPWithPrefixToString(route.Attributes.Dst, route.DstLength), // dest
|
||||||
|
networkRouteIPToString(route.Attributes.Gateway), // gw
|
||||||
|
strconv.FormatUint(uint64(route.Attributes.Priority), 10), // priority(metrics)
|
||||||
|
networkRouteProtocolToString(route.Protocol), // proto
|
||||||
|
"", // weight
|
||||||
|
}
|
||||||
|
ch <- prometheus.MustNewConstMetric(n.routeDesc, prometheus.GaugeValue, 1, labels...)
|
||||||
|
deviceRoutes[ifName]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for dev, total := range deviceRoutes {
|
||||||
|
ch <- prometheus.MustNewConstMetric(n.routesTotalDesc, prometheus.GaugeValue, float64(total), dev)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func networkRouteIPWithPrefixToString(ip net.IP, len uint8) string {
|
||||||
|
if len == 0 {
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
iplen := net.IPv4len
|
||||||
|
if ip.To4() == nil {
|
||||||
|
iplen = net.IPv6len
|
||||||
|
}
|
||||||
|
network := &net.IPNet{
|
||||||
|
IP: ip,
|
||||||
|
Mask: net.CIDRMask(int(len), iplen*8),
|
||||||
|
}
|
||||||
|
return network.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func networkRouteIPToString(ip net.IP) string {
|
||||||
|
if len(ip) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return ip.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func networkRouteProtocolToString(protocol uint8) string {
|
||||||
|
// from linux kernel 'include/uapi/linux/rtnetlink.h'
|
||||||
|
switch protocol {
|
||||||
|
case 0:
|
||||||
|
return "unspec"
|
||||||
|
case 1:
|
||||||
|
return "redirect"
|
||||||
|
case 2:
|
||||||
|
return "kernel"
|
||||||
|
case 3:
|
||||||
|
return "boot"
|
||||||
|
case 4:
|
||||||
|
return "static"
|
||||||
|
case 8:
|
||||||
|
return "gated"
|
||||||
|
case 9:
|
||||||
|
return "ra"
|
||||||
|
case 10:
|
||||||
|
return "mrt"
|
||||||
|
case 11:
|
||||||
|
return "zebra"
|
||||||
|
case 12:
|
||||||
|
return "bird"
|
||||||
|
case 13:
|
||||||
|
return "dnrouted"
|
||||||
|
case 14:
|
||||||
|
return "xorp"
|
||||||
|
case 15:
|
||||||
|
return "ntk"
|
||||||
|
case 16:
|
||||||
|
return "dhcp"
|
||||||
|
case 17:
|
||||||
|
return "mrouted"
|
||||||
|
case 42:
|
||||||
|
return "babel"
|
||||||
|
case 186:
|
||||||
|
return "bgp"
|
||||||
|
case 187:
|
||||||
|
return "isis"
|
||||||
|
case 188:
|
||||||
|
return "ospf"
|
||||||
|
case 189:
|
||||||
|
return "rip"
|
||||||
|
case 192:
|
||||||
|
return "eigrp"
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
5
go.mod
5
go.mod
|
@ -7,10 +7,10 @@ require (
|
||||||
github.com/go-kit/kit v0.10.0
|
github.com/go-kit/kit v0.10.0
|
||||||
github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968
|
github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968
|
||||||
github.com/hodgesds/perf-utils v0.0.8
|
github.com/hodgesds/perf-utils v0.0.8
|
||||||
|
github.com/jsimonetti/rtnetlink v0.0.0-20201125080424-8bebea019a6c
|
||||||
github.com/lufia/iostat v1.1.0
|
github.com/lufia/iostat v1.1.0
|
||||||
github.com/mattn/go-xmlrpc v0.0.3
|
github.com/mattn/go-xmlrpc v0.0.3
|
||||||
github.com/mdlayher/genetlink v1.0.0 // indirect
|
github.com/mdlayher/genetlink v1.0.0 // indirect
|
||||||
github.com/mdlayher/netlink v1.1.0 // indirect
|
|
||||||
github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd
|
github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd
|
||||||
github.com/prometheus/client_golang v1.7.1
|
github.com/prometheus/client_golang v1.7.1
|
||||||
github.com/prometheus/client_model v0.2.0
|
github.com/prometheus/client_model v0.2.0
|
||||||
|
@ -21,8 +21,9 @@ require (
|
||||||
github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a
|
github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a
|
||||||
go.uber.org/multierr v1.5.0 // indirect
|
go.uber.org/multierr v1.5.0 // indirect
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
|
||||||
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb // indirect
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect
|
||||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860
|
golang.org/x/sys v0.0.0-20201202213521-69691e467435
|
||||||
golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97 // indirect
|
golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97 // indirect
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3 // indirect
|
honnef.co/go/tools v0.0.1-2020.1.3 // indirect
|
||||||
|
|
15
go.sum
15
go.sum
|
@ -116,6 +116,9 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||||
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
@ -162,6 +165,9 @@ github.com/jsimonetti/rtnetlink v0.0.0-20190830100107-3784a6c7c552 h1:Ve/e6edHdA
|
||||||
github.com/jsimonetti/rtnetlink v0.0.0-20190830100107-3784a6c7c552/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
github.com/jsimonetti/rtnetlink v0.0.0-20190830100107-3784a6c7c552/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||||
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4 h1:nwOc1YaOrYJ37sEBrtWZrdqzK22hiJs3GpDmP3sR2Yw=
|
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4 h1:nwOc1YaOrYJ37sEBrtWZrdqzK22hiJs3GpDmP3sR2Yw=
|
||||||
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
|
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
|
||||||
|
github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
|
||||||
|
github.com/jsimonetti/rtnetlink v0.0.0-20201125080424-8bebea019a6c h1:SIKkaHgrNzRnHEB3QtUR3VUwy9+QpnTwhZ9GYBC0QyU=
|
||||||
|
github.com/jsimonetti/rtnetlink v0.0.0-20201125080424-8bebea019a6c/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
@ -203,6 +209,8 @@ github.com/mdlayher/netlink v1.0.0 h1:vySPY5Oxnn/8lxAPn2cK6kAzcZzYJl3KriSLO46OT1
|
||||||
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||||
github.com/mdlayher/netlink v1.1.0 h1:mpdLgm+brq10nI9zM1BpX1kpDbh3NLl3RSnVq6ZSkfg=
|
github.com/mdlayher/netlink v1.1.0 h1:mpdLgm+brq10nI9zM1BpX1kpDbh3NLl3RSnVq6ZSkfg=
|
||||||
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
|
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
|
||||||
|
github.com/mdlayher/netlink v1.1.1 h1:VqG+Voq9V4uZ+04vjIrcSCWDpf91B1xxbP4QBUmUJE8=
|
||||||
|
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||||
github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd h1:50p1vPNK43pzCVX10+5MmiOerbBzC1vR6+sLB3FZewE=
|
github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd h1:50p1vPNK43pzCVX10+5MmiOerbBzC1vR6+sLB3FZewE=
|
||||||
github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd/go.mod h1:Evt/EIne46u9PtQbeTx2NTcqURpr5K4SvKtGmBuDPN8=
|
github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd/go.mod h1:Evt/EIne46u9PtQbeTx2NTcqURpr5K4SvKtGmBuDPN8=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
|
@ -402,6 +410,11 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
|
||||||
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
|
||||||
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -449,6 +462,8 @@ golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXR
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|
Loading…
Reference in New Issue