Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb5b16614c | ||
|
|
e48ca80dee | ||
|
|
e7c9e22350 | ||
|
|
b8e7d83f19 | ||
|
|
4c304c0013 | ||
|
|
7249350757 | ||
|
|
50a8dc1383 | ||
|
|
71491138aa | ||
|
|
ca87f8ada3 | ||
|
|
835b3f3d67 | ||
|
|
263dffeedc | ||
|
|
e1063944f6 | ||
|
|
2380018457 | ||
|
|
a9db631836 | ||
|
|
b45f138ff1 | ||
|
|
b239694d34 |
No files matched your search
@@ -1,3 +1,10 @@
|
|||||||
|
## Release 1.7.1
|
||||||
|
|
||||||
|
Bug fixes and minor improvements
|
||||||
|
|
||||||
|
* Added utility to recover container addresses without asking Docker #2531
|
||||||
|
* Improved CI #2274
|
||||||
|
|
||||||
## Release 1.7.0
|
## Release 1.7.0
|
||||||
|
|
||||||
Highlights:
|
Highlights:
|
||||||
|
|||||||
Executable
+43
@@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# We need jq to analyse the PR files JSON, so install that first
|
||||||
|
sudo apt-get -q update && sudo apt-get -q install bc jq
|
||||||
|
|
||||||
|
echo "TEST_AND_PUBLISH=1" > "$STATE"
|
||||||
|
|
||||||
|
if [ -n "$CI_PULL_REQUEST" -a "$CI_PULL_REQUEST" = "$CI_PULL_REQUESTS" ] ; then
|
||||||
|
if PR=$(echo "$CI_PULL_REQUEST" | grep -oP '(?<=^https://github.com/weaveworks/weave/pull/)[0-9]+$') ; then
|
||||||
|
echo "GH_PR=$PR" >> "$STATE"
|
||||||
|
if FILES=$(curl -s https://api.github.com/repos/weaveworks/weave/pulls/$PR/files | jq -r '.[]|.filename') ; then
|
||||||
|
echo "PR touches [$FILES]"
|
||||||
|
if ! echo "$FILES" | grep -v ^site/ ; then
|
||||||
|
echo "PR contains site changes only - skipping tests"
|
||||||
|
echo "TEST_AND_PUBLISH=" >> "$STATE"
|
||||||
|
else
|
||||||
|
echo "PR contains non-site changes - running tests"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Unable to get files for PR $PR" >&2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Unable to extract PR number from $CI_PULL_REQUEST" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
source "$STATE"
|
||||||
|
|
||||||
|
mkdir -p $(dirname $SRCDIR) && cp -r $(pwd)/ $SRCDIR
|
||||||
|
|
||||||
|
if [ -n "$TEST_AND_PUBLISH" ] ; then
|
||||||
|
bin/setup-circleci-secrets "$SECRET_PASSWORD"
|
||||||
|
cd $SRCDIR; git submodule update --init
|
||||||
|
if [ "$CIRCLE_NODE_INDEX" = "0" ] ; then
|
||||||
|
cd $SRCDIR/test; ./gce.sh make_template
|
||||||
|
fi
|
||||||
|
cd $SRCDIR/build
|
||||||
|
../tools/rebuild-image weaveworks/weavebuild . Dockerfile build.sh
|
||||||
|
touch $SRCDIR/.build.uptodate
|
||||||
|
sudo chown -R ubuntu /usr/local/go
|
||||||
|
fi
|
||||||
Executable
+43
@@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
source "$STATE"
|
||||||
|
|
||||||
|
site_changes() {
|
||||||
|
curl -s https://api.github.com/repos/weaveworks/weave/pulls/$1/files |
|
||||||
|
jq -r '.[]|.status + " " + .filename' |
|
||||||
|
grep -oP '^(added|modified|removed) site/.*(?=\.md$)'
|
||||||
|
}
|
||||||
|
|
||||||
|
format_comment() {
|
||||||
|
if [ ! -d .git ] || ! BRANCH=$(git symbolic-ref --short HEAD) || [ -z "$BRANCH" ] ; then
|
||||||
|
echo "Could not determine branch" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "#### Documentation changes:"
|
||||||
|
while read ACTION PAGE; do
|
||||||
|
echo "$ACTION [${PAGE#site/}]($WP_DEV_URL/docs/net/${BRANCH#issues/}/${PAGE#site/}/)"
|
||||||
|
done | sort
|
||||||
|
}
|
||||||
|
|
||||||
|
post_comment() {
|
||||||
|
jq -s -R '. | tostring | { body: . }' |
|
||||||
|
curl -s -d @- \
|
||||||
|
-H "Authorization: Bearer $WP_GH_COMMENT_TOKEN" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
https://api.github.com/repos/weaveworks/weave/issues/$GH_PR/comments > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
cd $SRCDIR
|
||||||
|
bin/install-wordepress v1.0.0
|
||||||
|
bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
|
||||||
|
|
||||||
|
if [ -n "$WP_GH_COMMENT_TOKEN" -a -n "$GH_PR" ] ; then
|
||||||
|
echo ">>> Adding doc changelog to GitHub PR $GH_PR"
|
||||||
|
if CHANGES=$(site_changes $GH_PR) && [ -n "$CHANGES" ] ; then
|
||||||
|
echo "$CHANGES" | format_comment | post_comment
|
||||||
|
fi
|
||||||
|
fi
|
||||||
Executable
+16
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
source "$STATE"
|
||||||
|
|
||||||
|
if [ -n "$TEST_AND_PUBLISH" ] ; then
|
||||||
|
docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
|
||||||
|
cd $SRCDIR
|
||||||
|
make clean-bin
|
||||||
|
make publish
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $SRCDIR
|
||||||
|
bin/install-wordepress v1.0.0
|
||||||
|
bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
|
||||||
Executable
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd $SRCDIR
|
||||||
|
bin/install-wordepress v1.0.0
|
||||||
|
bin/publish-site "$WP_LIVE_URL" "$WP_LIVE_USER" "$WP_LIVE_PASSWORD"
|
||||||
Executable
+13
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
source "$STATE"
|
||||||
|
|
||||||
|
if [ -n "$TEST_AND_PUBLISH" ] ; then
|
||||||
|
if [ "$CIRCLE_NODE_INDEX" = "0" ] ; then
|
||||||
|
go get github.com/mattn/goveralls
|
||||||
|
goveralls -repotoken $COVERALLS_REPO_TOKEN -coverprofile=$SRCDIR/test/profile.cov -service=circleci
|
||||||
|
cd $SRCDIR/test; cp coverage.* $CIRCLE_ARTIFACTS
|
||||||
|
fi
|
||||||
|
fi
|
||||||
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
source "$STATE"
|
||||||
|
|
||||||
|
if [ -n "$TEST_AND_PUBLISH" ] ; then
|
||||||
|
cd $SRCDIR
|
||||||
|
make testrunner
|
||||||
|
make COVERAGE=true RM= all
|
||||||
|
|
||||||
|
cd $SRCDIR/test
|
||||||
|
./gce.sh setup && eval $(./gce.sh hosts) && ./setup.sh
|
||||||
|
fi
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
source "$STATE"
|
||||||
|
|
||||||
|
if [ -n "$TEST_AND_PUBLISH" ] ; then
|
||||||
|
cd $SRCDIR/test
|
||||||
|
eval $(./gce.sh hosts)
|
||||||
|
export COVERAGE=true
|
||||||
|
./run_all.sh
|
||||||
|
fi
|
||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
source "$STATE"
|
||||||
|
|
||||||
|
if [ -n "$TEST_AND_PUBLISH" ] ; then
|
||||||
|
cd $SRCDIR/test
|
||||||
|
./gce.sh destroy
|
||||||
|
test "$CIRCLE_NODE_INDEX" != "0" || (cd $SRCDIR/test; ./gen_coverage_reports.sh)
|
||||||
|
fi
|
||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
source "$STATE"
|
||||||
|
|
||||||
|
if [ -n "$TEST_AND_PUBLISH" ] ; then
|
||||||
|
cd $SRCDIR
|
||||||
|
make lint
|
||||||
|
COVERDIR=test/coverage make RM= tests
|
||||||
|
fi
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ $# -ne 1 ] ; then
|
||||||
|
echo USAGE: install-wordepress [COMMIT-ISH] >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
go get github.com/weaveworks/wordepress
|
||||||
|
cd /home/ubuntu/src/github.com/weaveworks/wordepress
|
||||||
|
git checkout $1
|
||||||
|
cd cmd/wordepress
|
||||||
|
go get
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
FROM golang:1.5.2
|
FROM golang:1.5.2
|
||||||
ENV GO15VENDOREXPERIMENT 1
|
ENV GO15VENDOREXPERIMENT 1
|
||||||
RUN apt-get update && apt-get install -y libpcap-dev python-requests time file
|
RUN apt-get update && apt-get install -y libpcap-dev python-requests time file
|
||||||
RUN go get github.com/golang/lint/golint github.com/fzipp/gocyclo github.com/client9/misspell/cmd/misspell
|
RUN go get github.com/fzipp/gocyclo github.com/client9/misspell/cmd/misspell
|
||||||
RUN go clean -i net && go install -tags netgo std
|
RUN go clean -i net && go install -tags netgo std
|
||||||
RUN go install -race -tags netgo std
|
RUN go install -race -tags netgo std
|
||||||
COPY build.sh /
|
COPY build.sh /
|
||||||
|
|||||||
+17
-38
@@ -12,46 +12,31 @@ machine:
|
|||||||
SRCDIR: /home/ubuntu/src/github.com/weaveworks/weave
|
SRCDIR: /home/ubuntu/src/github.com/weaveworks/weave
|
||||||
PATH: $PATH:$HOME/.local/bin
|
PATH: $PATH:$HOME/.local/bin
|
||||||
CLOUDSDK_CORE_DISABLE_PROMPTS: 1
|
CLOUDSDK_CORE_DISABLE_PROMPTS: 1
|
||||||
|
STATE: /home/ubuntu/state.env
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
cache_directories:
|
cache_directories:
|
||||||
- "~/docker"
|
- "~/docker"
|
||||||
post:
|
post:
|
||||||
- "sudo apt-get update && sudo apt-get install bc jq"
|
- bin/circle-dependencies-post
|
||||||
- bin/setup-circleci-secrets "$SECRET_PASSWORD"
|
|
||||||
- "mkdir -p $(dirname $SRCDIR) && cp -r $(pwd)/ $SRCDIR"
|
|
||||||
- "cd $SRCDIR; git submodule update --init"
|
|
||||||
- cd $SRCDIR/test; ./gce.sh make_template:
|
|
||||||
parallel: false
|
|
||||||
- "cd $SRCDIR/build; ../tools/rebuild-image weaveworks/weavebuild . Dockerfile build.sh && touch $SRCDIR/.build.uptodate"
|
|
||||||
- "sudo chown -R ubuntu /usr/local/go"
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
pre:
|
||||||
|
- "$SRCDIR/bin/circle-test-pre":
|
||||||
|
parallel: true
|
||||||
override:
|
override:
|
||||||
- cd $SRCDIR; make lint:
|
- "$SRCDIR/bin/circle-test-unit":
|
||||||
parallel: true
|
parallel: true
|
||||||
- cd $SRCDIR; COVERDIR=test/coverage make RM= tests:
|
- "$SRCDIR/bin/circle-test-smoke":
|
||||||
parallel: true
|
|
||||||
- cd $SRCDIR; make COVERAGE=true RM= exes all:
|
|
||||||
parallel: true
|
|
||||||
- cd $SRCDIR; make testrunner:
|
|
||||||
parallel: true
|
|
||||||
- cd $SRCDIR/test; ./gce.sh setup && eval $(./gce.sh hosts) && ./setup.sh:
|
|
||||||
parallel: true
|
|
||||||
- cd $SRCDIR/test; eval $(./gce.sh hosts); export COVERAGE=true; ./run_all.sh:
|
|
||||||
parallel: true
|
parallel: true
|
||||||
timeout: 300
|
timeout: 300
|
||||||
post:
|
post:
|
||||||
- cd $SRCDIR/test; ./gce.sh destroy:
|
- "$SRCDIR/bin/circle-test-teardown":
|
||||||
parallel: true
|
|
||||||
- test "$CIRCLE_NODE_INDEX" != "0" || (cd $SRCDIR/test; ./gen_coverage_reports.sh):
|
|
||||||
parallel: true
|
parallel: true
|
||||||
|
|
||||||
teardown:
|
teardown:
|
||||||
pre:
|
pre:
|
||||||
- test "$CIRCLE_NODE_INDEX" != "0" || (go get github.com/mattn/goveralls && goveralls -repotoken $COVERALLS_REPO_TOKEN -coverprofile=$SRCDIR/test/profile.cov -service=circleci || true):
|
- "$SRCDIR/bin/circle-teardown-pre":
|
||||||
parallel: true
|
|
||||||
- test "$CIRCLE_NODE_INDEX" != "0" || (cd $SRCDIR/test; cp coverage.* $CIRCLE_ARTIFACTS):
|
|
||||||
parallel: true
|
parallel: true
|
||||||
|
|
||||||
deployment:
|
deployment:
|
||||||
@@ -59,20 +44,14 @@ deployment:
|
|||||||
branch: /[0-9]+\.[0-9]+/
|
branch: /[0-9]+\.[0-9]+/
|
||||||
owner: weaveworks
|
owner: weaveworks
|
||||||
commands:
|
commands:
|
||||||
- go get github.com/weaveworks/wordepress && cd /home/ubuntu/src/github.com/weaveworks/wordepress && git checkout v1.0.0 && cd cmd/wordepress && go get
|
- "$SRCDIR/bin/circle-deploy-release"
|
||||||
- cd $SRCDIR; bin/publish-site "$WP_LIVE_URL" "$WP_LIVE_USER" "$WP_LIVE_PASSWORD"
|
master:
|
||||||
hub:
|
|
||||||
branch: master
|
branch: master
|
||||||
owner: weaveworks
|
owner: weaveworks
|
||||||
commands:
|
commands:
|
||||||
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
|
- "$SRCDIR/bin/circle-deploy-master"
|
||||||
- cd $SRCDIR; make clean-bin
|
issues:
|
||||||
- cd $SRCDIR; make exes publish
|
branch: /.*/
|
||||||
# - go get github.com/weaveworks/wordepress && cd /home/ubuntu/src/github.com/weaveworks/wordepress && git checkout v1.0.0 && cd cmd/wordepress && go get
|
owner: weaveworks
|
||||||
# - cd $SRCDIR; bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
|
commands:
|
||||||
# issues:
|
- "$SRCDIR/bin/circle-deploy-issues"
|
||||||
# branch: /.*/
|
|
||||||
# owner: weaveworks
|
|
||||||
# commands:
|
|
||||||
# - go get github.com/weaveworks/wordepress && cd /home/ubuntu/src/github.com/weaveworks/wordepress && git checkout v1.0.0 && cd cmd/wordepress && go get
|
|
||||||
# - cd $SRCDIR; bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AllPids(procRoot string) ([]int, error) {
|
||||||
|
fh, err := os.Open(procRoot)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer fh.Close()
|
||||||
|
dirNames, err := fh.Readdirnames(-1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pids := make([]int, len(dirNames))
|
||||||
|
for _, dirName := range dirNames {
|
||||||
|
pid, err := strconv.Atoi(dirName)
|
||||||
|
if err != nil { // Only interested in numeric entries - skip /proc/stat, etc.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pids = append(pids, pid)
|
||||||
|
}
|
||||||
|
return pids, err
|
||||||
|
}
|
||||||
+2
-1
@@ -125,7 +125,7 @@ func ConnectedToBridgePredicate(bridgeName string) (func(link netlink.Link) bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetNetDevsWithPredicate(processID int, predicate func(link netlink.Link) bool) ([]NetDev, error) {
|
func GetNetDevsWithPredicate(processID int, predicate func(link netlink.Link) bool) ([]NetDev, error) {
|
||||||
// Bail out if this container is running in the root namespace
|
// Bail out if this process is running in the root namespace
|
||||||
nsToplevel, err := netns.GetFromPid(1)
|
nsToplevel, err := netns.GetFromPid(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to open root namespace: %s", err)
|
return nil, fmt.Errorf("unable to open root namespace: %s", err)
|
||||||
@@ -133,6 +133,7 @@ func GetNetDevsWithPredicate(processID int, predicate func(link netlink.Link) bo
|
|||||||
defer nsToplevel.Close()
|
defer nsToplevel.Close()
|
||||||
nsContainr, err := netns.GetFromPid(processID)
|
nsContainr, err := netns.GetFromPid(processID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Unable to find a namespace for this process - just return nothing
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/weaveworks/weave/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dockerTLSArgs(args []string) error {
|
func dockerTLSArgs(args []string) error {
|
||||||
@@ -15,18 +17,14 @@ func dockerTLSArgs(args []string) error {
|
|||||||
cmdUsage("docker-tls-args", "")
|
cmdUsage("docker-tls-args", "")
|
||||||
}
|
}
|
||||||
procRoot := "/proc"
|
procRoot := "/proc"
|
||||||
dirEntries, err := ioutil.ReadDir(procRoot)
|
pids, err := common.AllPids(procRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dirEntry := range dirEntries {
|
for _, pid := range pids {
|
||||||
dirName := dirEntry.Name()
|
|
||||||
if _, err := strconv.Atoi(dirName); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
isDaemon := false
|
isDaemon := false
|
||||||
|
dirName := strconv.Itoa(pid)
|
||||||
if comm, err := ioutil.ReadFile(filepath.Join(procRoot, dirName, "comm")); err != nil {
|
if comm, err := ioutil.ReadFile(filepath.Join(procRoot, dirName, "comm")); err != nil {
|
||||||
continue
|
continue
|
||||||
} else if string(comm) == "dockerd\n" {
|
} else if string(comm) == "dockerd\n" {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ func init() {
|
|||||||
"create-plugin-network": createPluginNetwork,
|
"create-plugin-network": createPluginNetwork,
|
||||||
"remove-plugin-network": removePluginNetwork,
|
"remove-plugin-network": removePluginNetwork,
|
||||||
"container-addrs": containerAddrs,
|
"container-addrs": containerAddrs,
|
||||||
|
"process-addrs": processAddrs,
|
||||||
"attach-container": attach,
|
"attach-container": attach,
|
||||||
"detach-container": detach,
|
"detach-container": detach,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/weaveworks/weave/common"
|
||||||
|
weavenet "github.com/weaveworks/weave/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func processAddrs(args []string) error {
|
||||||
|
if len(args) < 1 {
|
||||||
|
cmdUsage("process-addrs", "<bridgeName>")
|
||||||
|
}
|
||||||
|
bridgeName := args[0]
|
||||||
|
|
||||||
|
pred, err := common.ConnectedToBridgePredicate(bridgeName)
|
||||||
|
if err != nil {
|
||||||
|
if err == weavenet.ErrLinkNotFound {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pids, err := common.AllPids("/proc")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: Because network namespaces (netns) are changed many times inside the loop,
|
||||||
|
// it's NOT safe to exec any code depending on the root netns without
|
||||||
|
// wrapping with WithNetNS*.
|
||||||
|
for _, pid := range pids {
|
||||||
|
netDevs, err := common.GetNetDevsWithPredicate(pid, pred)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
printNetDevs(strconv.Itoa(pid), netDevs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in new issue
Block a user