diff --git a/CHANGELOG.md b/CHANGELOG.md index bfc2aae..a307713 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ -### Version 3.2.1 +### Version 3.2.2 ### Bug fixes -- Fix bug with creating kvmvm. Now, the resource kvmvm creates with user defined network. +- Fix bug with getting kvmvm data_source + +### Features + +- Add enable/disable functionality for kvmvm resource +- Add status checker for kvmvm resource diff --git a/Dockerfile b/Dockerfile index b9ead01..13e6cf7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM docker.io/hashicorp/terraform:latest WORKDIR /opt/decort/tf/ COPY provider.tf ./ -COPY terraform-provider-decort ./terraform.d/plugins/digitalenergy.online/decort/decort/3.2.1/linux_amd64/ +COPY terraform-provider-decort ./terraform.d/plugins/digitalenergy.online/decort/decort/3.2.2/linux_amd64/ RUN terraform init WORKDIR /tf diff --git a/Makefile b/Makefile index 678e087..558254b 100644 --- a/Makefile +++ b/Makefile @@ -6,16 +6,16 @@ NAME=terraform-provider-decort BINARY=${NAME}.exe WORKPATH= ./examples/terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAMESPACE}/${VERSION}/${OS_ARCH} MAINPATH = ./cmd/decort/ -VERSION=3.2.1 +VERSION=1.1 #OS_ARCH=darwin_amd64 -#OS_ARCH=windows_amd64 +OS_ARCH=windows_amd64 #OS_ARCH=linux_amd64 default: install image: GOOS=linux GOARCH=amd64 go build -o terraform-provider-decort ./cmd/decort/ - docker build . -t rudecs/tf:3.2.1 + docker build . -t rudecs/tf:3.2.2 rm terraform-provider-decort lint: diff --git a/go.mod b/go.mod index a35ed33..6d38499 100644 --- a/go.mod +++ b/go.mod @@ -3,68 +3,68 @@ module github.com/rudecs/terraform-provider-decort go 1.18 require ( - github.com/golang-jwt/jwt/v4 v4.4.2 + github.com/golang-jwt/jwt/v4 v4.4.3 github.com/google/uuid v1.3.0 github.com/hashicorp/terraform-plugin-docs v0.13.0 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.19.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.1 github.com/sirupsen/logrus v1.9.0 - golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 + golang.org/x/net v0.4.0 ) require ( github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.1.1 // indirect - github.com/Masterminds/sprig/v3 v3.2.2 // indirect - github.com/agext/levenshtein v1.2.2 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect + github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect github.com/fatih/color v1.13.0 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect - github.com/hashicorp/go-hclog v1.2.1 // indirect + github.com/hashicorp/go-hclog v1.4.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.4 // indirect + github.com/hashicorp/go-plugin v1.4.8 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hc-install v0.4.0 // indirect - github.com/hashicorp/hcl/v2 v2.13.0 // indirect + github.com/hashicorp/hcl/v2 v2.15.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-exec v0.17.2 // indirect + github.com/hashicorp/terraform-exec v0.17.3 // indirect github.com/hashicorp/terraform-json v0.14.0 // indirect - github.com/hashicorp/terraform-plugin-go v0.12.0 // indirect - github.com/hashicorp/terraform-plugin-log v0.6.0 // indirect - github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c // indirect + github.com/hashicorp/terraform-plugin-go v0.14.2 // indirect + github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect + github.com/hashicorp/terraform-registry-address v0.1.0 // indirect github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect - github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect - github.com/huandu/xstrings v1.3.2 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect + github.com/huandu/xstrings v1.4.0 // indirect github.com/imdario/mergo v0.3.13 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/mitchellh/cli v1.1.4 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mitchellh/cli v1.1.5 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect - github.com/mitchellh/go-wordwrap v1.0.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/oklog/run v1.0.0 // indirect + github.com/oklog/run v1.1.0 // indirect github.com/posener/complete v1.2.3 // indirect github.com/russross/blackfriday v1.6.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect - github.com/vmihailenco/tagparser v0.1.1 // indirect - github.com/zclconf/go-cty v1.10.0 // indirect - golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect - golang.org/x/text v0.3.7 // indirect - google.golang.org/appengine v1.6.6 // indirect - google.golang.org/genproto v0.0.0-20200711021454-869866162049 // indirect - google.golang.org/grpc v1.48.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect + github.com/vmihailenco/tagparser v0.1.2 // indirect + github.com/zclconf/go-cty v1.12.1 // indirect + golang.org/x/crypto v0.4.0 // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/text v0.5.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 // indirect + google.golang.org/grpc v1.51.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect ) diff --git a/go.sum b/go.sum index e95fd18..5d4e732 100644 --- a/go.sum +++ b/go.sum @@ -6,9 +6,14 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJ github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.0/go.mod h1:tWhwTbUTndesPNeF0C900vKoq283u6zp4APT9vaF3SI= +github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= @@ -18,9 +23,12 @@ github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= +github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= @@ -70,6 +78,8 @@ github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU= +github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -98,6 +108,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -116,11 +128,15 @@ github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUK github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= +github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.4.4 h1:NVdrSdFRt3SkZtNckJ6tog7gbpRrcbOjQi/rgF7JYWQ= github.com/hashicorp/go-plugin v1.4.4/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= +github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -132,29 +148,46 @@ github.com/hashicorp/hc-install v0.4.0 h1:cZkRFr1WVa0Ty6x5fTvL1TuO1flul231rWkGH9 github.com/hashicorp/hc-install v0.4.0/go.mod h1:5d155H8EC5ewegao9A4PUTMNPZaq+TbOzkJJZ4vrXeI= github.com/hashicorp/hcl/v2 v2.13.0 h1:0Apadu1w6M11dyGFxWnmhhcMjkbAiKCv7G1r/2QgCNc= github.com/hashicorp/hcl/v2 v2.13.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= +github.com/hashicorp/hcl/v2 v2.15.0 h1:CPDXO6+uORPjKflkWCCwoWc9uRp+zSIPcCQ+BrxV7m8= +github.com/hashicorp/hcl/v2 v2.15.0/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/terraform-exec v0.17.2 h1:EU7i3Fh7vDUI9nNRdMATCEfnm9axzTnad8zszYZ73Go= github.com/hashicorp/terraform-exec v0.17.2/go.mod h1:tuIbsL2l4MlwwIZx9HPM+LOV9vVyEfBYu2GsO1uH3/8= +github.com/hashicorp/terraform-exec v0.17.3 h1:MX14Kvnka/oWGmIkyuyvL6POx25ZmKrjlaclkx3eErU= +github.com/hashicorp/terraform-exec v0.17.3/go.mod h1:+NELG0EqQekJzhvikkeQsOAZpsw0cv/03rbeQJqscAI= github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s= github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM= github.com/hashicorp/terraform-plugin-docs v0.13.0 h1:6e+VIWsVGb6jYJewfzq2ok2smPzZrt1Wlm9koLeKazY= github.com/hashicorp/terraform-plugin-docs v0.13.0/go.mod h1:W0oCmHAjIlTHBbvtppWHe8fLfZ2BznQbuv8+UD8OucQ= github.com/hashicorp/terraform-plugin-go v0.12.0 h1:6wW9mT1dSs0Xq4LR6HXj1heQ5ovr5GxXNJwkErZzpJw= github.com/hashicorp/terraform-plugin-go v0.12.0/go.mod h1:kwhmaWHNDvT1B3QiSJdAtrB/D4RaKSY/v3r2BuoWK4M= +github.com/hashicorp/terraform-plugin-go v0.14.2 h1:rhsVEOGCnY04msNymSvbUsXfRLKh9znXZmHlf5e8mhE= +github.com/hashicorp/terraform-plugin-go v0.14.2/go.mod h1:Q12UjumPNGiFsZffxOsA40Tlz1WVXt2Evh865Zj0+UA= github.com/hashicorp/terraform-plugin-log v0.6.0 h1:/Vq78uSIdUSZ3iqDc9PESKtwt8YqNKN6u+khD+lLjuw= github.com/hashicorp/terraform-plugin-log v0.6.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4= +github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs= +github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4= github.com/hashicorp/terraform-plugin-sdk/v2 v2.19.0 h1:7gDAcfto/C4Cjtf90SdukQshsxdMxJ/P69QxiF3digI= github.com/hashicorp/terraform-plugin-sdk/v2 v2.19.0/go.mod h1:/WYikYjhKB7c2j1HmXZhRsAARldRb4M38bLCLOhC3so= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.1 h1:zHcMbxY0+rFO9gY99elV/XC/UnQVg7FhRCbj1i5b7vM= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.1/go.mod h1:+tNlb0wkfdsDJ7JEiERLz4HzM19HyiuIoGzTsM7rPpw= github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c h1:D8aRO6+mTqHfLsK/BC3j5OAoogv1WLRWzY1AaTo3rBg= github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c/go.mod h1:Wn3Na71knbXc1G8Lh+yu/dQWWJeFQEpDeJMtWMtlmNI= +github.com/hashicorp/terraform-registry-address v0.1.0 h1:W6JkV9wbum+m516rCl5/NjKxCyTVaaUBbzYcMzBDO3U= +github.com/hashicorp/terraform-registry-address v0.1.0/go.mod h1:EnyO2jYO6j29DTHbJcm00E5nQTFeTtyZH3H5ycydQ5A= github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0= github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -180,12 +213,18 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mitchellh/cli v1.1.4 h1:qj8czE26AU4PbiaPXK5uVmMSM+V5BYsFBiM9HhGRLUA= github.com/mitchellh/cli v1.1.4/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ= +github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng= +github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -195,6 +234,8 @@ github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJ github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= @@ -204,6 +245,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -245,12 +288,17 @@ github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvC github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= +github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.10.0 h1:mp9ZXQeIcN8kAwuqorjH+Q+njbJKjLrvB2yIh4q7U+0= github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= +github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -261,12 +309,17 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= +golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -275,6 +328,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -284,6 +338,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +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.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -291,6 +349,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -311,20 +370,34 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.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/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -332,12 +405,16 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200711021454-869866162049 h1:YFTFpQhgvrLrmxtiIncJxFXeCyq84ixuKWVCaCAi9Oc= google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 h1:jmIfw8+gSvXcZSgaFAGyInDXeWzUhvYH57G/5GKMn70= +google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -346,6 +423,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -361,6 +440,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/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-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/constants/timeouts.go b/internal/constants/timeouts.go index b8faaf9..c7dce44 100644 --- a/internal/constants/timeouts.go +++ b/internal/constants/timeouts.go @@ -28,3 +28,4 @@ var Timeout180s = time.Second * 180 var Timeout300s = time.Second * 300 var Timeout600s = time.Second * 600 var Timeout20m = time.Minute * 20 +var Timeout30m = time.Minute * 30 diff --git a/internal/provider/cloudapi/data_sources_map.go b/internal/provider/cloudapi/data_sources_map.go index 7b89c1a..8bdd737 100644 --- a/internal/provider/cloudapi/data_sources_map.go +++ b/internal/provider/cloudapi/data_sources_map.go @@ -26,6 +26,7 @@ import ( "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/disks" "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/extnet" "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/image" + "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/k8s" "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm" "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/lb" "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/locations" @@ -39,6 +40,11 @@ func NewDataSourcesMap() map[string]*schema.Resource { "decort_account": account.DataSourceAccount(), "decort_resgroup": rg.DataSourceResgroup(), "decort_kvmvm": kvmvm.DataSourceCompute(), + "decort_k8s": k8s.DataSourceK8s(), + "decort_k8s_list": k8s.DataSourceK8sList(), + "decort_k8s_list_deleted": k8s.DataSourceK8sListDeleted(), + "decort_k8s_wg": k8s.DataSourceK8sWg(), + "decort_k8s_wg_list": k8s.DataSourceK8sWgList(), "decort_vins": vins.DataSourceVins(), "decort_snapshot_list": snapshot.DataSourceSnapshotList(), "decort_disk": disks.DataSourceDisk(), diff --git a/internal/service/cloudapi/k8s/api.go b/internal/service/cloudapi/k8s/api.go index ab5bf88..5cdb7c0 100644 --- a/internal/service/cloudapi/k8s/api.go +++ b/internal/service/cloudapi/k8s/api.go @@ -31,19 +31,23 @@ Documentation: https://github.com/rudecs/terraform-provider-decort/wiki package k8s -const K8sCreateAPI = "/restmachine/cloudapi/k8s/create" -const K8sGetAPI = "/restmachine/cloudapi/k8s/get" -const K8sUpdateAPI = "/restmachine/cloudapi/k8s/update" -const K8sDeleteAPI = "/restmachine/cloudapi/k8s/delete" +const ( + K8sCreateAPI = "/restmachine/cloudapi/k8s/create" + K8sGetAPI = "/restmachine/cloudapi/k8s/get" + K8sUpdateAPI = "/restmachine/cloudapi/k8s/update" + K8sDeleteAPI = "/restmachine/cloudapi/k8s/delete" + K8sListAPI = "/restmachine/cloudapi/k8s/list" + K8sListDeletedAPI = "/restmachine/cloudapi/k8s/listDeleted" -const K8sWgCreateAPI = "/restmachine/cloudapi/k8s/workersGroupAdd" -const K8sWgDeleteAPI = "/restmachine/cloudapi/k8s/workersGroupDelete" + K8sWgCreateAPI = "/restmachine/cloudapi/k8s/workersGroupAdd" + K8sWgDeleteAPI = "/restmachine/cloudapi/k8s/workersGroupDelete" -const K8sWorkerAddAPI = "/restmachine/cloudapi/k8s/workerAdd" -const K8sWorkerDeleteAPI = "/restmachine/cloudapi/k8s/deleteWorkerFromGroup" + K8sWorkerAddAPI = "/restmachine/cloudapi/k8s/workerAdd" + K8sWorkerDeleteAPI = "/restmachine/cloudapi/k8s/deleteWorkerFromGroup" -const K8sGetConfigAPI = "/restmachine/cloudapi/k8s/getConfig" + K8sGetConfigAPI = "/restmachine/cloudapi/k8s/getConfig" -const LbGetAPI = "/restmachine/cloudapi/lb/get" + LbGetAPI = "/restmachine/cloudapi/lb/get" -const AsyncTaskGetAPI = "/restmachine/cloudapi/tasks/get" + AsyncTaskGetAPI = "/restmachine/cloudapi/tasks/get" +) diff --git a/internal/service/cloudapi/k8s/data_source_k8s.go b/internal/service/cloudapi/k8s/data_source_k8s.go new file mode 100644 index 0000000..48bb523 --- /dev/null +++ b/internal/service/cloudapi/k8s/data_source_k8s.go @@ -0,0 +1,419 @@ +package k8s + +import ( + "context" + "encoding/json" + "net/url" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/rudecs/terraform-provider-decort/internal/constants" + "github.com/rudecs/terraform-provider-decort/internal/controller" + log "github.com/sirupsen/logrus" + + "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm" +) + +func dataSourceK8sRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + k8s, err := utilityDataK8sCheckPresence(ctx, d, m) + if err != nil { + return diag.FromErr(err) + } + d.SetId(strconv.FormatUint(k8s.ID, 10)) + + k8sList, err := utilityK8sListCheckPresence(ctx, d, m, K8sListAPI) + if err != nil { + d.SetId("") + return diag.FromErr(err) + } + curK8s := K8SItem{} + for _, k8sCluster := range k8sList { + if k8sCluster.ID == k8s.ID { + curK8s = k8sCluster + } + } + if curK8s.ID == 0 { + return diag.Errorf("Cluster with id %d not found in List clusters", k8s.ID) + } + d.Set("vins_id", curK8s.VINSID) + + masterComputeList := make([]kvmvm.ComputeGetResp, 0, len(k8s.K8SGroups.Masters.DetailedInfo)) + workersComputeList := make([]kvmvm.ComputeGetResp, 0, len(k8s.K8SGroups.Workers)) + for _, masterNode := range k8s.K8SGroups.Masters.DetailedInfo { + compute, err := utilityComputeCheckPresence(ctx, d, m, masterNode.ID) + if err != nil { + return diag.FromErr(err) + } + masterComputeList = append(masterComputeList, *compute) + } + for _, worker := range k8s.K8SGroups.Workers { + for _, info := range worker.DetailedInfo { + compute, err := utilityComputeCheckPresence(ctx, d, m, info.ID) + if err != nil { + return diag.FromErr(err) + } + workersComputeList = append(workersComputeList, *compute) + } + } + + c := m.(*controller.ControllerCfg) + urlValues := &url.Values{} + urlValues.Add("k8sId", d.Id()) + kubeconfig, err := c.DecortAPICall(ctx, "POST", K8sGetConfigAPI, urlValues) + if err != nil { + log.Warnf("could not get kubeconfig: %v", err) + } + d.Set("kubeconfig", kubeconfig) + + urlValues = &url.Values{} + urlValues.Add("lbId", strconv.FormatUint(k8s.LBID, 10)) + resp, err := c.DecortAPICall(ctx, "POST", LbGetAPI, urlValues) + if err != nil { + return diag.FromErr(err) + } + + var lb LbRecord + if err := json.Unmarshal([]byte(resp), &lb); err != nil { + return diag.FromErr(err) + } + d.Set("extnet_id", lb.ExtNetID) + d.Set("lb_ip", lb.PrimaryNode.FrontendIP) + + flattenK8sData(d, *k8s, masterComputeList, workersComputeList) + return nil +} + +func aclListSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "explicit": { + Type: schema.TypeBool, + Computed: true, + }, + "guid": { + Type: schema.TypeString, + Computed: true, + }, + "right": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "user_group_id": { + Type: schema.TypeString, + Computed: true, + }, + } +} + +func aclGroupSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "account_acl": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: aclListSchemaMake(), + }, + }, + "k8s_acl": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: aclListSchemaMake(), + }, + }, + "rg_acl": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: aclListSchemaMake(), + }, + }, + } +} + +func detailedInfoSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "compute_id": { + Type: schema.TypeInt, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "tech_status": { + Type: schema.TypeString, + Computed: true, + }, + "interfaces": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: interfacesSchemaMake(), + }, + }, + "natable_vins_ip": { + Type: schema.TypeString, + Computed: true, + }, + "natable_vins_network": { + Type: schema.TypeString, + Computed: true, + }, + } +} + +func interfacesSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "def_gw": { + Type: schema.TypeString, + Computed: true, + }, + "ip_address": { + Type: schema.TypeString, + Computed: true, + }, + } +} + +func masterGroupSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "cpu": { + Type: schema.TypeInt, + Computed: true, + }, + "detailed_info": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: detailedInfoSchemaMake(), + }, + }, + "disk": { + Type: schema.TypeInt, + Computed: true, + }, + "master_id": { + Type: schema.TypeInt, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "num": { + Type: schema.TypeInt, + Computed: true, + }, + "ram": { + Type: schema.TypeInt, + Computed: true, + }, + } +} + +func k8sGroupListSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "annotations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "cpu": { + Type: schema.TypeInt, + Computed: true, + }, + "detailed_info": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: detailedInfoSchemaMake(), + }, + }, + "disk": { + Type: schema.TypeInt, + Computed: true, + }, + "guid": { + Type: schema.TypeString, + Computed: true, + }, + "id": { + Type: schema.TypeInt, + Computed: true, + }, + "labels": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "num": { + Type: schema.TypeInt, + Computed: true, + }, + "ram": { + Type: schema.TypeInt, + Computed: true, + }, + "taints": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + } +} + +func dataSourceK8sSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "k8s_id": { + Type: schema.TypeInt, + Required: true, + }, + + "acl": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: aclGroupSchemaMake(), + }, + }, + "account_id": { + Type: schema.TypeInt, + Computed: true, + }, + "account_name": { + Type: schema.TypeString, + Computed: true, + }, + "bservice_id": { + Type: schema.TypeInt, + Computed: true, + }, + "k8sci_id": { + Type: schema.TypeInt, + Computed: true, + }, + "created_by": { + Type: schema.TypeString, + Computed: true, + }, + "created_time": { + Type: schema.TypeInt, + Computed: true, + }, + "deleted_by": { + Type: schema.TypeString, + Computed: true, + }, + "deleted_time": { + Type: schema.TypeInt, + Computed: true, + }, + "extnet_id": { + Type: schema.TypeInt, + Computed: true, + Description: "ID of the external network to connect workers to. If omitted network will be chosen by the platfom.", + }, + "k8s_ci_name": { + Type: schema.TypeString, + Computed: true, + }, + "masters": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: masterGroupSchemaMake(), + }, + }, + "workers": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: k8sGroupListSchemaMake(), + }, + }, + "lb_id": { + Type: schema.TypeInt, + Computed: true, + }, + "lb_ip": { + Type: schema.TypeString, + Computed: true, + Description: "IP address of default load balancer.", + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "rg_id": { + Type: schema.TypeInt, + Computed: true, + }, + "rg_name": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "tech_status": { + Type: schema.TypeString, + Computed: true, + }, + "updated_by": { + Type: schema.TypeString, + Computed: true, + }, + "updated_time": { + Type: schema.TypeInt, + Computed: true, + }, + "kubeconfig": { + Type: schema.TypeString, + Computed: true, + Description: "Kubeconfig for cluster access.", + }, + "vins_id": { + Type: schema.TypeInt, + Computed: true, + }, + } +} + +func DataSourceK8s() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + + ReadContext: dataSourceK8sRead, + + Timeouts: &schema.ResourceTimeout{ + Read: &constants.Timeout30s, + Default: &constants.Timeout60s, + }, + + Schema: dataSourceK8sSchemaMake(), + } +} diff --git a/internal/service/cloudapi/k8s/data_source_k8s_list.go b/internal/service/cloudapi/k8s/data_source_k8s_list.go new file mode 100644 index 0000000..93a5029 --- /dev/null +++ b/internal/service/cloudapi/k8s/data_source_k8s_list.go @@ -0,0 +1,268 @@ +package k8s + +import ( + "context" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/rudecs/terraform-provider-decort/internal/constants" +) + +func dataSourceK8sListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + k8sList, err := utilityK8sListCheckPresence(ctx, d, m, K8sListAPI) + if err != nil { + d.SetId("") + return diag.FromErr(err) + } + + id := uuid.New() + d.SetId(id.String()) + flattenK8sList(d, k8sList) + + return nil +} + +func serviceAccountSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "guid": { + Type: schema.TypeString, + Computed: true, + }, + "password": { + Type: schema.TypeString, + Computed: true, + }, + "username": { + Type: schema.TypeString, + Computed: true, + }, + } +} + +func k8sWorkersGroupsSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "annotations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "cpu": { + Type: schema.TypeInt, + Computed: true, + }, + "detailed_info": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: detailedInfoSchemaMake(), + }, + }, + "disk": { + Type: schema.TypeInt, + Computed: true, + }, + "guid": { + Type: schema.TypeString, + Computed: true, + }, + "detailed_info_id": { + Type: schema.TypeInt, + Computed: true, + }, + "labels": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "num": { + Type: schema.TypeInt, + Computed: true, + }, + "ram": { + Type: schema.TypeInt, + Computed: true, + }, + "taints": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + } +} + +func createK8sListSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "includedeleted": { + Type: schema.TypeBool, + Optional: true, + }, + "page": { + Type: schema.TypeInt, + Optional: true, + }, + "size": { + Type: schema.TypeInt, + Optional: true, + }, + + "items": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account_id": { + Type: schema.TypeInt, + Computed: true, + }, + "account_name": { + Type: schema.TypeString, + Computed: true, + }, + "acl": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "bservice_id": { + Type: schema.TypeInt, + Computed: true, + }, + "ci_id": { + Type: schema.TypeInt, + Computed: true, + }, + "config": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "created_by": { + Type: schema.TypeString, + Computed: true, + }, + "created_time": { + Type: schema.TypeInt, + Computed: true, + }, + "deleted_by": { + Type: schema.TypeString, + Computed: true, + }, + "deleted_time": { + Type: schema.TypeInt, + Computed: true, + }, + "desc": { + Type: schema.TypeString, + Computed: true, + }, + "extnet_id": { + Type: schema.TypeInt, + Computed: true, + }, + "gid": { + Type: schema.TypeInt, + Computed: true, + }, + "guid": { + Type: schema.TypeInt, + Computed: true, + }, + "k8s_id": { + Type: schema.TypeInt, + Computed: true, + }, + "lb_id": { + Type: schema.TypeInt, + Computed: true, + }, + "milestones": { + Type: schema.TypeInt, + Computed: true, + }, + "k8s_name": { + Type: schema.TypeString, + Computed: true, + }, + "rg_id": { + Type: schema.TypeInt, + Computed: true, + }, + "rg_name": { + Type: schema.TypeString, + Computed: true, + }, + "service_account": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: serviceAccountSchemaMake(), + }, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "tech_status": { + Type: schema.TypeString, + Computed: true, + }, + "updated_by": { + Type: schema.TypeString, + Computed: true, + }, + "updated_time": { + Type: schema.TypeInt, + Computed: true, + }, + "vins_id": { + Type: schema.TypeInt, + Computed: true, + }, + "workers_groups": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: k8sWorkersGroupsSchemaMake(), + }, + }, + }, + }, + }, + } +} + +func dataSourceK8sListSchemaMake() map[string]*schema.Schema { + k8sListSchema := createK8sListSchema() + return k8sListSchema +} + +func DataSourceK8sList() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + + ReadContext: dataSourceK8sListRead, + + Timeouts: &schema.ResourceTimeout{ + Read: &constants.Timeout30s, + Default: &constants.Timeout60s, + }, + + Schema: dataSourceK8sListSchemaMake(), + } +} diff --git a/internal/service/cloudapi/k8s/data_source_k8s_list_deleted.go b/internal/service/cloudapi/k8s/data_source_k8s_list_deleted.go new file mode 100644 index 0000000..6083319 --- /dev/null +++ b/internal/service/cloudapi/k8s/data_source_k8s_list_deleted.go @@ -0,0 +1,45 @@ +package k8s + +import ( + "context" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/rudecs/terraform-provider-decort/internal/constants" +) + +func dataSourceK8sListDeletedRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + k8sList, err := utilityK8sListCheckPresence(ctx, d, m, K8sListDeletedAPI) + if err != nil { + d.SetId("") + return diag.FromErr(err) + } + + id := uuid.New() + d.SetId(id.String()) + flattenK8sList(d, k8sList) + + return nil +} + +func dataSourceK8sListDeletedSchemaMake() map[string]*schema.Schema { + k8sListDeleted := createK8sListSchema() + delete(k8sListDeleted, "includedeleted") + return k8sListDeleted +} + +func DataSourceK8sListDeleted() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + + ReadContext: dataSourceK8sListDeletedRead, + + Timeouts: &schema.ResourceTimeout{ + Read: &constants.Timeout30s, + Default: &constants.Timeout60s, + }, + + Schema: dataSourceK8sListDeletedSchemaMake(), + } +} diff --git a/internal/service/cloudapi/k8s/data_source_k8s_wg_list.go b/internal/service/cloudapi/k8s/data_source_k8s_wg_list.go new file mode 100644 index 0000000..030fe6d --- /dev/null +++ b/internal/service/cloudapi/k8s/data_source_k8s_wg_list.go @@ -0,0 +1,129 @@ +package k8s + +import ( + "context" + "encoding/json" + "net/url" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/rudecs/terraform-provider-decort/internal/constants" + "github.com/rudecs/terraform-provider-decort/internal/controller" + "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm" +) + +func flattenWgList(wgList K8SGroupList, computesMap map[uint64][]kvmvm.ComputeGetResp) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + for _, wg := range wgList { + computes := computesMap[wg.ID] + temp := map[string]interface{}{ + "annotations": wg.Annotations, + "cpu": wg.CPU, + "wg_id": wg.ID, + "detailed_info": flattenDetailedInfo(wg.DetailedInfo, computes), + "disk": wg.Disk, + "guid": wg.GUID, + "labels": wg.Labels, + "name": wg.Name, + "num": wg.Num, + "ram": wg.RAM, + "taints": wg.Taints, + } + + res = append(res, temp) + } + return res +} + +func flattenItemsWg(d *schema.ResourceData, wgList K8SGroupList, computes map[uint64][]kvmvm.ComputeGetResp) { + d.Set("items", flattenWgList(wgList, computes)) +} + +func utilityK8sWgListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (K8SGroupList, error) { + + c := m.(*controller.ControllerCfg) + urlValues := &url.Values{} + urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int))) + + resp, err := c.DecortAPICall(ctx, "POST", K8sGetAPI, urlValues) + if err != nil { + return nil, err + } + + if resp == "" { + return nil, nil + } + + var k8s K8SRecord + if err := json.Unmarshal([]byte(resp), &k8s); err != nil { + return nil, err + } + + return k8s.K8SGroups.Workers, nil +} + +func dataSourceK8sWgListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + wgList, err := utilityK8sWgListCheckPresence(ctx, d, m) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(strconv.Itoa(d.Get("k8s_id").(int))) + + workersComputeList := make(map[uint64][]kvmvm.ComputeGetResp) + for _, worker := range wgList { + workersComputeList[worker.ID] = make([]kvmvm.ComputeGetResp, 0, len(worker.DetailedInfo)) + for _, info := range worker.DetailedInfo { + compute, err := utilityComputeCheckPresence(ctx, d, m, info.ID) + if err != nil { + return diag.FromErr(err) + } + workersComputeList[worker.ID] = append(workersComputeList[worker.ID], *compute) + } + } + flattenItemsWg(d, wgList, workersComputeList) + return nil +} + +func wgSchemaMake() map[string]*schema.Schema { + wgSchema := dataSourceK8sWgSchemaMake() + delete(wgSchema, "k8s_id") + wgSchema["wg_id"] = &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "ID of k8s worker Group.", + } + return wgSchema +} + +func dataSourceK8sWgListSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "k8s_id": { + Type: schema.TypeInt, + Required: true, + }, + "items": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: wgSchemaMake(), + }, + }, + } +} + +func DataSourceK8sWgList() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + + ReadContext: dataSourceK8sWgListRead, + + Timeouts: &schema.ResourceTimeout{ + Read: &constants.Timeout30s, + Default: &constants.Timeout60s, + }, + + Schema: dataSourceK8sWgListSchemaMake(), + } +} diff --git a/internal/service/cloudapi/k8s/data_source_wg.go b/internal/service/cloudapi/k8s/data_source_wg.go new file mode 100644 index 0000000..ed53e30 --- /dev/null +++ b/internal/service/cloudapi/k8s/data_source_wg.go @@ -0,0 +1,161 @@ +package k8s + +import ( + "context" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/rudecs/terraform-provider-decort/internal/constants" + "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm" + log "github.com/sirupsen/logrus" +) + +func flattenWgData(d *schema.ResourceData, wg K8SGroup, computes []kvmvm.ComputeGetResp) { + d.Set("annotations", wg.Annotations) + d.Set("cpu", wg.CPU) + d.Set("detailed_info", flattenDetailedInfo(wg.DetailedInfo, computes)) + d.Set("disk", wg.Disk) + d.Set("guid", wg.GUID) + d.Set("labels", wg.Labels) + d.Set("name", wg.Name) + d.Set("num", wg.Num) + d.Set("ram", wg.RAM) + d.Set("taints", wg.Taints) +} + +func dataSourceK8sWgRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + log.Debugf("dataSourceK8sWgRead: called with k8s id %d", d.Get("k8s_id").(int)) + + k8s, err := utilityDataK8sCheckPresence(ctx, d, m) + if err != nil { + return diag.FromErr(err) + } + d.SetId(strconv.Itoa(d.Get("wg_id").(int))) + + var id int + if d.Id() != "" { + id, err = strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + } else { + id = d.Get("wg_id").(int) + } + + curWg := K8SGroup{} + for _, wg := range k8s.K8SGroups.Workers { + if wg.ID == uint64(id) { + curWg = wg + break + } + } + if curWg.ID == 0 { + return diag.Errorf("Not found wg with id: %v in k8s cluster: %v", id, k8s.ID) + } + + workersComputeList := make([]kvmvm.ComputeGetResp, 0, 0) + for _, info := range curWg.DetailedInfo { + compute, err := utilityComputeCheckPresence(ctx, d, m, info.ID) + if err != nil { + return diag.FromErr(err) + } + workersComputeList = append(workersComputeList, *compute) + } + + flattenWgData(d, curWg, workersComputeList) + + return nil +} + +func dataSourceK8sWgSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "k8s_id": { + Type: schema.TypeInt, + Required: true, + Description: "ID of k8s instance.", + }, + "wg_id": { + Type: schema.TypeInt, + Required: true, + Description: "ID of k8s worker Group.", + }, + + "name": { + Type: schema.TypeString, + Computed: true, + Description: "Name of the worker group.", + }, + + "num": { + Type: schema.TypeInt, + Computed: true, + Description: "Number of worker nodes to create.", + }, + + "cpu": { + Type: schema.TypeInt, + Computed: true, + Description: "Worker node CPU count.", + }, + + "ram": { + Type: schema.TypeInt, + Computed: true, + Description: "Worker node RAM in MB.", + }, + + "disk": { + Type: schema.TypeInt, + Computed: true, + Description: "Worker node boot disk size. If unspecified or 0, size is defined by OS image size.", + }, + "detailed_info": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: detailedInfoSchemaMake(), + }, + }, + "labels": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "guid": { + Type: schema.TypeString, + Computed: true, + }, + "annotations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "taints": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + } +} + +func DataSourceK8sWg() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + + ReadContext: dataSourceK8sWgRead, + + Timeouts: &schema.ResourceTimeout{ + Read: &constants.Timeout30s, + Default: &constants.Timeout60s, + }, + + Schema: dataSourceK8sWgSchemaMake(), + } +} diff --git a/internal/service/cloudapi/k8s/flattens.go b/internal/service/cloudapi/k8s/flattens.go new file mode 100644 index 0000000..a0f4159 --- /dev/null +++ b/internal/service/cloudapi/k8s/flattens.go @@ -0,0 +1,247 @@ +package k8s + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm" +) + +func flattenAclList(aclList ACLList) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + for _, acl := range aclList { + temp := map[string]interface{}{ + "explicit": acl.Explicit, + "guid": acl.GUID, + "right": acl.Right, + "status": acl.Status, + "type": acl.Type, + "user_group_id": acl.UserGroupID, + } + res = append(res, temp) + } + return res +} + +func flattenAcl(acl ACLGroup) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + temp := map[string]interface{}{ + "account_acl": flattenAclList(acl.AccountACL), + "k8s_acl": flattenAclList(acl.K8SACL), + "rg_acl": flattenAclList(acl.RGACL), + } + + res = append(res, temp) + return res +} + +func flattenInterfaces(interfaces []kvmvm.InterfaceRecord) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + for _, interfaceCompute := range interfaces { + temp := map[string]interface{}{ + "def_gw": interfaceCompute.DefaultGW, + "ip_address": interfaceCompute.IPAddress, + } + res = append(res, temp) + } + + return res +} + +func flattenDetailedInfo(detailedInfoList DetailedInfoList, computes []kvmvm.ComputeGetResp) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + if computes != nil { + for i, detailedInfo := range detailedInfoList { + temp := map[string]interface{}{ + "compute_id": detailedInfo.ID, + "name": detailedInfo.Name, + "status": detailedInfo.Status, + "tech_status": detailedInfo.TechStatus, + "interfaces": flattenInterfaces(computes[i].Interfaces), + "natable_vins_ip": computes[i].NatableVinsIP, + "natable_vins_network": computes[i].NatableVinsNet, + } + res = append(res, temp) + } + } else { + for _, detailedInfo := range detailedInfoList { + temp := map[string]interface{}{ + "compute_id": detailedInfo.ID, + "name": detailedInfo.Name, + "status": detailedInfo.Status, + "tech_status": detailedInfo.TechStatus, + } + res = append(res, temp) + } + } + + return res +} + +func flattenMasterGroup(mastersGroup MasterGroup, masters []kvmvm.ComputeGetResp) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + temp := map[string]interface{}{ + "cpu": mastersGroup.CPU, + "detailed_info": flattenDetailedInfo(mastersGroup.DetailedInfo, masters), + "disk": mastersGroup.Disk, + "master_id": mastersGroup.ID, + "name": mastersGroup.Name, + "num": mastersGroup.Num, + "ram": mastersGroup.RAM, + } + + res = append(res, temp) + return res +} + +func flattenK8sGroup(k8SGroupList K8SGroupList, workers []kvmvm.ComputeGetResp) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + for _, k8sGroup := range k8SGroupList { + temp := map[string]interface{}{ + "annotations": k8sGroup.Annotations, + "cpu": k8sGroup.CPU, + "detailed_info": flattenDetailedInfo(k8sGroup.DetailedInfo, workers), + "disk": k8sGroup.Disk, + "guid": k8sGroup.GUID, + "id": k8sGroup.ID, + "labels": k8sGroup.Labels, + "name": k8sGroup.Name, + "num": k8sGroup.Num, + "ram": k8sGroup.RAM, + "taints": k8sGroup.Taints, + } + + res = append(res, temp) + } + return res +} + +func flattenK8sGroups(k8sGroups K8SGroups, masters []kvmvm.ComputeGetResp, workers []kvmvm.ComputeGetResp) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + temp := map[string]interface{}{ + "masters": flattenMasterGroup(k8sGroups.Masters, masters), + "workers": flattenK8sGroup(k8sGroups.Workers, workers), + } + res = append(res, temp) + return res +} + +func flattenK8sData(d *schema.ResourceData, k8s K8SRecord, masters []kvmvm.ComputeGetResp, workers []kvmvm.ComputeGetResp) { + d.Set("acl", flattenAcl(k8s.ACL)) + d.Set("account_id", k8s.AccountID) + d.Set("account_name", k8s.AccountName) + d.Set("bservice_id", k8s.BServiceID) + d.Set("k8sci_id", k8s.CIID) + d.Set("created_by", k8s.CreatedBy) + d.Set("created_time", k8s.CreatedTime) + d.Set("deleted_by", k8s.DeletedBy) + d.Set("deleted_time", k8s.DeletedTime) + d.Set("k8s_ci_name", k8s.K8CIName) + d.Set("masters", flattenMasterGroup(k8s.K8SGroups.Masters, masters)) + d.Set("workers", flattenK8sGroup(k8s.K8SGroups.Workers, workers)) + d.Set("lb_id", k8s.LBID) + d.Set("name", k8s.Name) + d.Set("rg_id", k8s.RGID) + d.Set("rg_name", k8s.RGName) + d.Set("status", k8s.Status) + d.Set("tech_status", k8s.TechStatus) + d.Set("updated_by", k8s.UpdatedBy) + d.Set("updated_time", k8s.UpdatedTime) +} + +func flattenServiceAccount(serviceAccount ServiceAccount) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + temp := map[string]interface{}{ + "guid": serviceAccount.GUID, + "password": serviceAccount.Password, + "username": serviceAccount.Username, + } + res = append(res, temp) + return res +} + +func flattenWorkersGroup(workersGroups K8SGroupList) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + for _, worker := range workersGroups { + temp := map[string]interface{}{ + "annotations": worker.Annotations, + "cpu": worker.CPU, + "detailed_info": flattenDetailedInfo(worker.DetailedInfo, nil), + "disk": worker.Disk, + "guid": worker.GUID, + "detailed_info_id": worker.ID, + "labels": worker.Labels, + "name": worker.Name, + "num": worker.Num, + "ram": worker.RAM, + "taints": worker.Taints, + } + res = append(res, temp) + } + return res +} + +func flattenConfig(config interface{}) map[string]interface{} { + return config.(map[string]interface{}) +} + +func flattenK8sItems(k8sItems K8SList) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + for _, item := range k8sItems { + temp := map[string]interface{}{ + "account_id": item.AccountID, + "account_name": item.Name, + "acl": item.ACL, + "bservice_id": item.BServiceID, + "ci_id": item.CIID, + "created_by": item.CreatedBy, + "created_time": item.CreatedTime, + "deleted_by": item.DeletedBy, + "deleted_time": item.DeletedTime, + "desc": item.Description, + "extnet_id": item.ExtNetID, + "gid": item.GID, + "guid": item.GUID, + "k8s_id": item.ID, + "lb_id": item.LBID, + "milestones": item.Milestones, + "k8s_name": item.Name, + "rg_id": item.RGID, + "rg_name": item.RGName, + "service_account": flattenServiceAccount(item.ServiceAccount), + "status": item.Status, + "tech_status": item.TechStatus, + "updated_by": item.UpdatedBy, + "updated_time": item.UpdatedTime, + "vins_id": item.VINSID, + "workers_groups": flattenWorkersGroup(item.WorkersGroup), + } + + res = append(res, temp) + } + return res +} + +func flattenK8sList(d *schema.ResourceData, k8sItems K8SList) { + d.Set("items", flattenK8sItems(k8sItems)) +} + +func flattenResourceK8s(d *schema.ResourceData, k8s K8SRecord, masters []kvmvm.ComputeGetResp, workers []kvmvm.ComputeGetResp) { + d.Set("acl", flattenAcl(k8s.ACL)) + d.Set("account_id", k8s.AccountID) + d.Set("account_name", k8s.AccountName) + d.Set("bservice_id", k8s.BServiceID) + d.Set("created_by", k8s.CreatedBy) + d.Set("created_time", k8s.CreatedTime) + d.Set("deleted_by", k8s.DeletedBy) + d.Set("deleted_time", k8s.DeletedTime) + d.Set("k8s_ci_name", k8s.K8CIName) + d.Set("masters", flattenMasterGroup(k8s.K8SGroups.Masters, masters)) + d.Set("workers", flattenK8sGroup(k8s.K8SGroups.Workers, workers)) + d.Set("lb_id", k8s.LBID) + d.Set("rg_id", k8s.RGID) + d.Set("rg_name", k8s.RGName) + d.Set("status", k8s.Status) + d.Set("tech_status", k8s.TechStatus) + d.Set("updated_by", k8s.UpdatedBy) + d.Set("updated_time", k8s.UpdatedTime) + d.Set("default_wg_id", k8s.K8SGroups.Workers[0].ID) +} diff --git a/internal/service/cloudapi/k8s/models.go b/internal/service/cloudapi/k8s/models.go index 7634dd0..38e701b 100644 --- a/internal/service/cloudapi/k8s/models.go +++ b/internal/service/cloudapi/k8s/models.go @@ -64,8 +64,11 @@ type K8sRecord struct { Name string `json:"name"` RgID int `json:"rgId"` RgName string `json:"rgName"` + VinsID int `json:"vinsId"` } +type K8sRecordList []K8sRecord + //LbRecord represents load balancer instance type LbRecord struct { ID int `json:"id"` @@ -129,3 +132,124 @@ type SshKeyConfig struct { SshKey string UserShell string } + +//FromSDK +type K8SGroup struct { + Annotations []string `json:"annotations"` + CPU uint64 `json:"cpu"` + DetailedInfo DetailedInfoList `json:"detailedInfo"` + Disk uint64 `json:"disk"` + GUID string `json:"guid"` + ID uint64 `json:"id"` + Labels []string `json:"labels"` + Name string `json:"name"` + Num uint64 `json:"num"` + RAM uint64 `json:"ram"` + Taints []string `json:"taints"` +} + +type K8SGroupList []K8SGroup + +type DetailedInfo struct { + ID uint64 `json:"id"` + Name string `json:"name"` + Status string `json:"status"` + TechStatus string `json:"techStatus"` +} + +type DetailedInfoList []DetailedInfo + +type K8SRecord struct { + ACL ACLGroup `json:"ACL"` + AccountID uint64 `json:"accountId"` + AccountName string `json:"accountName"` + BServiceID uint64 `json:"bserviceId"` + CIID uint64 `json:"ciId"` + CreatedBy string `json:"createdBy"` + CreatedTime uint64 `json:"createdTime"` + DeletedBy string `json:"deletedBy"` + DeletedTime uint64 `json:"deletedTime"` + ID uint64 `json:"id"` + K8CIName string `json:"k8ciName"` + K8SGroups K8SGroups `json:"k8sGroups"` + LBID uint64 `json:"lbId"` + Name string `json:"name"` + RGID uint64 `json:"rgId"` + RGName string `json:"rgName"` + Status string `json:"status"` + TechStatus string `json:"techStatus"` + UpdatedBy string `json:"updatedBy"` + UpdatedTime uint64 `json:"updatedTime"` +} + +type K8SRecordList []K8SRecord + +type K8SGroups struct { + Masters MasterGroup `json:"masters"` + Workers K8SGroupList `json:"workers"` +} + +type MasterGroup struct { + CPU uint64 `json:"cpu"` + DetailedInfo DetailedInfoList `json:"detailedInfo"` + Disk uint64 `json:"disk"` + ID uint64 `json:"id"` + Name string `json:"name"` + Num uint64 `json:"num"` + RAM uint64 `json:"ram"` +} + +type ACLGroup struct { + AccountACL ACLList `json:"accountAcl"` + K8SACL ACLList `json:"k8sAcl"` + RGACL ACLList `json:"rgAcl"` +} + +type ACL struct { + Explicit bool `json:"explicit"` + GUID string `json:"guid"` + Right string `json:"right"` + Status string `json:"status"` + Type string `json:"type"` + UserGroupID string `json:"userGroupId"` +} + +type ACLList []ACL + +type K8SItem struct { + AccountID uint64 `json:"accountId"` + AccountName string `json:"accountName"` + ACL []interface{} `json:"acl"` + BServiceID uint64 `json:"bserviceId"` + CIID uint64 `json:"ciId"` + Config interface{} `json:"config"` + CreatedBy string `json:"createdBy"` + CreatedTime uint64 `json:"createdTime"` + DeletedBy string `json:"deletedBy"` + DeletedTime uint64 `json:"deletedTime"` + Description string `json:"desc"` + ExtNetID uint64 `json:"extnetId"` + GID uint64 `json:"gid"` + GUID uint64 `json:"guid"` + ID uint64 `json:"id"` + LBID uint64 `json:"lbId"` + Milestones uint64 `json:"milestones"` + Name string `json:"name"` + RGID uint64 `json:"rgId"` + RGName string `json:"rgName"` + ServiceAccount ServiceAccount `json:"serviceAccount"` + Status string `json:"status"` + TechStatus string `json:"techStatus"` + UpdatedBy string `json:"updatedBy"` + UpdatedTime uint64 `json:"updatedTime"` + VINSID uint64 `json:"vinsId"` + WorkersGroup K8SGroupList `json:"workersGroups"` +} + +type ServiceAccount struct { + GUID string `json:"guid"` + Password string `json:"password"` + Username string `json:"username"` +} + +type K8SList []K8SItem diff --git a/internal/service/cloudapi/k8s/node_subresource.go b/internal/service/cloudapi/k8s/node_subresource.go index 78fc9ce..2229bd0 100644 --- a/internal/service/cloudapi/k8s/node_subresource.go +++ b/internal/service/cloudapi/k8s/node_subresource.go @@ -103,3 +103,59 @@ func nodeK8sSubresourceSchemaMake() map[string]*schema.Schema { }, } } + +func mastersSchemaMake() map[string]*schema.Schema { + masters := masterGroupSchemaMake() + masters["num"] = &schema.Schema{ + Type: schema.TypeInt, + Required: true, + Description: "Number of nodes to create.", + } + masters["cpu"] = &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "Node CPU count.", + } + masters["ram"] = &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "Node RAM in MB.", + } + masters["disk"] = &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "Node boot disk size in GB.", + } + return masters +} + +func workersSchemaMake() map[string]*schema.Schema { + workers := k8sGroupListSchemaMake() + workers["num"] = &schema.Schema{ + Type: schema.TypeInt, + Required: true, + Description: "Number of nodes to create.", + } + workers["cpu"] = &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "Node CPU count.", + } + workers["ram"] = &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "Node RAM in MB.", + } + workers["disk"] = &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "Node boot disk size in GB.", + } + return workers +} diff --git a/internal/service/cloudapi/k8s/resource_k8s.go b/internal/service/cloudapi/k8s/resource_k8s.go index c3e7d66..e05c9e2 100644 --- a/internal/service/cloudapi/k8s/resource_k8s.go +++ b/internal/service/cloudapi/k8s/resource_k8s.go @@ -44,6 +44,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/rudecs/terraform-provider-decort/internal/constants" "github.com/rudecs/terraform-provider-decort/internal/controller" + "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm" log "github.com/sirupsen/logrus" ) @@ -79,10 +80,11 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{ urlValues.Add("workerRam", strconv.Itoa(workerNode.Ram)) urlValues.Add("workerDisk", strconv.Itoa(workerNode.Disk)) - //if withLB, ok := d.GetOk("with_lb"); ok { - //urlValues.Add("withLB", strconv.FormatBool(withLB.(bool))) - //} - urlValues.Add("withLB", strconv.FormatBool(true)) + if withLB, ok := d.GetOk("with_lb"); ok { + urlValues.Add("withLB", strconv.FormatBool(withLB.(bool))) + } else { + urlValues.Add("withLB", strconv.FormatBool(true)) + } if extNet, ok := d.GetOk("extnet_id"); ok { urlValues.Add("extnetId", strconv.Itoa(extNet.(int))) @@ -90,9 +92,9 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{ urlValues.Add("extnetId", "0") } - //if desc, ok := d.GetOk("desc"); ok { - //urlValues.Add("desc", desc.(string)) - //} + if desc, ok := d.GetOk("desc"); ok { + urlValues.Add("desc", desc.(string)) + } resp, err := c.DecortAPICall(ctx, "POST", K8sCreateAPI, urlValues) if err != nil { @@ -126,59 +128,57 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{ time.Sleep(time.Second * 10) } - k8s, err := utilityK8sCheckPresence(ctx, d, m) - if err != nil { - return diag.FromErr(err) - } - - d.Set("default_wg_id", k8s.Groups.Workers[0].ID) + return resourceK8sRead(ctx, d, m) +} - urlValues = &url.Values{} - urlValues.Add("lbId", strconv.Itoa(k8s.LbID)) +func resourceK8sRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + //log.Debugf("resourceK8sRead: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int)) - resp, err = c.DecortAPICall(ctx, "POST", LbGetAPI, urlValues) + k8s, err := utilityDataK8sCheckPresence(ctx, d, m) if err != nil { + d.SetId("") return diag.FromErr(err) } - - var lb LbRecord - if err := json.Unmarshal([]byte(resp), &lb); err != nil { + k8sList, err := utilityK8sListCheckPresence(ctx, d, m, K8sListAPI) + if err != nil { + d.SetId("") return diag.FromErr(err) } - d.Set("extnet_id", lb.ExtNetID) - d.Set("lb_ip", lb.PrimaryNode.FrontendIP) - - urlValues = &url.Values{} - urlValues.Add("k8sId", d.Id()) - kubeconfig, err := c.DecortAPICall(ctx, "POST", K8sGetConfigAPI, urlValues) - if err != nil { - log.Warnf("could not get kubeconfig: %v", err) + curK8s := K8SItem{} + for _, k8sCluster := range k8sList { + if k8sCluster.ID == k8s.ID { + curK8s = k8sCluster + } } - d.Set("kubeconfig", kubeconfig) - - return nil -} - -func resourceK8sRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - log.Debugf("resourceK8sRead: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int)) + if curK8s.ID == 0 { + return diag.Errorf("Cluster with id %d not found", k8s.ID) + } + d.Set("vins_id", curK8s.VINSID) - k8s, err := utilityK8sCheckPresence(ctx, d, m) - if k8s == nil { - d.SetId("") - return diag.FromErr(err) + masterComputeList := make([]kvmvm.ComputeGetResp, 0, len(k8s.K8SGroups.Masters.DetailedInfo)) + workersComputeList := make([]kvmvm.ComputeGetResp, 0, len(k8s.K8SGroups.Workers)) + for _, masterNode := range k8s.K8SGroups.Masters.DetailedInfo { + compute, err := utilityComputeCheckPresence(ctx, d, m, masterNode.ID) + if err != nil { + return diag.FromErr(err) + } + masterComputeList = append(masterComputeList, *compute) + } + for _, worker := range k8s.K8SGroups.Workers { + for _, info := range worker.DetailedInfo { + compute, err := utilityComputeCheckPresence(ctx, d, m, info.ID) + if err != nil { + return diag.FromErr(err) + } + workersComputeList = append(workersComputeList, *compute) + } } - d.Set("name", k8s.Name) - d.Set("rg_id", k8s.RgID) - d.Set("k8sci_id", k8s.CI) - d.Set("wg_name", k8s.Groups.Workers[0].Name) - d.Set("masters", nodeToResource(k8s.Groups.Masters)) - d.Set("workers", nodeToResource(k8s.Groups.Workers[0])) - d.Set("default_wg_id", k8s.Groups.Workers[0].ID) + flattenResourceK8s(d, *k8s, masterComputeList, workersComputeList) c := m.(*controller.ControllerCfg) urlValues := &url.Values{} - urlValues.Add("lbId", strconv.Itoa(k8s.LbID)) + urlValues.Add("lbId", strconv.FormatUint(k8s.LBID, 10)) resp, err := c.DecortAPICall(ctx, "POST", LbGetAPI, urlValues) if err != nil { @@ -225,21 +225,21 @@ func resourceK8sUpdate(ctx context.Context, d *schema.ResourceData, m interface{ return diag.FromErr(err) } - wg := k8s.Groups.Workers[0] + wg := k8s.K8SGroups.Workers[0] urlValues := &url.Values{} urlValues.Add("k8sId", d.Id()) - urlValues.Add("workersGroupId", strconv.Itoa(wg.ID)) + urlValues.Add("workersGroupId", strconv.FormatUint(wg.ID, 10)) newWorkers := parseNode(d.Get("workers").([]interface{})) - if newWorkers.Num > wg.Num { - urlValues.Add("num", strconv.Itoa(newWorkers.Num-wg.Num)) + if uint64(newWorkers.Num) > wg.Num { + urlValues.Add("num", strconv.FormatUint(uint64(newWorkers.Num)-wg.Num, 10)) if _, err := c.DecortAPICall(ctx, "POST", K8sWorkerAddAPI, urlValues); err != nil { return diag.FromErr(err) } } else { - for i := wg.Num - 1; i >= newWorkers.Num; i-- { - urlValues.Set("workerId", strconv.Itoa(wg.DetailedInfo[i].ID)) + for i := int(wg.Num) - 1; i >= newWorkers.Num; i-- { + urlValues.Set("workerId", strconv.FormatUint(wg.DetailedInfo[i].ID, 10)) if _, err := c.DecortAPICall(ctx, "POST", K8sWorkerDeleteAPI, urlValues); err != nil { return diag.FromErr(err) } @@ -306,10 +306,11 @@ func resourceK8sSchemaMake() map[string]*schema.Schema { "masters": { Type: schema.TypeList, Optional: true, + Computed: true, ForceNew: true, MaxItems: 1, Elem: &schema.Resource{ - Schema: nodeK8sSubresourceSchemaMake(), + Schema: mastersSchemaMake(), }, Description: "Master node(s) configuration.", }, @@ -317,20 +318,21 @@ func resourceK8sSchemaMake() map[string]*schema.Schema { "workers": { Type: schema.TypeList, Optional: true, + Computed: true, MaxItems: 1, Elem: &schema.Resource{ - Schema: nodeK8sSubresourceSchemaMake(), + Schema: workersSchemaMake(), }, Description: "Worker node(s) configuration.", }, - //"with_lb": { - //Type: schema.TypeBool, - //Optional: true, - //ForceNew: true, - //Default: true, - //Description: "Create k8s with load balancer if true.", - //}, + "with_lb": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: true, + Description: "Create k8s with load balancer if true.", + }, "extnet_id": { Type: schema.TypeInt, @@ -340,17 +342,80 @@ func resourceK8sSchemaMake() map[string]*schema.Schema { Description: "ID of the external network to connect workers to. If omitted network will be chosen by the platfom.", }, - //"desc": { - //Type: schema.TypeString, - //Optional: true, - //Description: "Text description of this instance.", - //}, + "desc": { + Type: schema.TypeString, + Optional: true, + Description: "Text description of this instance.", + }, + "acl": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: aclGroupSchemaMake(), + }, + }, + "account_id": { + Type: schema.TypeInt, + Computed: true, + }, + "account_name": { + Type: schema.TypeString, + Computed: true, + }, + "bservice_id": { + Type: schema.TypeInt, + Computed: true, + }, + "created_by": { + Type: schema.TypeString, + Computed: true, + }, + "created_time": { + Type: schema.TypeInt, + Computed: true, + }, + "deleted_by": { + Type: schema.TypeString, + Computed: true, + }, + "deleted_time": { + Type: schema.TypeInt, + Computed: true, + }, + "k8s_ci_name": { + Type: schema.TypeString, + Computed: true, + }, + "lb_id": { + Type: schema.TypeInt, + Computed: true, + }, "lb_ip": { Type: schema.TypeString, Computed: true, Description: "IP address of default load balancer.", }, + "rg_name": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "tech_status": { + Type: schema.TypeString, + Computed: true, + }, + "updated_by": { + Type: schema.TypeString, + Computed: true, + }, + "updated_time": { + Type: schema.TypeInt, + Computed: true, + }, "default_wg_id": { Type: schema.TypeInt, @@ -363,6 +428,11 @@ func resourceK8sSchemaMake() map[string]*schema.Schema { Computed: true, Description: "Kubeconfig for cluster access.", }, + "vins_id": { + Type: schema.TypeInt, + Computed: true, + Description: "ID of default vins for this instace.", + }, } } @@ -380,7 +450,7 @@ func ResourceK8s() *schema.Resource { }, Timeouts: &schema.ResourceTimeout{ - Create: &constants.Timeout600s, + Create: &constants.Timeout30m, Read: &constants.Timeout300s, Update: &constants.Timeout300s, Delete: &constants.Timeout300s, diff --git a/internal/service/cloudapi/k8s/resource_k8s_wg.go b/internal/service/cloudapi/k8s/resource_k8s_wg.go index 0834a32..c459b87 100644 --- a/internal/service/cloudapi/k8s/resource_k8s_wg.go +++ b/internal/service/cloudapi/k8s/resource_k8s_wg.go @@ -35,11 +35,13 @@ import ( "context" "net/url" "strconv" + "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/rudecs/terraform-provider-decort/internal/constants" "github.com/rudecs/terraform-provider-decort/internal/controller" + "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm" log "github.com/sirupsen/logrus" ) @@ -91,23 +93,51 @@ func resourceK8sWgCreate(ctx context.Context, d *schema.ResourceData, m interfac //time.Sleep(time.Second * 5) //} - return nil + return resourceK8sWgRead(ctx, d, m) } func resourceK8sWgRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - log.Debugf("resourceK8sWgRead: called with k8s id %d", d.Get("k8s_id").(int)) + log.Debugf("resourceK8sWgRead: called with %v", d.Id()) - wg, err := utilityK8sWgCheckPresence(ctx, d, m) - if wg == nil { - d.SetId("") + k8s, err := utilityDataK8sCheckPresence(ctx, d, m) + if err != nil { return diag.FromErr(err) } - d.Set("name", wg.Name) - d.Set("num", wg.Num) - d.Set("cpu", wg.Cpu) - d.Set("ram", wg.Ram) - d.Set("disk", wg.Disk) + var id int + if d.Id() != "" { + id, err = strconv.Atoi(strings.Split(d.Id(), "#")[0]) + if err != nil { + return diag.FromErr(err) + } + } else { + id = d.Get("wg_id").(int) + } + + curWg := K8SGroup{} + for _, wg := range k8s.K8SGroups.Workers { + if wg.ID == uint64(id) { + curWg = wg + break + } + } + if curWg.ID == 0 { + return diag.Errorf("Not found wg with id: %v in k8s cluster: %v", id, k8s.ID) + } + + workersComputeList := make([]kvmvm.ComputeGetResp, 0, 0) + for _, info := range curWg.DetailedInfo { + compute, err := utilityComputeCheckPresence(ctx, d, m, info.ID) + if err != nil { + return diag.FromErr(err) + } + workersComputeList = append(workersComputeList, *compute) + } + + d.SetId(strings.Split(d.Id(), "#")[0]) + d.Set("k8s_id", k8s.ID) + d.Set("wg_id", curWg.ID) + flattenWgData(d, curWg, workersComputeList) return nil } @@ -126,15 +156,15 @@ func resourceK8sWgUpdate(ctx context.Context, d *schema.ResourceData, m interfac urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int))) urlValues.Add("workersGroupId", d.Id()) - if newNum := d.Get("num").(int); newNum > wg.Num { - urlValues.Add("num", strconv.Itoa(newNum-wg.Num)) + if newNum := d.Get("num").(int); uint64(newNum) > wg.Num { + urlValues.Add("num", strconv.FormatUint(uint64(newNum)-wg.Num, 10)) _, err := c.DecortAPICall(ctx, "POST", K8sWorkerAddAPI, urlValues) if err != nil { return diag.FromErr(err) } } else { - for i := wg.Num - 1; i >= newNum; i-- { - urlValues.Set("workerId", strconv.Itoa(wg.DetailedInfo[i].ID)) + for i := int(wg.Num) - 1; i >= newNum; i-- { + urlValues.Set("workerId", strconv.FormatUint(wg.DetailedInfo[i].ID, 10)) _, err := c.DecortAPICall(ctx, "POST", K8sWorkerDeleteAPI, urlValues) if err != nil { return diag.FromErr(err) @@ -159,7 +189,7 @@ func resourceK8sWgDelete(ctx context.Context, d *schema.ResourceData, m interfac c := m.(*controller.ControllerCfg) urlValues := &url.Values{} urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int))) - urlValues.Add("workersGroupId", strconv.Itoa(wg.ID)) + urlValues.Add("workersGroupId", strconv.FormatUint(wg.ID, 10)) _, err = c.DecortAPICall(ctx, "POST", K8sWgDeleteAPI, urlValues) if err != nil { @@ -215,6 +245,43 @@ func resourceK8sWgSchemaMake() map[string]*schema.Schema { Default: 0, Description: "Worker node boot disk size. If unspecified or 0, size is defined by OS image size.", }, + "wg_id": { + Type: schema.TypeInt, + Computed: true, + Description: "ID of k8s worker Group.", + }, + "detailed_info": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: detailedInfoSchemaMake(), + }, + }, + "labels": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "guid": { + Type: schema.TypeString, + Computed: true, + }, + "annotations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "taints": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, } } diff --git a/internal/service/cloudapi/k8s/utility_k8s.go b/internal/service/cloudapi/k8s/utility_k8s.go index 2c4270c..6f572a1 100644 --- a/internal/service/cloudapi/k8s/utility_k8s.go +++ b/internal/service/cloudapi/k8s/utility_k8s.go @@ -35,12 +35,15 @@ import ( "context" "encoding/json" "net/url" + "strconv" + "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/rudecs/terraform-provider-decort/internal/controller" + "github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm" ) -func utilityK8sCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*K8sRecord, error) { +func utilityK8sCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*K8SRecord, error) { c := m.(*controller.ControllerCfg) urlValues := &url.Values{} urlValues.Add("k8sId", d.Id()) @@ -54,10 +57,76 @@ func utilityK8sCheckPresence(ctx context.Context, d *schema.ResourceData, m inte return nil, nil } - var k8s K8sRecord + k8s := K8SRecord{} if err := json.Unmarshal([]byte(resp), &k8s); err != nil { return nil, err } return &k8s, nil } + +func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}, computeID uint64) (*kvmvm.ComputeGetResp, error) { + c := m.(*controller.ControllerCfg) + urlValues := &url.Values{} + + urlValues.Add("computeId", strconv.FormatUint(computeID, 10)) + + computeRaw, err := c.DecortAPICall(ctx, "POST", kvmvm.ComputeGetAPI, urlValues) + if err != nil { + return nil, err + } + + compute := &kvmvm.ComputeGetResp{} + err = json.Unmarshal([]byte(computeRaw), compute) + if err != nil { + return nil, err + } + + return compute, nil +} + +func utilityDataK8sCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*K8SRecord, error) { + c := m.(*controller.ControllerCfg) + urlValues := &url.Values{} + if d.Get("k8s_id") != 0 && d.Get("k8s_id") != nil { + urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int))) + } else if id := d.Id(); id != "" { + if strings.Contains(id, "#") { + urlValues.Add("k8sId", strings.Split(d.Id(), "#")[1]) + } else { + urlValues.Add("k8sId", d.Id()) + } + } + k8sRaw, err := c.DecortAPICall(ctx, "POST", K8sGetAPI, urlValues) + if err != nil { + return nil, err + } + + k8s := &K8SRecord{} + err = json.Unmarshal([]byte(k8sRaw), k8s) + if err != nil { + return nil, err + } + return k8s, nil +} + +func utilityK8sListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}, api string) (K8SList, error) { + c := m.(*controller.ControllerCfg) + urlValues := &url.Values{} + urlValues.Add("includedeleted", "false") + urlValues.Add("page", "0") + urlValues.Add("size", "0") + + k8sListRaw, err := c.DecortAPICall(ctx, "POST", api, urlValues) + if err != nil { + return nil, err + } + + k8sList := K8SList{} + + err = json.Unmarshal([]byte(k8sListRaw), &k8sList) + if err != nil { + return nil, err + } + return k8sList, nil +} diff --git a/internal/service/cloudapi/k8s/utility_k8s_wg.go b/internal/service/cloudapi/k8s/utility_k8s_wg.go index 9aef352..711b826 100644 --- a/internal/service/cloudapi/k8s/utility_k8s_wg.go +++ b/internal/service/cloudapi/k8s/utility_k8s_wg.go @@ -34,6 +34,7 @@ package k8s import ( "context" "encoding/json" + "fmt" "net/url" "strconv" @@ -41,7 +42,7 @@ import ( "github.com/rudecs/terraform-provider-decort/internal/controller" ) -func utilityK8sWgCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*K8sNodeRecord, error) { +func utilityK8sWgCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*K8SGroup, error) { c := m.(*controller.ControllerCfg) urlValues := &url.Values{} urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int))) @@ -52,24 +53,29 @@ func utilityK8sWgCheckPresence(ctx context.Context, d *schema.ResourceData, m in } if resp == "" { - return nil, nil + return nil, err } - var k8s K8sRecord + var k8s K8SRecord if err := json.Unmarshal([]byte(resp), &k8s); err != nil { return nil, err } - id, err := strconv.Atoi(d.Id()) - if err != nil { - return nil, err + var id int + if d.Id() != "" { + id, err = strconv.Atoi(d.Id()) + if err != nil { + return nil, err + } + } else { + id = d.Get("wg_id").(int) } - for _, wg := range k8s.Groups.Workers { - if wg.ID == id { + for _, wg := range k8s.K8SGroups.Workers { + if wg.ID == uint64(id) { return &wg, nil } } - return nil, nil + return nil, fmt.Errorf("Not found wg with id: %v in k8s cluster: %v", id, k8s.ID) } diff --git a/internal/service/cloudapi/kvmvm/api.go b/internal/service/cloudapi/kvmvm/api.go index 1094df0..30a55d3 100644 --- a/internal/service/cloudapi/kvmvm/api.go +++ b/internal/service/cloudapi/kvmvm/api.go @@ -49,4 +49,7 @@ const ( ComputeUpdateAPI = "/restmachine/cloudapi/compute/update" ComputeDiskAddAPI = "/restmachine/cloudapi/compute/diskAdd" ComputeDiskDeleteAPI = "/restmachine/cloudapi/compute/diskDel" + ComputeRestoreAPI = "/restmachine/cloudapi/compute/restore" + ComputeEnableAPI = "/restmachine/cloudapi/compute/enable" + ComputeDisableAPI = "/restmachine/cloudapi/compute/disable" ) diff --git a/internal/service/cloudapi/kvmvm/data_source_compute.go b/internal/service/cloudapi/kvmvm/data_source_compute.go index b662acf..e3f944a 100644 --- a/internal/service/cloudapi/kvmvm/data_source_compute.go +++ b/internal/service/cloudapi/kvmvm/data_source_compute.go @@ -40,10 +40,12 @@ import ( // "net/url" "github.com/rudecs/terraform-provider-decort/internal/constants" + "github.com/rudecs/terraform-provider-decort/internal/status" log "github.com/sirupsen/logrus" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" // "github.com/hashicorp/terraform-plugin-sdk/helper/validation" ) @@ -176,14 +178,17 @@ func flattenCompute(d *schema.ResourceData, compFacts string) error { d.Set("image_id", model.ImageID) } d.Set("description", model.Desc) + d.Set("enabled", false) + if model.Status == status.Enabled { + d.Set("enabled", true) + } + d.Set("cloud_init", "applied") // NOTE: for existing compute we hard-code this value as an indicator for DiffSuppress fucntion // d.Set("status", model.Status) // d.Set("tech_status", model.TechStatus) - + d.Set("started", false) if model.TechStatus == "STARTED" { d.Set("started", true) - } else { - d.Set("started", false) } bootDisk := findBootDisk(model.Disks) @@ -270,6 +275,12 @@ func DataSourceCompute() *schema.Resource { Description: "ID of the resource group where this compute instance is located.", }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + Description: "If true - enable the compute, else - disable", + }, + "rg_name": { Type: schema.TypeString, Computed: true, @@ -339,16 +350,67 @@ func DataSourceCompute() *schema.Resource { Description: "IDs of the extra disk(s) attached to this compute.", }, - /* - "disks": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: dataSourceDiskSchemaMake(), // ID, type, name, size, account ID, SEP ID, SEP type, pool, status, tech status, compute ID, image ID + "disks": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disk_name": { + Type: schema.TypeString, + Required: true, + Description: "Name for disk", + }, + "size": { + Type: schema.TypeInt, + Required: true, + Description: "Disk size in GiB", + }, + "disk_type": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"B", "D"}, false), + Description: "The type of disk in terms of its role in compute: 'B=Boot, D=Data'", + }, + "sep_id": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: "Storage endpoint provider ID; by default the same with boot disk", + }, + "pool": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: "Pool name; by default will be chosen automatically", + }, + "desc": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: "Optional description", + }, + "image_id": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: "Specify image id for create disk from template", + }, + "disk_id": { + Type: schema.TypeInt, + Computed: true, + Description: "Disk ID", + }, + "permanently": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Disk deletion status", + }, }, - Description: "Detailed specification for all disks attached to this compute instance (including bood disk).", }, - */ + }, "network": { Type: schema.TypeSet, @@ -384,7 +446,7 @@ func DataSourceCompute() *schema.Resource { "started": { Type: schema.TypeBool, Optional: true, - Default: true, + Computed: true, Description: "Is compute started.", }, }, diff --git a/internal/service/cloudapi/kvmvm/resource_compute.go b/internal/service/cloudapi/kvmvm/resource_compute.go index caf253e..df3760c 100644 --- a/internal/service/cloudapi/kvmvm/resource_compute.go +++ b/internal/service/cloudapi/kvmvm/resource_compute.go @@ -34,6 +34,7 @@ package kvmvm import ( "context" + "encoding/json" "fmt" "net/url" "strconv" @@ -41,6 +42,7 @@ import ( "github.com/rudecs/terraform-provider-decort/internal/constants" "github.com/rudecs/terraform-provider-decort/internal/controller" "github.com/rudecs/terraform-provider-decort/internal/statefuncs" + "github.com/rudecs/terraform-provider-decort/internal/status" log "github.com/sirupsen/logrus" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -208,6 +210,20 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf } } + if enabled, ok := d.GetOk("enabled"); ok { + api := ComputeDisableAPI + if enabled.(bool) { + api = ComputeEnableAPI + } + urlValues := &url.Values{} + urlValues.Add("computeId", fmt.Sprintf("%d", compId)) + log.Debugf("resourceComputeCreate: enable=%t Compute ID %d after completing its resource configuration", compId, enabled) + if _, err := c.DecortAPICall(ctx, "POST", api, urlValues); err != nil { + return diag.FromErr(err) + } + + } + if !cleanup { if disks, ok := d.GetOk("disks"); ok { log.Debugf("resourceComputeCreate: Create disks on ComputeID: %d", compId) @@ -258,6 +274,8 @@ func resourceComputeRead(ctx context.Context, d *schema.ResourceData, m interfac log.Debugf("resourceComputeRead: called for Compute name %s, RG ID %d", d.Get("name").(string), d.Get("rg_id").(int)) + c := m.(*controller.ControllerCfg) + compFacts, err := utilityComputeCheckPresence(ctx, d, m) if compFacts == "" { if err != nil { @@ -267,6 +285,49 @@ func resourceComputeRead(ctx context.Context, d *schema.ResourceData, m interfac return nil } + compute := &ComputeGetResp{} + err = json.Unmarshal([]byte(compFacts), compute) + + log.Debugf("resourceComputeRead: compute is: %+v", compute) + if err != nil { + return diag.FromErr(err) + } + + switch compute.Status { + case status.Deleted: + urlValues := &url.Values{} + urlValues.Add("computeId", d.Id()) + _, err := c.DecortAPICall(ctx, "POST", ComputeRestoreAPI, urlValues) + if err != nil { + return diag.FromErr(err) + } + _, err = c.DecortAPICall(ctx, "POST", ComputeEnableAPI, urlValues) + if err != nil { + return diag.FromErr(err) + } + case status.Destroyed: + d.SetId("") + return resourceComputeCreate(ctx, d, m) + case status.Disabled: + log.Debugf("The compute is in status: %s, may troubles can be occured with update. Please, enable compute first.", compute.Status) + case status.Redeploying: + case status.Deleting: + case status.Destroying: + return diag.Errorf("The compute is in progress with status: %s", compute.Status) + case status.Modeled: + return diag.Errorf("The compute is in status: %s, please, contant the support for more information", compute.Status) + } + + compFacts, err = utilityComputeCheckPresence(ctx, d, m) + log.Debugf("resourceComputeRead: after changes compute is: %s", compFacts) + if compFacts == "" { + if err != nil { + return diag.FromErr(err) + } + // Compute with such name and RG ID was not found + return nil + } + if err = flattenCompute(d, compFacts); err != nil { return diag.FromErr(err) } @@ -283,6 +344,56 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf c := m.(*controller.ControllerCfg) + computeRaw, err := utilityComputeCheckPresence(ctx, d, m) + if err != nil { + return diag.FromErr(err) + } + compute := &ComputeGetResp{} + err = json.Unmarshal([]byte(computeRaw), compute) + if err != nil { + return diag.FromErr(err) + } + + if d.HasChange("enabled") { + enabled := d.Get("enabled") + api := ComputeDisableAPI + if enabled.(bool) { + api = ComputeEnableAPI + } + urlValues := &url.Values{} + urlValues.Add("computeId", d.Id()) + log.Debugf("resourceComputeUpdate: enable=%t Compute ID %s after completing its resource configuration", d.Id(), enabled) + if _, err := c.DecortAPICall(ctx, "POST", api, urlValues); err != nil { + return diag.FromErr(err) + } + } + + // check compute statuses + switch compute.Status { + case status.Deleted: + urlValues := &url.Values{} + urlValues.Add("computeId", d.Id()) + _, err := c.DecortAPICall(ctx, "POST", ComputeRestoreAPI, urlValues) + if err != nil { + return diag.FromErr(err) + } + _, err = c.DecortAPICall(ctx, "POST", ComputeEnableAPI, urlValues) + if err != nil { + return diag.FromErr(err) + } + case status.Destroyed: + d.SetId("") + return resourceComputeCreate(ctx, d, m) + case status.Disabled: + log.Debugf("The compute is in status: %s, may troubles can be occured with update. Please, enable compute first.", compute.Status) + case status.Redeploying: + case status.Deleting: + case status.Destroying: + return diag.Errorf("The compute is in progress with status: %s", compute.Status) + case status.Modeled: + return diag.Errorf("The compute is in status: %s, please, contant the support for more information", compute.Status) + } + /* 1. Resize CPU/RAM 2. Resize (grow) boot disk @@ -348,7 +459,7 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf } // 4. Calculate and apply changes to network connections - err := utilityComputeNetworksConfigure(ctx, d, m, true, false) // pass do_delta = true to apply changes, if any + err = utilityComputeNetworksConfigure(ctx, d, m, true, false) // pass do_delta = true to apply changes, if any if err != nil { return diag.FromErr(err) } @@ -678,6 +789,13 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema { Description: "Optional cloud_init parameters. Applied when creating new compute instance only, ignored in all other cases.", }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "If true - enable compute, else - disable", + }, + // The rest are Compute properties, which are "computed" once it is created "rg_name": { Type: schema.TypeString, @@ -715,7 +833,7 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema { "started": { Type: schema.TypeBool, Optional: true, - Default: true, + Computed: true, Description: "Is compute started.", }, "detach_disks": { diff --git a/internal/status/status.go b/internal/status/status.go index f8d7124..6459dc0 100644 --- a/internal/status/status.go +++ b/internal/status/status.go @@ -3,30 +3,92 @@ package status type Status = string var ( - //The disk is linked to any Compute + // The disk is linked to any Compute + // Status available for: + // - Disk Assigned Status = "ASSIGNED" - //An object model has been created in the database + // An object enabled for operations + // Status available for: + // - Compute + // - Disk + Enabled Status = "ENABLED" + + // Enabling in process + // Status available for: + // - Disk + Enabling Status = "ENABLING" + + // An object disabled for operations + // Status available for: + // - Compute + // - Disk + Disabled Status = "DISABLED" + + // Disabling in process + // Status available for: + // - Disk + Disabling Status = "DISABLING" + + // An object model has been created in the database + // Status available for: + // - Image + // - Disk + // - Compute Modeled Status = "MODELED" - //In the process of creation + // In the process of creation + // Status available for: + // - Image Creating Status = "CREATING" - //Creating + // An object was created successfully + // Status available for: + // - Image + // - Disk + // - Compute Created Status = "CREATED" - //Physical resources are allocated for the object + // Physical resources are allocated for the object + // Status available for: + // - Compute Allocated Status = "ALLOCATED" - //The object has released (returned to the platform) the physical resources that it occupied + // The object has released (returned to the platform) the physical resources that it occupied + // Status available for: + // - Compute Unallocated Status = "UNALLOCATED" - //Permanently deleted + // Destroying in progress + // Status available for: + // - Disk + // - Compute + Destroying Status = "DESTROYING" + + // Permanently deleted + // Status available for: + // - Image + // - Disk + // - Compute Destroyed Status = "DESTROYED" - //Deleted to Trash + // Deleting in progress to Trash + // Status available for: + // - Compute + Deleting Status = "DELETING" + + // Deleted to Trash + // Status available for: + // - Compute Deleted Status = "DELETED" - //Deleted from storage + // Deleted from storage + // Status available for: + // - Image Purged Status = "PURGED" + + // Repeating deploy of the object in progress + // Status available for: + // - Compute + Redeploying Status = "REDEPLOYING" ) diff --git a/internal/techstatus/techstatus.go b/internal/techstatus/techstatus.go new file mode 100644 index 0000000..661d1fd --- /dev/null +++ b/internal/techstatus/techstatus.go @@ -0,0 +1,68 @@ +package techstatus + +type TechStatus = string + +var ( + // Start in progress - send an execution command + // Status available for: + // - Compute + Starting TechStatus = "STARTING" + + // An object started + // Can be stopped + // Correctly running + // Status available for: + // - Compute + Started TechStatus = "STARTED" + + // Stop in progress - send an execution command + // Status available for: + // - Compute + Stopping TechStatus = "STOPPING" + + // An object stopped + // Can be started + // Limited functionality + // Status available for: + // - Compute + Stopped TechStatus = "STOPPED" + + // Pause in progress - send an execution command + // Status available for: + // - Compute + Pausing TechStatus = "PAUSING" + + // An object paused + // Can be restarted + // Currently running + // Status available for: + // - Compute + Paused TechStatus = "PAUSED" + + // Migrate in progress + // Status available for: + // - Compute + Migrating TechStatus = "MIGRATING" + + // An object failure status + // Can be reastarted + // Limited functionality + // Status available for: + // - Compute + Down TechStatus = "DOWN" + + // An object configuration process + // Status available for: + // - Compute + Scheduled TechStatus = "SCHEDULED" + + // Physical resources are allocated for the object + // Status available for: + // - Image + Allocated TechStatus = "ALLOCATED" + + // The object has released (returned to the platform) the physical resources that it occupied + // Status available for: + // - Image + Unallocated TechStatus = "UNALLOCATED" +) diff --git a/provider.tf b/provider.tf index a99c4b4..0f556df 100644 --- a/provider.tf +++ b/provider.tf @@ -2,7 +2,7 @@ terraform { required_providers { decort = { source = "digitalenergy.online/decort/decort" - version = "3.2.1" + version = "3.2.2" } } } diff --git a/samples/cloudapi/data_kvmvm/main.tf b/samples/cloudapi/data_kvmvm/main.tf new file mode 100644 index 0000000..9f080d9 --- /dev/null +++ b/samples/cloudapi/data_kvmvm/main.tf @@ -0,0 +1,54 @@ +/* +Пример использования +Получение данных о compute (виртулаьной машине) +*/ +#Расскомментируйте этот код, +#и внесите необходимые правки в версию и путь, +#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером +/* +terraform { + required_providers { + decort = { + version = "1.1" + source = "digitalenergy.online/decort/decort" + } + } +} +*/ + +provider "decort" { + authenticator = "oauth2" + #controller_url = + controller_url = "https://ds1.digitalenergy.online" + #oauth2_url = + oauth2_url = "https://sso.digitalenergy.online" + allow_unverified_ssl = true +} + +data "decort_kvmvm" "comp" { + #Для получения информации о виртуальной машине + #можно воспользоваться двумя методами: + #1. получение информации по идентификатору машины - compute_id + #2. получение информации по имени машины и идентификатору ресурсной группы - name и rg_id + + #id виртуальной машины + #опциональный параметр + #тип - число + #compute_id = 11346 + + #название машины + #опциональный параметр + #тип - строка + #используется вместе с параметром rg_id + #name = "test-rg-temp" + + #id ресурсной группы + #опциональный параметр + #тип - число + #используется вместе с параметром name + #rg_id = 1825 +} + +output "test" { + value = data.decort_kvmvm.comp +} diff --git a/samples/cloudapi/resource_kvmvm/main.tf b/samples/cloudapi/resource_kvmvm/main.tf index 301a7b0..e8485a9 100644 --- a/samples/cloudapi/resource_kvmvm/main.tf +++ b/samples/cloudapi/resource_kvmvm/main.tf @@ -114,6 +114,11 @@ resource "decort_kvmvm" "comp" { #опциональный параметр #тип - bool permanently = false + + #Флаг доступности компьюта для проведения с ним операций + #опицональный параметр + #тип - bool + #enable = true }