diff --git a/edgenet-remove-calico.yml b/edgenet-remove-calico.yml deleted file mode 100644 index 3fc4d33..0000000 --- a/edgenet-remove-calico.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -- hosts: all - become: true - tasks: - - name: Ensure Calico CNI binaries are absent - file: - path: "{{ item }}" - state: absent - with_fileglob: /opt/cni/bin/*calico* - - - name: Ensure Calico CNI configurations are absent - file: - path: "{{ item }}" - state: absent - with_fileglob: /etc/cni/net.d/*calico* - - - name: Reboot the node - reboot: diff --git a/go.mod b/go.mod index 2ba8a0d..702ffdb 100644 --- a/go.mod +++ b/go.mod @@ -4,15 +4,16 @@ go 1.16 require ( cloud.google.com/go v0.94.1 - github.com/EdgeNet-project/edgenet v1.0.0-alpha.1.0.20210701214804-887efc4a97b0 + github.com/EdgeNet-project/edgenet v1.0.0-alpha.1.0.20210913151028-60f26ffd5fb3 github.com/aws/aws-sdk-go v1.40.35 github.com/coreos/go-iptables v0.6.0 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7 github.com/thanhpk/randstr v1.0.4 github.com/txn2/txeh v1.3.0 - github.com/vishvananda/netlink v1.1.0 + github.com/vishvananda/netlink v1.1.1-0.20210530105856-14e832ae1e8f github.com/yumaojun03/dmidecode v0.1.4 golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf + golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b k8s.io/apimachinery v0.22.1 k8s.io/client-go v0.22.1 diff --git a/go.sum b/go.sum index f8f4203..a5c0dca 100644 --- a/go.sum +++ b/go.sum @@ -65,8 +65,8 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/EdgeNet-project/edgenet v1.0.0-alpha.1.0.20210701214804-887efc4a97b0 h1:nj6XK2peWGpxswhnl6AfQBztiGFYIjkfQN32s0Mu+XU= -github.com/EdgeNet-project/edgenet v1.0.0-alpha.1.0.20210701214804-887efc4a97b0/go.mod h1:N0Bywx82T4cZylj+MD9EB1S0rK1inQ+lF5KPiGHi8Fw= +github.com/EdgeNet-project/edgenet v1.0.0-alpha.1.0.20210913151028-60f26ffd5fb3 h1:rQEXdXRTb0EGEPl5Uzs3Xn6n9Fjqrv5K3M+U84EtpCo= +github.com/EdgeNet-project/edgenet v1.0.0-alpha.1.0.20210913151028-60f26ffd5fb3/go.mod h1:znAhxW7yrlvtR4CWmcM+Oa8FFAZutZK6M9BaXF1R0VQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -359,6 +359,16 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA= +github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= +github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= +github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= +github.com/jsimonetti/rtnetlink v0.0.0-20201216134343-bde56ed16391/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw= +github.com/jsimonetti/rtnetlink v0.0.0-20201220180245-69540ac93943/go.mod h1:z4c53zj6Eex712ROyh8WI0ihysb5j2ROyV42iNogmAs= +github.com/jsimonetti/rtnetlink v0.0.0-20210122163228-8d122574c736/go.mod h1:ZXpIyOK59ZnN7J0BV99cZUPmsqDRZ3eq5X+st7u/oSA= +github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b h1:c3NTyLNozICy8B4mlMXemD3z/gXgQzVXZS/HqT+i3do= +github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b/go.mod h1:8w9Rh8m+aHZIG69YPGGem1i5VzoyRC8nw2kA8B+ik5U= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -405,8 +415,24 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43 h1:WgyLFv10Ov49JAQI/ZLUkCZ7VJS3r74hwFIGXJsgZlY= +github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo= +github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0= +github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= +github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= +github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= +github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= +github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= +github.com/mdlayher/netlink v1.2.0/go.mod h1:kwVW1io0AZy9A1E2YYgaD4Cj+C+GPkU6klXCMzIJ9p8= +github.com/mdlayher/netlink v1.2.1/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU= +github.com/mdlayher/netlink v1.2.2-0.20210123213345-5cc92139ae3e/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU= +github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuriDdoPSWys= +github.com/mdlayher/netlink v1.4.0 h1:n3ARR+Fm0dDv37dj5wSWZXDKcy+U0zwcXS3zKMnSiT0= +github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws= +github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= @@ -529,10 +555,10 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netlink v1.1.1-0.20210530105856-14e832ae1e8f h1:x8XiJlRNuo7qiP7DbEM3g5jOKf9pY+SsQra/n4XJUDc= +github.com/vishvananda/netlink v1.1.1-0.20210530105856-14e832ae1e8f/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -578,6 +604,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= +golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -640,6 +668,7 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -655,15 +684,19 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -707,12 +740,12 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -720,6 +753,7 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -731,6 +765,7 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -741,19 +776,29 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -850,6 +895,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.zx2c4.com/wireguard v0.0.0-20210427022245-097af6e1351b h1:XDLXhn7ryprJVo+Lpkiib6CIuXE2031GDwtfEm7vLjI= +golang.zx2c4.com/wireguard v0.0.0-20210427022245-097af6e1351b/go.mod h1:a057zjmoc00UN7gVkaJt2sXVK523kMJcogDTEvPIasg= +golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5 h1:LpEwXnbN4q2EIPkqbG9KHBUrducJYDOOdL+eMcJAlFo= +golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5/go.mod h1:+1XihzyZUBJcSc5WO9SwNA7v26puQwOEDwanaxfNXPQ= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= diff --git a/main.go b/main.go index 8733b8b..e5ea3dd 100644 --- a/main.go +++ b/main.go @@ -21,18 +21,25 @@ import ( "github.com/EdgeNet-project/node/pkg/cluster" "github.com/EdgeNet-project/node/pkg/network" "github.com/EdgeNet-project/node/pkg/platforms" + "github.com/EdgeNet-project/node/pkg/utils" "github.com/thanhpk/randstr" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" "gopkg.in/yaml.v3" "log" + "math/rand" "net" "os" "path/filepath" "strings" + "time" ) const defaultKubeconfigURL = "https://raw.githubusercontent.com/EdgeNet-project/edgenet/master/configs/public.cfg" +const defaultVPNNetworkV4 = "10.183.0.0/20" +const defaultVPNNetworkV6 = "fdb4:ae86:ec99:4004::/64" const edgenetConfigFile = "/opt/edgenet/config.yaml" const kubeletEnvFile = "/etc/default/kubelet" +const vpnLinkName = "edgenetmesh0" func check(err error) { if err != nil { @@ -55,6 +62,16 @@ type edgenetConfig struct { // PublicIPv4 is the public IPv4 address of the host. // This address must be reachable from the Internet. PublicIPv4 net.IP `yaml:"publicIPv4"` + // VPNIPv4 is the private IPv4 address of the VPN mesh interface. + // This address must be unique among the node in the cluster. + VPNIPv4 *utils.IPWithMask `yaml:"vpnIPv4"` + // VPNIPv4 is the private IPv6 address of the VPN mesh interface. + // This address must be unique among the node in the cluster. + VPNIPv6 *utils.IPWithMask `yaml:"vpnIPv6"` + // VPNPrivateKey is the WireGuard private key of the VPN mesh interface. + VPNPrivateKey string `yaml:"vpnPrivateKey"` + // VPNListenPort is the WireGuard port of the VPN mesh interface. + VPNListenPort int `yaml:"vpnListenPort"` } // load the EdgeNet configuration from the specified file. @@ -165,26 +182,62 @@ func main() { config.LocalIPv4, config.PublicIPv4 = getIPv4(config.Platform) } + // https://github.com/EdgeNet-project/edgenet/issues/156 + if config.VPNIPv4 == nil || config.VPNIPv6 == nil { + log.Println("step=get-vpn-ip") + _, vpnNetworkV4, err := net.ParseCIDR(defaultVPNNetworkV4) + check(err) + _, vpnNetworkV6, err := net.ParseCIDR(defaultVPNNetworkV6) + check(err) + config.VPNIPv4, config.VPNIPv6 = cluster.FindVPNIPs(defaultKubeconfigURL, *vpnNetworkV4, *vpnNetworkV6) + } + + if config.VPNPrivateKey == "" { + log.Println("step=get-vpn-private-key") + key, err := wgtypes.GeneratePrivateKey() + check(err) + config.VPNPrivateKey = key.String() + } + + if config.VPNListenPort == 0 { + log.Println("step=get-vpn-listen-port") + rand.Seed(time.Now().UnixNano()) + config.VPNListenPort = rand.Intn(32768) + 32768 + } + log.Println("step=save-config") log.Printf("config=%+v\n", config) config.save(edgenetConfigFile) - // Cloud providers assign a public IP to instances through NAT. - // The instance only sees an private _internal_ IP. - // This is problematic for Kubernetes, which expects to see the public IP on the interface. - // In this script, we assign the public IP to the instance interface. - if !config.LocalIPv4.Equal(config.PublicIPv4) { - log.Println("step=set-public-ip") - network.AssignPublicIP(config.LocalIPv4, config.PublicIPv4) - // This doesn't seems to be required anymore with Antrea (as it was with Calico). - // network.RewritePublicIP(config.LocalIPv4, config.PublicIPv4) - network.SetKubeletNodeIP(kubeletEnvFile, config.PublicIPv4) - } - log.Println("step=set-hostname") hostname := fmt.Sprintf("%s-%s.edge-net.io", config.HostnameRoot, config.HostnameSuffix) network.SetHostname(hostname) + // https://github.com/EdgeNet-project/edgenet/issues/156 + if config.VPNIPv4 != nil && config.VPNIPv6 != nil { + log.Println("step=configure-vpn") + network.InitializeVPN(vpnLinkName, config.VPNPrivateKey, config.VPNListenPort) + network.AssignVPNIP(vpnLinkName, *config.VPNIPv4, *config.VPNIPv6) + privateKey, err := wgtypes.ParseKey(config.VPNPrivateKey) + check(err) + cluster.CreateVPNPeer(defaultKubeconfigURL, hostname, config.PublicIPv4, config.VPNIPv4.IP, config.VPNIPv6.IP, config.VPNListenPort, privateKey.PublicKey().String()) + // Pre-establish the tunnels before the VPNPeer controller gets started. + peers := cluster.ListVPNPeer(defaultKubeconfigURL) + for _, peer := range peers { + network.AddPeer(vpnLinkName, peer) + } + } + + var nodeIP net.IP + if config.LocalIPv4.Equal(config.PublicIPv4) { + nodeIP = config.PublicIPv4 + } else { + nodeIP = config.VPNIPv4.IP + } + + log.Println("step=set-node-ip") + network.SetKubeletNodeIP(kubeletEnvFile, nodeIP) + log.Println("step=join-cluster") - cluster.Join(defaultKubeconfigURL, config.PublicIPv4, hostname) + cluster.Join(defaultKubeconfigURL, hostname, nodeIP) } diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index 935233e..e0ad172 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -19,7 +19,9 @@ package cluster import ( "context" "github.com/EdgeNet-project/edgenet/pkg/apis/core/v1alpha" + v1alpha2 "github.com/EdgeNet-project/edgenet/pkg/apis/networking/v1alpha" "github.com/EdgeNet-project/edgenet/pkg/generated/clientset/versioned" + "github.com/EdgeNet-project/node/pkg/utils" "io/ioutil" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,14 +51,67 @@ func configFromUrl(url string) (*rest.Config, error) { return clientcmd.RESTConfigFromKubeConfig(buf) } +func FindVPNIPs(configURL string, netv4 net.IPNet, netv6 net.IPNet) (*utils.IPWithMask, *utils.IPWithMask) { + peers := ListVPNPeer(configURL) + usedIPs := make([]net.IP, 0) + for _, peer := range peers { + usedIPs = append(usedIPs, net.ParseIP(peer.Spec.AddressV4)) + } + ipv4 := utils.RandIPv4(netv4, usedIPs) + ipv6 := make(net.IP, 16) + copy(ipv6[:12], netv6.IP[:12]) + copy(ipv6[12:16], ipv4) + return &utils.IPWithMask{IP: ipv4, Mask: netv4.Mask}, &utils.IPWithMask{IP: ipv6, Mask: netv6.Mask} +} + +func CreateVPNPeer(configURL string, hostname string, externalIP net.IP, ipv4 net.IP, ipv6 net.IP, listenPort int, publicKey string) { + config, err := configFromUrl(configURL) + check(err) + clientset, err := versioned.NewForConfig(config) + check(err) + client := clientset.NetworkingV1alpha().VPNPeers() + _externalIP := externalIP.String() + peer := &v1alpha2.VPNPeer{ + ObjectMeta: metav1.ObjectMeta{ + Name: hostname, + }, + Spec: v1alpha2.VPNPeerSpec{ + AddressV4: ipv4.String(), + AddressV6: ipv6.String(), + EndpointAddress: &_externalIP, + EndpointPort: &listenPort, + PublicKey: publicKey, + }, + } + _, err = client.Create(context.TODO(), peer.DeepCopy(), metav1.CreateOptions{}) + if errors.IsAlreadyExists(err) { + log.Print("vpn-peer-status=already-exists") + } else if err != nil { + panic(err) + } else { + log.Print("vpn-peer-status=created") + } +} + +func ListVPNPeer(configURL string) []v1alpha2.VPNPeer { + config, err := configFromUrl(configURL) + check(err) + clientset, err := versioned.NewForConfig(config) + check(err) + client := clientset.NetworkingV1alpha().VPNPeers() + peers, err := client.List(context.TODO(), metav1.ListOptions{}) + check(err) + return peers.Items +} + // Join the node to the cluster specified by configURL. // It ignores AlreadyExists errors when creating the NodeContribution object. -func Join(configURL string, externalIP net.IP, hostname string) { +func Join(configURL string, hostname string, externalIP net.IP) { config, err := configFromUrl(configURL) check(err) clientset, err := versioned.NewForConfig(config) check(err) - nodeContributionClient := clientset.CoreV1alpha().NodeContributions() + client := clientset.CoreV1alpha().NodeContributions() nodeContribution := &v1alpha.NodeContribution{ ObjectMeta: metav1.ObjectMeta{ Name: strings.ReplaceAll(hostname, ".edge-net.io", ""), @@ -69,7 +124,7 @@ func Join(configURL string, externalIP net.IP, hostname string) { User: "edgenet", }, } - _, err = nodeContributionClient.Create(context.TODO(), nodeContribution.DeepCopy(), metav1.CreateOptions{}) + _, err = client.Create(context.TODO(), nodeContribution.DeepCopy(), metav1.CreateOptions{}) if errors.IsAlreadyExists(err) { log.Print("node-contribution-status=already-exists") } else if err != nil { diff --git a/pkg/network/vpn.go b/pkg/network/vpn.go index d64f322..158ac12 100644 --- a/pkg/network/vpn.go +++ b/pkg/network/vpn.go @@ -15,3 +15,114 @@ limitations under the License. */ package network + +import ( + "github.com/EdgeNet-project/edgenet/pkg/apis/networking/v1alpha" + "github.com/EdgeNet-project/node/pkg/utils" + "github.com/vishvananda/netlink" + "golang.org/x/sys/unix" + "golang.zx2c4.com/wireguard/wgctrl" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + "net" + "time" +) + +func getOrAddVPNLink(name string) netlink.Link { + link, err := netlink.LinkByName(name) + if err == nil { + return link + } + _, ok := err.(netlink.LinkNotFoundError) + if !ok { + panic(err) + } + linkAttrs := netlink.NewLinkAttrs() + linkAttrs.Name = name + link = &netlink.Wireguard{LinkAttrs: linkAttrs} + check(netlink.LinkAdd(link)) + return link +} + +func InitializeVPN(name string, privateKey string, listenPort int) { + link := getOrAddVPNLink(name) + check(netlink.LinkSetUp(link)) + client, err := wgctrl.New() + check(err) + key, err := wgtypes.ParseKey(privateKey) + check(err) + config := wgtypes.Config{PrivateKey: &key, ListenPort: &listenPort} + check(client.ConfigureDevice(name, config)) +} + +func AssignVPNIP(name string, ipv4 utils.IPWithMask, ipv6 utils.IPWithMask) { + link := getOrAddVPNLink(name) + + addr4, err := netlink.ParseAddr(ipv4.String()) + check(err) + addrs, err := netlink.AddrList(link, unix.AF_INET) + check(err) + for _, addr := range addrs { + if !addr.Equal(*addr4) { + check(netlink.AddrDel(link, &addr)) + } + } + + addr6, err := netlink.ParseAddr(ipv6.String()) + check(err) + addrs, err = netlink.AddrList(link, unix.AF_INET6) + check(err) + for _, addr := range addrs { + if !addr.Equal(*addr6) { + check(netlink.AddrDel(link, &addr)) + } + } + + check(netlink.AddrReplace(link, addr4)) + check(netlink.AddrReplace(link, addr6)) +} + +func AddPeer(name string, peer v1alpha.VPNPeer) { + client, err := wgctrl.New() + check(err) + + publicKey, err := wgtypes.ParseKey(peer.Spec.PublicKey) + check(err) + + allowedIPs := []net.IPNet{ + { + IP: net.ParseIP(peer.Spec.AddressV4), + Mask: net.CIDRMask(32, 32), + }, + { + IP: net.ParseIP(peer.Spec.AddressV6), + Mask: net.CIDRMask(128, 128), + }, + } + + var endpoint *net.UDPAddr + if peer.Spec.EndpointAddress != nil && peer.Spec.EndpointPort != nil { + endpoint = &net.UDPAddr{ + IP: net.ParseIP(*peer.Spec.EndpointAddress), + Port: *peer.Spec.EndpointPort, + } + } + + keepaliveInterval := 5 * time.Second + + peerConfig := wgtypes.PeerConfig{ + AllowedIPs: allowedIPs, + Endpoint: endpoint, + PublicKey: publicKey, + PersistentKeepaliveInterval: &keepaliveInterval, + Remove: false, + ReplaceAllowedIPs: true, + UpdateOnly: false, + } + + deviceConfig := wgtypes.Config{ + Peers: []wgtypes.PeerConfig{peerConfig}, + ReplacePeers: false, + } + + check(client.ConfigureDevice(name, deviceConfig)) +} diff --git a/pkg/platforms/platforms.go b/pkg/platforms/platforms.go index 4e72106..48188e6 100644 --- a/pkg/platforms/platforms.go +++ b/pkg/platforms/platforms.go @@ -68,13 +68,12 @@ func Detect() string { // GCP log.Printf("try-detect=%s", GCP) - _, err = gcpmetadata.InstanceName() - if err == nil { + name, err := gcpmetadata.InstanceName() + if err == nil && name != "" { return GCP } // GENI - if utils.Exists("/usr/local/etc/emulab") { return GENI } @@ -105,3 +104,13 @@ func Detect() string { // Fallback return Generic } + +// IsCloud returns whether the platform is a cloud provider or not. +func IsCloud(platform string) bool { + switch platform { + case Azure, EC2, GCP, SCW: + return true + default: + return false + } +} diff --git a/pkg/utils/ip.go b/pkg/utils/ip.go new file mode 100644 index 0000000..982016e --- /dev/null +++ b/pkg/utils/ip.go @@ -0,0 +1,40 @@ +package utils + +import ( + "fmt" + "net" +) + +// IPWithMask stores an IP address and its associated network mask. +// It _semantically_ differs from IPNet which stores a network address. +type IPWithMask struct { + IP net.IP + Mask net.IPMask +} + +func (IP IPWithMask) String() string { + ones, _ := IP.Mask.Size() + return fmt.Sprintf("%s/%d", IP.IP.String(), ones) +} + +func (IP *IPWithMask) FromString(s string) error { + ip, ipnet, err := net.ParseCIDR(s) + if err == nil { + IP.IP = ip + IP.Mask = ipnet.Mask + } + return err +} + +func (IP IPWithMask) MarshalYAML() (interface{}, error) { + return IP.String(), nil +} + +func (IP *IPWithMask) UnmarshalYAML(unmarshal func(interface{}) error) error { + s := "" + err := unmarshal(&s) + if err != nil { + return err + } + return IP.FromString(s) +} diff --git a/pkg/utils/utils.go b/pkg/utils/os.go similarity index 100% rename from pkg/utils/utils.go rename to pkg/utils/os.go diff --git a/pkg/utils/rand.go b/pkg/utils/rand.go new file mode 100644 index 0000000..9ac94ae --- /dev/null +++ b/pkg/utils/rand.go @@ -0,0 +1,41 @@ +package utils + +import ( + "encoding/binary" + "math/rand" + "net" + "time" +) + +// firstLastIPv4 return the first and the last IP of an IPv4 network, +// excluding the network and the broadcast address. +func firstLastIPv4(network net.IPNet) (uint32, uint32) { + ones, bits := network.Mask.Size() + if bits > 32 || ones > 30 { + panic("IPv4 network <= /30 expected") + } + // https://stackoverflow.com/a/60542265 + mask := binary.BigEndian.Uint32(network.Mask) + first := binary.BigEndian.Uint32(network.IP) + last := (first & mask) | (mask ^ 0xffffffff) + return first + 1, last - 1 +} + +// TODO: Cleanup, this is horrible... :-) +func RandIPv4(network net.IPNet, excluded []net.IP) net.IP { + excludedMap := make(map[uint32]bool) + for _, ip := range excluded { + excludedMap[binary.BigEndian.Uint32(ip.To4())] = true + } + rand.Seed(time.Now().UnixNano()) + first, last := firstLastIPv4(network) + for i := 0; i < 1000; i++ { + candidate := uint32(rand.Int63n(int64(last-first+1)) + int64(first)) + if _, found := excludedMap[candidate]; !found { + ip := make(net.IP, 4) + binary.BigEndian.PutUint32(ip, candidate) + return ip + } + } + return nil +} diff --git a/pkg/utils/rand_test.go b/pkg/utils/rand_test.go new file mode 100644 index 0000000..c2d0533 --- /dev/null +++ b/pkg/utils/rand_test.go @@ -0,0 +1,63 @@ +package utils + +import ( + "net" + "testing" +) + +func Test_firstLastIPv4(t *testing.T) { + type args struct { + network net.IPNet + } + _, net1, _ := net.ParseCIDR("0.0.0.0/0") + _, net2, _ := net.ParseCIDR("192.168.142.0/24") + tests := []struct { + name string + args args + want uint32 + want1 uint32 + }{ + {"0.0.0.0/0", args{*net1}, 1, 4294967294}, + {"192.168.142.0/24", args{*net2}, 3232271873, 3232272126}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, got1 := firstLastIPv4(tt.args.network) + if got != tt.want { + t.Errorf("firstLastIPv4() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("firstLastIPv4() got1 = %v, want %v", got1, tt.want1) + } + }) + } +} + +func Test_RandIPv4(t *testing.T) { + type args struct { + network net.IPNet + excluded []net.IP + } + _, net1, _ := net.ParseCIDR("192.168.142.0/30") + tests := []struct { + name string + args args + want net.IP + }{ + {"192.168.142.0/30", + args{*net1, []net.IP{net.ParseIP("192.168.142.2")}}, + net.ParseIP("192.168.142.1"), + }, + {"192.168.142.0/30", + args{*net1, []net.IP{net.ParseIP("192.168.142.1")}}, + net.ParseIP("192.168.142.2"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := RandIPv4(tt.args.network, tt.args.excluded); !got.Equal(tt.want) { + t.Errorf("randIPv4() = %v, want %v", got, tt.want) + } + }) + } +}