diff --git a/.github/workflows/ci-pipeline.yaml b/.github/workflows/ci-pipeline.yaml index c089a21c..49d1aa40 100644 --- a/.github/workflows/ci-pipeline.yaml +++ b/.github/workflows/ci-pipeline.yaml @@ -48,6 +48,6 @@ jobs: with: go-version: ${{ env.GO_VERSION }} - name: Go tests - run: go test -v -race -coverprofile=coverage.out -covermode=atomic ./... + run: sudo go test -v -race -coverprofile=coverage.out -covermode=atomic ./... - name: Upload coverage to Codecov run: bash <(curl -s https://codecov.io/bash) -C $(Build.SourceVersion) diff --git a/.gitignore b/.gitignore index 02956036..4c816f75 100644 --- a/.gitignore +++ b/.gitignore @@ -344,3 +344,6 @@ deployment/overlays/temp # Local deployment configuration files **/.env **/.env.* + +# Test binaries +__debug_bin \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 16bcb143..790cbf1a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,22 +8,15 @@ "name": "Launch Tests", "type": "go", "request": "launch", - "program": "${fileDirname}", - "mode": "test", + "program": "${fileDirname}/__debug_bin", + "mode": "exec", "env": {}, "args": ["-test.v"], - "showLog": true - }, - { - "name": "Launch Tests with race check", - "type": "go", - "request": "launch", - "program": "${fileDirname}", - "mode": "test", - "env": {}, - "buildFlags": "-race", - "args": ["-test.v"], - "showLog": true + "showLog": true, + // https://github.com/golang/vscode-go/blob/master/docs/debugging.md#debug-a-package-test-as-root + "console": "integratedTerminal", + "asRoot": true, + "preLaunchTask": "go test (debug)", }, ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..85542131 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,21 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "go test (debug)", + "type": "shell", + "command": "go", + "args": [ + "test", + "-race", + "-c", + "-gcflags=all=-N -l", + "-o", + "${fileDirname}/__debug_bin" + ], + "options": { + "cwd": "${fileDirname}" + } + } + ] +} \ No newline at end of file diff --git a/builder/Dockerfile.linux b/builder/Dockerfile.linux index 9459af43..13010c88 100644 --- a/builder/Dockerfile.linux +++ b/builder/Dockerfile.linux @@ -16,7 +16,7 @@ RUN go mod download COPY . . -RUN go build ./cmd/aks-periscope +RUN go build -buildvcs=false ./cmd/aks-periscope # Add dependencies for building nsenter RUN apt-get update && \ diff --git a/builder/Dockerfile.windows b/builder/Dockerfile.windows index a3c94288..bb667b1d 100644 --- a/builder/Dockerfile.windows +++ b/builder/Dockerfile.windows @@ -16,7 +16,7 @@ RUN go mod download COPY . . -RUN go build ./cmd/aks-periscope +RUN go build -buildvcs=false ./cmd/aks-periscope # Runner FROM $BASE_IMAGE diff --git a/cmd/aks-periscope/aks-periscope.go b/cmd/aks-periscope/aks-periscope.go index 70acb343..7420ec80 100644 --- a/cmd/aks-periscope/aks-periscope.go +++ b/cmd/aks-periscope/aks-periscope.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/aks-periscope/pkg/exporter" "github.com/Azure/aks-periscope/pkg/interfaces" "github.com/Azure/aks-periscope/pkg/utils" + restclient "k8s.io/client-go/rest" ) @@ -99,6 +100,7 @@ func run(osIdentifier utils.OSIdentifier, knownFilePaths *utils.KnownFilePaths, collector.NewSystemPerfCollector(config, runtimeInfo), collector.NewWindowsLogsCollector(osIdentifier, runtimeInfo, knownFilePaths, fileSystem, 10*time.Second, 20*time.Minute), } + collectors = addOSSpecificCollectors(collectors, config, runtimeInfo) collectorGrp := new(sync.WaitGroup) diff --git a/cmd/aks-periscope/collectorsfactory_linux.go b/cmd/aks-periscope/collectorsfactory_linux.go new file mode 100644 index 00000000..20300fcd --- /dev/null +++ b/cmd/aks-periscope/collectorsfactory_linux.go @@ -0,0 +1,52 @@ +package main + +import ( + "log" + "time" + + "github.com/Azure/aks-periscope/pkg/collector" + "github.com/Azure/aks-periscope/pkg/interfaces" + "github.com/Azure/aks-periscope/pkg/utils" + + containercollection "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection" + "github.com/inspektor-gadget/inspektor-gadget/pkg/runcfanotify" + + restclient "k8s.io/client-go/rest" +) + +func addOSSpecificCollectors(collectors []interfaces.Collector, config *restclient.Config, runtimeInfo *utils.RuntimeInfo) []interfaces.Collector { + // Use the default InspektorGadget behaviour for determining containers: + // https://github.com/inspektor-gadget/inspektor-gadget/blob/6b00fea3f925c9da478126931e774e340ca9bfdf/pkg/gadgettracermanager/gadgettracermanager.go#L275-L283 + var containerCollectionOptions []containercollection.ContainerCollectionOption + if runcfanotify.Supported() { + containerCollectionOptions = []containercollection.ContainerCollectionOption{ + containercollection.WithRuncFanotify(), + containercollection.WithInitialKubernetesContainers(runtimeInfo.HostNodeName), + } + } else { + containerCollectionOptions = []containercollection.ContainerCollectionOption{ + containercollection.WithPodInformer(runtimeInfo.HostNodeName), + } + } + + containerCollectionOptions = append( + containerCollectionOptions, + containercollection.WithNodeName(runtimeInfo.HostNodeName), + containercollection.WithCgroupEnrichment(), + containercollection.WithLinuxNamespaceEnrichment(), + containercollection.WithKubernetesEnrichment(runtimeInfo.HostNodeName, config), + ) + + // Traces can produce a lot of data. + // TODO: Consider whether this should be lower or configurable. + traceCollectionPeriod := 30 * time.Second + traceWaiter := func() { + log.Printf("\twait for %v to stop collection", traceCollectionPeriod) + time.Sleep(traceCollectionPeriod) + } + + return append(collectors, + collector.NewInspektorGadgetDNSTraceCollector(runtimeInfo, traceWaiter, containerCollectionOptions), + collector.NewInspektorGadgetTCPTraceCollector(runtimeInfo, traceWaiter, containerCollectionOptions), + ) +} diff --git a/cmd/aks-periscope/collectorsfactory_windows.go b/cmd/aks-periscope/collectorsfactory_windows.go new file mode 100644 index 00000000..ed275435 --- /dev/null +++ b/cmd/aks-periscope/collectorsfactory_windows.go @@ -0,0 +1,11 @@ +package main + +import ( + "github.com/Azure/aks-periscope/pkg/interfaces" + "github.com/Azure/aks-periscope/pkg/utils" + restclient "k8s.io/client-go/rest" +) + +func addOSSpecificCollectors(collectors []interfaces.Collector, config *restclient.Config, runtimeInfo *utils.RuntimeInfo) []interfaces.Collector { + return collectors +} diff --git a/deployment/base/daemon-set.yaml b/deployment/base/daemon-set.yaml index 6f2e0600..18dcab14 100644 --- a/deployment/base/daemon-set.yaml +++ b/deployment/base/daemon-set.yaml @@ -35,8 +35,8 @@ spec: mountPath: /secret - name: varlog mountPath: /var/log - - name: resolvlog - mountPath: /run/systemd/resolve + - name: run + mountPath: /run - name: etcvmlog mountPath: /etchostlogs resources: @@ -56,9 +56,11 @@ spec: - name: varlog hostPath: path: /var/log - - name: resolvlog + # Need /run from the host to access the container runtime (e.g. containerd) client socket, + # which is used by InspektorGadget to determine the PID for a container ID. + - name: run hostPath: - path: /run/systemd/resolve + path: /run - name: etcvmlog hostPath: path: /etc diff --git a/go.mod b/go.mod index b1cd5e66..abaac2c7 100644 --- a/go.mod +++ b/go.mod @@ -6,21 +6,31 @@ go 1.19 require ( github.com/Azure/azure-storage-blob-go v0.14.0 + github.com/cilium/ebpf v0.9.3 github.com/docker/docker v20.10.17+incompatible github.com/google/uuid v1.2.0 github.com/hashicorp/go-multierror v1.1.1 + github.com/inspektor-gadget/inspektor-gadget v0.12.1 + github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 helm.sh/helm/v3 v3.10.3 - k8s.io/api v0.25.2 - k8s.io/apimachinery v0.25.2 - k8s.io/cli-runtime v0.25.2 - k8s.io/client-go v0.25.2 + k8s.io/api v0.25.4 + k8s.io/apimachinery v0.25.4 + k8s.io/cli-runtime v0.25.4 + k8s.io/client-go v0.25.4 k8s.io/kubectl v0.25.2 k8s.io/metrics v0.25.2 ) require ( + cloud.google.com/go v0.99.0 // indirect github.com/Azure/azure-pipeline-go v0.2.3 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest v0.11.27 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/BurntSushi/toml v1.1.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -56,6 +66,7 @@ require ( github.com/go-openapi/swag v0.19.14 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.2.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect @@ -98,17 +109,19 @@ require ( github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect + github.com/prometheus/client_golang v1.12.2 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect github.com/rubenv/sql-migrate v1.1.2 // indirect github.com/russross/blackfriday v1.5.2 // indirect + github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/cast v1.4.1 // indirect github.com/spf13/cobra v1.5.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -116,13 +129,14 @@ require ( go.etcd.io/etcd/api/v3 v3.5.4 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect + golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect google.golang.org/grpc v1.47.0 // indirect @@ -133,6 +147,7 @@ require ( k8s.io/apiextensions-apiserver v0.25.2 // indirect k8s.io/apiserver v0.25.2 // indirect k8s.io/component-base v0.25.2 // indirect + k8s.io/cri-api v0.23.1 // indirect k8s.io/klog/v2 v2.70.1 // indirect k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect @@ -143,4 +158,3 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) - diff --git a/go.sum b/go.sum index 5900da0f..2f45183c 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,15 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -46,11 +55,16 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg6 github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= +github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= +github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= +github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= @@ -76,6 +90,7 @@ github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 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= @@ -104,6 +119,7 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -112,11 +128,14 @@ github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHe github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.9.3 h1:5KtxXZU+scyERvkJMEm16TbScVvuuMrlhPly78ZMbSc= +github.com/cilium/ebpf v0.9.3/go.mod h1:w27N4UjpaQ9X/DGrSugxUG+H+NhgntDuPb5lCzxCn8A= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -164,6 +183,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= @@ -177,6 +197,7 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= @@ -222,7 +243,9 @@ github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -237,6 +260,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 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/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -255,6 +279,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -282,6 +307,7 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -293,6 +319,9 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -302,6 +331,8 @@ github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= @@ -346,6 +377,8 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inspektor-gadget/inspektor-gadget v0.12.1 h1:rJDc86ls4J3N4e9eWmiOSsIGt35ZBxzQoa9WBEQxkr8= +github.com/inspektor-gadget/inspektor-gadget v0.12.1/go.mod h1:nHHmmKxDgVoKm8ePfG2Z2OP2AZBCllwgwDrhfibcbDE= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -375,8 +408,8 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -463,12 +496,15 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= @@ -490,8 +526,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= 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/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -512,6 +548,7 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rubenv/sql-migrate v1.1.2 h1:9M6oj4e//owVVHYrFISmY9LBRw6gzkCNmD9MV36tZeQ= github.com/rubenv/sql-migrate v1.1.2/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ= @@ -520,6 +557,8 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a h1:np2nR32/A/VcOG9Hn+IOPA8kMk1gbBzK5LpSsgq5pJI= +github.com/s3rj1k/go-fanotify/fanotify v0.0.0-20210917134616-9c00a300bb7a/go.mod h1:wiP6GQ2T378F+YIyuNw7yXtBxJZR+fqrrn1Z6UHZi0Q= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= @@ -533,6 +572,7 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 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/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -549,7 +589,7 @@ github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= 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 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -558,6 +598,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= @@ -608,6 +650,8 @@ golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -620,6 +664,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d h1:vtUKgx8dahOomfFzLREU8nSv25YHnTgLBn4rDnWZdU0= +golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -685,8 +731,11 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -702,6 +751,9 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -737,6 +789,7 @@ golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -745,6 +798,7 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -772,15 +826,22 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI= +golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -797,8 +858,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/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-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -850,7 +911,11 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= 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= @@ -878,6 +943,15 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -927,7 +1001,24 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -949,10 +1040,16 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1004,20 +1101,22 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.25.2 h1:v6G8RyFcwf0HR5jQGIAYlvtRNrxMJQG1xJzaSeVnIS8= -k8s.io/api v0.25.2/go.mod h1:qP1Rn4sCVFwx/xIhe+we2cwBLTXNcheRyYXwajonhy0= +k8s.io/api v0.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs= +k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ= k8s.io/apiextensions-apiserver v0.25.2 h1:8uOQX17RE7XL02ngtnh3TgifY7EhekpK+/piwzQNnBo= k8s.io/apiextensions-apiserver v0.25.2/go.mod h1:iRwwRDlWPfaHhuBfQ0WMa5skdQfrE18QXJaJvIDLvE8= -k8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs= -k8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA= +k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc= +k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= k8s.io/apiserver v0.25.2 h1:YePimobk187IMIdnmsMxsfIbC5p4eX3WSOrS9x6FEYw= k8s.io/apiserver v0.25.2/go.mod h1:30r7xyQTREWCkG2uSjgjhQcKVvAAlqoD+YyrqR6Cn+I= -k8s.io/cli-runtime v0.25.2 h1:XOx+SKRjBpYMLY/J292BHTkmyDffl/qOx3YSuFZkTuc= -k8s.io/cli-runtime v0.25.2/go.mod h1:OQx3+/0st6x5YpkkJQlEWLC73V0wHsOFMC1/roxV8Oc= -k8s.io/client-go v0.25.2 h1:SUPp9p5CwM0yXGQrwYurw9LWz+YtMwhWd0GqOsSiefo= -k8s.io/client-go v0.25.2/go.mod h1:i7cNU7N+yGQmJkewcRD2+Vuj4iz7b30kI8OcL3horQ4= +k8s.io/cli-runtime v0.25.4 h1:GTSBN7aKBrc2LqpdO30CmHQqJtRmotxV7XsMSP+QZIk= +k8s.io/cli-runtime v0.25.4/go.mod h1:JGOw1CR8v4Mcz6cEKA7bFQe0bPrNn1l5sGAX1/Ke4Eg= +k8s.io/client-go v0.25.4 h1:3RNRDffAkNU56M/a7gUfXaEzdhZlYhoW8dgViGy5fn8= +k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw= k8s.io/component-base v0.25.2 h1:Nve/ZyHLUBHz1rqwkjXm/Re6IniNa5k7KgzxZpTfSQY= k8s.io/component-base v0.25.2/go.mod h1:90W21YMr+Yjg7MX+DohmZLzjsBtaxQDDwaX4YxDkl60= +k8s.io/cri-api v0.23.1 h1:0DHL/hpTf4Fp+QkUXFefWcp1fhjXr9OlNdY9X99c+O8= +k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= diff --git a/pkg/collector/inspektor_trace_common_test.go b/pkg/collector/inspektor_trace_common_test.go new file mode 100644 index 00000000..2915cef9 --- /dev/null +++ b/pkg/collector/inspektor_trace_common_test.go @@ -0,0 +1,119 @@ +package collector + +import ( + "context" + "fmt" + "os" + "strings" + + "github.com/Azure/aks-periscope/pkg/test" + containercollection "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection" + containerutils "github.com/inspektor-gadget/inspektor-gadget/pkg/container-utils" + ocispec "github.com/opencontainers/runtime-spec/specs-go" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + "k8s.io/client-go/rest" +) + +func getTestContainerCollectionOptions( + ccChan chan *containercollection.ContainerCollection, + nodeName string, + clusterConfig *rest.Config, +) []containercollection.ContainerCollectionOption { + // Make use of container collection options to: + // - Get hold of the ContainerCollection + // - Add node name to the collection + // - Add K8s pod metadata to the containers (based on the pod UID) + // We skip the following options that Periscope uses: + // - WithRuncFanotify: because we're not assuming our test is running in a containerized environment. + // - WithInitialKubernetesContainers: because this uses an in-cluster context that is inaccessible here. + // - WithPodInformer: also uses an in-cluster context. + // - WithCgroupEnrichment: because this process is not expected to have cgroups, and we're faking those. + // - WithLinuxNamespaceEnrichment: because this will set HostNetwork to true, and we're pretending it's false. + return []containercollection.ContainerCollectionOption{ + withContainerCollectionReceiver(ccChan), + containercollection.WithNodeName(nodeName), + containercollection.WithKubernetesEnrichment(nodeName, clusterConfig), + } +} + +func ensurePod(fixture *test.ClusterFixture, nodeName string) (*corev1.Pod, error) { + setupCommands := []string{ + fmt.Sprintf("kubectl -n %s apply -f /resources/pause-daemonset.yaml", fixture.KnownNamespaces.Periscope), + fmt.Sprintf("kubectl -n %s rollout status daemonset pauseds --timeout=60s", fixture.KnownNamespaces.Periscope), + } + setupCommand := strings.Join(setupCommands, " && ") + _, err := fixture.CommandRunner.Run(setupCommand, fixture.AdminAccess.GetKubeConfigBinding()) + if err != nil { + return nil, fmt.Errorf("failed to install test daemonset: %w", err) + } + + // Find the pod we've created. + return getTestPod(fixture, nodeName) +} + +func getTestPod(fixture *test.ClusterFixture, nodeName string) (*corev1.Pod, error) { + fieldSelector := fields.OneTermEqualSelector("spec.nodeName", nodeName) + nameRequirement, err := labels.NewRequirement("name", selection.Equals, []string{"pauseds"}) + if err != nil { + return nil, fmt.Errorf("failed to create name requirement: %w", err) + } + labelSelector := labels.NewSelector().Add(*nameRequirement) + pods, err := fixture.AdminAccess.Clientset.CoreV1().Pods(fixture.KnownNamespaces.Periscope).List(context.TODO(), metav1.ListOptions{ + FieldSelector: fieldSelector.String(), + LabelSelector: labelSelector.String(), + }) + if err != nil { + return nil, fmt.Errorf("failed to retrieve test pod: %w", err) + } + if len(pods.Items) != 1 { + return nil, fmt.Errorf("expected one test pod, found %d", len(pods.Items)) + } + return &pods.Items[0], nil +} + +func getCurrentProcessAsKubernetesContainer(pod *corev1.Pod) (*containercollection.Container, error) { + // Pretend the current test process is a kubernetes container. + testProcessPid := os.Getpid() + mnsnsid, err := containerutils.GetMntNs(testProcessPid) + if err != nil { + return nil, fmt.Errorf("failed to get mnt namespace id: %w", err) + } + + return &containercollection.Container{ + ID: fmt.Sprintf("test%08d", testProcessPid), + // Namespace, Podname and Labels should be populated by the Kubernetes enricher. + Pid: uint32(testProcessPid), + // This would normally be added by the cgroup enricher + CgroupV2: fmt.Sprintf("/kubelet/kubepods/pod%s/k8scontainerid", pod.ObjectMeta.UID), + // If OciConfig.Mounts is populated, it's used by the Kubernetes enricher to set the container name + // when the container is added. + // In gadgettracermanager, whose behaviour we're trying to replicate, the RuncFanotify enricher + // populates this. If we don't populate it here, the kubernetes enricher 'drops' the container: + // (https://github.com/inspektor-gadget/inspektor-gadget/blob/08b450065bb839e33012d80d476b3a3c17946379/pkg/container-collection/options.go#L497-L500) + OciConfig: &ocispec.Spec{ + Mounts: []ocispec.Mount{ + { + Destination: "/dev/termination-log", + Type: "bind", + Source: fmt.Sprintf("/var/lib/kubelet/pods/%s/containers/%s/dnstest/a1234abcd", pod.ObjectMeta.UID, pod.Spec.Containers[0].Name), + Options: []string{"rbind", "rprivate", "rw"}, + }, + }, + }, + // Set to correlate this container with requests coming from the TCP tracer. + Mntns: mnsnsid, + }, nil +} + +func withContainerCollectionReceiver(ccChan chan *containercollection.ContainerCollection) containercollection.ContainerCollectionOption { + return func(cc *containercollection.ContainerCollection) error { + go func() { + ccChan <- cc + }() + return nil + } +} diff --git a/pkg/collector/inspektor_trace_dns_collector_linux.go b/pkg/collector/inspektor_trace_dns_collector_linux.go new file mode 100644 index 00000000..2c0ddbb2 --- /dev/null +++ b/pkg/collector/inspektor_trace_dns_collector_linux.go @@ -0,0 +1,152 @@ +package collector + +import ( + "fmt" + "log" + "strings" + "sync" + + "github.com/Azure/aks-periscope/pkg/interfaces" + "github.com/Azure/aks-periscope/pkg/utils" + "github.com/cilium/ebpf/rlimit" + containercollection "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection" + "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection/networktracer" + "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/dns/tracer" + dnstypes "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/dns/types" + eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types" +) + +// InspektorGadgetDNSTraceCollector defines a InspektorGadget Trace DNS Collector struct +type InspektorGadgetDNSTraceCollector struct { + data map[string]string + runtimeInfo *utils.RuntimeInfo + waiter func() + containerCollectionOptions []containercollection.ContainerCollectionOption +} + +// CheckSupported implements the interface method +func (collector *InspektorGadgetDNSTraceCollector) CheckSupported() error { + // Inspektor Gadget relies on eBPF which is not (currently) available on Windows nodes. + // However, we're only compiling this for Linux OS right now, so we can skip the OS check. + return nil +} + +// NewInspektorGadgetDNSTraceCollector is a constructor. +func NewInspektorGadgetDNSTraceCollector( + runtimeInfo *utils.RuntimeInfo, + waiter func(), + containerCollectionOptions []containercollection.ContainerCollectionOption, +) *InspektorGadgetDNSTraceCollector { + return &InspektorGadgetDNSTraceCollector{ + data: make(map[string]string), + runtimeInfo: runtimeInfo, + waiter: waiter, + containerCollectionOptions: containerCollectionOptions, + } +} + +func (collector *InspektorGadgetDNSTraceCollector) GetName() string { + return "inspektorgadget-dnstrace" +} + +// Collect implements the interface method +func (collector *InspektorGadgetDNSTraceCollector) Collect() error { + // From https://www.inspektor-gadget.io/blog/2022/09/using-inspektor-gadget-from-golang-applications/ + // In some kernel versions it's needed to bump the rlimits to + // use run BPF programs. + if err := rlimit.RemoveMemlock(); err != nil { + return fmt.Errorf("failed to remove memlock: %w", err) + } + + // We want to trace DNS queries from all pods running on the node, not just the current process. + // To do this we need to make use of a ContainerCollection, which can be initially populated + // with all the pod processes, and dynamically updated as pods are created and deleted. + containerEventCallback := func(event containercollection.PubSubEvent) { + // This doesn't *do* anything, but there will be runtime errors if we don't supply a callback. + switch event.Type { + case containercollection.EventTypeAddContainer: + log.Printf("Container added: %q pid %d\n", event.Container.Name, event.Container.Pid) + case containercollection.EventTypeRemoveContainer: + log.Printf("Container removed: %q pid %d\n", event.Container.Name, event.Container.Pid) + } + } + + // Use the supplied container collection options, but prepend the container event callback. + // The options are all functions that are executed when the container collection is initialized. + opts := append( + []containercollection.ContainerCollectionOption{containercollection.WithPubSub(containerEventCallback)}, + collector.containerCollectionOptions..., + ) + + // Initialize the container collection + containerCollection := &containercollection.ContainerCollection{} + if err := containerCollection.Initialize(opts...); err != nil { + return fmt.Errorf("failed to initialize container collection: %w", err) + } + defer containerCollection.Close() + + // Build up a collection of DNS query events, with a mutex to protect against concurrent access. + var mu sync.Mutex + events := []string{} + + // Events will be collected in a callback from the DNS tracer. + dnsEventCallback := func(container *containercollection.Container, event dnstypes.Event) { + // Enrich event with data from container + event.Node = collector.runtimeInfo.HostNodeName + if !container.HostNetwork { + event.Namespace = container.Namespace + event.Pod = container.Podname + event.Container = container.Name + } + + eventString := eventtypes.EventString(event) + + mu.Lock() + defer mu.Unlock() + events = append(events, eventString) + } + + // The DNS tracer by itself is not associated with any process. It will need to be 'connected' + // to the container collection, which will manage the attaching and detaching of PIDs as + // containers are created and deleted. + tracer, err := tracer.NewTracer() + if err != nil { + return fmt.Errorf("failed to start dns tracer: %w", err) + } + defer tracer.Close() + + // Set up the information needed to link the tracer to the containers. The selector is empty, + // meaning that all containers in the collection will be traced. + config := &networktracer.ConnectToContainerCollectionConfig[dnstypes.Event]{ + Tracer: tracer, + Resolver: containerCollection, + Selector: containercollection.ContainerSelector{}, + EventCallback: dnsEventCallback, + Base: dnstypes.Base, + } + + // Connect the tracer up. Closing the connection will detach the PIDs from the tracer. + conn, err := networktracer.ConnectToContainerCollection(config) + if err != nil { + return fmt.Errorf("failed to connect network tracer: %w", err) + } + defer conn.Close() + + // The trace is now running. Run whatever function our consumer has supplied before storing the + // collected data. + collector.waiter() + + // Store the collected data. + func() { + mu.Lock() + defer mu.Unlock() + collector.data["dnstracer"] = strings.Join(events, "\n") + }() + + return nil +} + +// GetData implements the interface method +func (collector *InspektorGadgetDNSTraceCollector) GetData() map[string]interfaces.DataValue { + return utils.ToDataValueMap(collector.data) +} diff --git a/pkg/collector/inspektor_trace_dns_collector_linux_test.go b/pkg/collector/inspektor_trace_dns_collector_linux_test.go new file mode 100644 index 00000000..4e02f8c8 --- /dev/null +++ b/pkg/collector/inspektor_trace_dns_collector_linux_test.go @@ -0,0 +1,131 @@ +package collector + +import ( + "fmt" + "net" + "regexp" + "strings" + "testing" + + "github.com/Azure/aks-periscope/pkg/test" + "github.com/Azure/aks-periscope/pkg/utils" + containercollection "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection" + corev1 "k8s.io/api/core/v1" +) + +func TestInspektorGadgetDNSTraceCollectorGetName(t *testing.T) { + const expectedName = "inspektorgadget-dnstrace" + + c := NewInspektorGadgetDNSTraceCollector(nil, nil, []containercollection.ContainerCollectionOption{}) + actualName := c.GetName() + if actualName != expectedName { + t.Errorf("unexpected name: expected %s, found %s", expectedName, actualName) + } +} + +func TestInspektorGadgetDNSTraceCollectorCheckSupported(t *testing.T) { + c := NewInspektorGadgetDNSTraceCollector(nil, nil, []containercollection.ContainerCollectionOption{}) + err := c.CheckSupported() + if err != nil { + t.Errorf("error checking supported: %v", err) + } +} + +func TestInspektorGadgetDNSTraceCollectorCollect(t *testing.T) { + fixture, _ := test.GetClusterFixture() + + nodeNames, err := fixture.GetNodeNames() + if err != nil { + t.Fatalf("Error getting node names: %v", err) + } + + nodeName := nodeNames[0] + + // Ensure there is a pod running on our node. This pod process won't actually be traced, but we'll pretend + // our traces are coming from this pod. + pod, err := ensurePod(fixture, nodeName) + if err != nil { + t.Fatalf("Error setting up test pod: %v", err) + } + + // Create a container whose PID is the current process, but has the attributes of the pod. + testContainer, err := getCurrentProcessAsKubernetesContainer(pod) + if err != nil { + t.Fatalf("Unable create container from current process: %v", err) + } + + domains := []string{"microsoft.com", "google.com", "shouldnotexist.com"} + + tests := []struct { + name string + hostNodeName string + wantErr bool + wantData map[string]*regexp.Regexp + }{ + { + name: "valid", + hostNodeName: nodeName, + wantErr: false, + wantData: map[string]*regexp.Regexp{ + "dnstracer": getExpectedDnsTraceData(fixture, nodeName, pod, domains), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + runtimeInfo := &utils.RuntimeInfo{ + HostNodeName: tt.hostNodeName, + } + + // Use a channel to get hold of the ContainerCollection (via a ContainerCollectionOption). + // We'll use this to add our pretend kubernetes container to. + ccChan := make(chan *containercollection.ContainerCollection) + + opts := getTestContainerCollectionOptions(ccChan, tt.hostNodeName, fixture.PeriscopeAccess.ClientConfig) + + waiter := func() { + // While the tracer is running, add a fake container and perform some DNS queries from its process. + cc := <-ccChan + cc.AddContainer(testContainer) + defer cc.RemoveContainer(testContainer.ID) + + for _, domain := range domains { + // Perform a DNS lookup (discarding the result because we're only testing the events it triggers) + _, _ = net.LookupIP(domain) + } + } + + c := NewInspektorGadgetDNSTraceCollector(runtimeInfo, waiter, opts) + err := c.Collect() + + if (err != nil) != tt.wantErr { + t.Errorf("Collect() error = %v, wantErr %v", err, tt.wantErr) + } + data := c.GetData() + compareCollectorData(t, tt.wantData, data) + }) + } +} + +func getExpectedDnsTraceData(fixture *test.ClusterFixture, nodeName string, pod *corev1.Pod, domains []string) *regexp.Regexp { + containerName := pod.Spec.Containers[0].Name + + eventPatterns := []string{} + eventPatterns = append(eventPatterns, + fmt.Sprintf( + `{"node":%q,"namespace":%q,"pod":%q,"container":%q,"type":"debug","message":"tracer attached"}`, + nodeName, fixture.KnownNamespaces.Periscope, pod.Name, containerName), + ) + + for _, domain := range domains { + eventPatterns = append(eventPatterns, + fmt.Sprintf( + `{"node":%q,"namespace":%q,"pod":%q,"container":%q,"type":"normal","id":"[\w.]+","qr":"Q","nameserver":"[\d\.]+","pktType":"OUTGOING","qtype":"A","name":%q}`, + nodeName, fixture.KnownNamespaces.Periscope, pod.Name, containerName, domain+"."), + ) + } + + pattern := strings.Join(eventPatterns, `(\n.*)*`) + return regexp.MustCompile(pattern) +} diff --git a/pkg/collector/inspektor_trace_tcp_collector_linux.go b/pkg/collector/inspektor_trace_tcp_collector_linux.go new file mode 100644 index 00000000..5b586a45 --- /dev/null +++ b/pkg/collector/inspektor_trace_tcp_collector_linux.go @@ -0,0 +1,133 @@ +package collector + +import ( + "fmt" + "log" + "strings" + "sync" + + "github.com/Azure/aks-periscope/pkg/interfaces" + "github.com/Azure/aks-periscope/pkg/utils" + "github.com/cilium/ebpf/rlimit" + + containercollection "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection" + "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-collection/gadgets/trace" + tcptracer "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/tcp/tracer" + tcptypes "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/tcp/types" + standardtracer "github.com/inspektor-gadget/inspektor-gadget/pkg/standardgadgets/trace/tcp" + eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types" +) + +// InspektorGadgetTCPTraceCollector defines a InspektorGadget Trace TCP Collector struct +type InspektorGadgetTCPTraceCollector struct { + data map[string]string + runtimeInfo *utils.RuntimeInfo + waiter func() + containerCollectionOptions []containercollection.ContainerCollectionOption +} + +// CheckSupported implements the interface method +func (collector *InspektorGadgetTCPTraceCollector) CheckSupported() error { + // Inspektor Gadget relies on eBPF which is not (currently) available on Windows nodes. + // However, we're only compiling this for Linux OS right now, so we can skip the OS check. + return nil +} + +// NewInspektorGadgetTCPTraceCollector is a constructor. +func NewInspektorGadgetTCPTraceCollector( + runtimeInfo *utils.RuntimeInfo, + waiter func(), + containerCollectionOptions []containercollection.ContainerCollectionOption, +) *InspektorGadgetTCPTraceCollector { + return &InspektorGadgetTCPTraceCollector{ + data: make(map[string]string), + runtimeInfo: runtimeInfo, + waiter: waiter, + containerCollectionOptions: containerCollectionOptions, + } +} + +func (collector *InspektorGadgetTCPTraceCollector) GetName() string { + return "inspektorgadget-tcptrace" +} + +// Collect implements the interface method +func (collector *InspektorGadgetTCPTraceCollector) Collect() error { + // From https://www.inspektor-gadget.io/blog/2022/09/using-inspektor-gadget-from-golang-applications/ + // In some kernel versions it's needed to bump the rlimits to + // use run BPF programs. + if err := rlimit.RemoveMemlock(); err != nil { + return fmt.Errorf("failed to remove memlock: %w", err) + } + + // We want to trace DNS queries from all pods running on the node, not just the current process. + // To do this we need to make use of a ContainerCollection, which can be initially populated + // with all the pod processes, and dynamically updated as pods are created and deleted. + containerEventCallback := func(event containercollection.PubSubEvent) { + // This doesn't *do* anything, but there will be runtime errors if we don't supply a callback. + switch event.Type { + case containercollection.EventTypeAddContainer: + log.Printf("Container added: %q pid %d\n", event.Container.Name, event.Container.Pid) + case containercollection.EventTypeRemoveContainer: + log.Printf("Container removed: %q pid %d\n", event.Container.Name, event.Container.Pid) + } + } + + // Use the supplied container collection options, but prepend the container event callback. + // The options are all functions that are executed when the container collection is initialized. + opts := append( + []containercollection.ContainerCollectionOption{containercollection.WithPubSub(containerEventCallback)}, + collector.containerCollectionOptions..., + ) + + // Initialize the container collection + containerCollection := &containercollection.ContainerCollection{} + if err := containerCollection.Initialize(opts...); err != nil { + return fmt.Errorf("failed to initialize container collection: %w", err) + } + defer containerCollection.Close() + + // Build up a collection of DNS query events, with a mutex to protect against concurrent access. + var mu sync.Mutex + events := []string{} + + tcpEventCallback := func(event tcptypes.Event) { + eventString := eventtypes.EventString(event) + + mu.Lock() + defer mu.Unlock() + events = append(events, eventString) + } + + traceConfig := &tcptracer.Config{} + enricher := containerCollection + + var tracer trace.Tracer + tracer, err := tcptracer.NewTracer(traceConfig, enricher, tcpEventCallback) + if err != nil { + log.Printf("Failed to create core tracer, falling back to standard one: %v", err) + tracer, err = standardtracer.NewTracer(traceConfig, tcpEventCallback) + if err != nil { + return fmt.Errorf("failed to create a tracer: %w", err) + } + } + defer tracer.Stop() + + // The trace is now running. Run whatever function our consumer has supplied before storing the + // collected data. + collector.waiter() + + // Store the collected data. + func() { + mu.Lock() + defer mu.Unlock() + collector.data["tcptracer"] = strings.Join(events, "\n") + }() + + return nil +} + +// GetData implements the interface method +func (collector *InspektorGadgetTCPTraceCollector) GetData() map[string]interfaces.DataValue { + return utils.ToDataValueMap(collector.data) +} diff --git a/pkg/collector/inspektor_trace_tcp_collector_linux_test.go b/pkg/collector/inspektor_trace_tcp_collector_linux_test.go new file mode 100644 index 00000000..43d057a0 --- /dev/null +++ b/pkg/collector/inspektor_trace_tcp_collector_linux_test.go @@ -0,0 +1,118 @@ +package collector + +import ( + "fmt" + "net/http" + "regexp" + "testing" + + "github.com/Azure/aks-periscope/pkg/test" + "github.com/Azure/aks-periscope/pkg/utils" + containercollection "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection" + corev1 "k8s.io/api/core/v1" +) + +func TestInspektorGadgetTCPTraceCollectorGetName(t *testing.T) { + const expectedName = "inspektorgadget-tcptrace" + + c := NewInspektorGadgetTCPTraceCollector(nil, nil, []containercollection.ContainerCollectionOption{}) + actualName := c.GetName() + if actualName != expectedName { + t.Errorf("unexpected name: expected %s, found %s", expectedName, actualName) + } +} + +func TestInspektorGadgetTCPTraceCollectorCheckSupported(t *testing.T) { + c := NewInspektorGadgetTCPTraceCollector(nil, nil, []containercollection.ContainerCollectionOption{}) + err := c.CheckSupported() + if err != nil { + t.Errorf("error checking supported: %v", err) + } +} + +func TestInspektorGadgetTCPTraceCollectorCollect(t *testing.T) { + fixture, _ := test.GetClusterFixture() + + nodeNames, err := fixture.GetNodeNames() + if err != nil { + t.Fatalf("Error getting node names: %v", err) + } + + nodeName := nodeNames[0] + + // Ensure there is a pod running on our node. This pod process won't actually be traced, but we'll pretend + // our traces are coming from this pod. + pod, err := ensurePod(fixture, nodeName) + if err != nil { + t.Fatalf("Error setting up test pod: %v", err) + } + + // Create a container whose PID is the current process, but has the attributes of the pod. + testContainer, err := getCurrentProcessAsKubernetesContainer(pod) + if err != nil { + t.Fatalf("Unable create container from current process: %v", err) + } + + tests := []struct { + name string + hostNodeName string + wantErr bool + wantData map[string]*regexp.Regexp + }{ + { + name: "valid", + hostNodeName: nodeName, + wantErr: false, + wantData: map[string]*regexp.Regexp{ + "tcptracer": getExpectedTcpTraceData(fixture, nodeName, pod, testContainer), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + runtimeInfo := &utils.RuntimeInfo{ + HostNodeName: tt.hostNodeName, + } + + // Use a channel to get hold of the ContainerCollection (via a ContainerCollectionOption). + // We'll use this to add our pretend kubernetes container to. + ccChan := make(chan *containercollection.ContainerCollection) + + opts := getTestContainerCollectionOptions(ccChan, tt.hostNodeName, fixture.PeriscopeAccess.ClientConfig) + + waiter := func() { + // While the tracer is running, add a fake container and perform some DNS queries from its process. + cc := <-ccChan + cc.AddContainer(testContainer) + defer cc.RemoveContainer(testContainer.ID) + + // Make an HTTP request to a non-localhost URL - this should produce a TCP connect event. + url := "https://mcr.microsoft.com/v2/aks/periscope/tags/list" + _, err = http.Get(url) + if err != nil { + t.Fatalf("Unable to make request to %s: %v", url, err) + } + } + + c := NewInspektorGadgetTCPTraceCollector(runtimeInfo, waiter, opts) + err := c.Collect() + + if (err != nil) != tt.wantErr { + t.Errorf("Collect() error = %v, wantErr %v", err, tt.wantErr) + } + data := c.GetData() + compareCollectorData(t, tt.wantData, data) + }) + } +} + +func getExpectedTcpTraceData(fixture *test.ClusterFixture, nodeName string, pod *corev1.Pod, container *containercollection.Container) *regexp.Regexp { + containerName := pod.Spec.Containers[0].Name + + pattern := fmt.Sprintf( + `{"node":%q,"namespace":%q,"pod":%q,"container":%q,"type":"normal","operation":"connect","pid":\d+,"comm":"[\w.]+","ipversion":4,"saddr":"[\d\.]+","daddr":"[\d\.]+","sport":\d+,"dport":443,"mountnsid":%d}`, + nodeName, fixture.KnownNamespaces.Periscope, pod.Name, containerName, container.Mntns) + + return regexp.MustCompile(pattern) +} diff --git a/pkg/collector/kubeobjects_collector_test.go b/pkg/collector/kubeobjects_collector_test.go index a094f5d6..fa3fe06d 100644 --- a/pkg/collector/kubeobjects_collector_test.go +++ b/pkg/collector/kubeobjects_collector_test.go @@ -68,20 +68,6 @@ func getDefaultKubeObjectResults(fixture *test.ClusterFixture) (map[string]*rege return results, nil } -func getNodeNames(fixture *test.ClusterFixture) ([]string, error) { - nodeList, err := fixture.AdminAccess.Clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return nil, fmt.Errorf("error listing nodes: %w", err) - } - - nodeNames := make([]string, len(nodeList.Items)) - for i, node := range nodeList.Items { - nodeNames[i] = node.Name - } - - return nodeNames, nil -} - func getNodeResults(nodeNames []string) map[string]*regexp.Regexp { results := map[string]*regexp.Regexp{} for _, nodeName := range nodeNames { @@ -111,7 +97,7 @@ func TestKubeObjectsCollectorCollect(t *testing.T) { t.Fatalf("Error determining expected results for default configuration: %v", err) } - nodeNames, err := getNodeNames(fixture) + nodeNames, err := fixture.GetNodeNames() if err != nil { t.Fatalf("Error getting node names: %v", err) } diff --git a/pkg/collector/smi_collector_test.go b/pkg/collector/smi_collector_test.go index 31d47938..3c5d1746 100644 --- a/pkg/collector/smi_collector_test.go +++ b/pkg/collector/smi_collector_test.go @@ -148,7 +148,7 @@ func getExpectedSmiData(knownNamespaces *test.KnownNamespaces) map[string]*regex crdName: "tcproutes.specs.smi-spec.io", kind: "TCPRoute", resources: []crdResource{ - crdResource{ + { namespace: knownNamespaces.OsmBookWarehouse, name: "mysql", apiVersion: "specs.smi-spec.io/v1alpha4", @@ -159,7 +159,7 @@ func getExpectedSmiData(knownNamespaces *test.KnownNamespaces) map[string]*regex crdName: "trafficsplits.split.smi-spec.io", kind: "TrafficSplit", resources: []crdResource{ - crdResource{ + { namespace: knownNamespaces.OsmBookStore, name: "bookstore-split", apiVersion: "split.smi-spec.io/v1alpha2", diff --git a/pkg/collector/systemlogs_collector_test.go b/pkg/collector/systemlogs_collector_test.go index 70a09038..b3964aed 100644 --- a/pkg/collector/systemlogs_collector_test.go +++ b/pkg/collector/systemlogs_collector_test.go @@ -64,7 +64,7 @@ func TestSystemLogsCollectorCollect(t *testing.T) { { name: "get system logs", want: 1, - wantErr: true, + wantErr: false, }, } diff --git a/pkg/test/clusterFixture.go b/pkg/test/clusterFixture.go index e1bbd7a2..4e7e1daa 100644 --- a/pkg/test/clusterFixture.go +++ b/pkg/test/clusterFixture.go @@ -1,6 +1,7 @@ package test import ( + "context" "fmt" "log" "os" @@ -8,6 +9,7 @@ import ( "time" "github.com/docker/docker/client" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" @@ -95,6 +97,21 @@ func (fixture *ClusterFixture) PrintDiagnostics() { } } +// GetNodeNames retrieves the names of the nodes in the test cluster. +func (fixture *ClusterFixture) GetNodeNames() ([]string, error) { + nodeList, err := fixture.AdminAccess.Clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("error listing nodes: %w", err) + } + + nodeNames := make([]string, len(nodeList.Items)) + for i, node := range nodeList.Items { + nodeNames[i] = node.Name + } + + return nodeNames, nil +} + // GetKubeConfigBinding gets the Docker volume binding required to map the fixture's kubeconfig file // to the expected location in the testing tools container. func (clusterAccess *ClusterAccess) GetKubeConfigBinding() string { diff --git a/pkg/test/clusterResourceManagement.go b/pkg/test/clusterResourceManagement.go index bf8d6a27..1c4584fa 100644 --- a/pkg/test/clusterResourceManagement.go +++ b/pkg/test/clusterResourceManagement.go @@ -143,7 +143,7 @@ func deployOsmApplications(clientset *kubernetes.Clientset, commandRunner *Tools } command, binds = getDeployOsmAppsCommand(kubeConfigFile.Name(), knownNamespaces) - _, err = commandRunner.Run(command, binds...) + output, err = commandRunner.Run(command, binds...) fmt.Printf("%s\n%s\n\n", command, output) if err != nil { return fmt.Errorf("error installing applications for OSM: %w", err) diff --git a/pkg/test/dockerImageManagement.go b/pkg/test/dockerImageManagement.go index c1e907b1..b7adce05 100644 --- a/pkg/test/dockerImageManagement.go +++ b/pkg/test/dockerImageManagement.go @@ -112,6 +112,7 @@ func pullDockerImages(client *dockerclient.Client, imagesToPull []string) error pullOutput, err := client.ImagePull(context.Background(), image, dockertypes.ImagePullOptions{}) if err != nil { pullErrorsChan <- fmt.Errorf("error pulling image %s: %w", image, err) + return } defer pullOutput.Close() _, err = io.Copy(os.Stdout, pullOutput) diff --git a/pkg/test/resources/tools-resources/pause-daemonset.yaml b/pkg/test/resources/tools-resources/pause-daemonset.yaml new file mode 100644 index 00000000..351cd3b1 --- /dev/null +++ b/pkg/test/resources/tools-resources/pause-daemonset.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: pauseds +spec: + selector: + matchLabels: + name: pauseds + template: + metadata: + labels: + name: pauseds + spec: + containers: + - name: testcontainer + image: k8s.gcr.io/pause:3.6 + imagePullPolicy: Never + resources: + limits: + cpu: "0.1" + memory: "10Mi" + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule