diff --git a/go.mod b/go.mod index ff4bcc96..d1862a7d 100644 --- a/go.mod +++ b/go.mod @@ -7,12 +7,12 @@ require ( github.com/Masterminds/semver v1.5.0 github.com/briandowns/spinner v1.19.0 github.com/fatih/color v1.13.0 + github.com/go-playground/validator/v10 v10.14.1 github.com/go-sql-driver/mysql v1.6.0 github.com/google/go-cmp v0.5.9 github.com/onsi/ginkgo/v2 v2.4.0 github.com/onsi/gomega v1.23.0 github.com/spf13/cobra v1.6.1 - github.com/stretchr/testify v1.8.1 gopkg.in/yaml.v3 v3.0.1 helm.sh/helm/v3 v3.11.1 k8s.io/api v0.26.0 @@ -50,12 +50,15 @@ require ( github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/go-errors/errors v1.0.1 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/swag v0.19.14 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect @@ -76,6 +79,7 @@ require ( github.com/klauspost/compress v1.13.6 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect + github.com/leodido/go-urn v1.2.4 // indirect github.com/lib/pq v1.10.7 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.6 // indirect @@ -98,7 +102,6 @@ require ( github.com/opencontainers/image-spec v1.1.0-rc2 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect @@ -114,13 +117,13 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xlab/treeprint v1.1.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/net v0.7.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/net v0.8.0 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect @@ -134,7 +137,7 @@ require ( k8s.io/kubectl v0.26.0 // indirect k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect oras.land/oras-go v1.2.2 // indirect - sigs.k8s.io/controller-runtime v0.13.0 // indirect + sigs.k8s.io/controller-runtime v0.12.3 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/kustomize/api v0.12.1 // indirect sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect diff --git a/go.sum b/go.sum index 160afc72..428d204b 100644 --- a/go.sum +++ b/go.sum @@ -163,6 +163,8 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -191,6 +193,13 @@ github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXym github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +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.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.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= +github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= @@ -372,6 +381,8 @@ github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +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/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= @@ -557,8 +568,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -609,8 +620,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -691,8 +702,8 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -788,13 +799,13 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -805,8 +816,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1047,8 +1058,8 @@ oras.land/oras-go v1.2.2/go.mod h1:Apa81sKoZPpP7CDciE006tSZ0x3Q3+dOoBcMZ/aNxvw= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= -sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= +sigs.k8s.io/controller-runtime v0.12.3 h1:FCM8xeY/FI8hoAfh/V4XbbYMY20gElh9yh+A98usMio= +sigs.k8s.io/controller-runtime v0.12.3/go.mod h1:qKsk4WE6zW2Hfj0G4v10EnNB2jMG1C+NTb8h+DwCoU0= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kind v0.17.0 h1:CScmGz/wX66puA06Gj8OZb76Wmk7JIjgWf5JDvY7msM= diff --git a/pkg/deployer/baremetal/config.go b/pkg/deployer/baremetal/config.go index de7a7b8a..f05e0ece 100644 --- a/pkg/deployer/baremetal/config.go +++ b/pkg/deployer/baremetal/config.go @@ -16,21 +16,12 @@ package baremetal import ( "fmt" - "net" - "os" - "reflect" - "strconv" - "strings" -) - -const ( - ValidationTag = "validate" - validateNotNil = "not-nil" - validateNotEmpty = "not-empty" - validateIsAddr = "is-addr" + "github.com/go-playground/validator/v10" ) +var validate *validator.Validate + // Config is the desired state of a GreptimeDB cluster on bare metal. // // The field of Config that with `validate` tag will be validated @@ -38,56 +29,56 @@ const ( // // Each field of Config can also have its own exported method `Validate`. type Config struct { - Cluster *Cluster `yaml:"cluster" validate:"not-nil"` - Etcd *Etcd `yaml:"etcd" validate:"not-nil"` + Cluster *Cluster `yaml:"cluster" validate:"required"` + Etcd *Etcd `yaml:"etcd" validate:"required"` } type Cluster struct { - Artifact *Artifact `yaml:"artifact" validate:"not-nil"` - Frontend *Frontend `yaml:"frontend" validate:"not-nil"` - Meta *Meta `yaml:"meta" validate:"not-nil"` - Datanode *Datanode `yaml:"datanode" validate:"not-nil"` + Artifact *Artifact `yaml:"artifact" validate:"required"` + Frontend *Frontend `yaml:"frontend" validate:"required"` + Meta *Meta `yaml:"meta" validate:"required"` + Datanode *Datanode `yaml:"datanode" validate:"required"` } type Frontend struct { - GRPCAddr string `yaml:"grpcAddr" validate:"is-addr"` - HTTPAddr string `yaml:"httpAddr" validate:"is-addr"` - PostgresAddr string `yaml:"postgresAddr" validate:"is-addr"` - MetaAddr string `yaml:"metaAddr" validate:"is-addr"` + GRPCAddr string `yaml:"grpcAddr" validate:"omitempty,hostname_port"` + HTTPAddr string `yaml:"httpAddr" validate:"omitempty,hostname_port"` + PostgresAddr string `yaml:"postgresAddr" validate:"omitempty,hostname_port"` + MetaAddr string `yaml:"metaAddr" validate:"omitempty,hostname_port"` LogLevel string `yaml:"logLevel"` } type Datanode struct { - Replicas int `yaml:"replicas"` - NodeID int `yaml:"nodeID"` + Replicas int `yaml:"replicas" validate:"gt=0"` + NodeID int `yaml:"nodeID" validate:"gte=0"` - RPCAddr string `yaml:"rpcAddr" validate:"not-empty,is-addr"` - HTTPAddr string `yaml:"httpAddr" validate:"not-empty,is-addr"` + RPCAddr string `yaml:"rpcAddr" validate:"required,hostname_port"` + HTTPAddr string `yaml:"httpAddr" validate:"required,hostname_port"` - DataDir string `yaml:"dataDir"` - WalDir string `yaml:"walDir"` - ProcedureDir string `yaml:"procedureDir"` + DataDir string `yaml:"dataDir" validate:"omitempty,dirpath"` + WalDir string `yaml:"walDir" validate:"omitempty,dirpath"` + ProcedureDir string `yaml:"procedureDir" validate:"omitempty,dirpath"` LogLevel string `yaml:"logLevel"` } type Meta struct { - StoreAddr string `yaml:"storeAddr" validate:"is-addr"` - ServerAddr string `yaml:"serverAddr" validate:"is-addr"` - BindAddr string `yaml:"bindAddr" validate:"is-addr"` - HTTPAddr string `yaml:"httpAddr" validate:"not-empty,is-addr"` + StoreAddr string `yaml:"storeAddr" validate:"hostname_port"` + ServerAddr string `yaml:"serverAddr" validate:"hostname_port"` + BindAddr string `yaml:"bindAddr" validate:"omitempty,hostname_port"` + HTTPAddr string `yaml:"httpAddr" validate:"required,hostname_port"` LogLevel string `yaml:"logLevel"` } type Etcd struct { - Artifact *Artifact `yaml:"artifact" validate:"not-nil"` + Artifact *Artifact `yaml:"artifact" validate:"required"` } type Artifact struct { // Local is the local path of binary(greptime or etcd). - Local string `yaml:"local"` + Local string `yaml:"local" validate:"omitempty,file"` // Version is the release version of binary(greptime or etcd). // Usually, it points to the version of binary of GitHub release. @@ -100,123 +91,24 @@ func ValidateConfig(config *Config) error { return fmt.Errorf("no config to validate") } - err := validateConfigWithSingleValue(config, "") - if err != nil { - return err - } - - return nil -} - -// validateConfigWithSingleValue validate every single config value. -func validateConfigWithSingleValue(config interface{}, path string) error { - valueOf := reflect.ValueOf(config) - if valueOf.Kind() == reflect.Ptr { - valueOf = valueOf.Elem() - } - if valueOf.Kind() != reflect.Struct { - return nil - } - - typeOf := reflect.TypeOf(config) - if typeOf.Kind() == reflect.Ptr { - typeOf = typeOf.Elem() - } - for i := 0; i < valueOf.NumField(); i++ { - validateTypes := typeOf.Field(i).Tag.Get(ValidationTag) - - fieldPath := fmt.Sprintf("%s.%s", path, typeOf.Field(i).Name) - if len(validateTypes) > 0 { - if err := validateTags(validateTypes, valueOf.Field(i)); err != nil { - return fmt.Errorf("error at field `%s`: %v", fieldPath, err) - } - } - // Perform field validation that defined by `Validate` method. - if method := valueOf.Field(i).MethodByName("Validate"); method.IsValid() { - if err := method.Call(nil)[0]; !err.IsNil() { - return fmt.Errorf("error at field `%s`: %v", fieldPath, err) - } - } - - if err := validateConfigWithSingleValue(valueOf.Field(i).Interface(), fieldPath); err != nil { - return err - } - } - return nil -} + validate = validator.New() -func validateTags(types string, value reflect.Value) error { - tags := strings.Split(types, ",") - for _, tag := range tags { - switch tag { - case validateNotNil: - if value.Type().Kind() == reflect.Ptr && value.IsNil() { - return fmt.Errorf("got nil") - } - case validateNotEmpty: - if value.Type().Kind() != reflect.Ptr && value.Len() == 0 { - return fmt.Errorf("got empty") - } - case validateIsAddr: - if value.Type().Kind() == reflect.String && value.Len() > 0 { - return validateAddr(value.String()) - } - default: - return fmt.Errorf("unfamiliar validation tag: %s", tag) - } - } - return nil -} + // Register custom validation method for Artifact. + validate.RegisterStructValidation(ValidateArtifact, Artifact{}) -func validateAddr(addr string) error { - addr, port, err := net.SplitHostPort(addr) + err := validate.Struct(config) if err != nil { return err } - ip := net.ParseIP(addr) - if ip == nil { - return fmt.Errorf("invalid ip address '%s'", addr) - } - - p, err := strconv.Atoi(port) - if err != nil || p < 1 || p > 65535 { - return fmt.Errorf("invalid port '%s'", port) - } - return nil } -func (datanode *Datanode) Validate() error { - if datanode.Replicas <= 0 { - return fmt.Errorf("invalid replicas '%d'", datanode.Replicas) - } - - if datanode.NodeID < 0 { - return fmt.Errorf("invalid nodeID '%d'", datanode.NodeID) +func ValidateArtifact(sl validator.StructLevel) { + artifact := sl.Current().Interface().(Artifact) + if len(artifact.Version) == 0 && len(artifact.Local) == 0 { + sl.ReportError(sl.Current().Interface(), "Artifact", "Version/Local", "", "") } - return nil -} - -func (artifact *Artifact) Validate() error { - if artifact.Version == "" && artifact.Local == "" { - return fmt.Errorf("empty artifact") - } - - if artifact.Local != "" { - fileinfo, err := os.Stat(artifact.Local) - if os.IsNotExist(err) { - return fmt.Errorf("artifact '%s' not exist", artifact.Local) - } - if fileinfo.IsDir() { - return fmt.Errorf("artifact '%s' should be file, not directory", artifact.Local) - } - if err != nil { - return err - } - } - - return nil } func defaultConfig() *Config { diff --git a/pkg/deployer/baremetal/config_test.go b/pkg/deployer/baremetal/config_test.go deleted file mode 100644 index f74c316d..00000000 --- a/pkg/deployer/baremetal/config_test.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2023 Greptime Team -// -// 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 baremetal - -import ( - "fmt" - "os" - "testing" - - "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v3" -) - -type testCase struct { - name string - expect bool - errmsg string -} - -var testCases = []testCase{ - { - name: "default-config", - expect: true, - }, - { - name: "config-with-nil-part", - expect: false, - errmsg: "error at field `.Cluster.Meta`: got nil", - }, - { - name: "config-with-empty-part", - expect: false, - errmsg: "error at field `.Cluster.Datanode.HTTPAddr`: got empty", - }, - { - name: "config-with-invalid-addr", - expect: false, - errmsg: "error at field `.Cluster.Datanode.HTTPAddr`: invalid ip address '12345.0.0.0'", - }, -} - -func TestValidateConfig(t *testing.T) { - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - content, err := os.ReadFile(fmt.Sprintf("testdata/%s.yaml", tc.name)) - assert.NoError(t, err) - - var config *Config - err = yaml.Unmarshal(content, &config) - assert.NoError(t, err) - - err = ValidateConfig(config) - if tc.expect { - assert.NoError(t, err) - } else { - assert.EqualError(t, err, tc.errmsg, "got wrong error") - } - }) - } -} diff --git a/pkg/deployer/baremetal/testdata/config-with-empty-part.yaml b/pkg/deployer/baremetal/testdata/config-with-empty-part.yaml deleted file mode 100644 index a4f07e34..00000000 --- a/pkg/deployer/baremetal/testdata/config-with-empty-part.yaml +++ /dev/null @@ -1,16 +0,0 @@ -cluster: - name: test - artifact: - version: latest - frontend: {} - datanode: - replicas: 3 - rpcAddr: 0.0.0.0:14100 - mysqlAddr: 0.0.0.0:14200 - meta: - storeAddr: 127.0.0.1:2379 - serverAddr: 0.0.0.0:3002 - httpAddr: 0.0.0.0:14001 -etcd: - artifact: - version: v3.5.7 diff --git a/pkg/deployer/baremetal/testdata/config-with-invalid-addr.yaml b/pkg/deployer/baremetal/testdata/config-with-invalid-addr.yaml deleted file mode 100644 index 366b400f..00000000 --- a/pkg/deployer/baremetal/testdata/config-with-invalid-addr.yaml +++ /dev/null @@ -1,17 +0,0 @@ -cluster: - name: test - artifact: - version: latest - frontend: {} - datanode: - replicas: 3 - rpcAddr: 0.0.0.0:14100 - mysqlAddr: 0.0.0.0:14200 - httpAddr: 12345.0.0.0:14300 - meta: - storeAddr: 127.0.0.1:2379 - serverAddr: 0.0.0.0:3002 - httpAddr: 0.0.0.0:14001 -etcd: - artifact: - version: v3.5.7 diff --git a/pkg/deployer/baremetal/testdata/config-with-nil-part.yaml b/pkg/deployer/baremetal/testdata/config-with-nil-part.yaml deleted file mode 100644 index 5be4ef49..00000000 --- a/pkg/deployer/baremetal/testdata/config-with-nil-part.yaml +++ /dev/null @@ -1,13 +0,0 @@ -cluster: - name: test - artifact: - version: latest - frontend: {} - datanode: - replicas: 3 - rpcAddr: 0.0.0.0:14100 - mysqlAddr: 0.0.0.0:14200 - httpAddr: 0.0.0.0:14300 -etcd: - artifact: - version: v3.5.7 diff --git a/pkg/deployer/baremetal/testdata/default-config.yaml b/pkg/deployer/baremetal/testdata/default-config.yaml deleted file mode 100644 index 3cb914dc..00000000 --- a/pkg/deployer/baremetal/testdata/default-config.yaml +++ /dev/null @@ -1,17 +0,0 @@ -cluster: - name: test - artifact: - version: latest - frontend: {} - datanode: - replicas: 3 - rpcAddr: 0.0.0.0:14100 - mysqlAddr: 0.0.0.0:14200 - httpAddr: 0.0.0.0:14300 - meta: - storeAddr: 127.0.0.1:2379 - serverAddr: 0.0.0.0:3002 - httpAddr: 0.0.0.0:14001 -etcd: - artifact: - version: v3.5.7