From 34abfd40af8e39949d8837ecb9358d5f97efcdd9 Mon Sep 17 00:00:00 2001 From: hkavya26 Date: Sat, 17 Jul 2021 16:39:16 +0530 Subject: [PATCH] Support: HPCS Resource and Datasource --- go.mod | 3 +- go.sum | 54 +- ibm/data_source_ibm_hpcs.go | 292 ++++++++++ ibm/data_source_ibm_hpcs_test.go | 38 ++ ibm/internal/hashcode/hashcode.go | 12 - ibm/provider.go | 3 + ibm/provider_test.go | 36 +- ibm/resource_ibm_hpcs.go | 891 ++++++++++++++++++++++++++++++ ibm/resource_ibm_hpcs_test.go | 202 +++++++ ibm/structures.go | 7 +- website/allowed-subcategories.txt | 1 + website/docs/d/hpcs.html.markdown | 56 ++ website/docs/r/hpcs.html.markdown | 112 ++++ 13 files changed, 1645 insertions(+), 62 deletions(-) create mode 100644 ibm/data_source_ibm_hpcs.go create mode 100644 ibm/data_source_ibm_hpcs_test.go create mode 100644 ibm/resource_ibm_hpcs.go create mode 100644 ibm/resource_ibm_hpcs_test.go create mode 100644 website/docs/d/hpcs.html.markdown create mode 100644 website/docs/r/hpcs.html.markdown diff --git a/go.mod b/go.mod index 8cd53eaa816..91f3c2cdc3a 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/IBM/go-sdk-core/v5 v5.5.1 github.com/IBM/ibm-cos-sdk-go v1.7.0 github.com/IBM/ibm-cos-sdk-go-config v1.2.0 + github.com/IBM/ibm-hpcs-tke-sdk v0.0.0-20210716185544-e8403b3501ef github.com/IBM/keyprotect-go-client v0.7.0 github.com/IBM/networking-go-sdk v0.18.0 github.com/IBM/platform-services-go-sdk v0.18.16 @@ -41,7 +42,7 @@ require ( github.com/minsikl/netscaler-nitro-go v0.0.0-20170827154432-5b14ce3643e3 github.com/mitchellh/go-homedir v1.1.0 github.com/softlayer/softlayer-go v1.0.3 - golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b + golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff // indirect gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index 76d35c1daef..127821a38fa 100644 --- a/go.sum +++ b/go.sum @@ -32,7 +32,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/IBM-Cloud/bluemix-go v0.0.0-20210706092416-dc4055f8e0ea h1:3B8Hd2WknLK8mA8UonA2MxgkMS9ZdLK0PjUwgc+czTU= @@ -71,6 +70,8 @@ github.com/IBM/ibm-cos-sdk-go v1.7.0 h1:3DZULY/D5WzjlIm+Iaj6h0surEjQs65EZk1YAe8+ github.com/IBM/ibm-cos-sdk-go v1.7.0/go.mod h1:Oi8AC5WNDhmUJgbo1GL2FtBdo0nRgbzE/1HmCL1SERU= github.com/IBM/ibm-cos-sdk-go-config v1.2.0 h1:1E93234yZgVS0ntm7eUwVb3h0AAayPGcxEhhizEN1LE= github.com/IBM/ibm-cos-sdk-go-config v1.2.0/go.mod h1:Wetfgv6m1xyuzpZLQTTLIBsWstxjYa15h+Utj7x53Dk= +github.com/IBM/ibm-hpcs-tke-sdk v0.0.0-20210716185544-e8403b3501ef h1:x7xHqeuiTUfvozRQo3qt7W1qispGpLsDXqnBfXpkvYY= +github.com/IBM/ibm-hpcs-tke-sdk v0.0.0-20210716185544-e8403b3501ef/go.mod h1:M2JyuyeWHPtgGNeezr6YqVRuaav2MpY8Ha4QrEYvMoI= github.com/IBM/keyprotect-go-client v0.7.0 h1:JstSHD14Lp6ihwQseyPuGcs1AjOBjAmcisP0dTBA6A0= github.com/IBM/keyprotect-go-client v0.7.0/go.mod h1:SVr2ylV/fhSQPDiUjWirN9fsyWFCNNbt8GIT8hPJVjE= github.com/IBM/networking-go-sdk v0.18.0 h1:mlALxXptnoDGviRW59ZQTyCr4PgTdQKp/5ksh2NM6Sk= @@ -85,13 +86,13 @@ github.com/IBM/secrets-manager-go-sdk v0.1.19 h1:0GPs5EoTaWNsjo4QPj64GNxlWfN8VHJ github.com/IBM/secrets-manager-go-sdk v0.1.19/go.mod h1:eO3dBhzPrHkkt+yPex/jB2xD6qHZxBko+Aw+0tfqHeA= github.com/IBM/vpc-go-sdk v0.8.0 h1:CPuLXuKa0fbhAR+veaynW8AtGqkO846XYBdfTQGrq4s= github.com/IBM/vpc-go-sdk v0.8.0/go.mod h1:rnMs3IWLSr0n0MvqX3pg96u0mkHVBk4oBsHQYYv5CXw= +github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56 h1:vuquMR410psHNax14XKNWa0Ae/kYgWJcXi0IFuX60N0= +github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56/go.mod h1:Zb3OT4l0mf7P/GOs2w2Ilj5sdm5Whoq3pa24dAEBHFc= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= 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= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= @@ -102,9 +103,7 @@ github.com/ScaleFT/sshkeys v0.0.0-20200327173127-6142f742bca5 h1:VauE2GcJNZFun2O github.com/ScaleFT/sshkeys v0.0.0-20200327173127-6142f742bca5/go.mod h1:gxOHeajFfvGQh/fxlC8oOKBe23xnnJTif00IFFbiT+o= github.com/Shopify/sarama v1.27.2 h1:1EyY1dsxNDUQEv0O/4TsjosHI2CgB1uo9H/v56xzTxc= github.com/Shopify/sarama v1.27.2/go.mod h1:g5s5osgELxgM+Md9Qni9rzo7Rbt+vvFQI4bt/Mc93II= -github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -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.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= @@ -119,7 +118,6 @@ github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/Y github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= -github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= 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= @@ -168,7 +166,6 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8 github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -182,25 +179,19 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI github.com/form3tech-oss/jwt-go v3.2.1+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/frankban/quicktest v1.10.2 h1:19ARM85nVi4xH7xPXuc5eM/udya5ieh7b/Sv+d844Tk= github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -304,7 +295,6 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= @@ -376,9 +366,7 @@ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0 h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQyBs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -396,7 +384,6 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -455,25 +442,19 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jarcoal/httpmock v1.0.5 h1:cHtVEcTxRSX4J0je7mWPfc9BpDpqzXSJ5HbymZmyHck= github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8= github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -482,7 +463,6 @@ github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfE github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -493,15 +473,12 @@ github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= @@ -557,10 +534,8 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uY github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q= github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= @@ -573,7 +548,6 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= @@ -581,7 +555,6 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= @@ -595,7 +568,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -608,7 +580,6 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -627,9 +598,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= @@ -640,7 +609,6 @@ github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaU github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/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/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= @@ -692,8 +660,9 @@ golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -834,9 +803,9 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79 h1:RX8C8PRZc2hTIod4ds8ij+/4RQX3AqhYj3uOHmyaz4E= golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -989,31 +958,25 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M= gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= -gopkg.in/h2non/gock.v1 v1.0.15 h1:SzLqcIlb/fDfg7UvukMpNcWsu7sI5tWwL+KCATZqks0= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN5hSM= gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= -gopkg.in/jcmturner/goidentity.v3 v3.0.0 h1:1duIyWiTaYvVx3YX2CYtpJbUFd7/UuPYCfgXtQ3VTbI= gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= gopkg.in/jcmturner/gokrb5.v7 v7.5.0 h1:a9tsXlIDD9SKxotJMK3niV7rPZAJeX2aD/0yg3qlIrg= gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= gopkg.in/jcmturner/rpc.v1 v1.1.0 h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU= gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1024,7 +987,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= diff --git a/ibm/data_source_ibm_hpcs.go b/ibm/data_source_ibm_hpcs.go new file mode 100644 index 00000000000..9919fbc498a --- /dev/null +++ b/ibm/data_source_ibm_hpcs.go @@ -0,0 +1,292 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package ibm + +import ( + "context" + "fmt" + + "github.com/IBM/ibm-hpcs-tke-sdk/tkesdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2" + "github.com/IBM-Cloud/bluemix-go/models" +) + +func dataSourceIBMHPCS() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMHPCSRead, + + Schema: map[string]*schema.Schema{ + "name": { + Description: "Resource instance name for example, myobjectstorage", + Type: schema.TypeString, + Required: true, + }, + + "resource_group_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The id of the resource group in which the instance is present", + }, + + "location": { + Description: "The location or the environment in which instance exists", + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "service": { + Description: "The service type of the instance", + Type: schema.TypeString, + Optional: true, + Default: "hs-crypto", + }, + "units": { + Type: schema.TypeInt, + Computed: true, + Description: "The number of operational crypto units for your service instance", + }, + "failover_units": { + Type: schema.TypeInt, + Computed: true, + Description: "The number of failover crypto units for your service instance", + }, + + "plan": { + Description: "The plan type of the instance", + Type: schema.TypeString, + Computed: true, + }, + + "status": { + Description: "The resource instance status", + Type: schema.TypeString, + Computed: true, + }, + + "crn": { + Type: schema.TypeString, + Computed: true, + Description: "CRN of resource instance", + }, + + "guid": { + Type: schema.TypeString, + Computed: true, + Description: "Guid of resource instance", + }, + "extensions": { + Type: schema.TypeMap, + Computed: true, + Description: "The extended metadata as a map associated with the resource instance.", + }, + "hsm_info": { + Type: schema.TypeList, + Computed: true, + Description: "HSM Info of HPCS CryptoUnits", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "hsm_id": { + Type: schema.TypeString, + Computed: true, + }, + "hsm_location": { + Type: schema.TypeString, + Computed: true, + }, + "hsm_type": { + Type: schema.TypeString, + Computed: true, + }, + "signature_threshold": { + Type: schema.TypeInt, + Computed: true, + }, + "revocation_threshold": { + Type: schema.TypeInt, + Computed: true, + }, + "current_mk_status": { + Type: schema.TypeString, + Computed: true, + }, + "new_mk_status": { + Type: schema.TypeString, + Computed: true, + }, + "current_mkvp": { + Type: schema.TypeString, + Computed: true, + }, + "new_mkvp": { + Type: schema.TypeString, + Computed: true, + }, + "admins": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "ski": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMHPCSRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + rsConClient, err := meta.(ClientSession).ResourceControllerAPIV2() + if err != nil { + return diag.FromErr(err) + } + rsAPI := rsConClient.ResourceServiceInstanceV2() + name := d.Get("name").(string) + + rsInstQuery := controllerv2.ServiceInstanceQuery{ + Name: name, + } + + if rsGrpID, ok := d.GetOk("resource_group_id"); ok { + rsInstQuery.ResourceGroupID = rsGrpID.(string) + } else { + defaultRg, err := defaultResourceGroup(meta) + if err != nil { + return diag.FromErr(err) + } + rsInstQuery.ResourceGroupID = defaultRg + } + + rsCatClient, err := meta.(ClientSession).ResourceCatalogAPI() + if err != nil { + return diag.FromErr(err) + } + rsCatRepo := rsCatClient.ResourceCatalog() + + if service, ok := d.GetOk("service"); ok { + + serviceOff, err := rsCatRepo.FindByName(service.(string), true) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving service offering: %s", err)) + } + + rsInstQuery.ServiceID = serviceOff[0].ID + } + + var instances []models.ServiceInstanceV2 + + instances, err = rsAPI.ListInstances(rsInstQuery) + if err != nil { + return diag.FromErr(err) + } + var filteredInstances []models.ServiceInstanceV2 + var location string + + if loc, ok := d.GetOk("location"); ok { + location = loc.(string) + for _, instance := range instances { + if getLocation(instance) == location { + filteredInstances = append(filteredInstances, instance) + } + } + } else { + filteredInstances = instances + } + + if len(filteredInstances) == 0 { + return diag.FromErr(fmt.Errorf("[ERROR] No resource instance found with name [%s]\nIf not specified please specify more filters like resource_group_id if instance doesn't exists in default group, location or service", name)) + } + + var instance models.ServiceInstanceV2 + + if len(filteredInstances) > 1 { + return diag.FromErr(fmt.Errorf( + "[ERROR] More than one resource instance found with name matching [%s]\nIf not specified please specify more filters like resource_group_id if instance doesn't exists in default group, location or service", name)) + } + instance = filteredInstances[0] + + d.SetId(instance.ID) + d.Set("status", instance.State) + d.Set("resource_group_id", instance.ResourceGroupID) + d.Set("location", instance.RegionID) + serviceOff, err := rsCatRepo.GetServiceName(instance.ServiceID) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving service offering: %s", err)) + } + + d.Set("service", serviceOff) + d.Set("guid", instance.Guid) + if len(instance.Extensions) == 0 { + d.Set("extensions", instance.Extensions) + } else { + d.Set("extensions", Flatten(instance.Extensions)) + } + if instance.Parameters != nil { + if units, ok := instance.Parameters["units"]; ok { + d.Set("units", units) + } + if failover_units, ok := instance.Parameters["failover_units"]; ok { + d.Set("failover_units", failover_units) + } + } + servicePlan, err := rsCatRepo.GetServicePlanName(instance.ResourcePlanID) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving plan: %s", err)) + } + d.Set("plan", servicePlan) + d.Set("crn", instance.Crn.String()) + + ci, err := hsmClient(d, meta) + if err != nil { + return diag.FromErr(err) + } + ci.InstanceId = instance.Guid + hsmInfo, err := tkesdk.Query(ci) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error Quering HSM config %s", err)) + } + d.Set("hsm_info", FlattenHSMInfo(hsmInfo)) + + return nil +} + +func FlattenHSMInfo(hsmInfo []tkesdk.HsmInfo) []map[string]interface{} { + info := make([]map[string]interface{}, 0) + for _, h := range hsmInfo { + hsm := make(map[string]interface{}) + hsm["hsm_id"] = h.HsmId + hsm["hsm_location"] = h.HsmLocation + hsm["hsm_type"] = h.HsmType + hsm["signature_threshold"] = h.SignatureThreshold + hsm["revocation_threshold"] = h.RevocationThreshold + hsm["current_mk_status"] = h.CurrentMKStatus + hsm["new_mk_status"] = h.NewMKStatus + hsm["current_mkvp"] = h.CurrentMKVP + hsm["new_mkvp"] = h.NewMKVP + admin := make([]map[string]interface{}, 0) + for _, a := range h.Admins { + ad := make(map[string]interface{}) + ad["name"] = a.AdminName + ad["ski"] = a.AdminSKI + admin = append(admin, ad) + } + hsm["admins"] = admin + info = append(info, hsm) + } + return info +} diff --git a/ibm/data_source_ibm_hpcs_test.go b/ibm/data_source_ibm_hpcs_test.go new file mode 100644 index 00000000000..fd976b04956 --- /dev/null +++ b/ibm/data_source_ibm_hpcs_test.go @@ -0,0 +1,38 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package ibm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccIBMHPCSDatasourceBasic(t *testing.T) { + instanceName := "test-hpcs" + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMHPCSDatasourceConfig(instanceName), + Destroy: true, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.ibm_hpcs.hpcs", "name", instanceName), + resource.TestCheckResourceAttr("data.ibm_hpcs.hpcs", "service", "hs-crypto"), + ), + }, + }, + }) +} + +func testAccCheckIBMHPCSDatasourceConfig(instanceName string) string { + return fmt.Sprintf(` + data "ibm_hpcs" "hpcs" { + name = "%s" + } + `, instanceName) + +} diff --git a/ibm/internal/hashcode/hashcode.go b/ibm/internal/hashcode/hashcode.go index 20d789b82cc..94c0ff5082c 100644 --- a/ibm/internal/hashcode/hashcode.go +++ b/ibm/internal/hashcode/hashcode.go @@ -10,14 +10,6 @@ import ( ) // String hashes a string to a unique hashcode. -// -// Deprecated: This will be removed in v2 without replacement. If you need -// its functionality, you can copy it, import crc32 directly, or reference the -// v1 package. -// -// crc32 returns a uint32, but for our use we need -// and non negative integer. Here we cast to an integer -// and invert it if the result is negative. func String(s string) int { v := int(crc32.ChecksumIEEE([]byte(s))) if v >= 0 { @@ -31,10 +23,6 @@ func String(s string) int { } // Strings hashes a list of strings to a unique hashcode. -// -// Deprecated: This will be removed in v2 without replacement. If you need -// its functionality, you can copy it, import crc32 directly, or reference the -// v1 package. func Strings(strings []string) string { var buf bytes.Buffer diff --git a/ibm/provider.go b/ibm/provider.go index a1adf7d69a3..199383e2169 100644 --- a/ibm/provider.go +++ b/ibm/provider.go @@ -227,6 +227,7 @@ func Provider() *schema.Provider { "ibm_dns_domain": dataSourceIBMDNSDomain(), "ibm_dns_secondary": dataSourceIBMDNSSecondary(), "ibm_event_streams_topic": dataSourceIBMEventStreamsTopic(), + "ibm_hpcs": dataSourceIBMHPCS(), "ibm_iam_access_group": dataSourceIBMIAMAccessGroup(), "ibm_iam_account_settings": dataSourceIBMIAMAccountSettings(), "ibm_iam_auth_token": dataSourceIBMIAMAuthToken(), @@ -479,6 +480,7 @@ func Provider() *schema.Provider { "ibm_event_streams_topic": resourceIBMEventStreamsTopic(), "ibm_firewall": resourceIBMFirewall(), "ibm_firewall_policy": resourceIBMFirewallPolicy(), + "ibm_hpcs": resourceIBMHPCS(), "ibm_iam_access_group": resourceIBMIAMAccessGroup(), "ibm_iam_account_settings": resourceIbmIamAccountSettings(), "ibm_iam_custom_role": resourceIBMIAMCustomRole(), @@ -687,6 +689,7 @@ func Validator() ValidatorDict { "ibm_function_rule": resourceIBMFuncRuleValidator(), "ibm_function_trigger": resourceIBMFuncTriggerValidator(), "ibm_function_namespace": resourceIBMFuncNamespaceValidator(), + "ibm_hpcs": resourceIBMHPCSValidator(), "ibm_is_dedicated_host_group": resourceIbmIsDedicatedHostGroupValidator(), "ibm_is_dedicated_host": resourceIbmIsDedicatedHostValidator(), "ibm_is_dedicated_host_disk_management": resourceIBMISDedicatedHostDiskManagementValidator(), diff --git a/ibm/provider_test.go b/ibm/provider_test.go index 39793e200ee..316100c69ca 100644 --- a/ibm/provider_test.go +++ b/ibm/provider_test.go @@ -74,6 +74,10 @@ var hpcsInstanceID string var secretsManagerInstanceID string var secretsManagerSecretType string var secretsManagerSecretID string +var hpcsAdmin1 string +var hpcsToken1 string +var hpcsAdmin2 string +var hpcsToken2 string // For Power Colo @@ -556,6 +560,22 @@ func init() { if account_to_be_imported == "" { fmt.Println("[INFO] Set the environment variable ACCOUNT_TO_BE_IMPORTED for testing import enterprise account resource else tests will fail if this is not set correctly") } + hpcsAdmin1 = os.Getenv("IBM_HPCS_ADMIN1") + if hpcsAdmin1 == "" { + fmt.Println("[WARN] Set the environment variable IBM_HPCS_ADMIN1 with a VALID HPCS Admin Key1 Path") + } + hpcsToken1 = os.Getenv("IBM_HPCS_TOKEN1") + if hpcsToken1 == "" { + fmt.Println("[WARN] Set the environment variable IBM_HPCS_TOKEN1 with a VALID token for HPCS Admin Key1") + } + hpcsAdmin2 = os.Getenv("IBM_HPCS_ADMIN2") + if hpcsAdmin2 == "" { + fmt.Println("[WARN] Set the environment variable IBM_HPCS_ADMIN2 with a VALID HPCS Admin Key2 Path") + } + hpcsToken2 = os.Getenv("IBM_HPCS_TOKEN2") + if hpcsToken2 == "" { + fmt.Println("[WARN] Set the environment variable IBM_HPCS_TOKEN2 with a VALID token for HPCS Admin Key2") + } } @@ -622,7 +642,21 @@ func testAccPreCheckCis(t *testing.T) { t.Fatal("IBM_CIS_DOMAIN_TEST must be set for acceptance tests") } } - +func testAccPreCheckHPCS(t *testing.T) { + testAccPreCheck(t) + if hpcsAdmin1 == "" { + t.Fatal("IBM_HPCS_ADMIN1 must be set for acceptance tests") + } + if hpcsToken1 == "" { + t.Fatal("IBM_HPCS_TOKEN1 must be set for acceptance tests") + } + if hpcsAdmin2 == "" { + t.Fatal("IBM_HPCS_ADMIN2 must be set for acceptance tests") + } + if hpcsToken2 == "" { + t.Fatal("IBM_HPCS_TOKEN2 must be set for acceptance tests") + } +} func testAccPreCheckCOS(t *testing.T) { testAccPreCheck(t) if cosCRN == "" { diff --git a/ibm/resource_ibm_hpcs.go b/ibm/resource_ibm_hpcs.go new file mode 100644 index 00000000000..dd8d163f4fd --- /dev/null +++ b/ibm/resource_ibm_hpcs.go @@ -0,0 +1,891 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package ibm + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "log" + "os" + "strings" + "time" + + "github.com/IBM/ibm-hpcs-tke-sdk/tkesdk" + rc "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/bluemix-go/models" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/internal/hashcode" +) + +func resourceIBMHPCS() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMHPCSCreate, + ReadContext: resourceIBMHPCSRead, + UpdateContext: resourceIBMHPCSUpdate, + DeleteContext: resourceIBMHPCSDelete, + Importer: &schema.ResourceImporter{}, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), + }, + + CustomizeDiff: customdiff.Sequence( + func(_ context.Context, diff *schema.ResourceDiff, v interface{}) error { + return immutableResourceCustomizeDiff([]string{"units", "failover_units", "location", "resource_group_id", "service"}, diff) + }, + func(_ context.Context, diff *schema.ResourceDiff, v interface{}) error { + return resourceTagsCustomizeDiff(diff) + }, + ), + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "A name for the HPCS instance", + }, + "plan": { + Type: schema.TypeString, + Required: true, + Description: "The plan type of the HPCS Instance", + }, + "location": { + Description: "The location where the HPCS instance available", + Required: true, + Type: schema.TypeString, + }, + "units": { + Type: schema.TypeInt, + Required: true, + Description: "The number of operational crypto units for your service instance", + }, + "failover_units": { + Type: schema.TypeInt, + Optional: true, + Description: "The number of failover crypto units for your service instance", + }, + "service": { + Type: schema.TypeString, + Optional: true, + Default: "hs-crypto", + Description: "The name of the service offering `hs-crypto` ", + }, + "resource_group_id": { + Description: "The resource group id", + Optional: true, + Type: schema.TypeString, + Computed: true, + }, + "service_endpoints": { + Description: "Types of the service endpoints. Possible values are 'public', 'private', 'public-and-private'.", + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validateAllowedStringValue([]string{"public", "private", "public-and-private"}), + }, + "tags": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString, ValidateFunc: InvokeValidator("ibm_hpcs", "tag")}, + Set: resourceIBMVPCHash, + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "Status of HPCS instance", + }, + "crn": { + Type: schema.TypeString, + Computed: true, + Description: "CRN of HPCS instance", + }, + "guid": { + Type: schema.TypeString, + Computed: true, + Description: "Guid of HPCS instance", + }, + "dashboard_url": { + Description: "Dashboard URL to access resource.", + Type: schema.TypeString, + Computed: true, + }, + "state": { + Description: "The current state of the instance.", + Type: schema.TypeString, + Computed: true, + }, + "resource_aliases_url": { + Description: "The relative path to the resource aliases for the instance.", + Type: schema.TypeString, + Computed: true, + }, + "resource_bindings_url": { + Description: "The relative path to the resource bindings for the instance.", + Type: schema.TypeString, + Computed: true, + }, + "resource_keys_url": { + Description: "The relative path to the resource keys for the instance.", + Type: schema.TypeString, + Computed: true, + }, + "created_at": { + Type: schema.TypeString, + Description: "The date when the instance was created.", + Computed: true, + }, + "created_by": { + Type: schema.TypeString, + Description: "The subject who created the instance.", + Computed: true, + }, + "update_at": { + Type: schema.TypeString, + Description: "The date when the instance was last updated.", + Computed: true, + }, + "update_by": { + Type: schema.TypeString, + Description: "The subject who updated the instance.", + Computed: true, + }, + "deleted_at": { + Type: schema.TypeString, + Description: "The date when the instance was deleted.", + Computed: true, + }, + "deleted_by": { + Type: schema.TypeString, + Description: "The subject who deleted the instance.", + Computed: true, + }, + "scheduled_reclaim_at": { + Type: schema.TypeString, + Description: "The date when the instance was scheduled for reclamation.", + Computed: true, + }, + "scheduled_reclaim_by": { + Type: schema.TypeString, + Description: "The subject who initiated the instance reclamation.", + Computed: true, + }, + "restored_at": { + Type: schema.TypeString, + Description: "The date when the instance under reclamation was restored.", + Computed: true, + }, + "restored_by": { + Type: schema.TypeString, + Description: "The subject who restored the instance back from reclamation.", + Computed: true, + }, + "extensions": { + Type: schema.TypeMap, + Computed: true, + Description: "The extended metadata as a map associated with the HPCS instance.", + }, + "signature_server_url": { + Type: schema.TypeString, + Optional: true, + Description: "URL of signing service", + }, + "signature_threshold": { + Type: schema.TypeInt, + Required: true, + Description: "Signature Threshold Value", + }, + "revocation_threshold": { + Type: schema.TypeInt, + Required: true, + Description: "Revocation Threshold Value", + }, + "admins": { + Type: schema.TypeSet, + Required: true, + Description: "Crypto Unit Administrators", + Set: resourceIBMHPCSAdminHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "Admin Name", + }, + "key": { + Type: schema.TypeString, + Required: true, + Description: "The administrator signature key", + }, + "token": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + Description: "Credential giving access to the administrator signature key", + }, + }, + }, + }, + "hsm_info": { + Type: schema.TypeList, + Computed: true, + Description: "HSM Configuration", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "signature_threshold": { + Type: schema.TypeInt, + Computed: true, + Description: "Signature Threshold Value", + }, + "revocation_threshold": { + Type: schema.TypeInt, + Computed: true, + Description: "Revocation Threshold Value", + }, + "admins": { + Type: schema.TypeSet, + Computed: true, + Description: "Crypto Unit Administrators", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Description: "Admin Name", + }, + "ski": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "hsm_id": { + Type: schema.TypeString, + Computed: true, + }, + "hsm_location": { + Type: schema.TypeString, + Computed: true, + }, + "hsm_type": { + Type: schema.TypeString, + Computed: true, + }, + "current_mk_status": { + Type: schema.TypeString, + Computed: true, + }, + "new_mk_status": { + Type: schema.TypeString, + Computed: true, + }, + "current_mkvp": { + Type: schema.TypeString, + Computed: true, + }, + "new_mkvp": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +type HPCSParams struct { + Units int `json:"units,omitempty"` + FailoverUnits int `json:"failover_units,omitempty"` + ServiceEndpoints string `json:"service-endpoints,omitempty"` +} + +func resourceIBMHPCSValidator() *ResourceValidator { + validateSchema := make([]ValidateSchema, 1) + validateSchema = append(validateSchema, + ValidateSchema{ + Identifier: "tag", + ValidateFunctionIdentifier: ValidateRegexpLen, + Type: TypeString, + Optional: true, + Regexp: `^[A-Za-z0-9:_ .-]+$`, + MinValueLength: 1, + MaxValueLength: 128}) + + ibmResourceInstanceResourceValidator := ResourceValidator{ResourceName: "ibm_hpcs", Schema: validateSchema} + return &ibmResourceInstanceResourceValidator +} + +func resourceIBMHPCSCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + rsConClient, err := meta.(ClientSession).ResourceControllerV2API() + if err != nil { + return diag.FromErr(err) + } + + serviceName := d.Get("service").(string) + plan := d.Get("plan").(string) + name := d.Get("name").(string) + location := d.Get("location").(string) + + rsInst := rc.CreateResourceInstanceOptions{ + Name: &name, + } + // Fetch Service Plan ID using Global Catalog APIs + rsCatClient, err := meta.(ClientSession).ResourceCatalogAPI() + if err != nil { + return diag.FromErr(err) + } + rsCatRepo := rsCatClient.ResourceCatalog() + + serviceOff, err := rsCatRepo.FindByName(serviceName, true) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving service offering: %s", err)) + } + + if metadata, ok := serviceOff[0].Metadata.(*models.ServiceResourceMetadata); ok { + if !metadata.Service.RCProvisionable { + return diag.FromErr(fmt.Errorf("[ERROR] %s cannot be provisioned by resource controller", serviceName)) + } + } else { + return diag.FromErr(fmt.Errorf("[ERROR] Cannot create instance of resource %s", serviceName)) + } + + servicePlan, err := rsCatRepo.GetServicePlanID(serviceOff[0], plan) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving plan: %s", err)) + } + rsInst.ResourcePlanID = &servicePlan + + // Fetch Catalog CRN using Global Catalog APIs + deployments, err := rsCatRepo.ListDeployments(servicePlan) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving deployment for plan %s : %s", plan, err)) + } + if len(deployments) == 0 { + return diag.FromErr(fmt.Errorf("[ERROR] No deployment found for service plan : %s", plan)) + } + deployments, supportedLocations := filterDeployments(deployments, location) + if len(deployments) == 0 { + locationList := make([]string, 0, len(supportedLocations)) + for l := range supportedLocations { + locationList = append(locationList, l) + } + return diag.FromErr(fmt.Errorf("[ERROR] No deployment found for service plan %s at location %s.\n valid location(s) are: %q", plan, location, locationList)) + } + rsInst.Target = &deployments[0].CatalogCRN + + // Get Resource Group ID from User.. If not provided fetch Default resource group ID of the account + if rsGrpID, ok := d.GetOk("resource_group_id"); ok { + rg := rsGrpID.(string) + rsInst.ResourceGroup = &rg + } else { + defaultRg, err := defaultResourceGroup(meta) + if err != nil { + return diag.FromErr(err) + } + rsInst.ResourceGroup = &defaultRg + } + + // Resource Controller Parameters for HPCS Service + params := HPCSParams{} + if units, ok := d.GetOk("units"); ok { + params.Units = units.(int) + } + if failover_units, ok := d.GetOk("failover_units"); ok { + params.FailoverUnits = failover_units.(int) + } + if serviceEndpoint, ok := d.GetOk("service_endpoints"); ok { + params.ServiceEndpoints = serviceEndpoint.(string) + } + // Convert HPCSParams srtuct to map + parameters, _ := json.Marshal(params) + var raw map[string]interface{} + json.Unmarshal(parameters, &raw) + rsInst.Parameters = raw + + // Create HPCS Instance + instance, resp, err := rsConClient.CreateResourceInstance(&rsInst) + if err != nil || instance == nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error when creating HPCS instance: %s with resp code: %s", err, resp)) + } + d.SetId(*instance.ID) // Set Resource ID + _, err = waitForHPCSInstanceCreate(d, meta) // Wait for Instance to be available + if err != nil { + return diag.FromErr(fmt.Errorf( + "[ERROR] Error waiting for create HPCS instance (%s) to be succeeded: %s", d.Id(), err)) + } + + // Update Tags for this Resource using Global Tagging APIs + v := os.Getenv("IC_ENV_TAGS") + if _, ok := d.GetOk("tags"); ok || v != "" { + oldList, newList := d.GetChange("tags") + err = UpdateTagsUsingCRN(oldList, newList, meta, *instance.CRN) + if err != nil { + log.Printf( + "[ERROR] Error on create of HPCS instance (%s) tags: %s", d.Id(), err) + } + } + + return resourceIBMHPCSUpdate(context, d, meta) +} +func resourceIBMHPCSRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + rsConClient, err := meta.(ClientSession).ResourceControllerV2API() + if err != nil { + return diag.FromErr(err) + } + + instanceID := d.Id() + resourceInstanceGet := rc.GetResourceInstanceOptions{ + ID: &instanceID, + } + instance, resp, err := rsConClient.GetResourceInstance(&resourceInstanceGet) + if err != nil || instance == nil { + if resp != nil && resp.StatusCode == 404 { // If instance doesnt not exists, empty the statefile + d.SetId("") + return nil + } + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving HPCS instance: %s with resp code: %s", err, resp)) + } + if instance != nil && (strings.Contains(*instance.State, "removed") || strings.Contains(*instance.State, rsInstanceReclamation)) { + log.Printf("[WARN] Removing instance from state because it's in removed or pending_reclamation state") + d.SetId("") + return nil + } + + d.Set("name", instance.Name) + d.Set("status", instance.State) + d.Set("resource_group_id", instance.ResourceGroupID) + d.Set("crn", instance.CRN) + d.Set("dashboard_url", instance.DashboardURL) + d.Set("guid", instance.GUID) + d.Set("resource_keys_url", instance.ResourceKeysURL) + d.Set("resource_bindings_url", instance.ResourceBindingsURL) + d.Set("resource_aliases_url", instance.ResourceAliasesURL) + d.Set("state", instance.State) + d.Set("service", strings.Split(instanceID, ":")[4]) + //Set tags + tags, err := GetTagsUsingCRN(meta, *instance.CRN) + if err != nil { + log.Printf( + "[ERROR] Error on get of HPCS instance tags (%s) tags: %s", d.Id(), err) + } + d.Set("tags", tags) + // Set Location + if instance.CRN != nil { + location := strings.Split(*instance.CRN, ":") + if len(location) > 5 { + d.Set("location", location[5]) + } + } + // Set Service Plan + rsCatClient, err := meta.(ClientSession).ResourceCatalogAPI() + if err != nil { + return diag.FromErr(err) + } + rsCatRepo := rsCatClient.ResourceCatalog() + + servicePlan, err := rsCatRepo.GetServicePlanName(*instance.ResourcePlanID) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving plan: %s", err)) + } + d.Set("plan", servicePlan) + // Set Instance parameters + if instance.Parameters != nil { + if endpoint, ok := instance.Parameters["service-endpoints"]; ok { + d.Set("service_endpoints", endpoint) + } + if units, ok := instance.Parameters["units"]; ok { + d.Set("units", units) + } + if failover_units, ok := instance.Parameters["failover_units"]; ok { + d.Set("failover_units", failover_units) + } + } + // Set Extensions + if len(instance.Extensions) == 0 { + d.Set("extensions", instance.Extensions) + } else { + d.Set("extensions", Flatten(instance.Extensions)) + } + d.Set("restored_by", instance.RestoredBy) + d.Set("scheduled_reclaim_by", instance.ScheduledReclaimBy) + d.Set("deleted_by", instance.DeletedBy) + d.Set("update_by", instance.UpdatedBy) + d.Set("created_by", instance.CreatedBy) + if instance.RestoredAt != nil { + d.Set("restored_at", instance.RestoredAt.String()) + } + if instance.ScheduledReclaimAt != nil { + d.Set("scheduled_reclaim_at", instance.ScheduledReclaimAt.String()) + } + if instance.ScheduledReclaimAt != nil { + d.Set("deleted_at", instance.DeletedAt.String()) + } + if instance.UpdatedAt != nil { + d.Set("update_at", instance.UpdatedAt.String()) + } + if instance.CreatedAt != nil { + d.Set("created_at", instance.CreatedAt.String()) + } + // Bluemix Session to get Oauth tokens + ci, err := hsmClient(d, meta) + if err != nil { + return diag.FromErr(err) + } + ci.InstanceId = *instance.GUID + + hsmInfo, err := tkesdk.Query(ci) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error Quering HSM config: %s", err)) + } + d.Set("hsm_info", FlattenHSMInfo(hsmInfo)) + + if validateHSM(hsmInfo) && !d.IsNewResource() { + d.Set("admins", nil) + d.Set("signature_threshold", nil) + d.Set("revocation_threshold", nil) + } + + return nil +} + +func resourceIBMHPCSUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + rsConClient, err := meta.(ClientSession).ResourceControllerV2API() + if err != nil { + return diag.FromErr(err) + } + + instanceID := d.Id() + resourceInstanceUpdate := rc.UpdateResourceInstanceOptions{ + ID: &instanceID, + } + update := false + if d.HasChange("name") { + name := d.Get("name").(string) + resourceInstanceUpdate.Name = &name + update = true + } + if d.HasChange("plan") { + plan := d.Get("plan").(string) + service := d.Get("service").(string) + rsCatClient, err := meta.(ClientSession).ResourceCatalogAPI() + if err != nil { + return diag.FromErr(err) + } + rsCatRepo := rsCatClient.ResourceCatalog() + + serviceOff, err := rsCatRepo.FindByName(service, true) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving service offering: %s", err)) + } + + servicePlan, err := rsCatRepo.GetServicePlanID(serviceOff[0], plan) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error retrieving plan: %s", err)) + } + + resourceInstanceUpdate.ResourcePlanID = &servicePlan + update = true + + } + if d.HasChange("service_endpoints") { + params := Params{} + params.ServiceEndpoints = d.Get("service_endpoints").(string) + parameters, _ := json.Marshal(params) + var raw map[string]interface{} + json.Unmarshal(parameters, &raw) + resourceInstanceUpdate.Parameters = raw + update = true + } + resourceInstanceGet := rc.GetResourceInstanceOptions{ + ID: &instanceID, + } + instance, resp, err := rsConClient.GetResourceInstance(&resourceInstanceGet) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error Getting HPCS instance: %s with resp code: %s", err, resp)) + } + if d.HasChange("tags") { + oldList, newList := d.GetChange(isVPCTags) + err = UpdateTagsUsingCRN(oldList, newList, meta, *instance.CRN) + if err != nil { + log.Printf( + "[ERROR] Error on update of HPCS instance (%s) tags: %s", d.Id(), err) + } + } + if update && !d.IsNewResource() { // Update RC API only if its not a new resource + _, resp, err = rsConClient.UpdateResourceInstance(&resourceInstanceUpdate) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error updating HPCS instance: %s with resp code: %s", err, resp)) + } + + _, err = waitForHPCSInstanceUpdate(d, meta) + if err != nil { + return diag.FromErr(fmt.Errorf( + "[ERROR] Error waiting for update HPCS instance (%s) to be succeeded: %s", d.Id(), err)) + } + } + // Initialise HPCS Crypto Units + + if d.HasChange("signature_threshold") || d.HasChange("revocation_threshold") || d.HasChange("admins") || d.HasChange("signature_server_url") { + if url, ok := d.GetOk("signature_server_url"); ok { + serverURL := url.(string) + err := os.Setenv("TKE_SIGNSERV_URL", serverURL) + if err != nil { + return diag.FromErr(err) + } + } + hsm_config := expandHSMConfig(d, meta) + // Bluemix Session to get Oauth tokens + ci, err := hsmClient(d, meta) + if err != nil { + return diag.FromErr(err) + } + ci.InstanceId = *instance.GUID + + // Check Transitions + problems, err := tkesdk.CheckTransition(ci, hsm_config) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error Checking Transitions: %s", err)) + } + if len(problems) != 0 { + return diag.FromErr(fmt.Errorf("[ERROR] Error Checking Transitions: %v", problems)) + } + // Update / Initialize Crypto Units + hsmDetails, err := tkesdk.Update(ci, hsm_config) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error Updating Crypto Units: %s", err)) + } + if len(hsmDetails) != 0 { + return diag.FromErr(fmt.Errorf("[ERROR] Error Updating Crypto Units..One or more problems were found during initial checks: %v", hsmDetails)) + } + } + return resourceIBMHPCSRead(context, d, meta) +} +func expandHSMConfig(d *schema.ResourceData, meta interface{}) tkesdk.HsmConfig { + hsmConfig := tkesdk.HsmConfig{} + if s, ok := d.GetOk("signature_threshold"); ok { + hsmConfig.SignatureThreshold = s.(int) + } + if r, ok := d.GetOk("revocation_threshold"); ok { + hsmConfig.RevocationThreshold = r.(int) + } + if a, ok := d.GetOk("admins"); ok { + ads := a.(*schema.Set).List() + admins := []tkesdk.AdminInfo{} + for _, a := range ads { + ad := a.(map[string]interface{}) + admin := tkesdk.AdminInfo{ + Name: ad["name"].(string), + Key: ad["key"].(string), + Token: ad["token"].(string), + } + admins = append(admins, admin) + } + hsmConfig.Admins = admins + } + return hsmConfig +} +func resourceIBMHPCSDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + rsConClient, err := meta.(ClientSession).ResourceControllerV2API() + if err != nil { + return diag.FromErr(err) + } + id := d.Id() + resourceInstanceGet := rc.GetResourceInstanceOptions{ + ID: &id, + } + instance, resp, err := rsConClient.GetResourceInstance(&resourceInstanceGet) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error Getting HPCS instance: %s with resp code: %s", err, resp)) + } + // Bluemix Session to get Oauth tokens + ci, err := hsmClient(d, meta) + if err != nil { + return diag.FromErr(err) + } + ci.InstanceId = *instance.GUID + if url, ok := d.GetOk("signature_server_url"); ok { + serverURL := url.(string) + err := os.Setenv("TKE_SIGNSERV_URL", serverURL) + if err != nil { + return diag.FromErr(err) + } + } + // Zeroize Crypto Units + hsm := expandHSMConfig(d, meta) + err = tkesdk.Zeroize(ci, hsm) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error Zeroizing Crypto Units: %s", err)) + } + + // Delete Instance + recursive := true + resourceInstanceDelete := rc.DeleteResourceInstanceOptions{ + ID: &id, + Recursive: &recursive, + } + resp, error := rsConClient.DeleteResourceInstance(&resourceInstanceDelete) + if error != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error deleting HPCS instance: %s with resp code: %s", error, resp)) + } + _, err = waitForHPCSInstanceDelete(d, meta) + if err != nil { + return diag.FromErr(fmt.Errorf( + "[ERROR] Error waiting for HPCS instance (%s) to be deleted: %s", d.Id(), err)) + } + + d.SetId("") + + return nil +} +func waitForHPCSInstanceCreate(d *schema.ResourceData, meta interface{}) (interface{}, error) { + rsConClient, err := meta.(ClientSession).ResourceControllerV2API() + if err != nil { + return false, err + } + instanceID := d.Id() + resourceInstanceGet := rc.GetResourceInstanceOptions{ + ID: &instanceID, + } + + stateConf := &resource.StateChangeConf{ + Pending: []string{rsInstanceProgressStatus, rsInstanceInactiveStatus, rsInstanceProvisioningStatus}, + Target: []string{rsInstanceSuccessStatus}, + Refresh: func() (interface{}, string, error) { + instance, resp, err := rsConClient.GetResourceInstance(&resourceInstanceGet) + if err != nil { + if resp != nil && resp.StatusCode == 404 { + return nil, "", fmt.Errorf("[ERROR] HPCS instance %s does not exist anymore: %v", d.Id(), err) + } + return nil, "", fmt.Errorf("[ERROR] Get on HPCS instance %s failed with resp code: %s, err: %v", d.Id(), resp, err) + } + if *instance.State == rsInstanceFailStatus { + return instance, *instance.State, fmt.Errorf("[ERROR] The status of HPCS instance %s failed: %v", d.Id(), err) + } + return instance, *instance.State, nil + }, + Timeout: d.Timeout(schema.TimeoutCreate), + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + return stateConf.WaitForState() +} + +func waitForHPCSInstanceUpdate(d *schema.ResourceData, meta interface{}) (interface{}, error) { + rsConClient, err := meta.(ClientSession).ResourceControllerV2API() + if err != nil { + return false, err + } + instanceID := d.Id() + resourceInstanceGet := rc.GetResourceInstanceOptions{ + ID: &instanceID, + } + + stateConf := &resource.StateChangeConf{ + Pending: []string{rsInstanceProgressStatus, rsInstanceInactiveStatus}, + Target: []string{rsInstanceSuccessStatus}, + Refresh: func() (interface{}, string, error) { + instance, resp, err := rsConClient.GetResourceInstance(&resourceInstanceGet) + if err != nil { + if resp != nil && resp.StatusCode == 404 { + return nil, "", fmt.Errorf("[ERROR] HPCS instance %s does not exist anymore: %v", d.Id(), err) + } + return nil, "", fmt.Errorf("[ERROR] Get the HPCS instance %s failed with resp code: %s, err: %v", d.Id(), resp, err) + } + if *instance.State == rsInstanceFailStatus { + return instance, *instance.State, fmt.Errorf("[ERROR] The status of HPCS instance %s failed: %v", d.Id(), err) + } + return instance, *instance.State, nil + }, + Timeout: d.Timeout(schema.TimeoutUpdate), + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + return stateConf.WaitForState() +} + +func waitForHPCSInstanceDelete(d *schema.ResourceData, meta interface{}) (interface{}, error) { + rsConClient, err := meta.(ClientSession).ResourceControllerV2API() + if err != nil { + return false, err + } + instanceID := d.Id() + resourceInstanceGet := rc.GetResourceInstanceOptions{ + ID: &instanceID, + } + stateConf := &resource.StateChangeConf{ + Pending: []string{rsInstanceProgressStatus, rsInstanceInactiveStatus, rsInstanceSuccessStatus}, + Target: []string{rsInstanceRemovedStatus, rsInstanceReclamation}, + Refresh: func() (interface{}, string, error) { + instance, resp, err := rsConClient.GetResourceInstance(&resourceInstanceGet) + if err != nil { + if resp != nil && resp.StatusCode == 404 { + return instance, rsInstanceSuccessStatus, nil + } + return nil, "", fmt.Errorf("[ERROR] Get on HPCS instance %s failed with resp code: %s, err: %v", d.Id(), resp, err) + } + if *instance.State == rsInstanceFailStatus { + return instance, *instance.State, fmt.Errorf("[ERROR] HPCS instance %s failed to delete: %v", d.Id(), err) + } + return instance, *instance.State, nil + }, + Timeout: d.Timeout(schema.TimeoutDelete), + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + return stateConf.WaitForState() +} +func resourceIBMHPCSAdminHash(v interface{}) int { + var buf bytes.Buffer + a := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", a["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", a["key"].(string))) + buf.WriteString(fmt.Sprintf("%s-", a["token"].(string))) + + return hashcode.String(buf.String()) +} +func validateHSM(hsmInfo []tkesdk.HsmInfo) bool { + update := false + if len(hsmInfo) == 0 { + return true + } + for _, hsm := range hsmInfo { + if hsm.CurrentMKStatus != "Valid" { + update = true + } + } + return update +} +func hsmClient(d *schema.ResourceData, meta interface{}) (tkesdk.CommonInputs, error) { + ci := tkesdk.CommonInputs{} + // Bluemix Session to get Oauth tokens + bluemixSession, err := meta.(ClientSession).BluemixSession() + if err != nil { + return ci, err + } + err = refreshToken(bluemixSession) + if err != nil { + return ci, fmt.Errorf("[ERROR] Error Refreshing Authentication Token: %s", err) + } + ci.Region = d.Get("location").(string) + ci.ApiEndpoint = envFallBack([]string{"IBMCLOUD_HPCS_TKE_ENDPOINT"}, "cloud.ibm.com") + if bluemixSession.Config.Visibility == "private" || bluemixSession.Config.Visibility == "public-and-private" { + ci.ApiEndpoint = envFallBack([]string{"IBMCLOUD_HPCS_TKE_ENDPOINT"}, "private.cloud.ibm.com") + } + ci.AuthToken = bluemixSession.Config.IAMAccessToken + + return ci, err +} diff --git a/ibm/resource_ibm_hpcs_test.go b/ibm/resource_ibm_hpcs_test.go new file mode 100644 index 00000000000..0db2390ab60 --- /dev/null +++ b/ibm/resource_ibm_hpcs_test.go @@ -0,0 +1,202 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package ibm + +import ( + "fmt" + "log" + "regexp" + "strings" + "testing" + + rc "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccIBMHPCSInstanceBasic(t *testing.T) { + var hpcsInstance string + testName := fmt.Sprintf("tf-hpcs-%d", acctest.RandIntRange(10, 100)) + name := "ibm_hpcs.hpcs" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckHPCS(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIBMHPCSInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMHPCSInstanceBasic(testName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMHPCSInstanceExists(name, hpcsInstance), + resource.TestCheckResourceAttr(name, "name", testName), + resource.TestCheckResourceAttr(name, "plan", "standard"), + resource.TestCheckResourceAttr(name, "location", "us-south"), + resource.TestCheckResourceAttr(name, "admins.#", "1"), + ), + }, + { + Config: testAccCheckIBMHPCSInstanceAdminUpdate(testName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMHPCSInstanceExists(name, hpcsInstance), + resource.TestCheckResourceAttr(name, "name", testName), + resource.TestCheckResourceAttr(name, "plan", "standard"), + resource.TestCheckResourceAttr(name, "location", "us-south"), + resource.TestCheckResourceAttr(name, "admins.#", "2"), + ), + }, + { + Config: testAccCheckIBMHPCSInstanceAdminDelete(testName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMHPCSInstanceExists(name, hpcsInstance), + resource.TestCheckResourceAttr(name, "name", testName), + resource.TestCheckResourceAttr(name, "plan", "standard"), + resource.TestCheckResourceAttr(name, "location", "us-south"), + resource.TestCheckResourceAttr(name, "admins.#", "1"), + ), + }, + { + Config: testAccCheckIBMHPCSInstanceUnitsUpdate(testName), + ExpectError: regexp.MustCompile(`'units' attribute is immutable and can't be changed`), + }, + }, + }) +} + +func testAccCheckIBMHPCSInstanceDestroy(s *terraform.State) error { + rsConClient, err := testAccProvider.Meta().(ClientSession).ResourceControllerV2API() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_hpcs" { + continue + } + + instanceID := rs.Primary.ID + rsInst := rc.GetResourceInstanceOptions{ + ID: &instanceID, + } + instance, response, err := rsConClient.GetResourceInstance(&rsInst) + if err == nil { + if instance != nil && (strings.Contains(*instance.State, "removed") || strings.Contains(*instance.State, rsInstanceReclamation)) { + log.Printf("[WARN]Returning nil because it's in removed or pending_reclamation state") + return nil + } + return fmt.Errorf("Instance still exists: %s", rs.Primary.ID) + } else if strings.Contains(err.Error(), "404") { + return fmt.Errorf("Error checking if instance (%s) has been destroyed: %s %s", rs.Primary.ID, err, response) + } + } + return nil +} + +func testAccCheckIBMHPCSInstanceExists(n string, tfHPCSID string) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + rsConClient, err := testAccProvider.Meta().(ClientSession).ResourceControllerV2API() + if err != nil { + return err + } + instanceID := rs.Primary.ID + + rsInst := rc.GetResourceInstanceOptions{ + ID: &instanceID, + } + instance, response, err := rsConClient.GetResourceInstance(&rsInst) + if err != nil { + if response != nil && response.StatusCode == 404 { + tfHPCSID = "" + return nil + } + return fmt.Errorf("Error retrieving resource instance: %s %s", err, response) + } + if strings.Contains(*instance.State, "removed") { + tfHPCSID = "" + return nil + } + + tfHPCSID = instanceID + return nil + } +} + +func testAccCheckIBMHPCSInstanceBasic(name string) string { + return fmt.Sprintf(` + resource ibm_hpcs hpcs { + location = "us-south" + name = "%s" + plan = "standard" + units = 2 + signature_threshold = 1 + revocation_threshold = 1 + admins { + name = "ad1" + key = "%s" + token = "%s" + } + } + `, name, hpcsAdmin1, hpcsToken1) +} +func testAccCheckIBMHPCSInstanceAdminUpdate(name string) string { + return fmt.Sprintf(` + resource ibm_hpcs hpcs { + location = "us-south" + name = "%s" + plan = "standard" + units = 2 + signature_threshold = 1 + revocation_threshold = 1 + admins { + name = "ad1" + key = "%s" + token = "%s" + } + admins { + name = "ad2" + key = "%s" + token = "%s" + } + } + `, name, hpcsAdmin1, hpcsToken1, hpcsAdmin2, hpcsToken2) +} +func testAccCheckIBMHPCSInstanceAdminDelete(name string) string { + return fmt.Sprintf(` + resource ibm_hpcs hpcs { + location = "us-south" + name = "%s" + plan = "standard" + units = 2 + signature_threshold = 1 + revocation_threshold = 1 + admins { + name = "ad1" + key = "%s" + token = "%s" + } + } + `, name, hpcsAdmin1, hpcsToken1) +} +func testAccCheckIBMHPCSInstanceUnitsUpdate(name string) string { + return fmt.Sprintf(` + resource ibm_hpcs hpcs { + location = "us-south" + name = "%s" + plan = "standard" + units = 3 + signature_threshold = 1 + revocation_threshold = 1 + admins { + name = "ad1" + key = "%s" + token = "%s" + } + } + `, name, hpcsAdmin1, hpcsToken1) +} diff --git a/ibm/structures.go b/ibm/structures.go index 05bf1a65365..5e80c2ad00a 100644 --- a/ibm/structures.go +++ b/ibm/structures.go @@ -2509,13 +2509,16 @@ func getIBMUniqueId(accountID, userEmail string, meta interface{}) (string, erro func immutableResourceCustomizeDiff(resourceList []string, diff *schema.ResourceDiff) error { for _, rName := range resourceList { - if diff.Id() != "" && diff.HasChange(rName) { + if diff.Id() != "" && diff.HasChange(rName) && rName != sateLocZone { + return fmt.Errorf("'%s' attribute is immutable and can't be changed", rName) + } + if diff.Id() != "" && diff.HasChange(rName) && rName == sateLocZone { o, n := diff.GetChange(rName) old := o.(string) new := n.(string) if len(old) > 0 && old != new { if !(rName == sateLocZone && strings.Contains(old, new)) { - return fmt.Errorf("'%s' attribute is immutable and can't be changed from %s to %s.", rName, old, new) + return fmt.Errorf("'%s' attribute is immutable and can't be changed from %s to %s", rName, old, new) } } } diff --git a/website/allowed-subcategories.txt b/website/allowed-subcategories.txt index ed4a89bc7b6..8d98dc60a21 100644 --- a/website/allowed-subcategories.txt +++ b/website/allowed-subcategories.txt @@ -12,6 +12,7 @@ Enterprise Management Event Streams Functions Global Tagging +Hyper Protect Crypto Service (HPCS) Identity & Access Management (IAM) Internet services Key Management Service diff --git a/website/docs/d/hpcs.html.markdown b/website/docs/d/hpcs.html.markdown new file mode 100644 index 00000000000..67ef03e05e4 --- /dev/null +++ b/website/docs/d/hpcs.html.markdown @@ -0,0 +1,56 @@ +--- +subcategory: "Hyper Protect Crypto Service (HPCS)" +layout: "ibm" +page_title: "IBM : Hyper Protect Crypto Service instance" +description: |- + Get information on an IBM Cloud Hyper Protect Crypto Service Instance. +--- + +# ibm\_hpcs + +Imports a read only copy of an existing HPCS resource. + +## Example Usage + +```terraform +data "ibm_hpcs" "hpcs_instance" { + name = "test" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required, string) The name used to identify the HPCS instance in the IBM Cloud UI. +* `resource_group_id` -(Optional, string) The Id of Resource Group. +* `location` - (Optional, String) The location for this HPCS instance + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `crn` - (String) CRN of HPCS Instance +* `extensions` - (List) The extended metadata as a map associated with the resource instance. +* `guid` - (String) Unique identifier of resource instance. +* `hsm_info` - (List) HSM config of HPCS Instance Crypto Units. + Nested scheme for `hsm_info`: + * `admins` - (List) List of Admins for Crypto Units + Nested scheme for `admins`: + * `name` - (String) Name of Admin + * `ski` - (String) Subject Key Identifier of the administrator signature key + * `current_mk_status` - (String) Status of Current Master Key Register + * `current_mkvp` - (String) Current Master Key Register Verification Pattern. + * `hsm_id` - (String) HSM ID + * `hsm_location` - (String) HSM Location + * `hsm_type` - (String) HSM Type. + * `new_mk_status` - (String) Status of New Master Key Register + * `new_mkvp` - (String) New Master Key Register Verification Pattern + * `revocation_threshold` - (Int) Revocation Threshold for Crypto Units + * `signature_threshold`- (Int) Signature Threshold for Crypto Units +* `failover_units` - (String) The number of failover crypto units for your service instance +* `id` - (String) The unique identifier CRN of this HPCS instance. +* `plan` - (String) The pricing plan for your service instance. +* `service` - (String) The service type (`hs-crypto`) of the instance. +* `status` - (String) Status of the hpcs instance. +* `units` -(String) The number of operational crypto units for your service instance. \ No newline at end of file diff --git a/website/docs/r/hpcs.html.markdown b/website/docs/r/hpcs.html.markdown new file mode 100644 index 00000000000..ea536a56553 --- /dev/null +++ b/website/docs/r/hpcs.html.markdown @@ -0,0 +1,112 @@ +--- +subcategory: "Hyper Protect Crypto Service (HPCS)" +layout: "ibm" +page_title: "IBM : Hyper Protect Crypto Service instance" +description: |- + Manages IBM Cloud Hyper Protect Crypto Service Instance. +--- + +# ibm\_hpcs + +Manages HPCS resource. This allows hpcs sub-resources to be added to an existing hpcs instance. + +~> **Note:** As recovery crypto units are available only in us-south and us-east, only these two regions are supported if you want to use this resource for instance initialization. + +## Example Usage + +```terraform +resource ibm_hpcs hpcs { + location = "us-south" + name = "test-hpcs" + plan = "standard" + units = 2 + signature_threshold = 1 + revocation_threshold = 1 + admins { + name = "admin1" + key = "/cloudTKE/1.sigkey" + token = "" + } + admins { + name = "admin2" + key = "/cloudTKE/2.sigkey" + token = "" + } +} +``` + +## Argument Reference + +The following arguments are supported: +* `admins` - (Required, List) The list of administrators for the instance crypto units. You can set up to 8 administrators and the number needs to be equal to or greater than the thresholds that you specify. The following values need to be set for each administrator: + Nested scheme for `admins`: + * `key` - (Required, string) The path in your local workstation where you store the administrator signature file. + * `name` - (Required, string) The name of the administrator. name is limited to 30 characters. + * `token` - (Required, string, Sensitive) The administrator password to access the corresponding signature file. + +~> **Note:** When a `signature_server_url` (signing service) is used, the `key` parameter of `admins` identifies the signature key to be used. How the key parameter is defined depends on the signing service. The character string for the key parameter is appended to a URI and must contain only unreserved characters as defined by section 2.3 of RFC 3986. The `token` parameter of `admins` authorizes use of the signature key. How the token parameter is defined depends on the signing service. +* `failover_units` - (Optional, string) The number of failover crypto units for your service instance. Valid values are 2 or 3 but it must be less than or equal to the number of operational crypto units. +* `location` - (Required, string) The region abbreviation, such as us-south, that represents the geographic area where the operational crypto units of your service instance are located. For more information, see Regions and locations. As recovery crypto units are available only in us-south and us-east, only these two regions are supported if you want to use Terraform for instance initialization. +* `name` - (Required, string) The name of your Hyper Protect Crypto Service instance. +* `plan` - (Required, string) The pricing plan for your service instance. Currently, only the standard plan is supportd. +* `resource_group_id` - (Optional, string) The Id of resource group where you want to organize and manage your service instance. +* `revocation_threshold` - (Required, int) The number of administrator signatures that is required to remove an administrator after you leave imprint mode. The valid value is between 1 and 8. +* `service_endpoints` - (Optional, string) Types of the service endpoints that can be set to a resource instance. Possible values are 'public', 'private', 'public-and-private'. +* `signature_server_url` - (Optional, string) The URL of the signing service. If you use a third-party signing service to provide administrator signature keys, you need to specify the URL. +* `signature_threshold`- (Required, int) The number of administrator signatures that is required to execute administrative commands. The valid value is between 1 and 8. You need to set it to at least 2 to enable quorum authentication. +* `tags` - (Optional, array of strings) Tags that are associated with your instance are used to organize your resources. +* `units` -(Required, string) The number of operational crypto units for your service instance. Valid values are 2 and 3. +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `created_at` - (String) The date when the instance was created. +* `created_by` - (String) The subject who created the instance. +* `crn` - (String) CRN of HPCS Instance. +* `deleted_at` - (String) The date when the instance was deleted. +* `deleted_by` - (String) The subject who deleted the instance. +* `extensions` - (List) The extended metadata as a map associated with the resource instance. +* `guid` - (String) Unique identifier of resource instance. +* `hsm_info` - (List) HSM config of HPCS Instance Crypto Units. + Nested scheme for `hsm_info`: + * `admins` - (List) List of Admins for Crypto Units + Nested scheme for `admins`: + * `name` - (String) Name of Admin. + * `ski` - (String) Subject Key Identifier of the administrator signature key. + * `current_mk_status` - (String) Status of Current Master Key Register. + * `current_mkvp` - (String) Current Master Key Register Verification Pattern. + * `hsm_id` - (String) HSM ID. + * `hsm_location` - (String) HSM Location. + * `hsm_type` - (String) HSM Type. + * `new_mk_status` - (String) Status of New Master Key Register. + * `new_mkvp` - (String) New Master Key Register Verification Pattern. + * `revocation_threshold` - (Int) Revocation Threshold for Crypto Units. + * `signature_threshold`- (Int) Signature Threshold for Crypto Units. +* `id` - (String) The unique identifier CRN of this HPCS instance. +* `location` - (String) The location for this HPCS instance. +* `plan` - (String) The pricing plan for your service instance. +* `resource_aliases_url` - (String) The relative path to the resource aliases for the instance. +* `resource_bindings_url` - (String) The relative path to the resource bindings for the instance. +* `resource_keys_url` - (String) The relative path to the resource keys for the instance. +* `restored_at` - (String) The date when the instance under reclamation was restored. +* `restored_by` - (String) The subject who restored the instance back from reclamation. +* `scheduled_reclaim_at` - (String) The date when the instance was scheduled for reclamation. +* `scheduled_reclaim_by` - (String) The subject who initiated the instance reclamation. +* `service` - (String) The service type (`hs-crypto`) of the instance. +* `state` - (String) The current state of the instance. For example, if the instance is deleted, it will return removed. +* `status` - (String) Status of the hpcs instance. +* `update_at` - (String) The date when the instance was last updated. +* `update_by` - (String) The subject who updated the instance. + +## Import +The `ibm_hpcs` can be imported by using the `crn`. + +```bash +terraform import ibm_hpcs.hpcs +``` + +**Example** + +``` +$ terraform import ibm_hpcs.hpcs crn:v1:bluemix:public:hs-crypto:us-south:a/4448261269a14562b839e0a3019ed980:f115115b-5087-4a4e-9cc8-71acf0542c0d:: +```