diff --git a/go.mod b/go.mod index 7729c91..6868a4b 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/cors v1.4.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect diff --git a/go.sum b/go.sum index 2ffcb02..d6c409f 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,11 @@ github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhF github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g= +github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -25,16 +28,21 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -66,17 +74,21 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -90,10 +102,14 @@ github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE= github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -102,6 +118,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -111,6 +128,8 @@ github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gt github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -121,6 +140,7 @@ golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -130,6 +150,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= @@ -140,15 +161,21 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= @@ -167,17 +194,21 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6 google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= diff --git a/handler/common/client.go b/handler/common/client.go index 9b19d2f..0852004 100644 --- a/handler/common/client.go +++ b/handler/common/client.go @@ -22,9 +22,9 @@ func GetClientSet() (*kubernetes.Clientset, error) { // 2. 配置 kubeconfig, 得到client(ClientSet)对象 // 配置文件位置 - kubeConfigPath := ".kube/config" + //kubeConfigPath := kubeConfigPath // 构建配置,读取配置文件内容,解析为配置对象 - config, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath) + config, err := clientcmd.BuildConfigFromFlags("", KubeConfigPath) if err != nil { return nil, err } diff --git a/handler/common/constant.go b/handler/common/constant.go new file mode 100644 index 0000000..7e0f9b6 --- /dev/null +++ b/handler/common/constant.go @@ -0,0 +1,5 @@ +package common + +const ( + KubeConfigPath = ".kube/config" +) diff --git a/handler/config/handler.go b/handler/config/handler.go new file mode 100644 index 0000000..9afff06 --- /dev/null +++ b/handler/config/handler.go @@ -0,0 +1,122 @@ +package config + +import ( + "io" + "k8s-manager/handler/common" + "log" + "net/http" + "os" + "path/filepath" + + "k8s.io/client-go/tools/clientcmd" + + "github.com/gin-gonic/gin" +) + +// 配置文件上传接口的handler + +func Upload(ctx *gin.Context) { + + // 1. 获取上传的临时文件, post/put, + tmpFile, err := ctx.FormFile("config") + if err != nil { + log.Println(err) + ctx.JSON(http.StatusOK, gin.H{ + "code": 1, + "message": err.Error(), + }) + return + } + + // 2. 校验配置文件是否合理 + // clientcmd.Validate(config) + // 打开文件,读取文件内容,加载为配置,校验合法性 + // 打开文件 + file, err := tmpFile.Open() + if err != nil { + log.Println(err) + ctx.JSON(http.StatusOK, gin.H{ + "code": 1, + "message": err.Error(), + }) + return + } + // 读取文件内容 + content, err := io.ReadAll(file) + if err != nil { + log.Println(err) + ctx.JSON(http.StatusOK, gin.H{ + "code": 1, + "message": err.Error(), + }) + return + } + // 加载为配置 + config, err := clientcmd.Load(content) + if err != nil { + log.Println(err) + ctx.JSON(http.StatusOK, gin.H{ + "code": 1, + "message": err.Error(), + }) + return + } + // 校验合法性 + if err := clientcmd.Validate(*config); err != nil { + log.Println(err) + ctx.JSON(http.StatusOK, gin.H{ + "code": 1, + "message": err.Error(), + }) + return + } + + // 3. 将配置文件存储在正确的位置 + // 设置目标位置 + //kubeConfigPath := common.KubeConfigPath + // 创建必要的目录 + dir := filepath.Dir(common.KubeConfigPath) + if err := os.MkdirAll(dir, 0644); err != nil { + log.Println(err) + ctx.JSON(http.StatusOK, gin.H{ + "code": 1, + "message": err.Error(), + }) + return + } + // 将临时文件存储到目标位置 + if err := ctx.SaveUploadedFile(tmpFile, common.KubeConfigPath); err != nil { + log.Println(err) + ctx.JSON(http.StatusOK, gin.H{ + "code": 1, + "message": err.Error(), + }) + return + } + + // 4. 成功的响应 + ctx.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "config file uploaded", + }) + +} + +func Config(ctx *gin.Context) { + // 1. 读取文件内容 + content, err := os.ReadFile(common.KubeConfigPath) + if err != nil { + log.Println(err) + ctx.JSON(http.StatusOK, gin.H{ + "code": 1, + "message": err.Error(), + }) + return + } + + // 2. 响应 + ctx.JSON(http.StatusOK, gin.H{ + "code": 0, + "data": string(content), + }) +} diff --git a/handler/node/handler.go b/handler/node/handler.go index 021039b..3678d39 100644 --- a/handler/node/handler.go +++ b/handler/node/handler.go @@ -18,7 +18,8 @@ func List(ctx *gin.Context) { if err != nil { log.Println(err) ctx.JSON(http.StatusOK, gin.H{ - "code": 1, + // code == 2, 意味着配置文件有问题 + "code": 2, "message": err.Error(), }) return diff --git a/main.go b/main.go index 24cd9af..0acaa69 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,12 @@ package main import ( + "k8s-manager/handler/config" "k8s-manager/handler/node" "k8s-manager/handler/sys" + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" ) @@ -11,9 +14,22 @@ func main() { // 初始化默认的路由引擎 r := gin.Default() + // 中间件 middle ware + corsDC := cors.DefaultConfig() + // 配置响应头,通过属性配置 + corsDC.AllowAllOrigins = true // 允许全部的源,访问 + corsDC.AllowCredentials = true + corsDC.AddAllowHeaders("Authorization") + // 应用到全部路上 + r.Use(cors.New(corsDC)) + // 定义路由 r.GET("/ping", sys.Ping) r.GET("/node/get", node.List) + r.POST("/config/upload", config.Upload) + r.GET("/config", config.Config) + + r.Static("/ui", "./ui") r.Run(":8080") // 监听并在 0.0.0.0:8080 上启动服务 } diff --git a/test/clientSet.go b/test/clientSet.go new file mode 100644 index 0000000..1f111dc --- /dev/null +++ b/test/clientSet.go @@ -0,0 +1,39 @@ +package test + +import ( + "context" + "k8s-manager/handler/common" + "log" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "k8s.io/client-go/kubernetes" + + "k8s.io/client-go/tools/clientcmd" +) + +func ClientSetDeployments() { + // 1. 初始化配置 + // 加载配置 + config, err := clientcmd.BuildConfigFromFlags("", "../"+common.KubeConfigPath) + if err != nil { + log.Fatalln(err) + } + + // 2. 获取clientSet客户端 + clientSet, err := kubernetes.NewForConfig(config) + if err != nil { + log.Fatalln(err) + } + // 3. 调用封装的方法,获取资源。获取deployments + namespace := "kube-system" + deploymentList, err := clientSet.AppsV1().Deployments(namespace).List(context.Background(), metav1.ListOptions{}) + if err != nil { + log.Fatalln(err) + } + + // 4. 处理响应 + for _, item := range deploymentList.Items { + log.Printf("NAME: %s READY: %d/%d AVAILABLE: %d", item.Name, item.Status.ReadyReplicas, item.Status.Replicas, item.Status.AvailableReplicas) + } +} diff --git a/test/clientSet_test.go b/test/clientSet_test.go new file mode 100644 index 0000000..247604e --- /dev/null +++ b/test/clientSet_test.go @@ -0,0 +1,7 @@ +package test + +import "testing" + +func TestClientSetDeployments(t *testing.T) { + ClientSetDeployments() +} diff --git a/test/discoveryClient.go b/test/discoveryClient.go new file mode 100644 index 0000000..1bb136b --- /dev/null +++ b/test/discoveryClient.go @@ -0,0 +1,59 @@ +package test + +import ( + "k8s-manager/handler/common" + "log" + + "k8s.io/client-go/discovery" + + "k8s.io/client-go/tools/clientcmd" +) + +func DiscoveryClientGroupAndVersions() { + //discovery.DiscoveryClient{} + + // 1. 配置 + config, err := clientcmd.BuildConfigFromFlags("", "../"+common.KubeConfigPath) + if err != nil { + log.Fatalln(err) + } + + // 2. 客户端 + discoveryClient, err := discovery.NewDiscoveryClientForConfig(config) + if err != nil { + log.Fatalln(err) + } + + // 3. 获取资源,获取全部的组和版本资源 + apiGroups, apiResourceList, err := discoveryClient.ServerGroupsAndResources() + if err != nil { + log.Fatalln(err) + } + + // 4. 处理结果 + // groups + for _, g := range apiGroups { + log.Println("----------------Group----------------") + log.Printf("Name: %s \n", g.Name) + + // version + + log.Println("================Versions================") + for _, v := range g.Versions { + log.Printf("GroupVersion: %s \n", v.GroupVersion) + } + } + log.Println("******************************************************") + // apiResourceList + for _, ar := range apiResourceList { + log.Println("----------------apiResource----------------") + log.Printf("GroupVerion: %s, ", ar.GroupVersion) + + log.Println("----------------Resources----------------") + for _, r := range ar.APIResources { + log.Printf("Name: %s Namespace: %v\n", r.Name, r.Namespaced) + } + } + + //log.Println(_) +} diff --git a/test/discoveryClient_test.go b/test/discoveryClient_test.go new file mode 100644 index 0000000..29b7ef3 --- /dev/null +++ b/test/discoveryClient_test.go @@ -0,0 +1,7 @@ +package test + +import "testing" + +func TestDiscoveryClientGroupAndVersions(t *testing.T) { + DiscoveryClientGroupAndVersions() +} diff --git a/test/dynamicClient.go b/test/dynamicClient.go new file mode 100644 index 0000000..16af657 --- /dev/null +++ b/test/dynamicClient.go @@ -0,0 +1,141 @@ +package test + +import ( + "context" + "k8s-manager/handler/common" + "log" + + "k8s.io/apimachinery/pkg/runtime" + + corev1 "k8s.io/api/core/v1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "k8s.io/apimachinery/pkg/runtime/schema" + + "k8s.io/client-go/dynamic" + + "k8s.io/client-go/tools/clientcmd" +) + +// DynamicClientPods native resource +func DynamicClientPods() { + // 1. 加载配置 + config, err := clientcmd.BuildConfigFromFlags("", "../"+common.KubeConfigPath) + if err != nil { + log.Fatalln(err) + } + + // 2. 获取客户端 + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + log.Fatalln(err) + } + + // 3. 获取资源,pod list + // 基于 gvr 来获取 + gvr := schema.GroupVersionResource{ + Group: "", + Version: "v1", + Resource: "pods", + } + // 发出请求,获取资源 + namespace := "kube-system" + unstructruedList, err := dynamicClient. + Resource(gvr). + Namespace(namespace). + List(context.Background(), metav1.ListOptions{}) + if err != nil { + log.Fatalln(err) + } + + // 4. 从未结构化类型转换到具体的资源类型,重要 + // 定义目标类型,由于是原生资源,可以直接使用包中定义的类型 + podList := &corev1.PodList{} + // untructured to podlist 转换 + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructruedList.UnstructuredContent(), podList); err != nil { + log.Fatalln(err) + } + + // 5. 处理结果 + for _, pod := range podList.Items { + log.Printf("Name: %s Status: %s\n", pod.Name, pod.Status.Phase) + } + + // 结构说明,动态客户端类型 + //dynamic.DynamicClient{} + // 未结构化类型 + //runtime.Unstructured{} +} + +// DynamicClientCrontabs custome resource +func DynamicClientCrontabs() { + // 1. 加载配置 + config, err := clientcmd.BuildConfigFromFlags("", "../"+common.KubeConfigPath) + if err != nil { + log.Fatalln(err) + } + + // 2. 获取客户端 + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + log.Fatalln(err) + } + + // 3. 获取资源,crontab list + // 基于 gvr 来获取 + gvr := schema.GroupVersionResource{ + Group: "stable.example.com", + Version: "v1", + Resource: "crontabs", + } + // 发出请求,获取资源 + unstructruedList, err := dynamicClient. + Resource(gvr). + List(context.Background(), metav1.ListOptions{}) + if err != nil { + log.Fatalln(err) + } + + // 4. 从未结构化类型转换到具体的资源类型,重要 + // 定义目标类型,由于是原生资源,可以直接使用包中定义的类型 + list := &CrontabList{} + // untructured to podlist 转换 + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructruedList.UnstructuredContent(), list); err != nil { + log.Fatalln(err) + } + + // 5. 处理结果 + for _, item := range list.Items { + log.Printf("Name: %s Cron: %s\n", item.Name, item.Spec.CronSpec) + } +} + +// CrontabList is a list of Crontab. +// 定义资源类型 +type CrontabList struct { + // 类型元信息 + metav1.TypeMeta `json:",inline"` + // 列表元信息 + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // 自定义资源列表 + Items []Crontab `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// Pod is a collection of containers that can run on a host. This resource is created +// by clients and scheduled onto hosts. +type Crontab struct { + // 类型元信息 + metav1.TypeMeta `json:",inline"` + // 列表元信息 + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // 特定字段 + Spec CrontabSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` +} + +// PodSpec is a description of a pod. +type CrontabSpec struct { + // 自定义的字段 + CronSpec string `json:"cronSpec,omitempty" protobuf:"bytes,1,opt,name=cronSpec"` + Image string `json:"image,omitempty" protobuf:"bytes,2,opt,name=image"` +} diff --git a/test/dynamicClient_test.go b/test/dynamicClient_test.go new file mode 100644 index 0000000..d3b34fc --- /dev/null +++ b/test/dynamicClient_test.go @@ -0,0 +1,11 @@ +package test + +import "testing" + +func TestDynamicClientPods(t *testing.T) { + DynamicClientPods() +} + +func TestDynamicClientCrontabs(t *testing.T) { + DynamicClientCrontabs() +} diff --git a/test/restClient.go b/test/restClient.go new file mode 100644 index 0000000..265c4e7 --- /dev/null +++ b/test/restClient.go @@ -0,0 +1,54 @@ +package test + +import ( + "context" + "k8s-manager/handler/common" + "log" + + "k8s.io/client-go/kubernetes/scheme" + + corev1 "k8s.io/api/core/v1" + + "k8s.io/client-go/rest" + + "k8s.io/client-go/tools/clientcmd" +) + +func RestClientPods() { + // 1. 获取RestClient + // 加载配置 + config, err := clientcmd.BuildConfigFromFlags("", "../"+common.KubeConfigPath) + if err != nil { + log.Fatalln(err) + } + // 完成基础配置 + // api 路径 + config.APIPath = "api" + // 组版本 + config.GroupVersion = &corev1.SchemeGroupVersion + // 约定的编解码器(序列化器) + config.NegotiatedSerializer = scheme.Codecs + // 获取 RestClient + restClient, err := rest.RESTClientFor(config) + if err != nil { + log.Fatalln(err) + } + + // 2. 发出获取Pods的请求 + // 结果对象 + podList := &corev1.PodList{} + // 请求配置(参数,method,选项) + namespace := "kube-system" + if err := restClient.Get(). + Resource("pods"). + Namespace(namespace). + Do(context.Background()). + Into(podList); err != nil { + log.Fatalln(err) + } + + // 3. 处理获取的响应 + for _, pod := range podList.Items { + log.Printf("Name: %s Status: %s\n", pod.Name, pod.Status.Phase) + } +} diff --git a/test/restClient_test.go b/test/restClient_test.go new file mode 100644 index 0000000..c34c5f9 --- /dev/null +++ b/test/restClient_test.go @@ -0,0 +1,8 @@ +package test + +import "testing" + +func TestRestClientPods(t *testing.T) { + //RestClientPods() + ClientSetDeployments() +} diff --git a/ui/index.html b/ui/index.html new file mode 100644 index 0000000..6c6b137 --- /dev/null +++ b/ui/index.html @@ -0,0 +1,10 @@ + + + + + K8S集群管理平台 + + + + + \ No newline at end of file