mirror of https://github.com/k3s-io/k3s
Update flannel to 0.14.1
To fix systemd issue Signed-off-by: Manuel Buil <mbuil@suse.com>pull/4274/head
parent
0fbbc5af7c
commit
aa8457c18e
|
@ -29,7 +29,7 @@ K3s is a [fully conformant](https://github.com/cncf/k8s-conformance/pulls?q=is%3
|
|||
K3s bundles the following technologies together into a single cohesive distribution:
|
||||
|
||||
* [Containerd](https://containerd.io/) & [runc](https://github.com/opencontainers/runc)
|
||||
* [Flannel](https://github.com/coreos/flannel) for CNI
|
||||
* [Flannel](https://github.com/flannel-io/flannel) for CNI
|
||||
* [CoreDNS](https://coredns.io/)
|
||||
* [Metrics Server](https://github.com/kubernetes-sigs/metrics-server)
|
||||
* [Traefik](https://containo.us/traefik/) for ingress
|
||||
|
|
3
go.mod
3
go.mod
|
@ -17,7 +17,6 @@ replace (
|
|||
github.com/containerd/ttrpc => github.com/containerd/ttrpc v1.0.2
|
||||
github.com/containerd/typeurl => github.com/containerd/typeurl v1.0.2
|
||||
github.com/containerd/zfs => github.com/containerd/zfs v1.0.0
|
||||
github.com/coreos/flannel => github.com/rancher/flannel v0.12.0-k3s1
|
||||
github.com/coreos/go-systemd => github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
||||
github.com/docker/distribution => github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible
|
||||
github.com/docker/docker => github.com/docker/docker v17.12.0-ce-rc1.0.20200310163718-4634ce647cf2+incompatible
|
||||
|
@ -73,11 +72,11 @@ require (
|
|||
github.com/containerd/go-cni v1.0.2 // indirect
|
||||
github.com/containerd/imgcrypt v1.1.1 // indirect
|
||||
github.com/containernetworking/plugins v0.9.1 // indirect
|
||||
github.com/coreos/flannel v0.12.0
|
||||
github.com/coreos/go-iptables v0.5.0
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200916142827-bd33bbf0497b+incompatible
|
||||
github.com/erikdubbelboer/gspt v0.0.0-20190125194910-e68493906b83
|
||||
github.com/flannel-io/flannel v0.14.1
|
||||
github.com/go-bindata/go-bindata v3.1.2+incompatible
|
||||
github.com/go-sql-driver/mysql v1.4.1
|
||||
github.com/google/cadvisor v0.37.5
|
||||
|
|
22
go.sum
22
go.sum
|
@ -152,9 +152,11 @@ github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8h
|
|||
github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY=
|
||||
github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
|
||||
github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
|
||||
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||
github.com/containernetworking/cni v0.8.1 h1:7zpDnQ3T3s4ucOuJ/ZCLrYBxzkg0AELFfII3Epo9TmI=
|
||||
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
|
||||
github.com/containernetworking/plugins v0.9.1 h1:FD1tADPls2EEi3flPc2OegIY1M9pUa9r2Quag7HMLV8=
|
||||
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
|
||||
github.com/containers/ocicrypt v1.1.1 h1:prL8l9w3ntVqXvNH1CiNn5ENjcCnr38JqpSyvKKB4GI=
|
||||
|
@ -163,7 +165,7 @@ github.com/coredns/corefile-migration v1.0.10/go.mod h1:RMy/mXdeDlYwzt0vdMEJvT2h
|
|||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.1.11+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-iptables v0.4.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-iptables v0.5.0 h1:mw6SAibtHKZcNzAsOxjoHIG0gy5YFHhypWSSNc6EjbQ=
|
||||
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM=
|
||||
|
@ -241,6 +243,8 @@ github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8
|
|||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/flannel-io/flannel v0.14.1 h1:18j/zszdoBPG2Y2yk0MsZYIKZBhVKb5fknZm2lJcbW4=
|
||||
github.com/flannel-io/flannel v0.14.1/go.mod h1:qZhrC3nxQudgshBtTb5rBqFxeYtQGRa4AQGwKi4u4Ds=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
|
||||
|
@ -638,6 +642,7 @@ github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
|||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
@ -646,6 +651,7 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
|
|||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
|
@ -709,18 +715,10 @@ github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFB
|
|||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI=
|
||||
github.com/rakelkar/gonetsh v0.0.0-20190930180311-e5c5ffe4bdf0 h1:iXE9kmlAqhusXxzkXictdNgWS7p4ZBnmv9SdyMgTf6E=
|
||||
github.com/rakelkar/gonetsh v0.0.0-20190930180311-e5c5ffe4bdf0/go.mod h1:4XHkfaUj+URzGO9sohoAgt2V9Y8nIW7fugpu0E6gShk=
|
||||
github.com/rancher/cri-tools v1.19.0-k3s1 h1:c6lqNWyoAB5+NaUREbpZxKXCuYl9he24/DZEgHywg+A=
|
||||
github.com/rancher/cri-tools v1.19.0-k3s1/go.mod h1:bitvtZRi5F7t505Yw3zPzp22LOao1lqJKHfx6x0hnpw=
|
||||
github.com/rancher/dynamiclistener v0.2.2 h1:70dMwOr1sqb6mQqfU2nDb/fr5cv7HJjH+kFYzoxb8KU=
|
||||
github.com/rancher/dynamiclistener v0.2.2/go.mod h1:9WusTANoiRr8cDWCTtf5txieulezHbpv4vhLADPp0zU=
|
||||
github.com/rancher/flannel v0.12.0-k3s1 h1:P23dWSk/9mGT1x2rDWW9JXNrF/0kjftiHwMau/+ZLGM=
|
||||
github.com/rancher/flannel v0.12.0-k3s1/go.mod h1:zQ/9Uhaw0yV4Wh6ljVwHVT1x5KuhenZA+6L8lRzOJEY=
|
||||
github.com/rancher/go-powershell v0.0.0-20200701182037-6845e6fcfa79 h1:UeC0rjrIel8hHz92cdVN09Cm4Hz+BhsPP/ZvQnPOr58=
|
||||
github.com/rancher/go-powershell v0.0.0-20200701182037-6845e6fcfa79/go.mod h1:xi4WpK6Op4m1Lknq61/e+VSjYlTs9bulVOaDNyBdzvk=
|
||||
github.com/rancher/go-powershell v0.0.0-20200701184732-233247d45373 h1:BePi97poJ4hXnkP9yX96EmNQgMg+dGScvB1sqIheJ7w=
|
||||
github.com/rancher/go-powershell v0.0.0-20200701184732-233247d45373/go.mod h1:Vz8oLnHgttpo/aZrTpjbcpZEDzzElqNau2zmorToY0E=
|
||||
github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009/go.mod h1:wpITyDPTi/Na5h73XkbuEf2AP9fbgrIGqqxVzFhYD6U=
|
||||
github.com/rancher/remotedialer v0.2.0 h1:xD7t3K6JYwTdAsxmGtTHQMkEkFgKouQ1foLxVW424Dc=
|
||||
github.com/rancher/remotedialer v0.2.0/go.mod h1:tkU8ZvrR5lRgaKWaX71nAy6daeqvPFx/lJEnbW7tXSI=
|
||||
|
@ -810,6 +808,7 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG
|
|||
github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmDkqO9/zg7R0lSQRs=
|
||||
github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||
github.com/tektoncd/pipeline v0.4.0/go.mod h1:IZzJdiX9EqEMuUcgdnElozdYYRh0/ZRC+NKMLj1K3Yw=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v1.0.67/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI=
|
||||
github.com/thecodeteam/goscaleio v0.1.0/go.mod h1:68sdkZAsK8bvEwBlbQnlLS+xU+hvLYM/iQ8KXej1AwM=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
|
@ -828,11 +827,11 @@ github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
|
|||
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
github.com/vishvananda/netlink v0.0.0-20170220200719-fe3b5664d23a/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 h1:cPXZWzzG0NllBLdjWoD1nDfaqu98YMv+OneaKc8sPOA=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20170219233438-54f0e4339ce7/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
|
||||
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/vishvananda/netns v0.0.0-20200520041808-52d707b772fe/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
|
||||
|
@ -1064,7 +1063,6 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL
|
|||
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
|
||||
k8s.io/system-validators v1.1.2/go.mod h1:bPldcLgkIUK22ALflnsXk8pvkTEndYdNuaHH6gRrl0Q=
|
||||
k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
k8s.io/utils v0.0.0-20200414100711-2df71ebbae66/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg=
|
||||
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
|
|
|
@ -21,18 +21,18 @@ import (
|
|||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/network"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet/kube"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/network"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet/kube"
|
||||
"golang.org/x/net/context"
|
||||
log "k8s.io/klog"
|
||||
|
||||
// Backends need to be imported for their init() to get executed and them to register
|
||||
_ "github.com/coreos/flannel/backend/extension"
|
||||
_ "github.com/coreos/flannel/backend/hostgw"
|
||||
_ "github.com/coreos/flannel/backend/ipsec"
|
||||
_ "github.com/coreos/flannel/backend/vxlan"
|
||||
_ "github.com/flannel-io/flannel/backend/extension"
|
||||
_ "github.com/flannel-io/flannel/backend/hostgw"
|
||||
_ "github.com/flannel-io/flannel/backend/ipsec"
|
||||
_ "github.com/flannel-io/flannel/backend/vxlan"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -45,7 +45,7 @@ func flannel(ctx context.Context, flannelIface *net.Interface, flannelConf, kube
|
|||
return err
|
||||
}
|
||||
|
||||
sm, err := kube.NewSubnetManager("", kubeConfigFile, "flannel.alpha.coreos.com", flannelConf)
|
||||
sm, err := kube.NewSubnetManager(ctx, "", kubeConfigFile, "flannel.alpha.coreos.com", flannelConf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func flannel(ctx context.Context, flannelIface *net.Interface, flannelConf, kube
|
|||
return err
|
||||
}
|
||||
|
||||
bn, err := be.RegisterNetwork(ctx, sync.WaitGroup{}, config)
|
||||
bn, err := be.RegisterNetwork(ctx, &sync.WaitGroup{}, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -90,14 +90,14 @@ func LookupExtIface(iface *net.Interface) (*backend.ExternalInterface, error) {
|
|||
|
||||
if iface == nil {
|
||||
log.Info("Determining IP address of default interface")
|
||||
if iface, err = ip.GetDefaultGatewayIface(); err != nil {
|
||||
if iface, err = ip.GetDefaultGatewayInterface(); err != nil {
|
||||
return nil, fmt.Errorf("failed to get default interface: %s", err)
|
||||
}
|
||||
} else {
|
||||
log.Info("Determining IP address of specified interface: ", iface.Name)
|
||||
}
|
||||
|
||||
ifaceAddr, err = ip.GetIfaceIP4Addr(iface)
|
||||
ifaceAddr, err = ip.GetInterfaceIP4Addr(iface)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find IPv4 address for interface %s", iface.Name)
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
Copyright (c) 2017, Gorillalabs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
http://www.opensource.org/licenses/MIT
|
|
@ -1,110 +0,0 @@
|
|||
# go-powershell
|
||||
|
||||
This package is inspired by [jPowerShell](https://github.com/profesorfalken/jPowerShell)
|
||||
and allows one to run and remote-control a PowerShell session. Use this if you
|
||||
don't have a static script that you want to execute, bur rather run dynamic
|
||||
commands.
|
||||
|
||||
## Installation
|
||||
|
||||
go get github.com/rancher/go-powershell
|
||||
|
||||
## Usage
|
||||
|
||||
To start a PowerShell shell, you need a backend. Backends take care of starting
|
||||
and controlling the actual powershell.exe process. In most cases, you will want
|
||||
to use the Local backend, which just uses ``os/exec`` to start the process.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ps "github.com/rancher/go-powershell"
|
||||
"github.com/rancher/go-powershell/backend"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// choose a backend
|
||||
back := &backend.Local{}
|
||||
|
||||
// start a local powershell process
|
||||
shell, err := ps.New(back)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer shell.Exit()
|
||||
|
||||
// ... and interact with it
|
||||
stdout, stderr, err := shell.Execute("Get-WmiObject -Class Win32_Processor")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(stdout)
|
||||
}
|
||||
```
|
||||
|
||||
## Remote Sessions
|
||||
|
||||
You can use an existing PS shell to use PSSession cmdlets to connect to remote
|
||||
computers. Instead of manually handling that, you can use the Session middleware,
|
||||
which takes care of authentication. Note that you can still use the "raw" shell
|
||||
to execute commands on the computer where the powershell host process is running.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ps "github.com/rancher/go-powershell"
|
||||
"github.com/rancher/go-powershell/backend"
|
||||
"github.com/rancher/go-powershell/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// choose a backend
|
||||
back := &backend.Local{}
|
||||
|
||||
// start a local powershell process
|
||||
shell, err := ps.New(back)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// prepare remote session configuration
|
||||
config := middleware.NewSessionConfig()
|
||||
config.ComputerName = "remote-pc-1"
|
||||
|
||||
// create a new shell by wrapping the existing one in the session middleware
|
||||
session, err := middleware.NewSession(shell, config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer session.Exit() // will also close the underlying ps shell!
|
||||
|
||||
// everything run via the session is run on the remote machine
|
||||
stdout, stderr, err = session.Execute("Get-WmiObject -Class Win32_Processor")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(stdout)
|
||||
}
|
||||
```
|
||||
|
||||
Note that a single shell instance is not safe for concurrent use, as are remote
|
||||
sessions. You can have as many remote sessions using the same shell as you like,
|
||||
but you must execute commands serially. If you need concurrency, you can just
|
||||
spawn multiple PowerShell processes (i.e. call ``.New()`` multiple times).
|
||||
|
||||
Also, note that all commands that you execute are wrapped in special echo
|
||||
statements to delimit the stdout/stderr streams. After ``.Execute()``ing a command,
|
||||
you can therefore not access ``$LastExitCode`` anymore and expect meaningful
|
||||
results.
|
||||
|
||||
## License
|
||||
|
||||
MIT, see LICENSE file.
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright (c) 2017 Gorillalabs. All rights reserved.
|
||||
|
||||
package backend
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os/exec"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Local struct{}
|
||||
|
||||
func (b *Local) StartProcess(cmd string, args ...string) (Waiter, io.Writer, io.Reader, io.Reader, error) {
|
||||
command := exec.Command(cmd, args...)
|
||||
|
||||
stdin, err := command.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the PowerShell's stdin stream")
|
||||
}
|
||||
|
||||
stdout, err := command.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the PowerShell's stdout stream")
|
||||
}
|
||||
|
||||
stderr, err := command.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the PowerShell's stderr stream")
|
||||
}
|
||||
|
||||
err = command.Start()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not spawn PowerShell process")
|
||||
}
|
||||
|
||||
return command, stdin, stdout, stderr, nil
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
// Copyright (c) 2017 Gorillalabs. All rights reserved.
|
||||
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// sshSession exists so we don't create a hard dependency on crypto/ssh.
|
||||
type sshSession interface {
|
||||
Waiter
|
||||
|
||||
StdinPipe() (io.WriteCloser, error)
|
||||
StdoutPipe() (io.Reader, error)
|
||||
StderrPipe() (io.Reader, error)
|
||||
Start(string) error
|
||||
}
|
||||
|
||||
type SSH struct {
|
||||
Session sshSession
|
||||
}
|
||||
|
||||
func (b *SSH) StartProcess(cmd string, args ...string) (Waiter, io.Writer, io.Reader, io.Reader, error) {
|
||||
stdin, err := b.Session.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the SSH session's stdin stream")
|
||||
}
|
||||
|
||||
stdout, err := b.Session.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the SSH session's stdout stream")
|
||||
}
|
||||
|
||||
stderr, err := b.Session.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the SSH session's stderr stream")
|
||||
}
|
||||
|
||||
err = b.Session.Start(b.createCmd(cmd, args))
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not spawn process via SSH")
|
||||
}
|
||||
|
||||
return b.Session, stdin, stdout, stderr, nil
|
||||
}
|
||||
|
||||
func (b *SSH) createCmd(cmd string, args []string) string {
|
||||
parts := []string{cmd}
|
||||
simple := regexp.MustCompile(`^[a-z0-9_/.~+-]+$`)
|
||||
|
||||
for _, arg := range args {
|
||||
if !simple.MatchString(arg) {
|
||||
arg = b.quote(arg)
|
||||
}
|
||||
|
||||
parts = append(parts, arg)
|
||||
}
|
||||
|
||||
return strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
func (b *SSH) quote(s string) string {
|
||||
return fmt.Sprintf(`"%s"`, s)
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) 2017 Gorillalabs. All rights reserved.
|
||||
|
||||
package backend
|
||||
|
||||
import "io"
|
||||
|
||||
type Waiter interface {
|
||||
Wait() error
|
||||
}
|
||||
|
||||
type Starter interface {
|
||||
StartProcess(cmd string, args ...string) (Waiter, io.Writer, io.Reader, io.Reader, error)
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
module github.com/rancher/go-powershell
|
||||
|
||||
go 1.14
|
||||
|
||||
require github.com/pkg/errors v0.9.1
|
|
@ -1,2 +0,0 @@
|
|||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
@ -1,120 +0,0 @@
|
|||
// Copyright (c) 2017 Gorillalabs. All rights reserved.
|
||||
|
||||
package powershell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"sync"
|
||||
|
||||
"github.com/rancher/go-powershell/backend"
|
||||
"github.com/rancher/go-powershell/utils"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const newline = "\r\n"
|
||||
|
||||
type Shell interface {
|
||||
Execute(cmd string) (string, string, error)
|
||||
Exit()
|
||||
}
|
||||
|
||||
type shell struct {
|
||||
handle backend.Waiter
|
||||
stdin io.Writer
|
||||
stdout io.Reader
|
||||
stderr io.Reader
|
||||
}
|
||||
|
||||
func New(backend backend.Starter) (Shell, error) {
|
||||
handle, stdin, stdout, stderr, err := backend.StartProcess("powershell.exe", "-NoExit", "-Command", "-")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &shell{handle, stdin, stdout, stderr}, nil
|
||||
}
|
||||
|
||||
func (s *shell) Execute(cmd string) (string, string, error) {
|
||||
if s.handle == nil {
|
||||
return "", "", errors.Wrap(errors.New(cmd), "Cannot execute commands on closed shells.")
|
||||
}
|
||||
|
||||
outBoundary := createBoundary()
|
||||
errBoundary := createBoundary()
|
||||
|
||||
// wrap the command in special markers so we know when to stop reading from the pipes
|
||||
full := fmt.Sprintf("%s; echo '%s'; [Console]::Error.WriteLine('%s')%s", cmd, outBoundary, errBoundary, newline)
|
||||
|
||||
_, err := s.stdin.Write([]byte(full))
|
||||
if err != nil {
|
||||
return "", "", errors.Wrap(errors.Wrap(err, cmd), "Could not send PowerShell command")
|
||||
}
|
||||
|
||||
// read stdout and stderr
|
||||
sout := ""
|
||||
serr := ""
|
||||
|
||||
waiter := &sync.WaitGroup{}
|
||||
waiter.Add(2)
|
||||
|
||||
go streamReader(s.stdout, outBoundary, &sout, waiter)
|
||||
go streamReader(s.stderr, errBoundary, &serr, waiter)
|
||||
|
||||
waiter.Wait()
|
||||
|
||||
if len(serr) > 0 {
|
||||
return sout, serr, errors.Wrap(errors.New(cmd), serr)
|
||||
}
|
||||
|
||||
return sout, serr, nil
|
||||
}
|
||||
|
||||
func (s *shell) Exit() {
|
||||
s.stdin.Write([]byte("exit" + newline))
|
||||
|
||||
// if it's possible to close stdin, do so (some backends, like the local one,
|
||||
// do support it)
|
||||
closer, ok := s.stdin.(io.Closer)
|
||||
if ok {
|
||||
closer.Close()
|
||||
}
|
||||
|
||||
s.handle.Wait()
|
||||
|
||||
s.handle = nil
|
||||
s.stdin = nil
|
||||
s.stdout = nil
|
||||
s.stderr = nil
|
||||
}
|
||||
|
||||
func streamReader(stream io.Reader, boundary string, buffer *string, signal *sync.WaitGroup) error {
|
||||
// read all output until we have found our boundary token
|
||||
output := ""
|
||||
bufsize := 64
|
||||
marker := regexp.MustCompile("(?s)(.*)" + regexp.QuoteMeta(boundary))
|
||||
|
||||
for {
|
||||
buf := make([]byte, bufsize)
|
||||
read, err := stream.Read(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
output = output + string(buf[:read])
|
||||
|
||||
if marker.MatchString(output) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
*buffer = marker.FindStringSubmatch(output)[1]
|
||||
signal.Done()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createBoundary() string {
|
||||
return "$gorilla" + utils.CreateRandomString(12) + "$"
|
||||
}
|
80
vendor/github.com/containernetworking/plugins/pkg/utils/sysctl/sysctl_linux.go
generated
vendored
Normal file
80
vendor/github.com/containernetworking/plugins/pkg/utils/sysctl/sysctl_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sysctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Sysctl provides a method to set/get values from /proc/sys - in linux systems
|
||||
// new interface to set/get values of variables formerly handled by sysctl syscall
|
||||
// If optional `params` have only one string value - this function will
|
||||
// set this value into corresponding sysctl variable
|
||||
func Sysctl(name string, params ...string) (string, error) {
|
||||
if len(params) > 1 {
|
||||
return "", fmt.Errorf("unexcepted additional parameters")
|
||||
} else if len(params) == 1 {
|
||||
return setSysctl(name, params[0])
|
||||
}
|
||||
return getSysctl(name)
|
||||
}
|
||||
|
||||
func getSysctl(name string) (string, error) {
|
||||
fullName := filepath.Join("/proc/sys", toNormalName(name))
|
||||
fullName = filepath.Clean(fullName)
|
||||
data, err := ioutil.ReadFile(fullName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(data[:len(data)-1]), nil
|
||||
}
|
||||
|
||||
func setSysctl(name, value string) (string, error) {
|
||||
fullName := filepath.Join("/proc/sys", toNormalName(name))
|
||||
fullName = filepath.Clean(fullName)
|
||||
if err := ioutil.WriteFile(fullName, []byte(value), 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return getSysctl(name)
|
||||
}
|
||||
|
||||
// Normalize names by using slash as separator
|
||||
// Sysctl names can use dots or slashes as separator:
|
||||
// - if dots are used, dots and slashes are interchanged.
|
||||
// - if slashes are used, slashes and dots are left intact.
|
||||
// Separator in use is determined by first occurrence.
|
||||
func toNormalName(name string) string {
|
||||
interchange := false
|
||||
for _, c := range name {
|
||||
if c == '.' {
|
||||
interchange = true
|
||||
break
|
||||
}
|
||||
if c == '/' {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if interchange {
|
||||
r := strings.NewReplacer(".", "/", "/", ".")
|
||||
return r.Replace(name)
|
||||
}
|
||||
return name
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
// Copyright 2015 flannel authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ip
|
||||
|
||||
import (
|
||||
netsh "github.com/rakelkar/gonetsh/netsh"
|
||||
"net"
|
||||
)
|
||||
|
||||
func GetIfaceIP4Addr(iface *net.Interface) (net.IP, error) {
|
||||
// get ip address for the interface
|
||||
// prefer global unicast to link local addresses
|
||||
netHelper := netsh.New(nil)
|
||||
ifaceDetails, err := netHelper.GetInterfaceByName(iface.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ifAddr := net.ParseIP(ifaceDetails.IpAddress)
|
||||
|
||||
return ifAddr, nil
|
||||
}
|
||||
|
||||
func GetDefaultGatewayIface() (*net.Interface, error) {
|
||||
netHelper := netsh.New(nil)
|
||||
|
||||
defaultIfaceName, err := netHelper.GetDefaultGatewayIfaceName()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iface, err := net.InterfaceByName(defaultIfaceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return iface, nil
|
||||
}
|
||||
|
||||
func GetInterfaceByIP(ip net.IP) (*net.Interface, error) {
|
||||
netHelper := netsh.New(nil)
|
||||
|
||||
ifaceDetails, err := netHelper.GetInterfaceByIP(ip.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iface, err := net.InterfaceByName(ifaceDetails.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return iface, nil
|
||||
}
|
|
@ -20,7 +20,7 @@ import (
|
|||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
)
|
||||
|
||||
type ExternalInterface struct {
|
||||
|
@ -35,7 +35,7 @@ type ExternalInterface struct {
|
|||
// needed.
|
||||
type Backend interface {
|
||||
// Called when the backend should create or begin managing a new network
|
||||
RegisterNetwork(ctx context.Context, wg sync.WaitGroup, config *subnet.Config) (Network, error)
|
||||
RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, config *subnet.Config) (Network, error)
|
||||
}
|
||||
|
||||
type Network interface {
|
|
@ -24,12 +24,11 @@ import (
|
|||
"os/exec"
|
||||
"sync"
|
||||
|
||||
log "k8s.io/klog"
|
||||
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
"golang.org/x/net/context"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -56,7 +55,7 @@ func (_ *ExtensionBackend) Run(ctx context.Context) {
|
|||
<-ctx.Done()
|
||||
}
|
||||
|
||||
func (be *ExtensionBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
func (be *ExtensionBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
n := &network{
|
||||
extIface: be.extIface,
|
||||
sm: be.sm,
|
||||
|
@ -134,9 +133,8 @@ func (be *ExtensionBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGro
|
|||
|
||||
// Run a cmd, returning a combined stdout and stderr.
|
||||
func runCmd(env []string, stdin string, name string, arg ...string) (string, error) {
|
||||
env = append(env, fmt.Sprintf("PATH=%s", os.Getenv("PATH")))
|
||||
cmd := exec.Command(name, arg...)
|
||||
cmd.Env = env
|
||||
cmd.Env = append(os.Environ(), env...)
|
||||
|
||||
stdinpipe, err := cmd.StdinPipe()
|
||||
if err != nil {
|
|
@ -18,13 +18,13 @@ import (
|
|||
"encoding/json"
|
||||
"sync"
|
||||
|
||||
log "k8s.io/klog"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"fmt"
|
||||
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
type network struct {
|
||||
|
@ -61,11 +61,12 @@ func (n *network) Run(ctx context.Context) {
|
|||
|
||||
for {
|
||||
select {
|
||||
case evtBatch := <-evts:
|
||||
case evtBatch, ok := <-evts:
|
||||
if !ok {
|
||||
log.Infof("evts chan closed")
|
||||
return
|
||||
}
|
||||
n.handleSubnetEvents(evtBatch)
|
||||
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,9 +22,9 @@ import (
|
|||
|
||||
"sync"
|
||||
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -50,7 +50,7 @@ func New(sm subnet.Manager, extIface *backend.ExternalInterface) (backend.Backen
|
|||
return be, nil
|
||||
}
|
||||
|
||||
func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
n := &backend.RouteNetwork{
|
||||
SimpleNetwork: backend.SimpleNetwork{
|
||||
ExtIface: be.extIface,
|
|
@ -16,22 +16,20 @@ package hostgw
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/pkg/routing"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rakelkar/gonetsh/netroute"
|
||||
"github.com/rakelkar/gonetsh/netsh"
|
||||
"golang.org/x/net/context"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
log "k8s.io/klog"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -56,7 +54,7 @@ func New(sm subnet.Manager, extIface *backend.ExternalInterface) (backend.Backen
|
|||
return be, nil
|
||||
}
|
||||
|
||||
func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
// 1. Parse configuration
|
||||
cfg := struct {
|
||||
Name string
|
||||
|
@ -81,11 +79,11 @@ func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
|
|||
Mtu: be.extIface.Iface.MTU,
|
||||
LinkIndex: be.extIface.Iface.Index,
|
||||
}
|
||||
n.GetRoute = func(lease *subnet.Lease) *netroute.Route {
|
||||
return &netroute.Route{
|
||||
n.GetRoute = func(lease *subnet.Lease) *routing.Route {
|
||||
return &routing.Route{
|
||||
DestinationSubnet: lease.Subnet.ToIPNet(),
|
||||
GatewayAddress: lease.Attrs.PublicIP.ToIP(),
|
||||
LinkIndex: n.LinkIndex,
|
||||
InterfaceIndex: n.LinkIndex,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +106,6 @@ func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
|
|||
}
|
||||
|
||||
// 3. Check if the network exists and has the expected settings
|
||||
netshHelper := netsh.New(utilexec.New())
|
||||
createNewNetwork := true
|
||||
expectedSubnet := n.SubnetLease.Subnet
|
||||
expectedAddressPrefix := expectedSubnet.String()
|
||||
|
@ -162,18 +159,28 @@ func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
|
|||
|
||||
// Wait for the network to populate Management IP
|
||||
log.Infof("Waiting to get ManagementIP from HNSNetwork %s", networkName)
|
||||
var newNetworkID = newNetwork.Id
|
||||
waitErr = wait.Poll(500*time.Millisecond, 30*time.Second, func() (done bool, err error) {
|
||||
newNetwork, lastErr = hcsshim.HNSNetworkRequest("GET", newNetwork.Id, "")
|
||||
newNetwork, lastErr = hcsshim.HNSNetworkRequest("GET", newNetworkID, "")
|
||||
return newNetwork != nil && len(newNetwork.ManagementIP) != 0, nil
|
||||
})
|
||||
if waitErr == wait.ErrWaitTimeout {
|
||||
// Do not swallow the root cause
|
||||
if lastErr != nil {
|
||||
waitErr = lastErr
|
||||
}
|
||||
return nil, errors.Wrapf(waitErr, "timeout, failed to get management IP from HNSNetwork %s", networkName)
|
||||
}
|
||||
|
||||
// Wait for the interface with the management IP
|
||||
log.Infof("Waiting to get net interface for HNSNetwork %s (%s)", networkName, newNetwork.ManagementIP)
|
||||
managementIP, err := ip.ParseIP4(newNetwork.ManagementIP)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to parse management ip (%s)", newNetwork.ManagementIP)
|
||||
}
|
||||
|
||||
waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
|
||||
_, lastErr = netshHelper.GetInterfaceByIP(newNetwork.ManagementIP)
|
||||
_, lastErr = ip.GetInterfaceByIP(managementIP.ToIP())
|
||||
return lastErr == nil, nil
|
||||
})
|
||||
if waitErr == wait.ErrWaitTimeout {
|
||||
|
@ -221,7 +228,15 @@ func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
|
|||
log.Infof("Waiting to attach bridge endpoint %s to host", bridgeEndpointName)
|
||||
waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
|
||||
lastErr = expectedBridgeEndpoint.HostAttach(1)
|
||||
return lastErr == nil, nil
|
||||
if lastErr == nil {
|
||||
return true, nil
|
||||
}
|
||||
// See https://github.com/flannel-io/flannel/issues/1391 and
|
||||
// hcsshim lacks some validations to detect the error, so we judge it by error message.
|
||||
if strings.Contains(lastErr.Error(), "This endpoint is already attached to the switch.") {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if waitErr == wait.ErrWaitTimeout {
|
||||
return nil, errors.Wrapf(lastErr, "failed to hot attach bridge HNSEndpoint %s to host compartment", bridgeEndpointName)
|
||||
|
@ -230,23 +245,27 @@ func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
|
|||
|
||||
// 7. Enable forwarding on the host interface and endpoint
|
||||
for _, interfaceIpAddress := range []string{expectedNetwork.ManagementIP, expectedBridgeEndpoint.IPAddress.String()} {
|
||||
netInterface, err := netshHelper.GetInterfaceByIP(interfaceIpAddress)
|
||||
ipv4, err := ip.ParseIP4(interfaceIpAddress)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to parse expected net interface ip (%s)", interfaceIpAddress)
|
||||
}
|
||||
|
||||
netInterface, err := ip.GetInterfaceByIP(ipv4.ToIP())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to find interface for IP Address %s", interfaceIpAddress)
|
||||
}
|
||||
log.Infof("Found %+v interface with IP %s", netInterface, interfaceIpAddress)
|
||||
|
||||
// When a new hns network is created, the interface is modified, esp the name, index
|
||||
if expectedNetwork.ManagementIP == netInterface.IpAddress {
|
||||
n.LinkIndex = netInterface.Idx
|
||||
if expectedNetwork.ManagementIP == ipv4.String() {
|
||||
n.LinkIndex = netInterface.Index
|
||||
n.Name = netInterface.Name
|
||||
}
|
||||
|
||||
interfaceIdx := strconv.Itoa(netInterface.Idx)
|
||||
if err := netshHelper.EnableForwarding(interfaceIdx); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to enable forwarding on %s index %s", netInterface.Name, interfaceIdx)
|
||||
if err := ip.EnableForwardingForInterface(netInterface); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to enable forwarding on %s index %d", netInterface.Name, netInterface.Index)
|
||||
}
|
||||
log.Infof("Enabled forwarding on %s index %s", netInterface.Name, interfaceIdx)
|
||||
log.Infof("Enabled forwarding on %s index %d", netInterface.Name, netInterface.Index)
|
||||
}
|
||||
|
||||
return n, nil
|
|
@ -26,9 +26,9 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/bronze1man/goStrongswanVici"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
"golang.org/x/net/context"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
type Uri struct {
|
||||
|
@ -41,15 +41,19 @@ type CharonIKEDaemon struct {
|
|||
ctx context.Context
|
||||
}
|
||||
|
||||
func NewCharonIKEDaemon(ctx context.Context, wg sync.WaitGroup, espProposal string) (*CharonIKEDaemon, error) {
|
||||
|
||||
func NewCharonIKEDaemon(ctx context.Context, wg *sync.WaitGroup, espProposal string) (*CharonIKEDaemon, error) {
|
||||
charon := &CharonIKEDaemon{ctx: ctx, espProposal: espProposal}
|
||||
|
||||
addr := strings.Split("unix:///var/run/charon.vici", "://")
|
||||
charon.viciUri = Uri{addr[0], addr[1]}
|
||||
|
||||
cmd, err := charon.runBundled("/usr/lib/strongswan/", "charon")
|
||||
execPath, err := findExecPath()
|
||||
if err != nil {
|
||||
log.Errorf("Charon daemon not found: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd, err := charon.run(execPath)
|
||||
if err != nil {
|
||||
log.Errorf("Error starting charon daemon: %v", err)
|
||||
return nil, err
|
||||
|
@ -93,13 +97,9 @@ func (charon *CharonIKEDaemon) getClient(wait bool) (client *goStrongswanVici.Cl
|
|||
}
|
||||
}
|
||||
|
||||
func (charon *CharonIKEDaemon) runBundled(staticLocation string, command string) (cmd *exec.Cmd, err error) {
|
||||
path, err := exec.LookPath(command)
|
||||
if err != nil {
|
||||
path = staticLocation + command
|
||||
}
|
||||
func (charon *CharonIKEDaemon) run(execPath string) (cmd *exec.Cmd, err error) {
|
||||
cmd = &exec.Cmd{
|
||||
Path: path,
|
||||
Path: execPath,
|
||||
SysProcAttr: &syscall.SysProcAttr{
|
||||
Pdeathsig: syscall.SIGTERM,
|
||||
},
|
||||
|
@ -234,3 +234,25 @@ func formatConnectionName(localLease, remoteLease *subnet.Lease) string {
|
|||
func formatChildSAConfName(localLease, remoteLease *subnet.Lease) string {
|
||||
return fmt.Sprintf("%s-%s", localLease.Subnet, remoteLease.Subnet)
|
||||
}
|
||||
|
||||
func findExecPath() (string, error) {
|
||||
// try well known charon paths
|
||||
paths := []string{
|
||||
"charon", // PATH
|
||||
"/usr/lib/strongswan/charon", // alpine, arch, flannel container
|
||||
"/usr/lib/ipsec/charon", // debian/ubuntu
|
||||
"/usr/libexec/strongswan/charon", // centos/rhel
|
||||
"/usr/libexec/ipsec/charon", // opensuse/sles
|
||||
}
|
||||
for _, path := range paths {
|
||||
path, err := exec.LookPath(path)
|
||||
if err != nil {
|
||||
log.Warningf("No valid charon executable found at path %s: %v", path, err)
|
||||
continue
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
|
||||
err := fmt.Errorf("No valid charon executable found at paths %v", paths)
|
||||
return "", err
|
||||
}
|
|
@ -16,13 +16,14 @@
|
|||
package ipsec
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
log "k8s.io/klog"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
"github.com/coreos/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
func AddXFRMPolicy(myLease, remoteLease *subnet.Lease, dir netlink.Dir, reqID int) error {
|
||||
|
@ -30,7 +31,7 @@ func AddXFRMPolicy(myLease, remoteLease *subnet.Lease, dir netlink.Dir, reqID in
|
|||
|
||||
dst := remoteLease.Subnet.ToIPNet()
|
||||
|
||||
policy := netlink.XfrmPolicy{
|
||||
policy := &netlink.XfrmPolicy{
|
||||
Src: src,
|
||||
Dst: dst,
|
||||
Dir: dir,
|
||||
|
@ -47,14 +48,23 @@ func AddXFRMPolicy(myLease, remoteLease *subnet.Lease, dir netlink.Dir, reqID in
|
|||
Reqid: reqID,
|
||||
}
|
||||
|
||||
log.Infof("Adding ipsec policy: %+v", tmpl)
|
||||
|
||||
policy.Tmpls = append(policy.Tmpls, tmpl)
|
||||
|
||||
if err := netlink.XfrmPolicyAdd(&policy); err != nil {
|
||||
return fmt.Errorf("error adding policy: %+v err: %v", policy, err)
|
||||
if existingPolicy, err := netlink.XfrmPolicyGet(policy); err != nil {
|
||||
if errors.Is(err, syscall.ENOENT) {
|
||||
log.Infof("Adding ipsec policy: %+v", tmpl)
|
||||
if err := netlink.XfrmPolicyAdd(policy); err != nil {
|
||||
return fmt.Errorf("error adding policy: %+v err: %v", policy, err)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("error getting policy: %+v err: %v", policy, err)
|
||||
}
|
||||
} else {
|
||||
log.Infof("Updating ipsec policy %+v with %+v", existingPolicy, policy)
|
||||
if err := netlink.XfrmPolicyUpdate(policy); err != nil {
|
||||
return fmt.Errorf("error updating policy: %+v err: %v", policy, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -20,21 +20,21 @@ import (
|
|||
"fmt"
|
||||
"sync"
|
||||
|
||||
log "k8s.io/klog"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
/*
|
||||
Flannel's approach to IPSec uses Strongswan to handle the key exchange (using IKEv2) and the kernel to handle the
|
||||
actual encryption.
|
||||
|
||||
Strongswan's "charon" is bundled in the flannel container. Flannel runs it as a child process when the ipsec backend
|
||||
is selected and communicates with it using the "VICI" interface. Strongswan ships a utility "swanctl" which also
|
||||
uses the VICI interface. This utility is bundled in the flannel container and can help with debugging.
|
||||
Flannel runs Strongswan's "charon" as a child process when the ipsec backend is selected and communicates with it
|
||||
using the "VICI" interface. Strongswan ships a utility "swanctl" which also uses the VICI interface. This utility
|
||||
is bundled in the flannel container and can help with debugging.
|
||||
|
||||
The file "handle_charon.go" contains the logic for working with the charon. It supports creating a "CharonIKEDaemon"
|
||||
which supports loading the PSK into the charon and adding and removing connections.
|
||||
|
@ -70,7 +70,7 @@ func New(sm subnet.Manager, extIface *backend.ExternalInterface) (
|
|||
}
|
||||
|
||||
func (be *IPSECBackend) RegisterNetwork(
|
||||
ctx context.Context, wg sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
ctx context.Context, wg *sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
|
||||
cfg := struct {
|
||||
UDPEncap bool
|
|
@ -21,12 +21,11 @@ import (
|
|||
"strconv"
|
||||
"sync"
|
||||
|
||||
log "k8s.io/klog"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -95,12 +94,13 @@ func (n *network) Run(ctx context.Context) {
|
|||
|
||||
for {
|
||||
select {
|
||||
case evtsBatch := <-evts:
|
||||
case evtsBatch, ok := <-evts:
|
||||
if !ok {
|
||||
log.Infof("evts chan closed")
|
||||
return
|
||||
}
|
||||
log.Info("Handling event")
|
||||
n.handleSubnetEvents(evtsBatch)
|
||||
case <-ctx.Done():
|
||||
log.Info("Received DONE")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ import (
|
|||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
)
|
||||
|
||||
var constructors = make(map[string]BackendCtor)
|
|
@ -22,11 +22,11 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
log "k8s.io/klog"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
"github.com/vishvananda/netlink"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -69,11 +69,12 @@ func (n *RouteNetwork) Run(ctx context.Context) {
|
|||
|
||||
for {
|
||||
select {
|
||||
case evtBatch := <-evts:
|
||||
case evtBatch, ok := <-evts:
|
||||
if !ok {
|
||||
log.Infof("evts chan closed")
|
||||
return
|
||||
}
|
||||
n.handleSubnetEvents(evtBatch)
|
||||
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,15 +15,15 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "k8s.io/klog"
|
||||
"github.com/rakelkar/gonetsh/netroute"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"strings"
|
||||
"github.com/flannel-io/flannel/pkg/routing"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -35,10 +35,10 @@ type RouteNetwork struct {
|
|||
Name string
|
||||
BackendType string
|
||||
SM subnet.Manager
|
||||
GetRoute func(lease *subnet.Lease) *netroute.Route
|
||||
GetRoute func(lease *subnet.Lease) *routing.Route
|
||||
Mtu int
|
||||
LinkIndex int
|
||||
routes []netroute.Route
|
||||
routes []routing.Route
|
||||
}
|
||||
|
||||
func (n *RouteNetwork) MTU() int {
|
||||
|
@ -56,7 +56,7 @@ func (n *RouteNetwork) Run(ctx context.Context) {
|
|||
wg.Done()
|
||||
}()
|
||||
|
||||
n.routes = make([]netroute.Route, 0, 10)
|
||||
n.routes = make([]routing.Route, 0, 10)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
n.routeCheck(ctx)
|
||||
|
@ -67,17 +67,18 @@ func (n *RouteNetwork) Run(ctx context.Context) {
|
|||
|
||||
for {
|
||||
select {
|
||||
case evtBatch := <-evts:
|
||||
case evtBatch, ok := <-evts:
|
||||
if !ok {
|
||||
log.Infof("evts chan closed")
|
||||
return
|
||||
}
|
||||
n.handleSubnetEvents(evtBatch)
|
||||
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *RouteNetwork) handleSubnetEvents(batch []subnet.Event) {
|
||||
netrouteHelper := netroute.New()
|
||||
router := routing.RouterWindows{}
|
||||
|
||||
for _, evt := range batch {
|
||||
leaseSubnet := evt.Lease.Subnet
|
||||
|
@ -93,7 +94,7 @@ func (n *RouteNetwork) handleSubnetEvents(batch []subnet.Event) {
|
|||
case subnet.EventAdded:
|
||||
log.Infof("Subnet added: %v via %v", leaseSubnet, leaseAttrs.PublicIP)
|
||||
|
||||
existingRoutes, _ := netrouteHelper.GetNetRoutes(expectedRoute.LinkIndex, expectedRoute.DestinationSubnet)
|
||||
existingRoutes, _ := router.GetRoutesFromInterfaceToSubnet(expectedRoute.InterfaceIndex, expectedRoute.DestinationSubnet)
|
||||
if len(existingRoutes) > 0 {
|
||||
existingRoute := existingRoutes[0]
|
||||
if existingRoute.Equal(*expectedRoute) {
|
||||
|
@ -101,14 +102,14 @@ func (n *RouteNetwork) handleSubnetEvents(batch []subnet.Event) {
|
|||
}
|
||||
|
||||
log.Warningf("Replacing existing route %v via %v with %v via %v", leaseSubnet, existingRoute.GatewayAddress, leaseSubnet, leaseAttrs.PublicIP)
|
||||
err := netrouteHelper.RemoveNetRoute(existingRoute.LinkIndex, existingRoute.DestinationSubnet, existingRoute.GatewayAddress)
|
||||
err := router.DeleteRoute(existingRoute.InterfaceIndex, existingRoute.DestinationSubnet, existingRoute.GatewayAddress)
|
||||
if err != nil {
|
||||
log.Errorf("Error removing route: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
err := netrouteHelper.NewNetRoute(expectedRoute.LinkIndex, expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress)
|
||||
err := router.CreateRoute(expectedRoute.InterfaceIndex, expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress)
|
||||
if err != nil {
|
||||
log.Errorf("Error creating route: %v", err)
|
||||
continue
|
||||
|
@ -119,13 +120,13 @@ func (n *RouteNetwork) handleSubnetEvents(batch []subnet.Event) {
|
|||
case subnet.EventRemoved:
|
||||
log.Infof("Subnet removed: %v", leaseSubnet)
|
||||
|
||||
existingRoutes, _ := netrouteHelper.GetNetRoutes(expectedRoute.LinkIndex, expectedRoute.DestinationSubnet)
|
||||
existingRoutes, _ := router.GetRoutesFromInterfaceToSubnet(expectedRoute.InterfaceIndex, expectedRoute.DestinationSubnet)
|
||||
if len(existingRoutes) > 0 {
|
||||
existingRoute := existingRoutes[0]
|
||||
if existingRoute.Equal(*expectedRoute) {
|
||||
log.Infof("Removing existing route %v via %v", leaseSubnet, existingRoute.GatewayAddress)
|
||||
|
||||
err := netrouteHelper.RemoveNetRoute(existingRoute.LinkIndex, existingRoute.DestinationSubnet, existingRoute.GatewayAddress)
|
||||
err := router.DeleteRoute(existingRoute.InterfaceIndex, existingRoute.DestinationSubnet, existingRoute.GatewayAddress)
|
||||
if err != nil {
|
||||
log.Warningf("Error removing route: %v", err)
|
||||
}
|
||||
|
@ -140,7 +141,7 @@ func (n *RouteNetwork) handleSubnetEvents(batch []subnet.Event) {
|
|||
}
|
||||
}
|
||||
|
||||
func (n *RouteNetwork) addToRouteList(newRoute *netroute.Route) {
|
||||
func (n *RouteNetwork) addToRouteList(newRoute *routing.Route) {
|
||||
for _, route := range n.routes {
|
||||
if route.Equal(*newRoute) {
|
||||
return
|
||||
|
@ -150,7 +151,7 @@ func (n *RouteNetwork) addToRouteList(newRoute *netroute.Route) {
|
|||
n.routes = append(n.routes, *newRoute)
|
||||
}
|
||||
|
||||
func (n *RouteNetwork) removeFromRouteList(oldRoute *netroute.Route) {
|
||||
func (n *RouteNetwork) removeFromRouteList(oldRoute *routing.Route) {
|
||||
for index, route := range n.routes {
|
||||
if route.Equal(*oldRoute) {
|
||||
n.routes = append(n.routes[:index], n.routes[index+1:]...)
|
||||
|
@ -171,9 +172,9 @@ func (n *RouteNetwork) routeCheck(ctx context.Context) {
|
|||
}
|
||||
|
||||
func (n *RouteNetwork) checkSubnetExistInRoutes() {
|
||||
netrouteHelper := netroute.New()
|
||||
router := routing.RouterWindows{}
|
||||
|
||||
existingRoutes, err := netrouteHelper.GetNetRoutesAll()
|
||||
existingRoutes, err := router.GetAllRoutes()
|
||||
if err != nil {
|
||||
log.Errorf("Error enumerating routes: %v", err)
|
||||
return
|
||||
|
@ -188,12 +189,12 @@ func (n *RouteNetwork) checkSubnetExistInRoutes() {
|
|||
}
|
||||
|
||||
if !exist {
|
||||
err := netrouteHelper.NewNetRoute(expectedRoute.LinkIndex, expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress)
|
||||
err := router.CreateRoute(expectedRoute.InterfaceIndex, expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress)
|
||||
if err != nil {
|
||||
log.Warningf("Error recovering route to %v via %v on %v (%v).", expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress, expectedRoute.LinkIndex, err)
|
||||
log.Warningf("Error recovering route to %v via %v on %v (%v).", expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress, expectedRoute.InterfaceIndex, err)
|
||||
continue
|
||||
}
|
||||
log.Infof("Recovered route to %v via %v on %v.", expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress, expectedRoute.LinkIndex)
|
||||
log.Infof("Recovered route to %v via %v on %v.", expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress, expectedRoute.InterfaceIndex)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ package backend
|
|||
import (
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
)
|
||||
|
||||
type SimpleNetwork struct {
|
|
@ -13,7 +13,6 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// +build !windows
|
||||
|
||||
package vxlan
|
||||
|
||||
|
@ -22,10 +21,11 @@ import (
|
|||
"net"
|
||||
"syscall"
|
||||
|
||||
log "k8s.io/klog"
|
||||
"github.com/containernetworking/plugins/pkg/utils/sysctl"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/pkg/mac"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
type vxlanDeviceAttrs struct {
|
||||
|
@ -44,9 +44,15 @@ type vxlanDevice struct {
|
|||
}
|
||||
|
||||
func newVXLANDevice(devAttrs *vxlanDeviceAttrs) (*vxlanDevice, error) {
|
||||
hardwareAddr, err := mac.NewHardwareAddr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
link := &netlink.Vxlan{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: devAttrs.name,
|
||||
Name: devAttrs.name,
|
||||
HardwareAddr: hardwareAddr,
|
||||
},
|
||||
VxlanId: int(devAttrs.vni),
|
||||
VtepDevIndex: devAttrs.vtepIndex,
|
||||
|
@ -56,10 +62,13 @@ func newVXLANDevice(devAttrs *vxlanDeviceAttrs) (*vxlanDevice, error) {
|
|||
GBP: devAttrs.gbp,
|
||||
}
|
||||
|
||||
link, err := ensureLink(link)
|
||||
link, err = ensureLink(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv6/conf/%s/accept_ra", devAttrs.name), "0")
|
||||
|
||||
return &vxlanDevice{
|
||||
link: link,
|
||||
}, nil
|
||||
|
@ -109,8 +118,8 @@ func ensureLink(vxlan *netlink.Vxlan) (*netlink.Vxlan, error) {
|
|||
return vxlan, nil
|
||||
}
|
||||
|
||||
func (dev *vxlanDevice) Configure(ipn ip.IP4Net) error {
|
||||
if err := ip.EnsureV4AddressOnLink(ipn, dev.link); err != nil {
|
||||
func (dev *vxlanDevice) Configure(ipa ip.IP4Net, flannelnet ip.IP4Net) error {
|
||||
if err := ip.EnsureV4AddressOnLink(ipa, flannelnet, dev.link); err != nil {
|
||||
return fmt.Errorf("failed to ensure address of interface %s: %s", dev.link.Attrs().Name, err)
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// +build windows
|
||||
|
||||
package vxlan
|
||||
|
||||
|
@ -19,12 +20,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/Microsoft/hcsshim/hcn"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rakelkar/gonetsh/netsh"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
log "k8s.io/klog"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
type vxlanDeviceAttrs struct {
|
||||
|
@ -123,20 +122,29 @@ func ensureNetwork(expectedNetwork *hcn.HostComputeNetwork, expectedAddressPrefi
|
|||
var waitErr, lastErr error
|
||||
// Wait for the network to populate Management IP
|
||||
log.Infof("Waiting to get ManagementIP from HostComputeNetwork %s", networkName)
|
||||
var newNetworkID = newNetwork.Id
|
||||
waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
|
||||
newNetwork, lastErr = hcn.GetNetworkByID(newNetwork.Id)
|
||||
newNetwork, lastErr = hcn.GetNetworkByID(newNetworkID)
|
||||
return newNetwork != nil && len(getManagementIP(newNetwork)) != 0, nil
|
||||
})
|
||||
if waitErr == wait.ErrWaitTimeout {
|
||||
// Do not swallow the root cause
|
||||
if lastErr != nil {
|
||||
waitErr = lastErr
|
||||
}
|
||||
return nil, errors.Wrapf(lastErr, "timeout, failed to get management IP from HostComputeNetwork %s", networkName)
|
||||
}
|
||||
|
||||
managementIP := getManagementIP(newNetwork)
|
||||
// Wait for the interface with the management IP
|
||||
netshHelper := netsh.New(utilexec.New())
|
||||
log.Infof("Waiting to get net interface for HostComputeNetwork %s (%s)", networkName, managementIP)
|
||||
managementIPv4, err := ip.ParseIP4(managementIP)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to parse management ip (%s)", managementIP)
|
||||
}
|
||||
|
||||
waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
|
||||
_, lastErr = netshHelper.GetInterfaceByIP(managementIP)
|
||||
_, lastErr = ip.GetInterfaceByIP(managementIPv4.ToIP())
|
||||
return lastErr == nil, nil
|
||||
})
|
||||
if waitErr == wait.ErrWaitTimeout {
|
|
@ -55,15 +55,15 @@ package vxlan
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
log "k8s.io/klog"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -88,8 +88,10 @@ func New(sm subnet.Manager, extIface *backend.ExternalInterface) (backend.Backen
|
|||
return backend, nil
|
||||
}
|
||||
|
||||
func newSubnetAttrs(publicIP net.IP, mac net.HardwareAddr) (*subnet.LeaseAttrs, error) {
|
||||
data, err := json.Marshal(&vxlanLeaseAttrs{hardwareAddr(mac)})
|
||||
func newSubnetAttrs(publicIP net.IP, vnid uint16, mac net.HardwareAddr) (*subnet.LeaseAttrs, error) {
|
||||
data, err := json.Marshal(&vxlanLeaseAttrs{
|
||||
VNI: vnid,
|
||||
VtepMAC: hardwareAddr(mac)})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -101,7 +103,7 @@ func newSubnetAttrs(publicIP net.IP, mac net.HardwareAddr) (*subnet.LeaseAttrs,
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
// Parse our configuration
|
||||
cfg := struct {
|
||||
VNI int
|
||||
|
@ -136,7 +138,7 @@ func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
|
|||
}
|
||||
dev.directRouting = cfg.DirectRouting
|
||||
|
||||
subnetAttrs, err := newSubnetAttrs(be.extIface.ExtAddr, dev.MACAddr())
|
||||
subnetAttrs, err := newSubnetAttrs(be.extIface.ExtAddr, uint16(cfg.VNI), dev.MACAddr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -153,7 +155,7 @@ func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
|
|||
// Ensure that the device has a /32 address so that no broadcast routes are created.
|
||||
// This IP is just used as a source address for host to workload traffic (so
|
||||
// the return path for the traffic has an address on the flannel network to use as the destination)
|
||||
if err := dev.Configure(ip.IP4Net{IP: lease.Subnet.IP, PrefixLen: 32}); err != nil {
|
||||
if err := dev.Configure(ip.IP4Net{IP: lease.Subnet.IP, PrefixLen: 32}, config.Network); err != nil {
|
||||
return nil, fmt.Errorf("failed to configure interface %s: %s", dev.link.Attrs().Name, err)
|
||||
}
|
||||
|
|
@ -19,16 +19,15 @@ import (
|
|||
"encoding/json"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
log "k8s.io/klog"
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"syscall"
|
||||
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
"github.com/vishvananda/netlink"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
type network struct {
|
||||
|
@ -70,11 +69,12 @@ func (nw *network) Run(ctx context.Context) {
|
|||
|
||||
for {
|
||||
select {
|
||||
case evtBatch := <-events:
|
||||
case evtBatch, ok := <-events:
|
||||
if !ok {
|
||||
log.Infof("evts chan closed")
|
||||
return
|
||||
}
|
||||
nw.handleSubnetEvents(evtBatch)
|
||||
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ func (nw *network) MTU() int {
|
|||
}
|
||||
|
||||
type vxlanLeaseAttrs struct {
|
||||
VNI uint16
|
||||
VtepMAC hardwareAddr
|
||||
}
|
||||
|
|
@ -15,18 +15,18 @@
|
|||
package vxlan
|
||||
|
||||
import (
|
||||
log "k8s.io/klog"
|
||||
"golang.org/x/net/context"
|
||||
"sync"
|
||||
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
|
||||
"encoding/json"
|
||||
"github.com/Microsoft/hcsshim/hcn"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/Microsoft/hcsshim/hcn"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
type network struct {
|
||||
|
@ -73,11 +73,12 @@ func (nw *network) Run(ctx context.Context) {
|
|||
|
||||
for {
|
||||
select {
|
||||
case evtBatch := <-events:
|
||||
case evtBatch, ok := <-events:
|
||||
if !ok {
|
||||
log.Infof("evts chan closed")
|
||||
return
|
||||
}
|
||||
nw.handleSubnetEvents(evtBatch)
|
||||
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +102,11 @@ func (nw *network) handleSubnetEvents(batch []subnet.Event) {
|
|||
continue
|
||||
}
|
||||
|
||||
if vxlanAttrs.VNI < 4096 {
|
||||
log.Error("VNI is required to greater than or equal to 4096 on Windows.")
|
||||
continue
|
||||
}
|
||||
|
||||
hnsnetwork, err := hcn.GetNetworkByName(nw.dev.link.Name)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to find network %v, error: %v", nw.dev.link.Name, err)
|
||||
|
@ -109,7 +115,7 @@ func (nw *network) handleSubnetEvents(batch []subnet.Event) {
|
|||
managementIp := event.Lease.Attrs.PublicIP.String()
|
||||
|
||||
networkPolicySettings := hcn.RemoteSubnetRoutePolicySetting{
|
||||
IsolationId: 4096,
|
||||
IsolationId: vxlanAttrs.VNI,
|
||||
DistributedRouterMacAddress: net.HardwareAddr(vxlanAttrs.VtepMAC).String(),
|
||||
ProviderAddress: managementIp,
|
||||
DestinationPrefix: event.Lease.Subnet.String(),
|
|
@ -27,17 +27,16 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
log "k8s.io/klog"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/Microsoft/hcsshim/hcn"
|
||||
"github.com/coreos/flannel/backend"
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"net"
|
||||
"github.com/flannel-io/flannel/backend"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -84,7 +83,7 @@ func newSubnetAttrs(publicIP net.IP, vnid uint16, mac net.HardwareAddr) (*subnet
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
|
||||
// 1. Parse configuration
|
||||
cfg := struct {
|
||||
Name string
|
||||
|
@ -191,7 +190,10 @@ func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
|
|||
}
|
||||
|
||||
lease, err = be.subnetMgr.AcquireLease(ctx, subnetAttrs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
network.SubnetLease = lease
|
||||
return network, nil
|
||||
}
|
||||
|
|
@ -18,14 +18,12 @@ package network
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
log "k8s.io/klog"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/coreos/go-iptables/iptables"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
type IPTables interface {
|
||||
|
@ -34,6 +32,11 @@ type IPTables interface {
|
|||
Exists(table string, chain string, rulespec ...string) (bool, error)
|
||||
}
|
||||
|
||||
type IPTablesError interface {
|
||||
IsNotExist() bool
|
||||
Error() string
|
||||
}
|
||||
|
||||
type IPTablesRule struct {
|
||||
table string
|
||||
chain string
|
||||
|
@ -143,7 +146,9 @@ func ensureIPTables(ipt IPTables, rules []IPTablesRule) error {
|
|||
// Otherwise, teardown all the rules and set them up again
|
||||
// We do this because the order of the rules is important
|
||||
log.Info("Some iptables rules are missing; deleting and recreating rules")
|
||||
teardownIPTables(ipt, rules)
|
||||
if err = teardownIPTables(ipt, rules); err != nil {
|
||||
return fmt.Errorf("Error tearing down rules: %v", err)
|
||||
}
|
||||
if err = setupIPTables(ipt, rules); err != nil {
|
||||
return fmt.Errorf("Error setting up rules: %v", err)
|
||||
}
|
||||
|
@ -162,11 +167,23 @@ func setupIPTables(ipt IPTables, rules []IPTablesRule) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func teardownIPTables(ipt IPTables, rules []IPTablesRule) {
|
||||
func teardownIPTables(ipt IPTables, rules []IPTablesRule) error {
|
||||
for _, rule := range rules {
|
||||
log.Info("Deleting iptables rule: ", strings.Join(rule.rulespec, " "))
|
||||
// We ignore errors here because if there's an error it's almost certainly because the rule
|
||||
// doesn't exist, which is fine (we don't need to delete rules that don't exist)
|
||||
ipt.Delete(rule.table, rule.chain, rule.rulespec...)
|
||||
err := ipt.Delete(rule.table, rule.chain, rule.rulespec...)
|
||||
if err != nil {
|
||||
e := err.(IPTablesError)
|
||||
// If this error is because the rule is already deleted, the message from iptables will be
|
||||
// "Bad rule (does a matching rule exist in that chain?)". These are safe to ignore.
|
||||
// However other errors (like EAGAIN caused by other things not respecting the xtables.lock)
|
||||
// should halt the ensure process. Otherwise rules can get out of order when a rule we think
|
||||
// is deleted is actually still in the chain.
|
||||
// This will leave the rules incomplete until the next successful reconciliation loop.
|
||||
if !e.IsNotExist() {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -15,8 +15,8 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
)
|
||||
|
||||
type IPTables interface {
|
|
@ -13,7 +13,6 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// +build !windows
|
||||
|
||||
package ip
|
||||
|
||||
|
@ -24,6 +23,7 @@ import (
|
|||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
func getIfaceAddrs(iface *net.Interface) ([]netlink.Addr, error) {
|
||||
|
@ -36,7 +36,7 @@ func getIfaceAddrs(iface *net.Interface) ([]netlink.Addr, error) {
|
|||
return netlink.AddrList(link, syscall.AF_INET)
|
||||
}
|
||||
|
||||
func GetIfaceIP4Addr(iface *net.Interface) (net.IP, error) {
|
||||
func GetInterfaceIP4Addr(iface *net.Interface) (net.IP, error) {
|
||||
addrs, err := getIfaceAddrs(iface)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -67,7 +67,7 @@ func GetIfaceIP4Addr(iface *net.Interface) (net.IP, error) {
|
|||
return nil, errors.New("No IPv4 address found for given interface")
|
||||
}
|
||||
|
||||
func GetIfaceIP4AddrMatch(iface *net.Interface, matchAddr net.IP) error {
|
||||
func GetInterfaceIP4AddrMatch(iface *net.Interface, matchAddr net.IP) error {
|
||||
addrs, err := getIfaceAddrs(iface)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -86,7 +86,7 @@ func GetIfaceIP4AddrMatch(iface *net.Interface, matchAddr net.IP) error {
|
|||
return errors.New("No IPv4 address found for given interface")
|
||||
}
|
||||
|
||||
func GetDefaultGatewayIface() (*net.Interface, error) {
|
||||
func GetDefaultGatewayInterface() (*net.Interface, error) {
|
||||
routes, err := netlink.RouteList(nil, syscall.AF_INET)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -111,7 +111,7 @@ func GetInterfaceByIP(ip net.IP) (*net.Interface, error) {
|
|||
}
|
||||
|
||||
for _, iface := range ifaces {
|
||||
err := GetIfaceIP4AddrMatch(&iface, ip)
|
||||
err := GetInterfaceIP4AddrMatch(&iface, ip)
|
||||
if err == nil {
|
||||
return &iface, nil
|
||||
}
|
||||
|
@ -132,52 +132,33 @@ func DirectRouting(ip net.IP) (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
func linkAddrsAndRemoveLinkLocal(link netlink.Link) ([]netlink.Addr, error) {
|
||||
// EnsureV4AddressOnLink ensures that there is only one v4 Addr on `link` within the `ipn` address space and it equals `ipa`.
|
||||
func EnsureV4AddressOnLink(ipa IP4Net, ipn IP4Net, link netlink.Link) error {
|
||||
addr := netlink.Addr{IPNet: ipa.ToIPNet()}
|
||||
existingAddrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []netlink.Addr
|
||||
for _, addr := range existingAddrs {
|
||||
if addr.IP.IsLinkLocalUnicast() {
|
||||
if err := netlink.AddrDel(link, &addr); err != nil {
|
||||
return nil, fmt.Errorf("failed to remove IP address %s from %s: %s", addr.IP.String(), link.Attrs().Name, err)
|
||||
}
|
||||
} else {
|
||||
result = append(result, addr)
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// EnsureV4AddressOnLink ensures that there is only one v4 Addr on `link` and it equals `ipn`.
|
||||
// If there exist multiple addresses on link, it returns an error message to tell callers to remove additional address.
|
||||
func EnsureV4AddressOnLink(ipn IP4Net, link netlink.Link) error {
|
||||
addr := netlink.Addr{IPNet: ipn.ToIPNet()}
|
||||
existingAddrs, err := linkAddrsAndRemoveLinkLocal(link)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// flannel will never make this happen. This situation can only be caused by a user, so get them to sort it out.
|
||||
if len(existingAddrs) > 1 {
|
||||
return fmt.Errorf("link has incompatible addresses. Remove additional addresses and try again. %#v", link)
|
||||
}
|
||||
|
||||
// If the device has an incompatible address then delete it. This can happen if the lease changes for example.
|
||||
if len(existingAddrs) == 1 && !existingAddrs[0].Equal(addr) {
|
||||
if err := netlink.AddrDel(link, &existingAddrs[0]); err != nil {
|
||||
return fmt.Errorf("failed to remove IP address %s from %s: %s", ipn.String(), link.Attrs().Name, err)
|
||||
var hasAddr bool
|
||||
for _, existingAddr := range existingAddrs {
|
||||
if existingAddr.Equal(addr) {
|
||||
hasAddr = true
|
||||
continue
|
||||
}
|
||||
|
||||
if ipn.Contains(FromIP(existingAddr.IP)) {
|
||||
if err := netlink.AddrDel(link, &existingAddr); err != nil {
|
||||
return fmt.Errorf("failed to remove IP address %s from %s: %s", existingAddr.String(), link.Attrs().Name, err)
|
||||
}
|
||||
log.Infof("removed IP address %s from %s", existingAddr.String(), link.Attrs().Name)
|
||||
}
|
||||
existingAddrs = []netlink.Addr{}
|
||||
}
|
||||
|
||||
// Actually add the desired address to the interface if needed.
|
||||
if len(existingAddrs) == 0 {
|
||||
if !hasAddr {
|
||||
if err := netlink.AddrAdd(link, &addr); err != nil {
|
||||
return fmt.Errorf("failed to add IP address %s to %s: %s", ipn.String(), link.Attrs().Name, err)
|
||||
return fmt.Errorf("failed to add IP address %s to %s: %s", addr.String(), link.Attrs().Name, err)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
// +build windows
|
||||
|
||||
// Copyright 2015 flannel authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ip
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/flannel-io/flannel/pkg/powershell"
|
||||
"net"
|
||||
)
|
||||
|
||||
// GetInterfaceIP4Addr returns the IPv4 address for the given network interface
|
||||
func GetInterfaceIP4Addr(iface *net.Interface) (net.IP, error) {
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
var ip net.IP
|
||||
switch v := addr.(type) {
|
||||
case *net.IPAddr:
|
||||
ip = v.IP
|
||||
case *net.IPNet:
|
||||
ip = v.IP
|
||||
}
|
||||
|
||||
if ip != nil && ip.To4() != nil {
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("no IPv4 address found for given interface")
|
||||
}
|
||||
|
||||
// GetDefaultGatewayInterface returns the first network interface found with a default gateway set
|
||||
func GetDefaultGatewayInterface() (*net.Interface, error) {
|
||||
index, err := getDefaultGatewayInterfaceIndex()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return net.InterfaceByIndex(index)
|
||||
}
|
||||
|
||||
func getDefaultGatewayInterfaceIndex() (int, error) {
|
||||
powerShellJsonData := struct {
|
||||
IfIndex int `json:"ifIndex"`
|
||||
}{-1}
|
||||
|
||||
err := powershell.RunCommandWithJsonResult("Get-NetRoute | Where { $_.DestinationPrefix -eq '0.0.0.0/0' } | Select-Object -Property ifIndex", &powerShellJsonData)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
if powerShellJsonData.IfIndex < 0 {
|
||||
return -1, errors.New("unable to find default gateway interface index")
|
||||
}
|
||||
|
||||
return powerShellJsonData.IfIndex, nil
|
||||
}
|
||||
|
||||
// GetInterfaceByIP tries to get the network interface with the given ip address
|
||||
func GetInterfaceByIP(search net.IP) (*net.Interface, error) {
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, i := range ifaces {
|
||||
addrs, err := i.Addrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
var ip net.IP
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = v.IP
|
||||
case *net.IPAddr:
|
||||
ip = v.IP
|
||||
}
|
||||
|
||||
if ip != nil && ip.Equal(search) {
|
||||
return &i, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("no interface with given IP found")
|
||||
}
|
||||
|
||||
// EnableForwardingForInterface enables forwarding for given interface.
|
||||
// The process must run with elevated rights. Otherwise the function will fail with an "Access Denied" error.
|
||||
func EnableForwardingForInterface(iface *net.Interface) error {
|
||||
return setForwardingForInterface(iface, true)
|
||||
}
|
||||
|
||||
// DisableForwardingForInterface disables forwarding for given interface.
|
||||
// The process must run with elevated rights. Otherwise the function will fail with an "Access Denied" error.
|
||||
func DisableForwardingForInterface(iface *net.Interface) error {
|
||||
return setForwardingForInterface(iface, false)
|
||||
}
|
||||
|
||||
func setForwardingForInterface(iface *net.Interface, forwarding bool) error {
|
||||
value := "Enabled"
|
||||
if !forwarding {
|
||||
value = "Disabled"
|
||||
}
|
||||
|
||||
_, err := powershell.RunCommandf("Set-NetIPInterface -ifIndex %d -AddressFamily IPv4 -Forwarding %s", iface.Index, value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsForwardingEnabledForInterface(iface *net.Interface) (bool, error) {
|
||||
powerShellJsonData := struct {
|
||||
Forwarding int `json:"Forwarding"`
|
||||
}{0}
|
||||
|
||||
err := powershell.RunCommandWithJsonResult(fmt.Sprintf("Get-NetIPInterface -ifIndex %d -AddressFamily IPv4 | Select-Object -Property Forwarding", iface.Index), &powerShellJsonData)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return powerShellJsonData.Forwarding == 1, nil
|
||||
}
|
|
@ -31,7 +31,13 @@ func FromBytes(ip []byte) IP4 {
|
|||
}
|
||||
|
||||
func FromIP(ip net.IP) IP4 {
|
||||
return FromBytes(ip.To4())
|
||||
ipv4 := ip.To4()
|
||||
|
||||
if ipv4 == nil {
|
||||
panic("Address is not an IPv4 address")
|
||||
}
|
||||
|
||||
return FromBytes(ipv4)
|
||||
}
|
||||
|
||||
func ParseIP4(s string) (IP4, error) {
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2021 flannel authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package mac
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
// NewHardwareAddr generates a new random hardware (MAC) address, local and
|
||||
// unicast.
|
||||
func NewHardwareAddr() (net.HardwareAddr, error) {
|
||||
hardwareAddr := make(net.HardwareAddr, 6)
|
||||
if _, err := rand.Read(hardwareAddr); err != nil {
|
||||
return nil, fmt.Errorf("could not generate random MAC address: %w", err)
|
||||
}
|
||||
|
||||
// Ensure that address is locally administered and unicast.
|
||||
hardwareAddr[0] = (hardwareAddr[0] & 0xfe) | 0x02
|
||||
|
||||
return hardwareAddr, nil
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
// +build windows
|
||||
|
||||
// Copyright 2015 flannel authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package powershell
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//commandWrapper ensures that exceptions are written to stdout and the powershell process exit code is -1
|
||||
const commandWrapper = `$ErrorActionPreference="Stop";try { %s } catch { Write-Host $_; os.Exit(-1) }`
|
||||
|
||||
// RunCommand executes a given powershell command.
|
||||
//
|
||||
// When the command throws a powershell exception, RunCommand will return the exception message as error.
|
||||
func RunCommand(command string) ([]byte, error) {
|
||||
cmd := exec.Command("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", fmt.Sprintf(commandWrapper, command))
|
||||
|
||||
stdout, err := cmd.Output()
|
||||
if err != nil {
|
||||
if cmd.ProcessState.ExitCode() != 0 {
|
||||
message := strings.TrimSpace(string(stdout))
|
||||
return []byte{}, errors.New(message)
|
||||
}
|
||||
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
return stdout, nil
|
||||
}
|
||||
|
||||
// RunCommandf executes a given powershell command. Command argument formats according to a format specifier (See fmt.Sprintf).
|
||||
//
|
||||
// When the command throws a powershell exception, RunCommandf will return the exception message as error.
|
||||
func RunCommandf(command string, a ...interface{}) ([]byte, error) {
|
||||
return RunCommand(fmt.Sprintf(command, a...))
|
||||
}
|
||||
|
||||
// RunCommandWithJsonResult executes a given powershell command.
|
||||
// The command will be wrapped with ConvertTo-Json.
|
||||
//
|
||||
// You can Wrap your command with @(<cmd>) to ensure that the returned json is an array
|
||||
//
|
||||
// When the command throws a powershell exception, RunCommandf will return the exception message as error.
|
||||
func RunCommandWithJsonResult(command string, v interface{}) error {
|
||||
wrappedCommand := fmt.Sprintf(commandWrapper, "ConvertTo-Json (%s)")
|
||||
wrappedCommand = fmt.Sprintf(wrappedCommand, command)
|
||||
|
||||
stdout, err := RunCommandf(wrappedCommand)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(stdout, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2015 flannel authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package routing
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Router manages network routes
|
||||
type Router interface {
|
||||
// GetAllRoutes returns all existing routes
|
||||
GetAllRoutes() ([]Route, error)
|
||||
|
||||
// GetRoutesFromInterfaceToSubnet returns all routes from the given Interface to the given subnet
|
||||
GetRoutesFromInterfaceToSubnet(interfaceIndex int, destinationSubnet *net.IPNet) ([]Route, error)
|
||||
|
||||
// CreateRoute creates a new route
|
||||
CreateRoute(interfaceIndex int, destinationSubnet *net.IPNet, gatewayAddress net.IP) error
|
||||
|
||||
// DeleteRoute removes an existing route
|
||||
DeleteRoute(interfaceIndex int, destinationSubnet *net.IPNet, gatewayAddress net.IP) error
|
||||
}
|
||||
|
||||
// Route present a specific route
|
||||
type Route struct {
|
||||
InterfaceIndex int
|
||||
DestinationSubnet *net.IPNet
|
||||
GatewayAddress net.IP
|
||||
}
|
||||
|
||||
func (r *Route) Equal(other Route) bool {
|
||||
return r.DestinationSubnet.IP.Equal(other.DestinationSubnet.IP) && bytes.Equal(r.DestinationSubnet.Mask, other.DestinationSubnet.Mask) && r.GatewayAddress.Equal(other.GatewayAddress)
|
||||
}
|
83
vendor/github.com/flannel-io/flannel/pkg/routing/router_windows.go
generated
vendored
Normal file
83
vendor/github.com/flannel-io/flannel/pkg/routing/router_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
// +build windows
|
||||
|
||||
// Copyright 2015 flannel authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package routing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/flannel-io/flannel/pkg/powershell"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Router manages network routes on Windows OS using MSFT_NetRoute
|
||||
// See also https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/hh872448(v%3Dvs.85)
|
||||
type RouterWindows struct{}
|
||||
|
||||
func (r RouterWindows) GetAllRoutes() ([]Route, error) {
|
||||
return parseNetRoutes("@(Get-NetRoute | Select-Object -Property IfIndex,DestinationPrefix,NextHop)")
|
||||
}
|
||||
|
||||
func (r RouterWindows) GetRoutesFromInterfaceToSubnet(interfaceIndex int, destinationSubnet *net.IPNet) ([]Route, error) {
|
||||
return parseNetRoutes(fmt.Sprintf("@(Get-NetRoute -InterfaceIndex %d -DestinationPrefix %s | Select-Object -Property IfIndex,DestinationPrefix,NextHop)", interfaceIndex, destinationSubnet.String()))
|
||||
}
|
||||
|
||||
func (r RouterWindows) CreateRoute(interfaceIndex int, destinationSubnet *net.IPNet, gatewayAddress net.IP) error {
|
||||
_, err := powershell.RunCommandf("New-NetRoute -InterfaceIndex %d -DestinationPrefix %s -NextHop %s", interfaceIndex, destinationSubnet.String(), gatewayAddress.String())
|
||||
return err
|
||||
}
|
||||
|
||||
func (r RouterWindows) DeleteRoute(interfaceIndex int, destinationSubnet *net.IPNet, gatewayAddress net.IP) error {
|
||||
_, err := powershell.RunCommandf("Remove-NetRoute -InterfaceIndex %d -DestinationPrefix %s -NextHop %s -Verbose -Confirm:$false", interfaceIndex, destinationSubnet.String(), gatewayAddress.String())
|
||||
return err
|
||||
}
|
||||
|
||||
type winNetRoute struct {
|
||||
IfIndex int
|
||||
DestinationPrefix string
|
||||
NextHop string
|
||||
}
|
||||
|
||||
func parseNetRoutes(cmd string) ([]Route, error) {
|
||||
powerShellJsonData := make([]winNetRoute, 0)
|
||||
|
||||
err := powershell.RunCommandWithJsonResult(cmd, &powerShellJsonData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
routes := make([]Route, 0)
|
||||
for _, r := range powerShellJsonData {
|
||||
route := Route{
|
||||
InterfaceIndex: r.IfIndex,
|
||||
}
|
||||
|
||||
_, destinationSubnet, err := net.ParseCIDR(r.DestinationPrefix)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
route.DestinationSubnet = destinationSubnet
|
||||
|
||||
gatewayAddress := net.ParseIP(r.NextHop)
|
||||
if gatewayAddress == nil {
|
||||
continue
|
||||
}
|
||||
route.GatewayAddress = gatewayAddress
|
||||
|
||||
routes = append(routes, route)
|
||||
}
|
||||
|
||||
return routes, nil
|
||||
}
|
|
@ -19,7 +19,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
)
|
||||
|
||||
type Config struct {
|
|
@ -23,8 +23,8 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/coreos/flannel/subnet"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/subnet"
|
||||
"golang.org/x/net/context"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -60,8 +60,7 @@ type kubeSubnetManager struct {
|
|||
events chan subnet.Event
|
||||
}
|
||||
|
||||
func NewSubnetManager(apiUrl, kubeconfig, prefix, netConfPath string) (subnet.Manager, error) {
|
||||
|
||||
func NewSubnetManager(ctx context.Context, apiUrl, kubeconfig, prefix, netConfPath string) (subnet.Manager, error) {
|
||||
var cfg *rest.Config
|
||||
var err error
|
||||
// Try to build kubernetes config from a master url or a kubeconfig filepath. If neither masterUrl
|
||||
|
@ -88,7 +87,7 @@ func NewSubnetManager(apiUrl, kubeconfig, prefix, netConfPath string) (subnet.Ma
|
|||
return nil, fmt.Errorf("env variables POD_NAME and POD_NAMESPACE must be set")
|
||||
}
|
||||
|
||||
pod, err := c.CoreV1().Pods(podNamespace).Get(context.TODO(), podName, metav1.GetOptions{})
|
||||
pod, err := c.CoreV1().Pods(podNamespace).Get(ctx, podName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error retrieving pod spec for '%s/%s': %v", podNamespace, podName, err)
|
||||
}
|
||||
|
@ -108,7 +107,7 @@ func NewSubnetManager(apiUrl, kubeconfig, prefix, netConfPath string) (subnet.Ma
|
|||
return nil, fmt.Errorf("error parsing subnet config: %s", err)
|
||||
}
|
||||
|
||||
sm, err := newKubeSubnetManager(c, sc, nodeName, prefix)
|
||||
sm, err := newKubeSubnetManager(ctx, c, sc, nodeName, prefix)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating network manager: %s", err)
|
||||
}
|
||||
|
@ -126,7 +125,7 @@ func NewSubnetManager(apiUrl, kubeconfig, prefix, netConfPath string) (subnet.Ma
|
|||
return sm, nil
|
||||
}
|
||||
|
||||
func newKubeSubnetManager(c clientset.Interface, sc *subnet.Config, nodeName, prefix string) (*kubeSubnetManager, error) {
|
||||
func newKubeSubnetManager(ctx context.Context, c clientset.Interface, sc *subnet.Config, nodeName, prefix string) (*kubeSubnetManager, error) {
|
||||
var err error
|
||||
var ksm kubeSubnetManager
|
||||
ksm.annotations, err = newAnnotations(prefix)
|
||||
|
@ -140,10 +139,10 @@ func newKubeSubnetManager(c clientset.Interface, sc *subnet.Config, nodeName, pr
|
|||
indexer, controller := cache.NewIndexerInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return ksm.client.CoreV1().Nodes().List(context.TODO(), options)
|
||||
return ksm.client.CoreV1().Nodes().List(ctx, options)
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return ksm.client.CoreV1().Nodes().Watch(context.TODO(), options)
|
||||
return ksm.client.CoreV1().Nodes().Watch(ctx, options)
|
||||
},
|
||||
},
|
||||
&v1.Node{},
|
||||
|
@ -222,8 +221,8 @@ func (ksm *kubeSubnetManager) AcquireLease(ctx context.Context, attrs *subnet.Le
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
n := cachedNode.DeepCopy()
|
||||
|
||||
n := cachedNode.DeepCopy()
|
||||
if n.Spec.PodCIDR == "" {
|
||||
return nil, fmt.Errorf("node %q pod cidr not assigned", ksm.nodeName)
|
||||
}
|
||||
|
@ -269,12 +268,12 @@ func (ksm *kubeSubnetManager) AcquireLease(ctx context.Context, attrs *subnet.Le
|
|||
return nil, fmt.Errorf("failed to create patch for node %q: %v", ksm.nodeName, err)
|
||||
}
|
||||
|
||||
_, err = ksm.client.CoreV1().Nodes().Patch(context.TODO(), ksm.nodeName, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}, "status")
|
||||
_, err = ksm.client.CoreV1().Nodes().Patch(ctx, ksm.nodeName, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}, "status")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
err = ksm.setNodeNetworkUnavailableFalse()
|
||||
err = ksm.setNodeNetworkUnavailableFalse(ctx)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to set NetworkUnavailable to False for %q: %v", ksm.nodeName, err)
|
||||
}
|
||||
|
@ -292,7 +291,7 @@ func (ksm *kubeSubnetManager) WatchLeases(ctx context.Context, cursor interface{
|
|||
Events: []subnet.Event{event},
|
||||
}, nil
|
||||
case <-ctx.Done():
|
||||
return subnet.LeaseWatchResult{}, nil
|
||||
return subnet.LeaseWatchResult{}, context.Canceled
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +333,7 @@ func (ksm *kubeSubnetManager) Name() string {
|
|||
|
||||
// Set Kubernetes NodeNetworkUnavailable to false when starting
|
||||
// https://kubernetes.io/docs/concepts/architecture/nodes/#condition
|
||||
func (ksm *kubeSubnetManager) setNodeNetworkUnavailableFalse() error {
|
||||
func (ksm *kubeSubnetManager) setNodeNetworkUnavailableFalse(ctx context.Context) error {
|
||||
condition := v1.NodeCondition{
|
||||
Type: v1.NodeNetworkUnavailable,
|
||||
Status: v1.ConditionFalse,
|
||||
|
@ -348,6 +347,6 @@ func (ksm *kubeSubnetManager) setNodeNetworkUnavailableFalse() error {
|
|||
return err
|
||||
}
|
||||
patch := []byte(fmt.Sprintf(`{"status":{"conditions":%s}}`, raw))
|
||||
_, err = ksm.client.CoreV1().Nodes().PatchStatus(context.TODO(), ksm.nodeName, patch)
|
||||
_, err = ksm.client.CoreV1().Nodes().PatchStatus(ctx, ksm.nodeName, patch)
|
||||
return err
|
||||
}
|
|
@ -23,7 +23,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
|
@ -17,10 +17,10 @@ package subnet
|
|||
import (
|
||||
"time"
|
||||
|
||||
log "k8s.io/klog"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/flannel/pkg/ip"
|
||||
"github.com/flannel-io/flannel/pkg/ip"
|
||||
log "k8s.io/klog"
|
||||
)
|
||||
|
||||
// WatchLeases performs a long term watch of the given network's subnet leases
|
||||
|
@ -37,9 +37,15 @@ func WatchLeases(ctx context.Context, sm Manager, ownLease *Lease, receiver chan
|
|||
res, err := sm.WatchLeases(ctx, cursor)
|
||||
if err != nil {
|
||||
if err == context.Canceled || err == context.DeadlineExceeded {
|
||||
log.Infof("%v, close receiver chan", err)
|
||||
close(receiver)
|
||||
return
|
||||
}
|
||||
|
||||
if res.Cursor != nil {
|
||||
cursor = res.Cursor
|
||||
}
|
||||
|
||||
log.Errorf("Watch subnets: %v", err)
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
|
@ -165,10 +171,12 @@ func WatchLease(ctx context.Context, sm Manager, sn ip.IP4Net, receiver chan Eve
|
|||
wr, err := sm.WatchLease(ctx, sn, cursor)
|
||||
if err != nil {
|
||||
if err == context.Canceled || err == context.DeadlineExceeded {
|
||||
log.Infof("%v, close receiver chan", err)
|
||||
close(receiver)
|
||||
return
|
||||
}
|
||||
|
||||
//log.Errorf("Subnet watch failed: %v", err)
|
||||
log.Errorf("Subnet watch failed: %v", err)
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2019 Rakesh Kelkar
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -1,163 +0,0 @@
|
|||
package netroute
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
ps "github.com/benmoss/go-powershell"
|
||||
psbe "github.com/benmoss/go-powershell/backend"
|
||||
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// Interface is an injectable interface for running MSFT_NetRoute commands. Implementations must be goroutine-safe.
|
||||
type Interface interface {
|
||||
// Get all net routes on the host
|
||||
GetNetRoutesAll() ([]Route, error)
|
||||
|
||||
// Get net routes by link and destination subnet
|
||||
GetNetRoutes(linkIndex int, destinationSubnet *net.IPNet) ([]Route, error)
|
||||
|
||||
// Create a new route
|
||||
NewNetRoute(linkIndex int, destinationSubnet *net.IPNet, gatewayAddress net.IP) error
|
||||
|
||||
// Remove an existing route
|
||||
RemoveNetRoute(linkIndex int, destinationSubnet *net.IPNet, gatewayAddress net.IP) error
|
||||
|
||||
// exit the shell
|
||||
Exit()
|
||||
}
|
||||
|
||||
type Route struct {
|
||||
LinkIndex int
|
||||
DestinationSubnet *net.IPNet
|
||||
GatewayAddress net.IP
|
||||
RouteMetric int
|
||||
IfMetric int
|
||||
}
|
||||
|
||||
type shell struct {
|
||||
shellInstance ps.Shell
|
||||
}
|
||||
|
||||
func New() Interface {
|
||||
|
||||
s, _ := ps.New(&psbe.Local{})
|
||||
|
||||
runner := &shell{
|
||||
shellInstance: s,
|
||||
}
|
||||
|
||||
return runner
|
||||
}
|
||||
|
||||
func (shell *shell) Exit() {
|
||||
shell.shellInstance.Exit()
|
||||
shell.shellInstance = nil
|
||||
}
|
||||
|
||||
func (shell *shell) GetNetRoutesAll() ([]Route, error) {
|
||||
getRouteCmdLine := "get-netroute -erroraction Ignore"
|
||||
stdout, err := shell.runScript(getRouteCmdLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parseRoutesList(stdout), nil
|
||||
}
|
||||
func (shell *shell) GetNetRoutes(linkIndex int, destinationSubnet *net.IPNet) ([]Route, error) {
|
||||
getRouteCmdLine := fmt.Sprintf("get-netroute -InterfaceIndex %v -DestinationPrefix %v -erroraction Ignore", linkIndex, destinationSubnet.String())
|
||||
stdout, err := shell.runScript(getRouteCmdLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parseRoutesList(stdout), nil
|
||||
}
|
||||
|
||||
func (shell *shell) RemoveNetRoute(linkIndex int, destinationSubnet *net.IPNet, gatewayAddress net.IP) error {
|
||||
removeRouteCmdLine := fmt.Sprintf("remove-netroute -InterfaceIndex %v -DestinationPrefix %v -NextHop %v -Verbose -Confirm:$false", linkIndex, destinationSubnet.String(), gatewayAddress.String())
|
||||
_, err := shell.runScript(removeRouteCmdLine)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (shell *shell) NewNetRoute(linkIndex int, destinationSubnet *net.IPNet, gatewayAddress net.IP) error {
|
||||
newRouteCmdLine := fmt.Sprintf("new-netroute -InterfaceIndex %v -DestinationPrefix %v -NextHop %v -Verbose", linkIndex, destinationSubnet.String(), gatewayAddress.String())
|
||||
_, err := shell.runScript(newRouteCmdLine)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func parseRoutesList(stdout string) []Route {
|
||||
internalWhitespaceRegEx := regexp.MustCompile(`[\s\p{Zs}]{2,}`)
|
||||
scanner := bufio.NewScanner(strings.NewReader(stdout))
|
||||
var routes []Route
|
||||
for scanner.Scan() {
|
||||
line := internalWhitespaceRegEx.ReplaceAllString(scanner.Text(), "|")
|
||||
if strings.HasPrefix(line, "ifIndex") || strings.HasPrefix(line, "----") {
|
||||
continue
|
||||
}
|
||||
|
||||
parts := strings.Split(line, "|")
|
||||
if len(parts) != 5 {
|
||||
continue
|
||||
}
|
||||
|
||||
linkIndex, err := strconv.Atoi(parts[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
gatewayAddress := net.ParseIP(parts[2])
|
||||
if gatewayAddress == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
_, destinationSubnet, err := net.ParseCIDR(parts[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
route := Route{
|
||||
DestinationSubnet: destinationSubnet,
|
||||
GatewayAddress: gatewayAddress,
|
||||
LinkIndex: linkIndex,
|
||||
}
|
||||
|
||||
routes = append(routes, route)
|
||||
}
|
||||
|
||||
return routes
|
||||
}
|
||||
|
||||
func (r *Route) Equal(route Route) bool {
|
||||
if r.DestinationSubnet.IP.Equal(route.DestinationSubnet.IP) && r.GatewayAddress.Equal(route.GatewayAddress) && bytes.Equal(r.DestinationSubnet.Mask, route.DestinationSubnet.Mask) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (shell *shell) runScript(cmdLine string) (string, error) {
|
||||
|
||||
stdout, _, err := shell.shellInstance.Execute(cmdLine)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return stdout, nil
|
||||
}
|
||||
|
||||
func IpToInt(ip net.IP) *big.Int {
|
||||
if v := ip.To4(); v != nil {
|
||||
return big.NewInt(0).SetBytes(v)
|
||||
}
|
||||
return big.NewInt(0).SetBytes(ip.To16())
|
||||
}
|
||||
|
||||
func IntToIP(i *big.Int) net.IP {
|
||||
return net.IP(i.Bytes())
|
||||
}
|
|
@ -1,335 +0,0 @@
|
|||
package netsh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"errors"
|
||||
|
||||
utilexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
// Interface is an injectable interface for running netsh commands. Implementations must be goroutine-safe.
|
||||
type Interface interface {
|
||||
// EnsurePortProxyRule checks if the specified redirect exists, if not creates it
|
||||
EnsurePortProxyRule(args []string) (bool, error)
|
||||
// DeletePortProxyRule deletes the specified portproxy rule. If the rule did not exist, return error.
|
||||
DeletePortProxyRule(args []string) error
|
||||
// DeleteIPAddress checks if the specified IP address is present and, if so, deletes it.
|
||||
DeleteIPAddress(args []string) error
|
||||
// Restore runs `netsh exec` to restore portproxy or addresses using a file.
|
||||
// TODO Check if this is required, most likely not
|
||||
Restore(args []string) error
|
||||
// Get the interface name that has the default gateway
|
||||
GetDefaultGatewayIfaceName() (string, error)
|
||||
// Get a list of interfaces and addresses
|
||||
GetInterfaces() ([]Ipv4Interface, error)
|
||||
// Gets an interface by name
|
||||
GetInterfaceByName(name string) (Ipv4Interface, error)
|
||||
// Gets an interface by ip address in the format a.b.c.d
|
||||
GetInterfaceByIP(ipAddr string) (Ipv4Interface, error)
|
||||
// Enable forwarding on the interface (name or index)
|
||||
EnableForwarding(iface string) error
|
||||
}
|
||||
|
||||
const (
|
||||
cmdNetsh string = "netsh"
|
||||
)
|
||||
|
||||
// runner implements Interface in terms of exec("netsh").
|
||||
type runner struct {
|
||||
mu sync.Mutex
|
||||
exec utilexec.Interface
|
||||
}
|
||||
|
||||
// Ipv4Interface models IPv4 interface output from: netsh interface ipv4 show addresses
|
||||
type Ipv4Interface struct {
|
||||
Idx int
|
||||
Name string
|
||||
InterfaceMetric int
|
||||
DhcpEnabled bool
|
||||
IpAddress string
|
||||
SubnetPrefix int
|
||||
GatewayMetric int
|
||||
DefaultGatewayAddress string
|
||||
}
|
||||
|
||||
// New returns a new Interface which will exec netsh.
|
||||
func New(exec utilexec.Interface) Interface {
|
||||
|
||||
if exec == nil {
|
||||
exec = utilexec.New()
|
||||
}
|
||||
|
||||
runner := &runner{
|
||||
exec: exec,
|
||||
}
|
||||
return runner
|
||||
}
|
||||
|
||||
func (runner *runner) GetInterfaces() ([]Ipv4Interface, error) {
|
||||
interfaces, interfaceError := runner.getIpAddressConfigurations()
|
||||
|
||||
if interfaceError != nil {
|
||||
return nil, interfaceError
|
||||
}
|
||||
|
||||
indexMap, indexError := runner.getNetworkInterfaceParameters()
|
||||
|
||||
if indexError != nil {
|
||||
return nil, indexError
|
||||
}
|
||||
|
||||
// zip them up
|
||||
for i := 0; i < len(interfaces); i++ {
|
||||
name := interfaces[i].Name
|
||||
|
||||
if val, ok := indexMap[name]; ok {
|
||||
interfaces[i].Idx = val
|
||||
} else {
|
||||
return nil, fmt.Errorf("no index found for interface \"%v\"", name)
|
||||
}
|
||||
}
|
||||
|
||||
return interfaces, nil
|
||||
}
|
||||
|
||||
// GetInterfaces uses the show addresses command and returns a formatted structure
|
||||
func (runner *runner) getIpAddressConfigurations() ([]Ipv4Interface, error) {
|
||||
args := []string{
|
||||
"interface", "ipv4", "show", "addresses",
|
||||
}
|
||||
|
||||
output, err := runner.exec.Command(cmdNetsh, args...).CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
interfacesString := string(output[:])
|
||||
|
||||
outputLines := strings.Split(interfacesString, "\n")
|
||||
var interfaces []Ipv4Interface
|
||||
var currentInterface Ipv4Interface
|
||||
quotedPattern := regexp.MustCompile("\\\"(.*?)\\\"")
|
||||
cidrPattern := regexp.MustCompile("\\/(.*?)\\ ")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, outputLine := range outputLines {
|
||||
if strings.Contains(outputLine, "Configuration for interface") {
|
||||
if currentInterface != (Ipv4Interface{}) {
|
||||
interfaces = append(interfaces, currentInterface)
|
||||
}
|
||||
match := quotedPattern.FindStringSubmatch(outputLine)
|
||||
currentInterface = Ipv4Interface{
|
||||
Name: match[1],
|
||||
}
|
||||
} else {
|
||||
parts := strings.SplitN(outputLine, ":", 2)
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(parts[0])
|
||||
value := strings.TrimSpace(parts[1])
|
||||
if strings.HasPrefix(key, "DHCP enabled") {
|
||||
if value == "Yes" {
|
||||
currentInterface.DhcpEnabled = true
|
||||
}
|
||||
} else if strings.HasPrefix(key, "InterfaceMetric") {
|
||||
if val, err := strconv.Atoi(value); err == nil {
|
||||
currentInterface.InterfaceMetric = val
|
||||
}
|
||||
} else if strings.HasPrefix(key, "Gateway Metric") {
|
||||
if val, err := strconv.Atoi(value); err == nil {
|
||||
currentInterface.GatewayMetric = val
|
||||
}
|
||||
} else if strings.HasPrefix(key, "Subnet Prefix") {
|
||||
match := cidrPattern.FindStringSubmatch(value)
|
||||
if val, err := strconv.Atoi(match[1]); err == nil {
|
||||
currentInterface.SubnetPrefix = val
|
||||
}
|
||||
} else if strings.HasPrefix(key, "IP Address") {
|
||||
currentInterface.IpAddress = value
|
||||
} else if strings.HasPrefix(key, "Default Gateway") {
|
||||
currentInterface.DefaultGatewayAddress = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the last one
|
||||
if currentInterface != (Ipv4Interface{}) {
|
||||
interfaces = append(interfaces, currentInterface)
|
||||
}
|
||||
|
||||
if len(interfaces) == 0 {
|
||||
return nil, fmt.Errorf("no interfaces found in netsh output: %v", interfacesString)
|
||||
}
|
||||
|
||||
return interfaces, nil
|
||||
}
|
||||
|
||||
func (runner *runner) getNetworkInterfaceParameters() (map[string]int, error) {
|
||||
args := []string{
|
||||
"interface", "ipv4", "show", "interfaces",
|
||||
}
|
||||
|
||||
output, err := runner.exec.Command(cmdNetsh, args...).CombinedOutput()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Split output by line
|
||||
outputString := string(output[:])
|
||||
outputString = strings.TrimSpace(outputString)
|
||||
var outputLines = strings.Split(outputString, "\n")
|
||||
|
||||
if len(outputLines) < 3 {
|
||||
return nil, errors.New("unexpected netsh output:\n" + outputString)
|
||||
}
|
||||
|
||||
// Remove first two lines of header text
|
||||
outputLines = outputLines[2:]
|
||||
|
||||
indexMap := make(map[string]int)
|
||||
|
||||
reg := regexp.MustCompile("\\s{2,}")
|
||||
|
||||
for _, line := range outputLines {
|
||||
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
// Split the line by two or more whitespace characters, returning all substrings (n < 0)
|
||||
splitLine := reg.Split(line, -1)
|
||||
|
||||
name := splitLine[4]
|
||||
if idx, err := strconv.Atoi(splitLine[0]); err == nil {
|
||||
indexMap[name] = idx
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return indexMap, nil
|
||||
}
|
||||
|
||||
// Enable forwarding on the interface (name or index)
|
||||
func (runner *runner) EnableForwarding(iface string) error {
|
||||
args := []string{
|
||||
"int", "ipv4", "set", "int", strconv.Quote(iface), "for=en",
|
||||
}
|
||||
cmd := strings.Join(args, " ")
|
||||
if stdout, err := runner.exec.Command(cmdNetsh, args...).CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to enable forwarding on [%v], error: %v. cmd: %v. stdout: %v", iface, err.Error(), cmd, string(stdout))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnsurePortProxyRule checks if the specified redirect exists, if not creates it.
|
||||
func (runner *runner) EnsurePortProxyRule(args []string) (bool, error) {
|
||||
out, err := runner.exec.Command(cmdNetsh, args...).CombinedOutput()
|
||||
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if ee, ok := err.(utilexec.ExitError); ok {
|
||||
// netsh uses exit(0) to indicate a success of the operation,
|
||||
// as compared to a malformed commandline, for example.
|
||||
if ee.Exited() && ee.ExitStatus() != 0 {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return false, fmt.Errorf("error checking portproxy rule: %v: %s", err, out)
|
||||
|
||||
}
|
||||
|
||||
// DeletePortProxyRule deletes the specified portproxy rule. If the rule did not exist, return error.
|
||||
func (runner *runner) DeletePortProxyRule(args []string) error {
|
||||
out, err := runner.exec.Command(cmdNetsh, args...).CombinedOutput()
|
||||
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if ee, ok := err.(utilexec.ExitError); ok {
|
||||
// netsh uses exit(0) to indicate a success of the operation,
|
||||
// as compared to a malformed commandline, for example.
|
||||
if ee.Exited() && ee.ExitStatus() == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("error deleting portproxy rule: %v: %s", err, out)
|
||||
}
|
||||
|
||||
// DeleteIPAddress checks if the specified IP address is present and, if so, deletes it.
|
||||
func (runner *runner) DeleteIPAddress(args []string) error {
|
||||
out, err := runner.exec.Command(cmdNetsh, args...).CombinedOutput()
|
||||
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if ee, ok := err.(utilexec.ExitError); ok {
|
||||
// netsh uses exit(0) to indicate a success of the operation,
|
||||
// as compared to a malformed commandline, for example.
|
||||
if ee.Exited() && ee.ExitStatus() == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("error deleting ipv4 address: %v: %s", err, out)
|
||||
}
|
||||
|
||||
func (runner *runner) GetDefaultGatewayIfaceName() (string, error) {
|
||||
interfaces, err := runner.GetInterfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, iface := range interfaces {
|
||||
if iface.DefaultGatewayAddress != "" {
|
||||
return iface.Name, nil
|
||||
}
|
||||
}
|
||||
|
||||
// return "not found"
|
||||
return "", fmt.Errorf("Default interface not found")
|
||||
}
|
||||
|
||||
func (runner *runner) GetInterfaceByName(name string) (Ipv4Interface, error) {
|
||||
interfaces, err := runner.GetInterfaces()
|
||||
if err != nil {
|
||||
return Ipv4Interface{}, err
|
||||
}
|
||||
|
||||
for _, iface := range interfaces {
|
||||
if iface.Name == name {
|
||||
return iface, nil
|
||||
}
|
||||
}
|
||||
|
||||
// return "not found"
|
||||
return Ipv4Interface{}, fmt.Errorf("Interface not found: %v", name)
|
||||
}
|
||||
|
||||
func (runner *runner) GetInterfaceByIP(ipAddr string) (Ipv4Interface, error) {
|
||||
interfaces, err := runner.GetInterfaces()
|
||||
if err != nil {
|
||||
return Ipv4Interface{}, err
|
||||
}
|
||||
|
||||
for _, iface := range interfaces {
|
||||
if iface.IpAddress == ipAddr {
|
||||
return iface, nil
|
||||
}
|
||||
}
|
||||
|
||||
// return "not found"
|
||||
return Ipv4Interface{}, fmt.Errorf("Interface not found: %v", ipAddr)
|
||||
}
|
||||
|
||||
// Restore is part of Interface.
|
||||
func (runner *runner) Restore(args []string) error {
|
||||
return nil
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
Copyright (c) 2017, Gorillalabs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
http://www.opensource.org/licenses/MIT
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright (c) 2017 Gorillalabs. All rights reserved.
|
||||
|
||||
package backend
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os/exec"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Local struct{}
|
||||
|
||||
func (b *Local) StartProcess(cmd string, args ...string) (Waiter, io.Writer, io.Reader, io.Reader, error) {
|
||||
command := exec.Command(cmd, args...)
|
||||
|
||||
stdin, err := command.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the PowerShell's stdin stream")
|
||||
}
|
||||
|
||||
stdout, err := command.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the PowerShell's stdout stream")
|
||||
}
|
||||
|
||||
stderr, err := command.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the PowerShell's stderr stream")
|
||||
}
|
||||
|
||||
err = command.Start()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not spawn PowerShell process")
|
||||
}
|
||||
|
||||
return command, stdin, stdout, stderr, nil
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
// Copyright (c) 2017 Gorillalabs. All rights reserved.
|
||||
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// sshSession exists so we don't create a hard dependency on crypto/ssh.
|
||||
type sshSession interface {
|
||||
Waiter
|
||||
|
||||
StdinPipe() (io.WriteCloser, error)
|
||||
StdoutPipe() (io.Reader, error)
|
||||
StderrPipe() (io.Reader, error)
|
||||
Start(string) error
|
||||
}
|
||||
|
||||
type SSH struct {
|
||||
Session sshSession
|
||||
}
|
||||
|
||||
func (b *SSH) StartProcess(cmd string, args ...string) (Waiter, io.Writer, io.Reader, io.Reader, error) {
|
||||
stdin, err := b.Session.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the SSH session's stdin stream")
|
||||
}
|
||||
|
||||
stdout, err := b.Session.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the SSH session's stdout stream")
|
||||
}
|
||||
|
||||
stderr, err := b.Session.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not get hold of the SSH session's stderr stream")
|
||||
}
|
||||
|
||||
err = b.Session.Start(b.createCmd(cmd, args))
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Could not spawn process via SSH")
|
||||
}
|
||||
|
||||
return b.Session, stdin, stdout, stderr, nil
|
||||
}
|
||||
|
||||
func (b *SSH) createCmd(cmd string, args []string) string {
|
||||
parts := []string{cmd}
|
||||
simple := regexp.MustCompile(`^[a-z0-9_/.~+-]+$`)
|
||||
|
||||
for _, arg := range args {
|
||||
if !simple.MatchString(arg) {
|
||||
arg = b.quote(arg)
|
||||
}
|
||||
|
||||
parts = append(parts, arg)
|
||||
}
|
||||
|
||||
return strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
func (b *SSH) quote(s string) string {
|
||||
return fmt.Sprintf(`"%s"`, s)
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) 2017 Gorillalabs. All rights reserved.
|
||||
|
||||
package backend
|
||||
|
||||
import "io"
|
||||
|
||||
type Waiter interface {
|
||||
Wait() error
|
||||
}
|
||||
|
||||
type Starter interface {
|
||||
StartProcess(cmd string, args ...string) (Waiter, io.Writer, io.Reader, io.Reader, error)
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// Copyright (c) 2017 Gorillalabs. All rights reserved.
|
||||
|
||||
package utils
|
||||
|
||||
import "strings"
|
||||
|
||||
func QuoteArg(s string) string {
|
||||
return "'" + strings.Replace(s, "'", "\"", -1) + "'"
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright (c) 2017 Gorillalabs. All rights reserved.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
func CreateRandomString(bytes int) string {
|
||||
c := bytes
|
||||
b := make([]byte, c)
|
||||
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return hex.EncodeToString(b)
|
||||
}
|
|
@ -130,9 +130,6 @@ github.com/aws/aws-sdk-go/service/elbv2
|
|||
github.com/aws/aws-sdk-go/service/kms
|
||||
github.com/aws/aws-sdk-go/service/sts
|
||||
github.com/aws/aws-sdk-go/service/sts/stsiface
|
||||
# github.com/benmoss/go-powershell v0.0.0-00010101000000-000000000000 => github.com/rancher/go-powershell v0.0.0-20200701184732-233247d45373
|
||||
github.com/benmoss/go-powershell
|
||||
github.com/benmoss/go-powershell/backend
|
||||
# github.com/beorn7/perks v1.0.1
|
||||
github.com/beorn7/perks/quantile
|
||||
# github.com/blang/semver v3.5.0+incompatible
|
||||
|
@ -374,6 +371,7 @@ github.com/containernetworking/cni/pkg/version
|
|||
# github.com/containernetworking/plugins v0.9.1
|
||||
## explicit
|
||||
github.com/containernetworking/plugins/pkg/ns
|
||||
github.com/containernetworking/plugins/pkg/utils/sysctl
|
||||
# github.com/containers/ocicrypt v1.1.1
|
||||
github.com/containers/ocicrypt
|
||||
github.com/containers/ocicrypt/blockcipher
|
||||
|
@ -389,17 +387,6 @@ github.com/containers/ocicrypt/keywrap/pkcs7
|
|||
github.com/containers/ocicrypt/spec
|
||||
github.com/containers/ocicrypt/utils
|
||||
github.com/containers/ocicrypt/utils/keyprovider
|
||||
# github.com/coreos/flannel v0.12.0 => github.com/rancher/flannel v0.12.0-k3s1
|
||||
## explicit
|
||||
github.com/coreos/flannel/backend
|
||||
github.com/coreos/flannel/backend/extension
|
||||
github.com/coreos/flannel/backend/hostgw
|
||||
github.com/coreos/flannel/backend/ipsec
|
||||
github.com/coreos/flannel/backend/vxlan
|
||||
github.com/coreos/flannel/network
|
||||
github.com/coreos/flannel/pkg/ip
|
||||
github.com/coreos/flannel/subnet
|
||||
github.com/coreos/flannel/subnet/kube
|
||||
# github.com/coreos/go-iptables v0.5.0
|
||||
## explicit
|
||||
github.com/coreos/go-iptables/iptables
|
||||
|
@ -488,6 +475,20 @@ github.com/evanphx/json-patch
|
|||
github.com/exponent-io/jsonpath
|
||||
# github.com/fatih/camelcase v1.0.0
|
||||
github.com/fatih/camelcase
|
||||
# github.com/flannel-io/flannel v0.14.1
|
||||
## explicit
|
||||
github.com/flannel-io/flannel/backend
|
||||
github.com/flannel-io/flannel/backend/extension
|
||||
github.com/flannel-io/flannel/backend/hostgw
|
||||
github.com/flannel-io/flannel/backend/ipsec
|
||||
github.com/flannel-io/flannel/backend/vxlan
|
||||
github.com/flannel-io/flannel/network
|
||||
github.com/flannel-io/flannel/pkg/ip
|
||||
github.com/flannel-io/flannel/pkg/mac
|
||||
github.com/flannel-io/flannel/pkg/powershell
|
||||
github.com/flannel-io/flannel/pkg/routing
|
||||
github.com/flannel-io/flannel/subnet
|
||||
github.com/flannel-io/flannel/subnet/kube
|
||||
# github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/fsnotify/fsnotify
|
||||
# github.com/ghodss/yaml v1.0.0
|
||||
|
@ -864,9 +865,6 @@ github.com/prometheus/common/model
|
|||
github.com/prometheus/procfs
|
||||
github.com/prometheus/procfs/internal/fs
|
||||
github.com/prometheus/procfs/internal/util
|
||||
# github.com/rakelkar/gonetsh v0.0.0-20190930180311-e5c5ffe4bdf0
|
||||
github.com/rakelkar/gonetsh/netroute
|
||||
github.com/rakelkar/gonetsh/netsh
|
||||
# github.com/rancher/dynamiclistener v0.2.2
|
||||
## explicit
|
||||
github.com/rancher/dynamiclistener
|
||||
|
@ -875,9 +873,6 @@ github.com/rancher/dynamiclistener/factory
|
|||
github.com/rancher/dynamiclistener/storage/file
|
||||
github.com/rancher/dynamiclistener/storage/kubernetes
|
||||
github.com/rancher/dynamiclistener/storage/memory
|
||||
# github.com/rancher/go-powershell v0.0.0-20200701182037-6845e6fcfa79
|
||||
github.com/rancher/go-powershell/backend
|
||||
github.com/rancher/go-powershell/utils
|
||||
# github.com/rancher/remotedialer v0.2.0
|
||||
## explicit
|
||||
github.com/rancher/remotedialer
|
||||
|
@ -2982,7 +2977,6 @@ vbom.ml/util/sortorder
|
|||
# github.com/containerd/ttrpc => github.com/containerd/ttrpc v1.0.2
|
||||
# github.com/containerd/typeurl => github.com/containerd/typeurl v1.0.2
|
||||
# github.com/containerd/zfs => github.com/containerd/zfs v1.0.0
|
||||
# github.com/coreos/flannel => github.com/rancher/flannel v0.12.0-k3s1
|
||||
# github.com/coreos/go-systemd => github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
||||
# github.com/docker/distribution => github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible
|
||||
# github.com/docker/docker => github.com/docker/docker v17.12.0-ce-rc1.0.20200310163718-4634ce647cf2+incompatible
|
||||
|
|
Loading…
Reference in New Issue