From 1f5898999e54a14dbe5621389fd3648c1049fc3a Mon Sep 17 00:00:00 2001 From: kamijin_fanta Date: Thu, 13 Aug 2020 15:57:48 +0900 Subject: [PATCH 1/2] add network_route collector Signed-off-by: kamijin_fanta --- collector/network_route_linux.go | 172 +++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 5 + 3 files changed, 178 insertions(+) create mode 100644 collector/network_route_linux.go diff --git a/collector/network_route_linux.go b/collector/network_route_linux.go new file mode 100644 index 0000000000..a6eca8410f --- /dev/null +++ b/collector/network_route_linux.go @@ -0,0 +1,172 @@ +// 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" + "net" + "strconv" + + "github.com/go-kit/kit/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/vishvananda/netlink" +) + +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) + + routes, err := netlink.RouteList(nil, netlink.FAMILY_V4) + if err != nil { + return fmt.Errorf("couldn't get route list: %w", err) + } + + for _, route := range routes { + if len(route.MultiPath) != 0 { // route has multipath + for _, nexthop := range route.MultiPath { + link, err := netlink.LinkByIndex(nexthop.LinkIndex) + if err != nil { + return fmt.Errorf("couldn't get link by index: %w", err) + } + labels := []string{ + link.Attrs().Name, // if + networkRouteIPToString(route.Src), // src + networkRouteIPNetToString(route.Dst), // dest + networkRouteIPToString(nexthop.Gw), // gw + strconv.Itoa(route.Priority), // priority(metrics) + networkRouteProtocolToString(route.Protocol), // proto + strconv.Itoa(nexthop.Hops + 1), // weight + } + ch <- prometheus.MustNewConstMetric(n.routeDesc, prometheus.GaugeValue, 1, labels...) + deviceRoutes[link.Attrs().Name]++ + } + } else { + link, err := netlink.LinkByIndex(route.LinkIndex) + if err != nil { + return fmt.Errorf("couldn't get link by index: %w", err) + } + labels := []string{ + link.Attrs().Name, // if + networkRouteIPToString(route.Src), // src + networkRouteIPNetToString(route.Dst), // dest + networkRouteIPToString(route.Gw), // gw + strconv.Itoa(route.Priority), // priority(metrics) + networkRouteProtocolToString(route.Protocol), // proto + "", // weight + } + ch <- prometheus.MustNewConstMetric(n.routeDesc, prometheus.GaugeValue, 1, labels...) + deviceRoutes[link.Attrs().Name]++ + } + } + + for dev, total := range deviceRoutes { + ch <- prometheus.MustNewConstMetric(n.routesTotalDesc, prometheus.GaugeValue, float64(total), dev) + } + + return nil +} + +func networkRouteIPNetToString(ip *net.IPNet) string { + if ip == nil { + return "default" + } + return ip.String() +} + +func networkRouteIPToString(ip net.IP) string { + if len(ip) == 0 { + return "" + } + return ip.String() +} + +func networkRouteProtocolToString(protocol int) 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" +} diff --git a/go.mod b/go.mod index 8893ce3d36..84a48384db 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/prometheus/procfs v0.2.0 github.com/siebenmann/go-kstat v0.0.0-20200303194639-4e8294f9e9d5 github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a + github.com/vishvananda/netlink v1.1.0 go.uber.org/multierr v1.5.0 // indirect golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect diff --git a/go.sum b/go.sum index fe1a9550da..e828d2a4a9 100644 --- a/go.sum +++ b/go.sum @@ -329,6 +329,10 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -427,6 +431,7 @@ golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzCANp9oXhu6zFBW6ODx4= From 67480c5e5ba29d27576f99fe6e28a21fbeba5e9f Mon Sep 17 00:00:00 2001 From: kamijin_fanta Date: Fri, 4 Dec 2020 11:35:33 +0900 Subject: [PATCH 2/2] repalce to jsimonetti/rtnetlink Signed-off-by: kamijin_fanta --- collector/network_route_linux.go | 91 +++++++++++++++++++++----------- go.mod | 6 +-- go.sum | 28 +++++++--- 3 files changed, 85 insertions(+), 40 deletions(-) diff --git a/collector/network_route_linux.go b/collector/network_route_linux.go index a6eca8410f..cdd0c8ccd0 100644 --- a/collector/network_route_linux.go +++ b/collector/network_route_linux.go @@ -17,12 +17,13 @@ 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" - "github.com/vishvananda/netlink" ) type networkRouteCollector struct { @@ -58,46 +59,68 @@ func NewNetworkRouteCollector(logger log.Logger) (Collector, error) { func (n networkRouteCollector) Update(ch chan<- prometheus.Metric) error { deviceRoutes := make(map[string]int) - routes, err := netlink.RouteList(nil, netlink.FAMILY_V4) + conn, err := rtnetlink.Dial(nil) if err != nil { - return fmt.Errorf("couldn't get route list: %w", err) + 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 len(route.MultiPath) != 0 { // route has multipath - for _, nexthop := range route.MultiPath { - link, err := netlink.LinkByIndex(nexthop.LinkIndex) - if err != nil { - return fmt.Errorf("couldn't get link by index: %w", err) + 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{ - link.Attrs().Name, // if - networkRouteIPToString(route.Src), // src - networkRouteIPNetToString(route.Dst), // dest - networkRouteIPToString(nexthop.Gw), // gw - strconv.Itoa(route.Priority), // priority(metrics) - networkRouteProtocolToString(route.Protocol), // proto - strconv.Itoa(nexthop.Hops + 1), // weight + 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[link.Attrs().Name]++ + deviceRoutes[ifName]++ } } else { - link, err := netlink.LinkByIndex(route.LinkIndex) - if err != nil { - return fmt.Errorf("couldn't get link by index: %w", err) + ifName := "" + for _, link := range links { + if link.Index == route.Attributes.OutIface { + ifName = link.Attributes.Name + break + } } + labels := []string{ - link.Attrs().Name, // if - networkRouteIPToString(route.Src), // src - networkRouteIPNetToString(route.Dst), // dest - networkRouteIPToString(route.Gw), // gw - strconv.Itoa(route.Priority), // priority(metrics) - networkRouteProtocolToString(route.Protocol), // proto + 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[link.Attrs().Name]++ + deviceRoutes[ifName]++ } } @@ -108,11 +131,19 @@ func (n networkRouteCollector) Update(ch chan<- prometheus.Metric) error { return nil } -func networkRouteIPNetToString(ip *net.IPNet) string { - if ip == nil { +func networkRouteIPWithPrefixToString(ip net.IP, len uint8) string { + if len == 0 { return "default" } - return ip.String() + 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 { @@ -122,7 +153,7 @@ func networkRouteIPToString(ip net.IP) string { return ip.String() } -func networkRouteProtocolToString(protocol int) string { +func networkRouteProtocolToString(protocol uint8) string { // from linux kernel 'include/uapi/linux/rtnetlink.h' switch protocol { case 0: diff --git a/go.mod b/go.mod index 84a48384db..43f061d72c 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,10 @@ require ( github.com/go-kit/kit v0.10.0 github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968 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/mattn/go-xmlrpc v0.0.3 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/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.7.1 @@ -19,12 +19,12 @@ require ( github.com/prometheus/procfs v0.2.0 github.com/siebenmann/go-kstat v0.0.0-20200303194639-4e8294f9e9d5 github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a - github.com/vishvananda/netlink v1.1.0 go.uber.org/multierr v1.5.0 // indirect golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a 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/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 gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/yaml.v2 v2.3.0 diff --git a/go.sum b/go.sum index e828d2a4a9..3a35c8c178 100644 --- a/go.sum +++ b/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.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.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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 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-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-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.7/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.1.0 h1:mpdLgm+brq10nI9zM1BpX1kpDbh3NLl3RSnVq6ZSkfg= 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/go.mod h1:Evt/EIne46u9PtQbeTx2NTcqURpr5K4SvKtGmBuDPN8= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -329,10 +337,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -404,6 +408,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-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-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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -431,7 +440,6 @@ golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzCANp9oXhu6zFBW6ODx4= @@ -445,11 +453,17 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860 h1:YEu4SMq7D0cmT7CBbXfcH0NZeuChAXwsHe/9XueUO6o= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=