diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d09de8994..33a09bc22a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,10 +39,10 @@ jobs: passphrase: ${{ secrets.PASSPHRASE }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v5 + uses: goreleaser/goreleaser-action@v6 with: - version: latest - args: release --rm-dist + version: v1.26.2 + args: release --clean env: GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} # GitHub sets this automatically diff --git a/.gitignore b/.gitignore index 1ee2755aec..0856a3fcc7 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ vendor/ !command/test-fixtures/**/*.tfstate !command/test-fixtures/**/.terraform/ +!jenkins/workflow.xml *.sh !createaddon.sh diff --git a/.secrets.baseline b/.secrets.baseline index 5854738e07..02cf8638a7 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,8 +3,11 @@ "files": "go.mod|go.sum|.*.map|^.secrets.baseline$", "lines": null }, - "generated_at": "2024-07-02T05:46:14Z", + "generated_at": "2024-08-27T13:07:20Z", "plugins_used": [ + { + "name": "AWSKeyDetector" + }, { "name": "ArtifactoryDetector" }, @@ -18,6 +21,12 @@ { "name": "BasicAuthDetector" }, + { + "name": "BoxDetector" + }, + { + "name": "CloudantDetector" + }, { "ghe_instance": "github.ibm.com", "name": "GheDetector" @@ -42,6 +51,9 @@ "keyword_exclude": null, "name": "KeywordDetector" }, + { + "name": "MailchimpDetector" + }, { "name": "NpmDetector" }, @@ -56,6 +68,12 @@ }, { "name": "SquareOAuthDetector" + }, + { + "name": "StripeDetector" + }, + { + "name": "TwilioKeyDetector" } ], "results": { @@ -758,7 +776,7 @@ "hashed_secret": "731438016c5ab94431f61820f35e3ae5f8ad6004", "is_secret": false, "is_verified": false, - "line_number": 478, + "line_number": 485, "type": "Secret Keyword", "verified_result": null }, @@ -766,7 +784,7 @@ "hashed_secret": "12da2e35d6b50c902c014f1ab9e3032650368df7", "is_secret": false, "is_verified": false, - "line_number": 484, + "line_number": 491, "type": "Secret Keyword", "verified_result": null }, @@ -774,7 +792,7 @@ "hashed_secret": "813274ccae5b6b509379ab56982d862f7b5969b6", "is_secret": false, "is_verified": false, - "line_number": 1262, + "line_number": 1275, "type": "Base64 High Entropy String", "verified_result": null } @@ -784,7 +802,7 @@ "hashed_secret": "9184b0c38101bf24d78b2bb0d044deb1d33696fc", "is_secret": false, "is_verified": false, - "line_number": 134, + "line_number": 136, "type": "Secret Keyword", "verified_result": null }, @@ -792,7 +810,7 @@ "hashed_secret": "c427f185ddcb2440be9b77c8e45f1cd487a2e790", "is_secret": false, "is_verified": false, - "line_number": 1471, + "line_number": 1484, "type": "Base64 High Entropy String", "verified_result": null }, @@ -800,7 +818,7 @@ "hashed_secret": "1f7e33de15e22de9d2eaf502df284ed25ca40018", "is_secret": false, "is_verified": false, - "line_number": 1538, + "line_number": 1551, "type": "Secret Keyword", "verified_result": null }, @@ -808,7 +826,7 @@ "hashed_secret": "1f614c2eb6b3da22d89bd1b9fd47d7cb7c8fc670", "is_secret": false, "is_verified": false, - "line_number": 3412, + "line_number": 3458, "type": "Secret Keyword", "verified_result": null }, @@ -816,7 +834,7 @@ "hashed_secret": "7abfce65b8504403afc25c9790f358d513dfbcc6", "is_secret": false, "is_verified": false, - "line_number": 3425, + "line_number": 3471, "type": "Secret Keyword", "verified_result": null }, @@ -824,7 +842,7 @@ "hashed_secret": "0c2d85bf9a9b1579b16f220a4ea8c3d62b2e24b1", "is_secret": false, "is_verified": false, - "line_number": 3466, + "line_number": 3512, "type": "Secret Keyword", "verified_result": null } @@ -862,7 +880,7 @@ "hashed_secret": "c8b6f5ef11b9223ac35a5663975a466ebe7ebba9", "is_secret": false, "is_verified": false, - "line_number": 2143, + "line_number": 2171, "type": "Secret Keyword", "verified_result": null }, @@ -870,7 +888,7 @@ "hashed_secret": "8abf4899c01104241510ba87685ad4de76b0c437", "is_secret": false, "is_verified": false, - "line_number": 2149, + "line_number": 2177, "type": "Secret Keyword", "verified_result": null } @@ -1132,7 +1150,7 @@ "hashed_secret": "92f08f2d9a0dc3f0d4cb3796435a48508cf59ecd", "is_secret": false, "is_verified": false, - "line_number": 722, + "line_number": 791, "type": "Secret Keyword", "verified_result": null } @@ -1152,7 +1170,7 @@ "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", "is_secret": false, "is_verified": false, - "line_number": 410, + "line_number": 415, "type": "Secret Keyword", "verified_result": null } @@ -1162,7 +1180,7 @@ "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", "is_secret": false, "is_verified": false, - "line_number": 228, + "line_number": 233, "type": "Secret Keyword", "verified_result": null }, @@ -1170,7 +1188,7 @@ "hashed_secret": "17f5f58d3d8d9871c52ab032989df3d810d2443e", "is_secret": false, "is_verified": false, - "line_number": 383, + "line_number": 392, "type": "Secret Keyword", "verified_result": null } @@ -1180,7 +1198,7 @@ "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", "is_secret": false, "is_verified": false, - "line_number": 470, + "line_number": 465, "type": "Secret Keyword", "verified_result": null } @@ -1190,7 +1208,7 @@ "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", "is_secret": false, "is_verified": false, - "line_number": 189, + "line_number": 88, "type": "Secret Keyword", "verified_result": null }, @@ -1198,7 +1216,7 @@ "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 528, + "line_number": 483, "type": "Secret Keyword", "verified_result": null } @@ -1724,37 +1742,21 @@ } ], "ibm/service/codeengine/data_source_ibm_code_engine_app.go": [ - { - "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", - "is_secret": false, - "is_verified": false, - "line_number": 74, - "type": "Secret Keyword", - "verified_result": null - }, { "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 313, + "line_number": 442, "type": "Secret Keyword", "verified_result": null } ], "ibm/service/codeengine/data_source_ibm_code_engine_build.go": [ - { - "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", - "is_secret": false, - "is_verified": false, - "line_number": 79, - "type": "Secret Keyword", - "verified_result": null - }, { "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 193, + "line_number": 215, "type": "Secret Keyword", "verified_result": null } @@ -1778,19 +1780,11 @@ } ], "ibm/service/codeengine/data_source_ibm_code_engine_job.go": [ - { - "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", - "is_secret": false, - "is_verified": false, - "line_number": 59, - "type": "Secret Keyword", - "verified_result": null - }, { "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 242, + "line_number": 275, "type": "Secret Keyword", "verified_result": null } @@ -1800,25 +1794,17 @@ "hashed_secret": "b10b32fc1b6d1a4a455c44de75d5a8ab9386068d", "is_secret": false, "is_verified": false, - "line_number": 75, + "line_number": 76, "type": "Secret Keyword", "verified_result": null } ], "ibm/service/codeengine/resource_ibm_code_engine_app.go": [ - { - "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", - "is_secret": false, - "is_verified": false, - "line_number": 63, - "type": "Secret Keyword", - "verified_result": null - }, { "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 582, + "line_number": 727, "type": "Secret Keyword", "verified_result": null }, @@ -1826,25 +1812,17 @@ "hashed_secret": "3c956707ac29b4a200e47fceffa923341eed7e4f", "is_secret": false, "is_verified": false, - "line_number": 767, + "line_number": 962, "type": "Secret Keyword", "verified_result": null } ], "ibm/service/codeengine/resource_ibm_code_engine_build.go": [ - { - "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", - "is_secret": false, - "is_verified": false, - "line_number": 74, - "type": "Secret Keyword", - "verified_result": null - }, { "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 391, + "line_number": 400, "type": "Secret Keyword", "verified_result": null }, @@ -1852,7 +1830,7 @@ "hashed_secret": "e8dc1fe90828a509bfa71eeccb5234a9bedb10e2", "is_secret": false, "is_verified": false, - "line_number": 494, + "line_number": 516, "type": "Secret Keyword", "verified_result": null }, @@ -1860,7 +1838,7 @@ "hashed_secret": "d4ee3538b3b38ad8931e35bbe9db217fbd6687c1", "is_secret": false, "is_verified": false, - "line_number": 511, + "line_number": 531, "type": "Secret Keyword", "verified_result": null } @@ -1885,26 +1863,36 @@ ], "ibm/service/codeengine/resource_ibm_code_engine_job.go": [ { - "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", + "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 50, + "line_number": 478, "type": "Secret Keyword", "verified_result": null }, { - "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", + "hashed_secret": "3c956707ac29b4a200e47fceffa923341eed7e4f", "is_secret": false, "is_verified": false, - "line_number": 463, + "line_number": 646, + "type": "Secret Keyword", + "verified_result": null + } + ], + "ibm/service/codeengine/resource_ibm_code_engine_project_test.go": [ + { + "hashed_secret": "f75b33f87ffeacb3a4f793a09693e672e07449ff", + "is_secret": false, + "is_verified": false, + "line_number": 125, "type": "Secret Keyword", "verified_result": null }, { - "hashed_secret": "3c956707ac29b4a200e47fceffa923341eed7e4f", + "hashed_secret": "1f7e33de15e22de9d2eaf502df284ed25ca40018", "is_secret": false, "is_verified": false, - "line_number": 604, + "line_number": 127, "type": "Secret Keyword", "verified_result": null } @@ -1914,7 +1902,7 @@ "hashed_secret": "05f899c96f7e8d7874797a5fa19902a12bd47b79", "is_secret": false, "is_verified": false, - "line_number": 80, + "line_number": 81, "type": "Secret Keyword", "verified_result": null }, @@ -1922,7 +1910,7 @@ "hashed_secret": "b10b32fc1b6d1a4a455c44de75d5a8ab9386068d", "is_secret": false, "is_verified": false, - "line_number": 128, + "line_number": 129, "type": "Secret Keyword", "verified_result": null }, @@ -1930,7 +1918,7 @@ "hashed_secret": "a2ff1f57ccf7131152dd24b9360d2c02b87e2166", "is_secret": false, "is_verified": false, - "line_number": 135, + "line_number": 136, "type": "Secret Keyword", "verified_result": null } @@ -1958,7 +1946,7 @@ "hashed_secret": "884a58e4c2c5d195d3876787bdc63af6c5af2924", "is_secret": false, "is_verified": false, - "line_number": 638, + "line_number": 647, "type": "Secret Keyword", "verified_result": null } @@ -1968,7 +1956,7 @@ "hashed_secret": "884a58e4c2c5d195d3876787bdc63af6c5af2924", "is_secret": false, "is_verified": false, - "line_number": 1661, + "line_number": 1692, "type": "Secret Keyword", "verified_result": null } @@ -1978,7 +1966,7 @@ "hashed_secret": "b02fa7fd7ca08b5dc86c2548e40f8a21171ef977", "is_secret": false, "is_verified": false, - "line_number": 509, + "line_number": 514, "type": "Secret Keyword", "verified_result": null } @@ -1988,7 +1976,7 @@ "hashed_secret": "988ff3bd9a74260f3e32e115fdd6535aaa5c531a", "is_secret": false, "is_verified": false, - "line_number": 2221, + "line_number": 2257, "type": "Secret Keyword", "verified_result": null } @@ -1998,7 +1986,7 @@ "hashed_secret": "b02fa7fd7ca08b5dc86c2548e40f8a21171ef977", "is_secret": false, "is_verified": false, - "line_number": 367, + "line_number": 373, "type": "Secret Keyword", "verified_result": null } @@ -2016,7 +2004,7 @@ "hashed_secret": "2c7d1e61c036dc18b2e9b3e6392c8e59c8437f23", "is_secret": false, "is_verified": false, - "line_number": 1965, + "line_number": 1957, "type": "Secret Keyword", "verified_result": null } @@ -2026,7 +2014,7 @@ "hashed_secret": "deab23f996709b4e3d14e5499d1cc2de677bfaa8", "is_secret": false, "is_verified": false, - "line_number": 1452, + "line_number": 1365, "type": "Secret Keyword", "verified_result": null }, @@ -2034,7 +2022,7 @@ "hashed_secret": "20a25bac21219ffff1904bde871ded4027eca2f8", "is_secret": false, "is_verified": false, - "line_number": 2055, + "line_number": 1954, "type": "Secret Keyword", "verified_result": null }, @@ -2042,25 +2030,7 @@ "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 2074, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "1f5e25be9b575e9f5d39c82dfd1d9f4d73f1975c", - "is_secret": false, - "is_verified": false, - "line_number": 2287, - "type": "Secret Keyword", - "verified_result": null - } - ], - "ibm/service/database/resource_ibm_database_cassandra_test.go": [ - { - "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", - "is_secret": false, - "is_verified": false, - "line_number": 731, + "line_number": 1973, "type": "Secret Keyword", "verified_result": null } @@ -2070,7 +2040,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 202, + "line_number": 189, "type": "Secret Keyword", "verified_result": null } @@ -2080,7 +2050,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 784, + "line_number": 760, "type": "Secret Keyword", "verified_result": null } @@ -2090,7 +2060,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 832, + "line_number": 808, "type": "Secret Keyword", "verified_result": null } @@ -2100,7 +2070,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 216, + "line_number": 207, "type": "Secret Keyword", "verified_result": null } @@ -2110,7 +2080,7 @@ "hashed_secret": "8cbbbfad0206e5953901f679b0d26d583c4f5ffe", "is_secret": false, "is_verified": false, - "line_number": 269, + "line_number": 252, "type": "Secret Keyword", "verified_result": null }, @@ -2118,7 +2088,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 334, + "line_number": 317, "type": "Secret Keyword", "verified_result": null } @@ -2128,7 +2098,7 @@ "hashed_secret": "5667b8489a17faa9ef54941db31ed762be280bec", "is_secret": false, "is_verified": false, - "line_number": 154, + "line_number": 145, "type": "Secret Keyword", "verified_result": null }, @@ -2136,7 +2106,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 186, + "line_number": 177, "type": "Secret Keyword", "verified_result": null } @@ -2146,7 +2116,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 220, + "line_number": 211, "type": "Secret Keyword", "verified_result": null } @@ -2156,7 +2126,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 156, + "line_number": 144, "type": "Secret Keyword", "verified_result": null } @@ -2166,7 +2136,7 @@ "hashed_secret": "728e83f156932be9b1dc48a5c3f7a3bfbeeb08ce", "is_secret": false, "is_verified": false, - "line_number": 497, + "line_number": 472, "type": "Secret Keyword", "verified_result": null }, @@ -2174,7 +2144,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 674, + "line_number": 649, "type": "Secret Keyword", "verified_result": null } @@ -2184,7 +2154,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 229, + "line_number": 222, "type": "Secret Keyword", "verified_result": null } @@ -2194,7 +2164,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 282, + "line_number": 277, "type": "Secret Keyword", "verified_result": null }, @@ -2202,7 +2172,7 @@ "hashed_secret": "44cdfc3615970ada14420caaaa5c5745fca06002", "is_secret": false, "is_verified": false, - "line_number": 300, + "line_number": 295, "type": "Secret Keyword", "verified_result": null } @@ -2316,7 +2286,7 @@ "hashed_secret": "f591b975c1668d110a6af6556a8e0067fd37d210", "is_secret": false, "is_verified": false, - "line_number": 194, + "line_number": 195, "type": "Secret Keyword", "verified_result": null } @@ -2893,6 +2863,44 @@ "verified_result": null } ], + "ibm/service/logsrouting/data_source_ibm_logs-router_targets_test.go": [ + { + "hashed_secret": "1018de48014135565e13b4b33d5d34cde9d5c23b", + "is_secret": false, + "is_verified": false, + "line_number": 186, + "type": "Hex High Entropy String", + "verified_result": null + } + ], + "ibm/service/logsrouting/data_source_ibm_logs-router_tenants_test.go": [ + { + "hashed_secret": "18697a00f52cfe022bb910a8a7af9d509114f997", + "is_secret": false, + "is_verified": false, + "line_number": 112, + "type": "Hex High Entropy String", + "verified_result": null + }, + { + "hashed_secret": "1018de48014135565e13b4b33d5d34cde9d5c23b", + "is_secret": false, + "is_verified": false, + "line_number": 241, + "type": "Hex High Entropy String", + "verified_result": null + } + ], + "ibm/service/logsrouting/resource_ibm_logs-router_tenant_test.go": [ + { + "hashed_secret": "1018de48014135565e13b4b33d5d34cde9d5c23b", + "is_secret": false, + "is_verified": false, + "line_number": 314, + "type": "Hex High Entropy String", + "verified_result": null + } + ], "ibm/service/project/data_source_ibm_project_config.go": [ { "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", @@ -3020,7 +3028,7 @@ "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 168, + "line_number": 177, "type": "Secret Keyword", "verified_result": null } @@ -3030,7 +3038,7 @@ "hashed_secret": "b732fb611fd46a38e8667f9972e0cde777fbe37f", "is_secret": false, "is_verified": false, - "line_number": 315, + "line_number": 320, "type": "Secret Keyword", "verified_result": null } @@ -3136,7 +3144,7 @@ "hashed_secret": "347cd9c53ff77d41a7b22aa56c7b4efaf54658e3", "is_secret": false, "is_verified": false, - "line_number": 72, + "line_number": 88, "type": "Secret Keyword", "verified_result": null } @@ -3266,7 +3274,7 @@ "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", "is_secret": false, "is_verified": false, - "line_number": 212, + "line_number": 265, "type": "Secret Keyword", "verified_result": null }, @@ -3274,7 +3282,7 @@ "hashed_secret": "3ad6a2f4e68613da801ef1ddc1baf6d5b25607b2", "is_secret": false, "is_verified": false, - "line_number": 419, + "line_number": 484, "type": "Secret Keyword", "verified_result": null } @@ -3284,7 +3292,7 @@ "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", "is_secret": false, "is_verified": false, - "line_number": 236, + "line_number": 289, "type": "Secret Keyword", "verified_result": null }, @@ -3292,7 +3300,7 @@ "hashed_secret": "9beb31de125498074813c6f31c0e4df3e54a5489", "is_secret": false, "is_verified": false, - "line_number": 470, + "line_number": 535, "type": "Secret Keyword", "verified_result": null } @@ -3604,7 +3612,7 @@ "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", "is_secret": false, "is_verified": false, - "line_number": 250, + "line_number": 322, "type": "Secret Keyword", "verified_result": null }, @@ -3612,7 +3620,7 @@ "hashed_secret": "9beb31de125498074813c6f31c0e4df3e54a5489", "is_secret": false, "is_verified": false, - "line_number": 750, + "line_number": 923, "type": "Secret Keyword", "verified_result": null } @@ -3622,7 +3630,7 @@ "hashed_secret": "3046d9f6cfaaeea6eed9bb7a4ab010fe49b0cfd4", "is_secret": false, "is_verified": false, - "line_number": 279, + "line_number": 351, "type": "Secret Keyword", "verified_result": null }, @@ -3630,7 +3638,7 @@ "hashed_secret": "9beb31de125498074813c6f31c0e4df3e54a5489", "is_secret": false, "is_verified": false, - "line_number": 756, + "line_number": 847, "type": "Secret Keyword", "verified_result": null } @@ -3817,6 +3825,26 @@ "verified_result": null } ], + "ibm/service/vpc/data_source_ibm_is_share_accessor_binding_test.go": [ + { + "hashed_secret": "cb76de39e0f3b6d952156908871c4b9c3daeae0e", + "is_secret": false, + "is_verified": false, + "line_number": 240, + "type": "Hex High Entropy String", + "verified_result": null + } + ], + "ibm/service/vpc/data_source_ibm_is_share_accessor_bindings_test.go": [ + { + "hashed_secret": "cb76de39e0f3b6d952156908871c4b9c3daeae0e", + "is_secret": false, + "is_verified": false, + "line_number": 308, + "type": "Hex High Entropy String", + "verified_result": null + } + ], "ibm/service/vpc/resource_ibm_is_vpn_server.go": [ { "hashed_secret": "4d55af37dbbb6a42088d917caa1ca25428ec42c9", @@ -3860,7 +3888,7 @@ "hashed_secret": "5fb0fa884132a8724a8d7cba55853737e442adbd", "is_secret": false, "is_verified": false, - "line_number": 119093, + "line_number": 119081, "type": "Secret Keyword", "verified_result": null }, @@ -3868,7 +3896,7 @@ "hashed_secret": "1e5c2f367f02e47a8c160cda1cd9d91decbac441", "is_secret": false, "is_verified": false, - "line_number": 151301, + "line_number": 151289, "type": "Secret Keyword", "verified_result": null } @@ -4089,84 +4117,12 @@ "verified_result": null } ], - "website/docs/r/cd_tekton_pipeline.html.markdown": [ + "website/docs/r/cbr_zone_addresses.html.markdown": [ { "hashed_secret": "d47dcacc720a39e236679ac3e311a0d58bb6519e", "is_secret": false, "is_verified": false, - "line_number": 228, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "e66e7d67fdf3c596c435fc7828b13205e4950a0f", - "is_secret": false, - "is_verified": false, - "line_number": 230, - "type": "Secret Keyword", - "verified_result": null - } - ], - "website/docs/r/cd_tekton_pipeline_definition.html.markdown": [ - { - "hashed_secret": "d47dcacc720a39e236679ac3e311a0d58bb6519e", - "is_secret": false, - "is_verified": false, - "line_number": 100, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "e66e7d67fdf3c596c435fc7828b13205e4950a0f", - "is_secret": false, - "is_verified": false, - "line_number": 102, - "type": "Secret Keyword", - "verified_result": null - } - ], - "website/docs/r/cd_tekton_pipeline_property.html.markdown": [ - { - "hashed_secret": "d47dcacc720a39e236679ac3e311a0d58bb6519e", - "is_secret": false, - "is_verified": false, - "line_number": 82, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "e66e7d67fdf3c596c435fc7828b13205e4950a0f", - "is_secret": false, - "is_verified": false, - "line_number": 84, - "type": "Secret Keyword", - "verified_result": null - } - ], - "website/docs/r/cd_tekton_pipeline_trigger.html.markdown": [ - { - "hashed_secret": "d47dcacc720a39e236679ac3e311a0d58bb6519e", - "is_secret": false, - "is_verified": false, - "line_number": 153, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "e66e7d67fdf3c596c435fc7828b13205e4950a0f", - "is_secret": false, - "is_verified": false, - "line_number": 155, - "type": "Secret Keyword", - "verified_result": null - } - ], - "website/docs/r/cd_tekton_pipeline_trigger_property.html.markdown": [ - { - "hashed_secret": "d47dcacc720a39e236679ac3e311a0d58bb6519e", - "is_secret": false, - "is_verified": false, - "line_number": 85, + "line_number": 94, "type": "Secret Keyword", "verified_result": null }, @@ -4174,7 +4130,7 @@ "hashed_secret": "e66e7d67fdf3c596c435fc7828b13205e4950a0f", "is_secret": false, "is_verified": false, - "line_number": 87, + "line_number": 96, "type": "Secret Keyword", "verified_result": null } @@ -4242,7 +4198,7 @@ "hashed_secret": "da7a68734367828e30b94927f4c2b43ed2c0f652", "is_secret": false, "is_verified": false, - "line_number": 106, + "line_number": 113, "type": "Secret Keyword", "verified_result": null } @@ -4386,7 +4342,7 @@ "hashed_secret": "2317aa72dafa0a07f05af47baa2e388f95dcf6f3", "is_secret": false, "is_verified": false, - "line_number": 541, + "line_number": 492, "type": "Secret Keyword", "verified_result": null }, @@ -4394,7 +4350,7 @@ "hashed_secret": "ddf75a48487b387b1dc328ac0a942377b377c556", "is_secret": false, "is_verified": false, - "line_number": 606, + "line_number": 557, "type": "Secret Keyword", "verified_result": null }, @@ -4402,7 +4358,7 @@ "hashed_secret": "91199272d5d6a574a51722ca6f3d1148edb1a0e7", "is_secret": false, "is_verified": false, - "line_number": 630, + "line_number": 581, "type": "Secret Keyword", "verified_result": null } @@ -4806,7 +4762,7 @@ "hashed_secret": "d47dcacc720a39e236679ac3e311a0d58bb6519e", "is_secret": false, "is_verified": false, - "line_number": 145, + "line_number": 163, "type": "Secret Keyword", "verified_result": null }, @@ -4814,7 +4770,7 @@ "hashed_secret": "e66e7d67fdf3c596c435fc7828b13205e4950a0f", "is_secret": false, "is_verified": false, - "line_number": 147, + "line_number": 165, "type": "Secret Keyword", "verified_result": null } @@ -4824,7 +4780,7 @@ "hashed_secret": "d47dcacc720a39e236679ac3e311a0d58bb6519e", "is_secret": false, "is_verified": false, - "line_number": 144, + "line_number": 161, "type": "Secret Keyword", "verified_result": null }, @@ -4832,7 +4788,7 @@ "hashed_secret": "e66e7d67fdf3c596c435fc7828b13205e4950a0f", "is_secret": false, "is_verified": false, - "line_number": 146, + "line_number": 163, "type": "Secret Keyword", "verified_result": null } @@ -5032,7 +4988,7 @@ } ] }, - "version": "0.13.1+ibm.62.dss", + "version": "0.13.1+ibm.61.dss", "word_list": { "file": null, "hash": null diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fc03730ff..724eb90965 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,209 @@ +# 1.69.0(Sep 04, 2024) +Features +* Support Cloud Logs Routing + - **Datasources** + - ibm_logs_router_tenant + - **Resources** + - ibm_logs_router_tenants + - ibm_logs_router_targets +* Support EN + - **Datasources** + - ibm_en_metrics + - ibm_en_smtp_allowed_ips + +* Support Partner Center Sell + - **Resources** + - ibm_onboarding_registration + - ibm_onboarding_product + - ibm_onboarding_iam_registration + - ibm_onboarding_catalog_product + - ibm_onboarding_catalog_plan + - ibm_onboarding_catalog_deployment + - ibm_onboarding_resource_broker + +Enhancements +* Deprecate `force_delete` attribute of ibm_kms_rings ([5539](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5539)) +* feat(tekton): Add support for CEL filtering ([5531](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5531)) +* PKI HSM Addition ([5531](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5531)) +* updated error messages for catalog service ([5553](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5553)) +* feat(CIS): Origin Post Quantum Encryption and Max HTTP Version ([5504](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5504)) +* refactor of instance network attachment reference to use vni ([5563](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5563)) +* Update storage types docs ([5569](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5569)) +* Force delete subresources during kmip_adapter destroy, avoid casting panics ([5565](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5565)) +* Add support for retry of deletion of resource group ([5537](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5537)) +* Remove beta for logs service docs ([5581](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5581)) +* feat: document tagging and enhanced metrics ([5604](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5604)) +* move wait_till logic into function, integrate it into cluster datasource ([5540](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5540)) + +BugFixes +* fix(docs): doc section fix for share accessor binding data sources ([5559](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5559)) +* Fix panics on alerts resource ([5561](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5561)) +* ibm_is_lb: Total provision time too long ([5523](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5523)) +* ibm_pi_image docs should link to the catalog images ibm_pi_catalog_images ([5047](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5047)) +* Resource controller can't able to update service-endpoint for event-stream instance ([5568](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5568)) +* The terraform-provider-ibm_v1.68.1 plugin crashed when trying to update Code Engine Secrets ([5582](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5582)) +* ibm_scc_profile_attachment does not update attachment parameters ([5535](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5535)) +* fix: wait for async instance update ([5601](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5601)) +* Updated ibm_is_subnet_reserved_ip docs ([5606](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5606)) + +# 1.69.0-beta1 (Aug 31, 2024) +Features +* Support Cloud Logs Routing + - **Datasources** + - ibm_logs_router_tenant + - **Resources** + - ibm_logs_router_tenants + - ibm_logs_router_targets +* Support EN + - **Datasources** + - ibm_en_metrics + - ibm_en_smtp_allowed_ips + +* Support Partner Center Sell + - **Resources** + - ibm_onboarding_registration + - ibm_onboarding_product + - ibm_onboarding_iam_registration + - ibm_onboarding_catalog_product + - ibm_onboarding_catalog_plan + - ibm_onboarding_catalog_deployment + - ibm_onboarding_resource_broker + +Enhancements +* Deprecate `force_delete` attribute of ibm_kms_rings ([5539](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5539)) +* feat(tekton): Add support for CEL filtering ([5531](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5531)) +* PKI HSM Addition ([5531](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5531)) +* updated error messages for catalog service ([5553](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5553)) +* feat(CIS): Origin Post Quantum Encryption and Max HTTP Version ([5504](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5504)) +* refactor of instance network attachment reference to use vni ([5563](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5563)) +* Update storage types docs ([5569](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5569)) +* Force delete subresources during kmip_adapter destroy, avoid casting panics ([5565](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5565)) +* Add support for retry of deletion of resource group ([5537](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5537)) +* Remove beta for logs service docs ([5581](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5581)) + +BugFixes +* fix(docs): doc section fix for share accessor binding data sources ([5559](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5559)) +* Fix panics on alerts resource ([5561](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5561)) +* ibm_is_lb: Total provision time too long ([5523](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5523)) +* ibm_pi_image docs should link to the catalog images ibm_pi_catalog_images ([5047](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5047)) +* Resource controller can't able to update service-endpoint for event-stream instance ([5568](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5568)) +* The terraform-provider-ibm_v1.68.1 plugin crashed when trying to update Code Engine Secrets ([5582](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5582)) +* ibm_scc_profile_attachment does not update attachment parameters ([5535](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5535)) + + +# 1.69.0-beta0 (Aug 22, 2024) +Features +* Support Cloud Logs Routing + - **Datasources** + - ibm_logs_router_tenant + - **Resources** + - ibm_logs_router_tenants + - ibm_logs_router_targets +* Support EN + - **Datasources** + - ibm_en_metrics + - ibm_en_smtp_allowed_ips + +Enhancements +* Deprecate `force_delete` attribute of ibm_kms_rings ([5503](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5503)) +* feat(tekton): Add support for CEL filtering ([5531](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5531)) +* PKI HSM Addition ([5531](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5531)) +* updated error messages for catalog service ([5553](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5553)) +* feat(CIS): Origin Post Quantum Encryption and Max HTTP Version ([5504](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5504)) +* refactor of instance network attachment reference to use vni ([5563](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5563)) + + +BugFixes +* fix(docs): doc section fix for share accessor binding data sources ([5559](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5559)) +* Fix panics on alerts resource ([5561](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5561)) +* ibm_is_lb: Total provision time too long ([5523](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5523)) + +# 1.68.1 (Aug 12, 2024) +BugFixes +* Fix code engine job regression ([5545](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5545)) +* Update(Cloud-Databases): Added hints for region and location mismatches ([5557](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5557)) +* fix(Cloud-Databases): Remove deprecated connectionstrings attribute ([5554](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5554)) +* remove the return value from waitForVpcCluster ([5557](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5557)) +* fix: read endpoint type from schema ([5552](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5552)) + +# 1.68.0 (Aug 04, 2024) +Features +* Support CBR + - **Datasources** + - ibm_cbr_zone_addresses + - **Resources** + - ibm_cbr_zone_addresses +* Support CIS + - **Datasources** + - ibm_cis_origin_certificates + - **Resources** + - ibm_cis_advanced_certificate_pack_order + - ibm_cis_origin_certificate_order +* Support VPC + - **Resources** + - ibm_is_bare_metal_server_initialization + +Enhancements +* Add dhcp network support for stratos ([5503](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5503)) +* IAM Policy Assignment: S2S Policy Assignments ([5499](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5499)) +* Code Engine Provider and Documentation Update ([5347](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5347)) +* move wait_till logic into function, integrate it into vpc_cluster datasource ([5476](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5346)) +* Remove hardcoded values for private and direct cos config endpoint ([5484](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5484)) +* feat(bm-dynamic-bandwidth): Support for bandwidth in bare metal ([5493](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5493)) +* Doc update for ODF ([5454](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5454)) +* feat(fs-cross-account): Support for file share cross account access ([5510](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5510)) +* feat Bm firmware update ([5519](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5519)) +* Changing the documentation for SCC ([5456](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5456)) +* feat(lb-parameterized-redirect): Update doc to specify parameterized url redirect ([5521](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5521)) +* chore(Cloud-Databases): Remove Datastax ([5511](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5511)) +* feat(ResourceController): Added onetime_credentials to ResourceInstance and ResourceKey read schemas ([5532](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5532)) +* Add PhysicalAddress and CapabilitiesManagedBySatellite to Terraform SatelliteLocation ([5530](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5530)) +* Added support for bm reinitialization ([5520](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5520)) + +BugFixes +* fix(CIS): updating managed ruleset documents ([5488](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5488)) +* fix(ins-keys): Make VSI keys optional ([5518](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5518)) +* fix(is-volume): Set catalogoffering computed attribute empty list ([5514](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5514)) +* add import_on_create param to ibm_container_vpc_worker_pool doc ([5506](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5506)) +* [Doc]Update Doc for E1080 Support ([5536](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5536)) +* Fix(iam-identity):trusted profile templates ([5440](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5440)) +* S2S documentation note for ibm_kms_key and minor linting fixes ([5529](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5529)) + +# 1.68.0-beta0 (July 23, 2024) +Features +* Support CBR + - **Datasources** + - ibm_cbr_zone_addresses + - **Resources** + - ibm_cbr_zone_addresses +* Support CIS + - **Datasources** + - ibm_cis_origin_certificates + - **Resources** + - ibm_cis_advanced_certificate_pack_order + - ibm_cis_origin_certificate_order + +Enhancements +* Add dhcp network support for stratos ([5503](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5503)) +* IAM Policy Assignment: S2S Policy Assignments ([5499](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5499)) +* Code Engine Provider and Documentation Update ([5347](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5347)) +* move wait_till logic into function, integrate it into vpc_cluster datasource ([5476](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5346)) +* Remove hardcoded values for private and direct cos config endpoint ([5484](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5484)) +* feat(bm-dynamic-bandwidth): Support for bandwidth in bare metal ([5493](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5493)) +* Doc update for ODF ([5454](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5454)) +* feat(fs-cross-account): Support for file share cross account access ([5510](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5510)) +* feat Bm firmware update ([5519](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5519)) +* Changing the documentation for SCC ([5456](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5456)) +* feat(lb-parameterized-redirect): Update doc to specify parameterized url redirect ([5521](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5521)) + + +BugFixes +* fix(CIS): updating managed ruleset documents ([5488](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5488)) +* fix(ins-keys): Make VSI keys optional ([5518](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5518)) +* fix(is-volume): Set catalogoffering computed attribute empty list ([5514](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5514)) +* add import_on_create param to ibm_container_vpc_worker_pool doc ([5506](https://github.com/IBM-Cloud/terraform-provider-ibm/pull/5506)) + + # 1.67.1 (July 05, 2024) BugFixes * Error: The terraform-provider-ibm_v1.67.0 plugin crashed! ([5485](https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5485)) diff --git a/examples/ibm-cis/main.tf b/examples/ibm-cis/main.tf index 7b57ad19a0..4adaa420b5 100644 --- a/examples/ibm-cis/main.tf +++ b/examples/ibm-cis/main.tf @@ -777,4 +777,32 @@ resource "ibm_cis_ruleset_version_detach" "tests" { domain_id = data.ibm_cis_domain.cis_domain.domain_id ruleset_id = "" version = "" +} + +# Order Advanced Certificate Pack +resource "ibm_cis_advanced_certificate_pack_order" "test" { + cis_id = data.ibm_cis.cis.id + domain_id = data.ibm_cis_domain.cis_domain.domain_id + hosts = ["example.com"] + certificate_authority = "lets_encrypt" + cloudflare_branding = false + validation_method = "txt" + validity = 90 +} + +# Order Origin Certificate +resource "ibm_cis_origin_certificate_order" "test" { + cis_id = data.ibm_cis.cis.id + domain_id = data.ibm_cis_domain.cis_domain.domain_id + hostnames = ["example.com"] + request_type = "origin-rsa" + requested_validity = 5475 + csr = "-----BEGIN CERTIFICATE REQUEST-----\nMIICxzCC***TA67sdbcQ==\n-----END CERTIFICATE REQUEST-----" +} + +# Get Origin Certificates +data ibm_cis_origin_certificates "test" { + cis_id = ibm_cis.instance.id + domain_id = ibm_cis_domain.example.id + certificate_id = "25392180178235735583993116186144990011711092749" } \ No newline at end of file diff --git a/examples/ibm-cos-bucket/README.md b/examples/ibm-cos-bucket/README.md index 6f4e5f6360..91d220a059 100644 --- a/examples/ibm-cos-bucket/README.md +++ b/examples/ibm-cos-bucket/README.md @@ -22,6 +22,11 @@ Run `terraform destroy` when you don't need these resources. Create an IBM Cloud Object Storage bucket. The bucket is used to store your data: + **Note:** + +A bucket name can be reused as soon as 15 minutes after the contents of the bucket have been deleted and the bucket has been deleted. Then, the objects and bucket are irrevocably deleted and can not be restored. +For more information, please refer to [this link](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-faq-bucket#faq-reuse-name) + ```terraform data "ibm_resource_group" "cos_group" { diff --git a/examples/ibm-event-streams/README.md b/examples/ibm-event-streams/README.md index 7a1aa0679e..2e3dab13b1 100644 --- a/examples/ibm-event-streams/README.md +++ b/examples/ibm-event-streams/README.md @@ -1,70 +1,101 @@ # IBM Event Streams examples -This example shows 3 usage scenarios. +This example shows several Event Streams usage scenarios. -#### Scenario 1: Create an Event Streams service instance and topic. +## Creating Event Streams instances + +Event Streams service instances are created with the `"ibm_resource_instance"` resource type. + +The following `"ibm_resource_instance"` arguments are required: + +- `name`: The service instance name, as it will appear in the Event Streams UI and CLI. + +- `service`: Use `"messagehub"` for an Event Streams instance. + +- `plan`: One of `"lite"`, `"standard"`, or `"enterprise-3nodes-2tb"`. For more information about the plans, see [Choosing your plan](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-plan_choose). Note: `"enterprise-3nodes-2tb"` selects the Enterprise plan. + +- `location`: The region where the service instance will be provisioned. For a list of regions, see [Region and data center locations](https://cloud.ibm.com/docs/overview?topic=overview-locations). + +- `resource_group_id`: The ID of the resource group in which the instance will be provisioned. For more information about resource groups, see [Managing resource groups](https://cloud.ibm.com/docs/account?topic=account-rgs). + +The `parameters` argument is optional and provides additional provision or update options. Supported parameters are: + +- `throughput`: One of `"150"` (the default), `"300"`, `"450"`. The maximum capacity in MB/s for producing or consuming messages. For more information see [Scaling Enterprise plan capacity](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-ES_scaling_capacity). *Note:* See [Scaling combinations](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-ES_scaling_capacity#ES_scaling_combinations) for allowed combinations of `throughput` and `storage_size`. + - Example: `throughput = "300"` + +- `storage_size`: One of `"2048"` (the default), `"4096"`, `"6144"`, `"8192"`, `"10240"`, or `"12288"`. The amount of storage capacity in GB. For more information see [Scaling Enterprise plan capacity](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-ES_scaling_capacity). *Note:* See [Scaling combinations](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-ES_scaling_capacity#ES_scaling_combinations) for allowed combinations of `throughput` and `storage_size`. + - Example: `storage_size = "4096"` + +- `service-endpoints`: One of `"public"` (the default), `"private"`, or `"public-and-private"`. For enterprise instance only. For more information see [Restricting network access](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-restrict_access). + - Example: `service-endpoints = "private"` + +- `private_ip_allowlist`: **Deprecated** An array of CIDRs specifying a private IP allowlist. For enterprise instance only. For more information see [Specifying an IP allowlist](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-restrict_access#specify_allowlist). This feature has been deprecated in favor of context-based restrictions. + - Example: `private_ip_allowlist = "[10.0.0.0/32,10.0.0.1/32]"` + +- `metrics`: An array of strings, allowed values are `"topic"`, `"partition"`, and `"consumers"`. Enables additional enhanced metrics for the instance. For enterprise instance only. For more information on enhanced metrics, see [Enabling enhanced Event Streams metrics](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-metrics#opt_in_enhanced_metrics). + - Example: `metrics = "[topic,partition]"` + +- `kms_key_crn`: The CRN (as a string) of a customer-managed root key provisioned with an IBM Cloud Key Protect or Hyper Protect Crypto Service. If provided, this key is used to encrypt all data at rest. For more information on customer-managed encryption, see [Managing encryption in Event Streams](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-managing_encryption). + - Example: `kms_key_crn = "crn:v1:prod:public:kms:us-south:a/6db1b0d0b5c54ee5c201552547febcd8:20adf7eb-e095-4dec-08cf-0b7d81e32db6:key:3fa9d921-d3b6-3516-a1ec-d54e27e7638b"` + +The `timeouts` argument is used to specify how long the IBM Cloud terraform provider will wait for the provision, update, or deprovision of the service instance. Values of 15 minutes are sufficient for standard and lite plans. For enterprise plans: +- Use "3h" for create. Add an additional 1 hour for each level of non-default throughput, and an additional 30 minutes for each level of non-default storage size. For example with `throughput = "300"` (one level over default) and `storage_size = "8192"` (three levels over default), use 3 hours + 1 * 1 hour + 3 * 30 minutes = 5.5 hours. +- Use "1h" for update. If increasing the throughput or storage size, add an additional 1 hour for each level of non-default throughput, and an additional 30 minutes for each level of non-default storage size. +- Use "1h" for delete. + +## Scenarios + +#### Scenario 1: Create an Event Streams standard-plan service instance. + +This creates a standard plan instance in us-south. ```terraform resource "ibm_resource_instance" "es_instance_1" { name = "terraform-integration-1" service = "messagehub" - plan = "standard" # "lite", "enterprise-3nodes-2tb" - location = "us-south" # "us-east", "eu-gb", "eu-de", "jp-tok", "au-syd" + plan = "standard" + location = "us-south" resource_group_id = data.ibm_resource_group.group.id - # parameters = { - # service-endpoints = "private" # for enterprise instance only, Options are: "public", "public-and-private", "private". Default is "public" when not specified. - # private_ip_allowlist = "[10.0.0.0/32,10.0.0.1/32]" # for enterprise instance only. Specify 1 or more IP range in CIDR format - # # document about using private service endpoint and IP allowlist to restrict access: https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-restrict_access - - # throughput = "150" # for enterprise instance only. Options are: "150", "300", "450". Default is "150" when not specified. - # storage_size = "2048" # for enterprise instance only. Options are: "2048", "4096", "6144", "8192", "10240", "12288". Default is "2048" when not specified. - # # Note: when throughput is "300", storage_size starts from "4096", when throughput is "450", storage_size starts from "6144" - # # document about supported combinations of throughput and storage_size: https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-ES_scaling_capacity#ES_scaling_combinations - # } - - # timeouts { - # create = "15m" # use 3h when creating enterprise instance, add additional 1h for each level of non-default throughput, add additional 30m for each level of non-default storage_size - # update = "15m" # use 1h when updating enterprise instance, add additional 1h for each level of non-default throughput, add additional 30m for each level of non-default storage_size - # delete = "15m" - # } -} - -resource "ibm_event_streams_topic" "es_topic_1" { - resource_instance_id = ibm_resource_instance.es_instance_1.id - name = "my-es-topic" - partitions = 1 - config = { - "cleanup.policy" = "compact,delete" - "retention.ms" = "86400000" - "retention.bytes" = "1073741824" - "segment.bytes" = "536870912" + timeouts { + create = "15m" + update = "15m" + delete = "15m" } } ``` -#### Scenario 2: Create a topic on an existing Event Streams instance. +#### Scenario 2: Create an Event Streams enterprise service instance with non-default attributes + +This creates an enterprise plan instance in us-east with 300 MB/s throughput, 4 TB storage, private endpoints with an allowlist, and enhanced metrics for topics and consumer groups. The timeouts are calculated as described above. ```terraform -data "ibm_resource_instance" "es_instance_2" { +resource "ibm_resource_instance" "es_instance_2" { name = "terraform-integration-2" + service = "messagehub" + plan = "enterprise-3nodes-2tb" + location = "us-east" resource_group_id = data.ibm_resource_group.group.id -} -resource "ibm_event_streams_topic" "es_topic_2" { - resource_instance_id = data.ibm_resource_instance.es_instance_2.id - name = "my-es-topic" - partitions = 1 - config = { - "cleanup.policy" = "compact,delete" - "retention.ms" = "86400000" - "retention.bytes" = "1073741824" - "segment.bytes" = "536870912" + parameters = { + throughput = "300" + storage_size = "4096" + service-endpoints = "private" + private_ip_allowlist = "[10.0.0.0/32,10.0.0.1/32]" + metrics = "[topic,consumers]" + } + + timeouts { + create = "330m" # 5.5h + update = "210m" # 3.5h + delete = "1h" } } ``` -#### Scenario 3: Create a kafka consumer application connecting to an existing Event Streams instance and its topics. +#### Scenario 3: Create a topic on an existing Event Streams instance. + +For more information on topics and topic parameters, see [Topics and partitions](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-apache_kafka&interface=ui#kafka_topics_partitions) and [Using the administration Kafka Java client API](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-kafka_java_api). ```terraform data "ibm_resource_instance" "es_instance_3" { @@ -72,20 +103,23 @@ data "ibm_resource_instance" "es_instance_3" { resource_group_id = data.ibm_resource_group.group.id } -data "ibm_event_streams_topic" "es_topic_3" { +resource "ibm_event_streams_topic" "es_topic_3" { resource_instance_id = data.ibm_resource_instance.es_instance_3.id name = "my-es-topic" -} - -resource "kafka_consumer_app" "es_kafka_app" { - bootstrap_server = lookup(data.ibm_resource_instance.es_instance_3.extensions, "kafka_brokers_sasl", []) - topics = [data.ibm_event_streams_topic.es_topic_3.name] - apikey = var.es_reader_api_key + partitions = 1 + config = { + "cleanup.policy" = "compact,delete" + "retention.ms" = "86400000" + "retention.bytes" = "1073741824" + "segment.bytes" = "536870912" + } } ``` #### Scenario 4: Create a schema on an existing Event Streams Enterprise instance +For more information on the Event Streams schema registry, see [Using Event Streams Schema Registry](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-ES_schema_registry). + ```terraform data "ibm_resource_instance" "es_instance_4" { name = "terraform-integration-4" @@ -108,6 +142,60 @@ resource "ibm_event_streams_schema" "es_schema" { } ``` +#### Scenario 5: Apply access tags to an Event Streams service instance + +Tags are applied using the `"ibm_resource_tag"` terraform resource. +For more information about tagging, see the documentation for the `"ibm_resource_tag"` resource and [Tagging](https://cloud.ibm.com/apidocs/tagging). + +```terraform +data "ibm_resource_instance" "es_instance_5" { + name = "terraform-integration-5" + resource_group_id = data.ibm_resource_group.group.id +} + +resource "ibm_resource_tag" "tag_example_on_es" { + tags = ["example:tag"] + tag_type = "access" + resource_id = data.ibm_resource_instance.es_instance_5.id +} +``` + +#### Scenario 6: Connect to an existing Event Streams instance and its topics. + +This scenario uses a fictitious `"kafka_consumer_app"` resource to demonstrate how a consumer application could be configured. +The resource uses three configuration properties: + +1. The Kafka broker hostnames used to connect to the service instance. +2. An API key for reading from the topics. +3. The names of the topic(s) which the consumer should read. + +The broker hostnames would be required by any consumer or producer application. After the Event Streams service instance has been created, they are available in the `extensions` attribute of the service instance, as an array named `"kafka_brokers_sasl"`. This is shown in the example. + +An API key would also be required by any application. This key would typically be created with reduced permissions to restrict the operations it can perform, for example only allowing it to read from certain topics. See [Managing authentication to your Event Streams instance](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-security) for more information on creating keys. The example assumes the key is provided as a terraform variable. + +The topic names can be provided as strings, or can be taken from topic data sources as shown in the example. + +```terraform +# Use an existing instance +data "ibm_resource_instance" "es_instance_6" { + name = "terraform-integration-6" + resource_group_id = data.ibm_resource_group.group.id +} + +# Use an existing topic on that instance +data "ibm_event_streams_topic" "es_topic_6" { + resource_instance_id = data.ibm_resource_instance.es_instance_6.id + name = "my-es-topic" +} + +# The FICTITIOUS consumer application, configured with brokers, API key, and topics +resource "kafka_consumer_app" "es_kafka_app" { + bootstrap_server = lookup(data.ibm_resource_instance.es_instance_4.extensions, "kafka_brokers_sasl", []) + apikey = var.es_reader_api_key + topics = [data.ibm_event_streams_topic.es_topic_4.name] +} +``` + ## Dependencies - The owner of the `ibmcloud_api_key` has permission to create Event Streams instance under specified resource group and has Manager role to the created instance in order to create topic. @@ -116,9 +204,7 @@ resource "ibm_event_streams_schema" "es_schema" { ## Configuration -- `ibmcloud_api_key` - An API key for IBM Cloud services. If you don't have one already, go to https://cloud.ibm.com/iam/#/apikeys and create a new key. - -- `es_reader_api_key` - An service ID API key with reduced permission in scenario 3 if user wish to scope the access to Event Streams instance and topics. +- `ibmcloud_api_key` - An API key for IBM Cloud services. If you don't have one already, go to https://cloud.ibm.com/iam/apikeys and create a new key. ## Running the configuration diff --git a/examples/ibm-event-streams/main.tf b/examples/ibm-event-streams/main.tf index 44c3e91214..a16618467b 100644 --- a/examples/ibm-event-streams/main.tf +++ b/examples/ibm-event-streams/main.tf @@ -1,83 +1,72 @@ +# This is not functional terraform code. It is intended as a template for users to remove +# unneeded scenarios and edit the other sections. + +# Replace the resource group name with the one in which your resources should be created data "ibm_resource_group" "group" { name = "Default" } -#### Scenario 1: Create Event Streams service instance and topic +#### Scenario 1: Create an Event Streams standard-plan service instance. resource "ibm_resource_instance" "es_instance_1" { name = "terraform-integration-1" service = "messagehub" - plan = "standard" # "lite", "enterprise-3nodes-2tb" - location = "us-south" # "us-east", "eu-gb", "eu-de", "jp-tok", "au-syd" + plan = "standard" + location = "us-south" resource_group_id = data.ibm_resource_group.group.id - # parameters = { - # service-endpoints = "private" # for enterprise instance only, Options are: "public", "public-and-private", "private". Default is "public" when not specified. - # private_ip_allowlist = "[10.0.0.0/32,10.0.0.1/32]" # for enterprise instance only. Specify 1 or more IP range in CIDR format - # # document about using private service endpoint and IP allowlist to restrict access: https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-restrict_access - - # throughput = "150" # for enterprise instance only. Options are: "150", "300", "450". Default is "150" when not specified. - # storage_size = "2048" # for enterprise instance only. Options are: "2048", "4096", "6144", "8192", "10240", "12288". Default is "2048" when not specified. - # kms_key_crn = "crn:v1:bluemix:public:kms:us-south:a/6db1b0d0b5c54ee5c201552547febcd8:0aa69b09-941b-41b2-bbf9-9f9f0f6a6f79:key:dd37a0b6-eff4-4708-8459-e29ae0a8f256" # for enterprise instance only. Specify the CRN of a root key from a Key Management Service instance used to encrypt disks. - # # Note: when throughput is "300", storage_size starts from "4096", when throughput is "450", storage_size starts from "6144" - # # document about supported combinations of throughput and storage_size: https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-ES_scaling_capacity#ES_scaling_combinations - # } - - # timeouts { - # create = "15m" # use 3h when creating enterprise instance, add additional 1h for each level of non-default throughput, add additional 30m for each level of non-default storage_size - # update = "15m" # use 1h when updating enterprise instance, add additional 1h for each level of non-default throughput, add additional 30m for each level of non-default storage_size - # delete = "15m" - # } -} - -resource "ibm_event_streams_topic" "es_topic_1" { - resource_instance_id = ibm_resource_instance.es_instance_1.id - name = "my-es-topic" - partitions = 1 - config = { - "cleanup.policy" = "compact,delete" - "retention.ms" = "86400000" - "retention.bytes" = "1073741824" - "segment.bytes" = "536870912" + timeouts { + create = "15m" + update = "15m" + delete = "15m" } } -#### Scenario 2: Create topic on an existing Event Streams instance -data "ibm_resource_instance" "es_instance_2" { +#### Scenario 2: Create an Event Streams enterprise service instance with non-default attributes +resource "ibm_resource_instance" "es_instance_2" { name = "terraform-integration-2" + service = "messagehub" + plan = "enterprise-3nodes-2tb" + location = "us-east" resource_group_id = data.ibm_resource_group.group.id -} -resource "ibm_event_streams_topic" "es_topic_2" { - resource_instance_id = data.ibm_resource_instance.es_instance_2.id - name = "my-es-topic" - partitions = 1 - config = { - "cleanup.policy" = "compact,delete" - "retention.ms" = "86400000" - "retention.bytes" = "1073741824" - "segment.bytes" = "536870912" + parameters = { + throughput = "300" + storage_size = "4096" + service-endpoints = "private" + private_ip_allowlist = "[10.0.0.0/32,10.0.0.1/32]" + metrics = "[topic,consumers]" + } + + timeouts { + create = "330m" # 5.5h + update = "210m" # 3.5h + delete = "1h" } } -#### Scenario 3: Create a kafka consumer application connecting to an existing Event Streams instance and its topics +#### Scenario 3: Create a topic on an existing Event Streams instance. + +# the existing instance data "ibm_resource_instance" "es_instance_3" { name = "terraform-integration-3" resource_group_id = data.ibm_resource_group.group.id } -data "ibm_event_streams_topic" "es_topic_3" { +resource "ibm_event_streams_topic" "es_topic_3" { resource_instance_id = data.ibm_resource_instance.es_instance_3.id name = "my-es-topic" + partitions = 1 + config = { + "cleanup.policy" = "compact,delete" + "retention.ms" = "86400000" + "retention.bytes" = "1073741824" + "segment.bytes" = "536870912" + } } -resource "kafka_consumer_app" "es_kafka_app" { - bootstrap_server = lookup(data.ibm_resource_instance.es_instance_3.extensions, "kafka_brokers_sasl", []) - topics = [data.ibm_event_streams_topic.es_topic_3.name] - apikey = var.es_reader_api_key -} +#### Scenario 4: Create a schema on an existing Event Streams Enterprise instance -#### Scenario 4 Create a schema on an existing Event Streams Enterprise instance data "ibm_resource_instance" "es_instance_4" { name = "terraform-integration-4" resource_group_id = data.ibm_resource_group.group.id @@ -85,7 +74,7 @@ data "ibm_resource_instance" "es_instance_4" { resource "ibm_event_streams_schema" "es_schema" { resource_instance_id = data.ibm_resource_instance.es_instance_4.id - schema_id = "my-es-schema" + schema_id = "tf_schema" schema = < 0.12 | + +## Providers + +| Name | Version | +|------|---------| +| ibm | 1.13.1 | diff --git a/examples/ibm-logs-routing/main.tf b/examples/ibm-logs-routing/main.tf new file mode 100644 index 0000000000..fce3673817 --- /dev/null +++ b/examples/ibm-logs-routing/main.tf @@ -0,0 +1,36 @@ +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = "us-south" +} + +// Provision logs_router_tenant resource instance +resource "ibm_logs_router_tenant" "logs_router_tenant_instance" { + name = var.logs_router_tenant_name + targets { + log_sink_crn = "crn:v1:bluemix:public:logdna:eu-de:a/7246b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + name = "my-logdna-target" + parameters { + host = "www.example-1.com" + port = 80 + access_credential = "new-cred" + } + } + targets { + log_sink_crn = "crn:v1:bluemix:public:logs:eu-de:a/7246b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + name = "my-cloud-logs-target" + parameters { + host = "www.example-2.com" + port = 80 + } + } +} + +// Create logs_router_tenants data source +data "ibm_logs_router_tenants" "logs_router_tenants_instance" { + name = ibm_logs_router_tenant.logs_router_tenant_instance_both.name +} + +// Create logs_router_targets data source +data "ibm_logs_router_targets" "logs_router_targets_instance" { + tenant_id = ibm_logs_router_tenant.logs_router_tenant_instance_both.id +} \ No newline at end of file diff --git a/examples/ibm-logs-routing/outputs.tf b/examples/ibm-logs-routing/outputs.tf new file mode 100644 index 0000000000..26d312f64e --- /dev/null +++ b/examples/ibm-logs-routing/outputs.tf @@ -0,0 +1,12 @@ +// This output allows logs_router_tenant data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_logs_router_tenant" { + value = ibm_logs_router_tenant.logs_router_tenant_instance + description = "logs_router_tenant resource instance" +} + +output "ibm_logs_router_tenants" { + value = data.ibm_logs_router_tenants.logs_router_tenants_instance + description = "logs_router_tenants" +} + diff --git a/examples/ibm-logs-routing/variables.tf b/examples/ibm-logs-routing/variables.tf new file mode 100644 index 0000000000..c8d7c4f458 --- /dev/null +++ b/examples/ibm-logs-routing/variables.tf @@ -0,0 +1,11 @@ +variable "ibmcloud_api_key" { + description = "IBM Cloud API key" + type = string +} + +// Resource arguments for logs_router_tenant +variable "logs_router_tenant_name" { + description = "The name for this tenant. The name is regionally unique across all tenants in the account." + type = string + default = "my-logging-tenant" +} diff --git a/examples/ibm-logs-routing/versions.tf b/examples/ibm-logs-routing/versions.tf new file mode 100644 index 0000000000..4049a00043 --- /dev/null +++ b/examples/ibm-logs-routing/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.0" + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + version = "1.52.0-beta0" + } + } +} \ No newline at end of file diff --git a/examples/ibm-partner-center-sell/README.md b/examples/ibm-partner-center-sell/README.md new file mode 100644 index 0000000000..0fe30efee7 --- /dev/null +++ b/examples/ibm-partner-center-sell/README.md @@ -0,0 +1,340 @@ +# Examples for Partner Center Sell + +These examples illustrate how to use the resources and data sources associated with Partner Center Sell. + +The following resources are supported: +* ibm_onboarding_resource_broker +* ibm_onboarding_catalog_deployment +* ibm_onboarding_catalog_plan +* ibm_onboarding_catalog_product +* ibm_onboarding_iam_registration +* ibm_onboarding_product +* ibm_onboarding_registration + +## Usage + +To run this example, execute the following commands: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Run `terraform destroy` when you don't need these resources. + +## Partner Center Sell resources + +### Resource: ibm_onboarding_resource_broker + +```hcl +resource "ibm_onboarding_resource_broker" "onboarding_resource_broker_instance" { + env = var.onboarding_resource_broker_env + auth_username = var.onboarding_resource_broker_auth_username + auth_password = var.onboarding_resource_broker_auth_password + auth_scheme = var.onboarding_resource_broker_auth_scheme + resource_group_crn = var.onboarding_resource_broker_resource_group_crn + state = var.onboarding_resource_broker_state + broker_url = var.onboarding_resource_broker_broker_url + allow_context_updates = var.onboarding_resource_broker_allow_context_updates + catalog_type = var.onboarding_resource_broker_catalog_type + type = var.onboarding_resource_broker_type + name = var.onboarding_resource_broker_name + region = var.onboarding_resource_broker_region +} +``` + +#### Inputs + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| env | The environment to fetch this object from. | `string` | false | +| auth_username | The authentication username to reach the broker. | `string` | true | +| auth_password | The authentication password to reach the broker. | `string` | true | +| auth_scheme | The supported authentication scheme for the broker. | `string` | true | +| resource_group_crn | The cloud resource name of the resource group. | `string` | false | +| state | The state of the broker. | `string` | false | +| broker_url | The URL associated with the broker application. | `string` | true | +| allow_context_updates | Whether the resource controller will call the broker for any context changes to the instance. Currently, the only context related change is an instance name update. | `bool` | false | +| catalog_type | To enable the provisioning of your broker, set this parameter value to `service`. | `string` | false | +| type | The type of the provisioning model. | `string` | true | +| name | The name of the broker. | `string` | true | +| region | The region where the pricing plan is available. | `string` | false | + +#### Outputs + +| Name | Description | +|------|-------------| +| account_id | The ID of the account in which you manage the broker. | +| crn | The cloud resource name (CRN) of the broker. | +| created_at | The time when the service broker was created. | +| updated_at | The time when the service broker was updated. | +| deleted_at | The time when the service broker was deleted. | +| created_by | The details of the user who created this broker. | +| updated_by | The details of the user who updated this broker. | +| deleted_by | The details of the user who deleted this broker. | +| guid | The globally unique identifier of the broker. | +| url | The URL associated with the broker. | + +### Resource: ibm_onboarding_catalog_deployment + +```hcl +resource "ibm_onboarding_catalog_deployment" "onboarding_catalog_deployment_instance" { + product_id = var.onboarding_catalog_deployment_product_id + catalog_product_id = var.onboarding_catalog_deployment_catalog_product_id + catalog_plan_id = var.onboarding_catalog_deployment_catalog_plan_id + env = var.onboarding_catalog_deployment_env + name = var.onboarding_catalog_deployment_name + active = var.onboarding_catalog_deployment_active + disabled = var.onboarding_catalog_deployment_disabled + kind = var.onboarding_catalog_deployment_kind + overview_ui = var.onboarding_catalog_deployment_overview_ui + tags = var.onboarding_catalog_deployment_tags + object_provider = var.onboarding_catalog_deployment_object_provider + metadata = var.onboarding_catalog_deployment_metadata +} +``` + +#### Inputs + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| product_id | The unique ID of the product. | `string` | true | +| catalog_product_id | The unique ID of this global catalog product. | `string` | true | +| catalog_plan_id | The unique ID of this global catalog plan. | `string` | true | +| env | The environment to fetch this object from. | `string` | false | +| name | The programmatic name of this deployment. | `string` | true | +| active | Whether the service is active. | `bool` | true | +| disabled | Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled. | `bool` | true | +| kind | The kind of the global catalog object. | `string` | true | +| overview_ui | The object that contains the service details from the Overview page in global catalog. | `` | false | +| tags | A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog. | `list(string)` | true | +| object_provider | The provider or owner of the product. | `` | true | +| metadata | Global catalog deployment metadata. | `` | false | + +#### Outputs + +| Name | Description | +|------|-------------| +| url | The global catalog URL of your product. | +| catalog_deployment_id | The ID of a global catalog object. | + +### Resource: ibm_onboarding_catalog_plan + +```hcl +resource "ibm_onboarding_catalog_plan" "onboarding_catalog_plan_instance" { + product_id = var.onboarding_catalog_plan_product_id + catalog_product_id = var.onboarding_catalog_plan_catalog_product_id + env = var.onboarding_catalog_plan_env + name = var.onboarding_catalog_plan_name + active = var.onboarding_catalog_plan_active + disabled = var.onboarding_catalog_plan_disabled + kind = var.onboarding_catalog_plan_kind + overview_ui = var.onboarding_catalog_plan_overview_ui + tags = var.onboarding_catalog_plan_tags + object_provider = var.onboarding_catalog_plan_object_provider + metadata = var.onboarding_catalog_plan_metadata +} +``` + +#### Inputs + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| product_id | The unique ID of the product. | `string` | true | +| catalog_product_id | The unique ID of this global catalog product. | `string` | true | +| env | The environment to fetch this object from. | `string` | false | +| name | The programmatic name of this plan. | `string` | true | +| active | Whether the service is active. | `bool` | true | +| disabled | Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled. | `bool` | true | +| kind | The kind of the global catalog object. | `string` | true | +| overview_ui | The object that contains the service details from the Overview page in global catalog. | `` | false | +| tags | A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog. | `list(string)` | true | +| object_provider | The provider or owner of the product. | `` | true | +| metadata | Global catalog plan metadata. | `` | false | + +#### Outputs + +| Name | Description | +|------|-------------| +| url | The global catalog URL of your product. | +| catalog_plan_id | The ID of a global catalog object. | + +### Resource: ibm_onboarding_catalog_product + +```hcl +resource "ibm_onboarding_catalog_product" "onboarding_catalog_product_instance" { + product_id = var.onboarding_catalog_product_product_id + env = var.onboarding_catalog_product_env + name = var.onboarding_catalog_product_name + active = var.onboarding_catalog_product_active + disabled = var.onboarding_catalog_product_disabled + kind = var.onboarding_catalog_product_kind + overview_ui = var.onboarding_catalog_product_overview_ui + tags = var.onboarding_catalog_product_tags + images = var.onboarding_catalog_product_images + object_provider = var.onboarding_catalog_product_object_provider + metadata = var.onboarding_catalog_product_metadata +} +``` + +#### Inputs + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| product_id | The unique ID of the product. | `string` | true | +| env | The environment to fetch this object from. | `string` | false | +| name | The programmatic name of this product. | `string` | true | +| active | Whether the service is active. | `bool` | true | +| disabled | Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled. | `bool` | true | +| kind | The kind of the global catalog object. | `string` | true | +| overview_ui | The object that contains the service details from the Overview page in global catalog. | `` | false | +| tags | A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog. | `list(string)` | true | +| images | Images from the global catalog entry that help illustrate the service. | `` | false | +| object_provider | The provider or owner of the product. | `` | true | +| metadata | The global catalog service metadata object. | `` | false | + +#### Outputs + +| Name | Description | +|------|-------------| +| url | The global catalog URL of your product. | +| catalog_product_id | The ID of a global catalog object. | + +### Resource: ibm_onboarding_iam_registration + +```hcl +resource "ibm_onboarding_iam_registration" "onboarding_iam_registration_instance" { + product_id = var.onboarding_iam_registration_product_id + env = var.onboarding_iam_registration_env + name = var.onboarding_iam_registration_name + enabled = var.onboarding_iam_registration_enabled + service_type = var.onboarding_iam_registration_service_type + actions = var.onboarding_iam_registration_actions + additional_policy_scopes = var.onboarding_iam_registration_additional_policy_scopes + display_name = var.onboarding_iam_registration_display_name + parent_ids = var.onboarding_iam_registration_parent_ids + resource_hierarchy_attribute = var.onboarding_iam_registration_resource_hierarchy_attribute + supported_anonymous_accesses = var.onboarding_iam_registration_supported_anonymous_accesses + supported_attributes = var.onboarding_iam_registration_supported_attributes + supported_authorization_subjects = var.onboarding_iam_registration_supported_authorization_subjects + supported_roles = var.onboarding_iam_registration_supported_roles + supported_network = var.onboarding_iam_registration_supported_network +} +``` + +#### Inputs + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| product_id | The unique ID of the product. | `string` | true | +| env | The environment to fetch this object from. | `string` | false | +| name | The IAM registration name, which must be the programmatic name of the product. | `string` | false | +| enabled | Whether the service is enabled or disabled for IAM. | `bool` | false | +| service_type | The type of the service. | `string` | false | +| actions | The product access management action. | `list()` | false | +| additional_policy_scopes | List of additional policy scopes. | `list(string)` | false | +| display_name | The display name of the object. | `` | false | +| parent_ids | The list of parent IDs for product access management. | `list(string)` | false | +| resource_hierarchy_attribute | The resource hierarchy key-value pair for composite services. | `` | false | +| supported_anonymous_accesses | The list of supported anonymous accesses. | `list()` | false | +| supported_attributes | The list of supported attributes. | `list()` | false | +| supported_authorization_subjects | The list of supported authorization subjects. | `list()` | false | +| supported_roles | The list of roles that you can use to assign access. | `list()` | false | +| supported_network | The registration of set of endpoint types that are supported by your service in the `networkType` environment attribute. This constrains the context-based restriction rules specific to the service such that they describe access restrictions on only this set of endpoints. | `` | false | + +### Resource: ibm_onboarding_product + +```hcl +resource "ibm_onboarding_product" "onboarding_product_instance" { + type = var.onboarding_product_type + primary_contact = var.onboarding_product_primary_contact + eccn_number = var.onboarding_product_eccn_number + ero_class = var.onboarding_product_ero_class + unspsc = var.onboarding_product_unspsc + tax_assessment = var.onboarding_product_tax_assessment + support = var.onboarding_product_support +} +``` + +#### Inputs + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| type | The type of the product. | `string` | true | +| primary_contact | The primary contact for your product. | `` | true | +| eccn_number | The Export Control Classification Number of your product. | `string` | false | +| ero_class | The ERO class of your product. | `string` | false | +| unspsc | The United Nations Standard Products and Services Code of your product. | `number` | false | +| tax_assessment | The tax assessment type of your product. | `string` | false | +| support | The support information that is not displayed in the catalog, but available in ServiceNow. | `` | false | + +#### Outputs + +| Name | Description | +|------|-------------| +| account_id | The IBM Cloud account ID of the provider. | +| private_catalog_id | The ID of the private catalog that contains the product. Only applicable for software type products. | +| private_catalog_offering_id | The ID of the linked private catalog product. Only applicable for software type products. | +| global_catalog_offering_id | The ID of a global catalog object. | +| staging_global_catalog_offering_id | The ID of a global catalog object. | +| approver_resource_id | The ID of the approval workflow of your product. | + +### Resource: ibm_onboarding_registration + +```hcl +resource "ibm_onboarding_registration" "onboarding_registration_instance" { + account_id = var.onboarding_registration_account_id + company_name = var.onboarding_registration_company_name + primary_contact = var.onboarding_registration_primary_contact + default_private_catalog_id = var.onboarding_registration_default_private_catalog_id + provider_access_group = var.onboarding_registration_provider_access_group +} +``` + +#### Inputs + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| account_id | The ID of your account. | `string` | true | +| company_name | The name of your company that is displayed in the IBM Cloud catalog. | `string` | true | +| primary_contact | The primary contact for your product. | `` | true | +| default_private_catalog_id | The default private catalog in which products are created. | `string` | false | +| provider_access_group | The onboarding access group for your team. | `string` | false | + +#### Outputs + +| Name | Description | +|------|-------------| +| account_dra_id | The ID of the IBM Digital Platform Reseller Agreement. | +| account_dpa_id | The ID of the IBM Digital Provider Agreement. | +| created_at | The time when the registration was created. | +| updated_at | The time when the registration was updated. | + + +## Assumptions + +1. TODO + +## Notes + +1. TODO + +## Requirements + +| Name | Version | +|------|---------| +| terraform | ~> 0.12 | + +## Providers + +| Name | Version | +|------|---------| +| ibm | 1.13.1 | diff --git a/examples/ibm-partner-center-sell/main.tf b/examples/ibm-partner-center-sell/main.tf new file mode 100644 index 0000000000..a94ca8db57 --- /dev/null +++ b/examples/ibm-partner-center-sell/main.tf @@ -0,0 +1,457 @@ +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key +} + +// Provision onboarding_resource_broker resource instance +resource "ibm_onboarding_resource_broker" "onboarding_resource_broker_instance" { + env = var.onboarding_resource_broker_env + auth_username = var.onboarding_resource_broker_auth_username + auth_password = var.onboarding_resource_broker_auth_password + auth_scheme = var.onboarding_resource_broker_auth_scheme + resource_group_crn = var.onboarding_resource_broker_resource_group_crn + state = var.onboarding_resource_broker_state + broker_url = var.onboarding_resource_broker_broker_url + allow_context_updates = var.onboarding_resource_broker_allow_context_updates + catalog_type = var.onboarding_resource_broker_catalog_type + type = var.onboarding_resource_broker_type + name = var.onboarding_resource_broker_name + region = var.onboarding_resource_broker_region +} + +// Provision onboarding_catalog_deployment resource instance +resource "ibm_onboarding_catalog_deployment" "onboarding_catalog_deployment_instance" { + product_id = var.onboarding_catalog_deployment_product_id + catalog_product_id = var.onboarding_catalog_deployment_catalog_product_id + catalog_plan_id = var.onboarding_catalog_deployment_catalog_plan_id + env = var.onboarding_catalog_deployment_env + name = var.onboarding_catalog_deployment_name + active = var.onboarding_catalog_deployment_active + disabled = var.onboarding_catalog_deployment_disabled + kind = var.onboarding_catalog_deployment_kind + overview_ui { + en { + display_name = "display_name" + description = "description" + long_description = "long_description" + } + } + tags = var.onboarding_catalog_deployment_tags + object_provider { + name = "name" + email = "email" + } + metadata { + rc_compatible = true + ui { + strings { + en { + bullets { + description = "description" + description_i18n = { "key" = "inner" } + title = "title" + title_i18n = { "key" = "inner" } + } + media { + caption = "caption" + caption_i18n = { "key" = "inner" } + thumbnail = "thumbnail" + type = "image" + url = "url" + } + } + } + urls { + doc_url = "doc_url" + terms_url = "terms_url" + } + hidden = true + side_by_side_index = 1.0 + } + service { + rc_provisionable = true + iam_compatible = true + } + } +} + +// Provision onboarding_catalog_plan resource instance +resource "ibm_onboarding_catalog_plan" "onboarding_catalog_plan_instance" { + product_id = var.onboarding_catalog_plan_product_id + catalog_product_id = var.onboarding_catalog_plan_catalog_product_id + env = var.onboarding_catalog_plan_env + name = var.onboarding_catalog_plan_name + active = var.onboarding_catalog_plan_active + disabled = var.onboarding_catalog_plan_disabled + kind = var.onboarding_catalog_plan_kind + overview_ui { + en { + display_name = "display_name" + description = "description" + long_description = "long_description" + } + } + tags = var.onboarding_catalog_plan_tags + object_provider { + name = "name" + email = "email" + } + metadata { + rc_compatible = true + ui { + strings { + en { + bullets { + description = "description" + description_i18n = { "key" = "inner" } + title = "title" + title_i18n = { "key" = "inner" } + } + media { + caption = "caption" + caption_i18n = { "key" = "inner" } + thumbnail = "thumbnail" + type = "image" + url = "url" + } + } + } + urls { + doc_url = "doc_url" + terms_url = "terms_url" + } + hidden = true + side_by_side_index = 1.0 + } + pricing { + type = "free" + origin = "global_catalog" + } + } +} + +// Provision onboarding_catalog_product resource instance +resource "ibm_onboarding_catalog_product" "onboarding_catalog_product_instance" { + product_id = var.onboarding_catalog_product_product_id + env = var.onboarding_catalog_product_env + name = var.onboarding_catalog_product_name + active = var.onboarding_catalog_product_active + disabled = var.onboarding_catalog_product_disabled + kind = var.onboarding_catalog_product_kind + overview_ui { + en { + display_name = "display_name" + description = "description" + long_description = "long_description" + } + } + tags = var.onboarding_catalog_product_tags + images { + image = "image" + } + object_provider { + name = "name" + email = "email" + } + metadata { + rc_compatible = true + ui { + strings { + en { + bullets { + description = "description" + description_i18n = { "key" = "inner" } + title = "title" + title_i18n = { "key" = "inner" } + } + media { + caption = "caption" + caption_i18n = { "key" = "inner" } + thumbnail = "thumbnail" + type = "image" + url = "url" + } + } + } + urls { + doc_url = "doc_url" + terms_url = "terms_url" + } + hidden = true + side_by_side_index = 1.0 + } + service { + rc_provisionable = true + iam_compatible = true + } + other { + pc { + support { + url = "url" + status_url = "status_url" + locations = [ "locations" ] + languages = [ "languages" ] + process = "process" + process_i18n = { "key" = "inner" } + support_type = "community" + support_escalation { + contact = "contact" + escalation_wait_time { + value = 1.0 + type = "type" + } + response_wait_time { + value = 1.0 + type = "type" + } + } + support_details { + type = "support_site" + contact = "contact" + response_wait_time { + value = 1.0 + type = "type" + } + availability { + times { + day = 1.0 + start_time = "start_time" + end_time = "end_time" + } + timezone = "timezone" + always_available = true + } + } + } + } + } + } +} + +// Provision onboarding_iam_registration resource instance +resource "ibm_onboarding_iam_registration" "onboarding_iam_registration_instance" { + product_id = var.onboarding_iam_registration_product_id + env = var.onboarding_iam_registration_env + name = var.onboarding_iam_registration_name + enabled = var.onboarding_iam_registration_enabled + service_type = var.onboarding_iam_registration_service_type + actions { + id = "id" + roles = [ "roles" ] + description { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + options { + hidden = true + } + } + additional_policy_scopes = var.onboarding_iam_registration_additional_policy_scopes + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + parent_ids = var.onboarding_iam_registration_parent_ids + resource_hierarchy_attribute { + key = "key" + value = "value" + } + supported_anonymous_accesses { + attributes { + account_id = "account_id" + service_name = "service_name" + } + roles = [ "roles" ] + } + supported_attributes { + key = "key" + options { + operators = [ "stringEquals" ] + hidden = true + supported_attributes = [ "supported_attributes" ] + policy_types = [ "access" ] + is_empty_value_supported = true + is_string_exists_false_value_supported = true + key = "key" + resource_hierarchy { + key { + key = "key" + value = "value" + } + value { + key = "key" + } + } + } + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + description { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + ui { + input_type = "input_type" + input_details { + type = "type" + values { + value = "value" + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + } + gst { + query = "query" + value_property_name = "value_property_name" + label_property_name = "label_property_name" + input_option_label = "input_option_label" + } + url { + url_endpoint = "url_endpoint" + input_option_label = "input_option_label" + } + } + } + } + supported_authorization_subjects { + attributes { + service_name = "service_name" + resource_type = "resource_type" + } + roles = [ "roles" ] + } + supported_roles { + id = "id" + description { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + options { + access_policy = { "key" = "inner" } + policy_type = [ "access" ] + account_type = "enterprise" + } + } + supported_network { + environment_attributes { + key = "key" + values = [ "values" ] + options { + hidden = true + } + } + } +} + +// Provision onboarding_product resource instance +resource "ibm_onboarding_product" "onboarding_product_instance" { + type = var.onboarding_product_type + primary_contact { + name = "name" + email = "email" + } + eccn_number = var.onboarding_product_eccn_number + ero_class = var.onboarding_product_ero_class + unspsc = var.onboarding_product_unspsc + tax_assessment = var.onboarding_product_tax_assessment + support { + escalation_contacts { + name = "name" + email = "email" + role = "role" + } + } +} + +// Provision onboarding_registration resource instance +resource "ibm_onboarding_registration" "onboarding_registration_instance" { + account_id = var.onboarding_registration_account_id + company_name = var.onboarding_registration_company_name + primary_contact { + name = "name" + email = "email" + } + default_private_catalog_id = var.onboarding_registration_default_private_catalog_id + provider_access_group = var.onboarding_registration_provider_access_group +} diff --git a/examples/ibm-partner-center-sell/outputs.tf b/examples/ibm-partner-center-sell/outputs.tf new file mode 100644 index 0000000000..d54dd27d9b --- /dev/null +++ b/examples/ibm-partner-center-sell/outputs.tf @@ -0,0 +1,42 @@ +// This output allows onboarding_resource_broker data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_onboarding_resource_broker" { + value = ibm_onboarding_resource_broker.onboarding_resource_broker_instance + description = "onboarding_resource_broker resource instance" +} +// This output allows onboarding_catalog_deployment data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_onboarding_catalog_deployment" { + value = ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance + description = "onboarding_catalog_deployment resource instance" +} +// This output allows onboarding_catalog_plan data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_onboarding_catalog_plan" { + value = ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance + description = "onboarding_catalog_plan resource instance" +} +// This output allows onboarding_catalog_product data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_onboarding_catalog_product" { + value = ibm_onboarding_catalog_product.onboarding_catalog_product_instance + description = "onboarding_catalog_product resource instance" +} +// This output allows onboarding_iam_registration data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_onboarding_iam_registration" { + value = ibm_onboarding_iam_registration.onboarding_iam_registration_instance + description = "onboarding_iam_registration resource instance" +} +// This output allows onboarding_product data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_onboarding_product" { + value = ibm_onboarding_product.onboarding_product_instance + description = "onboarding_product resource instance" +} +// This output allows onboarding_registration data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_onboarding_registration" { + value = ibm_onboarding_registration.onboarding_registration_instance + description = "onboarding_registration resource instance" +} diff --git a/examples/ibm-partner-center-sell/variables.tf b/examples/ibm-partner-center-sell/variables.tf new file mode 100644 index 0000000000..60e1ae9410 --- /dev/null +++ b/examples/ibm-partner-center-sell/variables.tf @@ -0,0 +1,278 @@ +variable "ibmcloud_api_key" { + description = "IBM Cloud API key" + type = string +} + +// Resource arguments for onboarding_resource_broker +variable "onboarding_resource_broker_env" { + description = "The environment to fetch this object from." + type = string + default = "env" +} +variable "onboarding_resource_broker_auth_username" { + description = "The authentication username to reach the broker." + type = string + default = "auth_username" +} +variable "onboarding_resource_broker_auth_password" { + description = "The authentication password to reach the broker." + type = string + default = "auth_password" +} +variable "onboarding_resource_broker_auth_scheme" { + description = "The supported authentication scheme for the broker." + type = string + default = "auth_scheme" +} +variable "onboarding_resource_broker_resource_group_crn" { + description = "The cloud resource name of the resource group." + type = string + default = "resource_group_crn" +} +variable "onboarding_resource_broker_state" { + description = "The state of the broker." + type = string + default = "removed" +} +variable "onboarding_resource_broker_broker_url" { + description = "The URL associated with the broker application." + type = string + default = "broker_url" +} +variable "onboarding_resource_broker_allow_context_updates" { + description = "Whether the resource controller will call the broker for any context changes to the instance. Currently, the only context related change is an instance name update." + type = bool + default = true +} +variable "onboarding_resource_broker_catalog_type" { + description = "To enable the provisioning of your broker, set this parameter value to `service`." + type = string + default = "catalog_type" +} +variable "onboarding_resource_broker_type" { + description = "The type of the provisioning model." + type = string + default = "provision_through" +} +variable "onboarding_resource_broker_name" { + description = "The name of the broker." + type = string + default = "name" +} +variable "onboarding_resource_broker_region" { + description = "The region where the pricing plan is available." + type = string + default = "region" +} + +// Resource arguments for onboarding_catalog_deployment +variable "onboarding_catalog_deployment_product_id" { + description = "The unique ID of the product." + type = string + default = "product_id" +} +variable "onboarding_catalog_deployment_catalog_product_id" { + description = "The unique ID of this global catalog product." + type = string + default = "catalog_product_id" +} +variable "onboarding_catalog_deployment_catalog_plan_id" { + description = "The unique ID of this global catalog plan." + type = string + default = "catalog_plan_id" +} +variable "onboarding_catalog_deployment_env" { + description = "The environment to fetch this object from." + type = string + default = "env" +} +variable "onboarding_catalog_deployment_name" { + description = "The programmatic name of this deployment." + type = string + default = "name" +} +variable "onboarding_catalog_deployment_active" { + description = "Whether the service is active." + type = bool + default = true +} +variable "onboarding_catalog_deployment_disabled" { + description = "Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled." + type = bool + default = true +} +variable "onboarding_catalog_deployment_kind" { + description = "The kind of the global catalog object." + type = string + default = "deployment" +} +variable "onboarding_catalog_deployment_tags" { + description = "A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog." + type = list(string) + default = [ "tags" ] +} + +// Resource arguments for onboarding_catalog_plan +variable "onboarding_catalog_plan_product_id" { + description = "The unique ID of the product." + type = string + default = "product_id" +} +variable "onboarding_catalog_plan_catalog_product_id" { + description = "The unique ID of this global catalog product." + type = string + default = "catalog_product_id" +} +variable "onboarding_catalog_plan_env" { + description = "The environment to fetch this object from." + type = string + default = "env" +} +variable "onboarding_catalog_plan_name" { + description = "The programmatic name of this plan." + type = string + default = "name" +} +variable "onboarding_catalog_plan_active" { + description = "Whether the service is active." + type = bool + default = true +} +variable "onboarding_catalog_plan_disabled" { + description = "Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled." + type = bool + default = true +} +variable "onboarding_catalog_plan_kind" { + description = "The kind of the global catalog object." + type = string + default = "plan" +} +variable "onboarding_catalog_plan_tags" { + description = "A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog." + type = list(string) + default = [ "tags" ] +} + +// Resource arguments for onboarding_catalog_product +variable "onboarding_catalog_product_product_id" { + description = "The unique ID of the product." + type = string + default = "product_id" +} +variable "onboarding_catalog_product_env" { + description = "The environment to fetch this object from." + type = string + default = "env" +} +variable "onboarding_catalog_product_name" { + description = "The programmatic name of this product." + type = string + default = "name" +} +variable "onboarding_catalog_product_active" { + description = "Whether the service is active." + type = bool + default = true +} +variable "onboarding_catalog_product_disabled" { + description = "Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled." + type = bool + default = true +} +variable "onboarding_catalog_product_kind" { + description = "The kind of the global catalog object." + type = string + default = "service" +} +variable "onboarding_catalog_product_tags" { + description = "A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog." + type = list(string) + default = [ "tags" ] +} + +// Resource arguments for onboarding_iam_registration +variable "onboarding_iam_registration_product_id" { + description = "The unique ID of the product." + type = string + default = "product_id" +} +variable "onboarding_iam_registration_env" { + description = "The environment to fetch this object from." + type = string + default = "env" +} +variable "onboarding_iam_registration_name" { + description = "The IAM registration name, which must be the programmatic name of the product." + type = string + default = "name" +} +variable "onboarding_iam_registration_enabled" { + description = "Whether the service is enabled or disabled for IAM." + type = bool + default = true +} +variable "onboarding_iam_registration_service_type" { + description = "The type of the service." + type = string + default = "service" +} +variable "onboarding_iam_registration_additional_policy_scopes" { + description = "List of additional policy scopes." + type = list(string) + default = [ "additional_policy_scopes" ] +} +variable "onboarding_iam_registration_parent_ids" { + description = "The list of parent IDs for product access management." + type = list(string) + default = [ "parent_ids" ] +} + +// Resource arguments for onboarding_product +variable "onboarding_product_type" { + description = "The type of the product." + type = string + default = "software" +} +variable "onboarding_product_eccn_number" { + description = "The Export Control Classification Number of your product." + type = string + default = "eccn_number" +} +variable "onboarding_product_ero_class" { + description = "The ERO class of your product." + type = string + default = "ero_class" +} +variable "onboarding_product_unspsc" { + description = "The United Nations Standard Products and Services Code of your product." + type = number + default = 1.0 +} +variable "onboarding_product_tax_assessment" { + description = "The tax assessment type of your product." + type = string + default = "tax_assessment" +} + +// Resource arguments for onboarding_registration +variable "onboarding_registration_account_id" { + description = "The ID of your account." + type = string + default = "account_id" +} +variable "onboarding_registration_company_name" { + description = "The name of your company that is displayed in the IBM Cloud catalog." + type = string + default = "company_name" +} +variable "onboarding_registration_default_private_catalog_id" { + description = "The default private catalog in which products are created." + type = string + default = "default_private_catalog_id" +} +variable "onboarding_registration_provider_access_group" { + description = "The onboarding access group for your team." + type = string + default = "provider_access_group" +} diff --git a/examples/ibm-partner-center-sell/versions.tf b/examples/ibm-partner-center-sell/versions.tf new file mode 100644 index 0000000000..54c9d03e8d --- /dev/null +++ b/examples/ibm-partner-center-sell/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.0" + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + version = "1.52.0-beta0" + } + } +} diff --git a/examples/openshift-data-foundation/README.md b/examples/openshift-data-foundation/README.md index 7c09ba4aa8..2be7519a2d 100644 --- a/examples/openshift-data-foundation/README.md +++ b/examples/openshift-data-foundation/README.md @@ -6,7 +6,7 @@ OpenShift Data Foundation is a highly available storage solution that you can us If you'd like to Deploy and Manage the different configurations for ODF on a Red Hat OpenShift Cluster (VPC) head over to the [addon](https://github.com/IBM-Cloud/terraform-provider-ibm/tree/master/examples/openshift-data-foundation/addon) folder. -## Updating or replacing VPC worker nodes that use OpenShift Data Foundation +## Updating or replacing worker nodes that use OpenShift Data Foundation on VPC clusters If you'd like to update or replace the different worker nodes with ODF enabled, head over to the [vpc-worker-replace](https://github.com/IBM-Cloud/terraform-provider-ibm/tree/master/examples/openshift-data-foundation/vpc-worker-replace) folder. This inherently covers the worker replace steps of sequential cordon, drain, and replace. diff --git a/examples/openshift-data-foundation/addon/4.12.0/README.md b/examples/openshift-data-foundation/addon/4.12.0/README.md index 884e9f4ade..29ba5e821c 100644 --- a/examples/openshift-data-foundation/addon/4.12.0/README.md +++ b/examples/openshift-data-foundation/addon/4.12.0/README.md @@ -44,7 +44,7 @@ You do not have to change anything in the `ibm-odf-addon` and `ocscluster` folde To run this example on your Terminal, first download this directory i.e `examples/openshift-data-foundation/` ```bash -$ cd addon +$ cd addon/4.12.0 ``` ```bash diff --git a/examples/openshift-data-foundation/addon/4.13.0/README.md b/examples/openshift-data-foundation/addon/4.13.0/README.md index 035ae72397..5635fe7f62 100644 --- a/examples/openshift-data-foundation/addon/4.13.0/README.md +++ b/examples/openshift-data-foundation/addon/4.13.0/README.md @@ -44,7 +44,7 @@ You do not have to change anything in the `ibm-odf-addon` and `ocscluster` folde To run this example on your Terminal, first download this directory i.e `examples/openshift-data-foundation/` ```bash -$ cd addon +$ cd addon/4.13.0 ``` ```bash diff --git a/examples/openshift-data-foundation/addon/4.14.0/README.md b/examples/openshift-data-foundation/addon/4.14.0/README.md index 7fe4e508dd..38ff4dbf94 100644 --- a/examples/openshift-data-foundation/addon/4.14.0/README.md +++ b/examples/openshift-data-foundation/addon/4.14.0/README.md @@ -44,7 +44,7 @@ You do not have to change anything in the `ibm-odf-addon` and `ocscluster` folde To run this example on your Terminal, first download this directory i.e `examples/openshift-data-foundation/` ```bash -$ cd addon +$ cd addon/4.14.0 ``` ```bash diff --git a/examples/openshift-data-foundation/addon/4.15.0/README.md b/examples/openshift-data-foundation/addon/4.15.0/README.md index 93bb4cfeb1..2f80a6ab8f 100644 --- a/examples/openshift-data-foundation/addon/4.15.0/README.md +++ b/examples/openshift-data-foundation/addon/4.15.0/README.md @@ -44,7 +44,7 @@ You do not have to change anything in the `ibm-odf-addon` and `ocscluster` folde To run this example on your Terminal, first download this directory i.e `examples/openshift-data-foundation/` ```bash -$ cd addon +$ cd addon/4.15.0 ``` ```bash @@ -93,6 +93,7 @@ ocsUpgrade = "false" osdDevicePaths = null osdSize = "512Gi" osdStorageClassName = "ibmc-vpc-block-metro-10iops-tier" +workerPools = null workerNodes = null encryptionInTransit = false taintNodes = false @@ -111,6 +112,7 @@ The following variables in the `schematics.tfvars` file can be edited * numOfOsd - To scale your storage * workerNodes - To increase the number of Worker Nodes with ODF +* workerPools - To increase the number of Storage Nodes by adding more nodes using workerpool ```hcl # For CRD Management @@ -175,6 +177,7 @@ ocsUpgrade = "false" -> "true" | ignoreNoobaa | Set to true if you do not want MultiCloudGateway | `bool` | no | false | ocsUpgrade | Set to true to upgrade Ocscluster | `string` | no | false | osdDevicePaths | IDs of the disks to be used for OSD pods if using local disks or standard classic cluster | `string` | no | null +| workerPools | A list of the worker pools names where you want to deploy ODF. Either specify workerpool or workernodes to deploy ODF, if not specified ODF will deploy on all nodes | `string` | no | null | workerNodes | Provide the names of the worker nodes on which to install ODF. Leave blank to install ODF on all worker nodes | `string` | no | null | encryptionInTransit |To enable in-transit encryption. Enabling in-transit encryption does not affect the existing mapped or mounted volumes. After a volume is mapped/mounted, it retains the encryption settings that were used when it was initially mounted. To change the encryption settings for existing volumes, they must be remounted again one-by-one. | `bool` | no | false | taintNodes | Specify true to taint the selected worker nodes so that only OpenShift Data Foundation pods can run on those nodes. Use this option only if you limit ODF to a subset of nodes in your cluster. | `bool` | no | false diff --git a/examples/openshift-data-foundation/addon/4.15.0/main.tf b/examples/openshift-data-foundation/addon/4.15.0/main.tf index e9d130535d..7a8b06d6f4 100644 --- a/examples/openshift-data-foundation/addon/4.15.0/main.tf +++ b/examples/openshift-data-foundation/addon/4.15.0/main.tf @@ -1,14 +1,14 @@ resource "null_resource" "customResourceGroup" { provisioner "local-exec" { - + when = create command = "sh ./createcrd.sh" - + } provisioner "local-exec" { - + when = destroy command = "sh ./deletecrd.sh" @@ -18,7 +18,7 @@ resource "null_resource" "customResourceGroup" { null_resource.addOn ] - + } @@ -35,9 +35,9 @@ resource "null_resource" "addOn" { when = destroy command = "sh ./deleteaddon.sh" - + } - + } @@ -47,18 +47,19 @@ resource "null_resource" "updateCRD" { numOfOsd = var.numOfOsd ocsUpgrade = var.ocsUpgrade workerNodes = var.workerNodes + workerPools = var.workerPools osdDevicePaths = var.osdDevicePaths taintNodes = var.taintNodes addSingleReplicaPool = var.addSingleReplicaPool resourceProfile = var.resourceProfile enableNFS = var.enableNFS } - + provisioner "local-exec" { - + command = "sh ./updatecrd.sh" - + } depends_on = [ @@ -78,11 +79,11 @@ resource "null_resource" "upgradeODF" { provisioner "local-exec" { command = "sh ./updateodf.sh" - + } - + depends_on = [ null_resource.customResourceGroup, null_resource.addOn ] -} \ No newline at end of file +} diff --git a/examples/openshift-data-foundation/addon/4.15.0/ocscluster/main.tf b/examples/openshift-data-foundation/addon/4.15.0/ocscluster/main.tf index cf38d92459..43d6d31bf6 100644 --- a/examples/openshift-data-foundation/addon/4.15.0/ocscluster/main.tf +++ b/examples/openshift-data-foundation/addon/4.15.0/ocscluster/main.tf @@ -50,6 +50,7 @@ resource "kubernetes_manifest" "ocscluster_ocscluster_auto" { "osdDevicePaths" = var.osdDevicePaths==null ? null : split(",", var.osdDevicePaths), "osdSize" = var.osdSize, "osdStorageClassName" = var.osdStorageClassName, + "workerPools" = var.workerPools==null ? null : split(",", var.workerPools), "workerNodes" = var.workerNodes==null ? null : split(",", var.workerNodes), "encryptionInTransit" = var.encryptionInTransit, "taintNodes" = var.taintNodes, @@ -65,4 +66,4 @@ resource "kubernetes_manifest" "ocscluster_ocscluster_auto" { field_manager { force_conflicts = true } -} \ No newline at end of file +} diff --git a/examples/openshift-data-foundation/addon/4.15.0/schematics.tfvars b/examples/openshift-data-foundation/addon/4.15.0/schematics.tfvars index f86fc55992..383fd86e37 100644 --- a/examples/openshift-data-foundation/addon/4.15.0/schematics.tfvars +++ b/examples/openshift-data-foundation/addon/4.15.0/schematics.tfvars @@ -25,6 +25,7 @@ ocsUpgrade = "false" osdDevicePaths = null osdSize = "512Gi" osdStorageClassName = "ibmc-vpc-block-metro-10iops-tier" +workerPools = null workerNodes = null encryptionInTransit = false taintNodes = false @@ -33,4 +34,4 @@ prepareForDisasterRecovery = false disableNoobaaLB = false useCephRBDAsDefaultStorageClass = false enableNFS = false -resourceProfile = "balanced" \ No newline at end of file +resourceProfile = "balanced" diff --git a/examples/openshift-data-foundation/addon/4.15.0/variables.tf b/examples/openshift-data-foundation/addon/4.15.0/variables.tf index f1ce8fc71d..648d9b25af 100644 --- a/examples/openshift-data-foundation/addon/4.15.0/variables.tf +++ b/examples/openshift-data-foundation/addon/4.15.0/variables.tf @@ -2,7 +2,7 @@ variable "ibmcloud_api_key" { type = string description = "IBM Cloud API Key" - + } variable "cluster" { @@ -15,7 +15,7 @@ variable "region" { type = string description = "Enter Cluster Region" - + } variable "odfVersion" { @@ -23,7 +23,7 @@ variable "odfVersion" { type = string default = "4.15.0" description = "Provide the ODF Version you wish to install on your cluster" - + } variable "numOfOsd" { @@ -31,7 +31,7 @@ variable "numOfOsd" { type = string default = "1" description = "Number of Osd" - + } variable "osdDevicePaths" { @@ -48,7 +48,7 @@ variable "ocsUpgrade" { default = "false" description = "Set to true to upgrade Ocscluster" - + } variable "clusterEncryption" { @@ -62,14 +62,14 @@ variable "billingType" { type = string default = "advanced" description = "Choose between advanced and essentials" - + } variable "ignoreNoobaa" { type = bool default = false description = "Set to true if you do not want MultiCloudGateway" - + } variable "osdSize" { @@ -82,7 +82,7 @@ variable "osdStorageClassName" { type = string default = "ibmc-vpc-block-metro-10iops-tier" description = "Enter the storage class to be used to provision block volumes for Object Storage Daemon (OSD) pods." - + } variable "autoDiscoverDevices" { @@ -98,7 +98,7 @@ variable "hpcsEncryption" { type = string default = "false" description = "Set to true to enable HPCS Encryption" - + } variable "hpcsServiceName" { @@ -115,6 +115,13 @@ variable "hpcsSecretName" { description = "Please provide the HPCS secret name" } +variable "workerPools" { + + type = string + default = null + description = "A list of the worker pool names where you want to deploy ODF. Either specify workerpool or workernodes to deploy ODF, if not specified ODF will deploy on all nodes" +} + variable "workerNodes" { type = string @@ -148,7 +155,7 @@ variable "encryptionInTransit" { type = bool default = false description = "Enter true to enable in-transit encryption. Enabling in-transit encryption does not affect the existing mapped or mounted volumes. After a volume is mapped/mounted, it retains the encryption settings that were used when it was initially mounted. To change the encryption settings for existing volumes, they must be remounted again one-by-one." - + } variable "taintNodes" { @@ -204,4 +211,4 @@ variable "resourceProfile" { default = "balanced" description = "Provides an option to choose a resource profile based on the availability of resources during deployment. Choose between lean, balanced and performance." -} \ No newline at end of file +} diff --git a/examples/openshift-data-foundation/satellite/odf-local/4.13/README.md b/examples/openshift-data-foundation/satellite/odf-local/4.13/README.md index 3cec5f0709..3593da1632 100644 --- a/examples/openshift-data-foundation/satellite/odf-local/4.13/README.md +++ b/examples/openshift-data-foundation/satellite/odf-local/4.13/README.md @@ -108,7 +108,11 @@ In this example we set the `updateConfigRevision` parameter to true in order to You could also use `updateAssignments` to directly update the storage configuration's assignments, but if you have a dependent `storage_assignment` resource, it's lifecycle will be affected. It it recommended to use this parameter when you've only defined the `storage_configuration` resource. ### Upgrade of ODF +**Step 1:** +Follow the [Satellite worker upgrade documentation](https://cloud.ibm.com/docs/satellite?topic=satellite-sat-storage-odf-update&interface=ui) step 1 to step 7 to perform worker upgrade. +**Step 2:** +Follow the below steps to upgrade ODF to next version. The following variables in the `input.tfvars` file should be changed in order to upgrade the ODF add-on and the Ocscluster CRD. * storageTemplateVersion - Specify the version you wish to upgrade to diff --git a/examples/openshift-data-foundation/satellite/odf-local/4.14/README.md b/examples/openshift-data-foundation/satellite/odf-local/4.14/README.md index 8efbc71266..b91b3236a4 100644 --- a/examples/openshift-data-foundation/satellite/odf-local/4.14/README.md +++ b/examples/openshift-data-foundation/satellite/odf-local/4.14/README.md @@ -115,6 +115,11 @@ You could also use `updateAssignments` to directly update the storage configurat ### Upgrade of ODF +**Step 1:** +Follow the [Satellite worker upgrade documentation](https://cloud.ibm.com/docs/satellite?topic=satellite-sat-storage-odf-update&interface=ui) step 1 to step 7 to perform worker upgrade. + +**Step 2:** +Follow the below steps to upgrade ODF to next version. The following variables in the `input.tfvars` file should be changed in order to upgrade the ODF add-on and the Ocscluster CRD. * storageTemplateVersion - Specify the version you wish to upgrade to diff --git a/examples/openshift-data-foundation/satellite/odf-local/4.15/README.md b/examples/openshift-data-foundation/satellite/odf-local/4.15/README.md index 6efecedf23..c1c97b72c2 100644 --- a/examples/openshift-data-foundation/satellite/odf-local/4.15/README.md +++ b/examples/openshift-data-foundation/satellite/odf-local/4.15/README.md @@ -40,7 +40,7 @@ https://cloud.ibm.com/docs/schematics?topic=schematics-get-started-terraform The default input.tfvars is given below, the user should just change the value of the parameters in accorandance to their requirment. ```hcl -# Common for both storage configuration and assignment +# Common for both storage configuration and assignment ibmcloud_api_key = "" location = "" #Location of your storage configuration and assignment configName = "" #Name of your storage configuration @@ -66,6 +66,7 @@ ibmCosLocation = null ignoreNoobaa = false numOfOsd = "1" ocsUpgrade = "false" +workerPools = null workerNodes = null encryptionInTransit = false disableNoobaaLB = false @@ -103,11 +104,13 @@ The following variables in the `input.tfvars` file can be edited * numOfOsd - To scale your storage * workerNodes - To increase the number of Worker Nodes with ODF +* workerPools - To increase the number of Worker Nodes with ODF by including new workerpools ```hcl numOfOsd = "1" -> "2" workerNodes = null -> "worker_1_ID,worker_2_ID" updateConfigRevision = true +workerPools = "workerpool_1" -> "workerpool_1,workerpool_2" ``` In this example we set the `updateConfigRevision` parameter to true in order to update our storage assignment with the latest configuration revision i.e the OcsCluster CRD is updated with the latest changes. @@ -115,6 +118,11 @@ You could also use `updateAssignments` to directly update the storage configurat ### Upgrade of ODF +**Step 1:** +Follow the [Satellite worker upgrade documentation](https://cloud.ibm.com/docs/satellite?topic=satellite-sat-storage-odf-update&interface=ui) step 1 to step 7 to perform worker upgrade. + +**Step 2:** +Follow the below steps to upgrade ODF to next version. The following variables in the `input.tfvars` file should be changed in order to upgrade the ODF add-on and the Ocscluster CRD. * storageTemplateVersion - Specify the version you wish to upgrade to @@ -170,7 +178,8 @@ Note this operation deletes the existing configuration and it's respective assig | ignoreNoobaa | Set to true if you do not want MultiCloudGateway | `bool` | no | false | ocsUpgrade | Set to true to upgrade Ocscluster | `string` | no | false | osdDevicePaths | IDs of the disks to be used for OSD pods if using local disks or standard classic cluster | `string` | no | null -| workerNodes | Provide the names of the worker nodes on which to install ODF. Leave blank to install ODF on all worker nodes | `string` | no | null +| workerPools | Provide the names/ID of the workerpool on which to install ODF. Specify either workerpool or worker nodes to select storage nodes. If none of them specified, ODF will install on all workers | `string` | no | null +| workerNodes | Provide the names of the worker nodes on which to install ODF. | `string` | no | null | encryptionInTransit |To enable in-transit encryption. Enabling in-transit encryption does not affect the existing mapped or mounted volumes. After a volume is mapped/mounted, it retains the encryption settings that were used when it was initially mounted. To change the encryption settings for existing volumes, they must be remounted again one-by-one. | `bool` | no | false | taintNodes | Specify true to taint the selected worker nodes so that only OpenShift Data Foundation pods can run on those nodes. Use this option only if you limit ODF to a subset of nodes in your cluster. | `bool` | no | false | addSingleReplicaPool | Specify true to create a single replica pool without data replication, increasing the risk of data loss, data corruption, and potential system instability. | `bool` | no | false @@ -185,5 +194,6 @@ Refer - https://cloud.ibm.com/docs/satellite?topic=satellite-storage-odf-local&i ## Note * Users should only change the values of the variables within quotes, variables should be left untouched with the default values if they are not set. +* `workerPools` takes a string containing comma separated values of the names of the workerpool you wish to enable ODF on. Specify either workerpool or worker nodes to select storage nodes. If none of them specified, ODF will install on all workers * `workerNodes` takes a string containing comma separated values of the names of the worker nodes you wish to enable ODF on. * During ODF Storage Template Update, it is recommended to delete all terraform related assignments before handed, as their lifecycle will be affected, during update new storage assignments are made back internally with new UUIDs. diff --git a/examples/openshift-data-foundation/satellite/odf-local/4.15/input.tfvars b/examples/openshift-data-foundation/satellite/odf-local/4.15/input.tfvars index 12695afe69..a303280732 100644 --- a/examples/openshift-data-foundation/satellite/odf-local/4.15/input.tfvars +++ b/examples/openshift-data-foundation/satellite/odf-local/4.15/input.tfvars @@ -2,7 +2,7 @@ ## Please change according to your configuratiom ## -# Common for both storage configuration and assignment +# Common for both storage configuration and assignment ibmcloud_api_key = "" location = "" #Location of your storage configuration and assignment configName = "" #Name of your storage configuration @@ -30,6 +30,7 @@ ibmCosLocation = null ignoreNoobaa = false numOfOsd = "1" ocsUpgrade = "false" +workerPools = null workerNodes = null encryptionInTransit = false disableNoobaaLB = false @@ -56,4 +57,4 @@ updateConfigRevision = false ## NOTE ## # The following variables will cause issues to your storage assignment lifecycle, so please use only with a storage configuration resource. deleteAssignments = false -updateAssignments = false \ No newline at end of file +updateAssignments = false diff --git a/examples/openshift-data-foundation/satellite/odf-local/4.15/main.tf b/examples/openshift-data-foundation/satellite/odf-local/4.15/main.tf index b7d1984fb8..f8bf9dd51b 100644 --- a/examples/openshift-data-foundation/satellite/odf-local/4.15/main.tf +++ b/examples/openshift-data-foundation/satellite/odf-local/4.15/main.tf @@ -35,6 +35,7 @@ resource "ibm_satellite_storage_configuration" "storage_configuration" { "perform-cleanup"= var.performCleanup, "disable-noobaa-LB"= var.disableNoobaaLB, "encryption-intransit"= var.encryptionInTransit, + "worker-pools"=var.workerPools, "worker-nodes"= var.workerNodes, "add-single-replica-pool" = var.addSingleReplicaPool, "taint-nodes" = var.taintNodes, diff --git a/examples/openshift-data-foundation/satellite/odf-local/4.15/variables.tf b/examples/openshift-data-foundation/satellite/odf-local/4.15/variables.tf index 8c72dd6298..c96922ea01 100644 --- a/examples/openshift-data-foundation/satellite/odf-local/4.15/variables.tf +++ b/examples/openshift-data-foundation/satellite/odf-local/4.15/variables.tf @@ -129,7 +129,7 @@ variable "osdStorageClassName" { type = string default = "ibmc-vpc-block-metro-10iops-tier" description = "Enter the storage class to be used to provision block volumes for Object Storage Daemon (OSD) pods." - + } variable "autoDiscoverDevices" { @@ -156,10 +156,16 @@ variable "kmsSecretName" { description = "Please provide the HPCS secret name" } +variable "workerPools" { + type = string + default = null + description = "Provide the names/ID of the workerpool on which to install ODF. Specify either workerpool or worker nodes to select storage nodes. If none of them specified, ODF will install on all workers." +} + variable "workerNodes" { type = string default = null - description = "Provide the names of the worker nodes on which to install ODF. Leave blank to install ODF on all worker nodes." + description = "Provide the names of the worker nodes on which to install ODF." } variable "kmsInstanceId" { @@ -260,4 +266,4 @@ variable "resourceProfile" { default = "balanced" description = "Provides an option to choose a resource profile based on the availability of resources during deployment. Choose between lean, balanced and performance." -} \ No newline at end of file +} diff --git a/examples/openshift-data-foundation/satellite/odf-remote/4.13/README.md b/examples/openshift-data-foundation/satellite/odf-remote/4.13/README.md index 602b9327c8..61711b7838 100644 --- a/examples/openshift-data-foundation/satellite/odf-remote/4.13/README.md +++ b/examples/openshift-data-foundation/satellite/odf-remote/4.13/README.md @@ -109,6 +109,11 @@ You could also use `updateAssignments` to directly update the storage configurat ### Upgrade of ODF +**Step 1:** +Follow the [Satellite worker upgrade documentation](https://cloud.ibm.com/docs/satellite?topic=satellite-sat-storage-odf-update&interface=ui) step 1 to step 7 to perform worker upgrade. + +**Step 2:** +Follow the below steps to upgrade ODF to next version. The following variables in the `input.tfvars` file should be changed in order to upgrade the ODF add-on and the Ocscluster CRD. * storageTemplateVersion - Specify the version you wish to upgrade to diff --git a/examples/openshift-data-foundation/satellite/odf-remote/4.14/README.md b/examples/openshift-data-foundation/satellite/odf-remote/4.14/README.md index 1a07c9e670..72ab614ee9 100644 --- a/examples/openshift-data-foundation/satellite/odf-remote/4.14/README.md +++ b/examples/openshift-data-foundation/satellite/odf-remote/4.14/README.md @@ -115,6 +115,11 @@ You could also use `updateAssignments` to directly update the storage configurat ### Upgrade of ODF +**Step 1:** +Follow the [Satellite worker upgrade documentation](https://cloud.ibm.com/docs/satellite?topic=satellite-sat-storage-odf-update&interface=ui) step 1 to step 7 to perform worker upgrade. + +**Step 2:** +Follow the below steps to upgrade ODF to next version. The following variables in the `input.tfvars` file should be changed in order to upgrade the ODF add-on and the Ocscluster CRD. * storageTemplateVersion - Specify the version you wish to upgrade to diff --git a/examples/openshift-data-foundation/satellite/odf-remote/4.15/README.md b/examples/openshift-data-foundation/satellite/odf-remote/4.15/README.md index ea43906b41..742d0c469d 100644 --- a/examples/openshift-data-foundation/satellite/odf-remote/4.15/README.md +++ b/examples/openshift-data-foundation/satellite/odf-remote/4.15/README.md @@ -40,7 +40,7 @@ https://cloud.ibm.com/docs/schematics?topic=schematics-get-started-terraform The default input.tfvars is given below, the user should just change the value of the parameters in accorandance to their requirment. ```hcl -# Common for both storage configuration and assignment +# Common for both storage configuration and assignment ibmcloud_api_key = "" location = "" #Location of your storage configuration and assignment configName = "" #Name of your storage configuration @@ -66,6 +66,7 @@ numOfOsd = "1" ocsUpgrade = "false" osdSize = "512Gi" osdStorageClassName = "ibmc-vpc-block-metro-5iops-tier" +workerPools = null workerNodes = null encryptionInTransit = false disableNoobaaLB = false @@ -103,11 +104,13 @@ The following variables in the `input.tfvars` file can be edited * numOfOsd - To scale your storage * workerNodes - To increase the number of Worker Nodes with ODF +* workerPools - To increase the number of Worker Nodes with ODF by including new workerpools ```hcl numOfOsd = "1" -> "2" workerNodes = null -> "worker_1_ID,worker_2_ID" updateConfigRevision = true +workerPools = "workerpool_1" -> "workerpool_1,workerpool_2" ``` In this example we set the `updateConfigRevision` parameter to true in order to update our storage assignment with the latest configuration revision i.e the OcsCluster CRD is updated with the latest changes. @@ -115,6 +118,11 @@ You could also use `updateAssignments` to directly update the storage configurat ### Upgrade of ODF +**Step 1:** +Follow the [worker upgrade documentation](https://cloud.ibm.com/docs/satellite?topic=satellite-sat-storage-odf-update&interface=ui) from step 1 to step 7 to perform worker upgrade. + +**Step 2:** +Follow the below steps to upgrade ODF to next version. The following variables in the `input.tfvars` file should be changed in order to upgrade the ODF add-on and the Ocscluster CRD. * storageTemplateVersion - Specify the version you wish to upgrade to @@ -170,6 +178,7 @@ Note this operation deletes the existing configuration and it's respective assig | kmsTokenUrl | The HPCS Token URL | `string` | no | null | ignoreNoobaa | Set to true if you do not want MultiCloudGateway | `bool` | no | false | ocsUpgrade | Set to true to upgrade Ocscluster | `string` | no | false +| workerPools | Provide the names/ID of the workerpool on which to install ODF. Specify either workerpool or worker nodes to select storage nodes. If none of them specified, ODF will install on all workers | `string` | no | null | workerNodes | Provide the names of the worker nodes on which to install ODF. Leave blank to install ODF on all worker nodes | `string` | no | null | encryptionInTransit |To enable in-transit encryption. Enabling in-transit encryption does not affect the existing mapped or mounted volumes. After a volume is mapped/mounted, it retains the encryption settings that were used when it was initially mounted. To change the encryption settings for existing volumes, they must be remounted again one-by-one. | `bool` | no | false | taintNodes | Specify true to taint the selected worker nodes so that only OpenShift Data Foundation pods can run on those nodes. Use this option only if you limit ODF to a subset of nodes in your cluster. | `bool` | no | false @@ -185,5 +194,6 @@ Refer - https://cloud.ibm.com/docs/satellite?topic=satellite-storage-odf-remote& ## Note * Users should only change the values of the variables within quotes, variables should be left untouched with the default values if they are not set. +* `workerPools` takes a string containing comma separated values of the names of the workerpool you wish to enable ODF on. Specify either workerpool or worker nodes to select storage nodes. If none of them specified, ODF will install on all workers * `workerNodes` takes a string containing comma separated values of the names of the worker nodes you wish to enable ODF on. * During ODF Storage Template Update, it is recommended to delete all terraform related assignments before handed, as their lifecycle will be affected, during update new storage assignments are made back internally with new UUIDs. diff --git a/examples/openshift-data-foundation/satellite/odf-remote/4.15/input.tfvars b/examples/openshift-data-foundation/satellite/odf-remote/4.15/input.tfvars index 1f4cf9ea29..b12d17ef5c 100644 --- a/examples/openshift-data-foundation/satellite/odf-remote/4.15/input.tfvars +++ b/examples/openshift-data-foundation/satellite/odf-remote/4.15/input.tfvars @@ -2,7 +2,7 @@ ## Please change according to your configuratiom ## -# Common for both storage configuration and assignment +# Common for both storage configuration and assignment ibmcloud_api_key = "" location = "" #Location of your storage configuration and assignment configName = "" #Name of your storage configuration @@ -30,6 +30,7 @@ numOfOsd = "1" ocsUpgrade = "false" osdSize = "512Gi" osdStorageClassName = "ibmc-vpc-block-metro-5iops-tier" +workerPools = null workerNodes = null encryptionInTransit = false disableNoobaaLB = false @@ -56,4 +57,4 @@ updateConfigRevision = false ## NOTE ## # The following variables will cause issues to your storage assignment lifecycle, so please use only with a storage configuration resource. deleteAssignments = false -updateAssignments = false \ No newline at end of file +updateAssignments = false diff --git a/examples/openshift-data-foundation/satellite/odf-remote/4.15/main.tf b/examples/openshift-data-foundation/satellite/odf-remote/4.15/main.tf index 9b0598daee..169e9aab80 100644 --- a/examples/openshift-data-foundation/satellite/odf-remote/4.15/main.tf +++ b/examples/openshift-data-foundation/satellite/odf-remote/4.15/main.tf @@ -35,6 +35,7 @@ resource "ibm_satellite_storage_configuration" "storage_configuration" { "perform-cleanup"= var.performCleanup, "disable-noobaa-LB"= var.disableNoobaaLB, "encryption-intransit"= var.encryptionInTransit, + "worker-pools"=var.workerPools, "worker-nodes"= var.workerNodes, "add-single-replica-pool" = var.addSingleReplicaPool, "taint-nodes" = var.taintNodes, diff --git a/examples/openshift-data-foundation/satellite/odf-remote/4.15/variables.tf b/examples/openshift-data-foundation/satellite/odf-remote/4.15/variables.tf index 8c72dd6298..26e263a282 100644 --- a/examples/openshift-data-foundation/satellite/odf-remote/4.15/variables.tf +++ b/examples/openshift-data-foundation/satellite/odf-remote/4.15/variables.tf @@ -129,7 +129,7 @@ variable "osdStorageClassName" { type = string default = "ibmc-vpc-block-metro-10iops-tier" description = "Enter the storage class to be used to provision block volumes for Object Storage Daemon (OSD) pods." - + } variable "autoDiscoverDevices" { @@ -156,6 +156,12 @@ variable "kmsSecretName" { description = "Please provide the HPCS secret name" } +variable "workerPools" { + type = string + default = null + description = "Provide the names/ID of the workerpool on which to install ODF. Specify either workerpool or worker nodes to select storage nodes. If none of them specified, ODF will install on all workers." +} + variable "workerNodes" { type = string default = null @@ -260,4 +266,4 @@ variable "resourceProfile" { default = "balanced" description = "Provides an option to choose a resource profile based on the availability of resources during deployment. Choose between lean, balanced and performance." -} \ No newline at end of file +} diff --git a/examples/openshift-data-foundation/vpc-worker-replace/README.md b/examples/openshift-data-foundation/vpc-worker-replace/README.md index 3181dbb8c2..0e7e8109d7 100644 --- a/examples/openshift-data-foundation/vpc-worker-replace/README.md +++ b/examples/openshift-data-foundation/vpc-worker-replace/README.md @@ -1,4 +1,4 @@ -# OpenShift-Data-Foundation VPC Worker Replace +# OpenShift-Data-Foundation VPC ROKS Worker Replace This example shows how to replace & update the Kubernetes VPC Gen-2 worker installed with Openshift-Data-Foundation to the latest patch in the specified cluster. diff --git a/go.mod b/go.mod index 9e3a441b9f..2effbbf28c 100644 --- a/go.mod +++ b/go.mod @@ -1,39 +1,45 @@ module github.com/IBM-Cloud/terraform-provider-ibm -go 1.22.2 +go 1.22.4 -toolchain go1.22.3 +toolchain go1.22.5 require ( - github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240216115622-a311507b4b5b + github.com/IBM-Cloud/bluemix-go v0.0.0-20240719075425-078fcb3a55be + github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240725064144-454a2ae23113 github.com/IBM-Cloud/power-go-client v1.7.0 github.com/IBM/apigateway-go-sdk v0.0.0-20210714141226-a5d5d49caaca github.com/IBM/appconfiguration-go-admin-sdk v0.3.0 github.com/IBM/appid-management-go-sdk v0.0.0-20210908164609-dd0e0eaf732f github.com/IBM/cloud-databases-go-sdk v0.7.0 - github.com/IBM/cloudant-go-sdk v0.0.43 + github.com/IBM/cloudant-go-sdk v0.8.0 github.com/IBM/code-engine-go-sdk v0.0.0-20240126185534-a6e054aa01ed github.com/IBM/container-registry-go-sdk v1.1.0 - github.com/IBM/continuous-delivery-go-sdk v1.5.0 - github.com/IBM/event-notifications-go-admin-sdk v0.6.1 + github.com/IBM/continuous-delivery-go-sdk v1.6.0 + github.com/IBM/event-notifications-go-admin-sdk v0.8.0 github.com/IBM/eventstreams-go-sdk v1.4.0 + github.com/IBM/go-sdk-core v1.1.0 github.com/IBM/go-sdk-core/v3 v3.2.4 github.com/IBM/go-sdk-core/v5 v5.17.4 github.com/IBM/ibm-cos-sdk-go v1.10.3 github.com/IBM/ibm-cos-sdk-go-config/v2 v2.1.0 github.com/IBM/ibm-hpcs-tke-sdk v0.0.0-20211109141421-a4b61b05f7d1 github.com/IBM/ibm-hpcs-uko-sdk v0.0.20-beta - github.com/IBM/keyprotect-go-client v0.14.0 + github.com/IBM/keyprotect-go-client v0.15.1 github.com/IBM/logs-go-sdk v0.3.0 - github.com/IBM/networking-go-sdk v0.47.1 - github.com/IBM/platform-services-go-sdk v0.64.3 + github.com/IBM/logs-router-go-sdk v1.0.3 + github.com/IBM/mqcloud-go-sdk v0.1.0 + github.com/IBM/networking-go-sdk v0.49.0 + github.com/IBM/platform-services-go-sdk v0.67.0 github.com/IBM/project-go-sdk v0.3.5 github.com/IBM/push-notifications-go-sdk v0.0.0-20210310100607-5790b96c47f5 - github.com/IBM/scc-go-sdk/v5 v5.1.6 + github.com/IBM/sarama v1.41.2 + github.com/IBM/scc-go-sdk/v5 v5.4.1 github.com/IBM/schematics-go-sdk v0.2.3 - github.com/IBM/secrets-manager-go-sdk/v2 v2.0.4 + github.com/IBM/secrets-manager-go-sdk/v2 v2.0.5 + github.com/IBM/vmware-go-sdk v0.1.2 github.com/IBM/vpc-beta-go-sdk v0.6.0 - github.com/IBM/vpc-go-sdk v0.53.0 + github.com/IBM/vpc-go-sdk v0.57.0 github.com/ScaleFT/sshkeys v0.0.0-20200327173127-6142f742bca5 github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 github.com/akamai/AkamaiOPEN-edgegrid-golang/v5 v5.0.0 @@ -55,21 +61,13 @@ require ( github.com/pkg/errors v0.9.1 github.com/rook/rook v1.11.4 github.com/softlayer/softlayer-go v1.0.3 - golang.org/x/crypto v0.22.0 + github.com/stretchr/testify v1.9.0 + golang.org/x/crypto v0.25.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools v2.2.0+incompatible k8s.io/api v0.26.3 k8s.io/apimachinery v0.26.3 k8s.io/client-go v0.26.1 -) - -require ( - github.com/IBM-Cloud/bluemix-go v0.0.0-20240423071914-9e96525baef4 - github.com/IBM/go-sdk-core v1.1.0 - github.com/IBM/mqcloud-go-sdk v0.1.0 - github.com/IBM/sarama v1.41.2 - github.com/IBM/vmware-go-sdk v0.1.2 - github.com/stretchr/testify v1.9.0 k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 sigs.k8s.io/controller-runtime v0.14.1 ) @@ -120,7 +118,7 @@ require ( github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.19.0 // indirect + github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -207,16 +205,16 @@ require ( github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/zclconf/go-cty v1.14.1 // indirect - go.mongodb.org/mongo-driver v1.15.0 // indirect + go.mongodb.org/mongo-driver v1.16.0 // indirect go.opentelemetry.io/otel v1.14.0 // indirect go.opentelemetry.io/otel/trace v1.14.0 // indirect go.uber.org/ratelimit v0.2.0 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.24.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/term v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/term v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.3.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index f689b48182..c3a7916418 100644 --- a/go.sum +++ b/go.sum @@ -113,10 +113,10 @@ github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.4.4/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/IBM-Cloud/bluemix-go v0.0.0-20240423071914-9e96525baef4 h1:43l8CU5cW4pOea10+jWtqRJj/4F4Ghfn6Oc82jB9RhM= -github.com/IBM-Cloud/bluemix-go v0.0.0-20240423071914-9e96525baef4/go.mod h1:/7hMjdZA6fEpd/dQAOEABxKEwN0t72P3PlpEDu0Y7bE= -github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240216115622-a311507b4b5b h1:Wnq0BuprazpP41+nQlRpxpmAs8+8jyOqU50KrvFdJQ4= -github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240216115622-a311507b4b5b/go.mod h1:xUQL9SGAjoZFd4GNjrjjtEpjpkgU7RFXRyHesbKTjiY= +github.com/IBM-Cloud/bluemix-go v0.0.0-20240719075425-078fcb3a55be h1:USOcBHkYQ4o/ccoEvoHinrba8NQthLJpFXnAoBY+MI4= +github.com/IBM-Cloud/bluemix-go v0.0.0-20240719075425-078fcb3a55be/go.mod h1:/7hMjdZA6fEpd/dQAOEABxKEwN0t72P3PlpEDu0Y7bE= +github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240725064144-454a2ae23113 h1:f2Erqfea1dKpaTFagTJM6W/wnD3JGq/Vn9URh8nuRwk= +github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240725064144-454a2ae23113/go.mod h1:xUQL9SGAjoZFd4GNjrjjtEpjpkgU7RFXRyHesbKTjiY= github.com/IBM-Cloud/ibm-cloud-cli-sdk v0.5.3/go.mod h1:RiUvKuHKTBmBApDMUQzBL14pQUGKcx/IioKQPIcRQjs= github.com/IBM-Cloud/power-go-client v1.7.0 h1:/GuGwPMTKoCZACfnwt7b6wKr4v32q1VO1AMFGNETRN4= github.com/IBM-Cloud/power-go-client v1.7.0/go.mod h1:9izycYAmNQ+NAdVPXDC3fHYxqWLjlR2YiwqKYveMv5Y= @@ -130,16 +130,16 @@ github.com/IBM/appid-management-go-sdk v0.0.0-20210908164609-dd0e0eaf732f h1:4c1 github.com/IBM/appid-management-go-sdk v0.0.0-20210908164609-dd0e0eaf732f/go.mod h1:d22kTYY7RYBWcQlZpqrSdshpB/lJ16viWS5Sbjtlc8s= github.com/IBM/cloud-databases-go-sdk v0.7.0 h1:prvLebKD1kcIk81D6yRhOr/TWp1VQJGLhGAasQr7RtA= github.com/IBM/cloud-databases-go-sdk v0.7.0/go.mod h1:JYucI1PdwqbAd8XGdDAchxzxRP7bxOh1zUnseovHKsc= -github.com/IBM/cloudant-go-sdk v0.0.43 h1:YxTy4RpAEezX32YIWnds76hrBREmO4u6IkBz1WylNuQ= -github.com/IBM/cloudant-go-sdk v0.0.43/go.mod h1:WeYrJPaHTw19943ndWnVfwMIlZ5z0XUM2uEXNBrwZ1M= +github.com/IBM/cloudant-go-sdk v0.8.0 h1:XzaqZFy5fm1Q9+iK52X5zRW39SHaahT9pf5SRgVTsTY= +github.com/IBM/cloudant-go-sdk v0.8.0/go.mod h1:zDGBs8ideVtn9MehXbIQNI3852B68BsMtKJvq3iPn/Q= github.com/IBM/code-engine-go-sdk v0.0.0-20240126185534-a6e054aa01ed h1:X0VrZW5ulbqxbOmy5JoZcH0A+tw80k0/ZmRZz1NqogM= github.com/IBM/code-engine-go-sdk v0.0.0-20240126185534-a6e054aa01ed/go.mod h1:m4pD/58c6NVzlAFkN3XCYXpmDFmUyTG31ivLy/loyHQ= github.com/IBM/container-registry-go-sdk v1.1.0 h1:sYyknIod8R4RJZQqAheiduP6wbSTphE9Ag8ho28yXjc= github.com/IBM/container-registry-go-sdk v1.1.0/go.mod h1:4TwsCnQtVfZ4Vkapy/KPvQBKFc3VOyUZYkwRU4FTPrs= -github.com/IBM/continuous-delivery-go-sdk v1.5.0 h1:FHSRruNt9WK7SavpIVuV6N+xll90UgZsuQjZvQ+slB4= -github.com/IBM/continuous-delivery-go-sdk v1.5.0/go.mod h1:nZdKUnubXNLo+zo28R4Rd+TGDqiJ/xoE8WO/A3kLw1E= -github.com/IBM/event-notifications-go-admin-sdk v0.6.1 h1:85gB9evVX8AmNyd4Fh1O2G/0mgpt2HIQpyeWOoftEb4= -github.com/IBM/event-notifications-go-admin-sdk v0.6.1/go.mod h1:xRsMCxmPLXvmmWEXF8rshZlZgMrllPSiT9MBi4+Q6cs= +github.com/IBM/continuous-delivery-go-sdk v1.6.0 h1:eAL/jIWHrDFlWDF+Qd9Y5UN99Pr5Mjd/H/bvTbXUbz4= +github.com/IBM/continuous-delivery-go-sdk v1.6.0/go.mod h1:nZdKUnubXNLo+zo28R4Rd+TGDqiJ/xoE8WO/A3kLw1E= +github.com/IBM/event-notifications-go-admin-sdk v0.8.0 h1:xk2CYTayQtKi6LSgGGFRxFJfWUxyM5SY8Rs64ducAhw= +github.com/IBM/event-notifications-go-admin-sdk v0.8.0/go.mod h1:OByvqfrNVxs7G6ggv8pwQCEVw10/TBJCLh7NM3z707w= github.com/IBM/eventstreams-go-sdk v1.4.0 h1:yS/Ns29sBOe8W2tynQmz9HTKqQZ0ckse4Py5Oy/F2rM= github.com/IBM/eventstreams-go-sdk v1.4.0/go.mod h1:2tuAxaYLctfqfr5jvyqSrxxEQGMwYPm3yJGWSj85YVQ= github.com/IBM/go-sdk-core v1.1.0 h1:pV73lZqr9r1xKb3h08c1uNG3AphwoV5KzUzhS+pfEqY= @@ -150,7 +150,6 @@ github.com/IBM/go-sdk-core/v5 v5.0.0/go.mod h1:vyNdbFujJtdTj9HbihtvKwwS3k/GKSKpO github.com/IBM/go-sdk-core/v5 v5.5.1/go.mod h1:Sn+z+qTDREQvCr+UFa22TqqfXNxx3o723y8GsfLV8e0= github.com/IBM/go-sdk-core/v5 v5.6.3/go.mod h1:tt/B9rxLkRtglE7pvqLuYikgCXaZFL3btdruJaoUeek= github.com/IBM/go-sdk-core/v5 v5.7.0/go.mod h1:+YbdhrjCHC84ls4MeBp+Hj4NZCni+tDAc0XQUqRO9Jc= -github.com/IBM/go-sdk-core/v5 v5.9.2/go.mod h1:YlOwV9LeuclmT/qi/LAK2AsobbAP42veV0j68/rlZsE= github.com/IBM/go-sdk-core/v5 v5.9.5/go.mod h1:YlOwV9LeuclmT/qi/LAK2AsobbAP42veV0j68/rlZsE= github.com/IBM/go-sdk-core/v5 v5.10.2/go.mod h1:WZPFasUzsKab/2mzt29xPcfruSk5js2ywAPwW4VJjdI= github.com/IBM/go-sdk-core/v5 v5.17.4 h1:VGb9+mRrnS2HpHZFM5hy4J6ppIWnwNrw0G+tLSgcJLc= @@ -164,34 +163,36 @@ github.com/IBM/ibm-hpcs-tke-sdk v0.0.0-20211109141421-a4b61b05f7d1/go.mod h1:M2J github.com/IBM/ibm-hpcs-uko-sdk v0.0.20-beta h1:P1fdIfKsD9xvJQ5MHIEztPS9yfNf9x+VDTamaYcmqcs= github.com/IBM/ibm-hpcs-uko-sdk v0.0.20-beta/go.mod h1:MLVNHMYoKsvovJZ4v1gQCpIYtRDHTtoIHK6XztDZGsU= github.com/IBM/keyprotect-go-client v0.5.1/go.mod h1:5TwDM/4FRJq1ZOlwQL1xFahLWQ3TveR88VmL1u3njyI= -github.com/IBM/keyprotect-go-client v0.14.0 h1:GqgK3BdczA/w7+B1RxEPLya0w9S/ZXi5YWKAxdW8vHQ= -github.com/IBM/keyprotect-go-client v0.14.0/go.mod h1:cAt714Vnwnd03mmkBHHSJlDNRVthdRmJB6RePd4/B8Q= +github.com/IBM/keyprotect-go-client v0.15.1 h1:m4qzqF5zOumRxKZ8s7vtK7A/UV/D278L8xpRG+WgT0s= +github.com/IBM/keyprotect-go-client v0.15.1/go.mod h1:asXtHwL/4uCHA221Vd/7SkXEi2pcRHDzPyyksc1DthE= github.com/IBM/logs-go-sdk v0.3.0 h1:FHzTCCMyp9DvQGXgkppzcOPywC4ggt7x8xu0MR5h8xI= github.com/IBM/logs-go-sdk v0.3.0/go.mod h1:yv/GCXC4/p+MZEeXl4xjZAOMvDAVRwu61WyHZFKFXQM= +github.com/IBM/logs-router-go-sdk v1.0.3 h1:VO64OpANNouxS/0kvUeBpENKWxYx3TYnoNzW8OycMb0= +github.com/IBM/logs-router-go-sdk v1.0.3/go.mod h1:tCN2vFgu5xG0ob9iJcxi5M4bJ6mWmu3nhmRPnvlwev0= github.com/IBM/mqcloud-go-sdk v0.1.0 h1:fWt4uisg5GbbsfNmAxx5/6c5gQIPM+VrEsTtnimELeA= github.com/IBM/mqcloud-go-sdk v0.1.0/go.mod h1:LesMQlKHXvdks4jqQLZH7HfATY5lvTzHuwQU5+y7b2g= -github.com/IBM/networking-go-sdk v0.47.1 h1:Zqqu9CrZ86jkjMyuIJtBLLOE0D7YtirxnlFyAngEfLw= -github.com/IBM/networking-go-sdk v0.47.1/go.mod h1:yF4XStkswGgVwQVqPUk6b4YTP0dVap52q8HDYwY4gXQ= -github.com/IBM/platform-services-go-sdk v0.64.3 h1:AKDrLXjybG09i5MyqptY0UpyejeiYrTbdylDC7FQM1k= -github.com/IBM/platform-services-go-sdk v0.64.3/go.mod h1:6rYd3stLSnotYmZlxclw45EJPaQuLmh5f7c+Mg7rOg4= +github.com/IBM/networking-go-sdk v0.49.0 h1:lPS34u3C0JVrbxH+Ulua76Nwl6Frv8BEfq6LRkyvOv0= +github.com/IBM/networking-go-sdk v0.49.0/go.mod h1:G9CKbmPE8gSLjN+ABh4hIZ1bMx076enl5Eekvj6zQnA= +github.com/IBM/platform-services-go-sdk v0.67.0 h1:AGu3NiCUyvyFUqbgtmsFRh74kyXrmNbSu1yG/qwGLIM= +github.com/IBM/platform-services-go-sdk v0.67.0/go.mod h1:6rYd3stLSnotYmZlxclw45EJPaQuLmh5f7c+Mg7rOg4= github.com/IBM/project-go-sdk v0.3.5 h1:L+YClFUa14foS0B/hOOY9n7sIdsT5/XQicnXOyJSpyM= github.com/IBM/project-go-sdk v0.3.5/go.mod h1:FOJM9ihQV3EEAY6YigcWiTNfVCThtdY8bLC/nhQHFvo= github.com/IBM/push-notifications-go-sdk v0.0.0-20210310100607-5790b96c47f5 h1:NPUhkoOCRuv3OFWt19PmwjXGGTKlvmbuPg9fUrBUNe4= github.com/IBM/push-notifications-go-sdk v0.0.0-20210310100607-5790b96c47f5/go.mod h1:b07XHUVh0XYnQE9s2mqgjYST1h9buaQNqN4EcKhOsX0= github.com/IBM/sarama v1.41.2 h1:ZDBZfGPHAD4uuAtSv4U22fRZBgst0eEwGFzLj0fb85c= github.com/IBM/sarama v1.41.2/go.mod h1:xdpu7sd6OE1uxNdjYTSKUfY8FaKkJES9/+EyjSgiGQk= -github.com/IBM/scc-go-sdk/v5 v5.1.6 h1:vpcrADzaY6K967pcOVvp+rjAmoOyyxFgR9woQ20Q/l8= -github.com/IBM/scc-go-sdk/v5 v5.1.6/go.mod h1:YtAVlzq10bwR82QX4ZavhDIwa1s85RuVO9N/KmXVcuk= +github.com/IBM/scc-go-sdk/v5 v5.4.1 h1:RXIuxOo9/hxkWyHCI69ae+KIJgSbXcAkJwTEl+fO3LQ= +github.com/IBM/scc-go-sdk/v5 v5.4.1/go.mod h1:2xQTDgNXG5QMEfQxBDKB067z+5ha6OgcaKCTcdGDAo8= github.com/IBM/schematics-go-sdk v0.2.3 h1:lgTt0Sbudii3cuSk1YSQgrtiZAXDbBABAoVj3eQuBrU= github.com/IBM/schematics-go-sdk v0.2.3/go.mod h1:Tw2OSAPdpC69AxcwoyqcYYaGTTW6YpERF9uNEU+BFRQ= -github.com/IBM/secrets-manager-go-sdk/v2 v2.0.4 h1:xa9e+POVqaXxXHXkSMCOVAbKdUNEu86jQmo5hcpd+L4= -github.com/IBM/secrets-manager-go-sdk/v2 v2.0.4/go.mod h1:5gq8D8uWOIbqOm1uztay6lpOysgJaxxEsaVZLWGWb40= +github.com/IBM/secrets-manager-go-sdk/v2 v2.0.5 h1:VMc/Zd6RzB8j60CqZekkwYT2wQsCfrkGV2n01Gviuaw= +github.com/IBM/secrets-manager-go-sdk/v2 v2.0.5/go.mod h1:5kUgJ1dG9cdiAcPDqVz46m362bPnoqZQSth24NiowSg= github.com/IBM/vmware-go-sdk v0.1.2 h1:5lKWFyInWz9e2hwGsoFTEoLa1jYkD30SReN0fQ10w9M= github.com/IBM/vmware-go-sdk v0.1.2/go.mod h1:2UGPBJju3jiv5VKKBBm9a5L6bzF/aJdKOKAzJ7HaOjA= github.com/IBM/vpc-beta-go-sdk v0.6.0 h1:wfM3AcW3zOM3xsRtZ+EA6+sESlGUjQ6Yf4n5QQyz4uc= github.com/IBM/vpc-beta-go-sdk v0.6.0/go.mod h1:fzHDAQIqH/5yJmYsKodKHLcqxMDT+yfH6vZjdiw8CQA= -github.com/IBM/vpc-go-sdk v0.53.0 h1:wlrROeQFTb4utkCKn72eSKGlS4zi3n5pTAJ2pcYTtwE= -github.com/IBM/vpc-go-sdk v0.53.0/go.mod h1:FoZljso53oB/A2mW7ExsfHXZ3T3XWV7c7R5JSgS4QfY= +github.com/IBM/vpc-go-sdk v0.57.0 h1:E8CPDpUE4z0cvvmFZzqUthMtGJx71Fne6vdvkjZdXfg= +github.com/IBM/vpc-go-sdk v0.57.0/go.mod h1:swmxiYLT+OfBsBYqJWGeRd6NPmBk4u/het2PZdtzIaw= github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E= github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56 h1:vuquMR410psHNax14XKNWa0Ae/kYgWJcXi0IFuX60N0= @@ -479,6 +480,7 @@ github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3 github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= @@ -548,6 +550,7 @@ github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpX github.com/go-openapi/errors v0.20.0/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= +github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho= github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= @@ -593,9 +596,9 @@ github.com/go-openapi/strfmt v0.19.10/go.mod h1:qBBipho+3EoIqn6YDI+4RnQEtj6jT/Id github.com/go-openapi/strfmt v0.20.1/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= github.com/go-openapi/strfmt v0.20.2/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= +github.com/go-openapi/strfmt v0.22.1/go.mod h1:OfVoytIXJasDkkGvkb1Cceb3BPyMOwk1FgmyyEw7NYg= github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= @@ -626,8 +629,9 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= +github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= @@ -777,7 +781,6 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -1109,8 +1112,9 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y 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/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 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= @@ -1356,7 +1360,6 @@ github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je4 github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.0/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= @@ -1601,6 +1604,7 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1642,8 +1646,10 @@ github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI 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= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= @@ -1683,8 +1689,9 @@ go.mongodb.org/mongo-driver v1.7.0/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8N go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= -go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= -go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4BQ4= +go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A= go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1760,9 +1767,11 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= 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= @@ -1807,8 +1816,9 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1869,7 +1879,6 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1887,8 +1896,10 @@ golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190130055435-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1925,8 +1936,9 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2020,6 +2032,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc 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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2032,10 +2045,13 @@ golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -2053,8 +2069,9 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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= @@ -2066,6 +2083,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= @@ -2075,8 +2093,9 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2167,8 +2186,9 @@ golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/ibm/acctest/acctest.go b/ibm/acctest/acctest.go index 461686f799..410539545e 100644 --- a/ibm/acctest/acctest.go +++ b/ibm/acctest/acctest.go @@ -97,6 +97,7 @@ var ( InstanceProfileNameUpdate string IsBareMetalServerProfileName string IsBareMetalServerImage string + IsBareMetalServerImage2 string DNSInstanceCRN string DNSZoneID string DNSInstanceCRN1 string @@ -149,23 +150,27 @@ var ( // Secrets Manager var ( - SecretsManagerInstanceID string - SecretsManagerInstanceRegion string - SecretsManagerENInstanceCrn string - SecretsManagerIamCredentialsConfigurationApiKey string - SecretsManagerIamCredentialsSecretServiceId string - SecretsManagerIamCredentialsSecretServiceAccessGroup string - SecretsManagerPublicCertificateLetsEncryptEnvironment string - SecretsManagerPublicCertificateLetsEncryptPrivateKey string - SecretsManagerPublicCertificateCisCrn string - SecretsManagerPublicCertificateClassicInfrastructureUsername string - SecretsManagerPublicCertificateClassicInfrastructurePassword string - SecretsManagerPublicCertificateCommonName string - SecretsManagerValidateManualDnsCisZoneId string - SecretsManagerImportedCertificatePathToCertificate string - SecretsManagerServiceCredentialsCosCrn string - SecretsManagerSecretType string - SecretsManagerSecretID string + SecretsManagerInstanceID string + SecretsManagerInstanceRegion string + SecretsManagerENInstanceCrn string + SecretsManagerIamCredentialsConfigurationApiKey string + SecretsManagerIamCredentialsSecretServiceId string + SecretsManagerIamCredentialsSecretServiceAccessGroup string + SecretsManagerPublicCertificateLetsEncryptEnvironment string + SecretsManagerPublicCertificateLetsEncryptPrivateKey string + SecretsManagerPublicCertificateCisCrn string + SecretsManagerPublicCertificateClassicInfrastructureUsername string + SecretsManagerPublicCertificateClassicInfrastructurePassword string + SecretsManagerPublicCertificateCommonName string + SecretsManagerValidateManualDnsCisZoneId string + SecretsManagerImportedCertificatePathToCertificate string + SecretsManagerServiceCredentialsCosCrn string + SecretsManagerPrivateCertificateConfigurationCryptoKeyIAMSecretServiceId string + SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderType string + SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderInstanceCrn string + SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderPrivateKeystoreId string + SecretsManagerSecretType string + SecretsManagerSecretID string ) var ( @@ -352,6 +357,8 @@ var ( CeDomainMappingName string CeTLSCert string CeTLSKey string + CeTLSKeyFilePath string + CeTLSCertFilePath string ) // Satellite tests @@ -389,6 +396,18 @@ var ( TargetAccountId string ) +// For Partner Center Sell +var ( + PcsRegistrationAccountId string + PcsOnboardingProductWithApprovedProgrammaticName string + // one Onboarding product can only have one catalog product ever + PcsOnboardingProductWithApprovedProgrammaticName2 string + PcsOnboardingProductWithCatalogProduct string + PcsOnboardingCatalogProductId string + PcsOnboardingCatalogPlanId string + PcsIamServiceRegistrationId string +) + func init() { testlogger := os.Getenv("TF_LOG") if testlogger != "" { @@ -854,6 +873,12 @@ func init() { fmt.Println("[INFO] Set the environment variable IsBareMetalServerImage for testing ibm_is_bare_metal_server resource else it is set to default value 'r006-2d1f36b0-df65-4570-82eb-df7ae5f778b1'") } + IsBareMetalServerImage2 = os.Getenv("IS_BARE_METAL_SERVER_IMAGE2") + if IsBareMetalServerImage2 == "" { + IsBareMetalServerImage2 = "r006-2d1f36b0-df65-4570-82eb-df7ae5f778b1" // for next gen infrastructure + fmt.Println("[INFO] Set the environment variable IsBareMetalServerImage2 for testing ibm_is_bare_metal_server resource else it is set to default value 'r006-2d1f36b0-df65-4570-82eb-df7ae5f778b1'") + } + DNSInstanceCRN = os.Getenv("IS_DNS_INSTANCE_CRN") if DNSInstanceCRN == "" { DNSInstanceCRN = "crn:v1:bluemix:public:dns-svcs:global:a/7f75c7b025e54bc5635f754b2f888665:fa78ce08-a161-4703-98e5-35ed2bfe0e7c::" // for next gen infrastructure @@ -1352,6 +1377,26 @@ func init() { fmt.Println("[INFO] Set the environment variable SECRETS_MANAGER_SERVICE_CREDENTIALS_COS_CRN for testing service credentials' tests, else tests fail if not set correctly") } + SecretsManagerPrivateCertificateConfigurationCryptoKeyIAMSecretServiceId = os.Getenv("SECRETS_MANAGER_PRIVATE_CERTIFICATE_CONFIGURATION_CRYPTO_KEY_IAM_SECRET_SERVICE_ID") + if SecretsManagerPrivateCertificateConfigurationCryptoKeyIAMSecretServiceId == "" { + fmt.Println("[INFO] Set the environment variable SECRETS_MANAGER_PRIVATE_CERTIFICATE_CONFIGURATION_CRYPTO_KEY_IAM_SECRET_SERVICE_ID for testing private certificate's configuration with crypto key tests, else tests fail if not set correctly") + } + + SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderType = os.Getenv("SECRETS_MANAGER_PRIVATE_CERTIFICATE_CONFIGURATION_CRYPTO_KEY_PROVIDER_TYPE") + if SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderType == "" { + fmt.Println("[INFO] Set the environment variable SECRETS_MANAGER_PRIVATE_CERTIFICATE_CONFIGURATION_CRYPTO_KEY_PROVIDER_TYPE for testing private certificate's configuration with crypto key tests, else tests fail if not set correctly") + } + + SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderInstanceCrn = os.Getenv("SECRETS_MANAGER_PRIVATE_CERTIFICATE_CONFIGURATION_CRYPTO_KEY_PROVIDER_INSTANCE_CRN") + if SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderInstanceCrn == "" { + fmt.Println("[INFO] Set the environment variable SECRETS_MANAGER_PRIVATE_CERTIFICATE_CONFIGURATION_CRYPTO_KEY_PROVIDER_INSTANCE_CRN for testing private certificate's configuration with crypto key tests, else tests fail if not set correctly") + } + + SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderPrivateKeystoreId = os.Getenv("SECRETS_MANAGER_PRIVATE_CERTIFICATE_CONFIGURATION_CRYPTO_KEY_PROVIDER_PRIVATE_KEYSTORE_ID") + if SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderPrivateKeystoreId == "" { + fmt.Println("[INFO] Set the environment variable SECRETS_MANAGER_PRIVATE_CERTIFICATE_CONFIGURATION_CRYPTO_KEY_PROVIDER_PRIVATE_KEYSTORE_ID for testing private certificate's configuration with crypto key tests, else tests fail if not set correctly") + } + Tg_cross_network_account_api_key = os.Getenv("IBM_TG_CROSS_ACCOUNT_API_KEY") if Tg_cross_network_account_api_key == "" { fmt.Println("[INFO] Set the environment variable IBM_TG_CROSS_ACCOUNT_API_KEY for testing ibm_tg_connection resource else tests will fail if this is not set correctly") @@ -1699,6 +1744,18 @@ func init() { fmt.Println("[WARN] Set the environment variable IBM_CODE_ENGINE_TLS_KEY with a TLS key in base64 format") } + CeTLSKeyFilePath = os.Getenv("IBM_CODE_ENGINE_TLS_CERT_KEY_PATH") + if CeTLSKeyFilePath == "" { + CeTLSKeyFilePath = "" + fmt.Println("[WARN] Set the environment variable IBM_CODE_ENGINE_TLS_CERT_KEY_PATH to point to CERT KEY file path") + } + + CeTLSCertFilePath = os.Getenv("IBM_CODE_ENGINE_TLS_CERT_PATH") + if CeTLSCertFilePath == "" { + CeTLSCertFilePath = "" + fmt.Println("[WARN] Set the environment variable IBM_CODE_ENGINE_TLS_CERT_PATH to point to CERT file path") + } + SatelliteSSHPubKey = os.Getenv("IBM_SATELLITE_SSH_PUB_KEY") if SatelliteSSHPubKey == "" { fmt.Println("[WARN] Set the environment variable IBM_SATELLITE_SSH_PUB_KEY with a ssh public key or ibm_satellite_* tests may fail") @@ -1812,6 +1869,41 @@ func init() { if TargetAccountId == "" { fmt.Println("[INFO] Set the environment variable IBM_POLICY_ASSIGNMENT_TARGET_ACCOUNT_ID for testing ibm_iam_policy_assignment resource else tests will fail if this is not set correctly") } + + PcsRegistrationAccountId = os.Getenv("PCS_REGISTRATION_ACCOUNT_ID") + if PcsRegistrationAccountId == "" { + fmt.Println("[WARN] Set the environment variable PCS_REGISTRATION_ACCOUNT_ID for testing iam_onboarding resource else tests will fail if this is not set correctly") + } + + PcsOnboardingProductWithApprovedProgrammaticName = os.Getenv("PCS_PRODUCT_WITH_APPROVED_PROGRAMMATIC_NAME") + if PcsOnboardingProductWithApprovedProgrammaticName == "" { + fmt.Println("[WARN] Set the environment variable PCS_PRODUCT_WITH_APPROVED_PROGRAMMATIC_NAME for testing iam_onboarding resource else tests will fail if this is not set correctly") + } + + PcsOnboardingProductWithApprovedProgrammaticName2 = os.Getenv("PCS_PRODUCT_WITH_APPROVED_PROGRAMMATIC_NAME_2") + if PcsOnboardingProductWithApprovedProgrammaticName2 == "" { + fmt.Println("[WARN] Set the environment variable PCS_PRODUCT_WITH_APPROVED_PROGRAMMATIC_NAME_2 for testing iam_onboarding resource else tests will fail if this is not set correctly") + } + + PcsOnboardingProductWithCatalogProduct = os.Getenv("PCS_PRODUCT_WITH_CATALOG_PRODUCT") + if PcsOnboardingProductWithCatalogProduct == "" { + fmt.Println("[WARN] Set the environment variable PCS_PRODUCT_WITH_CATALOG_PRODUCT for testing iam_onboarding resource else tests will fail if this is not set correctly") + } + + PcsOnboardingCatalogProductId = os.Getenv("PCS_CATALOG_PRODUCT") + if PcsOnboardingCatalogProductId == "" { + fmt.Println("[WARN] Set the environment variable PCS_CATALOG_PRODUCT for testing iam_onboarding resource else tests will fail if this is not set correctly") + } + + PcsOnboardingCatalogPlanId = os.Getenv("PCS_CATALOG_PLAN") + if PcsIamServiceRegistrationId == "" { + fmt.Println("[WARN] Set the environment variable PCS_CATALOG_PLAN for testing iam_onboarding resource else tests will fail if this is not set correctly") + } + + PcsIamServiceRegistrationId = os.Getenv("PCS_IAM_REGISTRATION_ID") + if PcsIamServiceRegistrationId == "" { + fmt.Println("[WARN] Set the environment variable PCS_IAM_TEGISTRATION_ID for testing iam_onboarding resource else tests will fail if this is not set correctly") + } } var ( @@ -2007,11 +2099,11 @@ func TestAccPreCheckCodeEngine(t *testing.T) { if CeDomainMappingName == "" { t.Fatal("IBM_CODE_ENGINE_DOMAIN_MAPPING_NAME must be set for acceptance tests") } - if CeTLSCert == "" { - t.Fatal("IBM_CODE_ENGINE_DOMAIN_MAPPING_TLS_CERT must be set for acceptance tests") + if CeTLSKeyFilePath == "" { + t.Fatal("IBM_CODE_ENGINE_TLS_CERT_KEY_PATH must be set for acceptance tests") } - if CeTLSKey == "" { - t.Fatal("IBM_CODE_ENGINE_DOMAIN_MAPPING_TLS_KEY must be set for acceptance tests") + if CeTLSCertFilePath == "" { + t.Fatal("IBM_CODE_ENGINE_TLS_CERT_PATH must be set for acceptance tests") } } @@ -2115,6 +2207,31 @@ func TestAccPreCheckVMwareService(t *testing.T) { } } +func TestAccPreCheckPartnerCenterSell(t *testing.T) { + TestAccPreCheck(t) + if PcsRegistrationAccountId == "" { + t.Fatal("PCS_REGISTRATION_ACCOUNT_ID must be set for acceptance tests") + } + if PcsOnboardingProductWithApprovedProgrammaticName == "" { + t.Fatal("PCS_PRODUCT_WITH_APPROVED_PROGRAMMATIC_NAME must be set for acceptance tests") + } + if PcsOnboardingProductWithApprovedProgrammaticName2 == "" { + t.Fatal("PCS_PRODUCT_WITH_APPROVED_PROGRAMMATIC_NAME_2 must be set for acceptance tests") + } + if PcsOnboardingProductWithCatalogProduct == "" { + t.Fatal("PCS_PRODUCT_WITH_CATALOG_PRODUCT must be set for acceptance tests") + } + if PcsOnboardingCatalogProductId == "" { + t.Fatal("PCS_CATALOG_PRODUCT must be set for acceptance tests") + } + if PcsOnboardingCatalogPlanId == "" { + t.Fatal("PCS_CATALOG_PLAN must be set for acceptance tests") + } + if PcsIamServiceRegistrationId == "" { + t.Fatal("PCS_IAM_REGISTRATION_ID must be set for acceptance tests") + } +} + func TestAccProviderFactories() map[string]func() (*schema.Provider, error) { return map[string]func() (*schema.Provider, error){ ProviderName: func() (*schema.Provider, error) { return provider.Provider(), nil }, diff --git a/ibm/conns/config.go b/ibm/conns/config.go index 0e8750619c..83ae73f383 100644 --- a/ibm/conns/config.go +++ b/ibm/conns/config.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "io/ioutil" "log" "net" @@ -29,6 +30,7 @@ import ( "github.com/IBM/go-sdk-core/v5/core" cosconfig "github.com/IBM/ibm-cos-sdk-go-config/v2/resourceconfigurationv1" kp "github.com/IBM/keyprotect-go-client" + "github.com/IBM/logs-router-go-sdk/ibmcloudlogsroutingv0" "github.com/IBM/mqcloud-go-sdk/mqcloudv1" cisalertsv1 "github.com/IBM/networking-go-sdk/alertsv1" cisoriginpull "github.com/IBM/networking-go-sdk/authenticatedoriginpullapiv1" @@ -121,6 +123,7 @@ import ( "github.com/IBM/eventstreams-go-sdk/pkg/schemaregistryv1" "github.com/IBM/ibm-hpcs-uko-sdk/ukov4" "github.com/IBM/logs-go-sdk/logsv0" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" scc "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" "github.com/IBM/secrets-manager-go-sdk/v2/secretsmanagerv2" ) @@ -231,6 +234,7 @@ type ClientSession interface { ResourceManagementAPIv2() (managementv2.ResourceManagementAPIv2, error) ResourceControllerAPI() (controller.ResourceControllerAPI, error) ResourceControllerAPIV2() (controllerv2.ResourceControllerAPIV2, error) + IBMCloudLogsRoutingV0() (*ibmcloudlogsroutingv0.IBMCloudLogsRoutingV0, error) SoftLayerSession() *slsession.Session IBMPISession() (*ibmpisession.IBMPISession, error) UserManagementAPI() (usermanagementv2.UserManagementAPI, error) @@ -299,6 +303,7 @@ type ClientSession interface { SecurityAndComplianceCenterV3() (*scc.SecurityAndComplianceCenterApiV3, error) CdToolchainV2() (*cdtoolchainv2.CdToolchainV2, error) CdTektonPipelineV2() (*cdtektonpipelinev2.CdTektonPipelineV2, error) + PartnerCenterSellV1() (*partnercentersellv1.PartnerCenterSellV1, error) CodeEngineV2() (*codeengine.CodeEngineV2, error) ProjectV1() (*project.ProjectV1, error) UsageReportsV4() (*usagereportsv4.UsageReportsV4, error) @@ -542,6 +547,9 @@ type clientSession struct { catalogManagementClient *catalogmanagementv1.CatalogManagementV1 catalogManagementClientErr error + partnerCenterSellClient *partnercentersellv1.PartnerCenterSellV1 + partnerCenterSellClientErr error + enterpriseManagementClient *enterprisemanagementv1.EnterpriseManagementV1 enterpriseManagementClientErr error @@ -644,6 +652,10 @@ type clientSession struct { // Cloud Logs logsClient *logsv0.LogsV0 logsClientErr error + + // Logs Routing + ibmCloudLogsRoutingClient *ibmcloudlogsroutingv0.IBMCloudLogsRoutingV0 + ibmCloudLogsRoutingClientErr error } // Usage Reports @@ -651,6 +663,10 @@ func (session clientSession) UsageReportsV4() (*usagereportsv4.UsageReportsV4, e return session.usageReportsClient, session.usageReportsClientErr } +func (session clientSession) PartnerCenterSellV1() (*partnercentersellv1.PartnerCenterSellV1, error) { + return session.partnerCenterSellClient, session.partnerCenterSellClientErr +} + // AppIDAPI provides AppID Service APIs ... func (session clientSession) AppIDAPI() (*appid.AppIDManagementV4, error) { return session.appidAPI, session.appidErr @@ -1246,6 +1262,11 @@ func (session clientSession) LogsV0() (*logsv0.LogsV0, error) { return session.logsClient, session.logsClientErr } +// IBM Cloud Logs Routing +func (session clientSession) IBMCloudLogsRoutingV0() (*ibmcloudlogsroutingv0.IBMCloudLogsRoutingV0, error) { + return session.ibmCloudLogsRoutingClient, session.ibmCloudLogsRoutingClientErr +} + // ClientSession configures and returns a fully initialized ClientSession func (c *Config) ClientSession() (interface{}, error) { sess, err := newSession(c) @@ -1287,6 +1308,7 @@ func (c *Config) ClientSession() (interface{}, error) { session.enterpriseManagementClientErr = errEmptyBluemixCredentials session.resourceControllerErr = errEmptyBluemixCredentials session.catalogManagementClientErr = errEmptyBluemixCredentials + session.partnerCenterSellClientErr = errEmptyBluemixCredentials session.ibmpiConfigErr = errEmptyBluemixCredentials session.userManagementErr = errEmptyBluemixCredentials session.vpcErr = errEmptyBluemixCredentials @@ -1341,6 +1363,7 @@ func (c *Config) ClientSession() (interface{}, error) { session.projectClientErr = errEmptyBluemixCredentials session.mqcloudClientErr = errEmptyBluemixCredentials session.logsClientErr = errEmptyBluemixCredentials + session.ibmCloudLogsRoutingClientErr = errEmptyBluemixCredentials return session, nil } @@ -1604,6 +1627,39 @@ func (c *Config) ClientSession() (interface{}, error) { session.logsClientErr = fmt.Errorf("Error occurred while configuring Cloud Logs API service: %q", err) } + // LOGS ROUTER Version 0 + var logsrouterClientURL string + var logsrouterURLErr error + + if c.Visibility == "private" || c.Visibility == "public-and-private" { + logsrouterClientURL, logsrouterURLErr = ibmcloudlogsroutingv0.GetServiceURLForRegion("private." + c.Region) + if err != nil && c.Visibility == "public-and-private" { + logsrouterClientURL, logsrouterURLErr = ibmcloudlogsroutingv0.GetServiceURLForRegion(c.Region) + } + } else { + logsrouterClientURL, logsrouterURLErr = ibmcloudlogsroutingv0.GetServiceURLForRegion(c.Region) + } + if logsrouterURLErr != nil { + logsrouterClientURL = ibmcloudlogsroutingv0.DefaultServiceURL + } + ibmCloudLogsRoutingClientOptions := &ibmcloudlogsroutingv0.IBMCloudLogsRoutingV0Options{ + Authenticator: authenticator, + URL: logsrouterClientURL, + } + + // Construct the service client. + session.ibmCloudLogsRoutingClient, err = ibmcloudlogsroutingv0.NewIBMCloudLogsRoutingV0(ibmCloudLogsRoutingClientOptions) + if err == nil { + // Enable retries for API calls + session.ibmCloudLogsRoutingClient.Service.EnableRetries(c.RetryCount, c.RetryDelay) + // Add custom header for analytics + session.ibmCloudLogsRoutingClient.SetDefaultHeaders(gohttp.Header{ + "X-Original-User-Agent": {fmt.Sprintf("terraform-provider-ibm/%s", version.Version)}, + }) + } else { + session.ibmCloudLogsRoutingClientErr = fmt.Errorf("Error occurred while configuring IBM Cloud Logs Routing service: %q", err) + } + // Construct an "options" struct for creating the service client. ukoClientOptions := &ukov4.UkoV4Options{ Authenticator: authenticator, @@ -1676,7 +1732,33 @@ func (c *Config) ClientSession() (interface{}, error) { session.contextBasedRestrictionsClientErr = fmt.Errorf("[ERROR] Error occurred while configuring Context Based Restrictions service: %q", err) } - // // Usage Reports Service Client + // PARTNER CENTER SELL (product lifecycle) service + partnerCenterSellURL := "https://product-lifecycle.api.cloud.ibm.com/openapi/v1" + if c.Visibility == "private" { + session.partnerCenterSellClientErr = fmt.Errorf("partner center sell does not support private endpoints") + } + if fileMap != nil && c.Visibility != "public-and-private" { + partnerCenterSellURL = fileFallBack(fileMap, c.Visibility, "IBMCLOUD_PARTNER_CENTER_SELL_API_ENDPOINT", c.Region, partnerCenterSellURL) + } + partnerCenterSellClientOptions := &partnercentersellv1.PartnerCenterSellV1Options{ + URL: EnvFallBack([]string{"IBMCLOUD_PARTNER_CENTER_SELL_API_ENDPOINT"}, partnerCenterSellURL), + Authenticator: authenticator, + } + // Construct the service client. + session.partnerCenterSellClient, err = partnercentersellv1.NewPartnerCenterSellV1(partnerCenterSellClientOptions) + if err != nil { + session.partnerCenterSellClientErr = fmt.Errorf("[ERROR] Error occurred while configuring Partner Center Sell API service: %q", err) + } + if session.partnerCenterSellClient != nil && session.partnerCenterSellClient.Service != nil { + // Enable retries for API calls + session.partnerCenterSellClient.Service.EnableRetries(c.RetryCount, c.RetryDelay) + // Add custom header for analytics + session.partnerCenterSellClient.SetDefaultHeaders(gohttp.Header{ + "X-Original-User-Agent": {fmt.Sprintf("terraform-provider-ibm/%s", version.Version)}, + }) + } + + //Usage Reports Service Client usageReportsURL := usagereportsv4.DefaultServiceURL if c.Visibility == "private" { if c.Region == "us-south" || c.Region == "us-east" { @@ -3567,6 +3649,27 @@ func EnvFallBack(envs []string, defaultValue string) string { return defaultValue } +func FileFallBack(endpointsFile, visibility, key, region, defaultValue string) string { + var fileMap map[string]interface{} + if f := EnvFallBack([]string{"IBMCLOUD_ENDPOINTS_FILE_PATH", "IC_ENDPOINTS_FILE_PATH"}, endpointsFile); f != "" { + jsonFile, err := os.Open(f) + if err != nil { + log.Fatalf("Unable to open Endpoints File %s", err) + } + defer jsonFile.Close() + bytes, err := io.ReadAll(jsonFile) + if err != nil { + log.Fatalf("Unable to read Endpoints File %s", err) + } + err = json.Unmarshal([]byte(bytes), &fileMap) + if err != nil { + log.Fatalf("Unable to unmarshal Endpoints File %s", err) + } + } + + return fileFallBack(fileMap, visibility, key, region, defaultValue) +} + func fileFallBack(fileMap map[string]interface{}, visibility, key, region, defaultValue string) string { if val, ok := fileMap[key]; ok { if v, ok := val.(map[string]interface{})[visibility]; ok { diff --git a/ibm/flex/structures.go b/ibm/flex/structures.go index 2d9699081d..da354497e6 100644 --- a/ibm/flex/structures.go +++ b/ibm/flex/structures.go @@ -19,10 +19,15 @@ import ( "strings" "time" + "github.com/IBM-Cloud/bluemix-go/api/container/containerv1" + "github.com/IBM-Cloud/bluemix-go/api/container/containerv2" + "github.com/IBM-Cloud/bluemix-go/api/icd/icdv4" + "github.com/IBM-Cloud/bluemix-go/api/mccp/mccpv2" + "github.com/IBM-Cloud/bluemix-go/api/schematics" + "github.com/IBM-Cloud/bluemix-go/api/usermanagement/usermanagementv2" "github.com/IBM-Cloud/bluemix-go/bmxerror" "github.com/IBM-Cloud/bluemix-go/models" "github.com/IBM-Cloud/container-services-go-sdk/kubernetesserviceapiv1" - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM/cloud-databases-go-sdk/clouddatabasesv5" "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/ibm-cos-sdk-go-config/v2/resourceconfigurationv1" @@ -31,8 +36,11 @@ import ( kp "github.com/IBM/keyprotect-go-client" "github.com/IBM/platform-services-go-sdk/globalsearchv2" "github.com/IBM/platform-services-go-sdk/globaltaggingv1" + "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" + "github.com/IBM/platform-services-go-sdk/iamidentityv1" "github.com/IBM/platform-services-go-sdk/iampolicymanagementv1" "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" + rc "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" rg "github.com/IBM/platform-services-go-sdk/resourcemanagerv2" "github.com/apache/openwhisk-client-go/whisk" "github.com/go-openapi/strfmt" @@ -41,15 +49,7 @@ import ( "github.com/softlayer/softlayer-go/datatypes" "github.com/softlayer/softlayer-go/sl" - "github.com/IBM-Cloud/bluemix-go/api/container/containerv1" - "github.com/IBM-Cloud/bluemix-go/api/container/containerv2" - "github.com/IBM-Cloud/bluemix-go/api/icd/icdv4" - "github.com/IBM-Cloud/bluemix-go/api/mccp/mccpv2" - "github.com/IBM-Cloud/bluemix-go/api/schematics" - "github.com/IBM-Cloud/bluemix-go/api/usermanagement/usermanagementv2" - "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" - "github.com/IBM/platform-services-go-sdk/iamidentityv1" - rc "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" ) const ( @@ -4239,6 +4239,15 @@ func FlattenSatelliteHosts(hostList []kubernetesserviceapiv1.MultishiftQueueNode return hosts } +func FlattenSatelliteCapabilities(capabilities *schema.Set) []kubernetesserviceapiv1.CapabilityManagedBySatellite { + result := make([]kubernetesserviceapiv1.CapabilityManagedBySatellite, capabilities.Len()) + for i, v := range capabilities.List() { + result[i] = kubernetesserviceapiv1.CapabilityManagedBySatellite(v.(string)) + } + + return result +} + func FlattenWorkerPoolHostLabels(hostLabels map[string]string) *schema.Set { mapped := make([]string, 0) for k, v := range hostLabels { diff --git a/ibm/flex/terraform_problem.go b/ibm/flex/terraform_problem.go index 9296485fe2..46aa9cdab2 100644 --- a/ibm/flex/terraform_problem.go +++ b/ibm/flex/terraform_problem.go @@ -3,6 +3,7 @@ package flex import ( "errors" "fmt" + v "github.com/IBM-Cloud/terraform-provider-ibm/version" "github.com/IBM/go-sdk-core/v5/core" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" diff --git a/ibm/provider/provider.go b/ibm/provider/provider.go index 442bd73bcf..dc4a116869 100644 --- a/ibm/provider/provider.go +++ b/ibm/provider/provider.go @@ -47,9 +47,11 @@ import ( "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/kms" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/kubernetes" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/logs" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/logsrouting" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/metricsrouter" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/mqcloud" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/pag" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/partnercentersell" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/power" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/project" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/pushnotification" @@ -302,6 +304,7 @@ func Provider() *schema.Provider { "ibm_cis_waf_rules": cis.DataSourceIBMCISWAFRules(), "ibm_cis_filters": cis.DataSourceIBMCISFilters(), "ibm_cis_firewall_rules": cis.DataSourceIBMCISFirewallRules(), + "ibm_cis_origin_certificates": cis.DataSourceIBMCISOriginCertificateOrder(), "ibm_cloudant": cloudant.DataSourceIBMCloudant(), "ibm_cloudant_database": cloudant.DataSourceIBMCloudantDatabase(), "ibm_database": database.DataSourceIBMDatabaseInstance(), @@ -513,6 +516,8 @@ func Provider() *schema.Provider { "ibm_is_shares": vpc.DataSourceIbmIsShares(), "ibm_is_share_profile": vpc.DataSourceIbmIsShareProfile(), "ibm_is_share_profiles": vpc.DataSourceIbmIsShareProfiles(), + "ibm_is_share_accessor_bindings": vpc.DataSourceIBMIsShareAccessorBindings(), + "ibm_is_share_accessor_binding": vpc.DataSourceIBMIsShareAccessorBinding(), "ibm_is_virtual_network_interface": vpc.DataSourceIBMIsVirtualNetworkInterface(), "ibm_is_virtual_network_interfaces": vpc.DataSourceIBMIsVirtualNetworkInterfaces(), @@ -830,8 +835,9 @@ func Provider() *schema.Provider { "ibm_pag_instance": pag.DataSourceIBMPag(), // Added for Context Based Restrictions - "ibm_cbr_zone": contextbasedrestrictions.DataSourceIBMCbrZone(), - "ibm_cbr_rule": contextbasedrestrictions.DataSourceIBMCbrRule(), + "ibm_cbr_zone": contextbasedrestrictions.DataSourceIBMCbrZone(), + "ibm_cbr_zone_addresses": contextbasedrestrictions.DataSourceIBMCbrZoneAddresses(), + "ibm_cbr_rule": contextbasedrestrictions.DataSourceIBMCbrRule(), // Added for Event Notifications "ibm_en_source": eventnotification.DataSourceIBMEnSource(), @@ -884,6 +890,8 @@ func Provider() *schema.Provider { "ibm_en_smtp_user": eventnotification.DataSourceIBMEnSMTPUser(), "ibm_en_smtp_users": eventnotification.DataSourceIBMEnSMTPUsers(), "ibm_en_slack_template": eventnotification.DataSourceIBMEnSlackTemplate(), + "ibm_en_metrics": eventnotification.DataSourceIBMEnMetrics(), + "ibm_en_smtp_allowed_ips": eventnotification.DataSourceIBMEnSMTPAllowedIps(), // Added for Toolchain "ibm_cd_toolchain": cdtoolchain.DataSourceIBMCdToolchain(), @@ -955,6 +963,10 @@ func Provider() *schema.Provider { "ibm_logs_data_usage_metrics": logs.AddLogsInstanceFields(logs.DataSourceIbmLogsDataUsageMetrics()), "ibm_logs_enrichments": logs.AddLogsInstanceFields(logs.DataSourceIbmLogsEnrichments()), "ibm_logs_data_access_rules": logs.AddLogsInstanceFields(logs.DataSourceIbmLogsDataAccessRules()), + + // Logs Router Service + "ibm_logs_router_tenants": logsrouting.DataSourceIBMLogsRouterTenants(), + "ibm_logs_router_targets": logsrouting.DataSourceIBMLogsRouterTargets(), }, ResourcesMap: map[string]*schema.Resource{ @@ -996,43 +1008,45 @@ func Provider() *schema.Provider { "ibm_function_trigger": functions.ResourceIBMFunctionTrigger(), "ibm_function_namespace": functions.ResourceIBMFunctionNamespace(), - "ibm_cis": cis.ResourceIBMCISInstance(), - "ibm_database": database.ResourceIBMDatabaseInstance(), - "ibm_cis_domain": cis.ResourceIBMCISDomain(), - "ibm_cis_domain_settings": cis.ResourceIBMCISSettings(), - "ibm_cis_firewall": cis.ResourceIBMCISFirewallRecord(), - "ibm_cis_range_app": cis.ResourceIBMCISRangeApp(), - "ibm_cis_healthcheck": cis.ResourceIBMCISHealthCheck(), - "ibm_cis_origin_pool": cis.ResourceIBMCISPool(), - "ibm_cis_global_load_balancer": cis.ResourceIBMCISGlb(), - "ibm_cis_certificate_upload": cis.ResourceIBMCISCertificateUpload(), - "ibm_cis_dns_record": cis.ResourceIBMCISDnsRecord(), - "ibm_cis_dns_records_import": cis.ResourceIBMCISDNSRecordsImport(), - "ibm_cis_rate_limit": cis.ResourceIBMCISRateLimit(), - "ibm_cis_page_rule": cis.ResourceIBMCISPageRule(), - "ibm_cis_edge_functions_action": cis.ResourceIBMCISEdgeFunctionsAction(), - "ibm_cis_edge_functions_trigger": cis.ResourceIBMCISEdgeFunctionsTrigger(), - "ibm_cis_tls_settings": cis.ResourceIBMCISTLSSettings(), - "ibm_cis_waf_package": cis.ResourceIBMCISWAFPackage(), - "ibm_cis_webhook": cis.ResourceIBMCISWebhooks(), - "ibm_cis_origin_auth": cis.ResourceIBMCISOriginAuthPull(), - "ibm_cis_mtls": cis.ResourceIBMCISMtls(), - "ibm_cis_mtls_app": cis.ResourceIBMCISMtlsApp(), - "ibm_cis_bot_management": cis.ResourceIBMCISBotManagement(), - "ibm_cis_logpush_job": cis.ResourceIBMCISLogPushJob(), - "ibm_cis_alert": cis.ResourceIBMCISAlert(), - "ibm_cis_routing": cis.ResourceIBMCISRouting(), - "ibm_cis_waf_group": cis.ResourceIBMCISWAFGroup(), - "ibm_cis_cache_settings": cis.ResourceIBMCISCacheSettings(), - "ibm_cis_custom_page": cis.ResourceIBMCISCustomPage(), - "ibm_cis_waf_rule": cis.ResourceIBMCISWAFRule(), - "ibm_cis_certificate_order": cis.ResourceIBMCISCertificateOrder(), - "ibm_cis_filter": cis.ResourceIBMCISFilter(), - "ibm_cis_firewall_rule": cis.ResourceIBMCISFirewallrules(), - "ibm_cis_ruleset": cis.ResourceIBMCISRuleset(), - "ibm_cis_ruleset_version_detach": cis.ResourceIBMCISRulesetVersionDetach(), - "ibm_cis_ruleset_rule": cis.ResourceIBMCISRulesetRule(), - "ibm_cis_ruleset_entrypoint_version": cis.ResourceIBMCISRulesetEntryPointVersion(), + "ibm_cis": cis.ResourceIBMCISInstance(), + "ibm_database": database.ResourceIBMDatabaseInstance(), + "ibm_cis_domain": cis.ResourceIBMCISDomain(), + "ibm_cis_domain_settings": cis.ResourceIBMCISSettings(), + "ibm_cis_firewall": cis.ResourceIBMCISFirewallRecord(), + "ibm_cis_range_app": cis.ResourceIBMCISRangeApp(), + "ibm_cis_healthcheck": cis.ResourceIBMCISHealthCheck(), + "ibm_cis_origin_pool": cis.ResourceIBMCISPool(), + "ibm_cis_global_load_balancer": cis.ResourceIBMCISGlb(), + "ibm_cis_certificate_upload": cis.ResourceIBMCISCertificateUpload(), + "ibm_cis_dns_record": cis.ResourceIBMCISDnsRecord(), + "ibm_cis_dns_records_import": cis.ResourceIBMCISDNSRecordsImport(), + "ibm_cis_rate_limit": cis.ResourceIBMCISRateLimit(), + "ibm_cis_page_rule": cis.ResourceIBMCISPageRule(), + "ibm_cis_edge_functions_action": cis.ResourceIBMCISEdgeFunctionsAction(), + "ibm_cis_edge_functions_trigger": cis.ResourceIBMCISEdgeFunctionsTrigger(), + "ibm_cis_tls_settings": cis.ResourceIBMCISTLSSettings(), + "ibm_cis_waf_package": cis.ResourceIBMCISWAFPackage(), + "ibm_cis_webhook": cis.ResourceIBMCISWebhooks(), + "ibm_cis_origin_auth": cis.ResourceIBMCISOriginAuthPull(), + "ibm_cis_mtls": cis.ResourceIBMCISMtls(), + "ibm_cis_mtls_app": cis.ResourceIBMCISMtlsApp(), + "ibm_cis_bot_management": cis.ResourceIBMCISBotManagement(), + "ibm_cis_logpush_job": cis.ResourceIBMCISLogPushJob(), + "ibm_cis_alert": cis.ResourceIBMCISAlert(), + "ibm_cis_routing": cis.ResourceIBMCISRouting(), + "ibm_cis_waf_group": cis.ResourceIBMCISWAFGroup(), + "ibm_cis_cache_settings": cis.ResourceIBMCISCacheSettings(), + "ibm_cis_custom_page": cis.ResourceIBMCISCustomPage(), + "ibm_cis_waf_rule": cis.ResourceIBMCISWAFRule(), + "ibm_cis_certificate_order": cis.ResourceIBMCISCertificateOrder(), + "ibm_cis_filter": cis.ResourceIBMCISFilter(), + "ibm_cis_firewall_rule": cis.ResourceIBMCISFirewallrules(), + "ibm_cis_ruleset": cis.ResourceIBMCISRuleset(), + "ibm_cis_ruleset_version_detach": cis.ResourceIBMCISRulesetVersionDetach(), + "ibm_cis_ruleset_rule": cis.ResourceIBMCISRulesetRule(), + "ibm_cis_ruleset_entrypoint_version": cis.ResourceIBMCISRulesetEntryPointVersion(), + "ibm_cis_advanced_certificate_pack_order": cis.ResourceIBMCISAdvancedCertificatePackOrder(), + "ibm_cis_origin_certificate_order": cis.ResourceIBMCISOriginCertificateOrder(), "ibm_cloudant": cloudant.ResourceIBMCloudant(), "ibm_cloudant_database": cloudant.ResourceIBMCloudantDatabase(), @@ -1132,6 +1146,7 @@ func Provider() *schema.Provider { // bare_metal_server "ibm_is_bare_metal_server_action": vpc.ResourceIBMIsBareMetalServerAction(), "ibm_is_bare_metal_server_disk": vpc.ResourceIBMIsBareMetalServerDisk(), + "ibm_is_bare_metal_server_initialization": vpc.ResourceIBMIsBareMetalServerInitialization(), "ibm_is_bare_metal_server_network_attachment": vpc.ResourceIBMIsBareMetalServerNetworkAttachment(), "ibm_is_bare_metal_server_network_interface_allow_float": vpc.ResourceIBMIsBareMetalServerNetworkInterfaceAllowFloat(), "ibm_is_bare_metal_server_network_interface_floating_ip": vpc.ResourceIBMIsBareMetalServerNetworkInterfaceFloatingIp(), @@ -1176,6 +1191,7 @@ func Provider() *schema.Provider { "ibm_is_share": vpc.ResourceIbmIsShare(), "ibm_is_share_replica_operations": vpc.ResourceIbmIsShareReplicaOperations(), "ibm_is_share_mount_target": vpc.ResourceIBMIsShareMountTarget(), + "ibm_is_share_delete_accessor_binding": vpc.ResourceIbmIsShareDeleteAccessorBinding(), "ibm_is_subnet": vpc.ResourceIBMISSubnet(), "ibm_is_reservation": vpc.ResourceIBMISReservation(), "ibm_is_reservation_activate": vpc.ResourceIBMISReservationActivate(), @@ -1256,6 +1272,15 @@ func Provider() *schema.Provider { "ibm_cdn": classicinfrastructure.ResourceIBMCDN(), "ibm_hardware_firewall_shared": classicinfrastructure.ResourceIBMFirewallShared(), + // Partner Center Sell + "ibm_onboarding_registration": partnercentersell.ResourceIbmOnboardingRegistration(), + "ibm_onboarding_product": partnercentersell.ResourceIbmOnboardingProduct(), + "ibm_onboarding_iam_registration": partnercentersell.ResourceIbmOnboardingIamRegistration(), + "ibm_onboarding_catalog_product": partnercentersell.ResourceIbmOnboardingCatalogProduct(), + "ibm_onboarding_catalog_plan": partnercentersell.ResourceIbmOnboardingCatalogPlan(), + "ibm_onboarding_catalog_deployment": partnercentersell.ResourceIbmOnboardingCatalogDeployment(), + "ibm_onboarding_resource_broker": partnercentersell.ResourceIbmOnboardingResourceBroker(), + // Added for Power Colo "ibm_pi_capture": power.ResourceIBMPICapture(), "ibm_pi_cloud_connection_network_attach": power.ResourceIBMPICloudConnectionNetworkAttach(), @@ -1417,8 +1442,9 @@ func Provider() *schema.Provider { "ibm_pag_instance": pag.ResourceIBMPag(), // Added for Context Based Restrictions - "ibm_cbr_zone": contextbasedrestrictions.ResourceIBMCbrZone(), - "ibm_cbr_rule": contextbasedrestrictions.ResourceIBMCbrRule(), + "ibm_cbr_zone": contextbasedrestrictions.ResourceIBMCbrZone(), + "ibm_cbr_zone_addresses": contextbasedrestrictions.ResourceIBMCbrZoneAddresses(), + "ibm_cbr_rule": contextbasedrestrictions.ResourceIBMCbrRule(), // Added for Event Notifications "ibm_en_source": eventnotification.ResourceIBMEnSource(), @@ -1528,6 +1554,9 @@ func Provider() *schema.Provider { "ibm_logs_data_usage_metrics": logs.AddLogsInstanceFields(logs.ResourceIbmLogsDataUsageMetrics()), "ibm_logs_enrichment": logs.AddLogsInstanceFields(logs.ResourceIbmLogsEnrichment()), "ibm_logs_data_access_rule": logs.AddLogsInstanceFields(logs.ResourceIbmLogsDataAccessRule()), + + // Logs Router Service + "ibm_logs_router_tenant": logsrouting.ResourceIBMLogsRouterTenant(), }, ConfigureFunc: providerConfigure, @@ -1732,6 +1761,8 @@ func Validator() validate.ValidatorDict { "ibm_cis_ruleset_entrypoint_version": cis.ResourceIBMCISRulesetEntryPointVersionValidator(), "ibm_cis_ruleset_rule": cis.ResourceIBMCISRulesetRuleValidator(), "ibm_cis_ruleset_version_detach": cis.ResourceIBMCISRulesetVersionDetachValidator(), + "ibm_cis_advanced_certificate_pack_order": cis.ResourceIBMCISAdvancedCertificatePackOrderValidator(), + "ibm_cis_origin_certificate_order": cis.ResourceIBMCISOriginCertificateOrderValidator(), "ibm_container_cluster": kubernetes.ResourceIBMContainerClusterValidator(), "ibm_container_worker_pool": kubernetes.ResourceIBMContainerWorkerPoolValidator(), "ibm_container_vpc_worker_pool": kubernetes.ResourceIBMContainerVPCWorkerPoolValidator(), @@ -1854,10 +1885,22 @@ func Validator() validate.ValidatorDict { "ibm_metrics_router_route": metricsrouter.ResourceIBMMetricsRouterRouteValidator(), "ibm_metrics_router_settings": metricsrouter.ResourceIBMMetricsRouterSettingsValidator(), "ibm_satellite_endpoint": satellite.ResourceIBMSatelliteEndpointValidator(), - "ibm_cbr_zone": contextbasedrestrictions.ResourceIBMCbrZoneValidator(), - "ibm_cbr_rule": contextbasedrestrictions.ResourceIBMCbrRuleValidator(), "ibm_satellite_host": satellite.ResourceIBMSatelliteHostValidator(), + // Partner Center Sell + "ibm_onboarding_registration": partnercentersell.ResourceIbmOnboardingRegistrationValidator(), + "ibm_onboarding_product": partnercentersell.ResourceIbmOnboardingProductValidator(), + "ibm_onboarding_iam_registration": partnercentersell.ResourceIbmOnboardingIamRegistrationValidator(), + "ibm_onboarding_catalog_product": partnercentersell.ResourceIbmOnboardingCatalogProductValidator(), + "ibm_onboarding_catalog_plan": partnercentersell.ResourceIbmOnboardingCatalogPlanValidator(), + "ibm_onboarding_catalog_deployment": partnercentersell.ResourceIbmOnboardingCatalogDeploymentValidator(), + "ibm_onboarding_resource_broker": partnercentersell.ResourceIbmOnboardingResourceBrokerValidator(), + + // Added for Context Based Restrictions + "ibm_cbr_zone": contextbasedrestrictions.ResourceIBMCbrZoneValidator(), + "ibm_cbr_zone_addresses": contextbasedrestrictions.ResourceIBMCbrZoneAddressesValidator(), + "ibm_cbr_rule": contextbasedrestrictions.ResourceIBMCbrRuleValidator(), + // Added for SCC "ibm_scc_instance_settings": scc.ResourceIbmSccInstanceSettingsValidator(), "ibm_scc_rule": scc.ResourceIbmSccRuleValidator(), @@ -1969,6 +2012,9 @@ func Validator() validate.ValidatorDict { "ibm_logs_dashboard_folder": logs.ResourceIbmLogsDashboardFolderValidator(), "ibm_logs_enrichment": logs.ResourceIbmLogsEnrichmentValidator(), "ibm_logs_data_access_rule": logs.ResourceIbmLogsDataAccessRuleValidator(), + + // Added for Logs Router Service + "ibm_logs_router_tenant": logsrouting.ResourceIBMLogsRouterTenantValidator(), }, DataSourceValidatorDictionary: map[string]*validate.ResourceValidator{ "ibm_is_subnet": vpc.DataSourceIBMISSubnetValidator(), @@ -2018,6 +2064,7 @@ func Validator() validate.ValidatorDict { "ibm_cis_waf_packages": cis.DataSourceIBMCISWAFPackagesValidator(), "ibm_cis_waf_rules": cis.DataSourceIBMCISWAFRulesValidator(), "ibm_cis_logpush_jobs": cis.DataSourceIBMCISLogPushJobsValidator(), + "ibm_cis_origin_certificates": cis.DataIBMCISOriginCertificateOrderValidator(), "ibm_cos_bucket": cos.DataSourceIBMCosBucketValidator(), diff --git a/ibm/service/catalogmanagement/data_source_ibm_cm_catalog.go b/ibm/service/catalogmanagement/data_source_ibm_cm_catalog.go index d89a313b57..47b31b1680 100644 --- a/ibm/service/catalogmanagement/data_source_ibm_cm_catalog.go +++ b/ibm/service/catalogmanagement/data_source_ibm_cm_catalog.go @@ -300,14 +300,17 @@ func DataSourceIBMCmCatalog() *schema.Resource { func dataSourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } listCatalogsOptions := &catalogmanagementv1.ListCatalogsOptions{} catalogs, response, err := catalogManagementClient.ListCatalogsWithContext(context, listCatalogsOptions) if err != nil { - log.Printf("[DEBUG] ListCatalogsWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ListCatalogsWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ListCatalogsWithContext failed %s\n%s", err, response), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } var catalogId string @@ -318,8 +321,9 @@ func dataSourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, } if catalogId == "" { - log.Printf("[DEBUG] Could not find catalog from provided ID or label") - return diag.FromErr(fmt.Errorf("Could not find catalog from provided ID or label")) + tfErr := flex.TerraformErrorf(flex.FmtErrorf("Could not find catalog from provided ID or label"), "Could not find catalog from provided ID or label", "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getCatalogOptions := &catalogmanagementv1.GetCatalogOptions{} @@ -328,64 +332,81 @@ func dataSourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, catalog, response, err := catalogManagementClient.GetCatalogWithContext(context, getCatalogOptions) if err != nil { - log.Printf("[DEBUG] GetCatalogWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetCatalogWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetCatalogWithContext failed %s\n%s", err, response), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(fmt.Sprintf("%s", *getCatalogOptions.CatalogIdentifier)) if err = d.Set("id", catalog.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting id: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("rev", catalog.Rev); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rev: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("label", catalog.Label); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalog.LabelI18n != nil { if err = d.Set("label_i18n", catalog.LabelI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label_i18n: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting label_i18n %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label_i18n: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("short_description", catalog.ShortDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalog.ShortDescriptionI18n != nil { if err = d.Set("short_description_i18n", catalog.ShortDescriptionI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description_i18n: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description_i18n %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description_i18n: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("catalog_icon_url", catalog.CatalogIconURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_icon_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_icon_url: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_banner_url", catalog.CatalogBannerURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_banner_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_banner_url: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("url", catalog.URL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting url: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("crn", catalog.CRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offerings_url", catalog.OfferingsURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offerings_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offerings_url: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } features := []map[string]interface{}{} @@ -393,49 +414,69 @@ func dataSourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, for _, modelItem := range catalog.Features { modelMap, err := dataSourceIBMCmCatalogFeatureToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting features: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } features = append(features, modelMap) } } if err = d.Set("features", features); err != nil { - return diag.FromErr(fmt.Errorf("Error setting features %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting features: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("disabled", catalog.Disabled); err != nil { - return diag.FromErr(fmt.Errorf("Error setting disabled: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting disabled: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("created", flex.DateTimeToString(catalog.Created)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting created: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("updated", flex.DateTimeToString(catalog.Updated)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting updated: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("resource_group_id", catalog.ResourceGroupID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting resource_group_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting resource_group_id: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("owning_account", catalog.OwningAccount); err != nil { - return diag.FromErr(fmt.Errorf("Error setting owning_account: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting owning_account: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } catalogFilters := []map[string]interface{}{} if catalog.CatalogFilters != nil { modelMap, err := dataSourceIBMCmCatalogFiltersToMap(catalog.CatalogFilters) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_filters: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } catalogFilters = append(catalogFilters, modelMap) } if err = d.Set("catalog_filters", catalogFilters); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_filters %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_filters: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("kind", catalog.Kind); err != nil { - return diag.FromErr(fmt.Errorf("Error setting kind: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting kind: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalog.Metadata != nil { @@ -445,10 +486,9 @@ func dataSourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, } if err = d.Set("metadata", flex.Flatten(convertedMap)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting metadata: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting metadata %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting metadata: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -457,13 +497,17 @@ func dataSourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, for _, tacItem := range catalog.TargetAccountContexts { tacItemMap, err := resourceIBMCmCatalogTargetAccountContextToMap(&tacItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting target_account_contexts: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } targetAccountContexts = append(targetAccountContexts, tacItemMap) } } if err = d.Set("target_account_contexts", targetAccountContexts); err != nil { - return diag.FromErr(fmt.Errorf("Error setting target_account_contexts: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting target_account_contexts: %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil diff --git a/ibm/service/catalogmanagement/data_source_ibm_cm_object.go b/ibm/service/catalogmanagement/data_source_ibm_cm_object.go index d46e887163..e95b630020 100644 --- a/ibm/service/catalogmanagement/data_source_ibm_cm_object.go +++ b/ibm/service/catalogmanagement/data_source_ibm_cm_object.go @@ -196,7 +196,9 @@ func DataSourceIBMCmObject() *schema.Resource { func dataSourceIBMCmObjectRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getObjectOptions := &catalogmanagementv1.GetObjectOptions{} @@ -206,109 +208,144 @@ func dataSourceIBMCmObjectRead(context context.Context, d *schema.ResourceData, catalogObject, response, err := catalogManagementClient.GetObjectWithContext(context, getObjectOptions) if err != nil { - log.Printf("[DEBUG] GetObjectWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetObjectWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetObjectWithContext failed %s\n%s", err, response), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(*getObjectOptions.ObjectIdentifier) if err = d.Set("catalog_object_id", catalogObject.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_object_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_object_id: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("name", catalogObject.Name); err != nil { - return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting name: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("rev", catalogObject.Rev); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rev: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("crn", catalogObject.CRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("url", catalogObject.URL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting url: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("parent_id", catalogObject.ParentID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting parent_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting parent_id: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalogObject.LabelI18n != nil { if err = d.Set("label_i18n", catalogObject.LabelI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label_i18n: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting label_i18n %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label_i18n: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("label", catalogObject.Label); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("created", flex.DateTimeToString(catalogObject.Created)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting created: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("updated", flex.DateTimeToString(catalogObject.Updated)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting updated: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("short_description", catalogObject.ShortDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalogObject.ShortDescriptionI18n != nil { if err = d.Set("short_description_i18n", catalogObject.ShortDescriptionI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description_i18n: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description_i18n %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description_i18n: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("kind", catalogObject.Kind); err != nil { - return diag.FromErr(fmt.Errorf("Error setting kind: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting kind: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } publish := []map[string]interface{}{} if catalogObject.Publish != nil { modelMap, err := dataSourceIBMCmObjectPublishObjectToMap(catalogObject.Publish) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } publish = append(publish, modelMap) } if err = d.Set("publish", publish); err != nil { - return diag.FromErr(fmt.Errorf("Error setting publish %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting publish: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } state := []map[string]interface{}{} if catalogObject.State != nil { modelMap, err := dataSourceIBMCmObjectStateToMap(catalogObject.State) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } state = append(state, modelMap) } if err = d.Set("state", state); err != nil { - return diag.FromErr(fmt.Errorf("Error setting state %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting state: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_name", catalogObject.CatalogName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_name: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalogObject.Data != nil { dataString, err := json.Marshal(catalogObject.Data) if err != nil { - return diag.FromErr(fmt.Errorf("Error setting data, error with json marshal: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting data, error with json marshal: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("data", string(dataString)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting data: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting data: %s", err), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } diff --git a/ibm/service/catalogmanagement/data_source_ibm_cm_offering.go b/ibm/service/catalogmanagement/data_source_ibm_cm_offering.go index 761fa4559e..beba0f75a0 100644 --- a/ibm/service/catalogmanagement/data_source_ibm_cm_offering.go +++ b/ibm/service/catalogmanagement/data_source_ibm_cm_offering.go @@ -2016,12 +2016,6 @@ func DataSourceIBMCmOffering() *schema.Resource { Computed: true, Description: "Determine if this offering should be displayed in the Consumption UI.", }, - // "provider": &schema.Schema{ - // Type: schema.TypeString, - // Computed: true, - // Deprecated: "This argument is deprecated", - // Description: "Deprecated - Provider of this offering.", - // }, "provider_info": &schema.Schema{ Type: schema.TypeList, Computed: true, @@ -2446,7 +2440,9 @@ func DataSourceIBMCmOffering() *schema.Resource { func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getOfferingOptions := &catalogmanagementv1.GetOfferingOptions{} @@ -2456,55 +2452,73 @@ func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData offering, response, err := catalogManagementClient.GetOfferingWithContext(context, getOfferingOptions) if err != nil { - log.Printf("[DEBUG] GetOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetOfferingWithContext failed %s\n%s", err, response), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(*getOfferingOptions.OfferingID) if err = d.Set("rev", offering.Rev); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rev: %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_identifier", offering.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_identifier: %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("url", offering.URL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting url: %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("crn", offering.CRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("label", offering.Label); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label: %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if offering.LabelI18n != nil { if err = d.Set("label_i18n", offering.LabelI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label_i18n: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting label_i18n %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label_i18n: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("name", offering.Name); err != nil { - return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting name: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_icon_url", offering.OfferingIconURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering_icon_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_icon_url: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_docs_url", offering.OfferingDocsURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering_docs_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_docs_url: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_support_url", offering.OfferingSupportURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering_support_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_support_url: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } tags := []string{} @@ -2512,7 +2526,9 @@ func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData tags = offering.Tags } if err = d.Set("tags", tags); err != nil { - return diag.FromErr(fmt.Errorf("Error setting tags: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting tags: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } keywords := []string{} @@ -2520,52 +2536,64 @@ func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData keywords = offering.Keywords } if err = d.Set("keywords", keywords); err != nil { - return diag.FromErr(fmt.Errorf("Error setting keywords: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting keywords: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } rating := []map[string]interface{}{} if offering.Rating != nil { modelMap, err := dataSourceIBMCmOfferingRatingToMap(offering.Rating) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } rating = append(rating, modelMap) } if err = d.Set("rating", rating); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rating %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rating : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("created", flex.DateTimeToString(offering.Created)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting created: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("updated", flex.DateTimeToString(offering.Updated)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting updated: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("short_description", offering.ShortDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if offering.ShortDescriptionI18n != nil { if err = d.Set("short_description_i18n", offering.ShortDescriptionI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description_i18n: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description_i18n %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description_i18n: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("long_description", offering.LongDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting long_description: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if offering.LongDescriptionI18n != nil { if err = d.Set("long_description_i18n", offering.LongDescriptionI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description_i18n: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description_i18n %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting long_description_i18n: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -2574,13 +2602,17 @@ func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData for _, modelItem := range offering.Features { modelMap, err := dataSourceIBMCmOfferingFeatureToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } features = append(features, modelMap) } } if err = d.Set("features", features); err != nil { - return diag.FromErr(fmt.Errorf("Error setting features %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting features : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } kinds := []map[string]interface{}{} @@ -2588,57 +2620,83 @@ func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData for _, modelItem := range offering.Kinds { modelMap, err := dataSourceIBMCmOfferingKindToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } kinds = append(kinds, modelMap) } } if err = d.Set("kinds", kinds); err != nil { - return diag.FromErr(fmt.Errorf("Error setting kinds %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting kinds : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("pc_managed", offering.PcManaged); err != nil { - return diag.FromErr(fmt.Errorf("Error setting pc_managed: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting pc_managed: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("publish_approved", offering.PublishApproved); err != nil { - return diag.FromErr(fmt.Errorf("Error setting publish_approved: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting publish_approved: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("share_with_all", offering.ShareWithAll); err != nil { - return diag.FromErr(fmt.Errorf("Error setting share_with_all: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting share_with_all: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("share_with_ibm", offering.ShareWithIBM); err != nil { - return diag.FromErr(fmt.Errorf("Error setting share_with_ibm: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting share_with_ibm: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("share_enabled", offering.ShareEnabled); err != nil { - return diag.FromErr(fmt.Errorf("Error setting share_enabled: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting share_enabled: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("public_original_crn", offering.PublicOriginalCRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting public_original_crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting public_original_crn: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("publish_public_crn", offering.PublishPublicCRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting publish_public_crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting publish_public_crn: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("portal_approval_record", offering.PortalApprovalRecord); err != nil { - return diag.FromErr(fmt.Errorf("Error setting portal_approval_record: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting portal_approval_record: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("portal_ui_url", offering.PortalUIURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting portal_ui_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting portal_ui_url: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_id", offering.CatalogID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_id: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_name", offering.CatalogName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_name: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if offering.Metadata != nil { @@ -2648,47 +2706,54 @@ func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData } if err = d.Set("metadata", flex.Flatten(convertedMap)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting metadata: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting metadata %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting metadata: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("disclaimer", offering.Disclaimer); err != nil { - return diag.FromErr(fmt.Errorf("Error setting disclaimer: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting disclaimer: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("hidden", offering.Hidden); err != nil { - return diag.FromErr(fmt.Errorf("Error setting hidden: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting hidden: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } - // if err = d.Set("provider", offering.Provider); err != nil { - // return diag.FromErr(fmt.Errorf("Error setting provider: %s", err)) - // } - providerInfo := []map[string]interface{}{} if offering.ProviderInfo != nil { modelMap, err := dataSourceIBMCmOfferingProviderInfoToMap(offering.ProviderInfo) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } providerInfo = append(providerInfo, modelMap) } if err = d.Set("provider_info", providerInfo); err != nil { - return diag.FromErr(fmt.Errorf("Error setting provider_info %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting provider_info : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } repoInfo := []map[string]interface{}{} if offering.RepoInfo != nil { modelMap, err := dataSourceIBMCmOfferingRepoInfoToMap(offering.RepoInfo) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } repoInfo = append(repoInfo, modelMap) } if err = d.Set("repo_info", repoInfo); err != nil { - return diag.FromErr(fmt.Errorf("Error setting repo_info %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting repo_info : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } imagePullKeys := []map[string]interface{}{} @@ -2696,25 +2761,33 @@ func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData for _, modelItem := range offering.ImagePullKeys { modelMap, err := dataSourceIBMCmOfferingImagePullKeyToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } imagePullKeys = append(imagePullKeys, modelMap) } } if err = d.Set("image_pull_keys", imagePullKeys); err != nil { - return diag.FromErr(fmt.Errorf("Error setting image_pull_keys %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting image_pull_keys : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } support := []map[string]interface{}{} if offering.Support != nil { modelMap, err := dataSourceIBMCmOfferingSupportToMap(offering.Support) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } support = append(support, modelMap) } if err = d.Set("support", support); err != nil { - return diag.FromErr(fmt.Errorf("Error setting support %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting support : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } media := []map[string]interface{}{} @@ -2722,29 +2795,39 @@ func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData for _, modelItem := range offering.Media { modelMap, err := dataSourceIBMCmOfferingMediaItemToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } media = append(media, modelMap) } } if err = d.Set("media", media); err != nil { - return diag.FromErr(fmt.Errorf("Error setting media %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting media : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } deprecatePending := []map[string]interface{}{} if offering.DeprecatePending != nil { modelMap, err := dataSourceIBMCmOfferingDeprecatePendingToMap(offering.DeprecatePending) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } deprecatePending = append(deprecatePending, modelMap) } if err = d.Set("deprecate_pending", deprecatePending); err != nil { - return diag.FromErr(fmt.Errorf("Error setting deprecate_pending %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting deprecate_pending : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("product_kind", offering.ProductKind); err != nil { - return diag.FromErr(fmt.Errorf("Error setting product_kind: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting product_kind: : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } badges := []map[string]interface{}{} @@ -2752,13 +2835,17 @@ func dataSourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData for _, modelItem := range offering.Badges { modelMap, err := dataSourceIBMCmOfferingBadgeToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } badges = append(badges, modelMap) } } if err = d.Set("badges", badges); err != nil { - return diag.FromErr(fmt.Errorf("Error setting badges %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting badges : %s", err), "(Data) ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil @@ -2822,9 +2909,6 @@ func dataSourceIBMCmOfferingKindToMap(model *catalogmanagementv1.Kind) (map[stri } if model.Metadata != nil { metadataMap := make(map[string]interface{}, len(model.Metadata)) - // k, v unused - // for k, v := range model.Metadata { - // } modelMap["metadata"] = flex.Flatten(metadataMap) } if model.Tags != nil { @@ -2945,10 +3029,6 @@ func dataSourceIBMCmOfferingVersionToMap(model *catalogmanagementv1.Version) (ma } modelMap["iam_permissions"] = iamPermissions } - // if model.Metadata != nil { - // metadataSlice := []map[string]interface{}{model.Metadata} - // modelMap["metadata"] = metadataSlice - // } metadata := []map[string]interface{}{} if model.Metadata != nil { var modelMapVSI map[string]interface{} @@ -3114,7 +3194,7 @@ func dataSourceIBMCmOfferingConfigurationToMap(model *catalogmanagementv1.Config if model.DefaultValue != nil { defaultValueJson, err := json.Marshal(model.DefaultValue) if err != nil { - return nil, fmt.Errorf("[ERROR] Error marshalling the version configuration default_value: %s", err) + return nil, flex.FmtErrorf("[ERROR] Error marshalling the version configuration default_value: %s", err) } defaultValueString, _ := strconv.Unquote(string(defaultValueJson)) modelMap["default_value"] = defaultValueString @@ -3266,8 +3346,6 @@ func dataSourceIBMCmOfferingValidationToMap(model *catalogmanagementv1.Validatio } if model.Target != nil { targetMap := make(map[string]interface{}, len(model.Target)) - // for k, v := range model.Target { - // } modelMap["target"] = flex.Flatten(targetMap) } if model.Message != nil { @@ -3556,8 +3634,6 @@ func dataSourceIBMCmOfferingProjectToMap(model *catalogmanagementv1.Project) (ma } if model.Metadata != nil { metadataMap := make(map[string]interface{}, len(model.Metadata)) - // for k, v := range model.Metadata { - // } modelMap["metadata"] = flex.Flatten(metadataMap) } if model.PastBreakdown != nil { @@ -3620,8 +3696,6 @@ func dataSourceIBMCmOfferingCostResourceToMap(model *catalogmanagementv1.CostRes } if model.Metadata != nil { metadataMap := make(map[string]interface{}, len(model.Metadata)) - // for k, v := range model.Metadata { - // } modelMap["metadata"] = flex.Flatten(metadataMap) } if model.HourlyCost != nil { diff --git a/ibm/service/catalogmanagement/data_source_ibm_cm_offering_instance.go b/ibm/service/catalogmanagement/data_source_ibm_cm_offering_instance.go index 7bd590a40b..98a0ce3bbd 100644 --- a/ibm/service/catalogmanagement/data_source_ibm_cm_offering_instance.go +++ b/ibm/service/catalogmanagement/data_source_ibm_cm_offering_instance.go @@ -9,6 +9,7 @@ import ( "log" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -125,7 +126,9 @@ func DataSourceIBMCmOfferingInstance() *schema.Resource { func dataSourceIBMCmOfferingInstanceRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getOfferingInstanceOptions := &catalogmanagementv1.GetOfferingInstanceOptions{} @@ -134,65 +137,102 @@ func dataSourceIBMCmOfferingInstanceRead(context context.Context, d *schema.Reso offeringInstance, response, err := catalogManagementClient.GetOfferingInstanceWithContext(context, getOfferingInstanceOptions) if err != nil { - log.Printf("[DEBUG] GetOfferingInstanceWithContext failed %s\n%s", err, response) - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetOfferingInstanceWithContext failed %s\n%s", err, response), "(Data) ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(*offeringInstance.ID) if err = d.Set("url", offeringInstance.URL); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting url: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("crn", offeringInstance.CRN); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("_rev", offeringInstance.Rev); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting _rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting _rev: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("label", offeringInstance.Label); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting label: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_id", offeringInstance.CatalogID); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting catalog_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_id: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_id", offeringInstance.OfferingID); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting offering_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_id: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("kind_format", offeringInstance.KindFormat); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting kind_format: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting kind_format: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("version", offeringInstance.Version); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting version: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting version: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("cluster_id", offeringInstance.ClusterID); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting cluster_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting cluster_id: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("cluster_region", offeringInstance.ClusterRegion); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting cluster_region: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting cluster_region: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("cluster_namespaces", offeringInstance.ClusterNamespaces); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting cluster_namespaces: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting cluster_namespaces: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("cluster_all_namespaces", offeringInstance.ClusterAllNamespaces); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting cluster_all_namespaces: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting cluster_all_namespaces: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("schematics_workspace_id", offeringInstance.SchematicsWorkspaceID); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting schematics_workspace_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting schematics_workspace_id: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("resource_group_id", offeringInstance.ResourceGroupID); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting resource_group_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting resource_group_id: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("install_plan", offeringInstance.InstallPlan); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting install_plan: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting install_plan: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("channel", offeringInstance.Channel); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting channel: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting channel: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("plan_id", offeringInstance.PlanID); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting plan_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting plan_id: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("parent_crn", offeringInstance.ParentCRN); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting parent_crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting parent_crn: %s", err), "(Data) ibm_cm_offering_instance", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil diff --git a/ibm/service/catalogmanagement/data_source_ibm_cm_preset.go b/ibm/service/catalogmanagement/data_source_ibm_cm_preset.go index ffa832af20..b2376b270d 100644 --- a/ibm/service/catalogmanagement/data_source_ibm_cm_preset.go +++ b/ibm/service/catalogmanagement/data_source_ibm_cm_preset.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/platform-services-go-sdk/catalogmanagementv1" ) @@ -40,17 +41,23 @@ func DataSourceIBMCmPreset() *schema.Resource { func dataSourceIBMCmPresetRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_preset", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } presetID := d.Get("id").(string) regex := "[A-Za-z0-9]+-[A-Za-z0-9]+-[A-Za-z0-9]+-[A-Za-z0-9]+-[A-Za-z0-9]+-([A-Za-z0-9]+(_[A-Za-z0-9]+)+)@[A-Za-z0-9]" match, err := regexp.MatchString(regex, presetID) if err != nil { - return diag.FromErr(fmt.Errorf("error attempting regex match string %s", err)) + tfErr := flex.TerraformErrorf(flex.FmtErrorf("error attempting regex match string %s", err), fmt.Sprintf("error attempting regex match string %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if !match { - return diag.FromErr(fmt.Errorf("Error: Preset ID does not match required format. Must be -@ %s", err)) + tfErr := flex.TerraformErrorf(flex.FmtErrorf("Error: Preset ID does not match required format. Must be -@ %s", err), fmt.Sprintf("Error: Preset ID does not match required format. Must be -@ %s", err), "(Data) ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } splitID := strings.Split(presetID, "@") version := splitID[len(splitID)-1] @@ -65,31 +72,44 @@ func dataSourceIBMCmPresetRead(context context.Context, d *schema.ResourceData, catalogObject, response, err := catalogManagementClient.GetObjectWithContext(context, getObjectOptions) if err != nil { - log.Printf("[DEBUG] GetObjectWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetObjectWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetObjectWithContext failed %s\n%s", err, response), "(Data) ibm_cm_preset", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(presetID) if catalogObject.Data == nil { - return diag.FromErr(fmt.Errorf("Error setting preset, object data is nil. %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting preset, object data is nil: %s", err), "(Data) ibm_cm_preset", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalogObject.Data["versions"] == nil { - return diag.FromErr(fmt.Errorf("Error setting preset, object data.versions is nil. %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting preset, object data.versions is nil: %s", err), "(Data) ibm_cm_preset", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalogObject.Data["versions"].(map[string]interface{})[version] == nil { - return diag.FromErr(fmt.Errorf("Error setting preset, could not find preset with version %s. %s", version, err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting preset, could not find preset with version %s. %s", version, err), "(Data) ibm_cm_preset", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalogObject.Data["versions"].(map[string]interface{})[version].(map[string]interface{})["preset"] == nil { - return diag.FromErr(fmt.Errorf("Error setting preset, preset field not found in version %s. %s", version, err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting preset, preset field not found in version %s. %s", version, err), "(Data) ibm_cm_preset", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } presetMap, err := json.Marshal(catalogObject.Data["versions"].(map[string]interface{})[version].(map[string]interface{})["preset"]) if err != nil { - return diag.FromErr(fmt.Errorf("Error setting preset, error with json marshal: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting preset, error with json marshal: %s", err), "(Data) ibm_cm_preset", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("preset", string(presetMap)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting preset: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting preset: %s", err), "(Data) ibm_cm_preset", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil diff --git a/ibm/service/catalogmanagement/data_source_ibm_cm_version.go b/ibm/service/catalogmanagement/data_source_ibm_cm_version.go index 644f309ee8..88c7143c28 100644 --- a/ibm/service/catalogmanagement/data_source_ibm_cm_version.go +++ b/ibm/service/catalogmanagement/data_source_ibm_cm_version.go @@ -1615,7 +1615,9 @@ func DataSourceIBMCmVersion() *schema.Resource { func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getVersionOptions := &catalogmanagementv1.GetVersionOptions{} @@ -1624,75 +1626,106 @@ func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, offering, response, err := catalogManagementClient.GetVersionWithContext(context, getVersionOptions) if err != nil { - log.Printf("[DEBUG] GetVersionWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetVersionWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetVersionWithContext failed %s\n%s", err, response), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } version := offering.Kinds[0].Versions[0] d.SetId(*getVersionOptions.VersionLocID) if err = d.Set("version_id", version.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting version_id: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("rev", version.Rev); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rev: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("crn", version.CRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("version", version.Version); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting version: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } flavor := []map[string]interface{}{} if version.Flavor != nil { modelMap, err := dataSourceIBMCmVersionFlavorToMap(version.Flavor) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } flavor = append(flavor, modelMap) } if err = d.Set("flavor", flavor); err != nil { - return diag.FromErr(fmt.Errorf("Error setting flavor %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting flavor: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("sha", version.Sha); err != nil { - return diag.FromErr(fmt.Errorf("Error setting sha: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting sha: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("created", flex.DateTimeToString(version.Created)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting created: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("updated", flex.DateTimeToString(version.Updated)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting updated: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_id", version.OfferingID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_id: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_id", version.CatalogID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_id: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("kind_id", version.KindID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting kind_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting kind_id: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("repo_url", version.RepoURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting repo_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting repo_url: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("source_url", version.SourceURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting source_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting source_url: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("tgz_url", version.TgzURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting tgz_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting tgz_url: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } configuration := []map[string]interface{}{} @@ -1700,13 +1733,17 @@ func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, for _, modelItem := range version.Configuration { modelMap, err := dataSourceIBMCmVersionConfigurationToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } configuration = append(configuration, modelMap) } } if err = d.Set("configuration", configuration); err != nil { - return diag.FromErr(fmt.Errorf("Error setting configuration %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting configuration: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } outputs := []map[string]interface{}{} @@ -1714,13 +1751,17 @@ func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, for _, modelItem := range version.Outputs { modelMap, err := dataSourceIBMCmVersionOutputToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } outputs = append(outputs, modelMap) } } if err = d.Set("outputs", outputs); err != nil { - return diag.FromErr(fmt.Errorf("Error setting outputs %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting outputs: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } iamPermissions := []map[string]interface{}{} @@ -1728,13 +1769,17 @@ func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, for _, modelItem := range version.IamPermissions { modelMap, err := dataSourceIBMCmVersionIamPermissionToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } iamPermissions = append(iamPermissions, modelMap) } } if err = d.Set("iam_permissions", iamPermissions); err != nil { - return diag.FromErr(fmt.Errorf("Error setting iam_permissions %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting iam_permissions: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } metadata := []map[string]interface{}{} @@ -1743,7 +1788,9 @@ func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, if version.Metadata["vsi_vpc"] != nil { modelMapVSI, err = dataSourceIBMCmVersionMetadataVSIToMap(version.Metadata["vsi_vpc"].(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } convertedMap := make(map[string]interface{}, len(version.Metadata)) @@ -1757,19 +1804,25 @@ func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, metadata = append(metadata, convertedMap) } if err = d.Set("metadata", metadata); err != nil { - return diag.FromErr(fmt.Errorf("Error setting metadata %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting metadata: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } validation := []map[string]interface{}{} if version.Validation != nil { modelMap, err := dataSourceIBMCmVersionValidationToMap(version.Validation) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } validation = append(validation, modelMap) } if err = d.Set("validation", validation); err != nil { - return diag.FromErr(fmt.Errorf("Error setting validation %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting validation: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } requiredResources := []map[string]interface{}{} @@ -1777,29 +1830,39 @@ func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, for _, modelItem := range version.RequiredResources { modelMap, err := dataSourceIBMCmVersionResourceToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } requiredResources = append(requiredResources, modelMap) } } if err = d.Set("required_resources", requiredResources); err != nil { - return diag.FromErr(fmt.Errorf("Error setting required_resources %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting required_resources: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("single_instance", version.SingleInstance); err != nil { - return diag.FromErr(fmt.Errorf("Error setting single_instance: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting single_instance: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } install := []map[string]interface{}{} if version.Install != nil { modelMap, err := dataSourceIBMCmVersionScriptToMap(version.Install) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } install = append(install, modelMap) } if err = d.Set("install", install); err != nil { - return diag.FromErr(fmt.Errorf("Error setting install %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting install: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } preInstall := []map[string]interface{}{} @@ -1807,25 +1870,33 @@ func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, for _, modelItem := range version.PreInstall { modelMap, err := dataSourceIBMCmVersionScriptToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } preInstall = append(preInstall, modelMap) } } if err = d.Set("pre_install", preInstall); err != nil { - return diag.FromErr(fmt.Errorf("Error setting pre_install %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting pre_install: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } entitlement := []map[string]interface{}{} if version.Entitlement != nil { modelMap, err := dataSourceIBMCmVersionVersionEntitlementToMap(version.Entitlement) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } entitlement = append(entitlement, modelMap) } if err = d.Set("entitlement", entitlement); err != nil { - return diag.FromErr(fmt.Errorf("Error setting entitlement %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting entitlement: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } licenses := []map[string]interface{}{} @@ -1833,86 +1904,115 @@ func dataSourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, for _, modelItem := range version.Licenses { modelMap, err := dataSourceIBMCmVersionLicenseToMap(&modelItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } licenses = append(licenses, modelMap) } } if err = d.Set("licenses", licenses); err != nil { - return diag.FromErr(fmt.Errorf("Error setting licenses %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting licenses: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("image_manifest_url", version.ImageManifestURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting image_manifest_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting image_manifest_url: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("deprecated", version.Deprecated); err != nil { - return diag.FromErr(fmt.Errorf("Error setting deprecated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting deprecated: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("package_version", version.PackageVersion); err != nil { - return diag.FromErr(fmt.Errorf("Error setting package_version: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting package_version: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } state := []map[string]interface{}{} if version.State != nil { modelMap, err := dataSourceIBMCmVersionStateToMap(version.State) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } state = append(state, modelMap) } if err = d.Set("state", state); err != nil { - return diag.FromErr(fmt.Errorf("Error setting state %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting state: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("version_locator", version.VersionLocator); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version_locator: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting version_locator: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("long_description", version.LongDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting long_description: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if version.LongDescriptionI18n != nil { if err = d.Set("long_description_i18n", version.LongDescriptionI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description_i18n: %s", err)) - } - if err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description_i18n %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting long_description_i18n: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("image_pull_key_name", version.ImagePullKeyName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting image_pull_key_name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting image_pull_key_name: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } deprecatePending := []map[string]interface{}{} if version.DeprecatePending != nil { modelMap, err := dataSourceIBMCmVersionDeprecatePendingToMap(version.DeprecatePending) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } deprecatePending = append(deprecatePending, modelMap) } if err = d.Set("deprecate_pending", deprecatePending); err != nil { - return diag.FromErr(fmt.Errorf("Error setting deprecate_pending %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting deprecate_pending: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } solutionInfo := []map[string]interface{}{} if version.SolutionInfo != nil { modelMap, err := dataSourceIBMCmVersionSolutionInfoToMap(version.SolutionInfo) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } solutionInfo = append(solutionInfo, modelMap) } if err = d.Set("solution_info", solutionInfo); err != nil { - return diag.FromErr(fmt.Errorf("Error setting solution_info %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting solution_info: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("is_consumable", version.IsConsumable); err != nil { - return diag.FromErr(fmt.Errorf("Error setting is_consumable: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting is_consumable: %s", err), "(Data) ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil diff --git a/ibm/service/catalogmanagement/resource_ibm_cm_catalog.go b/ibm/service/catalogmanagement/resource_ibm_cm_catalog.go index 188df0b1bf..54133acdf3 100644 --- a/ibm/service/catalogmanagement/resource_ibm_cm_catalog.go +++ b/ibm/service/catalogmanagement/resource_ibm_cm_catalog.go @@ -283,7 +283,9 @@ func ResourceIBMCmCatalog() *schema.Resource { func resourceIBMCmCatalogCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } createCatalogOptions := &catalogmanagementv1.CreateCatalogOptions{} @@ -309,7 +311,9 @@ func resourceIBMCmCatalogCreate(context context.Context, d *schema.ResourceData, value := e.(map[string]interface{}) featuresItem, err := resourceIBMCmCatalogMapToFeature(value) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "create") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } features = append(features, *featuresItem) } @@ -327,7 +331,9 @@ func resourceIBMCmCatalogCreate(context context.Context, d *schema.ResourceData, if _, ok := d.GetOk("catalog_filters"); ok { catalogFiltersModel, err := resourceIBMCmCatalogMapToFilters(d.Get("catalog_filters.0").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "create") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } createCatalogOptions.SetCatalogFilters(catalogFiltersModel) } @@ -340,7 +346,9 @@ func resourceIBMCmCatalogCreate(context context.Context, d *schema.ResourceData, value := e.(map[string]interface{}) targetAccountContextsItem, err := resourceIBMCmCatalogMapToTargetAccountContexts(nil, value) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "create") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } target_account_contexts = append(target_account_contexts, *targetAccountContextsItem) } @@ -349,8 +357,9 @@ func resourceIBMCmCatalogCreate(context context.Context, d *schema.ResourceData, catalog, response, err := catalogManagementClient.CreateCatalogWithContext(context, createCatalogOptions) if err != nil { - log.Printf("[DEBUG] CreateCatalogWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("CreateCatalogWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateCatalogWithContext failed %s\n%s", err, response), "ibm_cm_catalog", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(*catalog.ID) @@ -361,7 +370,9 @@ func resourceIBMCmCatalogCreate(context context.Context, d *schema.ResourceData, func resourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getCatalogOptions := &catalogmanagementv1.GetCatalogOptions{} @@ -373,28 +384,41 @@ func resourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, m d.SetId("") return nil } - log.Printf("[DEBUG] GetCatalogWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetCatalogWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetCatalogWithContext failed %s\n%s", err, response), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("rev", catalog.Rev); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rev: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("label", catalog.Label); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("short_description", catalog.ShortDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_icon_url", catalog.CatalogIconURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_icon_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_icon_url: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_banner_url", catalog.CatalogBannerURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_banner_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_banner_url: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalog.Tags != nil { if err = d.Set("tags", catalog.Tags); err != nil { - return diag.FromErr(fmt.Errorf("Error setting tags: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting tags: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } features := []map[string]interface{}{} @@ -402,65 +426,97 @@ func resourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, m for _, featuresItem := range catalog.Features { featuresItemMap, err := resourceIBMCmCatalogFeatureToMap(&featuresItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } features = append(features, featuresItemMap) } } if err = d.Set("features", features); err != nil { - return diag.FromErr(fmt.Errorf("Error setting features: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting features: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("disabled", catalog.Disabled); err != nil { - return diag.FromErr(fmt.Errorf("Error setting disabled: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting disabled: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("resource_group_id", catalog.ResourceGroupID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting resource_group_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting resource_group_id: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("owning_account", catalog.OwningAccount); err != nil { - return diag.FromErr(fmt.Errorf("Error setting owning_account: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting owning_account: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalog.CatalogFilters != nil { catalogFiltersMap, err := resourceIBMCmCatalogFiltersToMap(catalog.CatalogFilters) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_filters", []map[string]interface{}{catalogFiltersMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_filters: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_filters: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("kind", catalog.Kind); err != nil { - return diag.FromErr(fmt.Errorf("Error setting kind: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting kind: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("rev", catalog.Rev); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rev: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("url", catalog.URL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting url: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("crn", catalog.CRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offerings_url", catalog.OfferingsURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offerings_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offerings_url: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("created", flex.DateTimeToString(catalog.Created)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting created: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("updated", flex.DateTimeToString(catalog.Updated)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting updated: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } targetAccountContexts := []map[string]interface{}{} if catalog.TargetAccountContexts != nil { for _, tacItem := range catalog.TargetAccountContexts { tacItemMap, err := resourceIBMCmCatalogTargetAccountContextToMap(&tacItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } targetAccountContexts = append(targetAccountContexts, tacItemMap) } } if err = d.Set("target_account_contexts", targetAccountContexts); err != nil { - return diag.FromErr(fmt.Errorf("Error setting target_account_contexts: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting target_account_contexts: %s", err), "ibm_cm_catalog", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil @@ -469,7 +525,9 @@ func resourceIBMCmCatalogRead(context context.Context, d *schema.ResourceData, m func resourceIBMCmCatalogUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "update") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getCatalogOptions := &catalogmanagementv1.GetCatalogOptions{} @@ -481,8 +539,9 @@ func resourceIBMCmCatalogUpdate(context context.Context, d *schema.ResourceData, d.SetId("") return nil } - log.Printf("[DEBUG] GetCatalogWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetCatalogWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetCatalogWithContext failed %s\n%s", err, response), "ibm_cm_catalog", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } replaceCatalogOptions := &catalogmanagementv1.ReplaceCatalogOptions{} @@ -511,7 +570,9 @@ func resourceIBMCmCatalogUpdate(context context.Context, d *schema.ResourceData, value := e.(map[string]interface{}) featuresItem, err := resourceIBMCmCatalogMapToFeature(value) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "update") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } features = append(features, *featuresItem) } @@ -529,7 +590,9 @@ func resourceIBMCmCatalogUpdate(context context.Context, d *schema.ResourceData, if _, ok := d.GetOk("catalog_filters"); ok { catalogFilters, err := resourceIBMCmCatalogMapToFilters(d.Get("catalog_filters.0").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "update") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } replaceCatalogOptions.SetCatalogFilters(catalogFilters) } @@ -542,7 +605,9 @@ func resourceIBMCmCatalogUpdate(context context.Context, d *schema.ResourceData, value := e.(map[string]interface{}) targetAccountContextsItem, err := resourceIBMCmCatalogMapToTargetAccountContexts(catalog, value) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "update") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } target_account_contexts = append(target_account_contexts, *targetAccountContextsItem) } @@ -551,8 +616,9 @@ func resourceIBMCmCatalogUpdate(context context.Context, d *schema.ResourceData, _, response, err = catalogManagementClient.ReplaceCatalogWithContext(context, replaceCatalogOptions) if err != nil { - log.Printf("[DEBUG] ReplaceCatalogWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ReplaceCatalogWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ReplaceCatalogWithContext failed %s\n%s", err, response), "ibm_cm_catalog", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return resourceIBMCmCatalogRead(context, d, meta) @@ -561,7 +627,9 @@ func resourceIBMCmCatalogUpdate(context context.Context, d *schema.ResourceData, func resourceIBMCmCatalogDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_catalog", "delete") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } deleteCatalogOptions := &catalogmanagementv1.DeleteCatalogOptions{} @@ -570,8 +638,9 @@ func resourceIBMCmCatalogDelete(context context.Context, d *schema.ResourceData, response, err := catalogManagementClient.DeleteCatalogWithContext(context, deleteCatalogOptions) if err != nil { - log.Printf("[DEBUG] DeleteCatalogWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteCatalogWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteCatalogWithContext failed %s\n%s", err, response), "ibm_cm_catalog", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId("") diff --git a/ibm/service/catalogmanagement/resource_ibm_cm_object.go b/ibm/service/catalogmanagement/resource_ibm_cm_object.go index 86676b23c9..6a94b92e2a 100644 --- a/ibm/service/catalogmanagement/resource_ibm_cm_object.go +++ b/ibm/service/catalogmanagement/resource_ibm_cm_object.go @@ -194,7 +194,9 @@ func ResourceIBMCmObject() *schema.Resource { func resourceIBMCmObjectCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_object", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } createObjectOptions := &catalogmanagementv1.CreateObjectOptions{} @@ -221,8 +223,9 @@ func resourceIBMCmObjectCreate(context context.Context, d *schema.ResourceData, catalogObject, response, err := catalogManagementClient.CreateObjectWithContext(context, createObjectOptions) if err != nil { - log.Printf("[DEBUG] CreateObjectWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("CreateObjectWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateObjectWithContext failed %s\n%s", err, response), "ibm_cm_object", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(*catalogObject.ID) @@ -266,14 +269,17 @@ func resourceIBMCmObjectCreate(context context.Context, d *schema.ResourceData, } err = json.Unmarshal([]byte(dataString), &dataMap) if err != nil { - return diag.FromErr(fmt.Errorf("error unmarshalling json %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("error unmarshalling json %s", err), "ibm_cm_object", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } replaceObjectOptions.SetData(dataMap) catalogObject, response, err = catalogManagementClient.ReplaceObjectWithContext(context, replaceObjectOptions) if err != nil { - log.Printf("[DEBUG] ReplaceObjectWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ReplaceObjectWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ReplaceObjectWithContext failed %s\n%s", err, response), "ibm_cm_object", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -283,7 +289,9 @@ func resourceIBMCmObjectCreate(context context.Context, d *schema.ResourceData, func resourceIBMCmObjectRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getObjectOptions := &catalogmanagementv1.GetObjectOptions{} @@ -297,27 +305,40 @@ func resourceIBMCmObjectRead(context context.Context, d *schema.ResourceData, me d.SetId("") return nil } - log.Printf("[DEBUG] GetObjectWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetObjectWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetObjectWithContext failed %s\n%s", err, response), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_id", getObjectOptions.CatalogIdentifier); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_id: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("name", catalogObject.Name); err != nil { - return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting name: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("crn", catalogObject.CRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("url", catalogObject.URL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting url: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("parent_id", catalogObject.ParentID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting parent_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting parent_id: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("label", catalogObject.Label); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalogObject.Tags != nil { modifiedTags := []string{} @@ -327,61 +348,91 @@ func resourceIBMCmObjectRead(context context.Context, d *schema.ResourceData, me } } if err = d.Set("tags", modifiedTags); err != nil { - return diag.FromErr(fmt.Errorf("Error setting tags: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting tags: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("created", flex.DateTimeToString(catalogObject.Created)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting created: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("updated", flex.DateTimeToString(catalogObject.Updated)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting updated: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("short_description", catalogObject.ShortDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("kind", catalogObject.Kind); err != nil { - return diag.FromErr(fmt.Errorf("Error setting kind: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting kind: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } publishMap := map[string]interface{}{} if catalogObject.Publish != nil { publishMap, err = resourceIBMCmObjectPublishObjectToMap(catalogObject.Publish) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("publish", []map[string]interface{}{publishMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting publish: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting publish: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalogObject.State != nil { stateMap, err := resourceIBMCmObjectStateToMap(catalogObject.State) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("state", []map[string]interface{}{stateMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting state: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting state: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("catalog_id", catalogObject.CatalogID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_id: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_name", catalogObject.CatalogName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_name: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if catalogObject.Data != nil { dataString, err := json.Marshal(catalogObject.Data) if err != nil { - return diag.FromErr(fmt.Errorf("Error setting data, error with json marshal: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting data, error with json marshal: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("data", string(dataString)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting data: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting data: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("rev", catalogObject.Rev); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rev: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("object_id", catalogObject.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting object_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting object_id: %s", err), "ibm_cm_object", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil @@ -390,7 +441,9 @@ func resourceIBMCmObjectRead(context context.Context, d *schema.ResourceData, me func resourceIBMCmObjectUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_object", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getObjectOptions := &catalogmanagementv1.GetObjectOptions{} @@ -404,8 +457,9 @@ func resourceIBMCmObjectUpdate(context context.Context, d *schema.ResourceData, d.SetId("") return nil } - log.Printf("[DEBUG] GetObjectWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetObjectWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetObjectWithContext failed %s\n%s", err, response), "ibm_cm_object", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } replaceObjectOptions := &catalogmanagementv1.ReplaceObjectOptions{} @@ -453,7 +507,9 @@ func resourceIBMCmObjectUpdate(context context.Context, d *schema.ResourceData, if _, ok := d.GetOk("created"); ok { fmtDateTimeCreated, err := core.ParseDateTime(d.Get("created").(string)) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_object", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } replaceObjectOptions.SetCreated(&fmtDateTimeCreated) } else if catalogObject.Created != nil { @@ -462,7 +518,9 @@ func resourceIBMCmObjectUpdate(context context.Context, d *schema.ResourceData, if _, ok := d.GetOk("updated"); ok { fmtDateTimeUpdated, err := core.ParseDateTime(d.Get("updated").(string)) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_object", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } replaceObjectOptions.SetUpdated(&fmtDateTimeUpdated) } else if catalogObject.Updated != nil { @@ -496,7 +554,9 @@ func resourceIBMCmObjectUpdate(context context.Context, d *schema.ResourceData, } err = json.Unmarshal([]byte(dataString), &dataMap) if err != nil { - return diag.FromErr(fmt.Errorf("error unmarshalling json %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("error unmarshalling json %s", err), "ibm_cm_object", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } replaceObjectOptions.SetData(dataMap) } else if catalogObject.Data != nil { @@ -505,8 +565,9 @@ func resourceIBMCmObjectUpdate(context context.Context, d *schema.ResourceData, _, response, err = catalogManagementClient.ReplaceObjectWithContext(context, replaceObjectOptions) if err != nil { - log.Printf("[DEBUG] ReplaceObjectWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ReplaceObjectWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ReplaceObjectWithContext failed %s\n%s", err, response), "ibm_cm_object", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return resourceIBMCmObjectRead(context, d, meta) @@ -515,7 +576,9 @@ func resourceIBMCmObjectUpdate(context context.Context, d *schema.ResourceData, func resourceIBMCmObjectDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_object", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } deleteObjectOptions := &catalogmanagementv1.DeleteObjectOptions{} @@ -525,8 +588,9 @@ func resourceIBMCmObjectDelete(context context.Context, d *schema.ResourceData, response, err := catalogManagementClient.DeleteObjectWithContext(context, deleteObjectOptions) if err != nil { - log.Printf("[DEBUG] DeleteObjectWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteObjectWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteObjectWithContext failed %s\n%s", err, response), "ibm_cm_object", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId("") diff --git a/ibm/service/catalogmanagement/resource_ibm_cm_offering.go b/ibm/service/catalogmanagement/resource_ibm_cm_offering.go index c3e42b9f4a..556226e8c8 100644 --- a/ibm/service/catalogmanagement/resource_ibm_cm_offering.go +++ b/ibm/service/catalogmanagement/resource_ibm_cm_offering.go @@ -2549,7 +2549,9 @@ func ResourceIBMCmOffering() *schema.Resource { func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if _, ok := d.GetOk("offering_id"); ok { @@ -2563,15 +2565,18 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData d.SetId("") return nil } - log.Printf("[DEBUG] GetOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetOfferingWithContext failed %s\n%s", err, response), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(*offering.ID) err = handleShareOfferingAfterCreate(catalogManagementClient, *offering, d, context) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return resourceIBMCmOfferingRead(context, d, meta) @@ -2610,21 +2615,27 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData if _, ok := d.GetOk("rating"); ok { ratingModel, err := resourceIBMCmOfferingMapToRating(d.Get("rating.0").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } createOfferingOptions.SetRating(ratingModel) } if _, ok := d.GetOk("created"); ok { fmtDateTimeCreated, err := core.ParseDateTime(d.Get("created").(string)) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } createOfferingOptions.SetCreated(&fmtDateTimeCreated) } if _, ok := d.GetOk("updated"); ok { fmtDateTimeUpdated, err := core.ParseDateTime(d.Get("updated").(string)) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } createOfferingOptions.SetUpdated(&fmtDateTimeUpdated) } @@ -2640,7 +2651,9 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData value := e.(map[string]interface{}) featuresItem, err := resourceIBMCmOfferingMapToFeature(value) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } features = append(features, *featuresItem) } @@ -2652,7 +2665,9 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData value := e.(map[string]interface{}) kindsItem, err := resourceIBMCmOfferingMapToKind(value) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } kinds = append(kinds, *kindsItem) } @@ -2700,14 +2715,18 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData if _, ok := d.GetOk("provider_info"); ok { providerInfoModel, err := resourceIBMCmOfferingMapToProviderInfo(d.Get("provider_info.0").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } createOfferingOptions.SetProviderInfo(providerInfoModel) } if _, ok := d.GetOk("repo_info"); ok { repoInfoModel, err := resourceIBMCmOfferingMapToRepoInfo(d.Get("repo_info.0").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } createOfferingOptions.SetRepoInfo(repoInfoModel) } @@ -2717,7 +2736,9 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData value := e.(map[string]interface{}) imagePullKeysItem, err := resourceIBMCmOfferingMapToImagePullKey(value) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } imagePullKeys = append(imagePullKeys, *imagePullKeysItem) } @@ -2726,7 +2747,9 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData if _, ok := d.GetOk("support"); ok { supportModel, err := resourceIBMCmOfferingMapToSupport(d.Get("support.0").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } createOfferingOptions.SetSupport(supportModel) } @@ -2736,7 +2759,9 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData value := e.(map[string]interface{}) mediaItem, err := resourceIBMCmOfferingMapToMediaItem(value) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } media = append(media, *mediaItem) } @@ -2751,7 +2776,9 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData value := e.(map[string]interface{}) badgesItem, err := resourceIBMCmOfferingMapToBadge(value) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } badges = append(badges, *badgesItem) } @@ -2760,15 +2787,18 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData offering, response, err := catalogManagementClient.CreateOfferingWithContext(context, createOfferingOptions) if err != nil { - log.Printf("[DEBUG] CreateOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("CreateOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateOfferingWithContext failed %s\n%s", err, response), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(*offering.ID) err = handleShareOfferingAfterCreate(catalogManagementClient, *offering, d, context) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return resourceIBMCmOfferingRead(context, d, meta) @@ -2777,7 +2807,9 @@ func resourceIBMCmOfferingCreate(context context.Context, d *schema.ResourceData func resourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getOfferingOptions := &catalogmanagementv1.GetOfferingOptions{} @@ -2791,36 +2823,55 @@ func resourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData, d.SetId("") return nil } - log.Printf("[DEBUG] GetOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetOfferingWithContext failed %s\n%s", err, response), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_id", getOfferingOptions.CatalogIdentifier); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_id: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("url", offering.URL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting url: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("crn", offering.CRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("label", offering.Label); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("label_i18n", offering.LabelI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label_i18n: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting label_i18n: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("name", offering.Name); err != nil { - return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting name: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_icon_url", offering.OfferingIconURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering_icon_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_icon_url: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_docs_url", offering.OfferingDocsURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering_docs_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_docs_url: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_support_url", offering.OfferingSupportURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering_support_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_support_url: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } tags := []string{} if offering.Tags != nil { @@ -2835,126 +2886,190 @@ func resourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData, } } if err = d.Set("tags", tags); err != nil { - return diag.FromErr(fmt.Errorf("Error setting tags: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting tags: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } keywords := []string{} if offering.Keywords != nil { keywords = offering.Keywords } if err = d.Set("keywords", keywords); err != nil { - return diag.FromErr(fmt.Errorf("Error setting keywords: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting keywords: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("metadata", offering.Metadata); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering metadata: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering metadata: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if offering.Rating != nil { ratingMap, err := resourceIBMCmOfferingRatingToMap(offering.Rating) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("rating", []map[string]interface{}{ratingMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rating: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rating: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("created", flex.DateTimeToString(offering.Created)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting created: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("updated", flex.DateTimeToString(offering.Updated)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting updated: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("short_description", offering.ShortDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("short_description_i18n", offering.ShortDescriptionI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting short_description_i18n: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting short_description_i18n: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("long_description", offering.LongDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting long_description: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("long_description_i18n", offering.LongDescriptionI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description_i18n: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting long_description_i18n: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } features := []map[string]interface{}{} if offering.Features != nil { for _, featuresItem := range offering.Features { featuresItemMap, err := resourceIBMCmOfferingFeatureToMap(&featuresItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } features = append(features, featuresItemMap) } } if err = d.Set("features", features); err != nil { - return diag.FromErr(fmt.Errorf("Error setting features: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting features: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } kinds := []map[string]interface{}{} if offering.Kinds != nil { for _, kindsItem := range offering.Kinds { kindsItemMap, err := resourceIBMCmOfferingKindToMap(&kindsItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } kinds = append(kinds, kindsItemMap) } } if err = d.Set("kinds", kinds); err != nil { - return diag.FromErr(fmt.Errorf("Error setting kinds: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting kinds: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("pc_managed", offering.PcManaged); err != nil { - return diag.FromErr(fmt.Errorf("Error setting pc_managed: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting pc_managed: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("publish_approved", offering.PublishApproved); err != nil { - return diag.FromErr(fmt.Errorf("Error setting publish_approved: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting publish_approved: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("share_with_all", offering.ShareWithAll); err != nil { - return diag.FromErr(fmt.Errorf("Error setting share_with_all: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting share_with_all: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("share_with_ibm", offering.ShareWithIBM); err != nil { - return diag.FromErr(fmt.Errorf("Error setting share_with_ibm: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting share_with_ibm: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("share_enabled", offering.ShareEnabled); err != nil { - return diag.FromErr(fmt.Errorf("Error setting share_enabled: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting share_enabled: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("public_original_crn", offering.PublicOriginalCRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting public_original_crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting public_original_crn: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("publish_public_crn", offering.PublishPublicCRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting publish_public_crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting publish_public_crn: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("portal_approval_record", offering.PortalApprovalRecord); err != nil { - return diag.FromErr(fmt.Errorf("Error setting portal_approval_record: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting portal_approval_record: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("portal_ui_url", offering.PortalUIURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting portal_ui_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting portal_ui_url: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_id", offering.CatalogID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_id: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_name", offering.CatalogName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_name: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("disclaimer", offering.Disclaimer); err != nil { - return diag.FromErr(fmt.Errorf("Error setting disclaimer: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting disclaimer: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("hidden", offering.Hidden); err != nil { - return diag.FromErr(fmt.Errorf("Error setting hidden: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting hidden: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if offering.ProviderInfo != nil { providerInfoMap, err := resourceIBMCmOfferingProviderInfoToMap(offering.ProviderInfo) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("provider_info", []map[string]interface{}{providerInfoMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting provider_info: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting provider_info: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if offering.RepoInfo != nil { repoInfoMap, err := resourceIBMCmOfferingRepoInfoToMap(offering.RepoInfo) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("repo_info", []map[string]interface{}{repoInfoMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting repo_info: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting repo_info: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } imagePullKeys := []map[string]interface{}{} @@ -2962,21 +3077,29 @@ func resourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData, for _, imagePullKeysItem := range offering.ImagePullKeys { imagePullKeysItemMap, err := resourceIBMCmOfferingImagePullKeyToMap(&imagePullKeysItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } imagePullKeys = append(imagePullKeys, imagePullKeysItemMap) } } if err = d.Set("image_pull_keys", imagePullKeys); err != nil { - return diag.FromErr(fmt.Errorf("Error setting image_pull_keys: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting image_pull_keys: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if offering.Support != nil { supportMap, err := resourceIBMCmOfferingSupportToMap(offering.Support) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("support", []map[string]interface{}{supportMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting support: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting support: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } media := []map[string]interface{}{} @@ -2984,45 +3107,63 @@ func resourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData, for _, mediaItem := range offering.Media { mediaItemMap, err := resourceIBMCmOfferingMediaItemToMap(&mediaItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } media = append(media, mediaItemMap) } } if err = d.Set("media", media); err != nil { - return diag.FromErr(fmt.Errorf("Error setting media: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting media: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } deprecatePendingMap := make(map[string]interface{}) if offering.DeprecatePending != nil { deprecatePendingMap, err = resourceIBMCmOfferingDeprecatePendingToMap(offering.DeprecatePending) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("deprecate_pending", []map[string]interface{}{deprecatePendingMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting deprecate_pending: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting deprecate_pending: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("product_kind", offering.ProductKind); err != nil { - return diag.FromErr(fmt.Errorf("Error setting product_kind: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting product_kind: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } badges := []map[string]interface{}{} if offering.Badges != nil { for _, badgesItem := range offering.Badges { badgesItemMap, err := resourceIBMCmOfferingBadgeToMap(&badgesItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } badges = append(badges, badgesItemMap) } } if err = d.Set("badges", badges); err != nil { - return diag.FromErr(fmt.Errorf("Error setting badges: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting badges: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("rev", offering.Rev); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rev: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("offering_identifier", offering.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_id: %s", err), "ibm_cm_offering", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil @@ -3031,7 +3172,9 @@ func resourceIBMCmOfferingRead(context context.Context, d *schema.ResourceData, func resourceIBMCmOfferingUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } updateOfferingOptions := &catalogmanagementv1.UpdateOfferingOptions{} @@ -3046,8 +3189,9 @@ func resourceIBMCmOfferingUpdate(context context.Context, d *schema.ResourceData d.SetId("") return nil } - log.Printf("[DEBUG] GetOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetOfferingWithContext failed %s\n%s", err, response), "ibm_cm_offering", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } updateOfferingOptions.SetCatalogIdentifier(*offering.CatalogID) @@ -3451,7 +3595,9 @@ func resourceIBMCmOfferingUpdate(context context.Context, d *schema.ResourceData path := "/support" supportModel, err := resourceIBMCmOfferingMapToSupport(d.Get("support.0").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } update := catalogmanagementv1.JSONPatchOperation{ Op: &method, @@ -3519,8 +3665,9 @@ func resourceIBMCmOfferingUpdate(context context.Context, d *schema.ResourceData deleteOfferingAccessListOptions.SetAccesses(accountsToRemove) _, response, err = catalogManagementClient.DeleteOfferingAccessListWithContext(context, &deleteOfferingAccessListOptions) if err != nil { - log.Printf("[DEBUG] DeleteOfferingAccessListWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteOfferingAccessListWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteOfferingAccessListWithContext failed %s\n%s", err, response), "ibm_cm_offering", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -3532,8 +3679,9 @@ func resourceIBMCmOfferingUpdate(context context.Context, d *schema.ResourceData addOfferingAccessListOptions.SetAccesses(SIToSS(newAccountList.([]interface{}))) _, response, err = catalogManagementClient.AddOfferingAccessListWithContext(context, &addOfferingAccessListOptions) if err != nil { - log.Printf("[DEBUG] AddOfferingAccessListWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("AddOfferingAccessListWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("AddOfferingAccessListWithContext failed %s\n%s", err, response), "ibm_cm_offering", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } } @@ -3561,8 +3709,9 @@ func resourceIBMCmOfferingUpdate(context context.Context, d *schema.ResourceData if publishStatusChanged { _, response, err = catalogManagementClient.ShareOfferingWithContext(context, &shareOfferingOptions) if err != nil { - log.Printf("[DEBUG] ShareOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ShareOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ShareOfferingWithContext failed %s\n%s", err, response), "ibm_cm_offering", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -3574,16 +3723,18 @@ func resourceIBMCmOfferingUpdate(context context.Context, d *schema.ResourceData response, err := catalogManagementClient.DeprecateOfferingWithContext(context, deprecateOfferingOptions) if err != nil { - log.Printf("[DEBUG] UpdateOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("UpdateOfferingWithContext failed trying to deprecate offering - %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateOfferingWithContext failed trying to deprecate offering %s\n%s", err, response), "ibm_cm_offering", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if hasChange { _, response, err := catalogManagementClient.UpdateOfferingWithContext(context, updateOfferingOptions) if err != nil { - log.Printf("[DEBUG] UpdateOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("UpdateOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateOfferingWithContext failed %s\n%s", err, response), "ibm_cm_offering", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -3593,7 +3744,9 @@ func resourceIBMCmOfferingUpdate(context context.Context, d *schema.ResourceData func resourceIBMCmOfferingDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_offering", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } deleteOfferingOptions := &catalogmanagementv1.DeleteOfferingOptions{} @@ -3603,8 +3756,9 @@ func resourceIBMCmOfferingDelete(context context.Context, d *schema.ResourceData response, err := catalogManagementClient.DeleteOfferingWithContext(context, deleteOfferingOptions) if err != nil { - log.Printf("[DEBUG] DeleteOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteOfferingWithContext failed %s\n%s", err, response), "ibm_cm_offering", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId("") @@ -5034,7 +5188,7 @@ func resourceIBMCmOfferingConfigurationToMap(model *catalogmanagementv1.Configur if model.DefaultValue != nil { defaultValueJson, err := json.Marshal(model.DefaultValue) if err != nil { - return nil, fmt.Errorf("[ERROR] Error marshalling the version configuration default_value: %s", err) + return nil, flex.FmtErrorf("[ERROR] Error marshalling the version configuration default_value: %s", err) } modelMap["default_value"] = string(defaultValueJson) } @@ -5835,7 +5989,7 @@ func handleShareOfferingAfterCreate(catalogManagementClient *catalogmanagementv1 _, response, err := catalogManagementClient.AddOfferingAccessListWithContext(context, &addOfferingAccessListOptions) if err != nil { log.Printf("[DEBUG] AddOfferingAccessListWithContext failed %s\n%s", err, response) - return fmt.Errorf("AddOfferingAccessListWithContext failed %s\n%s", err, response) + return flex.FmtErrorf("AddOfferingAccessListWithContext failed %s\n%s", err, response) } } } @@ -5864,7 +6018,7 @@ func handleShareOfferingAfterCreate(catalogManagementClient *catalogmanagementv1 _, response, err := catalogManagementClient.ShareOfferingWithContext(context, &shareOfferingOptions) if err != nil { log.Printf("[DEBUG] ShareOfferingWithContext failed %s\n%s", err, response) - return fmt.Errorf("ShareOfferingWithContext failed %s\n%s", err, response) + return flex.FmtErrorf("ShareOfferingWithContext failed %s\n%s", err, response) } } diff --git a/ibm/service/catalogmanagement/resource_ibm_cm_offering_instance.go b/ibm/service/catalogmanagement/resource_ibm_cm_offering_instance.go index 9de261d3cb..f21b90bcfb 100644 --- a/ibm/service/catalogmanagement/resource_ibm_cm_offering_instance.go +++ b/ibm/service/catalogmanagement/resource_ibm_cm_offering_instance.go @@ -4,7 +4,6 @@ package catalogmanagement import ( - "fmt" "log" "os" "time" @@ -234,7 +233,7 @@ func waitUntilSuccess(d *schema.ResourceData, meta interface{}) (interface{}, er Refresh: func() (interface{}, string, error) { offeringInstance, _, err := catalogManagementClient.GetOfferingInstance(getOfferingInstanceOptions) if err != nil { - return nil, "", fmt.Errorf("[ERROR] Error retrieving offering instance: %s", err) + return nil, "", flex.FmtErrorf("[ERROR] Error retrieving offering instance: %s", err) } return offeringInstance, *offeringInstance.LastOperation.State, nil @@ -268,54 +267,54 @@ func resourceIBMCmOfferingInstanceRead(d *schema.ResourceData, meta interface{}) } if err = d.Set("url", offeringInstance.URL); err != nil { - return fmt.Errorf("[ERROR] Error setting url: %s", err) + return flex.FmtErrorf("[ERROR] Error setting url: %s", err) } if err = d.Set("crn", offeringInstance.CRN); err != nil { - return fmt.Errorf("[ERROR] Error setting crn: %s", err) + return flex.FmtErrorf("[ERROR] Error setting crn: %s", err) } if err = d.Set("label", offeringInstance.Label); err != nil { - return fmt.Errorf("[ERROR] Error setting label: %s", err) + return flex.FmtErrorf("[ERROR] Error setting label: %s", err) } if err = d.Set("catalog_id", offeringInstance.CatalogID); err != nil { - return fmt.Errorf("[ERROR] Error setting catalog_id: %s", err) + return flex.FmtErrorf("[ERROR] Error setting catalog_id: %s", err) } if err = d.Set("offering_id", offeringInstance.OfferingID); err != nil { - return fmt.Errorf("[ERROR] Error setting offering_id: %s", err) + return flex.FmtErrorf("[ERROR] Error setting offering_id: %s", err) } if err = d.Set("kind_format", offeringInstance.KindFormat); err != nil { - return fmt.Errorf("[ERROR] Error setting kind_format: %s", err) + return flex.FmtErrorf("[ERROR] Error setting kind_format: %s", err) } if err = d.Set("version", offeringInstance.Version); err != nil { - return fmt.Errorf("[ERROR] Error setting version: %s", err) + return flex.FmtErrorf("[ERROR] Error setting version: %s", err) } if err = d.Set("cluster_id", offeringInstance.ClusterID); err != nil { - return fmt.Errorf("[ERROR] Error setting cluster_id: %s", err) + return flex.FmtErrorf("[ERROR] Error setting cluster_id: %s", err) } if err = d.Set("cluster_region", offeringInstance.ClusterRegion); err != nil { - return fmt.Errorf("[ERROR] Error setting cluster_region: %s", err) + return flex.FmtErrorf("[ERROR] Error setting cluster_region: %s", err) } if offeringInstance.ClusterNamespaces != nil { if err = d.Set("cluster_namespaces", offeringInstance.ClusterNamespaces); err != nil { - return fmt.Errorf("[ERROR] Error setting cluster_namespaces: %s", err) + return flex.FmtErrorf("[ERROR] Error setting cluster_namespaces: %s", err) } } if err = d.Set("cluster_all_namespaces", offeringInstance.ClusterAllNamespaces); err != nil { - return fmt.Errorf("[ERROR] Error setting cluster_all_namespaces: %s", err) + return flex.FmtErrorf("[ERROR] Error setting cluster_all_namespaces: %s", err) } if err = d.Set("schematics_workspace_id", offeringInstance.SchematicsWorkspaceID); err != nil { - return fmt.Errorf("[ERROR] Error setting schematics_workspace_id: %s", err) + return flex.FmtErrorf("[ERROR] Error setting schematics_workspace_id: %s", err) } if err = d.Set("install_plan", offeringInstance.InstallPlan); err != nil { - return fmt.Errorf("[ERROR] Error setting install_plan: %s", err) + return flex.FmtErrorf("[ERROR] Error setting install_plan: %s", err) } if err = d.Set("channel", offeringInstance.Channel); err != nil { - return fmt.Errorf("[ERROR] Error setting channel: %s", err) + return flex.FmtErrorf("[ERROR] Error setting channel: %s", err) } if err = d.Set("plan_id", offeringInstance.PlanID); err != nil { - return fmt.Errorf("[ERROR] Error setting plan_id: %s", err) + return flex.FmtErrorf("[ERROR] Error setting plan_id: %s", err) } if err = d.Set("parent_crn", offeringInstance.ParentCRN); err != nil { - return fmt.Errorf("[ERROR] Error setting parent_crn: %s", err) + return flex.FmtErrorf("[ERROR] Error setting parent_crn: %s", err) } return nil diff --git a/ibm/service/catalogmanagement/resource_ibm_cm_validation.go b/ibm/service/catalogmanagement/resource_ibm_cm_validation.go index 3b1f2b5aac..44bfebbffe 100644 --- a/ibm/service/catalogmanagement/resource_ibm_cm_validation.go +++ b/ibm/service/catalogmanagement/resource_ibm_cm_validation.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/platform-services-go-sdk/catalogmanagementv1" ) @@ -168,7 +169,9 @@ func ResourceIBMCmValidation() *schema.Resource { func resourceIBMCmValidationCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } validateInstallOptions := &catalogmanagementv1.ValidateInstallOptions{} @@ -188,8 +191,9 @@ func resourceIBMCmValidationCreate(context context.Context, d *schema.ResourceDa d.SetId("") return nil } - log.Printf("[DEBUG] GetVersionWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetVersionWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetVersionWithContext failed %s\n%s", err, response), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } version = offering.Kinds[0].Versions[0] @@ -207,7 +211,9 @@ func resourceIBMCmValidationCreate(context context.Context, d *schema.ResourceDa err = markVersionAsConsumable(version, context, meta) if err != nil { d.SetId("") - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -220,35 +226,44 @@ func resourceIBMCmValidationCreate(context context.Context, d *schema.ResourceDa if _, ok := d.GetOk("override_values"); ok { overridesModel, err := configureOverrides(d.Get("override_values").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } validateInstallOptions.SetOverrideValues(&overridesModel) } if _, ok := d.GetOk("environment_variables"); ok { envsModel, err := envVariablesToDeployRequestBodyEnvVariables(d.Get("environment_variables").([]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } validateInstallOptions.SetEnvironmentVariables(envsModel) } if _, ok := d.GetOk("schematics"); ok { schematicsModel, err := schematicsMapToDeployRequestBodySchematics(d.Get("schematics").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } validateInstallOptions.SetSchematics(&schematicsModel) } bxSession, err := meta.(conns.ClientSession).BluemixSession() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } validateInstallOptions.SetXAuthRefreshToken(bxSession.Config.IAMRefreshToken) response, err := catalogManagementClient.ValidateInstallWithContext(context, validateInstallOptions) if err != nil { - log.Printf("[DEBUG] ValidateInstallWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ValidateInstallWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ValidateInstallWithContext failed %s\n%s", err, response), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(*validateInstallOptions.VersionLocID) @@ -258,8 +273,9 @@ func resourceIBMCmValidationCreate(context context.Context, d *schema.ResourceDa validationStatusOptions.SetXAuthRefreshToken(bxSession.Config.IAMRefreshToken) result, response, err := catalogManagementClient.GetValidationStatusWithContext(context, validationStatusOptions) if err != nil { - log.Printf("[DEBUG] GetValidationStatusWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetValidationStatusWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetValidationStatusWithContext failed %s\n%s", err, response), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } status := *result.State @@ -281,8 +297,9 @@ func resourceIBMCmValidationCreate(context context.Context, d *schema.ResourceDa result, response, err = catalogManagementClient.GetValidationStatusWithContext(context, validationStatusOptions) if err != nil { - log.Printf("[DEBUG] GetValidationStatusWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetValidationStatusWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetValidationStatusWithContext failed %s\n%s", err, response), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -291,7 +308,9 @@ func resourceIBMCmValidationCreate(context context.Context, d *schema.ResourceDa err = markVersionAsConsumable(version, context, meta) if err != nil { d.SetId("") - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_validation", "create") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -301,7 +320,9 @@ func resourceIBMCmValidationCreate(context context.Context, d *schema.ResourceDa func resourceIBMCmValidationRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_validation", "read") + log.Printf("[DEBUG]\\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getVersionOptions := &catalogmanagementv1.GetVersionOptions{} @@ -314,38 +335,51 @@ func resourceIBMCmValidationRead(context context.Context, d *schema.ResourceData d.SetId("") return nil } - log.Printf("[DEBUG] GetVersionWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetVersionWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetVersionWithContext failed %s\n%s", err, response), "ibm_cm_validation", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } version := offering.Kinds[0].Versions[0] if err = d.Set("version_locator", version.VersionLocator); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version_locator: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting version_locator: %s", err), "ibm_cm_validation", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if version.Validation != nil && version.Validation.Validated != nil { if err = d.Set("validated", version.Validation.Validated.String()); err != nil { - return diag.FromErr(fmt.Errorf("Error setting validation: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting validation: %s", err), "ibm_cm_validation", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if version.Validation != nil && version.Validation.Requested != nil { if err = d.Set("requested", version.Validation.Requested.String()); err != nil { - return diag.FromErr(fmt.Errorf("Error setting requested: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting requested: %s", err), "ibm_cm_validation", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if version.Validation != nil && version.Validation.State != nil { if err = d.Set("state", version.Validation.State); err != nil { - return diag.FromErr(fmt.Errorf("Error setting state: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting state: %s", err), "ibm_cm_validation", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if version.Validation != nil && version.Validation.LastOperation != nil { if err = d.Set("last_operation", version.Validation.LastOperation); err != nil { - return diag.FromErr(fmt.Errorf("Error setting last_operation: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting last_operation: %s", err), "ibm_cm_validation", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if version.Validation != nil && version.Validation.Message != nil { if err = d.Set("message", version.Validation.Message); err != nil { - return diag.FromErr(fmt.Errorf("Error setting message: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting message: %s", err), "ibm_cm_validation", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } // if version.Validation != nil && version.Validation.Target != nil { diff --git a/ibm/service/catalogmanagement/resource_ibm_cm_version.go b/ibm/service/catalogmanagement/resource_ibm_cm_version.go index be19b417b6..60cd65cf94 100644 --- a/ibm/service/catalogmanagement/resource_ibm_cm_version.go +++ b/ibm/service/catalogmanagement/resource_ibm_cm_version.go @@ -1731,7 +1731,9 @@ func ResourceIBMCmVersion() *schema.Resource { func resourceIBMCmVersionCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } importOfferingVersionOptions := &catalogmanagementv1.ImportOfferingVersionOptions{} @@ -1768,14 +1770,18 @@ func resourceIBMCmVersionCreate(context context.Context, d *schema.ResourceData, if _, ok := d.GetOk("flavor"); ok { flavorModel, err := resourceIBMCmVersionMapToFlavor(d.Get("flavor.0").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } importOfferingVersionOptions.SetFlavor(flavorModel) } if _, ok := d.GetOk("import_metadata"); ok { metadataModel, err := resourceIBMCmVersionMapToImportOfferingBodyMetadata(d.Get("import_metadata.0").(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } importOfferingVersionOptions.SetMetadata(metadataModel) } @@ -1815,20 +1821,23 @@ func resourceIBMCmVersionCreate(context context.Context, d *schema.ResourceData, d.SetId("") return nil } - log.Printf("[DEBUG] GetOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetOfferingWithContext failed %s\n%s", err, response), "ibm_cm_version", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } offering, response, err := catalogManagementClient.ImportOfferingVersionWithContext(context, importOfferingVersionOptions) if err != nil { - log.Printf("[DEBUG] ImportOfferingVersionWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ImportOfferingVersionWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ImportOfferingVersionWithContext failed %s\n%s", err, response), "ibm_cm_version", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } activeVersion, err := getVersionFromOffering(oldOffering, offering) if err != nil { - log.Printf("[DEBUG] getVersionFromOffering failed %s\n", err) - return diag.FromErr(fmt.Errorf("getVersionFromOffering failed %s\n", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("getVersionFromOffering failed %s\n%s", err, response), "ibm_cm_version", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId(fmt.Sprintf("%s/%s", *offering.CatalogID, *activeVersion.ID)) @@ -1887,7 +1896,9 @@ func resourceIBMCmVersionCreate(context context.Context, d *schema.ResourceData, path := fmt.Sprintf("%s/configuration", pathToVersion) configurations, err := configurationToProperFormat(d.Get("configuration").([]interface{})) if err != nil { - return diag.FromErr(fmt.Errorf("UpdateOfferingWithContext failed in ibm_cm_version create \"configuration\" %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateOfferingWithContext failed %s\n%s", err, response), "ibm_cm_version", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } update := catalogmanagementv1.JSONPatchOperation{ Op: &method, @@ -1987,7 +1998,9 @@ func resourceIBMCmVersionCreate(context context.Context, d *schema.ResourceData, path := fmt.Sprintf("%s/solution_info", pathToVersion) solutionInfoMap, err := solutionInfoToProperFormatMap(d.Get("solution_info.0").(map[string]interface{})) if err != nil { - return diag.FromErr(fmt.Errorf("UpdateOfferingWithContext failed in ibm_cm_version create \"solution_info\" %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateOfferingWithContext failed %s\n%s", err, response), "ibm_cm_version", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } update := catalogmanagementv1.JSONPatchOperation{ Op: &method, @@ -2033,8 +2046,9 @@ func resourceIBMCmVersionCreate(context context.Context, d *schema.ResourceData, if hasChange { _, response, err := catalogManagementClient.UpdateOfferingWithContext(context, updateOfferingOptions) if err != nil { - log.Printf("[DEBUG] UpdateOfferingWithContext failed in ibm_cm_version update %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("UpdateOfferingWithContext failed in ibm_cm_version update %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateOfferingWithContext failed %s\n%s", err, response), "ibm_cm_version", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -2044,7 +2058,9 @@ func resourceIBMCmVersionCreate(context context.Context, d *schema.ResourceData, func resourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getVersionOptions := &catalogmanagementv1.GetVersionOptions{} @@ -2057,33 +2073,46 @@ func resourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, m d.SetId("") return nil } - log.Printf("[DEBUG] GetVersionWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetVersionWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetVersionWithContext failed %s\n%s", err, response), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } version := offering.Kinds[0].Versions[0] if err = d.Set("offering_identifier", version.OfferingID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting offering_identifier: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting offering_identifier: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if version.Tags != nil { if err = d.Set("tags", version.Tags); err != nil { - return diag.FromErr(fmt.Errorf("Error setting tags: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting tags: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("sha", version.Sha); err != nil { - return diag.FromErr(fmt.Errorf("Error setting sha: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting sha: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("version", version.Version); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting version: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if version.Flavor != nil { flavorMap, err := resourceIBMCmVersionFlavorToMap(version.Flavor) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("flavor", []map[string]interface{}{flavorMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting flavor: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting flavor: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } metadata := []map[string]interface{}{} @@ -2092,7 +2121,9 @@ func resourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, m if version.Metadata["vsi_vpc"] != nil { modelMapVSI, err = dataSourceIBMCmVersionMetadataVSIToMap(version.Metadata["vsi_vpc"].(map[string]interface{})) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } convertedMap := make(map[string]interface{}, len(version.Metadata)) @@ -2106,81 +2137,117 @@ func resourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, m metadata = append(metadata, convertedMap) } if err = d.Set("metadata", metadata); err != nil { - return diag.FromErr(fmt.Errorf("Error setting metadata %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting metadata: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("rev", version.Rev); err != nil { - return diag.FromErr(fmt.Errorf("Error setting rev: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting rev: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("crn", version.CRN); err != nil { - return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("created", flex.DateTimeToString(version.Created)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting created: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("updated", flex.DateTimeToString(version.Updated)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting updated: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("catalog_id", version.CatalogID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting catalog_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting catalog_id: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("kind_id", version.KindID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting kind_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting kind_id: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("repo_url", version.RepoURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting repo_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting repo_url: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("source_url", version.SourceURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting source_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting source_url: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("tgz_url", version.TgzURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting tgz_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting tgz_url: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } configuration := []map[string]interface{}{} if version.Configuration != nil { for _, configurationItem := range version.Configuration { configurationItemMap, err := resourceIBMCmVersionConfigurationToMap(&configurationItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } configuration = append(configuration, configurationItemMap) } } if err = d.Set("configuration", configuration); err != nil { - return diag.FromErr(fmt.Errorf("Error setting configuration: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting configuration: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } outputs := []map[string]interface{}{} if version.Outputs != nil { for _, outputsItem := range version.Outputs { outputsItemMap, err := resourceIBMCmVersionOutputToMap(&outputsItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } outputs = append(outputs, outputsItemMap) } } if err = d.Set("outputs", outputs); err != nil { - return diag.FromErr(fmt.Errorf("Error setting outputs: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting outputs: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } iamPermissions := []map[string]interface{}{} if version.IamPermissions != nil { for _, iamPermissionsItem := range version.IamPermissions { iamPermissionsItemMap, err := resourceIBMCmVersionIamPermissionToMap(&iamPermissionsItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } iamPermissions = append(iamPermissions, iamPermissionsItemMap) } } if err = d.Set("iam_permissions", iamPermissions); err != nil { - return diag.FromErr(fmt.Errorf("Error setting iam_permissions: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting iam_permissions: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if version.Validation != nil { validationMap, err := resourceIBMCmVersionValidationToMap(version.Validation) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("validation", []map[string]interface{}{validationMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting validation: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting validation: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } requiredResources := []map[string]interface{}{} @@ -2188,47 +2255,65 @@ func resourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, m for _, requiredResourcesItem := range version.RequiredResources { requiredResourcesItemMap, err := resourceIBMCmVersionResourceToMap(&requiredResourcesItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } requiredResources = append(requiredResources, requiredResourcesItemMap) } } if err = d.Set("required_resources", requiredResources); err != nil { - return diag.FromErr(fmt.Errorf("Error setting required_resources: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting required_resources: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("single_instance", version.SingleInstance); err != nil { - return diag.FromErr(fmt.Errorf("Error setting single_instance: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting single_instance: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } installMap := make(map[string]interface{}) if version.Install != nil { installMap, err = resourceIBMCmVersionScriptToMap(version.Install) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("install", []map[string]interface{}{installMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting install: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting install: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } preInstall := []map[string]interface{}{} if version.PreInstall != nil { for _, preInstallItem := range version.PreInstall { preInstallItemMap, err := resourceIBMCmVersionScriptToMap(&preInstallItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } preInstall = append(preInstall, preInstallItemMap) } } if err = d.Set("pre_install", preInstall); err != nil { - return diag.FromErr(fmt.Errorf("Error setting pre_install: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting pre_install: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if version.Entitlement != nil { entitlementMap, err := resourceIBMCmVersionVersionEntitlementToMap(version.Entitlement) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("entitlement", []map[string]interface{}{entitlementMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting entitlement: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting entitlement: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } licenses := []map[string]interface{}{} @@ -2236,68 +2321,102 @@ func resourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, m for _, licensesItem := range version.Licenses { licensesItemMap, err := resourceIBMCmVersionLicenseToMap(&licensesItem) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } licenses = append(licenses, licensesItemMap) } } if err = d.Set("licenses", licenses); err != nil { - return diag.FromErr(fmt.Errorf("Error setting licenses: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting licenses: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("image_manifest_url", version.ImageManifestURL); err != nil { - return diag.FromErr(fmt.Errorf("Error setting image_manifest_url: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting image_manifest_url: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("deprecated", version.Deprecated); err != nil { - return diag.FromErr(fmt.Errorf("Error setting deprecated: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting deprecated: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("package_version", version.PackageVersion); err != nil { - return diag.FromErr(fmt.Errorf("Error setting package_version: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting package_version: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if version.State != nil { stateMap, err := resourceIBMCmVersionStateToMap(version.State) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("state", []map[string]interface{}{stateMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting state: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting state: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("version_locator", version.VersionLocator); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version_locator: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting version_locator: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("long_description", version.LongDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting long_description: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("long_description_i18n", version.LongDescriptionI18n); err != nil { - return diag.FromErr(fmt.Errorf("Error setting long_description_i18n: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting long_description_i18n: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("image_pull_key_name", version.ImagePullKeyName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting image_pull_key_name: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting image_pull_key_name: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } deprecatePendingMap := make(map[string]interface{}) if version.DeprecatePending != nil { deprecatePendingMap, err = resourceIBMCmVersionDeprecatePendingToMap(version.DeprecatePending) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("deprecate_pending", []map[string]interface{}{deprecatePendingMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting deprecate_pending: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting deprecate_pending: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if version.SolutionInfo != nil { solutionInfoMap, err := resourceIBMCmVersionSolutionInfoToMap(version.SolutionInfo) if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("solution_info", []map[string]interface{}{solutionInfoMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting solution_info: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting solution_info: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } if err = d.Set("is_consumable", version.IsConsumable); err != nil { - return diag.FromErr(fmt.Errorf("Error setting is_consumable: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting is_consumable: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if err = d.Set("version_id", version.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version_id: %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting version_id: %s", err), "ibm_cm_version", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil @@ -2306,7 +2425,9 @@ func resourceIBMCmVersionRead(context context.Context, d *schema.ResourceData, m func resourceIBMCmVersionUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } mk := fmt.Sprintf("%s.%s", d.Get("catalog_id").(string), d.Get("offering_id").(string)) @@ -2322,8 +2443,9 @@ func resourceIBMCmVersionUpdate(context context.Context, d *schema.ResourceData, d.SetId("") return nil } - log.Printf("[DEBUG] GetVersionWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetVersionWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetVersionWithContext failed %s\n%s", err, response), "ibm_cm_version", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } activeVersion := partialOffering.Kinds[0].Versions[0] @@ -2337,8 +2459,9 @@ func resourceIBMCmVersionUpdate(context context.Context, d *schema.ResourceData, d.SetId("") return nil } - log.Printf("[DEBUG] GetOfferingWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetOfferingWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetOfferingWithContext failed %s\n%s", err, response), "ibm_cm_version", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } updateOfferingOptions := &catalogmanagementv1.UpdateOfferingOptions{} @@ -2411,7 +2534,9 @@ func resourceIBMCmVersionUpdate(context context.Context, d *schema.ResourceData, path := fmt.Sprintf("%s/configuration", pathToVersion) configurations, err := configurationToProperFormat(d.Get("configuration").([]interface{})) if err != nil { - return diag.FromErr(fmt.Errorf("UpdateOfferingWithContext failed in ibm_cm_version create \"configuration\" %s", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateOfferingWithContext failed %s\n%s", err, response), "ibm_cm_version", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } update := catalogmanagementv1.JSONPatchOperation{ Op: &method, @@ -2511,7 +2636,9 @@ func resourceIBMCmVersionUpdate(context context.Context, d *schema.ResourceData, path := fmt.Sprintf("%s/solution_info", pathToVersion) solutionInfoMap, err := solutionInfoToProperFormatMap(d.Get("solution_info.0").(map[string]interface{})) if err != nil { - return diag.FromErr(fmt.Errorf("UpdateOfferingWithContext failed in ibm_cm_version update solution_info %s\n", err)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateOfferingWithContext failed %s\n%s", err, response), "ibm_cm_version", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } update := catalogmanagementv1.JSONPatchOperation{ Op: &method, @@ -2541,8 +2668,9 @@ func resourceIBMCmVersionUpdate(context context.Context, d *schema.ResourceData, if hasChange { _, response, err := catalogManagementClient.UpdateOfferingWithContext(context, updateOfferingOptions) if err != nil { - log.Printf("[DEBUG] UpdateOfferingWithContext failed in ibm_cm_version update %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("UpdateOfferingWithContext failed in ibm_cm_version update %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateOfferingWithContext failed %s\n%s", err, response), "ibm_cm_version", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -2553,8 +2681,9 @@ func resourceIBMCmVersionUpdate(context context.Context, d *schema.ResourceData, response, err := catalogManagementClient.SetDeprecateVersionWithContext(context, setDeprecateVersionOptions) if err != nil { - log.Printf("[DEBUG] SetDeprecateVersionWithContext failed in ibm_cm_version %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("SetDeprecateVersionWithContext failed trying to deprecate version - %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("SetDeprecateVersionWithContext failed %s\n%s", err, response), "ibm_cm_version", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } } @@ -2564,7 +2693,9 @@ func resourceIBMCmVersionUpdate(context context.Context, d *schema.ResourceData, func resourceIBMCmVersionDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { catalogManagementClient, err := meta.(conns.ClientSession).CatalogManagementV1() if err != nil { - return diag.FromErr(err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_cm_version", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } mk := fmt.Sprintf("%s.%s", d.Get("catalog_id").(string), d.Get("offering_id").(string)) @@ -2577,8 +2708,9 @@ func resourceIBMCmVersionDelete(context context.Context, d *schema.ResourceData, response, err := catalogManagementClient.DeleteVersionWithContext(context, deleteVersionOptions) if err != nil { - log.Printf("[DEBUG] DeleteVersionWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteVersionWithContext failed %s\n%s", err, response)) + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteVersionWithContext failed %s\n%s", err, response), "ibm_cm_version", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } d.SetId("") @@ -2837,7 +2969,7 @@ func resourceIBMCmVersionConfigurationToMap(model *catalogmanagementv1.Configura if model.DefaultValue != nil { defaultValueJson, err := json.Marshal(model.DefaultValue) if err != nil { - return nil, fmt.Errorf("[ERROR] Error marshalling the version configuration default_value: %s", err) + return nil, flex.FmtErrorf("[ERROR] Error marshalling the version configuration default_value: %s", err) } defaultValueString, _ := strconv.Unquote(string(defaultValueJson)) modelMap["default_value"] = defaultValueString @@ -3435,5 +3567,5 @@ func getVersionFromOffering(oldOffering *catalogmanagementv1.Offering, newOfferi return &newVer, nil } } - return nil, fmt.Errorf("error finding imported version") + return nil, flex.FmtErrorf("error finding imported version") } diff --git a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline.go b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline.go index 4e116e6254..609edc44e3 100644 --- a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline.go +++ b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline.go @@ -236,7 +236,7 @@ func DataSourceIBMCdTektonPipeline() *schema.Resource { "properties": &schema.Schema{ Type: schema.TypeList, Computed: true, - Description: "Optional trigger properties used to override or supplement the pipeline properties when triggering a pipeline run.", + Description: "Optional trigger properties are used to override or supplement the pipeline properties when triggering a pipeline run.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": &schema.Schema{ @@ -320,7 +320,7 @@ func DataSourceIBMCdTektonPipeline() *schema.Resource { "enabled": &schema.Schema{ Type: schema.TypeBool, Computed: true, - Description: "Flag whether the trigger is enabled.", + Description: "Flag to check if the trigger is enabled.", }, "favorite": &schema.Schema{ Type: schema.TypeBool, @@ -352,12 +352,12 @@ func DataSourceIBMCdTektonPipeline() *schema.Resource { "branch": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "Name of a branch from the repo. One of branch or pattern must be specified, but only one or the other.", + Description: "Name of a branch from the repo. Only one of branch, pattern, or filter should be specified.", }, "pattern": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "The pattern of Git branch or tag to which to listen. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags/branches in the repository. The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. One of branch or pattern must be specified, but only one or the other.", + Description: "The pattern of Git branch or tag. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags or branches in the repository.The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. Only one of branch, pattern, or filter should be specified.", }, "blind_connection": &schema.Schema{ Type: schema.TypeBool, @@ -367,7 +367,7 @@ func DataSourceIBMCdTektonPipeline() *schema.Resource { "hook_id": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "ID of the webhook from the repo. Computed upon creation of the trigger.", + Description: "Repository webhook ID. It is generated upon trigger creation.", }, "tool": &schema.Schema{ Type: schema.TypeList, @@ -392,25 +392,30 @@ func DataSourceIBMCdTektonPipeline() *schema.Resource { "events": &schema.Schema{ Type: schema.TypeList, Computed: true, - Description: "Only needed for Git triggers. List of events to which a Git trigger listens. Choose one or more from: 'push', 'pull_request' and 'pull_request_closed'. For SCM repositories that use 'merge request' events, such events map to the equivalent 'pull request' events.", + Description: "Either 'events' or 'filter' is required specifically for Git triggers. Stores a list of events that a Git trigger listens to. Choose one or more from 'push', 'pull_request', and 'pull_request_closed'. If SCM repositories use the 'merge request' term, they correspond to the generic term i.e. 'pull request'.", Elem: &schema.Schema{ Type: schema.TypeString, }, }, + "filter": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Either 'events' or 'filter' can be used. Stores the CEL (Common Expression Language) expression value which is used for event filtering against the Git webhook payloads.", + }, "cron": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "Only needed for timer triggers. Cron expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: 0 *_/2 * * * - every 2 hours.", + Description: "Only needed for timer triggers. CRON expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: The CRON expression 0 *_/2 * * * - translates to - every 2 hours.", }, "timezone": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the cron activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones.", + Description: "Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the CRON activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones.", }, "secret": &schema.Schema{ Type: schema.TypeList, Computed: true, - Description: "Only needed for generic webhook trigger type. Secret used to start generic webhook trigger.", + Description: "Only needed for Generic Webhook trigger type. The secret is used to start the Generic Webhook trigger.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "type": &schema.Schema{ @@ -496,17 +501,17 @@ func DataSourceIBMCdTektonPipeline() *schema.Resource { "enable_notifications": &schema.Schema{ Type: schema.TypeBool, Computed: true, - Description: "Flag whether to enable notifications for this pipeline. When enabled, pipeline run events will be published on all slack integration specified channels in the parent toolchain. If omitted, this feature is disabled by default.", + Description: "Flag to enable notifications for this pipeline. If enabled, the Tekton pipeline run events will be published to all the destinations specified by the Slack and Event Notifications integrations in the parent toolchain. If omitted, this feature is disabled by default.", }, "enable_partial_cloning": &schema.Schema{ Type: schema.TypeBool, Computed: true, - Description: "Flag whether to enable partial cloning for this pipeline. When partial clone is enabled, only the files contained within the paths specified in definition repositories are read and cloned, this means that symbolic links might not work. If omitted, this feature is disabled by default.", + Description: "Flag to enable partial cloning for this pipeline. When partial clone is enabled, only the files contained within the paths specified in definition repositories are read and cloned, this means that symbolic links might not work. If omitted, this feature is disabled by default.", }, "enabled": &schema.Schema{ Type: schema.TypeBool, Computed: true, - Description: "Flag whether this pipeline is enabled.", + Description: "Flag to check if the trigger is enabled.", }, }, } @@ -810,6 +815,9 @@ func dataSourceIBMCdTektonPipelineTriggerToMap(model cdtektonpipelinev2.TriggerI if model.Events != nil { modelMap["events"] = model.Events } + if model.Filter != nil { + modelMap["filter"] = model.Filter + } if model.Cron != nil { modelMap["cron"] = model.Cron } @@ -1005,6 +1013,9 @@ func dataSourceIBMCdTektonPipelineTriggerScmTriggerToMap(model *cdtektonpipeline if model.Events != nil { modelMap["events"] = model.Events } + if model.Filter != nil { + modelMap["filter"] = model.Filter + } return modelMap, nil } @@ -1101,5 +1112,8 @@ func dataSourceIBMCdTektonPipelineTriggerGenericTriggerToMap(model *cdtektonpipe if model.WebhookURL != nil { modelMap["webhook_url"] = model.WebhookURL } + if model.Filter != nil { + modelMap["filter"] = model.Filter + } return modelMap, nil } diff --git a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_property_test.go b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_property_test.go index 039e66f382..c29ce37471 100644 --- a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_property_test.go +++ b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_property_test.go @@ -37,8 +37,8 @@ func TestAccIBMCdTektonPipelinePropertyDataSourceBasic(t *testing.T) { func TestAccIBMCdTektonPipelinePropertyDataSourceAllArgs(t *testing.T) { propertyName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) - propertyValue := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) propertyType := "text" + propertyValue := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) propertyLocked := "true" propertyPath := fmt.Sprintf("tf_path_%d", acctest.RandIntRange(10, 100)) @@ -47,7 +47,7 @@ func TestAccIBMCdTektonPipelinePropertyDataSourceAllArgs(t *testing.T) { Providers: acc.TestAccProviders, Steps: []resource.TestStep{ resource.TestStep{ - Config: testAccCheckIBMCdTektonPipelinePropertyDataSourceConfig("", propertyName, propertyValue, propertyType, propertyLocked, propertyPath), + Config: testAccCheckIBMCdTektonPipelinePropertyDataSourceConfig("", propertyName, propertyType, propertyValue, propertyLocked, propertyPath), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "id"), resource.TestCheckResourceAttrSet("data.ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "pipeline_id"), @@ -106,7 +106,7 @@ func testAccCheckIBMCdTektonPipelinePropertyDataSourceConfigBasic(propertyPipeli `, rgName, tcName) } -func testAccCheckIBMCdTektonPipelinePropertyDataSourceConfig(propertyPipelineID string, propertyName string, propertyValue string, propertyType string, propertyLocked string, propertyPath string) string { +func testAccCheckIBMCdTektonPipelinePropertyDataSourceConfig(propertyPipelineID string, propertyName string, propertyType string, propertyValue string, propertyLocked string, propertyPath string) string { rgName := acc.CdResourceGroupName tcName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) return fmt.Sprintf(` diff --git a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger.go b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger.go index 78b5908680..8115dcc4fb 100644 --- a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger.go +++ b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger.go @@ -54,7 +54,7 @@ func DataSourceIBMCdTektonPipelineTrigger() *schema.Resource { "properties": &schema.Schema{ Type: schema.TypeList, Computed: true, - Description: "Optional trigger properties used to override or supplement the pipeline properties when triggering a pipeline run.", + Description: "Optional trigger properties are used to override or supplement the pipeline properties when triggering a pipeline run.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": &schema.Schema{ @@ -138,7 +138,7 @@ func DataSourceIBMCdTektonPipelineTrigger() *schema.Resource { "enabled": &schema.Schema{ Type: schema.TypeBool, Computed: true, - Description: "Flag whether the trigger is enabled.", + Description: "Flag to check if the trigger is enabled.", }, "favorite": &schema.Schema{ Type: schema.TypeBool, @@ -170,12 +170,12 @@ func DataSourceIBMCdTektonPipelineTrigger() *schema.Resource { "branch": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "Name of a branch from the repo. One of branch or pattern must be specified, but only one or the other.", + Description: "Name of a branch from the repo. Only one of branch, pattern, or filter should be specified.", }, "pattern": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "The pattern of Git branch or tag to which to listen. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags/branches in the repository. The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. One of branch or pattern must be specified, but only one or the other.", + Description: "The pattern of Git branch or tag. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags or branches in the repository.The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. Only one of branch, pattern, or filter should be specified.", }, "blind_connection": &schema.Schema{ Type: schema.TypeBool, @@ -185,7 +185,7 @@ func DataSourceIBMCdTektonPipelineTrigger() *schema.Resource { "hook_id": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "ID of the webhook from the repo. Computed upon creation of the trigger.", + Description: "Repository webhook ID. It is generated upon trigger creation.", }, "tool": &schema.Schema{ Type: schema.TypeList, @@ -210,25 +210,30 @@ func DataSourceIBMCdTektonPipelineTrigger() *schema.Resource { "events": &schema.Schema{ Type: schema.TypeList, Computed: true, - Description: "Only needed for Git triggers. List of events to which a Git trigger listens. Choose one or more from: 'push', 'pull_request' and 'pull_request_closed'. For SCM repositories that use 'merge request' events, such events map to the equivalent 'pull request' events.", + Description: "Either 'events' or 'filter' is required specifically for Git triggers. Stores a list of events that a Git trigger listens to. Choose one or more from 'push', 'pull_request', and 'pull_request_closed'. If SCM repositories use the 'merge request' term, they correspond to the generic term i.e. 'pull request'.", Elem: &schema.Schema{ Type: schema.TypeString, }, }, + "filter": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Either 'events' or 'filter' can be used. Stores the CEL (Common Expression Language) expression value which is used for event filtering against the Git webhook payloads.", + }, "cron": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "Only needed for timer triggers. Cron expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: 0 *_/2 * * * - every 2 hours.", + Description: "Only needed for timer triggers. CRON expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: The CRON expression 0 *_/2 * * * - translates to - every 2 hours.", }, "timezone": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the cron activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones.", + Description: "Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the CRON activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones.", }, "secret": &schema.Schema{ Type: schema.TypeList, Computed: true, - Description: "Only needed for generic webhook trigger type. Secret used to start generic webhook trigger.", + Description: "Only needed for Generic Webhook trigger type. The secret is used to start the Generic Webhook trigger.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "type": &schema.Schema{ @@ -366,6 +371,10 @@ func dataSourceIBMCdTektonPipelineTriggerRead(context context.Context, d *schema return diag.FromErr(fmt.Errorf("Error setting source %s", err)) } + if err = d.Set("filter", trigger.Filter); err != nil { + return diag.FromErr(fmt.Errorf("Error setting filter: %s", err)) + } + if err = d.Set("cron", trigger.Cron); err != nil { return diag.FromErr(fmt.Errorf("Error setting cron: %s", err)) } diff --git a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger_property_test.go b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger_property_test.go index 8446b940c4..7e547027c8 100644 --- a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger_property_test.go +++ b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger_property_test.go @@ -36,8 +36,8 @@ func TestAccIBMCdTektonPipelineTriggerPropertyDataSourceBasic(t *testing.T) { func TestAccIBMCdTektonPipelineTriggerPropertyDataSourceAllArgs(t *testing.T) { triggerPropertyName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) - triggerPropertyValue := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) triggerPropertyType := "text" + triggerPropertyValue := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) triggerPropertyPath := fmt.Sprintf("tf_path_%d", acctest.RandIntRange(10, 100)) triggerPropertyLocked := "true" @@ -46,7 +46,7 @@ func TestAccIBMCdTektonPipelineTriggerPropertyDataSourceAllArgs(t *testing.T) { Providers: acc.TestAccProviders, Steps: []resource.TestStep{ resource.TestStep{ - Config: testAccCheckIBMCdTektonPipelineTriggerPropertyDataSourceConfig("", "", triggerPropertyName, triggerPropertyValue, triggerPropertyType, triggerPropertyPath, triggerPropertyLocked), + Config: testAccCheckIBMCdTektonPipelineTriggerPropertyDataSourceConfig("", "", triggerPropertyName, triggerPropertyType, triggerPropertyValue, triggerPropertyPath, triggerPropertyLocked), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "id"), resource.TestCheckResourceAttrSet("data.ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "property_name"), @@ -135,7 +135,7 @@ func testAccCheckIBMCdTektonPipelineTriggerPropertyDataSourceConfigBasic(trigger `, rgName, tcName) } -func testAccCheckIBMCdTektonPipelineTriggerPropertyDataSourceConfig(triggerPropertyPipelineID string, triggerPropertyTriggerID string, triggerPropertyName string, triggerPropertyValue string, triggerPropertyType string, triggerPropertyPath string, triggerPropertyLocked string) string { +func testAccCheckIBMCdTektonPipelineTriggerPropertyDataSourceConfig(triggerPropertyPipelineID string, triggerPropertyTriggerID string, triggerPropertyName string, triggerPropertyType string, triggerPropertyValue string, triggerPropertyPath string, triggerPropertyLocked string) string { rgName := acc.CdResourceGroupName tcName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) return fmt.Sprintf(` diff --git a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger_test.go b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger_test.go index 0eac444401..914eb58815 100644 --- a/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger_test.go +++ b/ibm/service/cdtektonpipeline/data_source_ibm_cd_tekton_pipeline_trigger_test.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2023 All Rights Reserved. +// Copyright IBM Corp. 2024 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package cdtektonpipeline_test @@ -42,16 +42,17 @@ func TestAccIBMCdTektonPipelineTriggerDataSourceAllArgs(t *testing.T) { triggerEventListener := fmt.Sprintf("tf_event_listener_%d", acctest.RandIntRange(10, 100)) triggerMaxConcurrentRuns := fmt.Sprintf("%d", acctest.RandIntRange(10, 100)) triggerEnabled := "false" - triggerFavorite := "true" triggerCron := fmt.Sprintf("tf_cron_%d", acctest.RandIntRange(10, 100)) triggerTimezone := fmt.Sprintf("tf_timezone_%d", acctest.RandIntRange(10, 100)) + triggerFilter := fmt.Sprintf("tf_filter_%d", acctest.RandIntRange(10, 100)) + triggerFavorite := "true" resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, Providers: acc.TestAccProviders, Steps: []resource.TestStep{ resource.TestStep{ - Config: testAccCheckIBMCdTektonPipelineTriggerDataSourceConfig(triggerPipelineID, triggerType, triggerName, triggerEventListener, triggerMaxConcurrentRuns, triggerEnabled, triggerFavorite, triggerCron, triggerTimezone), + Config: testAccCheckIBMCdTektonPipelineTriggerDataSourceConfig(triggerPipelineID, triggerType, triggerName, triggerEventListener, triggerMaxConcurrentRuns, triggerEnabled, triggerCron, triggerTimezone, triggerFilter, triggerFavorite), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "id"), resource.TestCheckResourceAttrSet("data.ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "pipeline_id"), @@ -140,7 +141,7 @@ func testAccCheckIBMCdTektonPipelineTriggerDataSourceConfigBasic(triggerPipeline `, rgName, tcName, triggerType, triggerName, triggerEventListener) } -func testAccCheckIBMCdTektonPipelineTriggerDataSourceConfig(triggerPipelineID string, triggerType string, triggerName string, triggerEventListener string, triggerMaxConcurrentRuns string, triggerEnabled string, triggerFavorite string, triggerCron string, triggerTimezone string) string { +func testAccCheckIBMCdTektonPipelineTriggerDataSourceConfig(triggerPipelineID string, triggerType string, triggerName string, triggerEventListener string, triggerMaxConcurrentRuns string, triggerEnabled string, triggerCron string, triggerTimezone string, triggerFilter string, triggerFavorite string) string { rgName := acc.CdResourceGroupName tcName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) return fmt.Sprintf(` diff --git a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline.go b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline.go index f202c024b9..2330f74faa 100644 --- a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline.go +++ b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline.go @@ -27,47 +27,37 @@ func ResourceIBMCdTektonPipeline() *schema.Resource { Importer: &schema.ResourceImporter{}, Schema: map[string]*schema.Schema{ - "worker": &schema.Schema{ - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Description: "Details of the worker used to run the pipeline.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Name of the worker. Computed based on the worker ID.", - }, - "type": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Type of the worker. Computed based on the worker ID.", - }, - "id": &schema.Schema{ - Type: schema.TypeString, - Required: true, - Description: "ID of the worker.", - }, - }, - }, - }, "next_build_number": &schema.Schema{ Type: schema.TypeInt, Optional: true, - Description: "The build number that will be used for the next pipeline run.", + Description: "Specify the build number that will be used for the next pipeline run. Build numbers can be any positive whole number between 0 and 100000000000000.", }, "enable_notifications": &schema.Schema{ Type: schema.TypeBool, Optional: true, Default: false, - Description: "Flag whether to enable notifications for this pipeline. When enabled, pipeline run events will be published on all slack integration specified channels in the parent toolchain. If omitted, this feature is disabled by default.", + Description: "Flag to enable notifications for this pipeline. If enabled, the Tekton pipeline run events will be published to all the destinations specified by the Slack and Event Notifications integrations in the parent toolchain.", }, "enable_partial_cloning": &schema.Schema{ Type: schema.TypeBool, Optional: true, Default: false, - Description: "Flag whether to enable partial cloning for this pipeline. When partial clone is enabled, only the files contained within the paths specified in definition repositories are read and cloned, this means that symbolic links might not work. If omitted, this feature is disabled by default.", + Description: "Flag to enable partial cloning for this pipeline. When partial clone is enabled, only the files contained within the paths specified in definition repositories are read and cloned, this means that symbolic links might not work.", + }, + "worker": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Specify the worker that is to be used to run the trigger, indicated by a worker object with only the worker ID. If not specified or set as `worker: { id: 'public' }`, the IBM Managed shared workers are used.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "ID of the worker.", + }, + }, + }, }, "pipeline_id": &schema.Schema{ Type: schema.TypeString, @@ -291,7 +281,7 @@ func ResourceIBMCdTektonPipeline() *schema.Resource { "properties": &schema.Schema{ Type: schema.TypeList, Optional: true, - Description: "Optional trigger properties used to override or supplement the pipeline properties when triggering a pipeline run.", + Description: "Optional trigger properties are used to override or supplement the pipeline properties when triggering a pipeline run.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": &schema.Schema{ @@ -376,7 +366,7 @@ func ResourceIBMCdTektonPipeline() *schema.Resource { Type: schema.TypeBool, Optional: true, Default: true, - Description: "Flag whether the trigger is enabled.", + Description: "Flag to check if the trigger is enabled.", }, "favorite": &schema.Schema{ Type: schema.TypeBool, @@ -413,12 +403,12 @@ func ResourceIBMCdTektonPipeline() *schema.Resource { "branch": &schema.Schema{ Type: schema.TypeString, Optional: true, - Description: "Name of a branch from the repo. One of branch or pattern must be specified, but only one or the other.", + Description: "Name of a branch from the repo. Only one of branch, pattern, or filter should be specified.", }, "pattern": &schema.Schema{ Type: schema.TypeString, Optional: true, - Description: "The pattern of Git branch or tag to which to listen. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags/branches in the repository. The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. One of branch or pattern must be specified, but only one or the other.", + Description: "The pattern of Git branch or tag. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags or branches in the repository.The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. Only one of branch, pattern, or filter should be specified.", }, "blind_connection": &schema.Schema{ Type: schema.TypeBool, @@ -428,7 +418,7 @@ func ResourceIBMCdTektonPipeline() *schema.Resource { "hook_id": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "ID of the webhook from the repo. Computed upon creation of the trigger.", + Description: "Repository webhook ID. It is generated upon trigger creation.", }, "tool": &schema.Schema{ Type: schema.TypeList, @@ -454,24 +444,29 @@ func ResourceIBMCdTektonPipeline() *schema.Resource { Type: schema.TypeList, Optional: true, DiffSuppressFunc: flex.SuppressTriggerEvents, - Description: "Only needed for Git triggers. List of events to which a Git trigger listens. Choose one or more from: 'push', 'pull_request' and 'pull_request_closed'. For SCM repositories that use 'merge request' events, such events map to the equivalent 'pull request' events.", + Description: "Either 'events' or 'filter' is required specifically for Git triggers. Stores a list of events that a Git trigger listens to. Choose one or more from 'push', 'pull_request', and 'pull_request_closed'. If SCM repositories use the 'merge request' term, they correspond to the generic term i.e. 'pull request'.", Elem: &schema.Schema{Type: schema.TypeString}, }, + "filter": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Either 'events' or 'filter' can be used. Stores the CEL (Common Expression Language) expression value which is used for event filtering against the Git webhook payloads.", + }, "cron": &schema.Schema{ Type: schema.TypeString, Optional: true, - Description: "Only needed for timer triggers. Cron expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: 0 *_/2 * * * - every 2 hours.", + Description: "Only needed for timer triggers. CRON expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: The CRON expression 0 *_/2 * * * - translates to - every 2 hours.", }, "timezone": &schema.Schema{ Type: schema.TypeString, Optional: true, - Description: "Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the cron activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones.", + Description: "Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the CRON activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones.", }, "secret": &schema.Schema{ Type: schema.TypeList, MaxItems: 1, Optional: true, - Description: "Only needed for generic webhook trigger type. Secret used to start generic webhook trigger.", + Description: "Only needed for Generic Webhook trigger type. The secret is used to start the Generic Webhook trigger.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "type": &schema.Schema{ @@ -529,7 +524,7 @@ func ResourceIBMCdTektonPipeline() *schema.Resource { "enabled": &schema.Schema{ Type: schema.TypeBool, Computed: true, - Description: "Flag whether this pipeline is enabled.", + Description: "Flag to check if the trigger is enabled.", }, }, } @@ -611,15 +606,6 @@ func resourceIBMCdTektonPipelineRead(context context.Context, d *schema.Resource return diag.FromErr(fmt.Errorf("GetTektonPipelineWithContext failed %s\n%s", err, response)) } - if !core.IsNil(tektonPipeline.Worker) { - workerMap, err := resourceIBMCdTektonPipelineWorkerToMap(tektonPipeline.Worker) - if err != nil { - return diag.FromErr(err) - } - if err = d.Set("worker", []map[string]interface{}{workerMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting worker: %s", err)) - } - } if !core.IsNil(tektonPipeline.NextBuildNumber) { if err = d.Set("next_build_number", flex.IntValue(tektonPipeline.NextBuildNumber)); err != nil { return diag.FromErr(fmt.Errorf("Error setting next_build_number: %s", err)) @@ -635,6 +621,15 @@ func resourceIBMCdTektonPipelineRead(context context.Context, d *schema.Resource return diag.FromErr(fmt.Errorf("Error setting enable_partial_cloning: %s", err)) } } + if !core.IsNil(tektonPipeline.Worker) { + workerMap, err := resourceIBMCdTektonPipelineWorkerIdentityToMap(tektonPipeline.Worker) + if err != nil { + return diag.FromErr(err) + } + if err = d.Set("worker", []map[string]interface{}{workerMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting worker: %s", err)) + } + } if err = d.Set("pipeline_id", tektonPipeline.ID); err != nil { return diag.FromErr(fmt.Errorf("Error setting pipeline_id: %s", err)) } @@ -791,14 +786,8 @@ func resourceIBMCdTektonPipelineMapToWorkerIdentity(modelMap map[string]interfac return model, nil } -func resourceIBMCdTektonPipelineWorkerToMap(model *cdtektonpipelinev2.Worker) (map[string]interface{}, error) { +func resourceIBMCdTektonPipelineWorkerIdentityToMap(model *cdtektonpipelinev2.Worker) (map[string]interface{}, error) { modelMap := make(map[string]interface{}) - if model.Name != nil { - modelMap["name"] = model.Name - } - if model.Type != nil { - modelMap["type"] = model.Type - } modelMap["id"] = model.ID return modelMap, nil } @@ -958,6 +947,9 @@ func resourceIBMCdTektonPipelineTriggerToMap(model cdtektonpipelinev2.TriggerInt if model.Events != nil { modelMap["events"] = model.Events } + if model.Filter != nil { + modelMap["filter"] = model.Filter + } if model.Cron != nil { modelMap["cron"] = model.Cron } @@ -1002,6 +994,18 @@ func resourceIBMCdTektonPipelineTriggerPropertyToMap(model *cdtektonpipelinev2.T return modelMap, nil } +func resourceIBMCdTektonPipelineWorkerToMap(model *cdtektonpipelinev2.Worker) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Name != nil { + modelMap["name"] = model.Name + } + if model.Type != nil { + modelMap["type"] = model.Type + } + modelMap["id"] = model.ID + return modelMap, nil +} + func resourceIBMCdTektonPipelineTriggerSourceToMap(model *cdtektonpipelinev2.TriggerSource) (map[string]interface{}, error) { modelMap := make(map[string]interface{}) modelMap["type"] = model.Type @@ -1141,6 +1145,9 @@ func resourceIBMCdTektonPipelineTriggerScmTriggerToMap(model *cdtektonpipelinev2 if model.Events != nil { modelMap["events"] = model.Events } + if model.Filter != nil { + modelMap["filter"] = model.Filter + } return modelMap, nil } @@ -1237,5 +1244,8 @@ func resourceIBMCdTektonPipelineTriggerGenericTriggerToMap(model *cdtektonpipeli if model.WebhookURL != nil { modelMap["webhook_url"] = model.WebhookURL } + if model.Filter != nil { + modelMap["filter"] = model.Filter + } return modelMap, nil } diff --git a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_property.go b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_property.go index 064aaafd7a..dfddc9844f 100644 --- a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_property.go +++ b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_property.go @@ -41,6 +41,13 @@ func ResourceIBMCdTektonPipelineProperty() *schema.Resource { ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_property", "name"), Description: "Property name.", }, + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_property", "type"), + Description: "Property type.", + }, "value": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -54,13 +61,6 @@ func ResourceIBMCdTektonPipelineProperty() *schema.Resource { Description: "Options for `single_select` property type. Only needed when using `single_select` property type.", Elem: &schema.Schema{Type: schema.TypeString}, }, - "type": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_property", "type"), - Description: "Property type.", - }, "locked": &schema.Schema{ Type: schema.TypeBool, Optional: true, @@ -71,7 +71,7 @@ func ResourceIBMCdTektonPipelineProperty() *schema.Resource { Type: schema.TypeString, Optional: true, ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_property", "path"), - Description: "A dot notation path for `integration` type properties only, that selects a value from the tool integration. If left blank the full tool integration data will be used.", + Description: "A dot notation path for `integration` type properties only, to select a value from the tool integration. If left blank the full tool integration data will be used.", }, "href": &schema.Schema{ Type: schema.TypeString, @@ -103,6 +103,13 @@ func ResourceIBMCdTektonPipelinePropertyValidator() *validate.ResourceValidator MinValueLength: 1, MaxValueLength: 253, }, + validate.ValidateSchema{ + Identifier: "type", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: "appconfig, integration, secure, single_select, text", + }, validate.ValidateSchema{ Identifier: "value", ValidateFunctionIdentifier: validate.ValidateRegexpLen, @@ -112,13 +119,6 @@ func ResourceIBMCdTektonPipelinePropertyValidator() *validate.ResourceValidator MinValueLength: 0, MaxValueLength: 4096, }, - validate.ValidateSchema{ - Identifier: "type", - ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, - Type: validate.TypeString, - Required: true, - AllowedValues: "appconfig, integration, secure, single_select, text", - }, validate.ValidateSchema{ Identifier: "path", ValidateFunctionIdentifier: validate.ValidateRegexpLen, @@ -206,6 +206,9 @@ func resourceIBMCdTektonPipelinePropertyRead(context context.Context, d *schema. if err = d.Set("name", property.Name); err != nil { return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) } + if err = d.Set("type", property.Type); err != nil { + return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) + } if !core.IsNil(property.Value) { if err = d.Set("value", property.Value); err != nil { return diag.FromErr(fmt.Errorf("Error setting value: %s", err)) @@ -216,9 +219,6 @@ func resourceIBMCdTektonPipelinePropertyRead(context context.Context, d *schema. return diag.FromErr(fmt.Errorf("Error setting enum: %s", err)) } } - if err = d.Set("type", property.Type); err != nil { - return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) - } if !core.IsNil(property.Locked) { if err = d.Set("locked", property.Locked); err != nil { return diag.FromErr(fmt.Errorf("Error setting locked: %s", err)) diff --git a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_property_test.go b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_property_test.go index 0cf2bd361d..74171f47ec 100644 --- a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_property_test.go +++ b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_property_test.go @@ -41,8 +41,8 @@ func TestAccIBMCdTektonPipelinePropertyBasic(t *testing.T) { func TestAccIBMCdTektonPipelinePropertyAllArgs(t *testing.T) { var conf cdtektonpipelinev2.Property name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) - value := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) typeVar := "text" + value := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) locked := "true" path := fmt.Sprintf("tf_path_%d", acctest.RandIntRange(10, 100)) valueUpdate := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) @@ -55,21 +55,21 @@ func TestAccIBMCdTektonPipelinePropertyAllArgs(t *testing.T) { CheckDestroy: testAccCheckIBMCdTektonPipelinePropertyDestroy, Steps: []resource.TestStep{ resource.TestStep{ - Config: testAccCheckIBMCdTektonPipelinePropertyConfig("", name, value, typeVar, locked, path), + Config: testAccCheckIBMCdTektonPipelinePropertyConfig("", name, typeVar, value, locked, path), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckIBMCdTektonPipelinePropertyExists("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", conf), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "name", name), - resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "value", value), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "type", typeVar), + resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "value", value), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "locked", locked), ), }, resource.TestStep{ - Config: testAccCheckIBMCdTektonPipelinePropertyConfig("", name, valueUpdate, typeVar, lockedUpdate, pathUpdate), + Config: testAccCheckIBMCdTektonPipelinePropertyConfig("", name, typeVar, valueUpdate, lockedUpdate, pathUpdate), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "name", name), - resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "value", valueUpdate), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "type", typeVar), + resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "value", valueUpdate), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_property.cd_tekton_pipeline_property", "locked", lockedUpdate), ), }, @@ -121,7 +121,7 @@ func testAccCheckIBMCdTektonPipelinePropertyConfigBasic(pipelineID string, name `, rgName, tcName) } -func testAccCheckIBMCdTektonPipelinePropertyConfig(pipelineID string, name string, value string, typeVar string, locked string, path string) string { +func testAccCheckIBMCdTektonPipelinePropertyConfig(pipelineID string, name string, typeVar string, value string, locked string, path string) string { rgName := acc.CdResourceGroupName tcName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) return fmt.Sprintf(` diff --git a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger.go b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger.go index 47378fd1bd..ff3f66a237 100644 --- a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger.go +++ b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger.go @@ -56,26 +56,16 @@ func ResourceIBMCdTektonPipelineTrigger() *schema.Resource { "tags": &schema.Schema{ Type: schema.TypeList, Optional: true, - Description: "Optional trigger tags array.", + Description: "Trigger tags array.", Elem: &schema.Schema{Type: schema.TypeString}, }, "worker": &schema.Schema{ Type: schema.TypeList, MaxItems: 1, Optional: true, - Description: "Details of the worker used to run the trigger.", + Description: "Specify the worker used to run the trigger. Use `worker: { id: 'public' }` to use the IBM Managed workers. The default is to inherit the worker set in the pipeline settings, which can also be explicitly set using `worker: { id: 'inherit' }`.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Name of the worker. Computed based on the worker ID.", - }, - "type": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Type of the worker. Computed based on the worker ID.", - }, "id": &schema.Schema{ Type: schema.TypeString, Required: true, @@ -93,13 +83,55 @@ func ResourceIBMCdTektonPipelineTrigger() *schema.Resource { Type: schema.TypeBool, Optional: true, Default: true, - Description: "Flag whether the trigger is enabled.", + Description: "Flag to check if the trigger is enabled. If omitted the trigger is enabled by default.", }, - "favorite": &schema.Schema{ - Type: schema.TypeBool, + "secret": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, Optional: true, - Default: false, - Description: "Mark the trigger as a favorite.", + Description: "Only needed for Generic Webhook trigger type. The secret is used to start the Generic Webhook trigger.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Secret type.", + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: flex.SuppressGenericWebhookRawSecret, + Description: "Secret value, not needed if secret type is `internal_validation`.", + }, + "source": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Secret location, not needed if secret type is `internal_validation`.", + }, + "key_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Secret name, not needed if type is `internal_validation`.", + }, + "algorithm": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Algorithm used for `digest_matches` secret type. Only needed for `digest_matches` secret type.", + }, + }, + }, + }, + "cron": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_trigger", "cron"), + Description: "Only needed for timer triggers. CRON expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: The CRON expression 0 *_/2 * * * - translates to - every 2 hours.", + }, + "timezone": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_trigger", "timezone"), + Description: "Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the CRON activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones.", }, "source": &schema.Schema{ Type: schema.TypeList, @@ -130,36 +162,12 @@ func ResourceIBMCdTektonPipelineTrigger() *schema.Resource { "branch": &schema.Schema{ Type: schema.TypeString, Optional: true, - Description: "Name of a branch from the repo. One of branch or pattern must be specified, but only one or the other.", + Description: "Name of a branch from the repo. Only one of branch, pattern, or filter should be specified.", }, "pattern": &schema.Schema{ Type: schema.TypeString, Optional: true, - Description: "The pattern of Git branch or tag to which to listen. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags/branches in the repository. The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. One of branch or pattern must be specified, but only one or the other.", - }, - "blind_connection": &schema.Schema{ - Type: schema.TypeBool, - Computed: true, - Description: "True if the repository server is not addressable on the public internet. IBM Cloud will not be able to validate the connection details you provide.", - }, - "hook_id": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "ID of the webhook from the repo. Computed upon creation of the trigger.", - }, - "tool": &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Description: "Reference to the repository tool in the parent toolchain.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "ID of the repository tool instance in the parent toolchain.", - }, - }, - }, + Description: "The pattern of Git branch or tag. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags or branches in the repository.The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. Only one of branch, pattern, or filter should be specified.", }, }, }, @@ -171,56 +179,20 @@ func ResourceIBMCdTektonPipelineTrigger() *schema.Resource { Type: schema.TypeList, Optional: true, DiffSuppressFunc: flex.SuppressTriggerEvents, - Description: "Only needed for Git triggers. List of events to which a Git trigger listens. Choose one or more from: 'push', 'pull_request' and 'pull_request_closed'. For SCM repositories that use 'merge request' events, such events map to the equivalent 'pull request' events.", + Description: "Either 'events' or 'filter' is required specifically for Git triggers. Stores a list of events that a Git trigger listens to. Choose one or more from 'push', 'pull_request', and 'pull_request_closed'. If SCM repositories use the 'merge request' term, they correspond to the generic term i.e. 'pull request'.", Elem: &schema.Schema{Type: schema.TypeString}, }, - "cron": &schema.Schema{ + "filter": &schema.Schema{ Type: schema.TypeString, Optional: true, - ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_trigger", "cron"), - Description: "Only needed for timer triggers. Cron expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: 0 *_/2 * * * - every 2 hours.", + ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_trigger", "filter"), + Description: "Either 'events' or 'filter' can be used. Stores the CEL (Common Expression Language) expression value which is used for event filtering against the Git webhook payloads.", }, - "timezone": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_trigger", "timezone"), - Description: "Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the cron activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones.", - }, - "secret": &schema.Schema{ - Type: schema.TypeList, - MaxItems: 1, + "favorite": &schema.Schema{ + Type: schema.TypeBool, Optional: true, - Description: "Only needed for generic webhook trigger type. Secret used to start generic webhook trigger.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "type": &schema.Schema{ - Type: schema.TypeString, - Required: true, - Description: "Secret type.", - }, - "value": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - DiffSuppressFunc: flex.SuppressGenericWebhookRawSecret, - Description: "Secret value, not needed if secret type is `internal_validation`.", - }, - "source": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Description: "Secret location, not needed if secret type is `internal_validation`.", - }, - "key_name": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Description: "Secret name, not needed if type is `internal_validation`.", - }, - "algorithm": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Description: "Algorithm used for `digest_matches` secret type. Only needed for `digest_matches` secret type.", - }, - }, - }, + Default: false, + Description: "Mark the trigger as a favorite.", }, "href": &schema.Schema{ Type: schema.TypeString, @@ -230,7 +202,7 @@ func ResourceIBMCdTektonPipelineTrigger() *schema.Resource { "properties": &schema.Schema{ Type: schema.TypeList, Computed: true, - Description: "Optional trigger properties used to override or supplement the pipeline properties when triggering a pipeline run.", + Description: "Optional trigger properties are used to override or supplement the pipeline properties when triggering a pipeline run.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": &schema.Schema{ @@ -344,6 +316,15 @@ func ResourceIBMCdTektonPipelineTriggerValidator() *validate.ResourceValidator { MinValueLength: 1, MaxValueLength: 253, }, + validate.ValidateSchema{ + Identifier: "filter", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^.*$`, + MinValueLength: 1, + MaxValueLength: 4096, + }, ) resourceValidator := validate.ResourceValidator{ResourceName: "ibm_cd_tekton_pipeline_trigger", Schema: validateSchema} @@ -411,6 +392,9 @@ func resourceIBMCdTektonPipelineTriggerCreate(context context.Context, d *schema sort.Strings(events) createTektonPipelineTriggerOptions.SetEvents(events) } + if _, ok := d.GetOk("filter"); ok { + createTektonPipelineTriggerOptions.SetFilter(d.Get("filter").(string)) + } if _, ok := d.GetOk("favorite"); ok { createTektonPipelineTriggerOptions.SetFavorite(d.Get("favorite").(bool)) } @@ -472,7 +456,7 @@ func resourceIBMCdTektonPipelineTriggerRead(context context.Context, d *schema.R } } if !core.IsNil(trigger.Worker) { - workerMap, err := resourceIBMCdTektonPipelineTriggerWorkerToMap(trigger.Worker) + workerMap, err := resourceIBMCdTektonPipelineTriggerWorkerIdentityToMap(trigger.Worker) if err != nil { return diag.FromErr(err) } @@ -490,23 +474,13 @@ func resourceIBMCdTektonPipelineTriggerRead(context context.Context, d *schema.R return diag.FromErr(fmt.Errorf("Error setting enabled: %s", err)) } } - if !core.IsNil(trigger.Favorite) { - if err = d.Set("favorite", trigger.Favorite); err != nil { - return diag.FromErr(fmt.Errorf("Error setting favorite: %s", err)) - } - } - if !core.IsNil(trigger.Source) { - sourceMap, err := resourceIBMCdTektonPipelineTriggerTriggerSourceToMap(trigger.Source) + if !core.IsNil(trigger.Secret) { + secretMap, err := resourceIBMCdTektonPipelineTriggerGenericSecretToMap(trigger.Secret) if err != nil { return diag.FromErr(err) } - if err = d.Set("source", []map[string]interface{}{sourceMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting source: %s", err)) - } - } - if !core.IsNil(trigger.Events) { - if err = d.Set("events", trigger.Events); err != nil { - return diag.FromErr(fmt.Errorf("Error setting events: %s", err)) + if err = d.Set("secret", []map[string]interface{}{secretMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting secret: %s", err)) } } if !core.IsNil(trigger.Cron) { @@ -519,13 +493,28 @@ func resourceIBMCdTektonPipelineTriggerRead(context context.Context, d *schema.R return diag.FromErr(fmt.Errorf("Error setting timezone: %s", err)) } } - if !core.IsNil(trigger.Secret) { - secretMap, err := resourceIBMCdTektonPipelineTriggerGenericSecretToMap(trigger.Secret) + if !core.IsNil(trigger.Source) { + sourceMap, err := resourceIBMCdTektonPipelineTriggerTriggerSourcePrototypeToMap(trigger.Source) if err != nil { return diag.FromErr(err) } - if err = d.Set("secret", []map[string]interface{}{secretMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting secret: %s", err)) + if err = d.Set("source", []map[string]interface{}{sourceMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting source: %s", err)) + } + } + if !core.IsNil(trigger.Events) { + if err = d.Set("events", trigger.Events); err != nil { + return diag.FromErr(fmt.Errorf("Error setting events: %s", err)) + } + } + if !core.IsNil(trigger.Filter) { + if err = d.Set("filter", trigger.Filter); err != nil { + return diag.FromErr(fmt.Errorf("Error setting filter: %s", err)) + } + } + if !core.IsNil(trigger.Favorite) { + if err = d.Set("favorite", trigger.Favorite); err != nil { + return diag.FromErr(fmt.Errorf("Error setting favorite: %s", err)) } } if !core.IsNil(trigger.Href) { @@ -583,17 +572,11 @@ func resourceIBMCdTektonPipelineTriggerUpdate(context context.Context, d *schema return diag.FromErr(fmt.Errorf("Cannot update resource property \"%s\" with the ForceNew annotation."+ " The resource must be re-created to update this property.", "pipeline_id")) } - if d.HasChange("type") { + if d.HasChange("type") || d.HasChange("name") || d.HasChange("event_listener") { newType := d.Get("type").(string) patchVals.Type = &newType - hasChange = true - } - if d.HasChange("name") { newName := d.Get("name").(string) patchVals.Name = &newName - hasChange = true - } - if d.HasChange("event_listener") { newEventListener := d.Get("event_listener").(string) patchVals.EventListener = &newEventListener hasChange = true @@ -755,22 +738,36 @@ func resourceIBMCdTektonPipelineTriggerMapToTriggerSourcePropertiesPrototype(mod return model, nil } -func resourceIBMCdTektonPipelineTriggerWorkerToMap(model *cdtektonpipelinev2.Worker) (map[string]interface{}, error) { +func resourceIBMCdTektonPipelineTriggerWorkerIdentityToMap(model *cdtektonpipelinev2.Worker) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = model.ID + return modelMap, nil +} + +func resourceIBMCdTektonPipelineTriggerGenericSecretToMap(model *cdtektonpipelinev2.GenericSecret) (map[string]interface{}, error) { modelMap := make(map[string]interface{}) - if model.Name != nil { - modelMap["name"] = model.Name - } if model.Type != nil { modelMap["type"] = model.Type } - modelMap["id"] = model.ID + if model.Value != nil { + modelMap["value"] = model.Value + } + if model.Source != nil { + modelMap["source"] = model.Source + } + if model.KeyName != nil { + modelMap["key_name"] = model.KeyName + } + if model.Algorithm != nil { + modelMap["algorithm"] = model.Algorithm + } return modelMap, nil } -func resourceIBMCdTektonPipelineTriggerTriggerSourceToMap(model *cdtektonpipelinev2.TriggerSource) (map[string]interface{}, error) { +func resourceIBMCdTektonPipelineTriggerTriggerSourcePrototypeToMap(model *cdtektonpipelinev2.TriggerSource) (map[string]interface{}, error) { modelMap := make(map[string]interface{}) modelMap["type"] = model.Type - propertiesMap, err := resourceIBMCdTektonPipelineTriggerTriggerSourcePropertiesToMap(model.Properties) + propertiesMap, err := resourceIBMCdTektonPipelineTriggerTriggerSourcePropertiesPrototypeToMap(model.Properties) if err != nil { return modelMap, err } @@ -778,7 +775,7 @@ func resourceIBMCdTektonPipelineTriggerTriggerSourceToMap(model *cdtektonpipelin return modelMap, nil } -func resourceIBMCdTektonPipelineTriggerTriggerSourcePropertiesToMap(model *cdtektonpipelinev2.TriggerSourceProperties) (map[string]interface{}, error) { +func resourceIBMCdTektonPipelineTriggerTriggerSourcePropertiesPrototypeToMap(model *cdtektonpipelinev2.TriggerSourceProperties) (map[string]interface{}, error) { modelMap := make(map[string]interface{}) modelMap["url"] = model.URL if model.Branch != nil { @@ -787,41 +784,6 @@ func resourceIBMCdTektonPipelineTriggerTriggerSourcePropertiesToMap(model *cdtek if model.Pattern != nil { modelMap["pattern"] = model.Pattern } - modelMap["blind_connection"] = model.BlindConnection - if model.HookID != nil { - modelMap["hook_id"] = model.HookID - } - toolMap, err := resourceIBMCdTektonPipelineTriggerToolToMap(model.Tool) - if err != nil { - return modelMap, err - } - modelMap["tool"] = []map[string]interface{}{toolMap} - return modelMap, nil -} - -func resourceIBMCdTektonPipelineTriggerToolToMap(model *cdtektonpipelinev2.Tool) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - modelMap["id"] = model.ID - return modelMap, nil -} - -func resourceIBMCdTektonPipelineTriggerGenericSecretToMap(model *cdtektonpipelinev2.GenericSecret) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Type != nil { - modelMap["type"] = model.Type - } - if model.Value != nil { - modelMap["value"] = model.Value - } - if model.Source != nil { - modelMap["source"] = model.Source - } - if model.KeyName != nil { - modelMap["key_name"] = model.KeyName - } - if model.Algorithm != nil { - modelMap["algorithm"] = model.Algorithm - } return modelMap, nil } diff --git a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_property.go b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_property.go index 6bc7117888..871b7e30a1 100644 --- a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_property.go +++ b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_property.go @@ -48,6 +48,13 @@ func ResourceIBMCdTektonPipelineTriggerProperty() *schema.Resource { ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_trigger_property", "name"), Description: "Property name.", }, + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_trigger_property", "type"), + Description: "Property type.", + }, "value": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -61,18 +68,11 @@ func ResourceIBMCdTektonPipelineTriggerProperty() *schema.Resource { Description: "Options for `single_select` property type. Only needed for `single_select` property type.", Elem: &schema.Schema{Type: schema.TypeString}, }, - "type": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_trigger_property", "type"), - Description: "Property type.", - }, "path": &schema.Schema{ Type: schema.TypeString, Optional: true, ValidateFunc: validate.InvokeValidator("ibm_cd_tekton_pipeline_trigger_property", "path"), - Description: "A dot notation path for `integration` type properties only, that selects a value from the tool integration. If left blank the full tool integration data will be used.", + Description: "A dot notation path for `integration` type properties only, to select a value from the tool integration. If left blank the full tool integration data will be used.", }, "locked": &schema.Schema{ Type: schema.TypeBool, @@ -119,6 +119,13 @@ func ResourceIBMCdTektonPipelineTriggerPropertyValidator() *validate.ResourceVal MinValueLength: 1, MaxValueLength: 253, }, + validate.ValidateSchema{ + Identifier: "type", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: "appconfig, integration, secure, single_select, text", + }, validate.ValidateSchema{ Identifier: "value", ValidateFunctionIdentifier: validate.ValidateRegexpLen, @@ -128,13 +135,6 @@ func ResourceIBMCdTektonPipelineTriggerPropertyValidator() *validate.ResourceVal MinValueLength: 0, MaxValueLength: 4096, }, - validate.ValidateSchema{ - Identifier: "type", - ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, - Type: validate.TypeString, - Required: true, - AllowedValues: "appconfig, integration, secure, single_select, text", - }, validate.ValidateSchema{ Identifier: "path", ValidateFunctionIdentifier: validate.ValidateRegexpLen, @@ -227,6 +227,9 @@ func resourceIBMCdTektonPipelineTriggerPropertyRead(context context.Context, d * if err = d.Set("name", triggerProperty.Name); err != nil { return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) } + if err = d.Set("type", triggerProperty.Type); err != nil { + return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) + } if !core.IsNil(triggerProperty.Value) { if err = d.Set("value", triggerProperty.Value); err != nil { return diag.FromErr(fmt.Errorf("Error setting value: %s", err)) @@ -237,9 +240,6 @@ func resourceIBMCdTektonPipelineTriggerPropertyRead(context context.Context, d * return diag.FromErr(fmt.Errorf("Error setting enum: %s", err)) } } - if err = d.Set("type", triggerProperty.Type); err != nil { - return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) - } if !core.IsNil(triggerProperty.Path) { if err = d.Set("path", triggerProperty.Path); err != nil { return diag.FromErr(fmt.Errorf("Error setting path: %s", err)) diff --git a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_property_test.go b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_property_test.go index a734ff057d..fe5bcbf629 100644 --- a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_property_test.go +++ b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_property_test.go @@ -41,8 +41,8 @@ func TestAccIBMCdTektonPipelineTriggerPropertyBasic(t *testing.T) { func TestAccIBMCdTektonPipelineTriggerPropertyAllArgs(t *testing.T) { var conf cdtektonpipelinev2.TriggerProperty name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) - value := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) typeVar := "text" + value := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) path := fmt.Sprintf("tf_path_%d", acctest.RandIntRange(10, 100)) locked := "true" valueUpdate := fmt.Sprintf("tf_value_%d", acctest.RandIntRange(10, 100)) @@ -55,21 +55,21 @@ func TestAccIBMCdTektonPipelineTriggerPropertyAllArgs(t *testing.T) { CheckDestroy: testAccCheckIBMCdTektonPipelineTriggerPropertyDestroy, Steps: []resource.TestStep{ resource.TestStep{ - Config: testAccCheckIBMCdTektonPipelineTriggerPropertyConfig("", "", name, value, typeVar, path, locked), + Config: testAccCheckIBMCdTektonPipelineTriggerPropertyConfig("", "", name, typeVar, value, path, locked), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckIBMCdTektonPipelineTriggerPropertyExists("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", conf), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "name", name), - resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "value", value), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "type", typeVar), + resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "value", value), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "locked", locked), ), }, resource.TestStep{ - Config: testAccCheckIBMCdTektonPipelineTriggerPropertyConfig("", "", name, valueUpdate, typeVar, pathUpdate, lockedUpdate), + Config: testAccCheckIBMCdTektonPipelineTriggerPropertyConfig("", "", name, typeVar, valueUpdate, pathUpdate, lockedUpdate), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "name", name), - resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "value", valueUpdate), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "type", typeVar), + resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "value", valueUpdate), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger_property.cd_tekton_pipeline_trigger_property", "locked", lockedUpdate), ), }, @@ -151,7 +151,7 @@ func testAccCheckIBMCdTektonPipelineTriggerPropertyConfigBasic(pipelineID string `, rgName, tcName) } -func testAccCheckIBMCdTektonPipelineTriggerPropertyConfig(pipelineID string, triggerID string, name string, value string, typeVar string, path string, locked string) string { +func testAccCheckIBMCdTektonPipelineTriggerPropertyConfig(pipelineID string, triggerID string, name string, typeVar string, value string, path string, locked string) string { rgName := acc.CdResourceGroupName tcName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) return fmt.Sprintf(` diff --git a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_test.go b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_test.go index 07fb372eb4..1da2ffac65 100644 --- a/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_test.go +++ b/ibm/service/cdtektonpipeline/resource_ibm_cd_tekton_pipeline_trigger_test.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2023 All Rights Reserved. +// Copyright IBM Corp. 2024 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package cdtektonpipeline_test @@ -62,17 +62,19 @@ func TestAccIBMCdTektonPipelineTriggerAllArgs(t *testing.T) { eventListener := "listener" maxConcurrentRuns := fmt.Sprintf("%d", acctest.RandIntRange(3, 4)) enabled := "false" - favorite := "false" cron := fmt.Sprintf("*/5 10 10 %d *", acctest.RandIntRange(1, 12)) timezone := "Europe/London" + filter := "test" + favorite := "false" typeVarUpdate := "generic" nameUpdate := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) eventListenerUpdate := fmt.Sprintf("tf_event_listener_%d", acctest.RandIntRange(10, 100)) maxConcurrentRunsUpdate := fmt.Sprintf("%d", acctest.RandIntRange(1, 2)) enabledUpdate := "true" - favoriteUpdate := "true" cronUpdate := fmt.Sprintf("*/10 %d 10 10 *", acctest.RandIntRange(1, 23)) timezoneUpdate := "America/New_York" + filterUpdate := "true" + favoriteUpdate := "true" resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -80,7 +82,7 @@ func TestAccIBMCdTektonPipelineTriggerAllArgs(t *testing.T) { CheckDestroy: testAccCheckIBMCdTektonPipelineTriggerDestroy, Steps: []resource.TestStep{ resource.TestStep{ - Config: testAccCheckIBMCdTektonPipelineTriggerConfig(pipelineID, typeVar, name, eventListener, maxConcurrentRuns, enabled, favorite, cron, timezone), + Config: testAccCheckIBMCdTektonPipelineTriggerConfig(pipelineID, typeVar, name, eventListener, maxConcurrentRuns, enabled, cron, timezone, filter, favorite), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckIBMCdTektonPipelineTriggerExists("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", conf), testAccCheckIBMCdTektonPipelineTriggerExists("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger2", conf), @@ -88,9 +90,9 @@ func TestAccIBMCdTektonPipelineTriggerAllArgs(t *testing.T) { resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "name", name), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "max_concurrent_runs", maxConcurrentRuns), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "enabled", enabled), - resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "favorite", favorite), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger2", "cron", cron), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger2", "timezone", timezone), + resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "favorite", favorite), resource.TestCheckResourceAttrSet("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "pipeline_id"), resource.TestCheckResourceAttrSet("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "trigger_id"), resource.TestCheckResourceAttrSet("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger2", "pipeline_id"), @@ -106,14 +108,14 @@ func TestAccIBMCdTektonPipelineTriggerAllArgs(t *testing.T) { ), }, resource.TestStep{ - Config: testAccCheckIBMCdTektonPipelineTriggerConfig(pipelineID, typeVarUpdate, nameUpdate, eventListenerUpdate, maxConcurrentRunsUpdate, enabledUpdate, favoriteUpdate, cronUpdate, timezoneUpdate), + Config: testAccCheckIBMCdTektonPipelineTriggerConfig(pipelineID, typeVarUpdate, nameUpdate, eventListenerUpdate, maxConcurrentRunsUpdate, enabledUpdate, cronUpdate, timezoneUpdate, filterUpdate, favoriteUpdate), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "name", nameUpdate), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "max_concurrent_runs", maxConcurrentRunsUpdate), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "enabled", enabledUpdate), - resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "favorite", favoriteUpdate), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger2", "cron", cronUpdate), resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger2", "timezone", timezoneUpdate), + resource.TestCheckResourceAttr("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "favorite", favoriteUpdate), resource.TestCheckResourceAttrSet("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "pipeline_id"), resource.TestCheckResourceAttrSet("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger", "trigger_id"), resource.TestCheckResourceAttrSet("ibm_cd_tekton_pipeline_trigger.cd_tekton_pipeline_trigger2", "pipeline_id"), @@ -199,7 +201,7 @@ func testAccCheckIBMCdTektonPipelineTriggerConfigBasic(pipelineID string, typeVa `, rgName, tcName, typeVar, name, eventListener) } -func testAccCheckIBMCdTektonPipelineTriggerConfig(pipelineID string, typeVar string, name string, eventListener string, maxConcurrentRuns string, enabled string, favorite string, cron string, timezone string) string { +func testAccCheckIBMCdTektonPipelineTriggerConfig(pipelineID string, typeVar string, name string, eventListener string, maxConcurrentRuns string, enabled string, cron string, timezone string, filter string, favorite string) string { rgName := acc.CdResourceGroupName tcName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) return fmt.Sprintf(` diff --git a/ibm/service/cis/data_source_ibm_cis_origin_certificate_order.go b/ibm/service/cis/data_source_ibm_cis_origin_certificate_order.go new file mode 100644 index 0000000000..c815450ac3 --- /dev/null +++ b/ibm/service/cis/data_source_ibm_cis_origin_certificate_order.go @@ -0,0 +1,197 @@ +// Copyright IBM Corp. 2017, 2021, 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package cis + +import ( + "log" + "reflect" + "time" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func DataSourceIBMCISOriginCertificateOrder() *schema.Resource { + return &schema.Resource{ + Read: DataIBMCISOriginCertificateRead, + Importer: &schema.ResourceImporter{}, + Schema: map[string]*schema.Schema{ + cisID: { + Type: schema.TypeString, + Description: "CIS object ID or CRN", + Required: true, + ValidateFunc: validate.InvokeValidator(ibmCISOriginCertificateOrder, + "cis_id"), + }, + cisDomainID: { + Type: schema.TypeString, + Description: "Associated CIS domain", + Required: true, + DiffSuppressFunc: suppressDomainIDDiff, + }, + cisOriginCertificateID: { + Type: schema.TypeString, + Description: "Certificate ID", + Optional: true, + }, + cisOriginCertificateList: { + Type: schema.TypeList, + Description: "List of certificate", + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + cisOriginCertificateID: { + Type: schema.TypeString, + Description: "Certificate ID", + Computed: true, + }, + cisOriginCertificateType: { + Type: schema.TypeString, + Description: "Certificate type", + Computed: true, + }, + cisOriginCertificateHosts: { + Type: schema.TypeList, + Description: "Hosts for which certificates need to be ordered", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + cisOriginCertificateValidityDays: { + Type: schema.TypeInt, + Description: "Validity days", + Computed: true, + }, + cisOriginCertificateCSR: { + Type: schema.TypeString, + Description: "CSR", + Computed: true, + }, + cisOriginCertificatePrivateKey: { + Type: schema.TypeString, + Description: "Certificate private key", + Computed: true, + }, + cisOriginCertificate: { + Type: schema.TypeString, + Description: "Certificate", + Computed: true, + }, + cisOriginCertificateExpiresOn: { + Type: schema.TypeString, + Description: "Expiration date of the certificate", + Computed: true, + }, + }, + }, + }, + }, + } +} + +func DataIBMCISOriginCertificateOrderValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "cis_id", + ValidateFunctionIdentifier: validate.ValidateCloudData, + Type: validate.TypeString, + CloudDataType: "data_instance", + CloudDataRange: []string{"service:internet-svcs"}, + Required: true}) + + cisOriginCertificateOrderValidator := validate.ResourceValidator{ + ResourceName: ibmCISOriginCertificateOrder, + Schema: validateSchema} + return &cisOriginCertificateOrderValidator +} + +func DataIBMCISOriginCertificateRead(d *schema.ResourceData, meta interface{}) error { + + cisClient, err := meta.(conns.ClientSession).CisSSLClientSession() + if err != nil { + return err + } + + crn := d.Get(cisID).(string) + zoneID := d.Get(cisDomainID).(string) + cert_id := d.Get(cisOriginCertificateID).(string) + + cisClient.Crn = core.StringPtr(crn) + cisClient.ZoneIdentifier = core.StringPtr(zoneID) + + originCertList := make([]map[string]interface{}, 0) + + if cert_id != "" { + + opt := cisClient.NewGetOriginCertificateOptions(crn, zoneID, cert_id) + result, resp, err := cisClient.GetOriginCertificate(opt) + if err != nil { + log.Printf("Get Certificate read failed: %v", resp) + return err + } + + certOutput := map[string]interface{}{} + certOutput[cisOriginCertificateID] = *result.Result.ID + if !reflect.ValueOf(result.Result.RequestType).IsNil() { + certOutput[cisOriginCertificateType] = *result.Result.RequestType + } + certOutput[cisOriginCertificateHosts] = flex.FlattenStringList(result.Result.Hostnames) + if !reflect.ValueOf(result.Result.RequestedValidity).IsNil() { + certOutput[cisOriginCertificateValidityDays] = *result.Result.RequestedValidity + } + if !reflect.ValueOf(result.Result.Csr).IsNil() { + certOutput[cisOriginCertificateCSR] = *result.Result.Csr + } + if !reflect.ValueOf(result.Result.PrivateKey).IsNil() { + certOutput[cisOriginCertificatePrivateKey] = *result.Result.PrivateKey + } + certOutput[cisOriginCertificate] = *result.Result.Certificate + certOutput[cisOriginCertificateExpiresOn] = *result.Result.ExpiresOn + + originCertList = append(originCertList, certOutput) + + } else { + opt := cisClient.NewListOriginCertificatesOptions(crn, zoneID) + result, resp, err := cisClient.ListOriginCertificates(opt) + if err != nil { + log.Printf("List Certificate read failed: %v", resp) + return err + } + for _, certObj := range result.Result { + certOutput := map[string]interface{}{} + certOutput[cisOriginCertificateID] = *certObj.ID + if !reflect.ValueOf(certObj.RequestType).IsNil() { + certOutput[cisOriginCertificateType] = *certObj.RequestType + } + certOutput[cisOriginCertificateHosts] = flex.FlattenStringList(certObj.Hostnames) + if !reflect.ValueOf(certObj.RequestedValidity).IsNil() { + certOutput[cisOriginCertificateValidityDays] = *certObj.RequestedValidity + } + if !reflect.ValueOf(certObj.Csr).IsNil() { + certOutput[cisOriginCertificateCSR] = *certObj.Csr + } + if !reflect.ValueOf(certObj.PrivateKey).IsNil() { + certOutput[cisOriginCertificatePrivateKey] = *certObj.PrivateKey + } + certOutput[cisOriginCertificate] = *certObj.Certificate + certOutput[cisOriginCertificateExpiresOn] = *certObj.ExpiresOn + + originCertList = append(originCertList, certOutput) + } + } + + d.SetId(dataSourceIBMCISOriginCertificatesID()) + d.Set(cisID, crn) + d.Set(cisDomainID, zoneID) + d.Set(cisOriginCertificateList, originCertList) + + return nil +} + +func dataSourceIBMCISOriginCertificatesID() string { + return time.Now().UTC().String() +} diff --git a/ibm/service/cis/data_source_ibm_cis_origin_certificate_order_test.go b/ibm/service/cis/data_source_ibm_cis_origin_certificate_order_test.go new file mode 100644 index 0000000000..3cce40e001 --- /dev/null +++ b/ibm/service/cis/data_source_ibm_cis_origin_certificate_order_test.go @@ -0,0 +1,38 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package cis_test + +import ( + "fmt" + "testing" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccIBMCisOriginCertificateDataSource_Basic(t *testing.T) { + name := "data.ibm_cis_certificate_order.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckCis(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckCisOriginCertificateDataSourceConfigBasic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "hosts.#", "1"), + ), + }, + }, + }) +} + +func testAccCheckCisOriginCertificateDataSourceConfigBasic() string { + return testAccCheckIBMCisDomainDataSourceConfigBasic1() + fmt.Sprint(` + data "ibm_cis_origin_certificates" "test" { + cis_id = data.ibm_cis.cis.id + domain_id = data.ibm_cis_domain.cis_domain.domain_id + } + `, acc.CisDomainStatic) +} diff --git a/ibm/service/cis/resource_ibm_cis_advanced_certificate_pack_order.go b/ibm/service/cis/resource_ibm_cis_advanced_certificate_pack_order.go new file mode 100644 index 0000000000..84543114aa --- /dev/null +++ b/ibm/service/cis/resource_ibm_cis_advanced_certificate_pack_order.go @@ -0,0 +1,189 @@ +// Copyright IBM Corp. 2017, 2021, 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package cis + +import ( + "log" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +const ( + ibmCISAdvancedCertificatePackOrder = "ibm_cis_advanced_certificate_pack_order" + cisAdvancedCertificatePackOrderID = "certificate_id" + cisAdvancedCertificatePackOrderHosts = "hosts" + cisAdvancedCertificatePackOrderType = "type" + cisAdvancedCertificatePackOrderTypeDedicated = "dedicated" + cisAdvancedCertificatePackOrderStatus = "status" + cisAdvancedCertificatePackValidationMethod = "validation_method" + cisAdvancedCertificatePackValidityDays = "validity" + cisAdvancedCertificatePackCertificateAthority = "certificate_authority" + cisAdvancedCertificatePackCloudflareBranding = "cloudflare_branding" + cisAdvancedCertificatePackOrderTypeAdvanced = "advanced" + cisOriginCertificateList = "origin_certificate_list" +) + +func ResourceIBMCISAdvancedCertificatePackOrder() *schema.Resource { + return &schema.Resource{ + Create: ResourceIBMCISAdvancedCertificatePackOrderCreate, + Update: ResourceIBMCISAdvancedCertificatePackOrderRead, + Read: ResourceIBMCISAdvancedCertificatePackOrderRead, + Delete: ResourceIBMCISAdvancedCertificatePackOrderDelete, + Importer: &schema.ResourceImporter{}, + Schema: map[string]*schema.Schema{ + cisID: { + Type: schema.TypeString, + Description: "CIS object ID or CRN", + Required: true, + ValidateFunc: validate.InvokeValidator(ibmCISAdvancedCertificatePackOrder, + "cis_id"), + }, + cisDomainID: { + Type: schema.TypeString, + Description: "Associated CIS domain", + Required: true, + DiffSuppressFunc: suppressDomainIDDiff, + }, + cisAdvancedCertificatePackOrderID: { + Type: schema.TypeString, + Description: "Certificate ID", + Computed: true, + }, + cisAdvancedCertificatePackOrderType: { + Type: schema.TypeString, + Description: "Certificate type", + Optional: true, + Default: cisAdvancedCertificatePackOrderTypeAdvanced, + ValidateFunc: validate.InvokeValidator(ibmCISAdvancedCertificatePackOrder, + cisAdvancedCertificatePackOrderType), + }, + cisAdvancedCertificatePackOrderHosts: { + Type: schema.TypeList, + Description: "Hosts for which certificates need to be ordered", + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + cisAdvancedCertificatePackOrderStatus: { + Type: schema.TypeString, + Description: "Certificate status", + Computed: true, + }, + cisAdvancedCertificatePackValidationMethod: { + Type: schema.TypeString, + Description: "Validation method", + Required: true, + }, + cisAdvancedCertificatePackValidityDays: { + Type: schema.TypeInt, + Description: "Validity days", + Required: true, + }, + cisAdvancedCertificatePackCertificateAthority: { + Type: schema.TypeString, + Description: "Certificate authority", + Required: true, + }, + cisAdvancedCertificatePackCloudflareBranding: { + Type: schema.TypeBool, + Description: "Cloudflare branding", + Optional: true, + Default: false, + }, + }, + } +} + +func ResourceIBMCISAdvancedCertificatePackOrderValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "cis_id", + ValidateFunctionIdentifier: validate.ValidateCloudData, + Type: validate.TypeString, + CloudDataType: "resource_instance", + CloudDataRange: []string{"service:internet-svcs"}, + Required: true}) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: cisCertificateOrderType, + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: cisAdvancedCertificatePackOrderTypeAdvanced}) + + cisCertificateOrderValidator := validate.ResourceValidator{ + ResourceName: ibmCISAdvancedCertificatePackOrder, + Schema: validateSchema} + return &cisCertificateOrderValidator +} + +func ResourceIBMCISAdvancedCertificatePackOrderCreate(d *schema.ResourceData, meta interface{}) error { + cisClient, err := meta.(conns.ClientSession).CisSSLClientSession() + if err != nil { + return err + } + crn := d.Get(cisID).(string) + zoneID := d.Get(cisDomainID).(string) + certType := d.Get(cisAdvancedCertificatePackOrderType).(string) + cisClient.Crn = core.StringPtr(crn) + cisClient.ZoneIdentifier = core.StringPtr(zoneID) + + hosts := d.Get(cisAdvancedCertificatePackOrderHosts) + hostsList := flex.ExpandStringList(hosts.([]interface{})) + validationMethod := d.Get(cisAdvancedCertificatePackValidationMethod).(string) + validityDays := int64(d.Get(cisAdvancedCertificatePackValidityDays).(int)) + certificateAuthority := d.Get(cisAdvancedCertificatePackCertificateAthority).(string) + cfBranding := d.Get(cisAdvancedCertificatePackCloudflareBranding).(bool) + + opt := cisClient.NewOrderAdvancedCertificateOptions() + opt.SetType(certType) + opt.SetHosts(hostsList) + opt.SetValidationMethod(validationMethod) + opt.SetValidityDays(validityDays) + opt.SetCertificateAuthority(certificateAuthority) + opt.SetCloudflareBranding(cfBranding) + + result, resp, err := cisClient.OrderAdvancedCertificate(opt) + if err != nil { + log.Printf("Advanced Certificate Pack order failed: %v", resp) + return err + } + + d.SetId(flex.ConvertCisToTfThreeVar(*result.Result.ID, zoneID, crn)) + d.Set(cisAdvancedCertificatePackOrderID, *result.Result.ID) + d.Set(cisAdvancedCertificatePackOrderStatus, *result.Result.Status) + + return nil +} + +func ResourceIBMCISAdvancedCertificatePackOrderRead(d *schema.ResourceData, meta interface{}) error { + + return nil +} + +func ResourceIBMCISAdvancedCertificatePackOrderDelete(d *schema.ResourceData, meta interface{}) error { + cisClient, err := meta.(conns.ClientSession).CisSSLClientSession() + if err != nil { + return err + } + certificateID, zoneID, crn, err := flex.ConvertTfToCisThreeVar(d.Id()) + if err != nil { + log.Println("Error in reading certificate ID") + return err + } + cisClient.Crn = core.StringPtr(crn) + cisClient.ZoneIdentifier = core.StringPtr(zoneID) + opt := cisClient.NewDeleteCertificateV2Options(certificateID) + resp, err := cisClient.DeleteCertificateV2(opt) + if err != nil { + log.Printf("Advanced Certificate Pack delete failed: %v", resp) + return err + } + + return nil +} diff --git a/ibm/service/cis/resource_ibm_cis_advanced_certificate_pack_order_test.go b/ibm/service/cis/resource_ibm_cis_advanced_certificate_pack_order_test.go new file mode 100644 index 0000000000..c5360158e0 --- /dev/null +++ b/ibm/service/cis/resource_ibm_cis_advanced_certificate_pack_order_test.go @@ -0,0 +1,42 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package cis_test + +import ( + "fmt" + "testing" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccIBMCisAdvancedCertificatepackOrder_Basic(t *testing.T) { + name := "ibm_cis_advanced_certificate_pack_order.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckCis(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckCisAdvancedCertificatePackOrderConfigBasic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "hosts.#", "1"), + ), + }, + }, + }) +} + +func testAccCheckCisAdvancedCertificatePackOrderConfigBasic() string { + return fmt.Sprintf(` + resource "ibm_cis_advanced_certificate_pack_order" "test" { + cis_id = data.ibm_cis.cis.id + domain_id = data.ibm_cis_domain.cis_domain.domain_id + hosts = ["%[1]s"] + certificate_authority = "lets_encrypt" + validation_method = "txt" + validity = 90 + } + `, acc.CisDomainStatic) +} diff --git a/ibm/service/cis/resource_ibm_cis_domain_settings.go b/ibm/service/cis/resource_ibm_cis_domain_settings.go index 64ddb7047b..2d3100b727 100644 --- a/ibm/service/cis/resource_ibm_cis_domain_settings.go +++ b/ibm/service/cis/resource_ibm_cis_domain_settings.go @@ -59,6 +59,8 @@ const ( cisDomainSettingsMobileRedirectStripURI = "strip_uri" cisDomainSettingsMaxUpload = "max_upload" cisDomainSettingsCipher = "cipher" + cisDomainSettingsOriginMaxHTTPVersion = "origin_max_http_version" + cisDomainSettingsOriginPostQuantumEncryption = "origin_post_quantum_encryption" // cisDomainSettingsONOFFValidatorID = "on_off" // cisDomainSettingsActiveDisableValidatorID = "active_disable" cisDomainSettingsSSLSettingValidatorID = "ssl_setting" @@ -349,6 +351,24 @@ func ResourceIBMCISSettings() *schema.Resource { cisDomainSettingsCipherValidatorID), }, }, + cisDomainSettingsOriginMaxHTTPVersion: { + Type: schema.TypeString, + Description: "Max HTTP version used to connect to the origin", + Optional: true, + Computed: true, + ValidateFunc: validate.InvokeValidator( + ibmCISDomainSettings, + cisDomainSettingsOriginMaxHTTPVersion), + }, + cisDomainSettingsOriginPostQuantumEncryption: { + Type: schema.TypeString, + Description: "Enables post-quantum cryptography to connect to the origin", + Optional: true, + Computed: true, + ValidateFunc: validate.InvokeValidator( + ibmCISDomainSettings, + cisDomainSettingsOriginPostQuantumEncryption), + }, cisDomainSettingsMinify: { Type: schema.TypeList, Description: "Minify setting", @@ -474,6 +494,7 @@ func ResourceIBMCISDomainSettingValidator() *validate.ResourceValidator { challengeTTL := "300, 900, 1800, 2700, 3600, 7200, 10800, 14400, 28800, 57600, 86400, 604800, 2592000, 31536000" maxUpload := "100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375, 400, 425, 450, 475, 500" cipher := "ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-ECDSA-CHACHA20-POLY1305, ECDHE-RSA-AES128-GCM-SHA256,ECDHE-RSA-CHACHA20-POLY1305, ECDHE-ECDSA-AES128-SHA256, ECDHE-ECDSA-AES128-SHA, ECDHE-RSA-AES128-SHA256, ECDHE-RSA-AES128-SHA, AES128-GCM-SHA256, AES128-SHA256, AES128-SHA, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES256-SHA384, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-RSA-AES256-SHA384, ECDHE-RSA-AES256-SHA, AES256-GCM-SHA384, AES256-SHA256, AES256-SHA, DES-CBC3-SHA, AEAD-AES128-GCM-SHA256, AEAD-AES256-GCM-SHA384, AEAD-CHACHA20-POLY1305-SHA256" + quantumEncryption := "off, preferred, supported" validateSchema := make([]validate.ValidateSchema, 0) validateSchema = append(validateSchema, @@ -727,6 +748,20 @@ func ResourceIBMCISDomainSettingValidator() *validate.ResourceValidator { Type: validate.TypeString, Required: true, AllowedValues: cipher}) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: cisDomainSettingsOriginMaxHTTPVersion, + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: "1,2"}) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: cisDomainSettingsOriginPostQuantumEncryption, + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: quantumEncryption}) ibmCISDomainSettingResourceValidator := validate.ResourceValidator{ ResourceName: ibmCISDomainSettings, Schema: validateSchema} @@ -765,6 +800,8 @@ var settingsList = []string{ cisDomainSettingsMobileRedirect, cisDomainSettingsMaxUpload, cisDomainSettingsCipher, + cisDomainSettingsOriginMaxHTTPVersion, + cisDomainSettingsOriginPostQuantumEncryption, } func resourceCISSettingsUpdate(d *schema.ResourceData, meta interface{}) error { @@ -1015,6 +1052,22 @@ func resourceCISSettingsUpdate(d *schema.ResourceData, meta interface{}) error { _, resp, err = cisClient.UpdateCiphers(opt) } } + case cisDomainSettingsOriginMaxHTTPVersion: + if d.HasChange(item) { + if v, ok := d.GetOk(item); ok { + opt := cisClient.NewUpdateOriginMaxHttpVersionOptions() + opt.SetValue(v.(string)) + _, resp, err = cisClient.UpdateOriginMaxHttpVersion(opt) + } + } + case cisDomainSettingsOriginPostQuantumEncryption: + if d.HasChange(item) { + if v, ok := d.GetOk(item); ok { + opt := cisClient.NewUpdateOriginPostQuantumEncryptionOptions() + opt.SetValue(v.(string)) + _, resp, err = cisClient.UpdateOriginPostQuantumEncryption(opt) + } + } case cisDomainSettingsMinify: if d.HasChange(item) { if v, ok := d.GetOk(item); ok { @@ -1360,6 +1413,23 @@ func resourceCISSettingsRead(d *schema.ResourceData, meta interface{}) error { settingResponse = resp settingErr = err + case cisDomainSettingsOriginMaxHTTPVersion: + opt := cisClient.NewGetOriginMaxHttpVersionOptions() + result, resp, err := cisClient.GetOriginMaxHttpVersion(opt) + if err == nil { + d.Set(cisDomainSettingsOriginMaxHTTPVersion, result.Result.Value) + } + settingResponse = resp + settingErr = err + case cisDomainSettingsOriginPostQuantumEncryption: + opt := cisClient.NewGetOriginPostQuantumEncryptionOptions() + result, resp, err := cisClient.GetOriginPostQuantumEncryption(opt) + if err == nil { + d.Set(cisDomainSettingsOriginPostQuantumEncryption, result.Result.Value) + } + settingResponse = resp + settingErr = err + case cisDomainSettingsMinify: opt := cisClient.NewGetMinifyOptions() result, resp, err := cisClient.GetMinify(opt) diff --git a/ibm/service/cis/resource_ibm_cis_origin_certificate_order.go b/ibm/service/cis/resource_ibm_cis_origin_certificate_order.go new file mode 100644 index 0000000000..debe514c66 --- /dev/null +++ b/ibm/service/cis/resource_ibm_cis_origin_certificate_order.go @@ -0,0 +1,195 @@ +// Copyright IBM Corp. 2017, 2021, 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package cis + +import ( + "log" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +const ( + ibmCISOriginCertificateOrder = "ibm_cis_origin_certificate_order" + cisOriginCertificate = "certificate" + cisOriginCertificateID = "certificate_id" + cisOriginCertificateHosts = "hostnames" + cisOriginCertificateType = "request_type" + cisOriginCertificateValidityDays = "requested_validity" + cisOriginCertificateCSR = "csr" + cisOriginCertificateExpiresOn = "expires_on" + cisOriginCertificatePrivateKey = "private_key" +) + +func ResourceIBMCISOriginCertificateOrder() *schema.Resource { + return &schema.Resource{ + Create: ResourceIBMCISOriginCertificateCreate, + Update: ResourceIBMCISOriginCertificateRead, + Read: ResourceIBMCISOriginCertificateRead, + Delete: ResourceIBMCISOriginCertificateDelete, + Importer: &schema.ResourceImporter{}, + Schema: map[string]*schema.Schema{ + cisID: { + Type: schema.TypeString, + Description: "CIS object ID or CRN", + Required: true, + ValidateFunc: validate.InvokeValidator(ibmCISOriginCertificateOrder, + "cis_id"), + }, + cisDomainID: { + Type: schema.TypeString, + Description: "Associated CIS domain", + Required: true, + DiffSuppressFunc: suppressDomainIDDiff, + }, + cisOriginCertificateID: { + Type: schema.TypeString, + Description: "Certificate ID", + Computed: true, + }, + cisOriginCertificateType: { + Type: schema.TypeString, + Description: "Certificate type", + Required: true, + }, + cisOriginCertificateHosts: { + Type: schema.TypeList, + Description: "Hosts for which certificates need to be ordered", + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + cisOriginCertificateValidityDays: { + Type: schema.TypeInt, + Description: "Calidity days", + Required: true, + }, + cisOriginCertificateCSR: { + Type: schema.TypeString, + Description: "CSR", + Required: true, + }, + cisOriginCertificatePrivateKey: { + Type: schema.TypeString, + Description: "Certificate private key", + Computed: true, + }, + cisOriginCertificate: { + Type: schema.TypeString, + Description: "Certificate", + Computed: true, + }, + cisOriginCertificateExpiresOn: { + Type: schema.TypeString, + Description: "Expiration date of the certificate", + Computed: true, + }, + }, + } +} + +func ResourceIBMCISOriginCertificateOrderValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "cis_id", + ValidateFunctionIdentifier: validate.ValidateCloudData, + Type: validate.TypeString, + CloudDataType: "resource_instance", + CloudDataRange: []string{"service:internet-svcs"}, + Required: true}) + + cisCertificateOrderValidator := validate.ResourceValidator{ + ResourceName: ibmCISOriginCertificateOrder, + Schema: validateSchema} + return &cisCertificateOrderValidator +} + +func ResourceIBMCISOriginCertificateCreate(d *schema.ResourceData, meta interface{}) error { + cisClient, err := meta.(conns.ClientSession).CisSSLClientSession() + if err != nil { + return err + } + crn := d.Get(cisID).(string) + zoneID := d.Get(cisDomainID).(string) + cisClient.Crn = core.StringPtr(crn) + cisClient.ZoneIdentifier = core.StringPtr(zoneID) + + certType := d.Get(cisOriginCertificateType).(string) + hosts := d.Get(cisOriginCertificateHosts) + hostsList := flex.ExpandStringList(hosts.([]interface{})) + validityDays := int64(d.Get(cisOriginCertificateValidityDays).(int)) + csr := d.Get(cisOriginCertificateCSR).(string) + + opt := cisClient.NewCreateOriginCertificateOptions(crn, zoneID) + opt.SetHostnames(hostsList) + opt.SetCsr(csr) + opt.SetRequestType(certType) + opt.SetRequestedValidity(validityDays) + + result, resp, err := cisClient.CreateOriginCertificate(opt) + if err != nil { + log.Printf("Origin Certificate order failed: %v", resp) + return err + } + + d.SetId(flex.ConvertCisToTfThreeVar(*result.Result.ID, zoneID, crn)) + return ResourceIBMCISOriginCertificateRead(d, meta) +} + +func ResourceIBMCISOriginCertificateRead(d *schema.ResourceData, meta interface{}) error { + + cisClient, err := meta.(conns.ClientSession).CisSSLClientSession() + if err != nil { + return err + } + certificateID, zoneID, crn, err := flex.ConvertTfToCisThreeVar(d.Id()) + if err != nil { + log.Println("Error in reading certificate ID") + return err + } + cisClient.Crn = core.StringPtr(crn) + cisClient.ZoneIdentifier = core.StringPtr(zoneID) + opt := cisClient.NewGetOriginCertificateOptions(crn, zoneID, certificateID) + result, resp, err := cisClient.GetOriginCertificate(opt) + if err != nil { + log.Printf("Certificate read failed: %v", resp) + return err + } + d.Set(cisID, crn) + d.Set(cisDomainID, zoneID) + d.Set(cisOriginCertificateID, result.Result.ID) + d.Set(cisOriginCertificate, result.Result.Certificate) + d.Set(cisOriginCertificateHosts, flex.FlattenStringList(result.Result.Hostnames)) + d.Set(cisOriginCertificateExpiresOn, result.Result.ExpiresOn) + d.Set(cisOriginCertificateType, result.Result.RequestType) + d.Set(cisOriginCertificateValidityDays, result.Result.RequestedValidity) + d.Set(cisOriginCertificateCSR, result.Result.Csr) + d.Set(cisOriginCertificatePrivateKey, result.Result.PrivateKey) + return nil +} + +func ResourceIBMCISOriginCertificateDelete(d *schema.ResourceData, meta interface{}) error { + cisClient, err := meta.(conns.ClientSession).CisSSLClientSession() + if err != nil { + return err + } + certificateID, zoneID, crn, err := flex.ConvertTfToCisThreeVar(d.Id()) + if err != nil { + log.Println("Error in reading certificate Id") + return err + } + cisClient.Crn = core.StringPtr(crn) + cisClient.ZoneIdentifier = core.StringPtr(zoneID) + opt := cisClient.NewRevokeOriginCertificateOptions(crn, zoneID, certificateID) + resp, _, err := cisClient.RevokeOriginCertificate(opt) + if err != nil { + log.Printf("Origin Certificate delete failed: %v", resp) + return err + } + + return nil +} diff --git a/ibm/service/cis/resource_ibm_cis_origin_certificate_order_test.go b/ibm/service/cis/resource_ibm_cis_origin_certificate_order_test.go new file mode 100644 index 0000000000..d3b338f7d3 --- /dev/null +++ b/ibm/service/cis/resource_ibm_cis_origin_certificate_order_test.go @@ -0,0 +1,42 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package cis_test + +import ( + "fmt" + "testing" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccIBMCisOriginCertificate_Basic(t *testing.T) { + name := "ibm_cis_origin_certificate_order.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckCis(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckCisOrigibnCertificateOrderConfigBasic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "hosts.#", "1"), + ), + }, + }, + }) +} + +func testAccCheckCisOrigibnCertificateOrderConfigBasic() string { + return fmt.Sprintf(` + resource "ibm_cis_certificate_order" "test" { + cis_id = data.ibm_cis.cis.id + domain_id = data.ibm_cis_domain.cis_domain.domain_id + hostnames = ["%[1]s"] + request_type = "origin-rsa" + requested_validity = 5475 + csr = "-----BEGIN CERTIFICATE REQUEST-----\nMIICxzCCAa8CAQAwSDELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lz\nY28xCzAJBgNVBAcTAkNBMRQwEgYDVQQDEwtleGFtcGxlLm5ldDCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALxejtu4b+jPdFeFi6OUsye8TYJQBm3WfCvL\nHu5EvijMO/4Z2TImwASbwUF7Ir8OLgH+mGlQZeqyNvGoSOMEaZVXcYfpR1hlVak8\n4GGVr+04IGfOCqaBokaBFIwzclGZbzKmLGwIQioNxGfqFm6RGYGA3be2Je2iseBc\nN8GV1wYmvYE0RR+yWweJCTJ157exyRzu7sVxaEW9F87zBQLyOnwXc64rflXslRqi\ng7F7w5IaQYOl8yvmk/jEPCAha7fkiUfEpj4N12+oPRiMvleJF98chxjD4MH39c5I\nuOslULhrWunfh7GB1jwWNA9y44H0snrf+xvoy2TcHmxvma9Eln8CAwEAAaA6MDgG\nCSqGSIb3DQEJDjErMCkwJwYDVR0RBCAwHoILZXhhbXBsZS5uZXSCD3d3dy5leGFt\ncGxlLm5ldDANBgkqhkiG9w0BAQsFAAOCAQEAcBaX6dOnI8ncARrI9ZSF2AJX+8mx\npTHY2+Y2C0VvrVDGMtbBRH8R9yMbqWtlxeeNGf//LeMkSKSFa4kbpdx226lfui8/\nauRDBTJGx2R1ccUxmLZXx4my0W5iIMxunu+kez+BDlu7bTT2io0uXMRHue4i6quH\nyc5ibxvbJMjR7dqbcanVE10/34oprzXQsJ/VmSuZNXtjbtSKDlmcpw6To/eeAJ+J\nhXykcUihvHyG4A1m2R6qpANBjnA0pHexfwM/SgfzvpbvUg0T1ubmer8BgTwCKIWs\ndcWYTthM51JIqRBfNqy4QcBnX+GY05yltEEswQI55wdiS3CjTTA67sdbcQ==\n-----END CERTIFICATE REQUEST-----" + } + `, acc.CisDomainStatic) +} diff --git a/ibm/service/cloudant/data_source_ibm_cloudant.go b/ibm/service/cloudant/data_source_ibm_cloudant.go index 142174ec9b..510a5c32f4 100644 --- a/ibm/service/cloudant/data_source_ibm_cloudant.go +++ b/ibm/service/cloudant/data_source_ibm_cloudant.go @@ -4,9 +4,9 @@ package cloudant import ( - "fmt" "log" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/resourcecontroller" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -144,7 +144,7 @@ func dataSourceIBMCloudantRead(d *schema.ResourceData, meta interface{}) error { func setCloudantServerInformation(client *cloudantv1.CloudantV1, d *schema.ResourceData) error { serverInformation, err := readCloudantServerInformation(client) if err != nil { - return fmt.Errorf("[ERROR] Error retrieving server information: %s", err) + return flex.FmtErrorf("[ERROR] Error retrieving server information: %s", err) } if serverInformation.Vendor != nil && serverInformation.Vendor.Version != nil { diff --git a/ibm/service/cloudant/data_source_ibm_cloudant_database.go b/ibm/service/cloudant/data_source_ibm_cloudant_database.go index f62f10ad19..8318f03a31 100644 --- a/ibm/service/cloudant/data_source_ibm_cloudant_database.go +++ b/ibm/service/cloudant/data_source_ibm_cloudant_database.go @@ -5,10 +5,10 @@ package cloudant import ( "context" - "fmt" "log" "time" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -150,12 +150,14 @@ func dataSourceIBMCloudantDatabaseRead(context context.Context, d *schema.Resour instanceCRN := d.Get("instance_crn").(string) cUrl, err := GetCloudantInstanceUrl(instanceCRN, meta) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "read", "get-instance-url") + return tfErr.GetDiag() } cloudantClient, err := GetCloudantClientForUrl(cUrl, meta) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "read", "get-client") + return tfErr.GetDiag() } dbName := d.Get("db").(string) @@ -164,7 +166,8 @@ func dataSourceIBMCloudantDatabaseRead(context context.Context, d *schema.Resour databaseInformation, response, err := cloudantClient.GetDatabaseInformationWithContext(context, getDatabaseInformationOptions) if err != nil { log.Printf("[DEBUG] GetDatabaseInformationWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetDatabaseInformationWithContext failed %s\n%s", err, response)) + tfErr := flex.DiscriminatedTerraformErrorf(err, response.String(), "ibm_cloudant_database", "read", "get-database-information") + return tfErr.GetDiag() } d.SetId(dataSourceIBMCloudantDatabaseID(d)) @@ -172,7 +175,8 @@ func dataSourceIBMCloudantDatabaseRead(context context.Context, d *schema.Resour if databaseInformation.Cluster != nil { err = d.Set("cluster", dataSourceDatabaseInformationFlattenCluster(*databaseInformation.Cluster)) if err != nil { - return diag.FromErr(fmt.Errorf("Error setting cluster %s", err)) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "read", "set-cluster-property") + return tfErr.GetDiag() } } diff --git a/ibm/service/cloudant/resource_ibm_cloudant.go b/ibm/service/cloudant/resource_ibm_cloudant.go index ed1f8f7635..58800e1f8e 100644 --- a/ibm/service/cloudant/resource_ibm_cloudant.go +++ b/ibm/service/cloudant/resource_ibm_cloudant.go @@ -191,7 +191,7 @@ func resourceIBMCloudantCreate(d *schema.ResourceData, meta interface{}) error { if d.Get("include_data_events").(bool) { err := updateCloudantActivityTrackerEvents(client, d) if err != nil { - return fmt.Errorf("[ERROR] Error updating activity tracker events: %s", err) + return flex.FmtErrorf("[ERROR] Error updating activity tracker events: %s", err) } } @@ -199,13 +199,13 @@ func resourceIBMCloudantCreate(d *schema.ResourceData, meta interface{}) error { if d.Get("capacity").(int) > 1 { err := updateCloudantInstanceCapacity(client, d) if err != nil { - return fmt.Errorf("[ERROR] Error retrieving capacity throughput information: %s", err) + return flex.FmtErrorf("[ERROR] Error retrieving capacity throughput information: %s", err) } } err = updateCloudantInstanceCors(client, d) if err != nil { - return fmt.Errorf("[ERROR] Error updating CORS settings: %s", err) + return flex.FmtErrorf("[ERROR] Error updating CORS settings: %s", err) } return resourceIBMCloudantRead(d, meta) @@ -276,21 +276,21 @@ func resourceIBMCloudantUpdate(d *schema.ResourceData, meta interface{}) error { if d.HasChange("include_data_events") { err := updateCloudantActivityTrackerEvents(client, d) if err != nil { - return fmt.Errorf("[ERROR] Error updating activity tracker events: %s", err) + return flex.FmtErrorf("[ERROR] Error updating activity tracker events: %s", err) } } if d.HasChange("capacity") { err := updateCloudantInstanceCapacity(client, d) if err != nil { - return fmt.Errorf("[ERROR] Error retrieving capacity throughput information: %s", err) + return flex.FmtErrorf("[ERROR] Error retrieving capacity throughput information: %s", err) } } if d.HasChange("enable_cors") { err := updateCloudantInstanceCors(client, d) if err != nil { - return fmt.Errorf("[ERROR] Error updating CORS settings: %s", err) + return flex.FmtErrorf("[ERROR] Error updating CORS settings: %s", err) } } @@ -363,7 +363,7 @@ func getCloudantClient(d *schema.ResourceData, meta interface{}) (*cloudantv1.Cl case "private": _, ok := extensions["endpoints.private"] if !ok { - return nil, fmt.Errorf("[ERROR] Missing endpoints.private in extensions") + return nil, flex.FmtErrorf("[ERROR] Missing endpoints.private in extensions") } endpoint = "https://" + extensions["endpoints.private"].(string) case "public-and-private": @@ -374,7 +374,7 @@ func getCloudantClient(d *schema.ResourceData, meta interface{}) (*cloudantv1.Cl endpoint = conns.EnvFallBack([]string{"IBMCLOUD_CLOUDANT_ENDPOINT"}, endpoint) if endpoint == "" { - return nil, fmt.Errorf("[ERROR] Missing endpoints.public in extensions") + return nil, flex.FmtErrorf("[ERROR] Missing endpoints.public in extensions") } return GetCloudantClientForUrl(endpoint, meta) @@ -417,7 +417,7 @@ func GetCloudantClientForUrl(endpoint string, meta interface{}) (*cloudantv1.Clo URL: endpoint, }) if err != nil { - return nil, fmt.Errorf("[ERROR] Error occured while configuring Cloudant service: %q", err) + return nil, flex.FmtErrorf("[ERROR] Error occured while configuring Cloudant service: %q", err) } client.Service.SetUserAgent("cloudant-terraform/" + version.Version) @@ -427,7 +427,7 @@ func GetCloudantClientForUrl(endpoint string, meta interface{}) (*cloudantv1.Clo func setCloudantActivityTrackerEvents(client *cloudantv1.CloudantV1, d *schema.ResourceData) error { activityTrackerEvents, err := readCloudantActivityTrackerEvents(client) if err != nil { - return fmt.Errorf("[ERROR] Error retrieving activity tracker events: %s", err) + return flex.FmtErrorf("[ERROR] Error retrieving activity tracker events: %s", err) } if activityTrackerEvents.Types != nil { includeDataEvents := false @@ -470,7 +470,7 @@ func validateCloudantInstanceCapacity(d *schema.ResourceData) error { plan := d.Get("plan").(string) capacity := d.Get("capacity").(int) if capacity > 1 && plan == "lite" { - return fmt.Errorf("[ERROR] Setting capacity is not supported for your instance's plan") + return flex.FmtErrorf("[ERROR] Setting capacity is not supported for your instance's plan") } return nil } @@ -478,7 +478,7 @@ func validateCloudantInstanceCapacity(d *schema.ResourceData) error { func setCloudantInstanceCapacity(client *cloudantv1.CloudantV1, d *schema.ResourceData) error { capacityThroughputInformation, err := readCloudantInstanceCapacity(client) if err != nil { - return fmt.Errorf("[ERROR] Error retrieving capacity throughput information: %s", err) + return flex.FmtErrorf("[ERROR] Error retrieving capacity throughput information: %s", err) } if capacityThroughputInformation.Current != nil && capacityThroughputInformation.Current.Throughput != nil { @@ -536,7 +536,7 @@ func validateCloudantInstanceCors(d *schema.ResourceData) error { allowCredentials := corsConfig["allow_credentials"].(bool) origins := corsConfig["origins"].([]interface{}) if !allowCredentials || len(origins) > 0 { - return fmt.Errorf("[ERROR] Setting \"cors_config\" conflicts with enable_cors set to false") + return flex.FmtErrorf("[ERROR] Setting \"cors_config\" conflicts with enable_cors set to false") } } return nil @@ -545,7 +545,7 @@ func validateCloudantInstanceCors(d *schema.ResourceData) error { func setCloudantInstanceCors(client *cloudantv1.CloudantV1, d *schema.ResourceData) error { corsInformation, err := readCloudantInstanceCors(client) if err != nil { - return fmt.Errorf("[ERROR] Error retrieving CORS config: %s", err) + return flex.FmtErrorf("[ERROR] Error retrieving CORS config: %s", err) } if corsInformation != nil { d.Set("enable_cors", corsInformation.EnableCors) diff --git a/ibm/service/cloudant/resource_ibm_cloudant_database.go b/ibm/service/cloudant/resource_ibm_cloudant_database.go index f94cc37732..3a1985b58d 100644 --- a/ibm/service/cloudant/resource_ibm_cloudant_database.go +++ b/ibm/service/cloudant/resource_ibm_cloudant_database.go @@ -60,12 +60,14 @@ func resourceIBMCloudantDatabaseCreate(context context.Context, d *schema.Resour instanceCRN := d.Get("instance_crn").(string) cUrl, err := GetCloudantInstanceUrl(instanceCRN, meta) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "create", "get-instance-url") + return tfErr.GetDiag() } cloudantClient, err := GetCloudantClientForUrl(cUrl, meta) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "create", "get-client") + return tfErr.GetDiag() } dbName := d.Get("db").(string) @@ -80,7 +82,8 @@ func resourceIBMCloudantDatabaseCreate(context context.Context, d *schema.Resour _, response, err := cloudantClient.PutDatabaseWithContext(context, putDatabaseOptions) if err != nil { log.Printf("[DEBUG] PutDatabaseWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("PutDatabaseWithContext failed %s\n%s", err, response)) + tfErr := flex.DiscriminatedTerraformErrorf(err, response.String(), "ibm_cloudant_database", "create", "create-database") + return tfErr.GetDiag() } d.SetId(fmt.Sprintf("%s/%s", instanceCRN, dbName)) @@ -91,18 +94,21 @@ func resourceIBMCloudantDatabaseCreate(context context.Context, d *schema.Resour func resourceIBMCloudantDatabaseRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { parts, err := flex.IdParts(d.Id()) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "read", "id-parts") + return tfErr.GetDiag() } instanceCRN, dbName := strings.Join(parts[:len(parts)-1], "/"), parts[len(parts)-1] cUrl, err := GetCloudantInstanceUrl(instanceCRN, meta) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "read", "get-instance-url") + return tfErr.GetDiag() } cloudantClient, err := GetCloudantClientForUrl(cUrl, meta) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "read", "get-client") + return tfErr.GetDiag() } getDatabaseInformationOptions := cloudantClient.NewGetDatabaseInformationOptions(dbName) @@ -114,21 +120,25 @@ func resourceIBMCloudantDatabaseRead(context context.Context, d *schema.Resource return nil } log.Printf("[DEBUG] GetDatabaseInformationWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetDatabaseInformationWithContext failed %s\n%s", err, response)) + tfErr := flex.DiscriminatedTerraformErrorf(err, response.String(), "ibm_cloudant_database", "read", "get-database-information") + return tfErr.GetDiag() } d.Set("instance_crn", instanceCRN) if err = d.Set("db", *databaseInformation.DbName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting db: %s", err)) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "read", "set-db-property") + return tfErr.GetDiag() } if err = d.Set("partitioned", databaseInformation.Props.Partitioned != nil); err != nil { - return diag.FromErr(fmt.Errorf("Error setting partitioned: %s", err)) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "read", "set-partitioned-property") + return tfErr.GetDiag() } if err = d.Set("shards", int(*databaseInformation.Cluster.Q)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting shards: %s", err)) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "read", "set-shards-property") + return tfErr.GetDiag() } return nil @@ -137,18 +147,21 @@ func resourceIBMCloudantDatabaseRead(context context.Context, d *schema.Resource func resourceIBMCloudantDatabaseDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { parts, err := flex.IdParts(d.Id()) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "delete", "id-parts") + return tfErr.GetDiag() } instanceCRN, dbName := strings.Join(parts[:len(parts)-1], "/"), parts[len(parts)-1] cUrl, err := GetCloudantInstanceUrl(instanceCRN, meta) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "delete", "get-instance-url") + return tfErr.GetDiag() } cloudantClient, err := GetCloudantClientForUrl(cUrl, meta) if err != nil { - return diag.FromErr(err) + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_cloudant_database", "delete", "get-client") + return tfErr.GetDiag() } deleteDatabaseOptions := cloudantClient.NewDeleteDatabaseOptions(dbName) @@ -156,7 +169,8 @@ func resourceIBMCloudantDatabaseDelete(context context.Context, d *schema.Resour _, response, err := cloudantClient.DeleteDatabaseWithContext(context, deleteDatabaseOptions) if err != nil { log.Printf("[DEBUG] DeleteDatabaseWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteDatabaseWithContext failed %s\n%s", err, response)) + tfErr := flex.DiscriminatedTerraformErrorf(err, response.String(), "ibm_cloudant_database", "delete", "delete-database") + return tfErr.GetDiag() } d.SetId("") diff --git a/ibm/service/cloudant/resource_ibm_cloudant_test.go b/ibm/service/cloudant/resource_ibm_cloudant_test.go index 815d3f3c55..7ee21e0e20 100644 --- a/ibm/service/cloudant/resource_ibm_cloudant_test.go +++ b/ibm/service/cloudant/resource_ibm_cloudant_test.go @@ -5,22 +5,19 @@ package cloudant_test import ( "fmt" - "reflect" "strings" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + 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" - - "github.com/IBM-Cloud/bluemix-go/models" ) func TestAccIBMCloudant_basic(t *testing.T) { - var conf models.ServiceInstance resourceName := "ibm_cloudant.instance" serviceName := fmt.Sprintf("terraform-test-%s", acctest.RandString(8)) updateName := fmt.Sprintf("terraform-test-%s", acctest.RandString(8)) @@ -33,7 +30,7 @@ func TestAccIBMCloudant_basic(t *testing.T) { { Config: testAccCheckIBMCloudantResourceConfig(serviceName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMCloudantExists(resourceName, conf), + testAccCheckIBMCloudantExists(resourceName), resource.TestCheckResourceAttr(resourceName, "name", serviceName), resource.TestCheckResourceAttr(resourceName, "service", "cloudantnosqldb"), resource.TestCheckResourceAttr(resourceName, "plan", "standard"), @@ -63,7 +60,6 @@ func TestAccIBMCloudant_basic(t *testing.T) { } func TestAccIBMCloudant_import(t *testing.T) { - var conf models.ServiceInstance resourceName := "ibm_cloudant.instance" serviceName := fmt.Sprintf("terraform-test-%s", acctest.RandString(8)) @@ -75,7 +71,7 @@ func TestAccIBMCloudant_import(t *testing.T) { { Config: testAccCheckIBMCloudantResourceConfigLite(serviceName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMCloudantExists(resourceName, conf), + testAccCheckIBMCloudantExists(resourceName), resource.TestCheckResourceAttr(resourceName, "name", serviceName), resource.TestCheckResourceAttr(resourceName, "service", "cloudantnosqldb"), resource.TestCheckResourceAttr(resourceName, "plan", "lite"), @@ -97,7 +93,7 @@ func TestAccIBMCloudant_import(t *testing.T) { } func testAccCheckIBMCloudantDestroy(s *terraform.State) error { - rsContClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).ResourceControllerAPI() + rsContClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).ResourceControllerV2API() if err != nil { return err } @@ -107,17 +103,20 @@ func testAccCheckIBMCloudantDestroy(s *terraform.State) error { } instanceID := rs.Primary.ID + resourceInstanceGet := rc.GetResourceInstanceOptions{ + ID: &instanceID, + } // Try to find the key - instance, err := rsContClient.ResourceServiceInstance().GetInstance(instanceID) + instance, resp, err := rsContClient.GetResourceInstance(&resourceInstanceGet) if err == nil { - if !reflect.DeepEqual(instance, models.ServiceInstance{}) && instance.State == "active" { + if *instance.State == "active" { return fmt.Errorf("Resource Instance still exists: %s", rs.Primary.ID) } } else { if !strings.Contains(err.Error(), "404") { - return fmt.Errorf("[ERROR] Error checking if Resource Instance (%s) has been destroyed: %s", rs.Primary.ID, err) + return fmt.Errorf("[ERROR] Error checking if Resource Instance (%s) has been destroyed: %s with resp code: %s", rs.Primary.ID, err, resp) } } } @@ -125,7 +124,7 @@ func testAccCheckIBMCloudantDestroy(s *terraform.State) error { return nil } -func testAccCheckIBMCloudantExists(resourceName string, obj models.ServiceInstance) resource.TestCheckFunc { +func testAccCheckIBMCloudantExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] @@ -133,19 +132,21 @@ func testAccCheckIBMCloudantExists(resourceName string, obj models.ServiceInstan return fmt.Errorf("Not found: %s", resourceName) } - rsContClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).ResourceControllerAPI() + rsContClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).ResourceControllerV2API() if err != nil { return err } instanceID := rs.Primary.ID + resourceInstanceGet := rc.GetResourceInstanceOptions{ + ID: &instanceID, + } - instance, err := rsContClient.ResourceServiceInstance().GetInstance(instanceID) + _, resp, err := rsContClient.GetResourceInstance(&resourceInstanceGet) if err != nil { - return err + return fmt.Errorf("Get resource instance error: %s with resp code: %s", err, resp) } - obj = instance return nil } } diff --git a/ibm/service/codeengine/data_source_ibm_code_engine_job_test.go b/ibm/service/codeengine/data_source_ibm_code_engine_job_test.go index 9f518b453e..6141829e1e 100644 --- a/ibm/service/codeengine/data_source_ibm_code_engine_job_test.go +++ b/ibm/service/codeengine/data_source_ibm_code_engine_job_test.go @@ -93,8 +93,7 @@ func testAccCheckIbmCodeEngineJobDataSourceConfigBasic(projectID string, jobImag lifecycle { ignore_changes = [ - run_env_variables, - scale_array_spec + run_env_variables ] } } @@ -126,8 +125,7 @@ func testAccCheckIbmCodeEngineJobDataSourceConfig(projectID string, jobImageRefe lifecycle { ignore_changes = [ - run_env_variables, - scale_array_spec + run_env_variables ] } } diff --git a/ibm/service/codeengine/resource_ibm_code_engine_job.go b/ibm/service/codeengine/resource_ibm_code_engine_job.go index 6547d1efaa..51a4f970ae 100644 --- a/ibm/service/codeengine/resource_ibm_code_engine_job.go +++ b/ibm/service/codeengine/resource_ibm_code_engine_job.go @@ -157,6 +157,7 @@ func ResourceIbmCodeEngineJob() *schema.Resource { "scale_array_spec": { Type: schema.TypeString, Optional: true, + Default: "0", ValidateFunc: validate.InvokeValidator("ibm_code_engine_job", "scale_array_spec"), Description: "Define a custom set of array indices as a comma-separated list containing single values and hyphen-separated ranges, such as 5,12-14,23,27. Each instance gets its array index value from the environment variable JOB_INDEX. The number of unique array indices that you specify with this parameter determines the number of job instances to run.", }, diff --git a/ibm/service/codeengine/resource_ibm_code_engine_job_test.go b/ibm/service/codeengine/resource_ibm_code_engine_job_test.go index a0612b9bf9..30b285b2a2 100644 --- a/ibm/service/codeengine/resource_ibm_code_engine_job_test.go +++ b/ibm/service/codeengine/resource_ibm_code_engine_job_test.go @@ -158,8 +158,7 @@ func testAccCheckIbmCodeEngineJobConfigBasic(projectID string, name string, imag lifecycle { ignore_changes = [ - run_env_variables, - scale_array_spec + run_env_variables ] } } @@ -187,8 +186,7 @@ func testAccCheckIbmCodeEngineJobConfig(projectID string, name string, imageRefe lifecycle { ignore_changes = [ - run_env_variables, - scale_array_spec + run_env_variables ] } } diff --git a/ibm/service/codeengine/resource_ibm_code_engine_secret.go b/ibm/service/codeengine/resource_ibm_code_engine_secret.go index 500bf90157..100b40980f 100644 --- a/ibm/service/codeengine/resource_ibm_code_engine_secret.go +++ b/ibm/service/codeengine/resource_ibm_code_engine_secret.go @@ -434,6 +434,7 @@ func resourceIbmCodeEngineSecretUpdate(context context.Context, d *schema.Resour replaceSecretOptions.SetProjectID(parts[0]) replaceSecretOptions.SetName(parts[1]) + replaceSecretOptions.SetFormat(d.Get("format").(string)) hasChange := false @@ -450,7 +451,7 @@ func resourceIbmCodeEngineSecretUpdate(context context.Context, d *schema.Resour return tfErr.GetDiag() } if d.HasChange("data") { - data, err := resourceIbmCodeEngineSecretMapToSecretData(d.Get("data.0").(map[string]interface{})) + data, err := resourceIbmCodeEngineSecretMapToSecretData(d.Get("data").(map[string]interface{})) if err != nil { return diag.FromErr(err) } diff --git a/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone.go b/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone.go index 9357e4bb10..a10edd8ba5 100644 --- a/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone.go +++ b/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone.go @@ -6,8 +6,6 @@ package contextbasedrestrictions import ( "context" "fmt" - "log" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -163,17 +161,19 @@ func dataSourceIBMCbrZoneRead(context context.Context, d *schema.ResourceData, m return diag.FromErr(err) } - getZoneOptions := &contextbasedrestrictionsv1.GetZoneOptions{} - - getZoneOptions.SetZoneID(d.Get("zone_id").(string)) + zoneId := d.Get("zone_id").(string) - zone, response, err := contextBasedRestrictionsClient.GetZoneWithContext(context, getZoneOptions) + var zone *contextbasedrestrictionsv1.Zone + var found bool + zone, _, found, err = getZone(contextBasedRestrictionsClient, context, zoneId) if err != nil { - log.Printf("[DEBUG] GetZoneWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetZoneWithContext failed %s\n%s", err, response)) + return diag.FromErr(err) + } + if !found { + return diag.Errorf("zone_id %s not found", zoneId) } - d.SetId(fmt.Sprintf("%s", *getZoneOptions.ZoneID)) + d.SetId(zoneId) if err = d.Set("crn", zone.CRN); err != nil { return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) @@ -199,29 +199,19 @@ func dataSourceIBMCbrZoneRead(context context.Context, d *schema.ResourceData, m return diag.FromErr(fmt.Errorf("Error setting description: %s", err)) } - addresses := []map[string]interface{}{} - if zone.Addresses != nil { - for _, modelItem := range zone.Addresses { - modelMap, err := dataSourceIBMCbrZoneAddressToMap(modelItem) - if err != nil { - return diag.FromErr(err) - } - addresses = append(addresses, modelMap) - } + var addresses []map[string]interface{} + addresses, err = dataSourceDecodeAddressList(zone.Addresses, cbrZoneAddressIdDefault) + if err != nil { + return diag.FromErr(err) } if err = d.Set("addresses", addresses); err != nil { return diag.FromErr(fmt.Errorf("Error setting addresses %s", err)) } - excluded := []map[string]interface{}{} - if zone.Excluded != nil { - for _, modelItem := range zone.Excluded { - modelMap, err := dataSourceIBMCbrZoneAddressToMap(modelItem) - if err != nil { - return diag.FromErr(err) - } - excluded = append(excluded, modelMap) - } + var excluded []map[string]interface{} + excluded, err = dataSourceDecodeAddressList(zone.Excluded, cbrZoneAddressIdDefault) + if err != nil { + return diag.FromErr(err) } if err = d.Set("excluded", excluded); err != nil { return diag.FromErr(fmt.Errorf("Error setting excluded %s", err)) @@ -250,7 +240,7 @@ func dataSourceIBMCbrZoneRead(context context.Context, d *schema.ResourceData, m return nil } -func dataSourceIBMCbrZoneAddressToMap(model contextbasedrestrictionsv1.AddressIntf) (map[string]interface{}, error) { +func dataSourceIBMCbrZoneAddressToMap(model contextbasedrestrictionsv1.AddressIntf) (modelMap map[string]interface{}, addressId string, err error) { if _, ok := model.(*contextbasedrestrictionsv1.AddressIPAddress); ok { return dataSourceIBMCbrZoneAddressIPAddressToMap(model.(*contextbasedrestrictionsv1.AddressIPAddress)) } else if _, ok := model.(*contextbasedrestrictionsv1.AddressIPAddressRange); ok { @@ -262,25 +252,30 @@ func dataSourceIBMCbrZoneAddressToMap(model contextbasedrestrictionsv1.AddressIn } else if _, ok := model.(*contextbasedrestrictionsv1.AddressServiceRef); ok { return dataSourceIBMCbrZoneAddressServiceRefToMap(model.(*contextbasedrestrictionsv1.AddressServiceRef)) } else if _, ok := model.(*contextbasedrestrictionsv1.Address); ok { - modelMap := make(map[string]interface{}) - model := model.(*contextbasedrestrictionsv1.Address) - if model.Type != nil { - modelMap["type"] = *model.Type + modelMap = make(map[string]interface{}) + address := model.(*contextbasedrestrictionsv1.Address) + if address.Type != nil { + modelMap["type"] = *address.Type } - if model.Value != nil { - modelMap["value"] = *model.Value + if address.Value != nil { + modelMap["value"] = *address.Value } - if model.Ref != nil { - refMap, err := dataSourceIBMCbrZoneServiceRefValueToMap(model.Ref) + if address.Ref != nil { + var refMap map[string]interface{} + refMap, err = dataSourceIBMCbrZoneServiceRefValueToMap(address.Ref) if err != nil { - return modelMap, err + return } modelMap["ref"] = []map[string]interface{}{refMap} } - return modelMap, nil + if address.ID != nil { + addressId = *address.ID + } } else { - return nil, fmt.Errorf("Unrecognized contextbasedrestrictionsv1.AddressIntf subtype encountered") + err = fmt.Errorf("Unrecognized contextbasedrestrictionsv1.AddressIntf subtype encountered") } + + return } func dataSourceIBMCbrZoneServiceRefValueToMap(model *contextbasedrestrictionsv1.ServiceRefValue) (map[string]interface{}, error) { @@ -303,61 +298,93 @@ func dataSourceIBMCbrZoneServiceRefValueToMap(model *contextbasedrestrictionsv1. return modelMap, nil } -func dataSourceIBMCbrZoneAddressIPAddressToMap(model *contextbasedrestrictionsv1.AddressIPAddress) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func dataSourceIBMCbrZoneAddressIPAddressToMap(model *contextbasedrestrictionsv1.AddressIPAddress) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) if model.Type != nil { modelMap["type"] = *model.Type } if model.Value != nil { modelMap["value"] = *model.Value } - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return } -func dataSourceIBMCbrZoneAddressServiceRefToMap(model *contextbasedrestrictionsv1.AddressServiceRef) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func dataSourceIBMCbrZoneAddressServiceRefToMap(model *contextbasedrestrictionsv1.AddressServiceRef) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) if model.Type != nil { modelMap["type"] = *model.Type } if model.Ref != nil { - refMap, err := dataSourceIBMCbrZoneServiceRefValueToMap(model.Ref) + var refMap map[string]interface{} + refMap, err = dataSourceIBMCbrZoneServiceRefValueToMap(model.Ref) if err != nil { - return modelMap, err + return } modelMap["ref"] = []map[string]interface{}{refMap} } - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return } -func dataSourceIBMCbrZoneAddressSubnetToMap(model *contextbasedrestrictionsv1.AddressSubnet) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func dataSourceIBMCbrZoneAddressSubnetToMap(model *contextbasedrestrictionsv1.AddressSubnet) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) if model.Type != nil { modelMap["type"] = *model.Type } if model.Value != nil { modelMap["value"] = *model.Value } - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return } -func dataSourceIBMCbrZoneAddressIPAddressRangeToMap(model *contextbasedrestrictionsv1.AddressIPAddressRange) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func dataSourceIBMCbrZoneAddressIPAddressRangeToMap(model *contextbasedrestrictionsv1.AddressIPAddressRange) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) if model.Type != nil { modelMap["type"] = *model.Type } if model.Value != nil { modelMap["value"] = *model.Value } - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return } -func dataSourceIBMCbrZoneAddressVPCToMap(model *contextbasedrestrictionsv1.AddressVPC) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func dataSourceIBMCbrZoneAddressVPCToMap(model *contextbasedrestrictionsv1.AddressVPC) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) if model.Type != nil { modelMap["type"] = *model.Type } if model.Value != nil { modelMap["value"] = *model.Value } - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return +} + +func dataSourceDecodeAddressList(addresses []contextbasedrestrictionsv1.AddressIntf, wantAddressId string) (result []map[string]interface{}, err error) { + result = make([]map[string]interface{}, 0, len(addresses)) + for _, addr := range addresses { + var m map[string]interface{} + var addressId string + m, addressId, err = dataSourceIBMCbrZoneAddressToMap(addr) + if err != nil { + return + } + if addressId == wantAddressId { + result = append(result, m) + } + } + return } diff --git a/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone_addresses.go b/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone_addresses.go new file mode 100644 index 0000000000..35454cbd0e --- /dev/null +++ b/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone_addresses.go @@ -0,0 +1,131 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package contextbasedrestrictions + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM/platform-services-go-sdk/contextbasedrestrictionsv1" +) + +func DataSourceIBMCbrZoneAddresses() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMCbrZoneAddressesRead, + + Schema: map[string]*schema.Schema{ + "zone_addresses_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The ID of a zone addresses resource.", + }, + "zone_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the zone.", + }, + "addresses": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The list of addresses added to the zone.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type of address.", + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address.", + }, + "ref": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "A service reference value.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The id of the account owning the service.", + }, + "service_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The service type.", + }, + "service_name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The service name.", + }, + "service_instance": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The service instance.", + }, + "location": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The location.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMCbrZoneAddressesRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + contextBasedRestrictionsClient, err := meta.(conns.ClientSession).ContextBasedRestrictionsV1() + if err != nil { + return diag.FromErr(err) + } + + zoneAddressesId := d.Get("zone_addresses_id").(string) + zoneId, addressesId := decomposeZoneAddressesId(zoneAddressesId) + + if zoneId == "" || addressesId == "" { + return diag.Errorf("zone_addresses_id %s not found", zoneAddressesId) + } + + var zone *contextbasedrestrictionsv1.Zone + var found bool + zone, _, found, err = getZone(contextBasedRestrictionsClient, context, zoneId) + if err != nil { + return diag.FromErr(err) + } + if !found { + return diag.Errorf("zone_addresses_id %s not found", zoneAddressesId) + } + + var addresses []map[string]interface{} + addresses, err = dataSourceDecodeAddressList(zone.Addresses, addressesId) + if err != nil { + return diag.FromErr(err) + } + if len(addresses) == 0 { + return diag.Errorf("zone_addresses_id %s not found", zoneAddressesId) + } + + d.SetId(zoneAddressesId) + + if err = d.Set("zone_id", zoneId); err != nil { + return diag.FromErr(fmt.Errorf("Error setting zone_id: %s", err)) + } + + if err = d.Set("addresses", addresses); err != nil { + return diag.FromErr(fmt.Errorf("Error setting addresses %s", err)) + } + + return nil +} diff --git a/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone_addresses_test.go b/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone_addresses_test.go new file mode 100644 index 0000000000..03407ae514 --- /dev/null +++ b/ibm/service/contextbasedrestrictions/data_source_ibm_cbr_zone_addresses_test.go @@ -0,0 +1,113 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package contextbasedrestrictions_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" +) + +func TestAccIBMCbrZoneAddressesDataSourceBasic(t *testing.T) { + accountID, _ := getTestAccountAndZoneID() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckCbr(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMCbrZoneAddressesDataSourceConfigBasic(accountID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "id"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "zone_id"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "zone_addresses_id"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.#"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.value"), + ), + }, + }, + }) +} + +func TestAccIBMCbrZoneAddressesDataSourceMultiple(t *testing.T) { + accountID, _ := getTestAccountAndZoneID() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckCbr(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMCbrZoneAddressesDataSourceConfig(accountID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "id"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "zone_id"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "zone_addresses_id"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.#"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.value"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.1.type"), + resource.TestCheckResourceAttrSet("data.ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.1.value"), + ), + }, + }, + }) +} + +func testAccCheckIBMCbrZoneAddressesDataSourceConfigBasic(accountID string) string { + return fmt.Sprintf(` + resource "ibm_cbr_zone" "cbr_zone" { + name = "Test Zone Addresses Data Source Config Basic" + account_id = "%s" + addresses { + type = "ipRange" + value = "169.23.22.0-169.23.22.255" + } + } + + resource "ibm_cbr_zone_addresses" "cbr_zone_addresses" { + zone_id = ibm_cbr_zone.cbr_zone.id + addresses { + type = "subnet" + value = "10.0.0.0/24" + } + } + + data "ibm_cbr_zone_addresses" "cbr_zone_addresses" { + zone_addresses_id = ibm_cbr_zone_addresses.cbr_zone_addresses.id + } + `, accountID) +} + +func testAccCheckIBMCbrZoneAddressesDataSourceConfig(accountID string) string { + return fmt.Sprintf(` + resource "ibm_cbr_zone" "cbr_zone" { + name = "Test Zone Addresses Data Source Config" + account_id = "%s" + addresses { + type = "ipRange" + value = "169.23.22.0-169.23.22.255" + } + } + + resource "ibm_cbr_zone_addresses" "cbr_zone_addresses" { + zone_id = ibm_cbr_zone.cbr_zone.id + addresses { + type = "subnet" + value = "10.0.0.0/24" + } + addresses { + type = "ipAddress" + value = "169.24.22.10" + } + } + + data "ibm_cbr_zone_addresses" "cbr_zone_addresses" { + zone_addresses_id = ibm_cbr_zone_addresses.cbr_zone_addresses.id + } + `, accountID) +} diff --git a/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone.go b/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone.go index ce57ca1bc7..b38637b202 100644 --- a/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone.go +++ b/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "log" + "sync" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -21,9 +22,10 @@ import ( ) const ( - cbrZoneReadPending = "pending" - cbrZoneReadComplete = "finished" - cbrZoneReadError = "error" + cbrZoneReadPending = "pending" + cbrZoneReadComplete = "finished" + cbrZoneReadError = "error" + cbrZoneAddressIdDefault = "" ) func ResourceIBMCbrZone() *schema.Resource { @@ -246,49 +248,54 @@ func ResourceIBMCbrZoneValidator() *validate.ResourceValidator { return &resourceValidator } -// waitForCbrZoneRead will leverage use retry.StateChangeConf due to the service's eventual consistency -func waitForCbrZoneRead(cbrClient *contextbasedrestrictionsv1.ContextBasedRestrictionsV1, context context.Context, id string) (interface{}, error) { +func getZone(cbrClient *contextbasedrestrictionsv1.ContextBasedRestrictionsV1, context context.Context, id string) (result *contextbasedrestrictionsv1.Zone, version string, found bool, err error) { + getZoneOptions := cbrClient.NewGetZoneOptions(id) + + var response *core.DetailedResponse + result, response, err = cbrClient.GetZoneWithContext(context, getZoneOptions) + found = err == nil + if found { + version = response.Headers.Get("Etag") + return + } + if response != nil && response.StatusCode == 404 { + err = nil + return + } + log.Printf("[DEBUG] GetZoneWithContext failed %s\n%s", err, response) + err = fmt.Errorf("GetZoneWithContext failed %s\n%s", err, response) + return +} + +func readNewCbrZone(cbrClient *contextbasedrestrictionsv1.ContextBasedRestrictionsV1, context context.Context, id string) (err error) { + var found bool + _, _, found, err = getZone(cbrClient, context, id) + if found || err != nil { + return + } + + // Manual change. leverage retry for the read due to eventual consistency of the service. + log.Printf("[INFO] Read cbr zone response status code: 404, provider will try again. %s", err) stateConf := &retry.StateChangeConf{ Pending: []string{cbrRuleReadPending}, Target: []string{cbrRuleReadError, cbrRuleReadComplete, ""}, Refresh: func() (interface{}, string, error) { log.Printf("[INFO] Retrying cbr rule (%s) read", id) - getZoneOptions := &contextbasedrestrictionsv1.GetZoneOptions{} - getZoneOptions.SetZoneID(id) - _, response, err := cbrClient.GetZoneWithContext(context, getZoneOptions) - if err != nil && response.StatusCode == 404 { - return response, cbrZoneReadPending, nil - } else if err != nil { - return response, cbrZoneReadError, err - } else { - return response, cbrZoneReadComplete, nil + _, _, found, err := getZone(cbrClient, context, id) + if err != nil { + return nil, cbrZoneReadError, err + } + if !found { + return nil, cbrZoneReadPending, nil } + return nil, cbrZoneReadComplete, nil }, Timeout: 120 * time.Second, Delay: 20 * time.Second, MinTimeout: 10 * time.Second, } - return stateConf.WaitForStateContext(context) -} - -func readNewCbrZone(cbrClient *contextbasedrestrictionsv1.ContextBasedRestrictionsV1, context context.Context, d *schema.ResourceData) diag.Diagnostics { - getZoneOptions := &contextbasedrestrictionsv1.GetZoneOptions{} - getZoneOptions.SetZoneID(d.Id()) - - _, response, err := cbrClient.GetZoneWithContext(context, getZoneOptions) - - if response != nil && response.StatusCode == 404 { - // Manual change. leverage retry for the read due to eventual consistency of the service. - log.Printf("[INFO] Read cbr zone response status code: 404, provider will try again. %s", err) - _, err := waitForCbrZoneRead(cbrClient, context, d.Id()) - if err != nil { - log.Printf("[DEBUG] GetZoneWithContext failed %s\n%s", err, response) - d.SetId("") - return diag.FromErr(fmt.Errorf("GetZoneWithContext failed %s\n%s", err, response)) - } - } - - return nil + _, err = stateConf.WaitForStateContext(context) + return } func resourceIBMCbrZoneCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { @@ -297,7 +304,7 @@ func resourceIBMCbrZoneCreate(context context.Context, d *schema.ResourceData, m return diag.FromErr(err) } - createZoneOptions := &contextbasedrestrictionsv1.CreateZoneOptions{} + createZoneOptions := contextBasedRestrictionsClient.NewCreateZoneOptions() if _, ok := d.GetOk("name"); ok { createZoneOptions.SetName(d.Get("name").(string)) @@ -310,25 +317,17 @@ func resourceIBMCbrZoneCreate(context context.Context, d *schema.ResourceData, m } addresses := []contextbasedrestrictionsv1.AddressIntf{} if _, ok := d.GetOk("addresses"); ok { - for _, e := range d.Get("addresses").([]interface{}) { - value := e.(map[string]interface{}) - addressesItem, err := resourceIBMCbrZoneMapToAddress(value) - if err != nil { - return diag.FromErr(err) - } - addresses = append(addresses, addressesItem) + addresses, err = resourceEncodeAddressList(d.Get("addresses").([]interface{}), cbrZoneAddressIdDefault) + if err != nil { + return diag.FromErr(err) } } createZoneOptions.SetAddresses(addresses) if _, ok := d.GetOk("excluded"); ok { var excluded []contextbasedrestrictionsv1.AddressIntf - for _, e := range d.Get("excluded").([]interface{}) { - value := e.(map[string]interface{}) - excludedItem, err := resourceIBMCbrZoneMapToAddress(value) - if err != nil { - return diag.FromErr(err) - } - excluded = append(excluded, excludedItem) + excluded, err = resourceEncodeAddressList(d.Get("excluded").([]interface{}), cbrZoneAddressIdDefault) + if err != nil { + return diag.FromErr(err) } createZoneOptions.SetExcluded(excluded) } @@ -345,11 +344,13 @@ func resourceIBMCbrZoneCreate(context context.Context, d *schema.ResourceData, m return diag.FromErr(fmt.Errorf("CreateZoneWithContext failed %s\n%s", err, response)) } - d.SetId(*zone.ID) - // handle Eventual consistency case - readNewCbrZone(contextBasedRestrictionsClient, context, d) + err = readNewCbrZone(contextBasedRestrictionsClient, context, *zone.ID) + if err != nil { + return diag.FromErr(err) + } + d.SetId(*zone.ID) return resourceIBMCbrZoneRead(context, d, meta) } @@ -359,26 +360,18 @@ func resourceIBMCbrZoneRead(context context.Context, d *schema.ResourceData, met return diag.FromErr(err) } - getZoneOptions := &contextbasedrestrictionsv1.GetZoneOptions{} - - getZoneOptions.SetZoneID(d.Id()) - - zone, response, err := contextBasedRestrictionsClient.GetZoneWithContext(context, getZoneOptions) + var zone *contextbasedrestrictionsv1.Zone + var version string + var found bool + zone, version, found, err = getZone(contextBasedRestrictionsClient, context, d.Id()) if err != nil { - if response != nil && response.StatusCode == 404 { - d.SetId("") - return nil - } - log.Printf("[DEBUG] GetZoneWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetZoneWithContext failed %s\n%s", err, response)) - } - - if err = d.Set("x_correlation_id", getZoneOptions.XCorrelationID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting x_correlation_id: %s", err)) + return diag.FromErr(err) } - if err = d.Set("transaction_id", getZoneOptions.TransactionID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting transaction_id: %s", err)) + if !found { + d.SetId("") + return nil } + if err = d.Set("name", zone.Name); err != nil { return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) } @@ -388,32 +381,25 @@ func resourceIBMCbrZoneRead(context context.Context, d *schema.ResourceData, met if err = d.Set("description", zone.Description); err != nil { return diag.FromErr(fmt.Errorf("Error setting description: %s", err)) } - addresses := []map[string]interface{}{} - if zone.Addresses != nil { - for _, addressesItem := range zone.Addresses { - addressesItemMap, err := resourceIBMCbrZoneAddressToMap(addressesItem) - if err != nil { - return diag.FromErr(err) - } - addresses = append(addresses, addressesItemMap) - } + + var addresses []map[string]interface{} + addresses, err = resourceDecodeAddressList(zone.Addresses, cbrZoneAddressIdDefault) + if err != nil { + return diag.FromErr(err) } if err = d.Set("addresses", addresses); err != nil { return diag.FromErr(fmt.Errorf("Error setting addresses: %s", err)) } - excluded := []map[string]interface{}{} - if zone.Excluded != nil { - for _, excludedItem := range zone.Excluded { - excludedItemMap, err := resourceIBMCbrZoneAddressToMap(excludedItem) - if err != nil { - return diag.FromErr(err) - } - excluded = append(excluded, excludedItemMap) - } + + var excluded []map[string]interface{} + excluded, err = resourceDecodeAddressList(zone.Excluded, cbrZoneAddressIdDefault) + if err != nil { + return diag.FromErr(err) } if err = d.Set("excluded", excluded); err != nil { return diag.FromErr(fmt.Errorf("Error setting excluded: %s", err)) } + if err = d.Set("crn", zone.CRN); err != nil { return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) } @@ -438,7 +424,7 @@ func resourceIBMCbrZoneRead(context context.Context, d *schema.ResourceData, met if err = d.Set("last_modified_by_id", zone.LastModifiedByID); err != nil { return diag.FromErr(fmt.Errorf("Error setting last_modified_by_id: %s", err)) } - if err = d.Set("version", response.Headers.Get("Etag")); err != nil { + if err = d.Set("version", version); err != nil { return diag.FromErr(fmt.Errorf("Error setting version: %s", err)) } @@ -451,9 +437,27 @@ func resourceIBMCbrZoneUpdate(context context.Context, d *schema.ResourceData, m return diag.FromErr(err) } - replaceZoneOptions := &contextbasedrestrictionsv1.ReplaceZoneOptions{} + zoneId := d.Id() + + // synchronize with zone address update operations + mutex := zoneMutexKV.get(zoneId) + mutex.Lock() + defer mutex.Unlock() + + var currentZone *contextbasedrestrictionsv1.Zone + var version string + var found bool + currentZone, version, found, err = getZone(contextBasedRestrictionsClient, context, zoneId) + if err != nil { + return diag.FromErr(err) + } + if !found { + d.SetId("") + return nil + } + + replaceZoneOptions := contextBasedRestrictionsClient.NewReplaceZoneOptions(zoneId, version) - replaceZoneOptions.SetZoneID(d.Id()) if _, ok := d.GetOk("name"); ok { replaceZoneOptions.SetName(d.Get("name").(string)) } @@ -465,25 +469,23 @@ func resourceIBMCbrZoneUpdate(context context.Context, d *schema.ResourceData, m } addresses := []contextbasedrestrictionsv1.AddressIntf{} if _, ok := d.GetOk("addresses"); ok { - for _, e := range d.Get("addresses").([]interface{}) { - value := e.(map[string]interface{}) - addressesItem, err := resourceIBMCbrZoneMapToAddress(value) - if err != nil { - return diag.FromErr(err) - } - addresses = append(addresses, addressesItem) + addresses, err = resourceEncodeAddressList(d.Get("addresses").([]interface{}), cbrZoneAddressIdDefault) + if err != nil { + return diag.FromErr(err) } } + preservedAddresses := FilterAddressList(currentZone.Addresses, func(id string) bool { + return id != cbrZoneAddressIdDefault + }) + if len(preservedAddresses) > 0 { + addresses = append(addresses, preservedAddresses...) + } replaceZoneOptions.SetAddresses(addresses) if _, ok := d.GetOk("excluded"); ok { var excluded []contextbasedrestrictionsv1.AddressIntf - for _, e := range d.Get("excluded").([]interface{}) { - value := e.(map[string]interface{}) - excludedItem, err := resourceIBMCbrZoneMapToAddress(value) - if err != nil { - return diag.FromErr(err) - } - excluded = append(excluded, excludedItem) + excluded, err = resourceEncodeAddressList(d.Get("excluded").([]interface{}), cbrZoneAddressIdDefault) + if err != nil { + return diag.FromErr(err) } replaceZoneOptions.SetExcluded(excluded) } @@ -493,7 +495,6 @@ func resourceIBMCbrZoneUpdate(context context.Context, d *schema.ResourceData, m if _, ok := d.GetOk("transaction_id"); ok { replaceZoneOptions.SetTransactionID(d.Get("transaction_id").(string)) } - replaceZoneOptions.SetIfMatch(d.Get("version").(string)) _, response, err := contextBasedRestrictionsClient.ReplaceZoneWithContext(context, replaceZoneOptions) if err != nil { @@ -510,9 +511,7 @@ func resourceIBMCbrZoneDelete(context context.Context, d *schema.ResourceData, m return diag.FromErr(err) } - deleteZoneOptions := &contextbasedrestrictionsv1.DeleteZoneOptions{} - - deleteZoneOptions.SetZoneID(d.Id()) + deleteZoneOptions := contextBasedRestrictionsClient.NewDeleteZoneOptions(d.Id()) response, err := contextBasedRestrictionsClient.DeleteZoneWithContext(context, deleteZoneOptions) if err != nil { @@ -525,19 +524,19 @@ func resourceIBMCbrZoneDelete(context context.Context, d *schema.ResourceData, m return nil } -func resourceIBMCbrZoneMapToAddress(modelMap map[string]interface{}) (contextbasedrestrictionsv1.AddressIntf, error) { +func resourceIBMCbrZoneMapToAddress(modelMap map[string]interface{}, addressId string) (contextbasedrestrictionsv1.AddressIntf, error) { discValue, ok := modelMap["type"] if ok { if discValue == "ipAddress" { - return resourceIBMCbrZoneMapToAddressIPAddress(modelMap) + return resourceIBMCbrZoneMapToAddressIPAddress(modelMap, addressId) } else if discValue == "ipRange" { - return resourceIBMCbrZoneMapToAddressIPAddressRange(modelMap) + return resourceIBMCbrZoneMapToAddressIPAddressRange(modelMap, addressId) } else if discValue == "subnet" { - return resourceIBMCbrZoneMapToAddressSubnet(modelMap) + return resourceIBMCbrZoneMapToAddressSubnet(modelMap, addressId) } else if discValue == "vpc" { - return resourceIBMCbrZoneMapToAddressVPC(modelMap) + return resourceIBMCbrZoneMapToAddressVPC(modelMap, addressId) } else if discValue == "serviceRef" { - return resourceIBMCbrZoneMapToAddressServiceRef(modelMap) + return resourceIBMCbrZoneMapToAddressServiceRef(modelMap, addressId) } else { return nil, fmt.Errorf("unexpected value for discriminator property 'type' found in map: '%s'", discValue) } @@ -564,14 +563,17 @@ func resourceIBMCbrZoneMapToServiceRefValue(modelMap map[string]interface{}) (*c return model, nil } -func resourceIBMCbrZoneMapToAddressIPAddress(modelMap map[string]interface{}) (*contextbasedrestrictionsv1.AddressIPAddress, error) { +func resourceIBMCbrZoneMapToAddressIPAddress(modelMap map[string]interface{}, addressId string) (*contextbasedrestrictionsv1.AddressIPAddress, error) { model := &contextbasedrestrictionsv1.AddressIPAddress{} model.Type = core.StringPtr(modelMap["type"].(string)) model.Value = core.StringPtr(modelMap["value"].(string)) + if addressId != "" { + model.ID = core.StringPtr(addressId) + } return model, nil } -func resourceIBMCbrZoneMapToAddressServiceRef(modelMap map[string]interface{}) (*contextbasedrestrictionsv1.AddressServiceRef, error) { +func resourceIBMCbrZoneMapToAddressServiceRef(modelMap map[string]interface{}, addressId string) (*contextbasedrestrictionsv1.AddressServiceRef, error) { model := &contextbasedrestrictionsv1.AddressServiceRef{} model.Type = core.StringPtr(modelMap["type"].(string)) RefModel, err := resourceIBMCbrZoneMapToServiceRefValue(modelMap["ref"].([]interface{})[0].(map[string]interface{})) @@ -579,31 +581,43 @@ func resourceIBMCbrZoneMapToAddressServiceRef(modelMap map[string]interface{}) ( return model, err } model.Ref = RefModel + if addressId != "" { + model.ID = core.StringPtr(addressId) + } return model, nil } -func resourceIBMCbrZoneMapToAddressSubnet(modelMap map[string]interface{}) (*contextbasedrestrictionsv1.AddressSubnet, error) { +func resourceIBMCbrZoneMapToAddressSubnet(modelMap map[string]interface{}, addressId string) (*contextbasedrestrictionsv1.AddressSubnet, error) { model := &contextbasedrestrictionsv1.AddressSubnet{} model.Type = core.StringPtr(modelMap["type"].(string)) model.Value = core.StringPtr(modelMap["value"].(string)) + if addressId != "" { + model.ID = core.StringPtr(addressId) + } return model, nil } -func resourceIBMCbrZoneMapToAddressIPAddressRange(modelMap map[string]interface{}) (*contextbasedrestrictionsv1.AddressIPAddressRange, error) { +func resourceIBMCbrZoneMapToAddressIPAddressRange(modelMap map[string]interface{}, addressId string) (*contextbasedrestrictionsv1.AddressIPAddressRange, error) { model := &contextbasedrestrictionsv1.AddressIPAddressRange{} model.Type = core.StringPtr(modelMap["type"].(string)) model.Value = core.StringPtr(modelMap["value"].(string)) + if addressId != "" { + model.ID = core.StringPtr(addressId) + } return model, nil } -func resourceIBMCbrZoneMapToAddressVPC(modelMap map[string]interface{}) (*contextbasedrestrictionsv1.AddressVPC, error) { +func resourceIBMCbrZoneMapToAddressVPC(modelMap map[string]interface{}, addressId string) (*contextbasedrestrictionsv1.AddressVPC, error) { model := &contextbasedrestrictionsv1.AddressVPC{} model.Type = core.StringPtr(modelMap["type"].(string)) model.Value = core.StringPtr(modelMap["value"].(string)) + if addressId != "" { + model.ID = core.StringPtr(addressId) + } return model, nil } -func resourceIBMCbrZoneAddressToMap(model contextbasedrestrictionsv1.AddressIntf) (map[string]interface{}, error) { +func resourceIBMCbrZoneAddressToMap(model contextbasedrestrictionsv1.AddressIntf) (modelMap map[string]interface{}, addressId string, err error) { if _, ok := model.(*contextbasedrestrictionsv1.AddressIPAddress); ok { return resourceIBMCbrZoneAddressIPAddressToMap(model.(*contextbasedrestrictionsv1.AddressIPAddress)) } else if _, ok := model.(*contextbasedrestrictionsv1.AddressIPAddressRange); ok { @@ -615,25 +629,30 @@ func resourceIBMCbrZoneAddressToMap(model contextbasedrestrictionsv1.AddressIntf } else if _, ok := model.(*contextbasedrestrictionsv1.AddressServiceRef); ok { return resourceIBMCbrZoneAddressServiceRefToMap(model.(*contextbasedrestrictionsv1.AddressServiceRef)) } else if _, ok := model.(*contextbasedrestrictionsv1.Address); ok { - modelMap := make(map[string]interface{}) - model := model.(*contextbasedrestrictionsv1.Address) - if model.Type != nil { - modelMap["type"] = model.Type + modelMap = make(map[string]interface{}) + address := model.(*contextbasedrestrictionsv1.Address) + if address.Type != nil { + modelMap["type"] = address.Type } - if model.Value != nil { - modelMap["value"] = model.Value + if address.Value != nil { + modelMap["value"] = address.Value } - if model.Ref != nil { - refMap, err := resourceIBMCbrZoneServiceRefValueToMap(model.Ref) + if address.Ref != nil { + var refMap map[string]interface{} + refMap, err = resourceIBMCbrZoneServiceRefValueToMap(address.Ref) if err != nil { - return modelMap, err + return } modelMap["ref"] = []map[string]interface{}{refMap} } - return modelMap, nil + if address.ID != nil { + addressId = *address.ID + } } else { - return nil, fmt.Errorf("Unrecognized contextbasedrestrictionsv1.AddressIntf subtype encountered") + err = fmt.Errorf("Unrecognized contextbasedrestrictionsv1.AddressIntf subtype encountered") } + + return } func resourceIBMCbrZoneServiceRefValueToMap(model *contextbasedrestrictionsv1.ServiceRefValue) (map[string]interface{}, error) { @@ -654,41 +673,122 @@ func resourceIBMCbrZoneServiceRefValueToMap(model *contextbasedrestrictionsv1.Se return modelMap, nil } -func resourceIBMCbrZoneAddressIPAddressToMap(model *contextbasedrestrictionsv1.AddressIPAddress) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func resourceIBMCbrZoneAddressIPAddressToMap(model *contextbasedrestrictionsv1.AddressIPAddress) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) modelMap["type"] = model.Type modelMap["value"] = model.Value - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return } -func resourceIBMCbrZoneAddressServiceRefToMap(model *contextbasedrestrictionsv1.AddressServiceRef) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func resourceIBMCbrZoneAddressServiceRefToMap(model *contextbasedrestrictionsv1.AddressServiceRef) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) modelMap["type"] = model.Type - refMap, err := resourceIBMCbrZoneServiceRefValueToMap(model.Ref) + var refMap map[string]interface{} + refMap, err = resourceIBMCbrZoneServiceRefValueToMap(model.Ref) if err != nil { - return modelMap, err + return } modelMap["ref"] = []map[string]interface{}{refMap} - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return } -func resourceIBMCbrZoneAddressSubnetToMap(model *contextbasedrestrictionsv1.AddressSubnet) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func resourceIBMCbrZoneAddressSubnetToMap(model *contextbasedrestrictionsv1.AddressSubnet) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) modelMap["type"] = model.Type modelMap["value"] = model.Value - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return } -func resourceIBMCbrZoneAddressIPAddressRangeToMap(model *contextbasedrestrictionsv1.AddressIPAddressRange) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func resourceIBMCbrZoneAddressIPAddressRangeToMap(model *contextbasedrestrictionsv1.AddressIPAddressRange) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) modelMap["type"] = model.Type modelMap["value"] = model.Value - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return } -func resourceIBMCbrZoneAddressVPCToMap(model *contextbasedrestrictionsv1.AddressVPC) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) +func resourceIBMCbrZoneAddressVPCToMap(model *contextbasedrestrictionsv1.AddressVPC) (modelMap map[string]interface{}, addressId string, err error) { + modelMap = make(map[string]interface{}) modelMap["type"] = model.Type modelMap["value"] = model.Value - return modelMap, nil + if model.ID != nil { + addressId = *model.ID + } + return +} + +func resourceDecodeAddressList(addresses []contextbasedrestrictionsv1.AddressIntf, wantAddressId string) (result []map[string]interface{}, err error) { + result = make([]map[string]interface{}, 0, len(addresses)) + for _, addr := range addresses { + var m map[string]interface{} + var addressId string + m, addressId, err = resourceIBMCbrZoneAddressToMap(addr) + if err != nil { + return + } + if addressId == wantAddressId { + result = append(result, m) + } + } + return +} + +func resourceEncodeAddressList(addresses []interface{}, addressId string) (result []contextbasedrestrictionsv1.AddressIntf, err error) { + result = make([]contextbasedrestrictionsv1.AddressIntf, 0, len(addresses)) + for _, item := range addresses { + var addr contextbasedrestrictionsv1.AddressIntf + addr, err = resourceIBMCbrZoneMapToAddress(item.(map[string]interface{}), addressId) + if err != nil { + return + } + result = append(result, addr) + } + return +} + +func FilterAddressList(addresses []contextbasedrestrictionsv1.AddressIntf, keep func(id string) bool) (result []contextbasedrestrictionsv1.AddressIntf) { + result = make([]contextbasedrestrictionsv1.AddressIntf, 0, len(addresses)) + for _, addr := range addresses { + _, addressId, err := resourceIBMCbrZoneAddressToMap(addr) + if err == nil && keep(addressId) { + result = append(result, addr) + } + } + return +} + +// Synchronization for zone operations +var zoneMutexKV = newMutexKV() + +type mutexKV struct { + lock sync.Mutex + store map[string]*sync.Mutex +} + +func (m *mutexKV) get(key string) *sync.Mutex { + m.lock.Lock() + defer m.lock.Unlock() + mutex, ok := m.store[key] + if !ok { + mutex = &sync.Mutex{} + m.store[key] = mutex + } + return mutex +} + +func newMutexKV() *mutexKV { + return &mutexKV{ + store: make(map[string]*sync.Mutex), + } } diff --git a/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone_addresses.go b/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone_addresses.go new file mode 100644 index 0000000000..add8422a12 --- /dev/null +++ b/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone_addresses.go @@ -0,0 +1,298 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package contextbasedrestrictions + +import ( + "context" + "fmt" + "log" + "strings" + "time" + + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/platform-services-go-sdk/contextbasedrestrictionsv1" +) + +func ResourceIBMCbrZoneAddresses() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMCbrZoneAddressesCreate, + ReadContext: resourceIBMCbrZoneAddressesRead, + UpdateContext: resourceIBMCbrZoneAddressesUpdate, + DeleteContext: resourceIBMCbrZoneAddressesDelete, + Importer: &schema.ResourceImporter{}, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(2 * time.Minute), + Update: schema.DefaultTimeout(2 * time.Minute), + Delete: schema.DefaultTimeout(2 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "zone_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_cbr_zone_addresses", "zone_id"), + Description: "The id of the zone containing the addresses.", + }, + "addresses": &schema.Schema{ + Type: schema.TypeList, + Required: true, + Description: "The list of addresses added to the zone.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The type of address.", + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The IP address.", + }, + "ref": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "A service reference value.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The id of the account owning the service.", + }, + "service_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The service type.", + }, + "service_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The service name.", + }, + "service_instance": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The service instance.", + }, + "location": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The location.", + }, + }, + }, + }, + }, + }, + }, + "x_correlation_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_cbr_zone", "x_correlation_id"), + Description: "The supplied or generated value of this header is logged for a request and repeated in a response header for the corresponding response. The same value is used for downstream requests and retries of those requests. If a value of this headers is not supplied in a request, the service generates a random (version 4) UUID.", + }, + "transaction_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_cbr_zone", "transaction_id"), + Description: "The `Transaction-Id` header behaves as the `X-Correlation-Id` header. It is supported for backward compatibility with other IBM platform services that support the `Transaction-Id` header only. If both `X-Correlation-Id` and `Transaction-Id` are provided, `X-Correlation-Id` has the precedence over `Transaction-Id`.", + }, + }, + } +} + +func ResourceIBMCbrZoneAddressesValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "zone_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9\-]+$`, + MinValueLength: 1, + MaxValueLength: 128, + }, + validate.ValidateSchema{ + Identifier: "x_correlation_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-zA-Z0-9 ,\-_]+$`, + MinValueLength: 1, + MaxValueLength: 1024, + }, + validate.ValidateSchema{ + Identifier: "transaction_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-zA-Z0-9 ,\-_]+$`, + MinValueLength: 1, + MaxValueLength: 1024, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_cbr_zone_addresses", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMCbrZoneAddressesCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + zoneId := d.Get("zone_id").(string) + newUuid, _ := uuid.GenerateUUID() + addressesId := fmt.Sprintf("TF-%s", newUuid) + err := resourceReplaceZoneAddresses(context, d, meta, zoneId, addressesId, false) + if err != nil { + return diag.FromErr(err) + } + d.SetId(composeZoneAddressesId(zoneId, addressesId)) + return nil + +} + +func resourceIBMCbrZoneAddressesRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + contextBasedRestrictionsClient, err := meta.(conns.ClientSession).ContextBasedRestrictionsV1() + if err != nil { + return diag.FromErr(err) + } + + zoneId, addressesId := decomposeZoneAddressesId(d.Id()) + + var zone *contextbasedrestrictionsv1.Zone + var found bool + zone, _, found, err = getZone(contextBasedRestrictionsClient, context, zoneId) + if err != nil { + return diag.FromErr(err) + } + if !found { + d.SetId("") + return nil + } + + if err = d.Set("zone_id", zoneId); err != nil { + return diag.FromErr(fmt.Errorf("Error setting zone_id: %s", err)) + } + + var addresses []map[string]interface{} + addresses, err = resourceDecodeAddressList(zone.Addresses, addressesId) + if err != nil { + return diag.FromErr(err) + } + if len(addresses) == 0 { + d.SetId("") + return nil + } + + if err = d.Set("addresses", addresses); err != nil { + return diag.FromErr(fmt.Errorf("Error setting addresses: %s", err)) + } + + return nil +} + +func resourceIBMCbrZoneAddressesUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + zoneId, addressesId := decomposeZoneAddressesId(d.Id()) + err := resourceReplaceZoneAddresses(context, d, meta, zoneId, addressesId, false) + if err != nil { + return diag.FromErr(err) + } + return nil +} + +func resourceIBMCbrZoneAddressesDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + zoneId, addressesId := decomposeZoneAddressesId(d.Id()) + err := d.Set("addresses", nil) + if err != nil { + return diag.FromErr(fmt.Errorf("Error setting addresses: %s", err)) + } + err = resourceReplaceZoneAddresses(context, d, meta, zoneId, addressesId, true) + if err != nil { + return diag.FromErr(err) + } + + d.SetId("") + return nil +} + +func resourceReplaceZoneAddresses(context context.Context, d *schema.ResourceData, meta interface{}, zoneId string, addressesId string, delete bool) error { + contextBasedRestrictionsClient, err := meta.(conns.ClientSession).ContextBasedRestrictionsV1() + if err != nil { + return err + } + + // synchronize with zone address update operations + mutex := zoneMutexKV.get(zoneId) + mutex.Lock() + defer mutex.Unlock() + + var currentZone *contextbasedrestrictionsv1.Zone + var version string + var found bool + currentZone, version, found, err = getZone(contextBasedRestrictionsClient, context, zoneId) + if err != nil { + return err + } + if !found { + d.SetId("") + if !delete { + return fmt.Errorf("zone_id %s not found", zoneId) + } + return nil + } + + replaceZoneOptions := contextBasedRestrictionsClient.NewReplaceZoneOptions(zoneId, version) + replaceZoneOptions.SetName(*currentZone.Name) + replaceZoneOptions.SetAccountID(*currentZone.AccountID) + if currentZone.Description != nil { + replaceZoneOptions.SetDescription(*currentZone.Description) + } + if currentZone.Excluded != nil { + replaceZoneOptions.SetExcluded(currentZone.Excluded) + + } + + addresses := []contextbasedrestrictionsv1.AddressIntf{} + if _, ok := d.GetOk("addresses"); ok { + addresses, err = resourceEncodeAddressList(d.Get("addresses").([]interface{}), addressesId) + if err != nil { + return err + } + } + preservedAddresses := FilterAddressList(currentZone.Addresses, func(id string) bool { + return id != addressesId + }) + if len(preservedAddresses) > 0 { + addresses = append(preservedAddresses, addresses...) + } + replaceZoneOptions.SetAddresses(addresses) + + _, response, err := contextBasedRestrictionsClient.ReplaceZoneWithContext(context, replaceZoneOptions) + if err != nil { + log.Printf("[DEBUG] ReplaceZoneWithContext failed %s\n%s", err, response) + return fmt.Errorf("ReplaceZoneWithContext failed %s\n%s", err, response) + } + + return nil +} + +func composeZoneAddressesId(zoneId, addressesId string) (id string) { + id = fmt.Sprintf("%s/%s", zoneId, addressesId) + return +} + +func decomposeZoneAddressesId(id string) (zoneId, addressesId string) { + if index := strings.Index(id, "/"); index >= 0 { + zoneId = id[:index] + addressesId = id[index+1:] + } + return +} diff --git a/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone_addresses_test.go b/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone_addresses_test.go new file mode 100644 index 0000000000..7559a4ba63 --- /dev/null +++ b/ibm/service/contextbasedrestrictions/resource_ibm_cbr_zone_addresses_test.go @@ -0,0 +1,276 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package contextbasedrestrictions_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/contextbasedrestrictions" +) + +func TestAccIBMCbrZoneAddressesBasic(t *testing.T) { + accountID, _ := getTestAccountAndZoneID() + + baseAddresses := []map[string]string{ + { + "type": "ipRange", + "value": "169.23.22.0-169.23.22.255", + }, + } + + additionalAddresses := []map[string]string{ + { + "type": "subnet", + "value": "10.0.0.0/24", + }, + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckCbr(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMCbrZoneDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMCbrZoneAddressesConfig(accountID, baseAddresses, nil), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMCbrBaseZoneExists("ibm_cbr_zone.cbr_zone", 1), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.#", "1"), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.type", baseAddresses[0]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.value", baseAddresses[0]["value"]), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMCbrZoneAddressesConfig(accountID, baseAddresses, additionalAddresses), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMCbrBaseZoneExists("ibm_cbr_zone.cbr_zone", 1), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.#", "1"), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.type", baseAddresses[0]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.value", baseAddresses[0]["value"]), + testAccCheckIBMCbrZoneAddressesExists("ibm_cbr_zone_addresses.cbr_zone_addresses", 1), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.#", "1"), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.type", additionalAddresses[0]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.value", additionalAddresses[0]["value"]), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMCbrZoneAddressesConfig(accountID, baseAddresses, nil), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMCbrBaseZoneExists("ibm_cbr_zone.cbr_zone", 1), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.#", "1"), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.type", baseAddresses[0]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.value", baseAddresses[0]["value"]), + testAccCheckIBMCbrZoneAddressesDestroyed("ibm_cbr_zone_addresses.cbr_zone_addresses"), + ), + }, + }, + }) +} + +func TestAccIBMCbrZoneAddressesUpdate(t *testing.T) { + accountID, _ := getTestAccountAndZoneID() + + baseAddresses := []map[string]string{ + { + "type": "ipRange", + "value": "169.23.22.0-169.23.22.255", + }, + } + + additionalAddresses := []map[string]string{ + { + "type": "subnet", + "value": "10.0.0.0/24", + }, + } + + additionalAddressesUpdate := []map[string]string{ + { + "type": "subnet", + "value": "10.0.0.0/25", + }, + { + "type": "ipAddress", + "value": "169.24.22.10", + }, + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckCbr(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMCbrZoneDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMCbrZoneAddressesConfig(accountID, baseAddresses, nil), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMCbrBaseZoneExists("ibm_cbr_zone.cbr_zone", 1), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.#", "1"), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.type", baseAddresses[0]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.value", baseAddresses[0]["value"]), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMCbrZoneAddressesConfig(accountID, baseAddresses, additionalAddresses), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMCbrBaseZoneExists("ibm_cbr_zone.cbr_zone", 1), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.#", "1"), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.type", baseAddresses[0]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.value", baseAddresses[0]["value"]), + testAccCheckIBMCbrZoneAddressesExists("ibm_cbr_zone_addresses.cbr_zone_addresses", 1), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.#", "1"), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.type", additionalAddresses[0]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.value", additionalAddresses[0]["value"]), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMCbrZoneAddressesConfig(accountID, nil, additionalAddressesUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMCbrBaseZoneExists("ibm_cbr_zone.cbr_zone", 0), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.#", "0"), + testAccCheckIBMCbrZoneAddressesExists("ibm_cbr_zone_addresses.cbr_zone_addresses", 2), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.#", "2"), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.type", additionalAddressesUpdate[0]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.0.value", additionalAddressesUpdate[0]["value"]), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.1.type", additionalAddressesUpdate[1]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone_addresses.cbr_zone_addresses", "addresses.1.value", additionalAddressesUpdate[1]["value"]), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMCbrZoneAddressesConfig(accountID, baseAddresses, nil), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMCbrBaseZoneExists("ibm_cbr_zone.cbr_zone", 1), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.#", "1"), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.type", baseAddresses[0]["type"]), + resource.TestCheckResourceAttr("ibm_cbr_zone.cbr_zone", "addresses.0.value", baseAddresses[0]["value"]), + testAccCheckIBMCbrZoneAddressesDestroyed("ibm_cbr_zone_addresses.cbr_zone_addresses"), + ), + }, + }, + }) +} + +func testAccCheckIBMCbrZoneAddressesConfig(accountID string, base, additional []map[string]string) string { + var result strings.Builder + + addAddresses := func(addresses []map[string]string) { + for _, address := range addresses { + result.WriteString(fmt.Sprintf(` + addresses { + type = "%s" + value = "%s" + }`, + address["type"], address["value"])) + } + } + + result.WriteString(fmt.Sprintf(` + resource "ibm_cbr_zone" "cbr_zone" { + name = "Test Zone Addresses Resource Config" + description = "Test Zone Addresses Resource Config" + account_id = "%s"`, + accountID)) + addAddresses(base) + result.WriteString(` + } + `) + + if len(additional) > 0 { + result.WriteString(` + resource "ibm_cbr_zone_addresses" "cbr_zone_addresses" { + zone_id = ibm_cbr_zone.cbr_zone.id`) + addAddresses(additional) + result.WriteString(` + } + `) + } + return result.String() +} + +func testAccCheckIBMCbrBaseZoneExists(n string, expectedCount int) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + contextBasedRestrictionsClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).ContextBasedRestrictionsV1() + if err != nil { + return err + } + + getZoneOptions := contextBasedRestrictionsClient.NewGetZoneOptions(rs.Primary.ID) + + zone, _, err := contextBasedRestrictionsClient.GetZone(getZoneOptions) + if err != nil { + return err + } + + addresses := contextbasedrestrictions.FilterAddressList(zone.Addresses, func(id string) bool { + return id == "" + }) + + actualCount := len(addresses) + if actualCount != expectedCount { + return fmt.Errorf("%s has an unexpected number of addresses (actual=%d, expected=%d)", n, actualCount, expectedCount) + } + + return nil + } +} + +func testAccCheckIBMCbrZoneAddressesExists(n string, expectedCount int) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + + if expectedCount == 0 { + if !ok { + return nil + } + return fmt.Errorf("%s still exists", n) + } + + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + contextBasedRestrictionsClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).ContextBasedRestrictionsV1() + if err != nil { + return err + } + + parts := strings.Split(rs.Primary.ID, "/") + getZoneOptions := contextBasedRestrictionsClient.NewGetZoneOptions(parts[0]) + + zone, _, err := contextBasedRestrictionsClient.GetZone(getZoneOptions) + if err != nil { + return err + } + + addresses := contextbasedrestrictions.FilterAddressList(zone.Addresses, func(id string) bool { + return id == parts[1] + }) + + actualCount := len(addresses) + if actualCount != expectedCount { + if actualCount == 0 { + return fmt.Errorf("%s does not exist", n) + } + return fmt.Errorf("%s has an unexpected number of addresses (actual=%d, expected=%d)", n, actualCount, expectedCount) + } + + return nil + } +} + +func testAccCheckIBMCbrZoneAddressesDestroyed(n string) resource.TestCheckFunc { + return testAccCheckIBMCbrZoneAddressesExists(n, 0) +} diff --git a/ibm/service/cos/data_source_ibm_cos_bucket.go b/ibm/service/cos/data_source_ibm_cos_bucket.go index ef6b87f88b..24e7c74ad9 100644 --- a/ibm/service/cos/data_source_ibm_cos_bucket.go +++ b/ibm/service/cos/data_source_ibm_cos_bucket.go @@ -23,6 +23,11 @@ import ( var bucketTypes = []string{"single_site_location", "region_location", "cross_region_location"} +var cosConfigUrls = map[string]string{ + "private": "https://config.private.cloud-object-storage.cloud.ibm.com/v1", + "direct": "https://config.direct.cloud-object-storage.cloud.ibm.com/v1", +} + func DataSourceIBMCosBucket() *schema.Resource { return &schema.Resource{ Read: dataSourceIBMCosBucketRead, @@ -62,7 +67,7 @@ func DataSourceIBMCosBucket() *schema.Resource { Optional: true, // ValidateFunc: validate.ValidateAllowedStringValues([]string{"public", "private", "direct"}), ValidateFunc: validate.InvokeDataSourceValidator("ibm_cos_bucket", "endpoint_type"), - Description: "public or private", + Description: "COS endpoint type: public, private, direct", ConflictsWith: []string{"satellite_location_id"}, Default: "public", }, @@ -602,7 +607,7 @@ func dataSourceIBMCosBucketRead(d *schema.ResourceData, meta interface{}) error keyProtectFlag = true } - var satlc_id, apiEndpoint, apiEndpointPrivate, directApiEndpoint string + var satlc_id, apiEndpoint, apiEndpointPrivate, directApiEndpoint, visibility string if satlc, ok := d.GetOk("satellite_location_id"); ok { satlc_id = satlc.(string) @@ -617,15 +622,19 @@ func dataSourceIBMCosBucketRead(d *schema.ResourceData, meta interface{}) error } else { apiEndpoint, apiEndpointPrivate, directApiEndpoint = SelectCosApi(bucketLocationConvert(bucketType), bucketRegion) + visibility = endpointType if endpointType == "private" { apiEndpoint = apiEndpointPrivate } if endpointType == "direct" { + // visibility type "direct" is not supported in endpoints file. + visibility = "private" apiEndpoint = directApiEndpoint } } + apiEndpoint = conns.FileFallBack(rsConClient.Config.EndpointsFile, visibility, "IBMCLOUD_COS_ENDPOINT", bucketRegion, apiEndpoint) apiEndpoint = conns.EnvFallBack([]string{"IBMCLOUD_COS_ENDPOINT"}, apiEndpoint) if apiEndpoint == "" { return fmt.Errorf("[ERROR] The endpoint doesn't exists for given location %s and endpoint type %s", bucketRegion, endpointType) @@ -716,11 +725,13 @@ func dataSourceIBMCosBucketRead(d *schema.ResourceData, meta interface{}) error if err != nil { return err } - if endpointType == "private" { - sess.SetServiceURL("https://config.private.cloud-object-storage.cloud.ibm.com/v1") - } - if endpointType == "direct" { - sess.SetServiceURL("https://config.direct.cloud-object-storage.cloud.ibm.com/v1") + if endpointType != "public" { + // User is expected to define both private and direct url type under "private" in endpoints file since visibility type "direct" is not supported. + cosConfigURL := conns.FileFallBack(rsConClient.Config.EndpointsFile, "private", "IBMCLOUD_COS_CONFIG_ENDPOINT", bucketRegion, cosConfigUrls[endpointType]) + cosConfigURL = conns.EnvFallBack([]string{"IBMCLOUD_COS_CONFIG_ENDPOINT"}, cosConfigURL) + if cosConfigURL != "" { + sess.SetServiceURL(cosConfigURL) + } } if bucketType == "sl" { diff --git a/ibm/service/cos/resource_ibm_cos_bucket.go b/ibm/service/cos/resource_ibm_cos_bucket.go index c378f3fbbb..32850cd514 100644 --- a/ibm/service/cos/resource_ibm_cos_bucket.go +++ b/ibm/service/cos/resource_ibm_cos_bucket.go @@ -153,7 +153,7 @@ func ResourceIBMCOSBucket() *schema.Resource { "endpoint_type": { Type: schema.TypeString, Optional: true, - Description: "public or private", + Description: "COS endpoint type: public, private, direct", ConflictsWith: []string{"satellite_location_id"}, DiffSuppressFunc: flex.ApplyOnce, Default: "public", @@ -743,6 +743,9 @@ func resourceIBMCOSBucketUpdate(d *schema.ResourceData, meta interface{}) error bucketName := parseBucketId(d.Id(), "bucketName") serviceID := parseBucketId(d.Id(), "serviceID") endpointType := parseBucketId(d.Id(), "endpointType") + if endpointType == "" { + endpointType = d.Get("endpoint_type").(string) + } bLocation := parseBucketId(d.Id(), "bLocation") apiType := parseBucketId(d.Id(), "apiType") if apiType == "sl" { @@ -751,21 +754,27 @@ func resourceIBMCOSBucketUpdate(d *schema.ResourceData, meta interface{}) error serviceID = bucketsatcrn } - var apiEndpoint, apiEndpointPrivate, directApiEndpoint string + var apiEndpoint, apiEndpointPrivate, directApiEndpoint, visibility string if apiType == "sl" { apiEndpoint = SelectSatlocCosApi(apiType, serviceID, bLocation) } else { apiEndpoint, apiEndpointPrivate, directApiEndpoint = SelectCosApi(apiType, bLocation) + visibility = endpointType if endpointType == "private" { apiEndpoint = apiEndpointPrivate } if endpointType == "direct" { + // visibility type "direct" is not supported in endpoints file. + visibility = "private" apiEndpoint = directApiEndpoint } } + apiEndpoint = conns.FileFallBack(rsConClient.Config.EndpointsFile, visibility, "IBMCLOUD_COS_ENDPOINT", bLocation, apiEndpoint) + apiEndpoint = conns.EnvFallBack([]string{"IBMCLOUD_COS_ENDPOINT"}, apiEndpoint) + authEndpoint, err := rsConClient.Config.EndpointLocator.IAMEndpoint() if err != nil { @@ -774,7 +783,7 @@ func resourceIBMCOSBucketUpdate(d *schema.ResourceData, meta interface{}) error authEndpointPath := fmt.Sprintf("%s%s", authEndpoint, "/identity/token") apiKey := rsConClient.Config.BluemixAPIKey if apiKey != "" { - s3Conf = aws.NewConfig().WithEndpoint(conns.EnvFallBack([]string{"IBMCLOUD_COS_ENDPOINT"}, apiEndpoint)).WithCredentials(ibmiam.NewStaticCredentials(aws.NewConfig(), authEndpointPath, apiKey, serviceID)).WithS3ForcePathStyle(true) + s3Conf = aws.NewConfig().WithEndpoint(apiEndpoint).WithCredentials(ibmiam.NewStaticCredentials(aws.NewConfig(), authEndpointPath, apiKey, serviceID)).WithS3ForcePathStyle(true) } iamAccessToken := rsConClient.Config.IAMAccessToken if iamAccessToken != "" { @@ -787,7 +796,7 @@ func resourceIBMCOSBucketUpdate(d *schema.ResourceData, meta interface{}) error Expiration: time.Now().Add(-1 * time.Hour).Unix(), }, nil } - s3Conf = aws.NewConfig().WithEndpoint(conns.EnvFallBack([]string{"IBMCLOUD_COS_ENDPOINT"}, apiEndpoint)).WithCredentials(ibmiam.NewCustomInitFuncCredentials(aws.NewConfig(), initFunc, authEndpointPath, serviceID)).WithS3ForcePathStyle(true) + s3Conf = aws.NewConfig().WithEndpoint(apiEndpoint).WithCredentials(ibmiam.NewCustomInitFuncCredentials(aws.NewConfig(), initFunc, authEndpointPath, serviceID)).WithS3ForcePathStyle(true) } s3Sess := session.Must(session.NewSession()) s3Client := s3.New(s3Sess, s3Conf) @@ -928,11 +937,14 @@ func resourceIBMCOSBucketUpdate(d *schema.ResourceData, meta interface{}) error if err != nil { return err } - if endpointType == "private" { - sess.SetServiceURL("https://config.private.cloud-object-storage.cloud.ibm.com/v1") - } - if endpointType == "direct" { - sess.SetServiceURL("https://config.direct.cloud-object-storage.cloud.ibm.com/v1") + + if endpointType != "public" { + // User is expected to define both private and direct url type under "private" in endpoints file since visibility type "direct" is not supported. + cosConfigURL := conns.FileFallBack(rsConClient.Config.EndpointsFile, "private", "IBMCLOUD_COS_CONFIG_ENDPOINT", bLocation, cosConfigUrls[endpointType]) + cosConfigURL = conns.EnvFallBack([]string{"IBMCLOUD_COS_CONFIG_ENDPOINT"}, cosConfigURL) + if cosConfigURL != "" { + sess.SetServiceURL(cosConfigURL) + } } if apiType == "sl" { @@ -1080,6 +1092,9 @@ func resourceIBMCOSBucketRead(d *schema.ResourceData, meta interface{}) error { bucketName := parseBucketId(d.Id(), "bucketName") serviceID := parseBucketId(d.Id(), "serviceID") endpointType := parseBucketId(d.Id(), "endpointType") + if endpointType == "" { + endpointType = d.Get("endpoint_type").(string) + } apiType := parseBucketId(d.Id(), "apiType") bLocation := parseBucketId(d.Id(), "bLocation") @@ -1094,8 +1109,8 @@ func resourceIBMCOSBucketRead(d *schema.ResourceData, meta interface{}) error { serviceID = bucketsatcrn } - var apiEndpoint, apiEndpointPublic, apiEndpointPrivate, directApiEndpoint string - + var apiEndpoint, apiEndpointPublic, apiEndpointPrivate, directApiEndpoint, visibility string + visibility = endpointType if apiType == "sl" { apiEndpoint = SelectSatlocCosApi(apiType, serviceID, bLocation) } else { @@ -1105,11 +1120,14 @@ func resourceIBMCOSBucketRead(d *schema.ResourceData, meta interface{}) error { apiEndpoint = apiEndpointPrivate } if endpointType == "direct" { + // visibility type "direct" is not supported in endpoints file. + visibility = "private" apiEndpoint = directApiEndpoint } } + apiEndpoint = conns.FileFallBack(rsConClient.Config.EndpointsFile, visibility, "IBMCLOUD_COS_ENDPOINT", bLocation, apiEndpoint) apiEndpoint = conns.EnvFallBack([]string{"IBMCLOUD_COS_ENDPOINT"}, apiEndpoint) authEndpoint, err := rsConClient.Config.EndpointLocator.IAMEndpoint() @@ -1194,11 +1212,13 @@ func resourceIBMCOSBucketRead(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } - if endpointType == "private" { - sess.SetServiceURL("https://config.private.cloud-object-storage.cloud.ibm.com/v1") - } - if endpointType == "direct" { - sess.SetServiceURL("https://config.direct.cloud-object-storage.cloud.ibm.com/v1") + if endpointType != "public" { + // User is expected to define both private and direct url type under "private" in endpoints file since visibility type "direct" is not supported. + cosConfigURL := conns.FileFallBack(rsConClient.Config.EndpointsFile, "private", "IBMCLOUD_COS_CONFIG_ENDPOINT", bLocation, cosConfigUrls[endpointType]) + cosConfigURL = conns.EnvFallBack([]string{"IBMCLOUD_COS_CONFIG_ENDPOINT"}, cosConfigURL) + if cosConfigURL != "" { + sess.SetServiceURL(cosConfigURL) + } } if apiType == "sl" { @@ -1382,22 +1402,25 @@ func resourceIBMCOSBucketCreate(d *schema.ResourceData, meta interface{}) error var endpointType = d.Get("endpoint_type").(string) - var apiEndpoint, privateApiEndpoint, directApiEndpoint string + var apiEndpoint, privateApiEndpoint, directApiEndpoint, visibility string if apiType == "sl" { - apiEndpoint = SelectSatlocCosApi(apiType, serviceID, bLocation) } else { apiEndpoint, privateApiEndpoint, directApiEndpoint = SelectCosApi(apiType, bLocation) + visibility = endpointType if endpointType == "private" { apiEndpoint = privateApiEndpoint } if endpointType == "direct" { + // visibility type "direct" is not supported in endpoints file. + visibility = "private" apiEndpoint = directApiEndpoint } } + apiEndpoint = conns.FileFallBack(rsConClient.Config.EndpointsFile, visibility, "IBMCLOUD_COS_ENDPOINT", bLocation, apiEndpoint) apiEndpoint = conns.EnvFallBack([]string{"IBMCLOUD_COS_ENDPOINT"}, apiEndpoint) if apiEndpoint == "" { @@ -1500,8 +1523,10 @@ func resourceIBMCOSBucketDelete(d *schema.ResourceData, meta interface{}) error } endpointType := parseBucketId(d.Id(), "endpointType") - - var apiEndpoint, apiEndpointPrivate, directApiEndpoint string + if endpointType == "" { + endpointType = d.Get("endpoint_type").(string) + } + var apiEndpoint, apiEndpointPrivate, directApiEndpoint, visibility string if apiType == "sl" { @@ -1509,15 +1534,19 @@ func resourceIBMCOSBucketDelete(d *schema.ResourceData, meta interface{}) error } else { apiEndpoint, apiEndpointPrivate, directApiEndpoint = SelectCosApi(apiType, bLocation) + visibility = endpointType if endpointType == "private" { apiEndpoint = apiEndpointPrivate } if endpointType == "direct" { + // visibility type "direct" is not supported in endpoints file. + visibility = "private" apiEndpoint = directApiEndpoint } } + apiEndpoint = conns.FileFallBack(rsConClient.Config.EndpointsFile, visibility, "IBMCLOUD_COS_ENDPOINT", bLocation, apiEndpoint) apiEndpoint = conns.EnvFallBack([]string{"IBMCLOUD_COS_ENDPOINT"}, apiEndpoint) if apiEndpoint == "" { @@ -1621,8 +1650,11 @@ func resourceIBMCOSBucketExists(d *schema.ResourceData, meta interface{}) (bool, apiType := parseBucketId(d.Id(), "apiType") bLocation := parseBucketId(d.Id(), "bLocation") - endpointType := parseBucketId(d.Id(), "endpointType") + endpointType := parseBucketId(d.Id(), "endpointType") + if endpointType == "" { + endpointType = d.Get("endpoint_type").(string) + } if apiType == "sl" { satloc_guid := strings.Split(serviceID, ":") bucketsatcrn := satloc_guid[0] diff --git a/ibm/service/cos/resource_ibm_cos_bucket_object.go b/ibm/service/cos/resource_ibm_cos_bucket_object.go index 9b7afa0cf6..e907534138 100644 --- a/ibm/service/cos/resource_ibm_cos_bucket_object.go +++ b/ibm/service/cos/resource_ibm_cos_bucket_object.go @@ -494,8 +494,13 @@ func getCosEndpoint(bucketLocation string, endpointType string) string { func getS3Client(bxSession *bxsession.Session, bucketLocation string, endpointType string, instanceCRN string) (*s3.S3, error) { var s3Conf *aws.Config + visibility := endpointType + if endpointType == "direct" { + visibility = "private" + } apiEndpoint := getCosEndpoint(bucketLocation, endpointType) + apiEndpoint = conns.FileFallBack(bxSession.Config.EndpointsFile, visibility, "IBMCLOUD_COS_ENDPOINT", bucketLocation, apiEndpoint) apiEndpoint = conns.EnvFallBack([]string{"IBMCLOUD_COS_ENDPOINT"}, apiEndpoint) if apiEndpoint == "" { return nil, fmt.Errorf("the endpoint doesn't exists for given location %s and endpoint type %s", bucketLocation, endpointType) diff --git a/ibm/service/cos/resource_ibm_cos_replication_configuration.go b/ibm/service/cos/resource_ibm_cos_replication_configuration.go index 46129d2986..f805ace41f 100644 --- a/ibm/service/cos/resource_ibm_cos_replication_configuration.go +++ b/ibm/service/cos/resource_ibm_cos_replication_configuration.go @@ -353,7 +353,13 @@ func getCosEndpointType(bucketLocation string, endpointType string) string { func getS3ClientSession(bxSession *bxsession.Session, bucketLocation string, endpointType string, instanceCRN string) (*s3.S3, error) { var s3Conf *aws.Config + visibility := endpointType + if endpointType == "direct" { + visibility = "private" + } + apiEndpoint := getCosEndpointType(bucketLocation, endpointType) + apiEndpoint = conns.FileFallBack(bxSession.Config.EndpointsFile, visibility, "IBMCLOUD_COS_ENDPOINT", bucketLocation, apiEndpoint) apiEndpoint = conns.EnvFallBack([]string{"IBMCLOUD_COS_ENDPOINT"}, apiEndpoint) if apiEndpoint == "" { return nil, fmt.Errorf("the endpoint doesn't exists for given location %s and endpoint type %s", bucketLocation, endpointType) diff --git a/ibm/service/database/data_source_ibm_database.go b/ibm/service/database/data_source_ibm_database.go index 0ef0cfcf32..4b5462fdd3 100644 --- a/ibm/service/database/data_source_ibm_database.go +++ b/ibm/service/database/data_source_ibm_database.go @@ -685,7 +685,7 @@ func dataSourceIBMDatabaseInstanceRead(d *schema.ResourceData, meta interface{}) autoscalingGroup, _, err := cloudDatabasesClient.GetAutoscalingConditions(getAutoscalingConditionsOptions) if err != nil { - return fmt.Errorf("[ERROR] Error getting database autoscaling groups: %s", err) + return fmt.Errorf("[ERROR] Error getting database autoscaling groups: %s\n Hint: Check if there is a mismatch between your database location and IBMCLOUD_REGION", err) } d.Set("auto_scaling", flattenAutoScalingGroup(*autoscalingGroup)) diff --git a/ibm/service/database/data_source_ibm_database_connection.go b/ibm/service/database/data_source_ibm_database_connection.go index c774c52e60..e1ef5ae65e 100644 --- a/ibm/service/database/data_source_ibm_database_connection.go +++ b/ibm/service/database/data_source_ibm_database_connection.go @@ -1850,14 +1850,6 @@ func DataSourceIBMDatabaseConnectionRead(context context.Context, d *schema.Reso } secure := []map[string]interface{}{} - if conn.Secure != nil { - modelMap, err := DataSourceIBMDatabaseConnectionDataStaxConnectionURIToMap(conn.Secure) - if err != nil { - tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_database_connection", "read") - return tfErr.GetDiag() - } - secure = append(secure, modelMap) - } if err = d.Set("secure", secure); err != nil { tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting secure: %s", err), "(Data) ibm_database_connection", "read") return tfErr.GetDiag() @@ -2235,36 +2227,6 @@ func DataSourceIBMDatabaseConnectionMySQLConnectionURIToMap(model *clouddatabase return modelMap, nil } -func DataSourceIBMDatabaseConnectionDataStaxConnectionURIToMap(model *clouddatabasesv5.DataStaxConnectionURI) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Hosts != nil { - hosts := []map[string]interface{}{} - for _, hostsItem := range model.Hosts { - hostsItemMap, err := DataSourceIBMDatabaseConnectionConnectionHostToMap(&hostsItem) - if err != nil { - return modelMap, err - } - hosts = append(hosts, hostsItemMap) - } - modelMap["hosts"] = hosts - } - if model.Authentication != nil { - authenticationMap, err := DataSourceIBMDatabaseConnectionConnectionAuthenticationToMap(model.Authentication) - if err != nil { - return modelMap, err - } - modelMap["authentication"] = []map[string]interface{}{authenticationMap} - } - if model.Bundle != nil { - bundleMap, err := DataSourceIBMDatabaseConnectionConnectionBundleToMap(model.Bundle) - if err != nil { - return modelMap, err - } - modelMap["bundle"] = []map[string]interface{}{bundleMap} - } - return modelMap, nil -} - func DataSourceIBMDatabaseConnectionConnectionBundleToMap(model *clouddatabasesv5.ConnectionBundle) (map[string]interface{}, error) { modelMap := make(map[string]interface{}) if model.Name != nil { diff --git a/ibm/service/database/resource_ibm_database.go b/ibm/service/database/resource_ibm_database.go index dc3723ca51..1ce2a8ce34 100644 --- a/ibm/service/database/resource_ibm_database.go +++ b/ibm/service/database/resource_ibm_database.go @@ -11,7 +11,6 @@ import ( "log" "net/url" "os" - "reflect" "regexp" "sort" "strconv" @@ -348,88 +347,6 @@ func ResourceIBMDatabaseInstance() *schema.Resource { }, }, }, - "connectionstrings": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Description: "User name", - Type: schema.TypeString, - Computed: true, - }, - "composed": { - Description: "Connection string", - Type: schema.TypeString, - Computed: true, - }, - "scheme": { - Description: "DB scheme", - Type: schema.TypeString, - Computed: true, - }, - "certname": { - Description: "Certificate Name", - Type: schema.TypeString, - Computed: true, - }, - "certbase64": { - Description: "Certificate in base64 encoding", - Type: schema.TypeString, - Computed: true, - }, - "bundlename": { - Description: "Cassandra Bundle Name", - Type: schema.TypeString, - Computed: true, - }, - "bundlebase64": { - Description: "Cassandra base64 encoding", - Type: schema.TypeString, - Computed: true, - }, - "password": { - Description: "Password", - Type: schema.TypeString, - Computed: true, - }, - "queryoptions": { - Description: "DB query options", - Type: schema.TypeString, - Computed: true, - }, - "database": { - Description: "DB name", - Type: schema.TypeString, - Computed: true, - }, - "path": { - Description: "DB path", - Type: schema.TypeString, - Computed: true, - }, - "hosts": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "hostname": { - Description: "DB host name", - Type: schema.TypeString, - Computed: true, - }, - "port": { - Description: "DB port", - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - }, - }, - Deprecated: "This field is deprecated, please use ibm_database_connection instead", - }, "allowlist": { Type: schema.TypeSet, Optional: true, @@ -955,7 +872,7 @@ func ResourceIBMICDValidator() *validate.ResourceValidator { Identifier: "service", ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, Type: validate.TypeString, - AllowedValues: "databases-for-etcd, databases-for-postgresql, databases-for-redis, databases-for-elasticsearch, databases-for-mongodb, messages-for-rabbitmq, databases-for-mysql, databases-for-cassandra, databases-for-enterprisedb", + AllowedValues: "databases-for-etcd, databases-for-postgresql, databases-for-redis, databases-for-elasticsearch, databases-for-mongodb, messages-for-rabbitmq, databases-for-mysql, databases-for-enterprisedb", Required: true}) validateSchema = append(validateSchema, validate.ValidateSchema{ @@ -976,7 +893,7 @@ func ResourceIBMICDValidator() *validate.ResourceValidator { Identifier: "group_id", ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, Type: validate.TypeString, - AllowedValues: "member, analytics, bi_connector, search", + AllowedValues: "member, analytics, bi_connector", Required: true}) ibmICDResourceValidator := validate.ResourceValidator{ResourceName: "ibm_database", Schema: validateSchema} @@ -1041,10 +958,6 @@ func getDefaultScalingGroups(_service string, _plan string, _hostFlavor string, service := match[1] - if service == "cassandra" { - service = "datastax_enterprise_full" - } - if service == "mongodb" && _plan == "enterprise" { service = "mongodbee" } @@ -1643,7 +1556,6 @@ func resourceIBMDatabaseInstanceRead(context context.Context, d *schema.Resource } instanceID := d.Id() - connectionEndpoint := "public" rsInst := rc.GetResourceInstanceOptions{ ID: &instanceID, } @@ -1682,9 +1594,6 @@ func resourceIBMDatabaseInstanceRead(context context.Context, d *schema.Resource if instance.Parameters != nil { if endpoint, ok := instance.Parameters["service-endpoints"]; ok { - if endpoint == "private" { - connectionEndpoint = "private" - } d.Set("service_endpoints", endpoint) } @@ -1769,7 +1678,7 @@ func resourceIBMDatabaseInstanceRead(context context.Context, d *schema.Resource autoscalingGroup, _, err := cloudDatabasesClient.GetAutoscalingConditions(getAutoscalingConditionsOptions) if err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error getting database autoscaling groups: %s", err)) + return diag.FromErr(fmt.Errorf("[ERROR] Error getting database autoscaling groups: %s\n Hint: Check if there is a mismatch between your database location and IBMCLOUD_REGION", err)) } d.Set("auto_scaling", flattenAutoScalingGroup(*autoscalingGroup)) @@ -1785,7 +1694,6 @@ func resourceIBMDatabaseInstanceRead(context context.Context, d *schema.Resource d.Set("allowlist", flex.FlattenAllowlist(allowlist.IPAddresses)) - var connectionStrings []flex.CsEntry //ICD does not implement a GetUsers API. Users populated from tf configuration. tfusers := d.Get("users").(*schema.Set) users := flex.ExpandUsers(tfusers) @@ -1793,15 +1701,6 @@ func resourceIBMDatabaseInstanceRead(context context.Context, d *schema.Resource UserName: deployment.AdminUsernames["database"], } users = append(users, user) - for _, user := range users { - userName := user.UserName - csEntry, err := getConnectionString(d, userName, connectionEndpoint, meta) - if err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error getting user connection string for user (%s): %s", userName, err)) - } - connectionStrings = append(connectionStrings, csEntry) - } - d.Set("connectionstrings", flex.FlattenConnectionStrings(connectionStrings)) if serviceOff == "databases-for-postgresql" || serviceOff == "databases-for-redis" || serviceOff == "databases-for-enterprisedb" { configSchema, err := icdClient.Configurations().GetConfiguration(icdId) @@ -2234,85 +2133,6 @@ func resourceIBMDatabaseInstanceUpdate(context context.Context, d *schema.Resour return resourceIBMDatabaseInstanceRead(context, d, meta) } -func getConnectionString(d *schema.ResourceData, userName, connectionEndpoint string, meta interface{}) (flex.CsEntry, error) { - csEntry := flex.CsEntry{} - icdClient, err := meta.(conns.ClientSession).ICDAPI() - if err != nil { - return csEntry, fmt.Errorf("[ERROR] Error getting database client settings: %s", err) - } - - icdId := d.Id() - connection, err := icdClient.Connections().GetConnection(icdId, userName, connectionEndpoint) - if err != nil { - return csEntry, fmt.Errorf("[ERROR] Error getting database user connection string via ICD API: %s", err) - } - - service := d.Get("service") - dbConnection := icdv4.Uri{} - var cassandraConnection icdv4.CassandraUri - - switch service { - case "databases-for-postgresql": - dbConnection = connection.Postgres - case "databases-for-redis": - dbConnection = connection.Rediss - case "databases-for-mongodb": - dbConnection = connection.Mongo - case "databases-for-mysql": - dbConnection = connection.Mysql - case "databases-for-elasticsearch": - dbConnection = connection.Https - case "databases-for-cassandra": - cassandraConnection = connection.Secure - case "databases-for-etcd": - dbConnection = connection.Grpc - case "messages-for-rabbitmq": - dbConnection = connection.Amqps - case "databases-for-enterprisedb": - dbConnection = connection.Postgres - default: - return csEntry, fmt.Errorf("[ERROR] Unrecognised database type during connection string lookup: %s", service) - } - - if !reflect.DeepEqual(cassandraConnection, icdv4.CassandraUri{}) { - csEntry = flex.CsEntry{ - Name: userName, - Hosts: cassandraConnection.Hosts, - BundleName: cassandraConnection.Bundle.Name, - BundleBase64: cassandraConnection.Bundle.BundleBase64, - } - } else { - csEntry = flex.CsEntry{ - Name: userName, - Password: "", - // Populate only first 'composed' connection string as an example - Composed: dbConnection.Composed[0], - CertName: dbConnection.Certificate.Name, - CertBase64: dbConnection.Certificate.CertificateBase64, - Hosts: dbConnection.Hosts, - Scheme: dbConnection.Scheme, - Path: dbConnection.Path, - QueryOptions: dbConnection.QueryOptions.(map[string]interface{}), - } - - // Postgres DB name is of type string, Redis is json.Number, others are nil - if dbConnection.Database != nil { - switch v := dbConnection.Database.(type) { - default: - return csEntry, fmt.Errorf("Unexpected data type: %T", v) - case json.Number: - csEntry.Database = dbConnection.Database.(json.Number).String() - case string: - csEntry.Database = dbConnection.Database.(string) - } - } else { - csEntry.Database = "" - } - } - - return csEntry, nil -} - func resourceIBMDatabaseInstanceDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { rsConClient, err := meta.(conns.ClientSession).ResourceControllerV2API() if err != nil { diff --git a/ibm/service/database/resource_ibm_database_cassandra_test.go b/ibm/service/database/resource_ibm_database_cassandra_test.go deleted file mode 100644 index 2701ecb344..0000000000 --- a/ibm/service/database/resource_ibm_database_cassandra_test.go +++ /dev/null @@ -1,787 +0,0 @@ -// Copyright IBM Corp. 2017, 2021 All Rights Reserved. -// Licensed under the Mozilla Public License v2.0 - -package database_test - -import ( - "fmt" - "testing" - - acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func TestAccIBMCassandraDatabaseInstanceBasic(t *testing.T) { - t.Parallel() - databaseResourceGroup := "default" - var databaseInstanceOne string - rnd := fmt.Sprintf("tf-Datastax-%d", acctest.RandIntRange(10, 100)) - testName := rnd - name := "ibm_database." + testName - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccPreCheck(t) }, - Providers: acc.TestAccProviders, - CheckDestroy: testAccCheckIBMDatabaseInstanceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccCheckIBMDatabaseInstanceCassandraBasic(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "adminuser", "admin"), - resource.TestCheckResourceAttr(name, "allowlist.#", "1"), - resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - ), - }, - { - Config: testAccCheckIBMDatabaseInstanceCassandraFullyspecified(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "allowlist.#", "2"), - resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), - ), - }, - { - Config: testAccCheckIBMDatabaseInstanceCassandraReduced(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "allowlist.#", "0"), - resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), - ), - }, - }, - }) -} - -func TestAccIBMDatabaseInstance_Cassandra_Node(t *testing.T) { - t.Parallel() - databaseResourceGroup := "default" - var databaseInstanceOne string - rnd := fmt.Sprintf("tf-Datastax-%d", acctest.RandIntRange(10, 100)) - testName := rnd - name := "ibm_database." + testName - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccPreCheck(t) }, - Providers: acc.TestAccProviders, - CheckDestroy: testAccCheckIBMDatabaseInstanceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccCheckIBMDatabaseInstanceCassandraNodeBasic(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "adminuser", "admin"), - - resource.TestCheckResourceAttr(name, "allowlist.#", "1"), - resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), - ), - }, - { - Config: testAccCheckIBMDatabaseInstanceCassandraNodeFullyspecified(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "allowlist.#", "2"), - resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), - ), - }, - { - Config: testAccCheckIBMDatabaseInstanceCassandraNodeReduced(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "allowlist.#", "0"), - resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), - ), - }, - { - Config: testAccCheckIBMDatabaseInstanceCassandraNodeScaleOut(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "allowlist.#", "0"), - resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), - ), - }, - //{ - // ResourceName: name, - // ImportState: true, - // ImportStateVerify: true, - //}, - }, - }) -} - -func TestAccIBMDatabaseInstance_Cassandra_Group(t *testing.T) { - t.Parallel() - databaseResourceGroup := "default" - var databaseInstanceOne string - rnd := fmt.Sprintf("tf-Datastax-%d", acctest.RandIntRange(10, 100)) - testName := rnd - name := "ibm_database." + testName - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccPreCheck(t) }, - Providers: acc.TestAccProviders, - CheckDestroy: testAccCheckIBMDatabaseInstanceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccCheckIBMDatabaseInstanceCassandraGroupBasic(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "adminuser", "admin"), - resource.TestCheckResourceAttr(name, "groups.0.count", "3"), - resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "36864"), - resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "61440"), - resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "18"), - resource.TestCheckResourceAttr(name, "allowlist.#", "1"), - resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), - ), - }, - { - Config: testAccCheckIBMDatabaseInstanceCassandraGroupFullyspecified(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "groups.0.count", "3"), - resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "37248"), - resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "61440"), - resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "18"), - resource.TestCheckResourceAttr(name, "allowlist.#", "2"), - resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), - ), - }, - { - Config: testAccCheckIBMDatabaseInstanceCassandraGroupReduced(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "groups.0.count", "3"), - resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "36864"), - resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "61440"), - resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "18"), - resource.TestCheckResourceAttr(name, "allowlist.#", "0"), - resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), - ), - }, - { - Config: testAccCheckIBMDatabaseInstanceCassandraGroupScaleOut(databaseResourceGroup, testName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(name, &databaseInstanceOne), - resource.TestCheckResourceAttr(name, "name", testName), - resource.TestCheckResourceAttr(name, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(name, "plan", "enterprise"), - resource.TestCheckResourceAttr(name, "location", acc.Region()), - resource.TestCheckResourceAttr(name, "groups.0.count", "4"), - resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "49152"), - resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "81920"), - resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "24"), - resource.TestCheckResourceAttr(name, "groups.1.count", "3"), - resource.TestCheckResourceAttr(name, "allowlist.#", "0"), - resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), - ), - }, - }, - }) -} - -// TestAccIBMDatabaseInstance_CreateAfterManualDestroy not required as tested by resource_instance tests - -func TestAccIBMDatabaseInstanceCassandraImport(t *testing.T) { - t.Parallel() - databaseResourceGroup := "default" - var databaseInstanceOne string - serviceName := fmt.Sprintf("tf-Datastax-%d", acctest.RandIntRange(10, 100)) - //serviceName := "test_acc" - resourceName := "ibm_database." + serviceName - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccPreCheck(t) }, - Providers: acc.TestAccProviders, - CheckDestroy: testAccCheckIBMDatabaseInstanceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccCheckIBMDatabaseInstanceCassandraImport(databaseResourceGroup, serviceName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckIBMDatabaseInstanceExists(resourceName, &databaseInstanceOne), - resource.TestCheckResourceAttr(resourceName, "name", serviceName), - resource.TestCheckResourceAttr(resourceName, "service", "databases-for-cassandra"), - resource.TestCheckResourceAttr(resourceName, "plan", "enterprise"), - resource.TestCheckResourceAttr(resourceName, "location", acc.Region()), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "wait_time_minutes"}, - }, - }, - }) -} - -// func testAccCheckIBMDatabaseInstanceDestroy(s *terraform.State) etc in resource_ibm_database_postgresql_test.go - -func testAccCheckIBMDatabaseInstanceCassandraBasic(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - location = "%[3]s" - adminpassword = "password12345678" - users { - name = "user123" - password = "password12345678" - } - allowlist { - address = "172.168.1.2/32" - description = "desc1" - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraFullyspecified(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - location = "%[3]s" - adminpassword = "password12345678" - users { - name = "user123" - password = "password12345678" - } - users { - name = "user124" - password = "password12345678" - } - allowlist { - address = "172.168.1.2/32" - description = "desc1" - } - allowlist { - address = "172.168.1.1/32" - description = "desc" - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraReduced(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - location = "%[3]s" - adminpassword = "password12345678" - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraNodeBasic(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - location = "%[3]s" - adminpassword = "password12345678" - - group { - group_id = "member" - - memory { - allocation_mb = 12288 - } - - disk { - allocation_mb = 20480 - } - - cpu { - allocation_count = 6 - } - } - - users { - name = "user123" - password = "password12345678" - } - allowlist { - address = "172.168.1.2/32" - description = "desc1" - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraNodeFullyspecified(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - location = "%[3]s" - version = "5.1" - adminpassword = "password12345678" - - group { - group_id = "member" - members { - allocation_count = 3 - } - memory { - allocation_mb = 12416 - } - disk { - allocation_mb = 20480 - } - - cpu { - allocation_count = 6 - } - } - - users { - name = "user123" - password = "password12345678" - } - users { - name = "user124" - password = "password12345678" - } - allowlist { - address = "172.168.1.2/32" - description = "desc1" - } - allowlist { - address = "172.168.1.1/32" - description = "desc" - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraNodeReduced(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - location = "%[3]s" - version = "5.1" - adminpassword = "password12345678" - - group { - group_id = "member" - members { - allocation_count = 3 - } - memory { - allocation_mb = 12288 - } - disk { - allocation_mb = 20480 - } - cpu { - allocation_count = 6 - } - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraNodeScaleOut(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - location = "%[3]s" - adminpassword = "password12345678" - - group { - group_id = "member" - members { - allocation_count = 4 - } - memory { - allocation_mb = 12288 - } - disk { - allocation_mb = 20480 - } - cpu { - allocation_count = 6 - } - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraGroupBasic(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - version = "5.1" - location = "%[3]s" - adminpassword = "password12345678" - - group { - group_id = "member" - members { - allocation_count = 3 - } - memory { - allocation_mb = 12288 - } - disk { - allocation_mb = 20480 - } - cpu { - allocation_count = 6 - } - } - users { - name = "user123" - password = "password12345678" - } - allowlist { - address = "172.168.1.2/32" - description = "desc1" - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraGroupFullyspecified(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - version = "5.1" - location = "%[3]s" - adminpassword = "password12345678" - - group { - group_id = "member" - members { - allocation_count = 3 - } - memory { - allocation_mb = 12416 - } - disk { - allocation_mb = 20480 - } - cpu { - allocation_count = 6 - } - } - users { - name = "user123" - password = "password12345678" - } - users { - name = "user124" - password = "password12345678" - } - allowlist { - address = "172.168.1.2/32" - description = "desc1" - } - allowlist { - address = "172.168.1.1/32" - description = "desc" - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraGroupReduced(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - version = "5.1" - location = "%[3]s" - adminpassword = "password12345678" - group { - group_id = "member" - members { - allocation_count = 3 - } - memory { - allocation_mb = 12288 - } - disk { - allocation_mb = 20480 - } - cpu { - allocation_count = 6 - } - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraGroupScaleOut(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - version = "5.1" - location = "%[3]s" - adminpassword = "password12345678" - - group { - group_id = "member" - members { - allocation_count = 4 - } - memory { - allocation_mb = 12288 - } - disk { - allocation_mb = 20480 - } - cpu { - allocation_count = 6 - } - } - - group { - group_id = "search" - members { - allocation_count = 3 - } - } - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - } - `, databaseResourceGroup, name, acc.Region()) -} - -func testAccCheckIBMDatabaseInstanceCassandraImport(databaseResourceGroup string, name string) string { - return fmt.Sprintf(` - data "ibm_resource_group" "test_acc" { - is_default = true - # name = "%[1]s" - } - - resource "ibm_database" "%[2]s" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "%[2]s" - service = "databases-for-cassandra" - plan = "enterprise" - location = "%[3]s" - - timeouts { - create = "480m" - update = "480m" - delete = "15m" - } - - } - `, databaseResourceGroup, name, acc.Region()) -} diff --git a/ibm/service/database/resource_ibm_database_edb_test.go b/ibm/service/database/resource_ibm_database_edb_test.go index b4a7d149d9..00f2ee1904 100644 --- a/ibm/service/database/resource_ibm_database_edb_test.go +++ b/ibm/service/database/resource_ibm_database_edb_test.go @@ -5,7 +5,6 @@ package database_test import ( "fmt" - "regexp" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" @@ -41,10 +40,6 @@ func TestAccIBMEDBDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "service_endpoints", "public"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, @@ -61,13 +56,6 @@ func TestAccIBMEDBDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "service_endpoints", "public-and-private"), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.scheme", "postgres"), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.database", regexp.MustCompile("[-a-z0-9]+")), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, @@ -83,7 +71,6 @@ func TestAccIBMEDBDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "92160"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, diff --git a/ibm/service/database/resource_ibm_database_elasticsearch_platinum_test.go b/ibm/service/database/resource_ibm_database_elasticsearch_platinum_test.go index 14c18b201d..51d1802ef2 100644 --- a/ibm/service/database/resource_ibm_database_elasticsearch_platinum_test.go +++ b/ibm/service/database/resource_ibm_database_elasticsearch_platinum_test.go @@ -37,10 +37,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "adminuser", "admin"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), ), }, { @@ -53,8 +49,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "location", acc.Region()), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), ), }, { @@ -69,7 +63,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "18432"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, { @@ -84,7 +77,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "18432"), resource.TestCheckResourceAttr(name, "whitelist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, // { @@ -121,10 +113,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Node(t *testing.T) { resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), ), }, { @@ -137,8 +125,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Node(t *testing.T) { resource.TestCheckResourceAttr(name, "location", acc.Region()), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), ), }, { @@ -151,7 +137,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Node(t *testing.T) { resource.TestCheckResourceAttr(name, "location", acc.Region()), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, { @@ -164,7 +149,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Node(t *testing.T) { resource.TestCheckResourceAttr(name, "location", acc.Region()), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, //{ @@ -201,10 +185,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Group(t *testing.T) { resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), ), }, { @@ -221,8 +201,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Group(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "12"), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), ), }, { @@ -239,7 +217,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Group(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "12"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, { @@ -256,7 +233,6 @@ func TestAccIBMDatabaseInstance_ElasticsearchPlatinum_Group(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "16"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, //{ diff --git a/ibm/service/database/resource_ibm_database_elasticsearch_test.go b/ibm/service/database/resource_ibm_database_elasticsearch_test.go index b365fb81f8..e27f778876 100644 --- a/ibm/service/database/resource_ibm_database_elasticsearch_test.go +++ b/ibm/service/database/resource_ibm_database_elasticsearch_test.go @@ -37,10 +37,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "adminuser", "admin"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), ), }, { @@ -53,8 +49,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "location", acc.Region()), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), ), }, { @@ -67,7 +61,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "location", acc.Region()), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, { @@ -81,7 +74,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "12288"), resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "18432"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, // { @@ -118,10 +110,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Node(t *testing.T) { resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), ), }, { @@ -134,8 +122,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Node(t *testing.T) { resource.TestCheckResourceAttr(name, "location", acc.Region()), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), ), }, { @@ -148,7 +134,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Node(t *testing.T) { resource.TestCheckResourceAttr(name, "location", acc.Region()), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, { @@ -161,7 +146,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Node(t *testing.T) { resource.TestCheckResourceAttr(name, "location", acc.Region()), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, //{ @@ -198,10 +182,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Group(t *testing.T) { resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), ), }, { @@ -218,8 +198,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Group(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "9"), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), ), }, { @@ -236,7 +214,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Group(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "9"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, { @@ -253,7 +230,6 @@ func TestAccIBMDatabaseInstance_Elasticsearch_Group(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "12"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, //{ diff --git a/ibm/service/database/resource_ibm_database_etcd_test.go b/ibm/service/database/resource_ibm_database_etcd_test.go index bd279f277c..91cff8d6fc 100644 --- a/ibm/service/database/resource_ibm_database_etcd_test.go +++ b/ibm/service/database/resource_ibm_database_etcd_test.go @@ -5,7 +5,6 @@ package database_test import ( "fmt" - "regexp" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" @@ -40,12 +39,6 @@ func TestAccIBMDatabaseInstance_Etcd_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "184320"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "root"), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), ), }, { @@ -59,7 +52,6 @@ func TestAccIBMDatabaseInstance_Etcd_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "193536"), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), ), }, { @@ -73,7 +65,6 @@ func TestAccIBMDatabaseInstance_Etcd_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "193536"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, }, diff --git a/ibm/service/database/resource_ibm_database_mongodb_enterprise_test.go b/ibm/service/database/resource_ibm_database_mongodb_enterprise_test.go index c54a2e11d4..1ac55ec575 100644 --- a/ibm/service/database/resource_ibm_database_mongodb_enterprise_test.go +++ b/ibm/service/database/resource_ibm_database_mongodb_enterprise_test.go @@ -5,7 +5,6 @@ package database_test import ( "fmt" - "regexp" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" @@ -41,10 +40,6 @@ func TestAccIBMMongoDBEnterpriseDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "61440"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, @@ -62,13 +57,6 @@ func TestAccIBMMongoDBEnterpriseDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), resource.TestCheckResourceAttr(name, "users.1.type", "ops_manager"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.scheme", "mongodb"), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.database", regexp.MustCompile("[-a-z0-9]+")), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, @@ -84,7 +72,6 @@ func TestAccIBMMongoDBEnterpriseDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "49152"), resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "122880"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, @@ -93,7 +80,7 @@ func TestAccIBMMongoDBEnterpriseDatabaseInstanceBasic(t *testing.T) { ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{ - "wait_time_minutes", "adminpassword", "connectionstrings.0.queryoptions", "group"}, + "wait_time_minutes", "adminpassword", "group"}, }, }, }) @@ -124,13 +111,9 @@ func TestAccIBMMongoDBEnterpriseDatabaseInstanceGroupBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "service_endpoints", "public"), resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "49152"), resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "61440"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.name", "admin"), resource.TestCheckResourceAttr(name, "groups.0.count", "3"), resource.TestCheckResourceAttr(name, "groups.1.count", "1"), resource.TestCheckResourceAttr(name, "groups.2.count", "1"), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, diff --git a/ibm/service/database/resource_ibm_database_mongodb_sharding_test.go b/ibm/service/database/resource_ibm_database_mongodb_sharding_test.go index 20b90c13a5..42d8de0be0 100644 --- a/ibm/service/database/resource_ibm_database_mongodb_sharding_test.go +++ b/ibm/service/database/resource_ibm_database_mongodb_sharding_test.go @@ -5,7 +5,6 @@ package database_test import ( "fmt" - "regexp" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" @@ -40,10 +39,6 @@ func TestAccIBMMongoDBShardingDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "122880"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), ), }, { @@ -58,9 +53,6 @@ func TestAccIBMMongoDBShardingDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "245760"), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.scheme", "mongodb"), ), }, { @@ -75,7 +67,6 @@ func TestAccIBMMongoDBShardingDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "245760"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, }, diff --git a/ibm/service/database/resource_ibm_database_mongodb_test.go b/ibm/service/database/resource_ibm_database_mongodb_test.go index 7f4d31b37b..d753670559 100644 --- a/ibm/service/database/resource_ibm_database_mongodb_test.go +++ b/ibm/service/database/resource_ibm_database_mongodb_test.go @@ -5,7 +5,6 @@ package database_test import ( "fmt" - "regexp" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" @@ -40,10 +39,6 @@ func TestAccIBMDatabaseInstanceMongodbBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "users.#", "1"), resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "12288"), resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "30720"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), ), }, { @@ -58,9 +53,6 @@ func TestAccIBMDatabaseInstanceMongodbBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "users.#", "2"), resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "15360"), resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "30720"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.scheme", "mongodb"), ), }, { @@ -75,7 +67,6 @@ func TestAccIBMDatabaseInstanceMongodbBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "30720"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, // { @@ -117,7 +108,7 @@ func TestAccIBMDatabaseInstanceMongodbImport(t *testing.T) { ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{ - "wait_time_minutes", "connectionstrings"}, + "wait_time_minutes"}, }, }, }) diff --git a/ibm/service/database/resource_ibm_database_mysql_test.go b/ibm/service/database/resource_ibm_database_mysql_test.go index 3a1f7e4b1f..7a10a1c06c 100644 --- a/ibm/service/database/resource_ibm_database_mysql_test.go +++ b/ibm/service/database/resource_ibm_database_mysql_test.go @@ -5,7 +5,6 @@ package database_test import ( "fmt" - "regexp" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" @@ -40,10 +39,6 @@ func TestAccIBMMysqlDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "service_endpoints", "public"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, @@ -60,13 +55,6 @@ func TestAccIBMMysqlDatabaseInstanceBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "service_endpoints", "public-and-private"), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.scheme", "mysql"), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.database", regexp.MustCompile("[-a-z0-9]+")), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, diff --git a/ibm/service/database/resource_ibm_database_postgresql_test.go b/ibm/service/database/resource_ibm_database_postgresql_test.go index 7d11ef0837..f0ac0f50aa 100644 --- a/ibm/service/database/resource_ibm_database_postgresql_test.go +++ b/ibm/service/database/resource_ibm_database_postgresql_test.go @@ -6,7 +6,6 @@ package database_test import ( "fmt" "reflect" - "regexp" "strings" "testing" @@ -63,10 +62,6 @@ func TestAccIBMDatabaseInstancePostgresBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "service_endpoints", "public"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), resource.TestCheckResourceAttr(name, "tags.#", "1"), resource.TestCheckResourceAttr(name, "logical_replication_slot.#", "1"), ), @@ -84,13 +79,6 @@ func TestAccIBMDatabaseInstancePostgresBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "service_endpoints", "public-and-private"), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "4"), - resource.TestCheckResourceAttr(name, "connectionstrings.3.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.scheme", "postgres"), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.database", regexp.MustCompile("[-a-z0-9]+")), resource.TestCheckResourceAttr(name, "tags.#", "1"), resource.TestCheckResourceAttr(name, "logical_replication_slot.#", "2"), ), @@ -133,10 +121,6 @@ func TestAccIBMDatabaseInstancePostgresGroup(t *testing.T) { resource.TestCheckResourceAttr(name, "service_endpoints", "public"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.1.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, @@ -155,13 +139,6 @@ func TestAccIBMDatabaseInstancePostgresGroup(t *testing.T) { resource.TestCheckResourceAttr(name, "service_endpoints", "public-and-private"), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.scheme", "postgres"), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certname", regexp.MustCompile("[-a-z0-9]*")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.certbase64", regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")), - resource.TestMatchResourceAttr(name, "connectionstrings.0.database", regexp.MustCompile("[-a-z0-9]+")), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, @@ -179,7 +156,6 @@ func TestAccIBMDatabaseInstancePostgresGroup(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "6"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, @@ -197,7 +173,6 @@ func TestAccIBMDatabaseInstancePostgresGroup(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.cpu.0.allocation_count", "9"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), resource.TestCheckResourceAttr(name, "tags.#", "1"), ), }, diff --git a/ibm/service/database/resource_ibm_database_rabbitmq_test.go b/ibm/service/database/resource_ibm_database_rabbitmq_test.go index 7fa54800cf..0a5ca0befa 100644 --- a/ibm/service/database/resource_ibm_database_rabbitmq_test.go +++ b/ibm/service/database/resource_ibm_database_rabbitmq_test.go @@ -39,10 +39,6 @@ func TestAccIBMDatabaseInstance_Rabbitmq_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "3072"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), resource.TestCheckResourceAttr(name, "users.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.1.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.database", ""), ), }, { @@ -57,8 +53,6 @@ func TestAccIBMDatabaseInstance_Rabbitmq_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "6144"), resource.TestCheckResourceAttr(name, "allowlist.#", "2"), resource.TestCheckResourceAttr(name, "users.#", "2"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "3"), - resource.TestCheckResourceAttr(name, "connectionstrings.2.name", "admin"), ), }, { @@ -73,7 +67,6 @@ func TestAccIBMDatabaseInstance_Rabbitmq_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "6144"), resource.TestCheckResourceAttr(name, "allowlist.#", "0"), resource.TestCheckResourceAttr(name, "users.#", "0"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), ), }, // { diff --git a/ibm/service/database/resource_ibm_database_redis_test.go b/ibm/service/database/resource_ibm_database_redis_test.go index a71df9d4ce..47ffa86081 100644 --- a/ibm/service/database/resource_ibm_database_redis_test.go +++ b/ibm/service/database/resource_ibm_database_redis_test.go @@ -5,7 +5,6 @@ package database_test import ( "fmt" - "regexp" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" @@ -39,10 +38,6 @@ func TestAccIBMDatabaseInstance_Redis_Basic(t *testing.T) { resource.TestCheckResourceAttr(name, "groups.0.memory.0.allocation_mb", "8192"), resource.TestCheckResourceAttr(name, "groups.0.disk.0.allocation_mb", "2048"), resource.TestCheckResourceAttr(name, "allowlist.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.#", "1"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.name", "admin"), - resource.TestCheckResourceAttr(name, "connectionstrings.0.hosts.#", "1"), - resource.TestMatchResourceAttr(name, "connectionstrings.0.database", regexp.MustCompile("[-a-z0-9]+")), ), }, { diff --git a/ibm/service/eventnotification/data_source_ibm_en_destination_cf.go b/ibm/service/eventnotification/data_source_ibm_en_destination_cf.go index a99caeeb46..cda70209db 100644 --- a/ibm/service/eventnotification/data_source_ibm_en_destination_cf.go +++ b/ibm/service/eventnotification/data_source_ibm_en_destination_cf.go @@ -96,6 +96,7 @@ func DataSourceIBMEnCFDestination() *schema.Resource { }, }, }, + DeprecationMessage: "The IBM Cloud Function destination has been deprectated", } } diff --git a/ibm/service/eventnotification/data_source_ibm_en_metrics.go b/ibm/service/eventnotification/data_source_ibm_en_metrics.go new file mode 100644 index 0000000000..87b639fbae --- /dev/null +++ b/ibm/service/eventnotification/data_source_ibm_en_metrics.go @@ -0,0 +1,227 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package eventnotification + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/event-notifications-go-admin-sdk/eventnotificationsv1" +) + +func DataSourceIBMEnMetrics() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMEnMetricsRead, + + Schema: map[string]*schema.Schema{ + "instance_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Unique identifier for IBM Cloud Event Notifications instance.", + }, + "destination_type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Destination type. Allowed values are [smtp_custom].", + }, + "gte": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "GTE (greater than equal), start timestamp in UTC.", + }, + "lte": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "LTE (less than equal), end timestamp in UTC.", + }, + "destination_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Unique identifier for Destination.", + }, + "source_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Unique identifier for Source.", + }, + "email_to": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Receiver email id.", + }, + "notification_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Notification Id.", + }, + "subject": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Email subject.", + }, + "metrics": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "array of metrics.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "key.", + }, + "doc_count": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "doc count.", + }, + "histogram": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "Payload describing histogram.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "buckets": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "List of buckets.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "doc_count": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "Total count.", + }, + "key_as_string": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Timestamp.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMEnMetricsRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + eventNotificationsClient, err := meta.(conns.ClientSession).EventNotificationsApiV1() + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_en_metrics", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getMetricsOptions := &eventnotificationsv1.GetMetricsOptions{} + + getMetricsOptions.SetInstanceID(d.Get("instance_id").(string)) + getMetricsOptions.SetDestinationType(d.Get("destination_type").(string)) + getMetricsOptions.SetGte(d.Get("gte").(string)) + getMetricsOptions.SetLte(d.Get("lte").(string)) + if _, ok := d.GetOk("destination_id"); ok { + getMetricsOptions.SetDestinationID(d.Get("destination_id").(string)) + } + if _, ok := d.GetOk("source_id"); ok { + getMetricsOptions.SetSourceID(d.Get("source_id").(string)) + } + if _, ok := d.GetOk("email_to"); ok { + getMetricsOptions.SetEmailTo(d.Get("email_to").(string)) + } + if _, ok := d.GetOk("notification_id"); ok { + getMetricsOptions.SetNotificationID(d.Get("notification_id").(string)) + } + if _, ok := d.GetOk("subject"); ok { + getMetricsOptions.SetSubject(d.Get("subject").(string)) + } + + metricsres, _, err := eventNotificationsClient.GetMetricsWithContext(context, getMetricsOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetMetricsWithContext failed: %s", err.Error()), "(Data) ibm_en_metrics", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMEnMetricsID(d)) + + metrics := []map[string]interface{}{} + if metricsres.Metrics != nil { + for _, modelItem := range metricsres.Metrics { + modelMap, err := dataSourceIBMEnMetricsMetricToMap(&modelItem) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_en_metrics", "read") + return tfErr.GetDiag() + } + metrics = append(metrics, modelMap) + } + } + if err = d.Set("metrics", metrics); err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting metrics: %s", err), "(Data) ibm_en_metrics", "read") + return tfErr.GetDiag() + } + + return nil +} + +// dataSourceIBMEnMetricsID returns a reasonable ID for the list. +func dataSourceIBMEnMetricsID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func dataSourceIBMEnMetricsMetricToMap(model *eventnotificationsv1.Metric) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Key != nil { + modelMap["key"] = model.Key + } + if model.DocCount != nil { + modelMap["doc_count"] = flex.IntValue(model.DocCount) + } + if model.Histogram != nil { + histogramMap, err := dataSourceIBMEnMetricsHistrogramToMap(model.Histogram) + if err != nil { + return modelMap, err + } + modelMap["histogram"] = []map[string]interface{}{histogramMap} + } + return modelMap, nil +} + +func dataSourceIBMEnMetricsHistrogramToMap(model *eventnotificationsv1.Histrogram) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Buckets != nil { + buckets := []map[string]interface{}{} + for _, bucketsItem := range model.Buckets { + bucketsItemMap, err := dataSourceIBMEnMetricsBucketsToMap(&bucketsItem) + if err != nil { + return modelMap, err + } + buckets = append(buckets, bucketsItemMap) + } + modelMap["buckets"] = buckets + } + return modelMap, nil +} + +func dataSourceIBMEnMetricsBucketsToMap(model *eventnotificationsv1.Buckets) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.DocCount != nil { + modelMap["doc_count"] = flex.IntValue(model.DocCount) + } + if model.KeyAsString != nil { + modelMap["key_as_string"] = model.KeyAsString.String() + } + return modelMap, nil +} diff --git a/ibm/service/eventnotification/data_source_ibm_en_metrics_test.go b/ibm/service/eventnotification/data_source_ibm_en_metrics_test.go new file mode 100644 index 0000000000..f16dae51f6 --- /dev/null +++ b/ibm/service/eventnotification/data_source_ibm_en_metrics_test.go @@ -0,0 +1,49 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package eventnotification_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" +) + +func TestAccIBMEnMetricsDataSourceBasic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMEnMetricsDataSourceConfigBasic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_en_metrics.en_metrics_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_en_metrics.en_metrics_instance", "instance_id"), + resource.TestCheckResourceAttrSet("data.ibm_en_metrics.en_metrics_instance", "destination_type"), + resource.TestCheckResourceAttrSet("data.ibm_en_metrics.en_metrics_instance", "gte"), + resource.TestCheckResourceAttrSet("data.ibm_en_metrics.en_metrics_instance", "lte"), + resource.TestCheckResourceAttrSet("data.ibm_en_metrics.en_metrics_instance", "metrics.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMEnMetricsDataSourceConfigBasic() string { + return fmt.Sprintf(` + data "ibm_en_metrics" "en_metrics_instance" { + instance_id = "instance_id" + destination_type = "smtp_custom" + gte = "gte" + lte = "lte" + destination_id = "destination_id" + source_id = "source_id" + email_to = "email_to" + notification_id = "notification_id" + subject = "subject" + } + `) +} diff --git a/ibm/service/eventnotification/data_source_ibm_en_smtp_allowed_ips.go b/ibm/service/eventnotification/data_source_ibm_en_smtp_allowed_ips.go new file mode 100644 index 0000000000..1176bb4926 --- /dev/null +++ b/ibm/service/eventnotification/data_source_ibm_en_smtp_allowed_ips.go @@ -0,0 +1,97 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package eventnotification + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/event-notifications-go-admin-sdk/eventnotificationsv1" +) + +func DataSourceIBMEnSMTPAllowedIps() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMEnSMTPAllowedIpsRead, + + Schema: map[string]*schema.Schema{ + "instance_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Unique identifier for IBM Cloud Event Notifications instance.", + }, + "en_smtp_allowed_ips_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Unique identifier for SMTP.", + }, + "subnets": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The SMTP allowed Ips.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "updated_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Updated at.", + }, + }, + } +} + +func dataSourceIBMEnSMTPAllowedIpsRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + eventNotificationsClient, err := meta.(conns.ClientSession).EventNotificationsApiV1() + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_en_smtp_allowed_ips", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getSMTPAllowedIpsOptions := &eventnotificationsv1.GetSMTPAllowedIpsOptions{} + + getSMTPAllowedIpsOptions.SetInstanceID(d.Get("instance_id").(string)) + getSMTPAllowedIpsOptions.SetID(d.Get("en_smtp_allowed_ips_id").(string)) + + smtpAllowedIPs, _, err := eventNotificationsClient.GetSMTPAllowedIpsWithContext(context, getSMTPAllowedIpsOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetSMTPAllowedIpsWithContext failed: %s", err.Error()), "(Data) ibm_en_smtp_allowed_ips", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMEnSMTPAllowedIpsID(d)) + + if err = d.Set("updated_at", flex.DateTimeToString(smtpAllowedIPs.UpdatedAt)); err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting updated_at: %s", err), "(Data) ibm_en_smtp_allowed_ips", "read") + return tfErr.GetDiag() + } + + if smtpAllowedIPs.Subnets != nil { + err = d.Set("subnets", smtpAllowedIPs.Subnets) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error setting subnets %s", err)) + } + } + + // if err = d.Set("subnets", flex.ToString(smtpAllowedIPs.Subnets)); err != nil { + // tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting subnets: %s", err), "(Data) ibm_en_smtp_allowed_ips", "read") + // return tfErr.GetDiag() + // } + + return nil +} + +// dataSourceIBMEnSMTPAllowedIpsID returns a reasonable ID for the list. +func dataSourceIBMEnSMTPAllowedIpsID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} diff --git a/ibm/service/eventnotification/data_source_ibm_en_smtp_allowed_ips_test.go b/ibm/service/eventnotification/data_source_ibm_en_smtp_allowed_ips_test.go new file mode 100644 index 0000000000..4525946230 --- /dev/null +++ b/ibm/service/eventnotification/data_source_ibm_en_smtp_allowed_ips_test.go @@ -0,0 +1,41 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package eventnotification_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" +) + +func TestAccIBMEnSMTPAllowedIpsDataSourceBasic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMEnSMTPAllowedIpsDataSourceConfigBasic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_en_smtp_allowed_ips.en_smtp_allowed_ips_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_en_smtp_allowed_ips.en_smtp_allowed_ips_instance", "instance_id"), + resource.TestCheckResourceAttrSet("data.ibm_en_smtp_allowed_ips.en_smtp_allowed_ips_instance", "en_smtp_allowed_ips_id"), + resource.TestCheckResourceAttrSet("data.ibm_en_smtp_allowed_ips.en_smtp_allowed_ips_instance", "subnets.#"), + resource.TestCheckResourceAttrSet("data.ibm_en_smtp_allowed_ips.en_smtp_allowed_ips_instance", "updated_at"), + ), + }, + }, + }) +} + +func testAccCheckIBMEnSMTPAllowedIpsDataSourceConfigBasic() string { + return fmt.Sprintf(` + data "ibm_en_smtp_allowed_ips" "en_smtp_allowed_ips_instance" { + instance_id = "instance_id" + id = "id" + } + `) +} diff --git a/ibm/service/eventnotification/resource_ibm_en_destination_cf.go b/ibm/service/eventnotification/resource_ibm_en_destination_cf.go index bf674f84b1..d0ad167d53 100644 --- a/ibm/service/eventnotification/resource_ibm_en_destination_cf.go +++ b/ibm/service/eventnotification/resource_ibm_en_destination_cf.go @@ -102,6 +102,7 @@ func ResourceIBMEnCFDestination() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, }, }, + DeprecationMessage: "The IBM Cloud Function destination has been deprectated", } } diff --git a/ibm/service/eventnotification/resource_ibm_en_integration_cos.go b/ibm/service/eventnotification/resource_ibm_en_integration_cos.go index 662df4ad27..50557684ba 100644 --- a/ibm/service/eventnotification/resource_ibm_en_integration_cos.go +++ b/ibm/service/eventnotification/resource_ibm_en_integration_cos.go @@ -135,6 +135,13 @@ func resourceIBMEnCOSIntegrationRead(context context.Context, d *schema.Resource return diag.FromErr(fmt.Errorf("[ERROR] Error setting type: %s", err)) } + if result.Metadata != nil { + err = d.Set("metadata", enCOSIntegrationFlattenMetadata(result.Metadata)) + if err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error setting Metadata %s", err)) + } + } + if err = d.Set("updated_at", flex.DateTimeToString(result.UpdatedAt)); err != nil { return diag.FromErr(fmt.Errorf("[ERROR] Error setting updated_at: %s", err)) } diff --git a/ibm/service/eventnotification/resource_ibm_en_slack_template.go b/ibm/service/eventnotification/resource_ibm_en_slack_template.go index f60b131bd3..6d5fddaa5f 100644 --- a/ibm/service/eventnotification/resource_ibm_en_slack_template.go +++ b/ibm/service/eventnotification/resource_ibm_en_slack_template.go @@ -50,12 +50,12 @@ func ResourceIBMEnSlackTemplate() *schema.Resource { "params": { Type: schema.TypeList, MaxItems: 1, - Optional: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "body": { Type: schema.TypeString, - Optional: true, + Required: true, Description: "The Slack Template body.", }, }, @@ -103,7 +103,7 @@ func resourceIBMEnSlackTemplateCreate(context context.Context, d *schema.Resourc options.SetDescription(d.Get("description").(string)) } - params := EmailTemplateParamsMap(d.Get("params").(map[string]interface{})) + params := EmailTemplateParamsMap(d.Get("params.0").(map[string]interface{})) options.SetParams(¶ms) result, response, err := enClient.CreateTemplateWithContext(context, options) diff --git a/ibm/service/eventnotification/resource_ibm_en_smtp_setting.go b/ibm/service/eventnotification/resource_ibm_en_smtp_setting.go index d585bd5e2e..538f3b49bd 100644 --- a/ibm/service/eventnotification/resource_ibm_en_smtp_setting.go +++ b/ibm/service/eventnotification/resource_ibm_en_smtp_setting.go @@ -4,23 +4,12 @@ package eventnotification import ( - "context" - "fmt" - - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" - en "github.com/IBM/event-notifications-go-admin-sdk/eventnotificationsv1" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) func ResourceIBMEnSMTPSetting() *schema.Resource { return &schema.Resource{ - CreateContext: resourceIBMEnSMTPSettingCreate, - ReadContext: resourceIBMEnSMTPSettingRead, - UpdateContext: resourceIBMEnSMTPSettingUpdate, - DeleteContext: resourceIBMEnSMTPSettingsDelete, - Importer: &schema.ResourceImporter{}, + Importer: &schema.ResourceImporter{}, Schema: map[string]*schema.Schema{ "instance_guid": { @@ -50,110 +39,6 @@ func ResourceIBMEnSMTPSetting() *schema.Resource { }, }, }, + DeprecationMessage: "The resource has been deprecated since the support for legacy allowlisting has been deprecated. The support has been enabled via Context-based-restrictions. For detailed information, please refer here: https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-smtp-configurations#en-smtp-configurations-cbr", } } - -func resourceIBMEnSMTPSettingCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - enClient, err := meta.(conns.ClientSession).EventNotificationsApiV1() - if err != nil { - return diag.FromErr(err) - } - - options := &en.UpdateSMTPAllowedIpsOptions{} - - options.SetInstanceID(d.Get("instance_guid").(string)) - options.SetID(d.Get("smtp_config_id").(string)) - - subnets := AllowedIPSMap(d.Get("settings.0").(map[string]interface{})) - options.SetSubnets(subnets) - - _, response, err := enClient.UpdateSMTPAllowedIpsWithContext(context, options) - if err != nil { - return diag.FromErr(fmt.Errorf("UpdateSMTPAllowedIpsWithContext failed %s\n%s", err, response)) - } - - d.SetId(fmt.Sprintf("%s/%s", *options.InstanceID, *options.ID)) - - return resourceIBMEnSMTPSettingRead(context, d, meta) -} - -func resourceIBMEnSMTPSettingRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - enClient, err := meta.(conns.ClientSession).EventNotificationsApiV1() - if err != nil { - return diag.FromErr(err) - } - - options := &en.GetSMTPAllowedIpsOptions{} - - parts, err := flex.SepIdParts(d.Id(), "/") - if err != nil { - return diag.FromErr(err) - } - - options.SetInstanceID(parts[0]) - options.SetID(parts[1]) - - _, response, err := enClient.GetSMTPAllowedIpsWithContext(context, options) - if err != nil { - return diag.FromErr(fmt.Errorf("GetSMTPAllowedIpsWithContext failed %s\n%s", err, response)) - } - - if err = d.Set("instance_guid", options.InstanceID); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error setting instance_guid: %s", err)) - } - - if err = d.Set("smtp_config_id", options.ID); err != nil { - return diag.FromErr(fmt.Errorf("[ERROR] Error smtp_config_id: %s", err)) - } - - return nil -} - -func resourceIBMEnSMTPSettingUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - enClient, err := meta.(conns.ClientSession).EventNotificationsApiV1() - if err != nil { - return diag.FromErr(err) - } - - options := &en.UpdateSMTPAllowedIpsOptions{} - - options.SetInstanceID(d.Get("instance_guid").(string)) - options.SetID(d.Get("smtp_config_id").(string)) - - parts, err := flex.SepIdParts(d.Id(), "/") - if err != nil { - return diag.FromErr(err) - } - - options.SetInstanceID(parts[0]) - options.SetID(parts[1]) - - subnets := AllowedIPSMap(d.Get("settings.0").(map[string]interface{})) - options.SetSubnets(subnets) - - _, response, err := enClient.UpdateSMTPAllowedIpsWithContext(context, options) - if err != nil { - return diag.FromErr(fmt.Errorf("UpdateSMTPAllowedIpsWithContext failed %s\n%s", err, response)) - } - - return resourceIBMEnSMTPSettingRead(context, d, meta) -} - -func AllowedIPSMap(allowedip map[string]interface{}) []string { - - ips := []string{} - if allowedip["subnets"] != nil { - - for _, ip := range allowedip["subnets"].([]interface{}) { - ips = append(ips, ip.(string)) - } - - } - - return ips -} - -func resourceIBMEnSMTPSettingsDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - - return nil -} diff --git a/ibm/service/eventstreams/resource_ibm_event_streams_topic.go b/ibm/service/eventstreams/resource_ibm_event_streams_topic.go index a682866ea8..bc59c8f770 100644 --- a/ibm/service/eventstreams/resource_ibm_event_streams_topic.go +++ b/ibm/service/eventstreams/resource_ibm_event_streams_topic.go @@ -8,6 +8,7 @@ import ( "fmt" "log" "os" + "slices" "strings" "time" @@ -288,6 +289,7 @@ func createSaramaAdminClient(d *schema.ResourceData, meta interface{}) (sarama.C d.Set("kafka_http_url", adminURL) log.Printf("[INFO] createSaramaAdminClient kafka_http_url is set to %s", adminURL) brokerAddress := flex.ExpandStringList(instance.Extensions["kafka_brokers_sasl"].([]interface{})) + slices.Sort(brokerAddress) d.Set("kafka_brokers_sasl", brokerAddress) log.Printf("[INFO] createSaramaAdminClient kafka_brokers_sasl is set to %s", brokerAddress) tenantID := strings.TrimPrefix(strings.Split(adminURL, ".")[0], "https://") diff --git a/ibm/service/eventstreams/resource_ibm_event_streams_topic_test.go b/ibm/service/eventstreams/resource_ibm_event_streams_topic_test.go index ba446d6eff..680fd68775 100644 --- a/ibm/service/eventstreams/resource_ibm_event_streams_topic_test.go +++ b/ibm/service/eventstreams/resource_ibm_event_streams_topic_test.go @@ -302,7 +302,7 @@ func createEventStreamsTopicResourceWithConfig(createInstance bool, topicName st } func testAccCheckIBMEventStreamsInstanceDestroy(s *terraform.State) error { - rsContClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).ResourceControllerAPI() + rsContClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).ResourceControllerAPIV2() if err != nil { return err } @@ -311,16 +311,17 @@ func testAccCheckIBMEventStreamsInstanceDestroy(s *terraform.State) error { continue } instanceID := rs.Primary.ID - instance, err := rsContClient.ResourceServiceInstance().GetInstance(instanceID) - - if err == nil { - if !reflect.DeepEqual(instance, models.ServiceInstance{}) && instance.State == "active" { - return fmt.Errorf("Instance still exists: %s", rs.Primary.ID) - } - } else { - if !strings.Contains(err.Error(), "404") { - return fmt.Errorf("[ERROR] Error checking if instance (%s) has been destroyed: %s", rs.Primary.ID, err) + instance, err := rsContClient.ResourceServiceInstanceV2().GetInstance(instanceID) + if err != nil { + if strings.Contains(err.Error(), "404") { + return nil } + return fmt.Errorf("[ERROR] Error checking if instance (%s) has been destroyed: %s", rs.Primary.ID, err) + } + + if !reflect.DeepEqual(instance, models.ServiceInstanceV2{}) && + instance.State != "removed" && instance.State != "pending_reclamation" { + return fmt.Errorf("[ERROR] Instance (%s) is not removed", rs.Primary.ID) } } return nil diff --git a/ibm/service/iamidentity/resource_ibm_iam_trusted_profile_template.go b/ibm/service/iamidentity/resource_ibm_iam_trusted_profile_template.go index b890b7f9fc..586d06d2ec 100644 --- a/ibm/service/iamidentity/resource_ibm_iam_trusted_profile_template.go +++ b/ibm/service/iamidentity/resource_ibm_iam_trusted_profile_template.go @@ -6,9 +6,10 @@ package iamidentity import ( "context" "fmt" + "log" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "log" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" @@ -152,7 +153,7 @@ func ResourceIBMTrustedProfileTemplate() *schema.Resource { }, }, "policy_template_references": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Description: "Existing policy templates that you can reference to assign access in the trusted profile component.", Elem: &schema.Resource{ @@ -291,7 +292,7 @@ func resourceIBMTrustedProfileTemplateCreate(context context.Context, d *schema. } if _, ok := d.GetOk("policy_template_references"); ok { var policyTemplateReferences []iamidentityv1.PolicyTemplateReference - for _, v := range d.Get("policy_template_references").([]interface{}) { + for _, v := range d.Get("policy_template_references").(*schema.Set).List() { value := v.(map[string]interface{}) policyTemplateReferencesItem, err := resourceIBMTrustedProfileTemplateMapToPolicyTemplateReference(value) if err != nil { @@ -356,7 +357,7 @@ func resourceIBMTrustedProfileTemplateCreateVersion(context context.Context, d * } if _, ok := d.GetOk("policy_template_references"); ok { var policyTemplateReferences []iamidentityv1.PolicyTemplateReference - for _, v := range d.Get("policy_template_references").([]interface{}) { + for _, v := range d.Get("policy_template_references").(*schema.Set).List() { value := v.(map[string]interface{}) policyTemplateReferencesItem, err := resourceIBMTrustedProfileTemplateMapToPolicyTemplateReference(value) if err != nil { @@ -553,7 +554,7 @@ func resourceIBMTrustedProfileTemplateUpdate(context context.Context, d *schema. } if d.HasChange("policy_template_references") { var policyTemplateReferences []iamidentityv1.PolicyTemplateReference - for _, v := range d.Get("policy_template_references").([]interface{}) { + for _, v := range d.Get("policy_template_references").(*schema.Set).List() { value := v.(map[string]interface{}) policyTemplateReferencesItem, err := resourceIBMTrustedProfileTemplateMapToPolicyTemplateReference(value) if err != nil { diff --git a/ibm/service/kms/data_source_ibm_kms_key_rings.go b/ibm/service/kms/data_source_ibm_kms_key_rings.go index c3b6bb0483..d426c8e8ce 100644 --- a/ibm/service/kms/data_source_ibm_kms_key_rings.go +++ b/ibm/service/kms/data_source_ibm_kms_key_rings.go @@ -67,7 +67,7 @@ func dataSourceIBMKMSKeyRingsRead(d *schema.ResourceData, meta interface{}) erro if err != nil || keys == nil { return fmt.Errorf("[ERROR] Get Key Rings failed with error: %s", err) } - if keys == nil || keys.KeyRings == nil || len(keys.KeyRings) == 0 { + if keys.KeyRings == nil || len(keys.KeyRings) == 0 { return fmt.Errorf("[ERROR] No key Rings in instance %s", instanceID) } diff --git a/ibm/service/kms/data_source_ibm_kms_kmip_adapter.go b/ibm/service/kms/data_source_ibm_kms_kmip_adapter.go index c67105bcc3..9a50c3ab34 100644 --- a/ibm/service/kms/data_source_ibm_kms_kmip_adapter.go +++ b/ibm/service/kms/data_source_ibm_kms_kmip_adapter.go @@ -37,22 +37,22 @@ func dataSourceIBMKMSKmipAdapterBaseSchema() map[string]*schema.Schema { Computed: true, Description: "The data specific to the KMIP Adapter profile", }, - "created_by": &schema.Schema{ + "created_by": { Type: schema.TypeString, Computed: true, Description: "The unique identifier that is associated with the entity that created the adapter.", }, - "created_at": &schema.Schema{ + "created_at": { Type: schema.TypeString, Computed: true, Description: "The date when a resource was created. The date format follows RFC 3339.", }, - "updated_by": &schema.Schema{ + "updated_by": { Type: schema.TypeString, Computed: true, Description: "The unique identifier that is associated with the entity that updated the adapter.", }, - "updated_at": &schema.Schema{ + "updated_at": { Type: schema.TypeString, Computed: true, Description: "The date when a resource was updated. The date format follows RFC 3339.", diff --git a/ibm/service/kms/data_source_ibm_kms_kmip_adapters.go b/ibm/service/kms/data_source_ibm_kms_kmip_adapters.go index a73f672dd7..7b65a24558 100644 --- a/ibm/service/kms/data_source_ibm_kms_kmip_adapters.go +++ b/ibm/service/kms/data_source_ibm_kms_kmip_adapters.go @@ -68,9 +68,6 @@ func dataSourceIBMKMSKmipAdaptersList(d *schema.ResourceData, meta interface{}) if err != nil { return err } - if err != nil { - return err - } // call GetKMIPAdapters api opts := &kp.ListKmipAdaptersOptions{} diff --git a/ibm/service/kms/data_source_ibm_kms_kmip_client_certificate.go b/ibm/service/kms/data_source_ibm_kms_kmip_client_certificate.go index 8e43ca4b69..3ebd9dbe3f 100644 --- a/ibm/service/kms/data_source_ibm_kms_kmip_client_certificate.go +++ b/ibm/service/kms/data_source_ibm_kms_kmip_client_certificate.go @@ -29,12 +29,12 @@ func dataSourceIBMKmsKMIPClientCertificateBaseSchema() map[string]*schema.Schema Sensitive: true, Description: "The PEM-encoded contents of the certificate", }, - "created_by": &schema.Schema{ + "created_by": { Type: schema.TypeString, Computed: true, Description: "The unique identifier that is associated with the entity that created the adapter.", }, - "created_at": &schema.Schema{ + "created_at": { Type: schema.TypeString, Computed: true, Description: "The date when a resource was created. The date format follows RFC 3339.", @@ -101,7 +101,7 @@ func dataSourceIBMKmsKMIPClientCertRead(d *schema.ResourceData, meta interface{} // get adapterID and certID nameOrID, hasID := d.GetOk("adapter_id") if !hasID { - nameOrID, hasID = d.GetOk("adapter_name") + nameOrID = d.Get("adapter_name") } adapterNameOrID := nameOrID.(string) diff --git a/ibm/service/kms/data_source_ibm_kms_kmip_object.go b/ibm/service/kms/data_source_ibm_kms_kmip_object.go index 6d75661535..32f1035421 100644 --- a/ibm/service/kms/data_source_ibm_kms_kmip_object.go +++ b/ibm/service/kms/data_source_ibm_kms_kmip_object.go @@ -30,47 +30,47 @@ func dataSourceIBMKMSKMIPObjectBaseSchema(isForList bool) map[string]*schema.Sch Computed: true, Description: "The state of the KMIP object", }, - "created_by": &schema.Schema{ + "created_by": { Type: schema.TypeString, Computed: true, Description: "The unique identifier that is associated with the entity that created the adapter.", }, - "created_at": &schema.Schema{ + "created_at": { Type: schema.TypeString, Computed: true, Description: "The date when a resource was created. The date format follows RFC 3339.", }, - "created_by_cert_id": &schema.Schema{ + "created_by_cert_id": { Type: schema.TypeString, Computed: true, Description: "The ID of the certificate that created the object", }, - "updated_by": &schema.Schema{ + "updated_by": { Type: schema.TypeString, Computed: true, Description: "The unique identifier that is associated with the entity that updated the adapter.", }, - "updated_at": &schema.Schema{ + "updated_at": { Type: schema.TypeString, Computed: true, Description: "The date when a resource was updated. The date format follows RFC 3339.", }, - "updated_by_cert_id": &schema.Schema{ + "updated_by_cert_id": { Type: schema.TypeString, Computed: true, Description: "The ID of the certificate that updated the object", }, - "destroyed_by": &schema.Schema{ + "destroyed_by": { Type: schema.TypeString, Computed: true, Description: "The unique identifier that is associated with the entity that destroyed the adapter.", }, - "destroyed_at": &schema.Schema{ + "destroyed_at": { Type: schema.TypeString, Computed: true, Description: "The date when a resource was destroyed. The date format follows RFC 3339.", }, - "destroyed_by_cert_id": &schema.Schema{ + "destroyed_by_cert_id": { Type: schema.TypeString, Computed: true, Description: "The ID of the certificate that destroyed the object", @@ -92,7 +92,7 @@ func DataSourceIBMKMSKMIPObject() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - Description: "The id of the KMIP adapter that contains the cert", + Description: "The id of the KMIP adapter that contains the kmip object", ForceNew: true, ExactlyOneOf: []string{"adapter_id", "adapter_name"}, } @@ -100,7 +100,7 @@ func DataSourceIBMKMSKMIPObject() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - Description: "The name of the KMIP adapter that contains the cert", + Description: "The name of the KMIP adapter that contains the kmip object", ForceNew: true, ExactlyOneOf: []string{"adapter_id", "adapter_name"}, } diff --git a/ibm/service/kms/data_source_ibm_kms_kmip_objects.go b/ibm/service/kms/data_source_ibm_kms_kmip_objects.go index de470a8481..54f196d253 100644 --- a/ibm/service/kms/data_source_ibm_kms_kmip_objects.go +++ b/ibm/service/kms/data_source_ibm_kms_kmip_objects.go @@ -140,6 +140,9 @@ func dataSourceIBMKmsKMIPObjectList(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("[ERROR] Error setting adapter_name: %s", err) } objs, err := kpAPI.GetKMIPObjects(ctx, adapterNameOrID, opts) + if err != nil { + return fmt.Errorf("[ERROR] Error while retriving KMIP objects associated with adapter ID '%s': %v", adapter.ID, err) + } objsList := objs.Objects // set computed values mySlice := make([]map[string]interface{}, 0, len(objsList)) diff --git a/ibm/service/kms/resource_ibm_kms_key.go b/ibm/service/kms/resource_ibm_kms_key.go index d233d9647f..cc41d005cf 100644 --- a/ibm/service/kms/resource_ibm_kms_key.go +++ b/ibm/service/kms/resource_ibm_kms_key.go @@ -256,7 +256,7 @@ func resourceIBMKmsKeyDelete(d *schema.ResourceData, meta interface{}) error { if err1 != nil { registrations := d.Get("registrations").([]interface{}) var registrationLog error - if registrations != nil && len(registrations) > 0 { + if len(registrations) > 0 { resourceCrns := make([]string, 0) for _, registration := range registrations { r := registration.(map[string]interface{}) @@ -281,9 +281,10 @@ func resourceIBMKmsKeyExists(d *schema.ResourceData, meta interface{}) (bool, er _, err = kpAPI.GetKey(context.Background(), keyid) if err != nil { - kpError := err.(*kp.Error) - if kpError.StatusCode == 404 { - return false, nil + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 { + return false, nil + } } return false, err } @@ -455,10 +456,11 @@ func populateSchemaData(d *schema.ResourceData, meta interface{}) (*kp.Client, e ctx := context.Background() key, err := kpAPI.GetKey(ctx, keyid) if err != nil { - kpError := err.(*kp.Error) - if kpError.StatusCode == 404 || kpError.StatusCode == 409 { - d.SetId("") - return nil, nil + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 || kpError.StatusCode == 409 { + d.SetId("") + return nil, nil + } } return nil, fmt.Errorf("[ERROR] Get Key failed with error while reading Key: %s", err) } else if key.State == 5 { //Refers to Deleted state of the Key diff --git a/ibm/service/kms/resource_ibm_kms_key_alias.go b/ibm/service/kms/resource_ibm_kms_key_alias.go index 6cd7b78564..507a20a9b8 100644 --- a/ibm/service/kms/resource_ibm_kms_key_alias.go +++ b/ibm/service/kms/resource_ibm_kms_key_alias.go @@ -98,10 +98,11 @@ func resourceIBMKmsKeyAliasRead(d *schema.ResourceData, meta interface{}) error } key, err := kpAPI.GetKey(context.Background(), keyid) if err != nil { - kpError := err.(*kp.Error) - if kpError.StatusCode == 404 || kpError.StatusCode == 409 { - d.SetId("") - return nil + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 || kpError.StatusCode == 409 { + d.SetId("") + return nil + } } return fmt.Errorf("[ERROR] Get Key failed with error while reading policies: %s", err) } else if key.State == 5 { //Refers to Deleted state of the Key @@ -129,12 +130,12 @@ func resourceIBMKmsKeyAliasDelete(d *schema.ResourceData, meta interface{}) erro } err1 := kpAPI.DeleteKeyAlias(context.Background(), id[0], keyid) if err1 != nil { - kpError := err1.(*kp.Error) - if kpError.StatusCode == 404 { - return nil - } else { - return fmt.Errorf(" failed to Destroy alias with error: %s", err1) + if kpError, ok := err1.(*kp.Error); ok { + if kpError.StatusCode == 404 { + return nil + } } + return fmt.Errorf(" failed to Destroy alias with error: %s", err1) } return nil } diff --git a/ibm/service/kms/resource_ibm_kms_key_alias_test.go b/ibm/service/kms/resource_ibm_kms_key_alias_test.go index 5949cf3e92..28b43f8bbe 100644 --- a/ibm/service/kms/resource_ibm_kms_key_alias_test.go +++ b/ibm/service/kms/resource_ibm_kms_key_alias_test.go @@ -126,22 +126,47 @@ func TestAccIBMKMSResource_Key_Alias_Key_Check(t *testing.T) { func TestAccIBMKMSResource_Key_Alias_Key_Limit(t *testing.T) { instanceName := fmt.Sprintf("tf_kms_%d", acctest.RandIntRange(10, 100)) - // cosInstanceName := fmt.Sprintf("cos_%d", acctest.RandIntRange(10, 100)) - // bucketName := fmt.Sprintf("bucket-test77") + keyName := fmt.Sprintf("key_%d", acctest.RandIntRange(10, 100)) + aliasName := fmt.Sprintf("alias_%d", acctest.RandIntRange(10, 100)) aliasName2 := fmt.Sprintf("alias_%d", acctest.RandIntRange(10, 100)) aliasName3 := fmt.Sprintf("alias_%d", acctest.RandIntRange(10, 100)) aliasName4 := fmt.Sprintf("alias_%d", acctest.RandIntRange(10, 100)) aliasName5 := fmt.Sprintf("alias_%d", acctest.RandIntRange(10, 100)) aliasName6 := fmt.Sprintf("alias_%d", acctest.RandIntRange(10, 100)) - keyName := fmt.Sprintf("key_%d", acctest.RandIntRange(10, 100)) resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, Providers: acc.TestAccProviders, Steps: []resource.TestStep{ { - Config: testAccCheckIBMKmsResourceAliasLimitConfig(instanceName, keyName, aliasName, aliasName2, aliasName3, aliasName4, aliasName5, aliasName6), + Config: buildResourceSet(WithResourceKMSInstance(instanceName), + WithResourceKMSKey(keyName, "default"), + WithResourceKMSKeyAlias(aliasName, aliasName, "ibm_kms_key.test.key_id"), + WithResourceKMSKeyAlias(aliasName2, aliasName2, "ibm_kms_key.test.key_id"), + WithResourceKMSKeyAlias(aliasName3, aliasName3, "ibm_kms_key.test.key_id"), + WithResourceKMSKeyAlias(aliasName4, aliasName4, "ibm_kms_key.test.key_id"), + WithResourceKMSKeyAlias(aliasName5, aliasName5, "ibm_kms_key.test.key_id"), + ), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("ibm_kms_key.test", "key_name", keyName), + resource.TestCheckResourceAttr(fmt.Sprintf("ibm_kms_key_alias.%s", aliasName), "alias", aliasName), + resource.TestCheckResourceAttr(fmt.Sprintf("ibm_kms_key_alias.%s", aliasName2), "alias", aliasName2), + resource.TestCheckResourceAttr(fmt.Sprintf("ibm_kms_key_alias.%s", aliasName3), "alias", aliasName3), + resource.TestCheckResourceAttr(fmt.Sprintf("ibm_kms_key_alias.%s", aliasName4), "alias", aliasName4), + resource.TestCheckResourceAttr(fmt.Sprintf("ibm_kms_key_alias.%s", aliasName5), "alias", aliasName5), + ), + }, + { + Config: buildResourceSet(WithResourceKMSInstance(instanceName), + WithResourceKMSKey(keyName, "default"), + WithResourceKMSKeyAlias(aliasName, aliasName, "ibm_kms_key.test.key_id"), + WithResourceKMSKeyAlias(aliasName2, aliasName2, "ibm_kms_key.test.key_id"), + WithResourceKMSKeyAlias(aliasName3, aliasName3, "ibm_kms_key.test.key_id"), + WithResourceKMSKeyAlias(aliasName4, aliasName4, "ibm_kms_key.test.key_id"), + WithResourceKMSKeyAlias(aliasName5, aliasName5, "ibm_kms_key.test.key_id"), + WithResourceKMSKeyAlias(aliasName6, aliasName6, "ibm_kms_key.test.key_id"), + ), ExpectError: regexp.MustCompile("(KEY_ALIAS_QUOTA_ERR)"), }, }, @@ -286,50 +311,3 @@ func testAccCheckIBMKmsResourceAliasOne(instanceName, KeyName, aliasName string) `, addPrefixToResourceName(instanceName), KeyName, aliasName) } - -func testAccCheckIBMKmsResourceAliasLimitConfig(instanceName, KeyName, aliasName, aliasName2, aliasName3, aliasName4, aliasName5, aliasName6 string) string { - return fmt.Sprintf(` - resource "ibm_resource_instance" "kms_instance" { - name = "%s" - service = "kms" - plan = "tiered-pricing" - location = "us-south" - } - resource "ibm_kms_key" "test" { - instance_id = "${ibm_resource_instance.kms_instance.guid}" - key_name = "%s" - standard_key = true - force_delete = true - } - resource "ibm_kms_key_alias" "testAlias" { - instance_id = "${ibm_resource_instance.kms_instance.guid}" - alias = "%s" - key_id = "${ibm_kms_key.test.key_id}" - } - resource "ibm_kms_key_alias" "testAlias2" { - instance_id = "${ibm_resource_instance.kms_instance.guid}" - alias = "%s" - key_id = "${ibm_kms_key.test.key_id}" - } - resource "ibm_kms_key_alias" "testAlias3" { - instance_id = "${ibm_resource_instance.kms_instance.guid}" - alias = "%s" - key_id = "${ibm_kms_key.test.key_id}" - } - resource "ibm_kms_key_alias" "testAlias4" { - instance_id = "${ibm_resource_instance.kms_instance.guid}" - alias = "%s" - key_id = "${ibm_kms_key.test.key_id}" - } - resource "ibm_kms_key_alias" "testAlias5" { - instance_id = "${ibm_resource_instance.kms_instance.guid}" - alias = "%s" - key_id = "${ibm_kms_key.test.key_id}" - } - resource "ibm_kms_key_alias" "testAlias6" { - instance_id = "${ibm_resource_instance.kms_instance.guid}" - alias = "%s" - key_id = "${ibm_kms_key.test.key_id}" - } -`, addPrefixToResourceName(instanceName), KeyName, aliasName, aliasName2, aliasName3, aliasName4, aliasName5, aliasName6) -} diff --git a/ibm/service/kms/resource_ibm_kms_key_policies.go b/ibm/service/kms/resource_ibm_kms_key_policies.go index 5b3d726221..1fbd3918f7 100644 --- a/ibm/service/kms/resource_ibm_kms_key_policies.go +++ b/ibm/service/kms/resource_ibm_kms_key_policies.go @@ -213,10 +213,11 @@ func resourceIBMKmsKeyPolicyRead(context context.Context, d *schema.ResourceData } key, err := kpAPI.GetKey(context, keyid) if err != nil { - kpError := err.(*kp.Error) - if kpError.StatusCode == 404 || kpError.StatusCode == 409 { - d.SetId("") - return nil + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 || kpError.StatusCode == 409 { + d.SetId("") + return nil + } } return diag.Errorf("Get Key failed with error while reading policies: %s", err) } else if key.State == 5 { //Refers to Deleted state of the Key diff --git a/ibm/service/kms/resource_ibm_kms_key_rings.go b/ibm/service/kms/resource_ibm_kms_key_rings.go index f64278dda8..76b74c8224 100644 --- a/ibm/service/kms/resource_ibm_kms_key_rings.go +++ b/ibm/service/kms/resource_ibm_kms_key_rings.go @@ -39,9 +39,10 @@ func ResourceIBMKmskeyRings() *schema.Resource { "force_delete": { Type: schema.TypeBool, Optional: true, - Description: "set to true to force delete this key ring. This allows key ring deletion as long as all keys inside have key state equals to 5 (destroyed). Keys are moved to the default key ring.", + Description: "(Deprecated) set to true to force delete this key ring. This allows key ring deletion as long as all keys inside have key state equals to 5 (destroyed). Keys are moved to the default key ring.", ForceNew: false, Default: false, + Deprecated: "force_delete is now deprecated. Please remove all references to this field.", }, "endpoint_type": { Type: schema.TypeString, @@ -123,10 +124,11 @@ func resourceIBMKmsKeyRingRead(d *schema.ResourceData, meta interface{}) error { } _, err = kpAPI.GetKeyRings(context.Background()) if err != nil { - kpError := err.(*kp.Error) - if kpError.StatusCode == 404 || kpError.StatusCode == 409 { - d.SetId("") - return nil + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 || kpError.StatusCode == 409 { + d.SetId("") + return nil + } } return fmt.Errorf("[ERROR] Get Key Rings failed with error: %s", err) } @@ -148,17 +150,13 @@ func resourceIBMKmsKeyRingDelete(d *schema.ResourceData, meta interface{}) error if err != nil { return err } - force_delete := d.Get("force_delete").(bool) - err = kpAPI.DeleteKeyRing(context.Background(), id[0], kp.WithForce(force_delete)) + err = kpAPI.DeleteKeyRing(context.Background(), id[0], kp.WithForce(true)) if err != nil { - kpError := err.(*kp.Error) - // Key ring deletion used to occur by silencing the 409 failed deletion and allowing instance deletion to clean it up - // Will be deprecated in the future in favor of force_delete flag - if kpError.StatusCode == 404 || kpError.StatusCode == 409 { - return nil - } else { - return fmt.Errorf(" failed to Destroy key ring with error: %s", err) + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 { + return nil + } } } return nil diff --git a/ibm/service/kms/resource_ibm_kms_key_rings_test.go b/ibm/service/kms/resource_ibm_kms_key_rings_test.go index 1261be8a3b..47dc23027d 100644 --- a/ibm/service/kms/resource_ibm_kms_key_rings_test.go +++ b/ibm/service/kms/resource_ibm_kms_key_rings_test.go @@ -70,7 +70,7 @@ func TestAccIBMKMSResource_Key_Ring_Not_Exist(t *testing.T) { }) } -func TestAccIBMKMSResource_Key_Ring_ForceDeleteFalse(t *testing.T) { +func TestAccIBMKMSResource_Key_Ring_AlwaysForceDeleteTrue(t *testing.T) { instanceName := fmt.Sprintf("tf_kms_%d", acctest.RandIntRange(10, 100)) keyName := fmt.Sprintf("key_%d", acctest.RandIntRange(10, 100)) keyRing := fmt.Sprintf("keyRing%d", acctest.RandIntRange(10, 100)) @@ -88,102 +88,11 @@ func TestAccIBMKMSResource_Key_Ring_ForceDeleteFalse(t *testing.T) { resource.TestCheckResourceAttr("ibm_kms_key_rings.test", "force_delete", "false"), ), }, - // Developer note: We cannot move key rings to default key ring as we have not implemented that PATCH endpoint in terraform. Therefore we must depend on the force_delete flag to clean up test cases // Attempt to delete the key ring and key - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithDataKMSKeys()), - ExpectError: regexp.MustCompile("KEY_RING_NOT_EMPTY_ERR:"), - }, - // Update key ring to force_delete for cleanup - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithResourceKMSKeyRing(keyRing, true)), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("ibm_kms_key_rings.test", "force_delete", "true"), - ), - }, - // Delete Key Ring { Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithDataKMSKeys()), ExpectError: regexp.MustCompile(`\[ERROR\] No keys in instance`), }, - // Developer note: There is no support for listing keys under a certain key state so we cannot verify deleted key is now in default key ring - }, - }) -} - -func TestAccIBMKMSResource_Key_Ring_ForceDeleteTrue(t *testing.T) { - instanceName := fmt.Sprintf("tf_kms_%d", acctest.RandIntRange(10, 100)) - keyName := fmt.Sprintf("key_%d", acctest.RandIntRange(10, 100)) - keyRing := fmt.Sprintf("keyRing%d", acctest.RandIntRange(10, 100)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccPreCheck(t) }, - Providers: acc.TestAccProviders, - Steps: []resource.TestStep{ - // Create a Key Ring and check force_delete is true - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithResourceKMSKeyRing(keyRing, true), WithResourceKMSKey(keyName, "ibm_kms_key_rings.test.key_ring_id")), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("ibm_kms_key.test", "key_name", keyName), - resource.TestCheckResourceAttr("ibm_kms_key.test", "key_ring_id", keyRing), - resource.TestCheckResourceAttr("ibm_kms_key_rings.test", "force_delete", "true"), - ), - }, - // Attempt to delete the key ring and key - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName)), - Check: resource.ComposeTestCheckFunc(), - }, - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithDataKMSKeys()), - ExpectError: regexp.MustCompile(`\[ERROR\] No keys in instance`), - }, - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithDataKMSKeyRings()), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("data.ibm_kms_key_rings.test_key_rings", "key_rings.0.id", "default"), - ), - }, - }, - }) -} - -func TestAccIBMKMSResource_Key_Ring_ForceDeleteTrueContainsActiveKeys(t *testing.T) { - instanceName := fmt.Sprintf("tf_kms_%d", acctest.RandIntRange(10, 100)) - keyName := fmt.Sprintf("key_%d", acctest.RandIntRange(10, 100)) - keyRing := fmt.Sprintf("keyRing%d", acctest.RandIntRange(10, 100)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccPreCheck(t) }, - Providers: acc.TestAccProviders, - Steps: []resource.TestStep{ - // Create a Key Ring and check force_delete is true - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithResourceKMSKeyRing(keyRing, true), WithResourceKMSKey(keyName, "ibm_kms_key_rings.test.key_ring_id")), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("ibm_kms_key.test", "key_name", keyName), - resource.TestCheckResourceAttr("ibm_kms_key.test", "key_ring_id", keyRing), - resource.TestCheckResourceAttr("ibm_kms_key_rings.test", "force_delete", "true"), - ), - }, - // Attempt to delete the key ring while active key exists - // We must specify key ring ID and not reference here as the resource is removed - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithResourceKMSKey(keyName, keyRing)), - ExpectError: regexp.MustCompile("KEY_RING_KEYS_NOT_DELETED_ERR:"), - }, - // Attempt to delete keys - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithResourceKMSKeyRing(keyRing, true)), - }, - // Attempt to delete key ring and check no more keys - { - Config: buildResourceSet(WithResourceKMSInstance(instanceName), WithDataKMSKeys()), - ExpectError: regexp.MustCompile(`\[ERROR\] No keys in instance`), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("data.ibm_kms_key_rings.test_key_rings", "key_rings.0.id", "default"), - ), - }, }, }) } @@ -257,3 +166,14 @@ func WithDataKMSKeyRings() CreateResourceOption { }` } } + +func WithResourceKMSKeyAlias(tfConfigId string, alias string, tfConfigKeyId string) CreateResourceOption { + return func(resources *string) { + *resources += fmt.Sprintf(` + resource "ibm_kms_key_alias" "%s" { + instance_id = "${ibm_resource_instance.kms_instance.guid}" + alias = "%s" + key_id = "${%s}" + }`, tfConfigId, alias, tfConfigKeyId) + } +} diff --git a/ibm/service/kms/resource_ibm_kms_kmip_adapter.go b/ibm/service/kms/resource_ibm_kms_kmip_adapter.go index b74b300345..a7b7d93486 100644 --- a/ibm/service/kms/resource_ibm_kms_kmip_adapter.go +++ b/ibm/service/kms/resource_ibm_kms_kmip_adapter.go @@ -72,22 +72,22 @@ func ResourceIBMKmsKMIPAdapter() *schema.Resource { ForceNew: true, Description: "The description of the KMIP adapter", }, - "created_by": &schema.Schema{ + "created_by": { Type: schema.TypeString, Computed: true, Description: "The unique identifier that is associated with the entity that created the adapter.", }, - "created_at": &schema.Schema{ + "created_at": { Type: schema.TypeString, Computed: true, Description: "The date when a resource was created. The date format follows RFC 3339.", }, - "updated_by": &schema.Schema{ + "updated_by": { Type: schema.TypeString, Computed: true, Description: "The unique identifier that is associated with the entity that updated the adapter.", }, - "updated_at": &schema.Schema{ + "updated_at": { Type: schema.TypeString, Computed: true, Description: "The date when a resource was updated. The date format follows RFC 3339.", @@ -131,7 +131,6 @@ func resourceIBMKmsKMIPAdapterCreate(d *schema.ResourceData, meta interface{}) e } func resourceIBMKmsKMIPAdapterRead(d *schema.ResourceData, meta interface{}) error { - instanceID := d.Get("instance_id").(string) instanceID, adapterID, err := splitAdapterID(d.Id()) if err != nil { return err @@ -165,9 +164,19 @@ func resourceIBMKmsKMIPAdapterDelete(d *schema.ResourceData, meta interface{}) e } ctx := context.Background() objects, err := kpAPI.GetKMIPObjects(ctx, adapterID, nil) + if err != nil { + return fmt.Errorf("[ERROR] Failed to fetch KMIP objects associated with adapter '%s' for deletion: %v", adapterID, err) + } + for _, object := range objects.Objects { - err = kpAPI.DeleteKMIPObject(ctx, adapterID, object.ID) + err = kpAPI.DeleteKMIPObject(ctx, adapterID, object.ID, kp.WithForce(true)) if err != nil { + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 || kpError.StatusCode == 410 { + // if the kmip object is already deleted, do not error out + continue + } + } return fmt.Errorf("[ERROR] Failed to delete KMIP object associated with adapter (%s): %s", adapterID, err, @@ -180,7 +189,6 @@ func resourceIBMKmsKMIPAdapterDelete(d *schema.ResourceData, meta interface{}) e } func resourceIBMKmsKMIPAdapterExists(d *schema.ResourceData, meta interface{}) (bool, error) { - instanceID := d.Get("instance_id").(string) instanceID, adapterID, err := splitAdapterID(d.Id()) if err != nil { return false, err @@ -192,9 +200,10 @@ func resourceIBMKmsKMIPAdapterExists(d *schema.ResourceData, meta interface{}) ( ctx := context.Background() _, err = kpAPI.GetKMIPAdapter(ctx, adapterID) if err != nil { - kpError := err.(*kp.Error) - if kpError.StatusCode == 404 { - return false, nil + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 { + return false, nil + } } return false, wrapError(err, "Error checking adapter existence") } diff --git a/ibm/service/kms/resource_ibm_kms_kmip_client_cert.go b/ibm/service/kms/resource_ibm_kms_kmip_client_cert.go index f263d0aaaa..bd648597ba 100644 --- a/ibm/service/kms/resource_ibm_kms_kmip_client_cert.go +++ b/ibm/service/kms/resource_ibm_kms_kmip_client_cert.go @@ -63,12 +63,12 @@ func ResourceIBMKmsKMIPClientCertificate() *schema.Resource { Sensitive: true, Description: "The PEM-encoded contents of the certificate", }, - "created_by": &schema.Schema{ + "created_by": { Type: schema.TypeString, Computed: true, Description: "The unique identifier that is associated with the entity that created the adapter.", }, - "created_at": &schema.Schema{ + "created_at": { Type: schema.TypeString, Computed: true, Description: "The date when a resource was created. The date format follows RFC 3339.", @@ -104,8 +104,6 @@ func resourceIBMKmsKMIPClientCertCreate(d *schema.ResourceData, meta interface{} } func resourceIBMKmsKMIPClientCertRead(d *schema.ResourceData, meta interface{}) error { - instanceID := d.Get("instance_id").(string) - adapterID := d.Get("adapter_id").(string) // use instanceID and adapterID here to support terraform import case instanceID, adapterID, certID, err := splitCertID(d.Id()) if err != nil { @@ -148,8 +146,6 @@ func resourceIBMKmsKMIPClientCertDelete(d *schema.ResourceData, meta interface{} } func resourceIBMKmsKMIPClientCertExists(d *schema.ResourceData, meta interface{}) (bool, error) { - instanceID := d.Get("instance_id").(string) - adapterID := d.Get("adapter_id").(string) // use instanceID and adapterID here to support terraform import case instanceID, adapterID, certID, err := splitCertID(d.Id()) if err != nil { @@ -162,9 +158,10 @@ func resourceIBMKmsKMIPClientCertExists(d *schema.ResourceData, meta interface{} ctx := context.Background() _, err = kpAPI.GetKMIPClientCertificate(ctx, adapterID, certID) if err != nil { - kpError := err.(*kp.Error) - if kpError.StatusCode == 404 { - return false, nil + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 { + return false, nil + } } return false, wrapError(err, "Error checking KMIP Client Certificate existence") } diff --git a/ibm/service/kms/resource_ibm_kms_kmip_client_cert_test.go b/ibm/service/kms/resource_ibm_kms_kmip_client_cert_test.go index 39c1bf9aab..3aba90a537 100644 --- a/ibm/service/kms/resource_ibm_kms_kmip_client_cert_test.go +++ b/ibm/service/kms/resource_ibm_kms_kmip_client_cert_test.go @@ -138,6 +138,9 @@ func TestAccIBMKMSKMIPClientCertResource_InvalidCert(t *testing.T) { func TestAccIBMKMSKMIPClientCertResource_DuplicateNameError(t *testing.T) { instanceName := fmt.Sprintf("tf_kms_%d", acctest.RandIntRange(10, 100)) myCert, err := generateSelfSignedCertificate() + if err != nil { + t.Error(err) + } myCert2, err := generateSelfSignedCertificate() if err != nil { t.Error(err) @@ -223,7 +226,7 @@ func generateSelfSignedCertificate() (string, error) { Type: "CERTIFICATE", Bytes: certBytes, }) - certString := string(certPEM.Bytes()) + certString := certPEM.String() certString = strings.Replace(certString, "\n", "\\n", -1) return certString, nil } diff --git a/ibm/service/kms/resource_ibm_kp_key.go b/ibm/service/kms/resource_ibm_kp_key.go index 5797bd7a08..18a7396e09 100644 --- a/ibm/service/kms/resource_ibm_kp_key.go +++ b/ibm/service/kms/resource_ibm_kp_key.go @@ -267,9 +267,10 @@ func resourceIBMKeyExists(d *schema.ResourceData, meta interface{}) (bool, error // keyid := d.Id() _, err = api.GetKey(context.Background(), keyid) if err != nil { - kpError := err.(*kp.Error) - if kpError.StatusCode == 404 { - return false, nil + if kpError, ok := err.(*kp.Error); ok { + if kpError.StatusCode == 404 { + return false, nil + } } return false, err } diff --git a/ibm/service/kubernetes/data_source_ibm_container_cluster.go b/ibm/service/kubernetes/data_source_ibm_container_cluster.go index 12f0e640de..7e9e51c66b 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_cluster.go +++ b/ibm/service/kubernetes/data_source_ibm_container_cluster.go @@ -7,11 +7,13 @@ import ( "fmt" "log" "strings" + "time" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) func DataSourceIBMContainerCluster() *schema.Resource { @@ -35,6 +37,23 @@ func DataSourceIBMContainerCluster() *schema.Resource { "ibm_container_cluster", "name"), }, + "wait_till": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{oneWorkerNodeReady, clusterNormal}, true), + Description: "wait_till can be configured for Master Ready, One worker Ready, Ingress Ready or Normal", + }, + "wait_till_timeout": { + Type: schema.TypeInt, + Optional: true, + Default: "20", + Description: "timeout for wait_till in minutes", + RequiredWith: []string{"wait_till"}, + }, + "state": { + Type: schema.TypeString, + Computed: true, + }, "worker_count": { Description: "Number of workers", Type: schema.TypeInt, @@ -390,6 +409,16 @@ func dataSourceIBMContainerClusterRead(d *schema.ResourceData, meta interface{}) if v, ok := d.GetOk("name"); ok { name = v.(string) } + + // timeoutStage will define the timeout stage + var timeoutStage string + var timeout time.Duration = 20 * time.Minute + if v, ok := d.GetOk("wait_till"); ok { + timeoutStage = strings.ToLower(v.(string)) + timeoutInt := d.Get("wait_till_timeout").(int) + timeout = time.Duration(timeoutInt) * time.Minute + } + clusterFields, err := csAPI.Find(name, targetEnv) if err != nil { return fmt.Errorf("[ERROR] Error retrieving cluster: %s", err) @@ -434,6 +463,20 @@ func dataSourceIBMContainerClusterRead(d *schema.ResourceData, meta interface{}) filteredAlbs := flex.FlattenAlbs(albs, filterType) d.SetId(clusterFields.ID) + + if timeoutStage != "" { + err = waitForCluster(d, timeoutStage, timeout, meta) + if err != nil { + return err + } + + clusterFields, err = csAPI.Find(name, targetEnv) + if err != nil { + return fmt.Errorf("[ERROR] Error retrieving cluster after waitForCluster: %s", err) + } + } + + d.Set("state", clusterFields.State) d.Set("worker_count", clusterFields.WorkerCount) d.Set("workers", workers) d.Set("region", clusterFields.Region) diff --git a/ibm/service/kubernetes/data_source_ibm_container_cluster_config.go b/ibm/service/kubernetes/data_source_ibm_container_cluster_config.go index b3d1ce27ab..b8f1700804 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_cluster_config.go +++ b/ibm/service/kubernetes/data_source_ibm_container_cluster_config.go @@ -181,7 +181,7 @@ func dataSourceIBMContainerClusterConfigRead(d *schema.ResourceData, meta interf d.Set("config_file_path", configPath) } else { - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } diff --git a/ibm/service/kubernetes/data_source_ibm_container_cluster_test.go b/ibm/service/kubernetes/data_source_ibm_container_cluster_test.go index 07a1b5252c..55b9ca36dd 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_cluster_test.go +++ b/ibm/service/kubernetes/data_source_ibm_container_cluster_test.go @@ -16,6 +16,34 @@ import ( ) func TestAccIBMContainerClusterDataSource_basic(t *testing.T) { + clusterName := fmt.Sprintf("tf-cluster-%d", acctest.RandIntRange(10, 100)) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMContainerClusterDataSourceBasic(clusterName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "data.ibm_container_cluster.testacc_ds_cluster", "id"), + resource.TestCheckResourceAttr( + "data.ibm_container_cluster.testacc_ds_cluster", "state", "deploying"), + ), + }, + { + Config: testAccCheckIBMContainerClusterDataSourceBasic_update(clusterName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "data.ibm_container_cluster.testacc_ds_cluster", "id"), + resource.TestCheckResourceAttr( + "data.ibm_container_cluster.testacc_ds_cluster", "state", "normal"), + ), + }, + }, + }) +} + +func TestAccIBMContainerClusterDataSourceBindServiceBasic(t *testing.T) { clusterName := fmt.Sprintf("tf-cluster-%d", acctest.RandIntRange(10, 100)) serviceName := fmt.Sprintf("tf-cluster-%d", acctest.RandIntRange(10, 100)) resource.Test(t, resource.TestCase{ @@ -23,7 +51,7 @@ func TestAccIBMContainerClusterDataSource_basic(t *testing.T) { Providers: acc.TestAccProviders, Steps: []resource.TestStep{ { - Config: testAccCheckIBMContainerClusterDataSource(clusterName, serviceName), + Config: testAccCheckIBMContainerClusterDataSourceBindServiceBasic(clusterName, serviceName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( "data.ibm_container_cluster.testacc_ds_cluster", "id"), @@ -56,14 +84,34 @@ func testAccIBMClusterVlansCheck(n string) resource.TestCheckFunc { return nil } } -func testAccCheckIBMContainerClusterDataSource(clusterName, serviceName string) string { + +func testAccCheckIBMContainerClusterDataSourceBasic(clusterName string) string { + return testAccCheckIBMContainerClusterBasic(clusterName, "IngressReady") + ` + data "ibm_container_cluster" "testacc_ds_cluster" { + cluster_name_id = ibm_container_cluster.testacc_cluster.id + list_bounded_services = "false" + } + ` +} + +func testAccCheckIBMContainerClusterDataSourceBasic_update(clusterName string) string { + return testAccCheckIBMContainerClusterBasic(clusterName, "IngressReady") + ` + data "ibm_container_cluster" "testacc_ds_cluster" { + cluster_name_id = ibm_container_cluster.testacc_cluster.id + list_bounded_services = "false" + wait_till = "normal" + } + ` +} + +func testAccCheckIBMContainerClusterDataSourceBindServiceBasic(clusterName, serviceName string) string { return testAccCheckIBMContainerBindServiceBasic(clusterName, serviceName) + ` data "ibm_container_cluster" "testacc_ds_cluster" { cluster_name_id = ibm_container_cluster.testacc_cluster.id } data "ibm_container_bind_service" "bind_service" { cluster_name_id = ibm_container_bind_service.bind_service.cluster_name_id - service_instance_id = ibm_container_bind_service.bind_service.service_instance_id + service_instance_id = ibm_container_bind_service.bind_service.service_instance_id namespace_id = "default" } ` diff --git a/ibm/service/kubernetes/data_source_ibm_container_nlb_dns_test.go b/ibm/service/kubernetes/data_source_ibm_container_nlb_dns_test.go index 0f94e43499..2a34b1bec4 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_nlb_dns_test.go +++ b/ibm/service/kubernetes/data_source_ibm_container_nlb_dns_test.go @@ -30,7 +30,7 @@ func TestAccIBMContainerNLBDNSDatasourceBasic(t *testing.T) { } func testAccCheckIBMContainerNLBDNSDataSourceConfig(name string) string { - return testAccCheckIBMContainerVpcClusterBasic(name) + ` + return testAccCheckIBMContainerVpcClusterBasic(name, "OneWorkerNodeReady") + ` data "ibm_container_nlb_dns" "dns" { cluster = ibm_container_vpc_cluster.cluster.id } diff --git a/ibm/service/kubernetes/data_source_ibm_container_storage_attachment.go b/ibm/service/kubernetes/data_source_ibm_container_storage_attachment.go index 7b8c70ca9b..ec7411bc9a 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_storage_attachment.go +++ b/ibm/service/kubernetes/data_source_ibm_container_storage_attachment.go @@ -101,7 +101,7 @@ func dataSourceIBMContainerVpcWorkerVolumeAttachmentRead(context context.Context } workersAPI := wpClient.Workers() - target, err := getVpcClusterTargetHeader(d, meta) + target, err := getVpcClusterTargetHeader(d) if err != nil { return diag.FromErr(err) } diff --git a/ibm/service/kubernetes/data_source_ibm_container_vpc_alb.go b/ibm/service/kubernetes/data_source_ibm_container_vpc_alb.go index 41f7307c8d..2d605fc763 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_vpc_alb.go +++ b/ibm/service/kubernetes/data_source_ibm_container_vpc_alb.go @@ -74,7 +74,7 @@ func dataSourceIBMContainerVpcALBRead(d *schema.ResourceData, meta interface{}) albID := d.Get("alb_id").(string) albAPI := albClient.Albs() - targetEnv, _ := getVpcClusterTargetHeader(d, meta) + targetEnv, _ := getVpcClusterTargetHeader(d) albConfig, err := albAPI.GetAlb(albID, targetEnv) if err != nil { return err diff --git a/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster.go b/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster.go index 31a496730d..9c835343df 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster.go +++ b/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster.go @@ -7,11 +7,13 @@ import ( "fmt" "log" "strings" + "time" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) const ( @@ -39,6 +41,19 @@ func DataSourceIBMContainerVPCCluster() *schema.Resource { "ibm_container_vpc_cluster", "name"), }, + "wait_till": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{masterNodeReady, oneWorkerNodeReady, ingressReady, clusterNormal}, true), + Description: "wait_till can be configured for Master Ready, One worker Ready, Ingress Ready or Normal", + }, + "wait_till_timeout": { + Type: schema.TypeInt, + Optional: true, + Default: "20", + Description: "timeout for wait_till in minutes", + RequiredWith: []string{"wait_till"}, + }, "worker_count": { Description: "Number of workers", Type: schema.TypeInt, @@ -361,26 +376,47 @@ func dataSourceIBMContainerClusterVPCRead(d *schema.ResourceData, meta interface return err } - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } - - var clusterID string + var clusterNameOrID string if v, ok := d.GetOk("cluster_name_id"); ok { - clusterID = v.(string) + clusterNameOrID = v.(string) } if v, ok := d.GetOk("name"); ok { - clusterID = v.(string) + clusterNameOrID = v.(string) + } + + // timeoutStage will define the timeout stage + var timeoutStage string + var timeout time.Duration = 20 * time.Minute + if v, ok := d.GetOk("wait_till"); ok { + timeoutStage = strings.ToLower(v.(string)) + timeoutInt := d.Get("wait_till_timeout").(int) + timeout = time.Duration(timeoutInt) * time.Minute } - cls, err := csClient.Clusters().GetCluster(clusterID, targetEnv) + cls, err := csClient.Clusters().GetCluster(clusterNameOrID, targetEnv) if err != nil { return fmt.Errorf("[ERROR] Error retrieving container vpc cluster: %s", err) } d.SetId(cls.ID) + + if timeoutStage != "" { + err = waitForVpcCluster(d, meta, timeoutStage, timeout) + if err != nil { + return err + } + + cls, err = csClient.Clusters().GetCluster(clusterNameOrID, targetEnv) + if err != nil { + return fmt.Errorf("[ERROR] Error retrieving container vpc cluster: %s", err) + } + } + d.Set("crn", cls.CRN) d.Set("status", cls.Lifecycle.MasterStatus) d.Set("health", cls.Lifecycle.MasterHealth) @@ -404,7 +440,7 @@ func dataSourceIBMContainerClusterVPCRead(d *schema.ResourceData, meta interface d.Set("ingress_hostname", cls.Ingress.HostName) d.Set("ingress_secret", cls.Ingress.SecretName) - workerFields, err := csClient.Workers().ListWorkers(clusterID, false, targetEnv) + workerFields, err := csClient.Workers().ListWorkers(clusterNameOrID, false, targetEnv) if err != nil { return fmt.Errorf("[ERROR] Error retrieving workers for cluster: %s", err) } @@ -416,7 +452,7 @@ func dataSourceIBMContainerClusterVPCRead(d *schema.ResourceData, meta interface d.Set("workers", workers) //Get worker pools - pools, err := csClient.WorkerPools().ListWorkerPools(clusterID, targetEnv) + pools, err := csClient.WorkerPools().ListWorkerPools(clusterNameOrID, targetEnv) if err != nil { return fmt.Errorf("[ERROR] Error retrieving worker pools for container vpc cluster: %s", err) } @@ -424,9 +460,9 @@ func dataSourceIBMContainerClusterVPCRead(d *schema.ResourceData, meta interface d.Set("worker_pools", flex.FlattenVpcWorkerPools(pools)) if !strings.HasSuffix(cls.MasterKubeVersion, _OPENSHIFT) { - albs, err := csClient.Albs().ListClusterAlbs(clusterID, targetEnv) + albs, err := csClient.Albs().ListClusterAlbs(clusterNameOrID, targetEnv) if err != nil { - return fmt.Errorf("[ERROR] Error retrieving alb's of the cluster %s: %s", clusterID, err) + return fmt.Errorf("[ERROR] Error retrieving alb's of the cluster %s: %s", clusterNameOrID, err) } filterType := d.Get("alb_type").(string) @@ -453,7 +489,7 @@ func dataSourceIBMContainerClusterVPCRead(d *schema.ResourceData, meta interface if err != nil { return err } - apikeyConfig, err := apikeyAPI.GetApiKeyInfo(clusterID, v1targetEnv) + apikeyConfig, err := apikeyAPI.GetApiKeyInfo(clusterNameOrID, v1targetEnv) if err != nil { log.Printf("Error in GetApiKeyInfo, %s", err) //return err diff --git a/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster_test.go b/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster_test.go index b45bca4f9a..e95e67eca5 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster_test.go +++ b/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster_test.go @@ -15,14 +15,43 @@ import ( func TestAccIBMContainerVPCClusterDataSource_basic(t *testing.T) { name := fmt.Sprintf("tf-vpc-cluster-%d", acctest.RandIntRange(10, 100)) + masterNodeReadyClusterScript := testAccCheckIBMContainerVpcClusterBasic(name, "MasterNodeReady") + ` + data "ibm_container_vpc_cluster" "testacc_ds_cluster" { + name = ibm_container_vpc_cluster.cluster.id + } + ` + normalClusterScriptWithConfig := testAccCheckIBMContainerVpcClusterBasic(name, "MasterNodeReady") + ` + data "ibm_container_vpc_cluster" "testacc_ds_cluster" { + name = ibm_container_vpc_cluster.cluster.id + wait_till = "normal" + } + data "ibm_container_cluster_config" "testacc_ds_cluster" { + cluster_name_id = data.ibm_container_vpc_cluster.testacc_ds_cluster.name + } + ` + resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, Providers: acc.TestAccProviders, Steps: []resource.TestStep{ { - Config: testAccCheckIBMContainerVPCClusterDataSource(name), + Config: masterNodeReadyClusterScript, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_container_vpc_cluster.testacc_ds_cluster", "id"), + resource.TestCheckResourceAttrWith("data.ibm_container_vpc_cluster.testacc_ds_cluster", "state", func(value string) error { + switch value { + case "deploying", "deployed": + return nil + } + return fmt.Errorf("state is not deploying, it was %s", value) + }), + ), + }, + { + Config: normalClusterScriptWithConfig, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.ibm_container_vpc_cluster.testacc_ds_cluster", "id"), + resource.TestCheckResourceAttr("data.ibm_container_vpc_cluster.testacc_ds_cluster", "state", "normal"), resource.TestCheckResourceAttrSet("data.ibm_container_cluster_config.testacc_ds_cluster", "id"), ), }, @@ -54,17 +83,6 @@ func TestAccIBMContainerVPCClusterDataSource_DedicatedHost(t *testing.T) { }) } -func testAccCheckIBMContainerVPCClusterDataSource(name string) string { - return testAccCheckIBMContainerVpcClusterBasic(name) + ` -data "ibm_container_vpc_cluster" "testacc_ds_cluster" { - cluster_name_id = ibm_container_vpc_cluster.cluster.id -} -data "ibm_container_cluster_config" "testacc_ds_cluster" { - cluster_name_id = ibm_container_vpc_cluster.cluster.id - } -` -} - func testAccCheckIBMContainerVPCClusterDataSourceDedicatedHost(name, vpcID, flavor, subnetID, rgroupID, hostpoolID string) string { return testAccCheckIBMContainerVpcClusterDedicatedHostSetting(name, vpcID, flavor, subnetID, rgroupID, hostpoolID) + ` data "ibm_container_vpc_cluster" "testacc_cluster_dedicatedhost" { diff --git a/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster_worker.go b/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster_worker.go index 81ed36a2c9..22a91cd090 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster_worker.go +++ b/ibm/service/kubernetes/data_source_ibm_container_vpc_cluster_worker.go @@ -114,7 +114,7 @@ func dataSourceIBMContainerVPCClusterWorkerRead(d *schema.ResourceData, meta int return err } - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } diff --git a/ibm/service/kubernetes/data_source_ibm_container_vpc_worker_pool.go b/ibm/service/kubernetes/data_source_ibm_container_vpc_worker_pool.go index 00808c049e..3f8bac1230 100644 --- a/ibm/service/kubernetes/data_source_ibm_container_vpc_worker_pool.go +++ b/ibm/service/kubernetes/data_source_ibm_container_vpc_worker_pool.go @@ -153,7 +153,7 @@ func dataSourceIBMContainerVpcClusterWorkerPoolRead(d *schema.ResourceData, meta clusterName := d.Get("cluster").(string) workerPoolName := d.Get("worker_pool_name").(string) workerPoolsAPI := wpClient.WorkerPools() - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } diff --git a/ibm/service/kubernetes/resource_ibm_container_cluster.go b/ibm/service/kubernetes/resource_ibm_container_cluster.go index 98eeb77d17..99445c8a96 100644 --- a/ibm/service/kubernetes/resource_ibm_container_cluster.go +++ b/ibm/service/kubernetes/resource_ibm_container_cluster.go @@ -690,7 +690,7 @@ func resourceIBMContainerClusterCreate(d *schema.ResourceData, meta interface{}) } d.SetId(cls.ID) - targetEnvV2, err := getVpcClusterTargetHeader(d, meta) + targetEnvV2, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -701,26 +701,15 @@ func resourceIBMContainerClusterCreate(d *schema.ResourceData, meta interface{}) } } - _, err = waitForClusterMasterAvailable(d, meta) + _, err = waitForClusterMasterAvailable(d, meta, d.Timeout(schema.TimeoutCreate)) if err != nil { return err } - waitForState := strings.ToLower(d.Get("wait_till").(string)) - - switch waitForState { - case strings.ToLower(oneWorkerNodeReady): - _, err = waitForClusterOneWorkerAvailable(d, meta) - if err != nil { - return err - } - - case strings.ToLower(clusterNormal): - pendingStates := []string{clusterDeploying, clusterRequested, clusterPending, clusterDeployed, clusterCritical, clusterWarning} - _, err = waitForClusterState(d, meta, waitForState, pendingStates) - if err != nil { - return err - } + timeoutStage := strings.ToLower(d.Get("wait_till").(string)) + err = waitForCluster(d, timeoutStage, d.Timeout(schema.TimeoutCreate), meta) + if err != nil { + return err } d.Set("force_delete_storage", d.Get("force_delete_storage").(bool)) @@ -759,6 +748,31 @@ func resourceIBMContainerClusterCreate(d *schema.ResourceData, meta interface{}) return resourceIBMContainerClusterUpdate(d, meta) } +func waitForCluster(d *schema.ResourceData, timeoutStage string, timeout time.Duration, meta interface{}) error { + switch timeoutStage { + case strings.ToLower(masterNodeReady): + _, err := waitForClusterMasterAvailable(d, meta, timeout) + if err != nil { + return err + } + + case strings.ToLower(oneWorkerNodeReady): + _, err := waitForClusterOneWorkerAvailable(d, meta, timeout) + if err != nil { + return err + } + + case clusterNormal: + pendingStates := []string{clusterDeploying, clusterRequested, clusterPending, clusterDeployed, clusterCritical, clusterWarning} + _, err := waitForClusterState(d, meta, clusterNormal, pendingStates, timeout) + if err != nil { + return err + } + } + + return nil +} + func resourceIBMContainerClusterRead(d *schema.ResourceData, meta interface{}) error { csClient, err := meta.(conns.ClientSession).ContainerAPI() if err != nil { @@ -929,7 +943,7 @@ func resourceIBMContainerClusterUpdate(d *schema.ResourceData, meta interface{}) return err } - targetEnvV2, err := getVpcClusterTargetHeader(d, meta) + targetEnvV2, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -1275,46 +1289,8 @@ func waitForClusterDelete(d *schema.ResourceData, meta interface{}) (interface{} return stateConf.WaitForState() } -// WaitForClusterAvailable Waits for cluster creation -func WaitForClusterAvailable(d *schema.ResourceData, meta interface{}, target v1.ClusterTargetHeader) (interface{}, error) { - csClient, err := meta.(conns.ClientSession).ContainerAPI() - if err != nil { - return nil, err - } - log.Printf("Waiting for cluster (%s) to be available.", d.Id()) - id := d.Id() - - stateConf := &resource.StateChangeConf{ - Pending: []string{"retry", clusterProvisioning}, - Target: []string{clusterNormal}, - Refresh: clusterStateRefreshFunc(csClient.Clusters(), id, target), - Timeout: d.Timeout(schema.TimeoutCreate), - Delay: 10 * time.Second, - MinTimeout: 10 * time.Second, - } - - return stateConf.WaitForState() -} - -func clusterStateRefreshFunc(client v1.Clusters, instanceID string, target v1.ClusterTargetHeader) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - clusterFields, err := client.FindWithOutShowResourcesCompatible(instanceID, target) - if err != nil { - return nil, "", fmt.Errorf("[ERROR] clusterStateRefreshFunc Error retrieving cluster: %s", err) - } - // Check active transactions - log.Println("Checking cluster") - //Check for cluster state to be normal - log.Println("Checking cluster state", strings.Compare(clusterFields.State, clusterNormal)) - if strings.Compare(clusterFields.State, clusterNormal) != 0 { - return clusterFields, clusterProvisioning, nil - } - return clusterFields, clusterNormal, nil - } -} - // waitForClusterMasterAvailable Waits for cluster creation -func waitForClusterMasterAvailable(d *schema.ResourceData, meta interface{}) (interface{}, error) { +func waitForClusterMasterAvailable(d *schema.ResourceData, meta interface{}, timeout time.Duration) (interface{}, error) { targetEnv, err := getClusterTargetHeader(d, meta) if err != nil { return nil, err @@ -1339,7 +1315,7 @@ func waitForClusterMasterAvailable(d *schema.ResourceData, meta interface{}) (in } return clusterFields, deployInProgress, nil }, - Timeout: d.Timeout(schema.TimeoutCreate), + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 10 * time.Second, } @@ -1347,7 +1323,7 @@ func waitForClusterMasterAvailable(d *schema.ResourceData, meta interface{}) (in return stateConf.WaitForState() } -func waitForClusterState(d *schema.ResourceData, meta interface{}, waitForState string, pendingState []string) (interface{}, error) { +func waitForClusterState(d *schema.ResourceData, meta interface{}, waitForState string, pendingState []string, timeout time.Duration) (interface{}, error) { targetEnv, err := getClusterTargetHeader(d, meta) if err != nil { return nil, err @@ -1376,7 +1352,7 @@ func waitForClusterState(d *schema.ResourceData, meta interface{}, waitForState return cls, cls.State, nil }, - Timeout: d.Timeout(schema.TimeoutCreate), + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 10 * time.Second, } @@ -1385,7 +1361,7 @@ func waitForClusterState(d *schema.ResourceData, meta interface{}, waitForState } // waitForClusterOneWorkerAvailable Waits for cluster creation -func waitForClusterOneWorkerAvailable(d *schema.ResourceData, meta interface{}) (interface{}, error) { +func waitForClusterOneWorkerAvailable(d *schema.ResourceData, meta interface{}, timeout time.Duration) (interface{}, error) { targetEnv, err := getClusterTargetHeader(d, meta) if err != nil { return nil, err @@ -1435,7 +1411,7 @@ func waitForClusterOneWorkerAvailable(d *schema.ResourceData, meta interface{}) } return nil, normal, nil }, - Timeout: d.Timeout(schema.TimeoutCreate), + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 10 * time.Second, } @@ -1483,41 +1459,6 @@ func workerStateRefreshFunc(client v1.Workers, instanceID string, target v1.Clus } } -func WaitForClusterCreation(d *schema.ResourceData, meta interface{}, target v1.ClusterTargetHeader) (interface{}, error) { - csClient, err := meta.(conns.ClientSession).ContainerAPI() - if err != nil { - return nil, err - } - log.Printf("Waiting for cluster (%s) to be available.", d.Id()) - ClusterID := d.Id() - - stateConf := &resource.StateChangeConf{ - Pending: []string{"retry", clusterProvisioning}, - Target: []string{clusterNormal}, - Refresh: func() (interface{}, string, error) { - workerFields, err := csClient.Workers().List(ClusterID, target) - log.Println("Total workers: ", len(workerFields)) - if err != nil { - return nil, "", fmt.Errorf("[ERROR] Error retrieving workers for cluster: %s", err) - } - log.Println("Checking workers...") - //verifying for atleast sing node to be in normal state - for _, e := range workerFields { - log.Println("Worker node status: ", e.State) - if e.State == workerNormal { - return workerFields, workerNormal, nil - } - } - return workerFields, workerProvisioning, nil - }, - Timeout: d.Timeout(schema.TimeoutCreate), - Delay: 10 * time.Second, - MinTimeout: 10 * time.Second, - } - - return stateConf.WaitForState() -} - func WaitForSubnetAvailable(d *schema.ResourceData, meta interface{}, target v1.ClusterTargetHeader) (interface{}, error) { csClient, err := meta.(conns.ClientSession).ContainerAPI() if err != nil { diff --git a/ibm/service/kubernetes/resource_ibm_container_cluster_feature.go b/ibm/service/kubernetes/resource_ibm_container_cluster_feature.go index d1079a132c..72c718705e 100644 --- a/ibm/service/kubernetes/resource_ibm_container_cluster_feature.go +++ b/ibm/service/kubernetes/resource_ibm_container_cluster_feature.go @@ -6,6 +6,7 @@ package kubernetes import ( "fmt" "log" + "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -326,7 +327,7 @@ func resourceIBMContainerClusterFeatureUpdate(d *schema.ResourceData, meta inter return resourceIBMContainerClusterFeatureRead(d, meta) } -// WaitForClusterAvailable Waits for cluster creation +// WaitForClusterAvailableForFeatureUpdate Waits for cluster creation func WaitForClusterAvailableForFeatureUpdate(cluster string, timeout time.Duration, meta interface{}, target v1.ClusterTargetHeader) (interface{}, error) { csClient, err := meta.(conns.ClientSession).ContainerAPI() if err != nil { @@ -347,6 +348,23 @@ func WaitForClusterAvailableForFeatureUpdate(cluster string, timeout time.Durati return stateConf.WaitForState() } +func clusterStateRefreshFunc(client v1.Clusters, instanceID string, target v1.ClusterTargetHeader) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + clusterFields, err := client.FindWithOutShowResourcesCompatible(instanceID, target) + if err != nil { + return nil, "", fmt.Errorf("[ERROR] clusterStateRefreshFunc Error retrieving cluster: %s", err) + } + // Check active transactions + log.Println("Checking cluster") + //Check for cluster state to be normal + log.Println("Checking cluster state", strings.Compare(clusterFields.State, clusterNormal)) + if strings.Compare(clusterFields.State, clusterNormal) != 0 { + return clusterFields, clusterProvisioning, nil + } + return clusterFields, clusterNormal, nil + } +} + func WaitForWorkerAvailableForFeatureUpdate(cluster string, timeout time.Duration, meta interface{}, target v1.ClusterTargetHeader) (interface{}, error) { csClient, err := meta.(conns.ClientSession).ContainerAPI() if err != nil { diff --git a/ibm/service/kubernetes/resource_ibm_container_cluster_test.go b/ibm/service/kubernetes/resource_ibm_container_cluster_test.go index de6aaa134c..017de8e89b 100644 --- a/ibm/service/kubernetes/resource_ibm_container_cluster_test.go +++ b/ibm/service/kubernetes/resource_ibm_container_cluster_test.go @@ -27,7 +27,7 @@ func TestAccIBMContainerCluster_basic(t *testing.T) { CheckDestroy: testAccCheckIBMContainerClusterDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckIBMContainerClusterBasic(clusterName), + Config: testAccCheckIBMContainerClusterBasic(clusterName, "masterNodeReady"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( "ibm_container_cluster.testacc_cluster", "name", clusterName), @@ -42,9 +42,9 @@ func TestAccIBMContainerCluster_basic(t *testing.T) { resource.TestCheckResourceAttr( "ibm_container_cluster.testacc_cluster", "labels.%", "2"), resource.TestCheckResourceAttr( - "ibm_container_cluster.testacc_cluster", "tags.#", "1"), + "ibm_container_cluster.testacc_cluster", "image_security_enforcement", "false"), resource.TestCheckResourceAttr( - "ibm_container_cluster.testacc_cluster", "workers_info.#", "2"), + "ibm_container_cluster.testacc_cluster", "workers_info.#", "1"), ), }, { @@ -53,7 +53,7 @@ func TestAccIBMContainerCluster_basic(t *testing.T) { resource.TestCheckResourceAttr( "ibm_container_cluster.testacc_cluster", "name", clusterName), resource.TestCheckResourceAttr( - "ibm_container_cluster.testacc_cluster", "default_pool_size", "2"), + "ibm_container_cluster.testacc_cluster", "default_pool_size", "1"), resource.TestCheckResourceAttr( "ibm_container_cluster.testacc_cluster", "hardware", "shared"), resource.TestCheckResourceAttr( @@ -61,11 +61,11 @@ func TestAccIBMContainerCluster_basic(t *testing.T) { resource.TestCheckResourceAttrSet( "ibm_container_cluster.testacc_cluster", "resource_group_id"), resource.TestCheckResourceAttr( - "ibm_container_cluster.testacc_cluster", "labels.%", "3"), + "ibm_container_cluster.testacc_cluster", "labels.%", "2"), resource.TestCheckResourceAttr( - "ibm_container_cluster.testacc_cluster", "tags.#", "2"), + "ibm_container_cluster.testacc_cluster", "image_security_enforcement", "true"), resource.TestCheckResourceAttr( - "ibm_container_cluster.testacc_cluster", "workers_info.#", "4"), + "ibm_container_cluster.testacc_cluster", "workers_info.#", "1"), ), }, }, @@ -227,7 +227,7 @@ func testAccCheckIBMContainerClusterDestroy(s *terraform.State) error { return nil } -func testAccCheckIBMContainerClusterBasic(clusterName string) string { +func testAccCheckIBMContainerClusterBasic(clusterName, wait_till string) string { return fmt.Sprintf(` data "ibm_resource_group" "testacc_ds_resource_group" { @@ -245,13 +245,17 @@ resource "ibm_container_cluster" "testacc_cluster" { public_vlan_id = "%s" private_vlan_id = "%s" no_subnet = true - tags = ["test"] + labels = { + "test" = "test-label" + "test1" = "test-label1" + } + wait_till = "%s" timeouts { create = "720m" update = "720m" } -} `, clusterName, acc.Datacenter, acc.KubeVersion, acc.MachineType, acc.PublicVlanID, acc.PrivateVlanID) +} `, clusterName, acc.Datacenter, acc.KubeVersion, acc.MachineType, acc.PublicVlanID, acc.PrivateVlanID, wait_till) } func testAccCheckIBMContainerClusterKmsEnable(clusterName, kmsInstanceName, rootKeyName string) string { @@ -331,7 +335,7 @@ data "ibm_resource_group" "testacc_ds_resource_group" { resource "ibm_container_cluster" "testacc_cluster" { name = "%s" datacenter = "%s" - default_pool_size = 2 + default_pool_size = 2 # default_pool_size is applyonce, so should not modify anything in case of update hardware = "shared" resource_group_id = data.ibm_resource_group.testacc_ds_resource_group.id kube_version = "%s" @@ -340,7 +344,7 @@ resource "ibm_container_cluster" "testacc_cluster" { private_vlan_id = "%s" no_subnet = true update_all_workers = true - tags = ["test", "once"] + image_security_enforcement = true timeouts { create = "720m" update = "720m" diff --git a/ibm/service/kubernetes/resource_ibm_container_storage_attachment.go b/ibm/service/kubernetes/resource_ibm_container_storage_attachment.go index 8b46ab777f..de157a4748 100644 --- a/ibm/service/kubernetes/resource_ibm_container_storage_attachment.go +++ b/ibm/service/kubernetes/resource_ibm_container_storage_attachment.go @@ -127,7 +127,7 @@ func resourceIBMContainerVpcWorkerVolumeAttachmentCreate(context context.Context clusterNameorID := d.Get("cluster").(string) workerID := d.Get("worker").(string) - target, err := getVpcClusterTargetHeader(d, meta) + target, err := getVpcClusterTargetHeader(d) if err != nil { return diag.FromErr(err) } @@ -156,7 +156,7 @@ func resourceIBMContainerVpcWorkerVolumeAttachmentRead(context context.Context, } workersAPI := wpClient.Workers() - target, err := getVpcClusterTargetHeader(d, meta) + target, err := getVpcClusterTargetHeader(d) if err != nil { return diag.FromErr(err) } @@ -190,7 +190,7 @@ func resourceIBMContainerVpcWorkerVolumeAttachmentDelete(context context.Context } workersAPI := wpClient.Workers() - target, err := getVpcClusterTargetHeader(d, meta) + target, err := getVpcClusterTargetHeader(d) if err != nil { return diag.FromErr(err) } @@ -234,7 +234,7 @@ func resourceIBMContainerVpcWorkerVolumeAttachmentExists(d *schema.ResourceData, } workersAPI := wpClient.Workers() - target, err := getVpcClusterTargetHeader(d, meta) + target, err := getVpcClusterTargetHeader(d) if err != nil { return false, err } @@ -267,7 +267,7 @@ func waitforVolumetoAttach(d *schema.ResourceData, meta interface{}) (interface{ workersAPI := wpClient.Workers() - target, trgetErr := getVpcClusterTargetHeader(d, meta) + target, trgetErr := getVpcClusterTargetHeader(d) if trgetErr != nil { return nil, trgetErr } @@ -312,7 +312,7 @@ func waitForStorageAttachmentDelete(d *schema.ResourceData, meta interface{}) (i workersAPI := wpClient.Workers() - target, trgetErr := getVpcClusterTargetHeader(d, meta) + target, trgetErr := getVpcClusterTargetHeader(d) if trgetErr != nil { return nil, trgetErr } diff --git a/ibm/service/kubernetes/resource_ibm_container_vpc_alb.go b/ibm/service/kubernetes/resource_ibm_container_vpc_alb.go index 79f827a191..4fad643223 100644 --- a/ibm/service/kubernetes/resource_ibm_container_vpc_alb.go +++ b/ibm/service/kubernetes/resource_ibm_container_vpc_alb.go @@ -126,7 +126,7 @@ func resourceIBMContainerVpcALBEnable(d *schema.ResourceData, meta interface{}) } albAPI := albClient.Albs() - targetEnv, _ := getVpcClusterTargetHeader(d, meta) + targetEnv, _ := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -161,7 +161,7 @@ func resourceIBMContainerVpcALBRead(d *schema.ResourceData, meta interface{}) er albID := d.Id() albAPI := albClient.Albs() - targetEnv, _ := getVpcClusterTargetHeader(d, meta) + targetEnv, _ := getVpcClusterTargetHeader(d) albConfig, err := albAPI.GetAlb(albID, targetEnv) if err != nil { @@ -205,7 +205,7 @@ func resourceIBMContainerVpcALBUpdate(d *schema.ResourceData, meta interface{}) Enable: enable, } - targetEnv, _ := getVpcClusterTargetHeader(d, meta) + targetEnv, _ := getVpcClusterTargetHeader(d) if enable { err = albAPI.EnableAlb(params, targetEnv) @@ -237,7 +237,7 @@ func waitForVpcContainerALB(d *schema.ResourceData, meta interface{}, albID, tim Pending: []string{"pending"}, Target: []string{"active"}, Refresh: func() (interface{}, string, error) { - targetEnv, _ := getVpcClusterTargetHeader(d, meta) + targetEnv, _ := getVpcClusterTargetHeader(d) alb, err := albClient.Albs().GetAlb(albID, targetEnv) if err != nil { if apiErr, ok := err.(bmxerror.RequestFailure); ok && apiErr.StatusCode() == 404 { @@ -279,7 +279,7 @@ func waitForVpcClusterAvailable(d *schema.ResourceData, meta interface{}, albID, Pending: []string{deployRequested, deployInProgress}, Target: []string{ready}, Refresh: func() (interface{}, string, error) { - targetEnv, _ := getVpcClusterTargetHeader(d, meta) + targetEnv, _ := getVpcClusterTargetHeader(d) albInfo, err := albClient.Albs().GetAlb(albID, targetEnv) if err == nil { cluster := albInfo.Cluster diff --git a/ibm/service/kubernetes/resource_ibm_container_vpc_alb_create.go b/ibm/service/kubernetes/resource_ibm_container_vpc_alb_create.go index ad949d4cfb..835ed4e144 100644 --- a/ibm/service/kubernetes/resource_ibm_container_vpc_alb_create.go +++ b/ibm/service/kubernetes/resource_ibm_container_vpc_alb_create.go @@ -130,7 +130,7 @@ func resourceIBMContainerVpcAlbCreate(d *schema.ResourceData, meta interface{}) params.EnableByDefault = v.(bool) } - targetEnv, _ := getVpcClusterTargetHeader(d, meta) + targetEnv, _ := getVpcClusterTargetHeader(d) //v2.AlbCreateResp albResp, err := albAPI.CreateAlb(params, targetEnv) diff --git a/ibm/service/kubernetes/resource_ibm_container_vpc_cluster.go b/ibm/service/kubernetes/resource_ibm_container_vpc_cluster.go index e168e05841..fc129a8bd9 100644 --- a/ibm/service/kubernetes/resource_ibm_container_vpc_cluster.go +++ b/ibm/service/kubernetes/resource_ibm_container_vpc_cluster.go @@ -288,7 +288,7 @@ func ResourceIBMContainerVpcCluster() *schema.Resource { Default: ingressReady, DiffSuppressFunc: flex.ApplyOnce, ValidateFunc: validation.StringInSlice([]string{masterNodeReady, oneWorkerNodeReady, ingressReady, clusterNormal}, true), - Description: "wait_till can be configured for Master Ready, One worker Ready or Ingress Ready or Normal", + Description: "wait_till can be configured for Master Ready, One worker Ready, Ingress Ready or Normal", }, "entitlement": { @@ -635,7 +635,7 @@ func resourceIBMContainerVpcClusterCreate(d *schema.ResourceData, meta interface params.SecurityGroupIDs = securityGroups } - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -654,34 +654,11 @@ func resourceIBMContainerVpcClusterCreate(d *schema.ResourceData, meta interface } } - switch timeoutStage { - - case strings.ToLower(clusterNormal): - pendingStates := []string{clusterDeploying, clusterRequested, clusterPending, clusterDeployed, clusterCritical, clusterWarning} - _, err = waitForVpcClusterState(d, meta, clusterNormal, pendingStates) - if err != nil { - return err - } - - case strings.ToLower(masterNodeReady): - _, err = waitForVpcClusterMasterAvailable(d, meta) - if err != nil { - return err - } - - case strings.ToLower(oneWorkerNodeReady): - _, err = waitForVpcClusterOneWorkerAvailable(d, meta) - if err != nil { - return err - } - - case strings.ToLower(ingressReady): - _, err = waitForVpcClusterIngressAvailable(d, meta) - if err != nil { - return err - } - + err = waitForVpcCluster(d, meta, timeoutStage, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return err } + var taints []interface{} if taintRes, ok := d.GetOk("taints"); ok { taints = taintRes.(*schema.Set).List() @@ -691,7 +668,6 @@ func resourceIBMContainerVpcClusterCreate(d *schema.ResourceData, meta interface } return resourceIBMContainerVpcClusterUpdate(d, meta) - } func resourceIBMContainerVpcClusterUpdate(d *schema.ResourceData, meta interface{}) error { @@ -701,7 +677,7 @@ func resourceIBMContainerVpcClusterUpdate(d *schema.ResourceData, meta interface return err } - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -777,7 +753,7 @@ func resourceIBMContainerVpcClusterUpdate(d *schema.ResourceData, meta interface return err } - Env, err := getVpcClusterTargetHeader(d, meta) + Env, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -813,7 +789,7 @@ func resourceIBMContainerVpcClusterUpdate(d *schema.ResourceData, meta interface if Error != nil { return Error } - _, err = WaitForVpcClusterVersionUpdate(d, meta, targetEnv) + _, err = waitForVpcClusterVersionUpdate(d, meta, targetEnv) if err != nil { return fmt.Errorf("[ERROR] Error waiting for cluster (%s) version to be updated: %s", d.Id(), err) } @@ -823,16 +799,12 @@ func resourceIBMContainerVpcClusterUpdate(d *schema.ResourceData, meta interface if err != nil { return err } - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } clusterID := d.Id() - cls, err := csClient.Clusters().GetCluster(clusterID, targetEnv) - if err != nil { - return fmt.Errorf("[ERROR] Error retrieving conatiner vpc cluster: %s", err) - } // Update the worker nodes after master node kube-version is updated. // workers will store the existing workers info to identify the replaced node @@ -891,7 +863,7 @@ func resourceIBMContainerVpcClusterUpdate(d *schema.ResourceData, meta interface workersInfo[newWorkerID] = index //4. wait for the worker's version update and normal state - _, Err := WaitForVpcClusterWokersVersionUpdate(d, meta, targetEnv, cls.MasterKubeVersion, newWorkerID) + _, Err := waitForVpcClusterWokersVersionUpdate(d, meta, targetEnv, newWorkerID) if Err != nil { d.Set("patch_version", nil) return fmt.Errorf( @@ -926,39 +898,6 @@ func resourceIBMContainerVpcClusterUpdate(d *schema.ResourceData, meta interface return resourceIBMContainerVpcClusterRead(d, meta) } -func WaitForV2WorkerZoneDeleted(clusterNameOrID, workerPoolNameOrID, zone string, meta interface{}, timeout time.Duration, target v2.ClusterTargetHeader) (interface{}, error) { - csClient, err := meta.(conns.ClientSession).VpcContainerAPI() - if err != nil { - return nil, err - } - stateConf := &resource.StateChangeConf{ - Pending: []string{"deleting"}, - Target: []string{workerDeleteState}, - Refresh: workerPoolV2ZoneDeleteStateRefreshFunc(csClient.Workers(), clusterNameOrID, workerPoolNameOrID, zone, target), - Timeout: timeout, - Delay: 10 * time.Second, - MinTimeout: 10 * time.Second, - } - - return stateConf.WaitForState() -} -func workerPoolV2ZoneDeleteStateRefreshFunc(client v2.Workers, instanceID, workerPoolNameOrID, zone string, target v2.ClusterTargetHeader) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - workerFields, err := client.ListByWorkerPool(instanceID, workerPoolNameOrID, true, target) - if err != nil { - return nil, "", fmt.Errorf("[ERROR] Error retrieving workers for cluster: %s", err) - } - //Done worker has two fields State and Status , so check for those 2 - for _, e := range workerFields { - if e.Location == zone { - if strings.Compare(e.LifeCycle.ActualState, "deleted") != 0 { - return workerFields, "deleting", nil - } - } - } - return workerFields, workerDeleteState, nil - } -} func resourceIBMContainerVpcClusterRead(d *schema.ResourceData, meta interface{}) error { csClient, err := meta.(conns.ClientSession).VpcContainerAPI() @@ -967,7 +906,7 @@ func resourceIBMContainerVpcClusterRead(d *schema.ResourceData, meta interface{} } albsAPI := csClient.Albs() - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -1033,7 +972,7 @@ func resourceIBMContainerVpcClusterRead(d *schema.ResourceData, meta interface{} func resourceIBMContainerVpcClusterDelete(d *schema.ResourceData, meta interface{}) error { - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -1093,10 +1032,35 @@ func resourceIBMContainerVpcClusterDelete(d *schema.ResourceData, meta interface } return nil } + +func resourceIBMContainerVpcClusterExists(d *schema.ResourceData, meta interface{}) (bool, error) { + + csClient, err := meta.(conns.ClientSession).VpcContainerAPI() + if err != nil { + return false, err + } + targetEnv, err := getVpcClusterTargetHeader(d) + if err != nil { + return false, err + } + clusterID := d.Id() + cls, err := csClient.Clusters().GetCluster(clusterID, targetEnv) + if err != nil { + if apiErr, ok := err.(bmxerror.RequestFailure); ok { + if apiErr.StatusCode() == 404 && strings.Contains(apiErr.Description(), "The specified cluster could not be found") { + return false, nil + } + } + return false, fmt.Errorf("[ERROR] Error getting container vpc cluster: %s", err) + } + return cls.ID == clusterID, nil +} + func vpcClient(meta interface{}) (*vpcv1.VpcV1, error) { sess, err := meta.(conns.ClientSession).VpcV1API() return sess, err } + func isWaitForLBDeleted(lbc *vpcv1.VpcV1, id string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for (%s) to be deleted.", id) @@ -1111,6 +1075,7 @@ func isWaitForLBDeleted(lbc *vpcv1.VpcV1, id string, timeout time.Duration) (int return stateConf.WaitForState() } + func isLBDeleteRefreshFunc(lbc *vpcv1.VpcV1, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { log.Printf("[DEBUG] is lb delete function here") @@ -1128,8 +1093,41 @@ func isLBDeleteRefreshFunc(lbc *vpcv1.VpcV1, id string) resource.StateRefreshFun } } +func waitForVpcCluster(d *schema.ResourceData, meta interface{}, timeoutStage string, timeout time.Duration) error { + var err error + switch timeoutStage { + + case strings.ToLower(clusterNormal): + pendingStates := []string{clusterDeploying, clusterRequested, clusterPending, clusterDeployed, clusterCritical, clusterWarning} + _, err = waitForVpcClusterState(d, meta, clusterNormal, pendingStates, timeout) + if err != nil { + return err + } + + case strings.ToLower(masterNodeReady): + _, err = waitForVpcClusterMasterAvailable(d, meta, timeout) + if err != nil { + return err + } + + case strings.ToLower(oneWorkerNodeReady): + _, err = waitForVpcClusterOneWorkerAvailable(d, meta, timeout) + if err != nil { + return err + } + + case strings.ToLower(ingressReady): + _, err = waitForVpcClusterIngressAvailable(d, meta, timeout) + if err != nil { + return err + } + } + + return nil +} + func waitForVpcClusterDelete(d *schema.ResourceData, meta interface{}) (interface{}, error) { - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return nil, err } @@ -1160,8 +1158,8 @@ func waitForVpcClusterDelete(d *schema.ResourceData, meta interface{}) (interfac return deleteStateConf.WaitForState() } -func waitForVpcClusterOneWorkerAvailable(d *schema.ResourceData, meta interface{}) (interface{}, error) { - targetEnv, err := getVpcClusterTargetHeader(d, meta) +func waitForVpcClusterOneWorkerAvailable(d *schema.ResourceData, meta interface{}, timeout time.Duration) (interface{}, error) { + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return nil, err } @@ -1193,7 +1191,7 @@ func waitForVpcClusterOneWorkerAvailable(d *schema.ResourceData, meta interface{ return workers, deployInProgress, nil }, - Timeout: d.Timeout(schema.TimeoutCreate), + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 5 * time.Second, ContinuousTargetOccurence: 3, @@ -1201,8 +1199,8 @@ func waitForVpcClusterOneWorkerAvailable(d *schema.ResourceData, meta interface{ return createStateConf.WaitForState() } -func waitForVpcClusterState(d *schema.ResourceData, meta interface{}, waitForState string, pendingState []string) (interface{}, error) { - targetEnv, err := getVpcClusterTargetHeader(d, meta) +func waitForVpcClusterState(d *schema.ResourceData, meta interface{}, waitForState string, pendingState []string, timeout time.Duration) (interface{}, error) { + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return nil, err } @@ -1229,7 +1227,7 @@ func waitForVpcClusterState(d *schema.ResourceData, meta interface{}, waitForSta return clusterInfo, clusterInfo.State, nil }, - Timeout: d.Timeout(schema.TimeoutCreate), + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 5 * time.Second, ContinuousTargetOccurence: 3, @@ -1237,8 +1235,8 @@ func waitForVpcClusterState(d *schema.ResourceData, meta interface{}, waitForSta return createStateConf.WaitForState() } -func waitForVpcClusterMasterAvailable(d *schema.ResourceData, meta interface{}) (interface{}, error) { - targetEnv, err := getVpcClusterTargetHeader(d, meta) +func waitForVpcClusterMasterAvailable(d *schema.ResourceData, meta interface{}, timeout time.Duration) (interface{}, error) { + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return nil, err } @@ -1263,7 +1261,7 @@ func waitForVpcClusterMasterAvailable(d *schema.ResourceData, meta interface{}) return clusterInfo, deployInProgress, nil }, - Timeout: d.Timeout(schema.TimeoutCreate), + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 5 * time.Second, ContinuousTargetOccurence: 3, @@ -1273,7 +1271,7 @@ func waitForVpcClusterMasterAvailable(d *schema.ResourceData, meta interface{}) func waitForVpcClusterMasterKMSApply(d *schema.ResourceData, meta interface{}) (interface{}, error) { log.Printf("[DEBUG] Wait for KMS to apply to master") - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return nil, err } @@ -1313,8 +1311,8 @@ func waitForVpcClusterMasterKMSApply(d *schema.ResourceData, meta interface{}) ( return createStateConf.WaitForState() } -func waitForVpcClusterIngressAvailable(d *schema.ResourceData, meta interface{}) (interface{}, error) { - targetEnv, err := getVpcClusterTargetHeader(d, meta) +func waitForVpcClusterIngressAvailable(d *schema.ResourceData, meta interface{}, timeout time.Duration) (interface{}, error) { + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return nil, err } @@ -1339,7 +1337,7 @@ func waitForVpcClusterIngressAvailable(d *schema.ResourceData, meta interface{}) return clusterInfo, deployInProgress, nil }, - Timeout: d.Timeout(schema.TimeoutCreate), + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 5 * time.Second, ContinuousTargetOccurence: 3, @@ -1347,7 +1345,7 @@ func waitForVpcClusterIngressAvailable(d *schema.ResourceData, meta interface{}) return createStateConf.WaitForState() } -func getVpcClusterTargetHeader(d *schema.ResourceData, meta interface{}) (v2.ClusterTargetHeader, error) { +func getVpcClusterTargetHeader(d *schema.ResourceData) (v2.ClusterTargetHeader, error) { targetEnv := v2.ClusterTargetHeader{} var resourceGroup string if rg, ok := d.GetOk("resource_group_id"); ok { @@ -1358,31 +1356,8 @@ func getVpcClusterTargetHeader(d *schema.ResourceData, meta interface{}) (v2.Clu return targetEnv, nil } -func resourceIBMContainerVpcClusterExists(d *schema.ResourceData, meta interface{}) (bool, error) { - - csClient, err := meta.(conns.ClientSession).VpcContainerAPI() - if err != nil { - return false, err - } - targetEnv, err := getVpcClusterTargetHeader(d, meta) - if err != nil { - return false, err - } - clusterID := d.Id() - cls, err := csClient.Clusters().GetCluster(clusterID, targetEnv) - if err != nil { - if apiErr, ok := err.(bmxerror.RequestFailure); ok { - if apiErr.StatusCode() == 404 && strings.Contains(apiErr.Description(), "The specified cluster could not be found") { - return false, nil - } - } - return false, fmt.Errorf("[ERROR] Error getting container vpc cluster: %s", err) - } - return cls.ID == clusterID, nil -} - -// WaitForVpcClusterVersionUpdate Waits for cluster creation -func WaitForVpcClusterVersionUpdate(d *schema.ResourceData, meta interface{}, target v2.ClusterTargetHeader) (interface{}, error) { +// waitForVpcClusterVersionUpdate Waits for cluster creation +func waitForVpcClusterVersionUpdate(d *schema.ResourceData, meta interface{}, target v2.ClusterTargetHeader) (interface{}, error) { csClient, err := meta.(conns.ClientSession).VpcContainerAPI() if err != nil { return nil, err @@ -1419,8 +1394,8 @@ func vpcClusterVersionRefreshFunc(client v2.Clusters, instanceID string, d *sche } } -// WaitForVpcClusterWokersVersionUpdate Waits for Cluster version Update -func WaitForVpcClusterWokersVersionUpdate(d *schema.ResourceData, meta interface{}, target v2.ClusterTargetHeader, masterVersion, workerID string) (interface{}, error) { +// waitForVpcClusterWokersVersionUpdate Waits for Cluster version Update +func waitForVpcClusterWokersVersionUpdate(d *schema.ResourceData, meta interface{}, target v2.ClusterTargetHeader, workerID string) (interface{}, error) { csClient, err := meta.(conns.ClientSession).VpcContainerAPI() if err != nil { return nil, err @@ -1431,7 +1406,7 @@ func WaitForVpcClusterWokersVersionUpdate(d *schema.ResourceData, meta interface stateConf := &resource.StateChangeConf{ Pending: []string{"retry", versionUpdating}, Target: []string{workerNormal}, - Refresh: vpcClusterWorkersVersionRefreshFunc(csClient.Workers(), workerID, clusterID, d, target, masterVersion), + Refresh: vpcClusterWorkersVersionRefreshFunc(csClient.Workers(), workerID, clusterID, target), Timeout: d.Timeout(schema.TimeoutUpdate), Delay: 10 * time.Second, MinTimeout: 10 * time.Second, @@ -1441,7 +1416,7 @@ func WaitForVpcClusterWokersVersionUpdate(d *schema.ResourceData, meta interface return stateConf.WaitForState() } -func vpcClusterWorkersVersionRefreshFunc(client v2.Workers, workerID, clusterID string, d *schema.ResourceData, target v2.ClusterTargetHeader, masterVersion string) resource.StateRefreshFunc { +func vpcClusterWorkersVersionRefreshFunc(client v2.Workers, workerID, clusterID string, target v2.ClusterTargetHeader) resource.StateRefreshFunc { return func() (interface{}, string, error) { worker, err := client.Get(clusterID, workerID, target) if err != nil { diff --git a/ibm/service/kubernetes/resource_ibm_container_vpc_cluster_test.go b/ibm/service/kubernetes/resource_ibm_container_vpc_cluster_test.go index 7d9c8f0b69..1f18527d19 100644 --- a/ibm/service/kubernetes/resource_ibm_container_vpc_cluster_test.go +++ b/ibm/service/kubernetes/resource_ibm_container_vpc_cluster_test.go @@ -31,7 +31,7 @@ func TestAccIBMContainerVpcClusterBasic(t *testing.T) { CheckDestroy: testAccCheckIBMContainerVpcClusterDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckIBMContainerVpcClusterBasic(name), + Config: testAccCheckIBMContainerVpcClusterBasic(name, "OneWorkerNodeReady"), Check: resource.ComposeTestCheckFunc( testAccCheckIBMContainerVpcExists("ibm_container_vpc_cluster.cluster", conf), resource.TestCheckResourceAttr( @@ -58,10 +58,6 @@ func TestAccIBMContainerVpcClusterBasic(t *testing.T) { "ibm_container_vpc_cluster.cluster", "worker_count", "1"), resource.TestCheckResourceAttr( "ibm_container_vpc_cluster.cluster", "flavor", "cx2.2x4"), - resource.TestCheckResourceAttr( - "ibm_container_vpc_cluster.cluster", "zones.#", "2"), - resource.TestCheckResourceAttr( - "ibm_container_vpc_cluster.cluster", "worker_labels.%", "2"), resource.TestCheckResourceAttr( "ibm_container_vpc_cluster.cluster", "kms_config.#", "1"), ), @@ -71,7 +67,9 @@ func TestAccIBMContainerVpcClusterBasic(t *testing.T) { ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{ - "wait_till", "update_all_workers", "kms_config", "force_delete_storage", "wait_for_worker_update"}, + "wait_till", "update_all_workers", "kms_config", "force_delete_storage", "wait_for_worker_update", + "disable_outbound_traffic_protection", "flavor", "worker_count", "worker_labels", "zones", + }, }, }, }) @@ -302,11 +300,9 @@ func getVpcClusterTargetHeaderTestACC() v2.ClusterTargetHeader { return targetEnv } -func testAccCheckIBMContainerVpcClusterBasic(name string) string { +func testAccCheckIBMContainerVpcClusterBasic(name, wait_till string) string { + region := acc.Region() return fmt.Sprintf(` -provider "ibm" { - region ="eu-de" -} data "ibm_resource_group" "resource_group" { is_default = "true" //name = "Default" @@ -317,14 +313,14 @@ resource "ibm_is_vpc" "vpc" { resource "ibm_is_subnet" "subnet" { name = "%[1]s" vpc = ibm_is_vpc.vpc.id - zone = "eu-de-1" + zone = "%[2]s-1" total_ipv4_address_count = 256 } resource "ibm_resource_instance" "kms_instance" { name = "%[1]s" service = "kms" plan = "tiered-pricing" - location = "eu-de" + location = "%[2]s" } resource "ibm_kms_key" "test" { @@ -338,11 +334,11 @@ resource "ibm_container_vpc_cluster" "cluster" { vpc_id = ibm_is_vpc.vpc.id flavor = "cx2.2x4" worker_count = 1 - wait_till = "OneWorkerNodeReady" + wait_till = "%[3]s" resource_group_id = data.ibm_resource_group.resource_group.id zones { subnet_id = ibm_is_subnet.subnet.id - name = "eu-de-1" + name = "%[2]s-1" } kms_config { instance_id = ibm_resource_instance.kms_instance.guid @@ -355,7 +351,69 @@ resource "ibm_container_vpc_cluster" "cluster" { "test2" = "test-default-pool2" } - }`, name) + }`, name, region, wait_till) +} + +func testAccCheckIBMContainerVpcClusterUpdate(name string) string { + region := acc.Region() + return fmt.Sprintf(` +data "ibm_resource_group" "resource_group" { + is_default = "true" +} +resource "ibm_is_vpc" "vpc" { + name = "%[1]s" +} +resource "ibm_is_subnet" "subnet" { + name = "%[1]s" + vpc = ibm_is_vpc.vpc.id + zone = "%[2]s-1" + total_ipv4_address_count = 256 +} +resource "ibm_is_subnet" "subnet2" { + name = "%[1]s-2" + vpc = ibm_is_vpc.vpc.id + zone = "%[2]s-2" + total_ipv4_address_count = 256 +} +resource "ibm_resource_instance" "kms_instance" { + name = "%[1]s" + service = "kms" + plan = "tiered-pricing" + location = "%[2]s" +} + +resource "ibm_kms_key" "test" { + instance_id = ibm_resource_instance.kms_instance.guid + key_name = "%[1]s" + standard_key = false + force_delete = true +} +resource "ibm_container_vpc_cluster" "cluster" { + name = "%[1]s" + vpc_id = ibm_is_vpc.vpc.id + flavor = "cx2.2x4" + worker_count = 1 + wait_till = "OneWorkerNodeReady" + resource_group_id = data.ibm_resource_group.resource_group.id + zones { + subnet_id = ibm_is_subnet.subnet.id + name = "%[2]s-1" + } + zones { + subnet_id = ibm_is_subnet.subnet2.id + name = "%[2]s-2" + } + kms_config { + instance_id = ibm_resource_instance.kms_instance.guid + crk_id = ibm_kms_key.test.key_id + private_endpoint = false + } + worker_labels = { + "test" = "test-default-pool" + "test1" = "test-default-pool1" + } + + }`, name, region) } func testAccCheckIBMContainerVpcClusterDisableOutboundTrafficProtection(name, kubeVersion, disable_outbound_traffic_protection string) string { @@ -528,70 +586,6 @@ func testAccCheckIBMContainerVpcClusterSecurityGroups(name string) string { }`, name) } -func testAccCheckIBMContainerVpcClusterUpdate(name string) string { - return fmt.Sprintf(` -provider "ibm" { - region ="eu-de" -} -data "ibm_resource_group" "resource_group" { - is_default = "true" -} -resource "ibm_is_vpc" "vpc" { - name = "%[1]s" -} -resource "ibm_is_subnet" "subnet" { - name = "%[1]s" - vpc = ibm_is_vpc.vpc.id - zone = "eu-de-1" - total_ipv4_address_count = 256 -} -resource "ibm_is_subnet" "subnet2" { - name = "%[1]s-2" - vpc = ibm_is_vpc.vpc.id - zone = "eu-de-2" - total_ipv4_address_count = 256 -} -resource "ibm_resource_instance" "kms_instance" { - name = "%[1]s" - service = "kms" - plan = "tiered-pricing" - location = "eu-de" -} - -resource "ibm_kms_key" "test" { - instance_id = ibm_resource_instance.kms_instance.guid - key_name = "%[1]s" - standard_key = false - force_delete = true -} -resource "ibm_container_vpc_cluster" "cluster" { - name = "%[1]s" - vpc_id = ibm_is_vpc.vpc.id - flavor = "cx2.2x4" - worker_count = 1 - wait_till = "OneWorkerNodeReady" - resource_group_id = data.ibm_resource_group.resource_group.id - zones { - subnet_id = ibm_is_subnet.subnet.id - name = "eu-de-1" - } - zones { - subnet_id = ibm_is_subnet.subnet2.id - name = "eu-de-2" - } - kms_config { - instance_id = ibm_resource_instance.kms_instance.guid - crk_id = ibm_kms_key.test.key_id - private_endpoint = false - } - worker_labels = { - "test" = "test-default-pool" - "test1" = "test-default-pool1" - } - - }`, name) -} - func testAccCheckIBMContainerOcpClusterBasic(name, openshiftFlavour, openShiftworkerCount, operatingSystem string) string { return fmt.Sprintf(` data "ibm_resource_instance" "cos_instance" { diff --git a/ibm/service/kubernetes/resource_ibm_container_vpc_worker.go b/ibm/service/kubernetes/resource_ibm_container_vpc_worker.go index 5fbadaeb16..e45f55a5c4 100644 --- a/ibm/service/kubernetes/resource_ibm_container_vpc_worker.go +++ b/ibm/service/kubernetes/resource_ibm_container_vpc_worker.go @@ -252,7 +252,7 @@ func resourceIBMContainerVpcWorkerCreate(d *schema.ResourceData, meta interface{ return err } - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -379,7 +379,7 @@ func resourceIBMContainerVpcWorkerExists(d *schema.ResourceData, meta interface{ } cluster := parts[1] - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return false, err } diff --git a/ibm/service/kubernetes/resource_ibm_container_vpc_worker_pool.go b/ibm/service/kubernetes/resource_ibm_container_vpc_worker_pool.go index 477994c5bc..7baf4aa27f 100644 --- a/ibm/service/kubernetes/resource_ibm_container_vpc_worker_pool.go +++ b/ibm/service/kubernetes/resource_ibm_container_vpc_worker_pool.go @@ -278,7 +278,7 @@ func resourceIBMContainerVpcWorkerPoolCreate(d *schema.ResourceData, meta interf //read to get ID for default and d.Set! - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -365,7 +365,7 @@ func resourceIBMContainerVpcWorkerPoolCreate(d *schema.ResourceData, meta interf } workerPoolsAPI := wpClient.WorkerPools() - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -407,7 +407,7 @@ func resourceIBMContainerVpcWorkerPoolUpdate(d *schema.ResourceData, meta interf } } - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -437,7 +437,7 @@ func resourceIBMContainerVpcWorkerPoolUpdate(d *schema.ResourceData, meta interf clusterNameOrID := d.Get("cluster").(string) workerPoolName := d.Get("worker_pool_name").(string) count := d.Get("worker_count").(int) - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -456,7 +456,7 @@ func resourceIBMContainerVpcWorkerPoolUpdate(d *schema.ResourceData, meta interf if d.HasChange("zones") { clusterID := d.Get("cluster").(string) workerPoolName := d.Get("worker_pool_name").(string) - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -518,11 +518,46 @@ func resourceIBMContainerVpcWorkerPoolUpdate(d *schema.ResourceData, meta interf return resourceIBMContainerVpcWorkerPoolRead(d, meta) } +func WaitForV2WorkerZoneDeleted(clusterNameOrID, workerPoolNameOrID, zone string, meta interface{}, timeout time.Duration, target v2.ClusterTargetHeader) (interface{}, error) { + csClient, err := meta.(conns.ClientSession).VpcContainerAPI() + if err != nil { + return nil, err + } + stateConf := &resource.StateChangeConf{ + Pending: []string{"deleting"}, + Target: []string{workerDeleteState}, + Refresh: workerPoolV2ZoneDeleteStateRefreshFunc(csClient.Workers(), clusterNameOrID, workerPoolNameOrID, zone, target), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + return stateConf.WaitForState() +} + +func workerPoolV2ZoneDeleteStateRefreshFunc(client v2.Workers, instanceID, workerPoolNameOrID, zone string, target v2.ClusterTargetHeader) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + workerFields, err := client.ListByWorkerPool(instanceID, workerPoolNameOrID, true, target) + if err != nil { + return nil, "", fmt.Errorf("[ERROR] Error retrieving workers for cluster: %s", err) + } + //Done worker has two fields State and Status , so check for those 2 + for _, e := range workerFields { + if e.Location == zone { + if strings.Compare(e.LifeCycle.ActualState, "deleted") != 0 { + return workerFields, "deleting", nil + } + } + } + return workerFields, workerDeleteState, nil + } +} + func updateWorkerpoolTaints(d *schema.ResourceData, meta interface{}, clusterNameOrID string, workerPoolName string, taints []interface{}) error { taintParam := expandWorkerPoolTaints(clusterNameOrID, workerPoolName, taints) - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -580,7 +615,7 @@ func resourceIBMContainerVpcWorkerPoolRead(d *schema.ResourceData, meta interfac workerPoolID := parts[1] workerPoolsAPI := wpClient.WorkerPools() - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -653,7 +688,7 @@ func resourceIBMContainerVpcWorkerPoolDelete(d *schema.ResourceData, meta interf workerPoolNameorID := parts[1] workerPoolsAPI := wpClient.WorkerPools() - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -686,7 +721,7 @@ func resourceIBMContainerVpcWorkerPoolExists(d *schema.ResourceData, meta interf workerPoolID := parts[1] workerPoolsAPI := wpClient.WorkerPools() - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return false, err } diff --git a/ibm/service/kubernetes/resource_ibm_ob_logging.go b/ibm/service/kubernetes/resource_ibm_ob_logging.go index 74b7663d3c..ba7bd721fa 100644 --- a/ibm/service/kubernetes/resource_ibm_ob_logging.go +++ b/ibm/service/kubernetes/resource_ibm_ob_logging.go @@ -119,7 +119,7 @@ func ResourceIBMObLogging() *schema.Resource { } } func waitForClusterIntegration(d *schema.ResourceData, meta interface{}, clusterID string) (interface{}, error) { - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return nil, err } diff --git a/ibm/service/logs/data_source_ibm_logs_outgoing_webhook.go b/ibm/service/logs/data_source_ibm_logs_outgoing_webhook.go index cd31eaa93d..5ab42bb485 100644 --- a/ibm/service/logs/data_source_ibm_logs_outgoing_webhook.go +++ b/ibm/service/logs/data_source_ibm_logs_outgoing_webhook.go @@ -167,11 +167,11 @@ func DataSourceIbmLogsOutgoingWebhookOutgoingWebhooksV1IbmEventNotificationsConf modelMap := make(map[string]interface{}) modelMap["event_notifications_instance_id"] = model.EventNotificationsInstanceID.String() modelMap["region_id"] = *model.RegionID - // if model.SourceID != nil { - // modelMap["source_id"] = *model.SourceID - // } - // if model.SourceName != nil { - // modelMap["source_name"] = *model.SourceName - // } + if model.SourceID != nil { + modelMap["source_id"] = *model.SourceID + } + if model.SourceName != nil { + modelMap["source_name"] = *model.SourceName + } return modelMap, nil } diff --git a/ibm/service/logs/resource_ibm_logs_alert.go b/ibm/service/logs/resource_ibm_logs_alert.go index 9afb5821b6..7cc44686be 100644 --- a/ibm/service/logs/resource_ibm_logs_alert.go +++ b/ibm/service/logs/resource_ibm_logs_alert.go @@ -1269,11 +1269,13 @@ func ResourceIbmLogsAlert() *schema.Resource { "retriggering_period_seconds": &schema.Schema{ Type: schema.TypeInt, Optional: true, + Computed: true, Description: "Retriggering period of the alert in seconds.", }, "notify_on": &schema.Schema{ Type: schema.TypeString, Optional: true, + Computed: true, Description: "Notify on setting.", }, "integration_id": &schema.Schema{ @@ -1616,12 +1618,14 @@ func resourceIbmLogsAlertCreate(context context.Context, d *schema.ResourceData, createAlertOptions.SetCondition(conditionModel) var notificationGroups []logsv0.AlertsV2AlertNotificationGroups for _, v := range d.Get("notification_groups").([]interface{}) { - value := v.(map[string]interface{}) - notificationGroupsItem, err := ResourceIbmLogsAlertMapToAlertsV2AlertNotificationGroups(value) - if err != nil { - return diag.FromErr(err) + if v != nil { + value := v.(map[string]interface{}) + notificationGroupsItem, err := ResourceIbmLogsAlertMapToAlertsV2AlertNotificationGroups(value) + if err != nil { + return diag.FromErr(err) + } + notificationGroups = append(notificationGroups, *notificationGroupsItem) } - notificationGroups = append(notificationGroups, *notificationGroupsItem) } createAlertOptions.SetNotificationGroups(notificationGroups) filtersModel, err := ResourceIbmLogsAlertMapToAlertsV1AlertFilters(d.Get("filters.0").(map[string]interface{})) @@ -1873,12 +1877,14 @@ func resourceIbmLogsAlertUpdate(context context.Context, d *schema.ResourceData, var notificationGroups []logsv0.AlertsV2AlertNotificationGroups for _, v := range d.Get("notification_groups").([]interface{}) { - value := v.(map[string]interface{}) - notificationGroupsItem, err := ResourceIbmLogsAlertMapToAlertsV2AlertNotificationGroups(value) - if err != nil { - return diag.FromErr(err) + if v != nil { + value := v.(map[string]interface{}) + notificationGroupsItem, err := ResourceIbmLogsAlertMapToAlertsV2AlertNotificationGroups(value) + if err != nil { + return diag.FromErr(err) + } + notificationGroups = append(notificationGroups, *notificationGroupsItem) } - notificationGroups = append(notificationGroups, *notificationGroupsItem) } updateAlertOptions.SetNotificationGroups(notificationGroups) @@ -1989,56 +1995,56 @@ func resourceIbmLogsAlertDelete(context context.Context, d *schema.ResourceData, func ResourceIbmLogsAlertMapToAlertsV2AlertCondition(modelMap map[string]interface{}) (logsv0.AlertsV2AlertConditionIntf, error) { model := &logsv0.AlertsV2AlertCondition{} if modelMap["immediate"] != nil && len(modelMap["immediate"].([]interface{})) > 0 { - ImmediateModel, err := ResourceIbmLogsAlertMapToAlertsV2ImmediateConditionEmpty(modelMap["immediate"].([]interface{})[0].(map[string]interface{})) + ImmediateModel, err := ResourceIbmLogsAlertMapToAlertsV2ImmediateConditionEmpty(modelMap["immediate"].([]interface{})) if err != nil { return model, err } model.Immediate = ImmediateModel } if modelMap["less_than"] != nil && len(modelMap["less_than"].([]interface{})) > 0 { - LessThanModel, err := ResourceIbmLogsAlertMapToAlertsV2LessThanCondition(modelMap["less_than"].([]interface{})[0].(map[string]interface{})) + LessThanModel, err := ResourceIbmLogsAlertMapToAlertsV2LessThanCondition(modelMap["less_than"].([]interface{})) if err != nil { return model, err } model.LessThan = LessThanModel } if modelMap["more_than"] != nil && len(modelMap["more_than"].([]interface{})) > 0 { - MoreThanModel, err := ResourceIbmLogsAlertMapToAlertsV2MoreThanCondition(modelMap["more_than"].([]interface{})[0].(map[string]interface{})) + MoreThanModel, err := ResourceIbmLogsAlertMapToAlertsV2MoreThanCondition(modelMap["more_than"].([]interface{})) if err != nil { return model, err } model.MoreThan = MoreThanModel } if modelMap["more_than_usual"] != nil && len(modelMap["more_than_usual"].([]interface{})) > 0 { - MoreThanUsualModel, err := ResourceIbmLogsAlertMapToAlertsV2MoreThanUsualCondition(modelMap["more_than_usual"].([]interface{})[0].(map[string]interface{})) + MoreThanUsualModel, err := ResourceIbmLogsAlertMapToAlertsV2MoreThanUsualCondition(modelMap["more_than_usual"].([]interface{})) if err != nil { return model, err } model.MoreThanUsual = MoreThanUsualModel } if modelMap["new_value"] != nil && len(modelMap["new_value"].([]interface{})) > 0 { - NewValueModel, err := ResourceIbmLogsAlertMapToAlertsV2NewValueCondition(modelMap["new_value"].([]interface{})[0].(map[string]interface{})) + NewValueModel, err := ResourceIbmLogsAlertMapToAlertsV2NewValueCondition(modelMap["new_value"].([]interface{})) if err != nil { return model, err } model.NewValue = NewValueModel } if modelMap["flow"] != nil && len(modelMap["flow"].([]interface{})) > 0 { - FlowModel, err := ResourceIbmLogsAlertMapToAlertsV2FlowCondition(modelMap["flow"].([]interface{})[0].(map[string]interface{})) + FlowModel, err := ResourceIbmLogsAlertMapToAlertsV2FlowCondition(modelMap["flow"].([]interface{})) if err != nil { return model, err } model.Flow = FlowModel } if modelMap["unique_count"] != nil && len(modelMap["unique_count"].([]interface{})) > 0 { - UniqueCountModel, err := ResourceIbmLogsAlertMapToAlertsV2UniqueCountCondition(modelMap["unique_count"].([]interface{})[0].(map[string]interface{})) + UniqueCountModel, err := ResourceIbmLogsAlertMapToAlertsV2UniqueCountCondition(modelMap["unique_count"].([]interface{})) if err != nil { return model, err } model.UniqueCount = UniqueCountModel } if modelMap["less_than_usual"] != nil && len(modelMap["less_than_usual"].([]interface{})) > 0 { - LessThanUsualModel, err := ResourceIbmLogsAlertMapToAlertsV2LessThanUsualCondition(modelMap["less_than_usual"].([]interface{})[0].(map[string]interface{})) + LessThanUsualModel, err := ResourceIbmLogsAlertMapToAlertsV2LessThanUsualCondition(modelMap["less_than_usual"].([]interface{})) if err != nil { return model, err } @@ -2047,172 +2053,208 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertCondition(modelMap map[string]interfa return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2ImmediateConditionEmpty(modelMap map[string]interface{}) (*logsv0.AlertsV2ImmediateConditionEmpty, error) { +func ResourceIbmLogsAlertMapToAlertsV2ImmediateConditionEmpty(modelMap interface{}) (*logsv0.AlertsV2ImmediateConditionEmpty, error) { model := &logsv0.AlertsV2ImmediateConditionEmpty{} return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2LessThanCondition(modelMap map[string]interface{}) (*logsv0.AlertsV2LessThanCondition, error) { +func ResourceIbmLogsAlertMapToAlertsV2LessThanCondition(modelMap []interface{}) (*logsv0.AlertsV2LessThanCondition, error) { model := &logsv0.AlertsV2LessThanCondition{} - ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMapElement["parameters"].([]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel } - model.Parameters = ParametersModel + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMap map[string]interface{}) (*logsv0.AlertsV2ConditionParameters, error) { +func ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMap []interface{}) (*logsv0.AlertsV2ConditionParameters, error) { model := &logsv0.AlertsV2ConditionParameters{} - model.Threshold = core.Float64Ptr(modelMap["threshold"].(float64)) - model.Timeframe = core.StringPtr(modelMap["timeframe"].(string)) - if modelMap["group_by"] != nil { - groupBy := []string{} - for _, groupByItem := range modelMap["group_by"].([]interface{}) { - groupBy = append(groupBy, groupByItem.(string)) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + model.Threshold = core.Float64Ptr(modelMapElement["threshold"].(float64)) + model.Timeframe = core.StringPtr(modelMapElement["timeframe"].(string)) + if modelMapElement["group_by"] != nil { + groupBy := []string{} + for _, groupByItem := range modelMapElement["group_by"].([]interface{}) { + groupBy = append(groupBy, groupByItem.(string)) + } + model.GroupBy = groupBy } - model.GroupBy = groupBy - } - if modelMap["metric_alert_parameters"] != nil && len(modelMap["metric_alert_parameters"].([]interface{})) > 0 { - MetricAlertParametersModel, err := ResourceIbmLogsAlertMapToAlertsV1MetricAlertConditionParameters(modelMap["metric_alert_parameters"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if modelMapElement["metric_alert_parameters"] != nil && len(modelMapElement["metric_alert_parameters"].([]interface{})) > 0 { + MetricAlertParametersModel, err := ResourceIbmLogsAlertMapToAlertsV1MetricAlertConditionParameters(modelMapElement["metric_alert_parameters"].([]interface{})) + if err != nil { + return model, err + } + model.MetricAlertParameters = MetricAlertParametersModel } - model.MetricAlertParameters = MetricAlertParametersModel - } - if modelMap["metric_alert_promql_parameters"] != nil && len(modelMap["metric_alert_promql_parameters"].([]interface{})) > 0 { - MetricAlertPromqlParametersModel, err := ResourceIbmLogsAlertMapToAlertsV1MetricAlertPromqlConditionParameters(modelMap["metric_alert_promql_parameters"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if modelMapElement["metric_alert_promql_parameters"] != nil && len(modelMapElement["metric_alert_promql_parameters"].([]interface{})) > 0 { + MetricAlertPromqlParametersModel, err := ResourceIbmLogsAlertMapToAlertsV1MetricAlertPromqlConditionParameters(modelMapElement["metric_alert_promql_parameters"].([]interface{})) + if err != nil { + return model, err + } + model.MetricAlertPromqlParameters = MetricAlertPromqlParametersModel } - model.MetricAlertPromqlParameters = MetricAlertPromqlParametersModel - } - if modelMap["ignore_infinity"] != nil { - model.IgnoreInfinity = core.BoolPtr(modelMap["ignore_infinity"].(bool)) - } - if modelMap["relative_timeframe"] != nil && modelMap["relative_timeframe"].(string) != "" { - model.RelativeTimeframe = core.StringPtr(modelMap["relative_timeframe"].(string)) - } - if modelMap["cardinality_fields"] != nil { - cardinalityFields := []string{} - for _, cardinalityFieldsItem := range modelMap["cardinality_fields"].([]interface{}) { - cardinalityFields = append(cardinalityFields, cardinalityFieldsItem.(string)) + if modelMapElement["ignore_infinity"] != nil { + model.IgnoreInfinity = core.BoolPtr(modelMapElement["ignore_infinity"].(bool)) } - model.CardinalityFields = cardinalityFields - } - if modelMap["related_extended_data"] != nil && len(modelMap["related_extended_data"].([]interface{})) > 0 { - RelatedExtendedDataModel, err := ResourceIbmLogsAlertMapToAlertsV1RelatedExtendedData(modelMap["related_extended_data"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if modelMapElement["relative_timeframe"] != nil && modelMapElement["relative_timeframe"].(string) != "" { + model.RelativeTimeframe = core.StringPtr(modelMapElement["relative_timeframe"].(string)) + } + if modelMapElement["cardinality_fields"] != nil { + cardinalityFields := []string{} + for _, cardinalityFieldsItem := range modelMapElement["cardinality_fields"].([]interface{}) { + cardinalityFields = append(cardinalityFields, cardinalityFieldsItem.(string)) + } + model.CardinalityFields = cardinalityFields + } + if modelMapElement["related_extended_data"] != nil && len(modelMapElement["related_extended_data"].([]interface{})) > 0 { + RelatedExtendedDataModel, err := ResourceIbmLogsAlertMapToAlertsV1RelatedExtendedData(modelMapElement["related_extended_data"].([]interface{})) + if err != nil { + return model, err + } + model.RelatedExtendedData = RelatedExtendedDataModel } - model.RelatedExtendedData = RelatedExtendedDataModel } + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV1MetricAlertConditionParameters(modelMap map[string]interface{}) (*logsv0.AlertsV1MetricAlertConditionParameters, error) { +func ResourceIbmLogsAlertMapToAlertsV1MetricAlertConditionParameters(modelMap []interface{}) (*logsv0.AlertsV1MetricAlertConditionParameters, error) { model := &logsv0.AlertsV1MetricAlertConditionParameters{} - model.MetricField = core.StringPtr(modelMap["metric_field"].(string)) - model.MetricSource = core.StringPtr(modelMap["metric_source"].(string)) - model.ArithmeticOperator = core.StringPtr(modelMap["arithmetic_operator"].(string)) - if modelMap["arithmetic_operator_modifier"] != nil { - model.ArithmeticOperatorModifier = core.Int64Ptr(int64(modelMap["arithmetic_operator_modifier"].(int))) - } - if modelMap["sample_threshold_percentage"] != nil { - model.SampleThresholdPercentage = core.Int64Ptr(int64(modelMap["sample_threshold_percentage"].(int))) - } - if modelMap["non_null_percentage"] != nil { - model.NonNullPercentage = core.Int64Ptr(int64(modelMap["non_null_percentage"].(int))) - } - if modelMap["swap_null_values"] != nil { - model.SwapNullValues = core.BoolPtr(modelMap["swap_null_values"].(bool)) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + model.MetricField = core.StringPtr(modelMapElement["metric_field"].(string)) + model.MetricSource = core.StringPtr(modelMapElement["metric_source"].(string)) + model.ArithmeticOperator = core.StringPtr(modelMapElement["arithmetic_operator"].(string)) + if modelMapElement["arithmetic_operator_modifier"] != nil { + model.ArithmeticOperatorModifier = core.Int64Ptr(int64(modelMapElement["arithmetic_operator_modifier"].(int))) + } + if modelMapElement["sample_threshold_percentage"] != nil { + model.SampleThresholdPercentage = core.Int64Ptr(int64(modelMapElement["sample_threshold_percentage"].(int))) + } + if modelMapElement["non_null_percentage"] != nil { + model.NonNullPercentage = core.Int64Ptr(int64(modelMapElement["non_null_percentage"].(int))) + } + if modelMapElement["swap_null_values"] != nil { + model.SwapNullValues = core.BoolPtr(modelMapElement["swap_null_values"].(bool)) + } } + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV1MetricAlertPromqlConditionParameters(modelMap map[string]interface{}) (*logsv0.AlertsV1MetricAlertPromqlConditionParameters, error) { +func ResourceIbmLogsAlertMapToAlertsV1MetricAlertPromqlConditionParameters(modelMap []interface{}) (*logsv0.AlertsV1MetricAlertPromqlConditionParameters, error) { model := &logsv0.AlertsV1MetricAlertPromqlConditionParameters{} - model.PromqlText = core.StringPtr(modelMap["promql_text"].(string)) - if modelMap["arithmetic_operator_modifier"] != nil { - model.ArithmeticOperatorModifier = core.Int64Ptr(int64(modelMap["arithmetic_operator_modifier"].(int))) - } - model.SampleThresholdPercentage = core.Int64Ptr(int64(modelMap["sample_threshold_percentage"].(int))) - if modelMap["non_null_percentage"] != nil { - model.NonNullPercentage = core.Int64Ptr(int64(modelMap["non_null_percentage"].(int))) - } - if modelMap["swap_null_values"] != nil { - model.SwapNullValues = core.BoolPtr(modelMap["swap_null_values"].(bool)) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + model.PromqlText = core.StringPtr(modelMapElement["promql_text"].(string)) + if modelMapElement["arithmetic_operator_modifier"] != nil { + model.ArithmeticOperatorModifier = core.Int64Ptr(int64(modelMapElement["arithmetic_operator_modifier"].(int))) + } + model.SampleThresholdPercentage = core.Int64Ptr(int64(modelMapElement["sample_threshold_percentage"].(int))) + if modelMapElement["non_null_percentage"] != nil { + model.NonNullPercentage = core.Int64Ptr(int64(modelMapElement["non_null_percentage"].(int))) + } + if modelMapElement["swap_null_values"] != nil { + model.SwapNullValues = core.BoolPtr(modelMapElement["swap_null_values"].(bool)) + } } + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV1RelatedExtendedData(modelMap map[string]interface{}) (*logsv0.AlertsV1RelatedExtendedData, error) { +func ResourceIbmLogsAlertMapToAlertsV1RelatedExtendedData(modelMap []interface{}) (*logsv0.AlertsV1RelatedExtendedData, error) { model := &logsv0.AlertsV1RelatedExtendedData{} - if modelMap["cleanup_deadman_duration"] != nil && modelMap["cleanup_deadman_duration"].(string) != "" { - model.CleanupDeadmanDuration = core.StringPtr(modelMap["cleanup_deadman_duration"].(string)) - } - if modelMap["should_trigger_deadman"] != nil { - model.ShouldTriggerDeadman = core.BoolPtr(modelMap["should_trigger_deadman"].(bool)) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + if modelMapElement["cleanup_deadman_duration"] != nil && modelMapElement["cleanup_deadman_duration"].(string) != "" { + model.CleanupDeadmanDuration = core.StringPtr(modelMapElement["cleanup_deadman_duration"].(string)) + } + if modelMapElement["should_trigger_deadman"] != nil { + model.ShouldTriggerDeadman = core.BoolPtr(modelMapElement["should_trigger_deadman"].(bool)) + } } + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2MoreThanCondition(modelMap map[string]interface{}) (*logsv0.AlertsV2MoreThanCondition, error) { +func ResourceIbmLogsAlertMapToAlertsV2MoreThanCondition(modelMap []interface{}) (*logsv0.AlertsV2MoreThanCondition, error) { model := &logsv0.AlertsV2MoreThanCondition{} - ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err - } - model.Parameters = ParametersModel - if modelMap["evaluation_window"] != nil && modelMap["evaluation_window"].(string) != "" { - model.EvaluationWindow = core.StringPtr(modelMap["evaluation_window"].(string)) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMapElement["parameters"].([]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel + if modelMapElement["evaluation_window"] != nil && modelMapElement["evaluation_window"].(string) != "" { + model.EvaluationWindow = core.StringPtr(modelMapElement["evaluation_window"].(string)) + } } + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2MoreThanUsualCondition(modelMap map[string]interface{}) (*logsv0.AlertsV2MoreThanUsualCondition, error) { +func ResourceIbmLogsAlertMapToAlertsV2MoreThanUsualCondition(modelMap []interface{}) (*logsv0.AlertsV2MoreThanUsualCondition, error) { model := &logsv0.AlertsV2MoreThanUsualCondition{} - ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMapElement["parameters"].([]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel } - model.Parameters = ParametersModel + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2NewValueCondition(modelMap map[string]interface{}) (*logsv0.AlertsV2NewValueCondition, error) { +func ResourceIbmLogsAlertMapToAlertsV2NewValueCondition(modelMap []interface{}) (*logsv0.AlertsV2NewValueCondition, error) { model := &logsv0.AlertsV2NewValueCondition{} - ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMapElement["parameters"].([]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel } - model.Parameters = ParametersModel + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2FlowCondition(modelMap map[string]interface{}) (*logsv0.AlertsV2FlowCondition, error) { +func ResourceIbmLogsAlertMapToAlertsV2FlowCondition(modelMap []interface{}) (*logsv0.AlertsV2FlowCondition, error) { model := &logsv0.AlertsV2FlowCondition{} - if modelMap["stages"] != nil { - stages := []logsv0.AlertsV1FlowStage{} - for _, stagesItem := range modelMap["stages"].([]interface{}) { - stagesItemModel, err := ResourceIbmLogsAlertMapToAlertsV1FlowStage(stagesItem.(map[string]interface{})) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + if modelMapElement["stages"] != nil { + stages := []logsv0.AlertsV1FlowStage{} + for _, stagesItem := range modelMapElement["stages"].([]interface{}) { + stagesItemModel, err := ResourceIbmLogsAlertMapToAlertsV1FlowStage(stagesItem.(map[string]interface{})) + if err != nil { + return model, err + } + stages = append(stages, *stagesItemModel) + } + model.Stages = stages + } + if modelMapElement["parameters"] != nil && len(modelMapElement["parameters"].([]interface{})) > 0 { + ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMapElement["parameters"].([]interface{})) if err != nil { return model, err } - stages = append(stages, *stagesItemModel) + model.Parameters = ParametersModel } - model.Stages = stages - } - if modelMap["parameters"] != nil && len(modelMap["parameters"].([]interface{})) > 0 { - ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if modelMapElement["enforce_suppression"] != nil { + model.EnforceSuppression = core.BoolPtr(modelMapElement["enforce_suppression"].(bool)) } - model.Parameters = ParametersModel - } - if modelMap["enforce_suppression"] != nil { - model.EnforceSuppression = core.BoolPtr(modelMap["enforce_suppression"].(bool)) } + return model, nil } @@ -2230,7 +2272,7 @@ func ResourceIbmLogsAlertMapToAlertsV1FlowStage(modelMap map[string]interface{}) model.Groups = groups } if modelMap["timeframe"] != nil && len(modelMap["timeframe"].([]interface{})) > 0 { - TimeframeModel, err := ResourceIbmLogsAlertMapToAlertsV1FlowTimeframe(modelMap["timeframe"].([]interface{})[0].(map[string]interface{})) + TimeframeModel, err := ResourceIbmLogsAlertMapToAlertsV1FlowTimeframe(modelMap["timeframe"].([]interface{})) if err != nil { return model, err } @@ -2242,7 +2284,7 @@ func ResourceIbmLogsAlertMapToAlertsV1FlowStage(modelMap map[string]interface{}) func ResourceIbmLogsAlertMapToAlertsV1FlowGroup(modelMap map[string]interface{}) (*logsv0.AlertsV1FlowGroup, error) { model := &logsv0.AlertsV1FlowGroup{} if modelMap["alerts"] != nil && len(modelMap["alerts"].([]interface{})) > 0 { - AlertsModel, err := ResourceIbmLogsAlertMapToAlertsV1FlowAlerts(modelMap["alerts"].([]interface{})[0].(map[string]interface{})) + AlertsModel, err := ResourceIbmLogsAlertMapToAlertsV1FlowAlerts(modelMap["alerts"].([]interface{})) if err != nil { return model, err } @@ -2254,21 +2296,24 @@ func ResourceIbmLogsAlertMapToAlertsV1FlowGroup(modelMap map[string]interface{}) return model, nil } -func ResourceIbmLogsAlertMapToAlertsV1FlowAlerts(modelMap map[string]interface{}) (*logsv0.AlertsV1FlowAlerts, error) { +func ResourceIbmLogsAlertMapToAlertsV1FlowAlerts(modelMap []interface{}) (*logsv0.AlertsV1FlowAlerts, error) { model := &logsv0.AlertsV1FlowAlerts{} - if modelMap["op"] != nil && modelMap["op"].(string) != "" { - model.Op = core.StringPtr(modelMap["op"].(string)) - } - if modelMap["values"] != nil { - values := []logsv0.AlertsV1FlowAlert{} - for _, valuesItem := range modelMap["values"].([]interface{}) { - valuesItemModel, err := ResourceIbmLogsAlertMapToAlertsV1FlowAlert(valuesItem.(map[string]interface{})) - if err != nil { - return model, err + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + if modelMapElement["op"] != nil && modelMapElement["op"].(string) != "" { + model.Op = core.StringPtr(modelMapElement["op"].(string)) + } + if modelMapElement["values"] != nil { + values := []logsv0.AlertsV1FlowAlert{} + for _, valuesItem := range modelMapElement["values"].([]interface{}) { + valuesItemModel, err := ResourceIbmLogsAlertMapToAlertsV1FlowAlert(valuesItem.(map[string]interface{})) + if err != nil { + return model, err + } + values = append(values, *valuesItemModel) } - values = append(values, *valuesItemModel) + model.Values = values } - model.Values = values } return model, nil } @@ -2284,38 +2329,50 @@ func ResourceIbmLogsAlertMapToAlertsV1FlowAlert(modelMap map[string]interface{}) return model, nil } -func ResourceIbmLogsAlertMapToAlertsV1FlowTimeframe(modelMap map[string]interface{}) (*logsv0.AlertsV1FlowTimeframe, error) { +func ResourceIbmLogsAlertMapToAlertsV1FlowTimeframe(modelMap []interface{}) (*logsv0.AlertsV1FlowTimeframe, error) { model := &logsv0.AlertsV1FlowTimeframe{} - if modelMap["ms"] != nil { - model.Ms = core.Int64Ptr(int64(modelMap["ms"].(int))) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + if modelMapElement["ms"] != nil { + model.Ms = core.Int64Ptr(int64(modelMapElement["ms"].(int))) + } } + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2UniqueCountCondition(modelMap map[string]interface{}) (*logsv0.AlertsV2UniqueCountCondition, error) { +func ResourceIbmLogsAlertMapToAlertsV2UniqueCountCondition(modelMap []interface{}) (*logsv0.AlertsV2UniqueCountCondition, error) { model := &logsv0.AlertsV2UniqueCountCondition{} - ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMapElement["parameters"].([]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel } - model.Parameters = ParametersModel + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2LessThanUsualCondition(modelMap map[string]interface{}) (*logsv0.AlertsV2LessThanUsualCondition, error) { +func ResourceIbmLogsAlertMapToAlertsV2LessThanUsualCondition(modelMap []interface{}) (*logsv0.AlertsV2LessThanUsualCondition, error) { model := &logsv0.AlertsV2LessThanUsualCondition{} - ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + ParametersModel, err := ResourceIbmLogsAlertMapToAlertsV2ConditionParameters(modelMapElement["parameters"].([]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel } - model.Parameters = ParametersModel + return model, nil } func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionImmediate(modelMap map[string]interface{}) (*logsv0.AlertsV2AlertConditionConditionImmediate, error) { model := &logsv0.AlertsV2AlertConditionConditionImmediate{} if modelMap["immediate"] != nil && len(modelMap["immediate"].([]interface{})) > 0 { - ImmediateModel, err := ResourceIbmLogsAlertMapToAlertsV2ImmediateConditionEmpty(modelMap["immediate"].([]interface{})[0].(map[string]interface{})) + ImmediateModel, err := ResourceIbmLogsAlertMapToAlertsV2ImmediateConditionEmpty(modelMap["immediate"].([]interface{})) if err != nil { return model, err } @@ -2327,7 +2384,7 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionImmediate(modelMap func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionLessThan(modelMap map[string]interface{}) (*logsv0.AlertsV2AlertConditionConditionLessThan, error) { model := &logsv0.AlertsV2AlertConditionConditionLessThan{} if modelMap["less_than"] != nil && len(modelMap["less_than"].([]interface{})) > 0 { - LessThanModel, err := ResourceIbmLogsAlertMapToAlertsV2LessThanCondition(modelMap["less_than"].([]interface{})[0].(map[string]interface{})) + LessThanModel, err := ResourceIbmLogsAlertMapToAlertsV2LessThanCondition(modelMap["less_than"].([]interface{})) if err != nil { return model, err } @@ -2339,7 +2396,7 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionLessThan(modelMap m func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionMoreThan(modelMap map[string]interface{}) (*logsv0.AlertsV2AlertConditionConditionMoreThan, error) { model := &logsv0.AlertsV2AlertConditionConditionMoreThan{} if modelMap["more_than"] != nil && len(modelMap["more_than"].([]interface{})) > 0 { - MoreThanModel, err := ResourceIbmLogsAlertMapToAlertsV2MoreThanCondition(modelMap["more_than"].([]interface{})[0].(map[string]interface{})) + MoreThanModel, err := ResourceIbmLogsAlertMapToAlertsV2MoreThanCondition(modelMap["more_than"].([]interface{})) if err != nil { return model, err } @@ -2351,7 +2408,7 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionMoreThan(modelMap m func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionMoreThanUsual(modelMap map[string]interface{}) (*logsv0.AlertsV2AlertConditionConditionMoreThanUsual, error) { model := &logsv0.AlertsV2AlertConditionConditionMoreThanUsual{} if modelMap["more_than_usual"] != nil && len(modelMap["more_than_usual"].([]interface{})) > 0 { - MoreThanUsualModel, err := ResourceIbmLogsAlertMapToAlertsV2MoreThanUsualCondition(modelMap["more_than_usual"].([]interface{})[0].(map[string]interface{})) + MoreThanUsualModel, err := ResourceIbmLogsAlertMapToAlertsV2MoreThanUsualCondition(modelMap["more_than_usual"].([]interface{})) if err != nil { return model, err } @@ -2363,7 +2420,7 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionMoreThanUsual(model func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionNewValue(modelMap map[string]interface{}) (*logsv0.AlertsV2AlertConditionConditionNewValue, error) { model := &logsv0.AlertsV2AlertConditionConditionNewValue{} if modelMap["new_value"] != nil && len(modelMap["new_value"].([]interface{})) > 0 { - NewValueModel, err := ResourceIbmLogsAlertMapToAlertsV2NewValueCondition(modelMap["new_value"].([]interface{})[0].(map[string]interface{})) + NewValueModel, err := ResourceIbmLogsAlertMapToAlertsV2NewValueCondition(modelMap["new_value"].([]interface{})) if err != nil { return model, err } @@ -2375,7 +2432,7 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionNewValue(modelMap m func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionFlow(modelMap map[string]interface{}) (*logsv0.AlertsV2AlertConditionConditionFlow, error) { model := &logsv0.AlertsV2AlertConditionConditionFlow{} if modelMap["flow"] != nil && len(modelMap["flow"].([]interface{})) > 0 { - FlowModel, err := ResourceIbmLogsAlertMapToAlertsV2FlowCondition(modelMap["flow"].([]interface{})[0].(map[string]interface{})) + FlowModel, err := ResourceIbmLogsAlertMapToAlertsV2FlowCondition(modelMap["flow"].([]interface{})) if err != nil { return model, err } @@ -2387,7 +2444,7 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionFlow(modelMap map[s func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionUniqueCount(modelMap map[string]interface{}) (*logsv0.AlertsV2AlertConditionConditionUniqueCount, error) { model := &logsv0.AlertsV2AlertConditionConditionUniqueCount{} if modelMap["unique_count"] != nil && len(modelMap["unique_count"].([]interface{})) > 0 { - UniqueCountModel, err := ResourceIbmLogsAlertMapToAlertsV2UniqueCountCondition(modelMap["unique_count"].([]interface{})[0].(map[string]interface{})) + UniqueCountModel, err := ResourceIbmLogsAlertMapToAlertsV2UniqueCountCondition(modelMap["unique_count"].([]interface{})) if err != nil { return model, err } @@ -2399,7 +2456,7 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionUniqueCount(modelMa func ResourceIbmLogsAlertMapToAlertsV2AlertConditionConditionLessThanUsual(modelMap map[string]interface{}) (*logsv0.AlertsV2AlertConditionConditionLessThanUsual, error) { model := &logsv0.AlertsV2AlertConditionConditionLessThanUsual{} if modelMap["less_than_usual"] != nil && len(modelMap["less_than_usual"].([]interface{})) > 0 { - LessThanUsualModel, err := ResourceIbmLogsAlertMapToAlertsV2LessThanUsualCondition(modelMap["less_than_usual"].([]interface{})[0].(map[string]interface{})) + LessThanUsualModel, err := ResourceIbmLogsAlertMapToAlertsV2LessThanUsualCondition(modelMap["less_than_usual"].([]interface{})) if err != nil { return model, err } @@ -2433,7 +2490,8 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertNotificationGroups(modelMap map[strin func ResourceIbmLogsAlertMapToAlertsV2AlertNotification(modelMap map[string]interface{}) (logsv0.AlertsV2AlertNotificationIntf, error) { model := &logsv0.AlertsV2AlertNotification{} - if modelMap["retriggering_period_seconds"] != nil { + + if modelMap["retriggering_period_seconds"] != nil && modelMap["retriggering_period_seconds"] != 0 { model.RetriggeringPeriodSeconds = core.Int64Ptr(int64(modelMap["retriggering_period_seconds"].(int))) } if modelMap["notify_on"] != nil && modelMap["notify_on"].(string) != "" { @@ -2443,7 +2501,7 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertNotification(modelMap map[string]inte model.IntegrationID = core.Int64Ptr(int64(modelMap["integration_id"].(int))) } if modelMap["recipients"] != nil && len(modelMap["recipients"].([]interface{})) > 0 { - RecipientsModel, err := ResourceIbmLogsAlertMapToAlertsV2Recipients(modelMap["recipients"].([]interface{})[0].(map[string]interface{})) + RecipientsModel, err := ResourceIbmLogsAlertMapToAlertsV2Recipients(modelMap["recipients"].([]interface{})) if err != nil { return model, err } @@ -2452,15 +2510,19 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertNotification(modelMap map[string]inte return model, nil } -func ResourceIbmLogsAlertMapToAlertsV2Recipients(modelMap map[string]interface{}) (*logsv0.AlertsV2Recipients, error) { +func ResourceIbmLogsAlertMapToAlertsV2Recipients(modelMap []interface{}) (*logsv0.AlertsV2Recipients, error) { model := &logsv0.AlertsV2Recipients{} - if modelMap["emails"] != nil { - emails := []string{} - for _, emailsItem := range modelMap["emails"].([]interface{}) { - emails = append(emails, emailsItem.(string)) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + if modelMapElement["emails"] != nil { + emails := []string{} + for _, emailsItem := range modelMapElement["emails"].([]interface{}) { + emails = append(emails, emailsItem.(string)) + } + model.Emails = emails } - model.Emails = emails } + return model, nil } @@ -2487,7 +2549,7 @@ func ResourceIbmLogsAlertMapToAlertsV2AlertNotificationIntegrationTypeRecipients model.NotifyOn = core.StringPtr(modelMap["notify_on"].(string)) } if modelMap["recipients"] != nil && len(modelMap["recipients"].([]interface{})) > 0 { - RecipientsModel, err := ResourceIbmLogsAlertMapToAlertsV2Recipients(modelMap["recipients"].([]interface{})[0].(map[string]interface{})) + RecipientsModel, err := ResourceIbmLogsAlertMapToAlertsV2Recipients(modelMap["recipients"].([]interface{})) if err != nil { return model, err } @@ -2506,7 +2568,7 @@ func ResourceIbmLogsAlertMapToAlertsV1AlertFilters(modelMap map[string]interface model.Severities = severities } if modelMap["metadata"] != nil && len(modelMap["metadata"].([]interface{})) > 0 { - MetadataModel, err := ResourceIbmLogsAlertMapToAlertsV1AlertFiltersMetadataFilters(modelMap["metadata"].([]interface{})[0].(map[string]interface{})) + MetadataModel, err := ResourceIbmLogsAlertMapToAlertsV1AlertFiltersMetadataFilters(modelMap["metadata"].([]interface{})) if err != nil { return model, err } @@ -2535,21 +2597,24 @@ func ResourceIbmLogsAlertMapToAlertsV1AlertFilters(modelMap map[string]interface return model, nil } -func ResourceIbmLogsAlertMapToAlertsV1AlertFiltersMetadataFilters(modelMap map[string]interface{}) (*logsv0.AlertsV1AlertFiltersMetadataFilters, error) { +func ResourceIbmLogsAlertMapToAlertsV1AlertFiltersMetadataFilters(modelMap []interface{}) (*logsv0.AlertsV1AlertFiltersMetadataFilters, error) { model := &logsv0.AlertsV1AlertFiltersMetadataFilters{} - if modelMap["applications"] != nil { - applications := []string{} - for _, applicationsItem := range modelMap["applications"].([]interface{}) { - applications = append(applications, applicationsItem.(string)) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + if modelMapElement["applications"] != nil { + applications := []string{} + for _, applicationsItem := range modelMapElement["applications"].([]interface{}) { + applications = append(applications, applicationsItem.(string)) + } + model.Applications = applications } - model.Applications = applications - } - if modelMap["subsystems"] != nil { - subsystems := []string{} - for _, subsystemsItem := range modelMap["subsystems"].([]interface{}) { - subsystems = append(subsystems, subsystemsItem.(string)) + if modelMapElement["subsystems"] != nil { + subsystems := []string{} + for _, subsystemsItem := range modelMapElement["subsystems"].([]interface{}) { + subsystems = append(subsystems, subsystemsItem.(string)) + } + model.Subsystems = subsystems } - model.Subsystems = subsystems } return model, nil } @@ -2628,7 +2693,7 @@ func ResourceIbmLogsAlertMapToAlertsV1AlertActiveTimeframe(modelMap map[string]i daysOfWeek = append(daysOfWeek, daysOfWeekItem.(string)) } model.DaysOfWeek = daysOfWeek - RangeModel, err := ResourceIbmLogsAlertMapToAlertsV1TimeRange(modelMap["range"].([]interface{})[0].(map[string]interface{})) + RangeModel, err := ResourceIbmLogsAlertMapToAlertsV1TimeRange(modelMap["range"].([]interface{})) if err != nil { return model, err } @@ -2636,32 +2701,40 @@ func ResourceIbmLogsAlertMapToAlertsV1AlertActiveTimeframe(modelMap map[string]i return model, nil } -func ResourceIbmLogsAlertMapToAlertsV1TimeRange(modelMap map[string]interface{}) (*logsv0.AlertsV1TimeRange, error) { +func ResourceIbmLogsAlertMapToAlertsV1TimeRange(modelMap []interface{}) (*logsv0.AlertsV1TimeRange, error) { model := &logsv0.AlertsV1TimeRange{} - StartModel, err := ResourceIbmLogsAlertMapToAlertsV1Time(modelMap["start"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err - } - model.Start = StartModel - EndModel, err := ResourceIbmLogsAlertMapToAlertsV1Time(modelMap["end"].([]interface{})[0].(map[string]interface{})) - if err != nil { - return model, err + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + StartModel, err := ResourceIbmLogsAlertMapToAlertsV1Time(modelMapElement["start"].([]interface{})) + if err != nil { + return model, err + } + model.Start = StartModel + EndModel, err := ResourceIbmLogsAlertMapToAlertsV1Time(modelMapElement["end"].([]interface{})) + if err != nil { + return model, err + } + model.End = EndModel } - model.End = EndModel + return model, nil } -func ResourceIbmLogsAlertMapToAlertsV1Time(modelMap map[string]interface{}) (*logsv0.AlertsV1Time, error) { +func ResourceIbmLogsAlertMapToAlertsV1Time(modelMap []interface{}) (*logsv0.AlertsV1Time, error) { model := &logsv0.AlertsV1Time{} - if modelMap["hours"] != nil { - model.Hours = core.Int64Ptr(int64(modelMap["hours"].(int))) - } - if modelMap["minutes"] != nil { - model.Minutes = core.Int64Ptr(int64(modelMap["minutes"].(int))) - } - if modelMap["seconds"] != nil { - model.Seconds = core.Int64Ptr(int64(modelMap["seconds"].(int))) + if len(modelMap) > 0 && modelMap[0] != nil { + modelMapElement := modelMap[0].(map[string]interface{}) + if modelMapElement["hours"] != nil { + model.Hours = core.Int64Ptr(int64(modelMapElement["hours"].(int))) + } + if modelMapElement["minutes"] != nil { + model.Minutes = core.Int64Ptr(int64(modelMapElement["minutes"].(int))) + } + if modelMapElement["seconds"] != nil { + model.Seconds = core.Int64Ptr(int64(modelMapElement["seconds"].(int))) + } } + return model, nil } diff --git a/ibm/service/logs/resource_ibm_logs_outgoing_webhook.go b/ibm/service/logs/resource_ibm_logs_outgoing_webhook.go index 0f6ab85578..321390061d 100644 --- a/ibm/service/logs/resource_ibm_logs_outgoing_webhook.go +++ b/ibm/service/logs/resource_ibm_logs_outgoing_webhook.go @@ -66,11 +66,13 @@ func ResourceIbmLogsOutgoingWebhook() *schema.Resource { "source_id": &schema.Schema{ Type: schema.TypeString, Optional: true, + Computed: true, Description: "The ID of the created source in the IBM Event Notifications instance. Corresponds to the Cloud Logs instance crn. Not required when creating an Outbound Integration.", }, "source_name": &schema.Schema{ Type: schema.TypeString, Optional: true, + Computed: true, Description: "The name of the created source in the IBM Event Notifications instance. Not required when creating an Outbound Integration.", }, }, @@ -339,13 +341,13 @@ func resourceIbmLogsOutgoingWebhookDelete(context context.Context, d *schema.Res func ResourceIbmLogsOutgoingWebhookMapToOutgoingWebhooksV1IbmEventNotificationsConfig(modelMap map[string]interface{}) (*logsv0.OutgoingWebhooksV1IbmEventNotificationsConfig, error) { model := &logsv0.OutgoingWebhooksV1IbmEventNotificationsConfig{} model.EventNotificationsInstanceID = core.UUIDPtr(strfmt.UUID(modelMap["event_notifications_instance_id"].(string))) - model.RegionID = core.StringPtr(modelMap["region_id"].(string)) // TODO: is source_id and source_name supported by SDK? - // if modelMap["source_id"] != nil && modelMap["source_id"].(string) != "" { - // model.SourceID = core.StringPtr(modelMap["source_id"].(string)) - // } - // if modelMap["source_name"] != nil && modelMap["source_name"].(string) != "" { - // model.SourceName = core.StringPtr(modelMap["source_name"].(string)) - // } + model.RegionID = core.StringPtr(modelMap["region_id"].(string)) + if modelMap["source_id"] != nil && modelMap["source_id"].(string) != "" { + model.SourceID = core.StringPtr(modelMap["source_id"].(string)) + } + if modelMap["source_name"] != nil && modelMap["source_name"].(string) != "" { + model.SourceName = core.StringPtr(modelMap["source_name"].(string)) + } return model, nil } @@ -387,11 +389,11 @@ func ResourceIbmLogsOutgoingWebhookOutgoingWebhooksV1IbmEventNotificationsConfig modelMap := make(map[string]interface{}) modelMap["event_notifications_instance_id"] = model.EventNotificationsInstanceID.String() modelMap["region_id"] = *model.RegionID - // if model.SourceID != nil { - // modelMap["source_id"] = *model.SourceID - // } - // if model.SourceName != nil { - // modelMap["source_name"] = *model.SourceName - // } + if model.SourceID != nil { + modelMap["source_id"] = *model.SourceID + } + if model.SourceName != nil { + modelMap["source_name"] = *model.SourceName + } return modelMap, nil } diff --git a/ibm/service/logsrouting/README.md b/ibm/service/logsrouting/README.md new file mode 100644 index 0000000000..397cb49400 --- /dev/null +++ b/ibm/service/logsrouting/README.md @@ -0,0 +1,11 @@ +# Logs Routing Terraform IBM Provider + +This area is primarily for IBM provider contributors and maintainers. For information on _using_ Terraform and the IBM provider, see the links below. + + +## Handy Links +* [Find out about contributing](../../../CONTRIBUTING.md) to the IBM provider! +* IBM Provider Docs: [Home](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs) +* IBM Provider Docs: [One of the resources](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/ibm_logs_router_tenant) +* IBM API Docs: [IBM API Docs for IBM Cloud Logs Router](https://cloud.ibm.com/apidocs/logs-router-service-api/logs-router-v1) +* IBM SDK: [IBM SDK for IBM Cloud Logs Router](https://github.com/IBM/logs-router-go-sdk) \ No newline at end of file diff --git a/ibm/service/logsrouting/data_source_ibm_logs-router_targets.go b/ibm/service/logsrouting/data_source_ibm_logs-router_targets.go new file mode 100644 index 0000000000..8e3b178a87 --- /dev/null +++ b/ibm/service/logsrouting/data_source_ibm_logs-router_targets.go @@ -0,0 +1,247 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.90.1-64fd3296-20240515-180710 + */ + +package logsrouting + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/go-openapi/strfmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/logs-router-go-sdk/ibmcloudlogsroutingv0" +) + +func DataSourceIBMLogsRouterTargets() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMLogsRouterTargetsRead, + + Schema: map[string]*schema.Schema{ + "tenant_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The instance ID of the tenant.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Optional: Name of the tenant target.", + }, + "targets": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "List of target of a tenant.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Unique ID of the target.", + }, + "log_sink_crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Cloud resource name of the log-sink target instance.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this tenant target. The name is unique across all targets for this tenant.", + }, + "etag": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Resource version identifier.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Type of log-sink. Identical to the service-name segment of log_sink_crn.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the target was originally created.", + }, + "updated_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the target was last updated.", + }, + "parameters": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "List of properties returned from a successful list operation for a log-sink of type IBM Log Analysis (logdna).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "host": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Host name of the log-sink.", + }, + "port": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "Network port of the log-sink.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMLogsRouterTargetsRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + ibmCloudLogsRoutingClient, err := meta.(conns.ClientSession).IBMCloudLogsRoutingV0() + if err != nil { + // Error is coming from SDK client, so it doesn't need to be discriminated. + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_logs_router_targets", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + listTenantTargetsOptions := &ibmcloudlogsroutingv0.ListTenantTargetsOptions{} + + listTenantTargetsOptions.SetTenantID(core.UUIDPtr(strfmt.UUID(d.Get("tenant_id").(string)))) + if _, ok := d.GetOk("name"); ok { + listTenantTargetsOptions.SetName(d.Get("name").(string)) + } + + targetTypeCollection, _, err := ibmCloudLogsRoutingClient.ListTenantTargetsWithContext(context, listTenantTargetsOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ListTenantTargetsWithContext failed: %s", err.Error()), "(Data) ibm_logs_router_targets", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMLogsRouterTargetsID(d)) + + targets := []map[string]interface{}{} + if targetTypeCollection.Targets != nil { + for _, modelItem := range targetTypeCollection.Targets { + modelMap, err := DataSourceIBMLogsRouterTargetsTargetTypeToMap(modelItem) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_logs_router_targets", "read", "targets-to-map").GetDiag() + } + targets = append(targets, modelMap) + } + } + if err = d.Set("targets", targets); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting targets: %s", err), "(Data) ibm_logs_router_targets", "read", "set-targets").GetDiag() + } + + return nil +} + +// dataSourceIBMLogsRouterTargetsID returns a reasonable ID for the list. +func dataSourceIBMLogsRouterTargetsID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func DataSourceIBMLogsRouterTargetsTargetTypeToMap(model ibmcloudlogsroutingv0.TargetTypeIntf) (map[string]interface{}, error) { + if _, ok := model.(*ibmcloudlogsroutingv0.TargetTypeLogDna); ok { + return DataSourceIBMLogsRouterTargetsTargetTypeLogDnaToMap(model.(*ibmcloudlogsroutingv0.TargetTypeLogDna)) + } else if _, ok := model.(*ibmcloudlogsroutingv0.TargetTypeLogs); ok { + return DataSourceIBMLogsRouterTargetsTargetTypeLogsToMap(model.(*ibmcloudlogsroutingv0.TargetTypeLogs)) + } else if _, ok := model.(*ibmcloudlogsroutingv0.TargetType); ok { + modelMap := make(map[string]interface{}) + model := model.(*ibmcloudlogsroutingv0.TargetType) + if model.ID != nil { + modelMap["id"] = model.ID.String() + } + if model.LogSinkCRN != nil { + modelMap["log_sink_crn"] = *model.LogSinkCRN + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.Etag != nil { + modelMap["etag"] = *model.Etag + } + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.CreatedAt != nil { + modelMap["created_at"] = *model.CreatedAt + } + if model.UpdatedAt != nil { + modelMap["updated_at"] = *model.UpdatedAt + } + if model.Parameters != nil { + parametersMap, err := DataSourceIBMLogsRouterTargetsTargetParametersTypeLogDnaToMap(model.Parameters) + if err != nil { + return modelMap, err + } + modelMap["parameters"] = []map[string]interface{}{parametersMap} + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized ibmcloudlogsroutingv0.TargetTypeIntf subtype encountered") + } +} + +func DataSourceIBMLogsRouterTargetsTargetParametersTypeLogDnaToMap(model *ibmcloudlogsroutingv0.TargetParametersTypeLogDna) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["host"] = *model.Host + modelMap["port"] = flex.IntValue(model.Port) + return modelMap, nil +} + +func DataSourceIBMLogsRouterTargetsTargetTypeLogDnaToMap(model *ibmcloudlogsroutingv0.TargetTypeLogDna) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = model.ID.String() + modelMap["log_sink_crn"] = *model.LogSinkCRN + modelMap["name"] = *model.Name + modelMap["etag"] = *model.Etag + modelMap["type"] = *model.Type + modelMap["created_at"] = *model.CreatedAt + modelMap["updated_at"] = *model.UpdatedAt + if model.Parameters != nil { + parametersMap, err := DataSourceIBMLogsRouterTargetsTargetParametersTypeLogDnaToMap(model.Parameters) + if err != nil { + return modelMap, err + } + modelMap["parameters"] = []map[string]interface{}{parametersMap} + } + return modelMap, nil +} + +func DataSourceIBMLogsRouterTargetsTargetTypeLogsToMap(model *ibmcloudlogsroutingv0.TargetTypeLogs) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = model.ID.String() + modelMap["log_sink_crn"] = *model.LogSinkCRN + modelMap["name"] = *model.Name + modelMap["etag"] = *model.Etag + modelMap["type"] = *model.Type + modelMap["created_at"] = *model.CreatedAt + modelMap["updated_at"] = *model.UpdatedAt + if model.Parameters != nil { + parametersMap, err := DataSourceIBMLogsRouterTargetsTargetParametersTypeLogsToMap(model.Parameters) + if err != nil { + return modelMap, err + } + modelMap["parameters"] = []map[string]interface{}{parametersMap} + } + return modelMap, nil +} + +func DataSourceIBMLogsRouterTargetsTargetParametersTypeLogsToMap(model *ibmcloudlogsroutingv0.TargetParametersTypeLogs) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["host"] = *model.Host + modelMap["port"] = flex.IntValue(model.Port) + return modelMap, nil +} diff --git a/ibm/service/logsrouting/data_source_ibm_logs-router_targets_test.go b/ibm/service/logsrouting/data_source_ibm_logs-router_targets_test.go new file mode 100644 index 0000000000..721dda7c6c --- /dev/null +++ b/ibm/service/logsrouting/data_source_ibm_logs-router_targets_test.go @@ -0,0 +1,213 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.90.1-64fd3296-20240515-180710 + */ + +package logsrouting_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/logsrouting" + . "github.com/IBM-Cloud/terraform-provider-ibm/ibm/unittest" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/logs-router-go-sdk/ibmcloudlogsroutingv0" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMLogsRouterTargetsDataSourceBasic(t *testing.T) { + tenantName := fmt.Sprintf("tf-name-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMLogsRouterTargetsDataSourceConfigBasic(tenantName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_logs_router_targets.logs_router_targets_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_logs_router_targets.logs_router_targets_instance", "tenant_id"), + ), + }, + }, + }) +} + +func testAccCheckIBMLogsRouterTargetsDataSourceConfigBasic(tenantName string) string { + return fmt.Sprintf(` + resource "ibm_logs_router_tenant" "logs_router_tenant_instance" { + name = "%s" + targets { + log_sink_crn = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + name = "my-log-sink" + type = "logdna" + parameters { + host = "www.example.com" + port = 1 + access_credential = "%s" + } + } + } + + data "ibm_logs_router_targets" "logs_router_targets_instance" { + tenant_id = ibm_logs_router_tenant.logs_router_tenant_instance.id + } + `, tenantName, acc.IngestionKey) +} + +func TestDataSourceIBMLogsRouterTargetsTargetTypeToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogDnaModel := make(map[string]interface{}) + targetParametersTypeLogDnaModel["host"] = "www.example.com" + targetParametersTypeLogDnaModel["port"] = int(1) + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["log_sink_crn"] = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + model["type"] = "logdna" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["parameters"] = []map[string]interface{}{targetParametersTypeLogDnaModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogDnaModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + targetParametersTypeLogDnaModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogDnaModel.Port = core.Int64Ptr(int64(1)) + + model := new(ibmcloudlogsroutingv0.TargetType) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + model.Type = core.StringPtr("logdna") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.Parameters = targetParametersTypeLogDnaModel + + result, err := logsrouting.DataSourceIBMLogsRouterTargetsTargetTypeToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMLogsRouterTargetsTargetParametersTypeLogDnaToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["host"] = "www.example.com" + model["port"] = int(1) + + assert.Equal(t, result, model) + } + + model := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + model.Host = core.StringPtr("www.example.com") + model.Port = core.Int64Ptr(int64(1)) + + result, err := logsrouting.DataSourceIBMLogsRouterTargetsTargetParametersTypeLogDnaToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMLogsRouterTargetsTargetTypeLogDnaToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogDnaModel := make(map[string]interface{}) + targetParametersTypeLogDnaModel["host"] = "www.example.com" + targetParametersTypeLogDnaModel["port"] = int(8080) + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["log_sink_crn"] = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + model["type"] = "logdna" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["parameters"] = []map[string]interface{}{targetParametersTypeLogDnaModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogDnaModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + targetParametersTypeLogDnaModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogDnaModel.Port = core.Int64Ptr(int64(8080)) + + model := new(ibmcloudlogsroutingv0.TargetTypeLogDna) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + model.Type = core.StringPtr("logdna") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.Parameters = targetParametersTypeLogDnaModel + + result, err := logsrouting.DataSourceIBMLogsRouterTargetsTargetTypeLogDnaToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMLogsRouterTargetsTargetTypeLogsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogsModel := make(map[string]interface{}) + targetParametersTypeLogsModel["host"] = "www.example.com" + targetParametersTypeLogsModel["port"] = int(8080) + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["log_sink_crn"] = "crn:v1:bluemix:public:logs:eu-de:a/4516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + model["type"] = "logs" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["parameters"] = []map[string]interface{}{targetParametersTypeLogsModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogsModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogs) + targetParametersTypeLogsModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogsModel.Port = core.Int64Ptr(int64(8080)) + + model := new(ibmcloudlogsroutingv0.TargetTypeLogs) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logs:eu-de:a/4516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + model.Type = core.StringPtr("logs") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.Parameters = targetParametersTypeLogsModel + + result, err := logsrouting.DataSourceIBMLogsRouterTargetsTargetTypeLogsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMLogsRouterTargetsTargetParametersTypeLogsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["host"] = "www.example.com" + model["port"] = int(1) + + assert.Equal(t, result, model) + } + + model := new(ibmcloudlogsroutingv0.TargetParametersTypeLogs) + model.Host = core.StringPtr("www.example.com") + model.Port = core.Int64Ptr(int64(1)) + + result, err := logsrouting.DataSourceIBMLogsRouterTargetsTargetParametersTypeLogsToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/logsrouting/data_source_ibm_logs-router_tenants.go b/ibm/service/logsrouting/data_source_ibm_logs-router_tenants.go new file mode 100644 index 0000000000..1c263b140c --- /dev/null +++ b/ibm/service/logsrouting/data_source_ibm_logs-router_tenants.go @@ -0,0 +1,298 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.90.1-64fd3296-20240515-180710 + */ + +package logsrouting + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/logs-router-go-sdk/ibmcloudlogsroutingv0" +) + +func DataSourceIBMLogsRouterTenants() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMLogsRouterTenantsRead, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Optional: The name of a tenant.", + }, + "tenants": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "List of tenants in the account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Unique ID of the tenant.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the tenant was originally created.", + }, + "updated_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the tenant was last updated.", + }, + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Cloud resource name of the tenant.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this tenant. The name is regionally unique across all tenants in the account.", + }, + "etag": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Resource version identifier.", + }, + "targets": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "List of targets.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Unique ID of the target.", + }, + "log_sink_crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Cloud resource name of the log-sink target instance.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this tenant target. The name is unique across all targets for this tenant.", + }, + "etag": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Resource version identifier.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Type of log-sink. Identical to the service-name segment of log_sink_crn.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the target was originally created.", + }, + "updated_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the target was last updated.", + }, + "parameters": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "List of properties returned from a successful list operation for a log-sink of type IBM Log Analysis (logdna).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "host": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Host name of the log-sink.", + }, + "port": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "Network port of the log-sink.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMLogsRouterTenantsRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + ibmCloudLogsRoutingClient, err := meta.(conns.ClientSession).IBMCloudLogsRoutingV0() + if err != nil { + // Error is coming from SDK client, so it doesn't need to be discriminated. + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_logs_router_tenants", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + listTenantsOptions := &ibmcloudlogsroutingv0.ListTenantsOptions{} + + if _, ok := d.GetOk("name"); ok { + listTenantsOptions.SetName(d.Get("name").(string)) + } + + tenantCollection, _, err := ibmCloudLogsRoutingClient.ListTenantsWithContext(context, listTenantsOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ListTenantsWithContext failed: %s", err.Error()), "(Data) ibm_logs_router_tenants", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMLogsRouterTenantsID(d)) + + tenants := []map[string]interface{}{} + if tenantCollection.Tenants != nil { + for _, modelItem := range tenantCollection.Tenants { + modelMap, err := DataSourceIBMLogsRouterTenantsTenantToMap(&modelItem) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_logs_router_tenants", "read", "tenants-to-map").GetDiag() + } + tenants = append(tenants, modelMap) + } + } + if err = d.Set("tenants", tenants); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting tenants: %s", err), "(Data) ibm_logs_router_tenants", "read", "set-tenants").GetDiag() + } + + return nil +} + +// dataSourceIBMLogsRouterTenantsID returns a reasonable ID for the list. +func dataSourceIBMLogsRouterTenantsID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func DataSourceIBMLogsRouterTenantsTenantToMap(model *ibmcloudlogsroutingv0.Tenant) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = model.ID.String() + modelMap["created_at"] = *model.CreatedAt + modelMap["updated_at"] = *model.UpdatedAt + modelMap["crn"] = *model.CRN + modelMap["name"] = *model.Name + modelMap["etag"] = *model.Etag + targets := []map[string]interface{}{} + for _, targetsItem := range model.Targets { + targetsItemMap, err := DataSourceIBMLogsRouterTenantsTargetTypeToMap(targetsItem) + if err != nil { + return modelMap, err + } + targets = append(targets, targetsItemMap) + } + modelMap["targets"] = targets + return modelMap, nil +} + +func DataSourceIBMLogsRouterTenantsTargetTypeToMap(model ibmcloudlogsroutingv0.TargetTypeIntf) (map[string]interface{}, error) { + if _, ok := model.(*ibmcloudlogsroutingv0.TargetTypeLogDna); ok { + return DataSourceIBMLogsRouterTenantsTargetTypeLogDnaToMap(model.(*ibmcloudlogsroutingv0.TargetTypeLogDna)) + } else if _, ok := model.(*ibmcloudlogsroutingv0.TargetTypeLogs); ok { + return DataSourceIBMLogsRouterTenantsTargetTypeLogsToMap(model.(*ibmcloudlogsroutingv0.TargetTypeLogs)) + } else if _, ok := model.(*ibmcloudlogsroutingv0.TargetType); ok { + modelMap := make(map[string]interface{}) + model := model.(*ibmcloudlogsroutingv0.TargetType) + if model.ID != nil { + modelMap["id"] = model.ID.String() + } + if model.LogSinkCRN != nil { + modelMap["log_sink_crn"] = *model.LogSinkCRN + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.Etag != nil { + modelMap["etag"] = *model.Etag + } + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.CreatedAt != nil { + modelMap["created_at"] = *model.CreatedAt + } + if model.UpdatedAt != nil { + modelMap["updated_at"] = *model.UpdatedAt + } + if model.Parameters != nil { + parametersMap, err := DataSourceIBMLogsRouterTenantsTargetParametersTypeLogDnaToMap(model.Parameters) + if err != nil { + return modelMap, err + } + modelMap["parameters"] = []map[string]interface{}{parametersMap} + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized ibmcloudlogsroutingv0.TargetTypeIntf subtype encountered") + } +} + +func DataSourceIBMLogsRouterTenantsTargetParametersTypeLogDnaToMap(model *ibmcloudlogsroutingv0.TargetParametersTypeLogDna) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["host"] = *model.Host + modelMap["port"] = flex.IntValue(model.Port) + return modelMap, nil +} + +func DataSourceIBMLogsRouterTenantsTargetTypeLogDnaToMap(model *ibmcloudlogsroutingv0.TargetTypeLogDna) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = model.ID.String() + modelMap["log_sink_crn"] = *model.LogSinkCRN + modelMap["name"] = *model.Name + modelMap["etag"] = *model.Etag + modelMap["type"] = *model.Type + modelMap["created_at"] = *model.CreatedAt + modelMap["updated_at"] = *model.UpdatedAt + if model.Parameters != nil { + parametersMap, err := DataSourceIBMLogsRouterTenantsTargetParametersTypeLogDnaToMap(model.Parameters) + if err != nil { + return modelMap, err + } + modelMap["parameters"] = []map[string]interface{}{parametersMap} + } + return modelMap, nil +} + +func DataSourceIBMLogsRouterTenantsTargetTypeLogsToMap(model *ibmcloudlogsroutingv0.TargetTypeLogs) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = model.ID.String() + modelMap["log_sink_crn"] = *model.LogSinkCRN + modelMap["name"] = *model.Name + modelMap["etag"] = *model.Etag + modelMap["type"] = *model.Type + modelMap["created_at"] = *model.CreatedAt + modelMap["updated_at"] = *model.UpdatedAt + if model.Parameters != nil { + parametersMap, err := DataSourceIBMLogsRouterTenantsTargetParametersTypeLogsToMap(model.Parameters) + if err != nil { + return modelMap, err + } + modelMap["parameters"] = []map[string]interface{}{parametersMap} + } + return modelMap, nil +} + +func DataSourceIBMLogsRouterTenantsTargetParametersTypeLogsToMap(model *ibmcloudlogsroutingv0.TargetParametersTypeLogs) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["host"] = *model.Host + modelMap["port"] = flex.IntValue(model.Port) + return modelMap, nil +} diff --git a/ibm/service/logsrouting/data_source_ibm_logs-router_tenants_test.go b/ibm/service/logsrouting/data_source_ibm_logs-router_tenants_test.go new file mode 100644 index 0000000000..897e488753 --- /dev/null +++ b/ibm/service/logsrouting/data_source_ibm_logs-router_tenants_test.go @@ -0,0 +1,268 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.90.1-64fd3296-20240515-180710 + */ + +package logsrouting_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/logsrouting" + . "github.com/IBM-Cloud/terraform-provider-ibm/ibm/unittest" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/logs-router-go-sdk/ibmcloudlogsroutingv0" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMLogsRouterTenantsDataSourceBasic(t *testing.T) { + tenantName := fmt.Sprintf("tf-name-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMLogsRouterTenantsDataSourceConfigBasic(tenantName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_logs_router_tenants.logs_router_tenants_instance", "id"), + ), + }, + }, + }) +} + +func testAccCheckIBMLogsRouterTenantsDataSourceConfigBasic(tenantName string) string { + return fmt.Sprintf(` + resource "ibm_logs_router_tenant" "logs_router_tenant_instance" { + name = "%s" + targets { + log_sink_crn = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + name = "my-log-sink" + type = "logdna" + parameters { + host = "www.example.com" + port = 1 + access_credential = "%s" + } + } + } + + data "ibm_logs_router_tenants" "logs_router_tenants_instance" { + name = ibm_logs_router_tenant.logs_router_tenant_instance.name + } + `, tenantName, acc.IngestionKey) +} + +func TestDataSourceIBMLogsRouterTenantsTenantToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogDnaModel := make(map[string]interface{}) + targetParametersTypeLogDnaModel["host"] = "www.example.com" + targetParametersTypeLogDnaModel["port"] = int(8080) + + targetTypeModel := make(map[string]interface{}) + targetTypeModel["id"] = "C1C1C838-A4AC-4BD7-8BC6-3173B272429D" + targetTypeModel["log_sink_crn"] = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + targetTypeModel["name"] = "my-logdna-log-sink" + targetTypeModel["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + targetTypeModel["type"] = "logdna" + targetTypeModel["created_at"] = "2024-06-20T18:30:00.143156Z" + targetTypeModel["updated_at"] = "2024-06-20T18:30:00.143156Z" + targetTypeModel["parameters"] = []map[string]interface{}{targetParametersTypeLogDnaModel} + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["crn"] = "crn:v1:bluemix:public:logs-router:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-logging-tenant" + model["etag"] = "822b4b5423e225206c1d75666595714a11925cd0f82b229839864443d6c3c049" + model["targets"] = []map[string]interface{}{targetTypeModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogDnaModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + targetParametersTypeLogDnaModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogDnaModel.Port = core.Int64Ptr(int64(8080)) + + targetTypeModel := new(ibmcloudlogsroutingv0.TargetTypeLogDna) + targetTypeModel.ID = CreateMockUUID("C1C1C838-A4AC-4BD7-8BC6-3173B272429D") + targetTypeModel.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + targetTypeModel.Name = core.StringPtr("my-logdna-log-sink") + targetTypeModel.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + targetTypeModel.Type = core.StringPtr("logdna") + targetTypeModel.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + targetTypeModel.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + targetTypeModel.Parameters = targetParametersTypeLogDnaModel + + model := new(ibmcloudlogsroutingv0.Tenant) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.CRN = core.StringPtr("crn:v1:bluemix:public:logs-router:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-logging-tenant") + model.Etag = core.StringPtr("822b4b5423e225206c1d75666595714a11925cd0f82b229839864443d6c3c049") + model.Targets = []ibmcloudlogsroutingv0.TargetTypeIntf{targetTypeModel} + + result, err := logsrouting.DataSourceIBMLogsRouterTenantsTenantToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMLogsRouterTenantsTargetTypeToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogDnaModel := make(map[string]interface{}) + targetParametersTypeLogDnaModel["host"] = "www.example.com" + targetParametersTypeLogDnaModel["port"] = int(1) + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["log_sink_crn"] = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + model["type"] = "logdna" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["parameters"] = []map[string]interface{}{targetParametersTypeLogDnaModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogDnaModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + targetParametersTypeLogDnaModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogDnaModel.Port = core.Int64Ptr(int64(1)) + + model := new(ibmcloudlogsroutingv0.TargetType) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + model.Type = core.StringPtr("logdna") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.Parameters = targetParametersTypeLogDnaModel + + result, err := logsrouting.DataSourceIBMLogsRouterTenantsTargetTypeToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMLogsRouterTenantsTargetParametersTypeLogDnaToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["host"] = "www.example.com" + model["port"] = int(1) + + assert.Equal(t, result, model) + } + + model := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + model.Host = core.StringPtr("www.example.com") + model.Port = core.Int64Ptr(int64(1)) + + result, err := logsrouting.DataSourceIBMLogsRouterTenantsTargetParametersTypeLogDnaToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMLogsRouterTenantsTargetTypeLogDnaToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogDnaModel := make(map[string]interface{}) + targetParametersTypeLogDnaModel["host"] = "www.example.com" + targetParametersTypeLogDnaModel["port"] = int(8080) + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["log_sink_crn"] = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + model["type"] = "logdna" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["parameters"] = []map[string]interface{}{targetParametersTypeLogDnaModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogDnaModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + targetParametersTypeLogDnaModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogDnaModel.Port = core.Int64Ptr(int64(8080)) + + model := new(ibmcloudlogsroutingv0.TargetTypeLogDna) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + model.Type = core.StringPtr("logdna") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.Parameters = targetParametersTypeLogDnaModel + + result, err := logsrouting.DataSourceIBMLogsRouterTenantsTargetTypeLogDnaToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMLogsRouterTenantsTargetTypeLogsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogsModel := make(map[string]interface{}) + targetParametersTypeLogsModel["host"] = "www.example.com" + targetParametersTypeLogsModel["port"] = int(8080) + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["log_sink_crn"] = "crn:v1:bluemix:public:logs:eu-de:a/4516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + model["type"] = "logs" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["parameters"] = []map[string]interface{}{targetParametersTypeLogsModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogsModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogs) + targetParametersTypeLogsModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogsModel.Port = core.Int64Ptr(int64(8080)) + + model := new(ibmcloudlogsroutingv0.TargetTypeLogs) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logs:eu-de:a/4516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + model.Type = core.StringPtr("logs") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.Parameters = targetParametersTypeLogsModel + + result, err := logsrouting.DataSourceIBMLogsRouterTenantsTargetTypeLogsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMLogsRouterTenantsTargetParametersTypeLogsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["host"] = "www.example.com" + model["port"] = int(1) + + assert.Equal(t, result, model) + } + + model := new(ibmcloudlogsroutingv0.TargetParametersTypeLogs) + model.Host = core.StringPtr("www.example.com") + model.Port = core.Int64Ptr(int64(1)) + + result, err := logsrouting.DataSourceIBMLogsRouterTenantsTargetParametersTypeLogsToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/logsrouting/resource_ibm_logs-router_tenant.go b/ibm/service/logsrouting/resource_ibm_logs-router_tenant.go new file mode 100644 index 0000000000..0788aea6db --- /dev/null +++ b/ibm/service/logsrouting/resource_ibm_logs-router_tenant.go @@ -0,0 +1,766 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.90.1-64fd3296-20240515-180710 + */ + +package logsrouting + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/go-openapi/strfmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/logs-router-go-sdk/ibmcloudlogsroutingv0" +) + +func ResourceIBMLogsRouterTenant() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMLogsRouterTenantCreate, + ReadContext: resourceIBMLogsRouterTenantRead, + UpdateContext: resourceIBMLogsRouterTenantUpdate, + DeleteContext: resourceIBMLogsRouterTenantDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_logs_router_tenant", "name"), + Description: "The name for this tenant. The name is regionally unique across all tenants in the account.", + }, + "targets": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Description: "List of targets", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Unique ID of the target.", + }, + "log_sink_crn": &schema.Schema{ + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Description: "Cloud resource name of the log-sink target instance.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name for this tenant target. The name is unique across all targets for this tenant.", + }, + "etag": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Resource version identifier.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Type of log-sink. Identical to the service-name segment of log_sink_crn.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the target was originally created.", + }, + "updated_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the target was last updated.", + }, + "parameters": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "List of properties returned from a successful list operation for a log-sink of type IBM Log Analysis (logdna).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "host": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Host name of the log-sink.", + }, + "port": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + Description: "Network port of the log-sink.", + }, + "access_credential": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Sensitive: true, + Description: "Secret to connect to the log-sink", + }, + }, + }, + }, + }, + }, + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the tenant was originally created.", + }, + "updated_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Time stamp the tenant was last updated.", + }, + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Cloud resource name of the tenant.", + }, + "etag": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Resource version identifier.", + }, + }, + } +} + +func ResourceIBMLogsRouterTenantValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `[a-z,A-Z,0-9,-,.]`, + MinValueLength: 1, + MaxValueLength: 35, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_logs_router_tenant", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMLogsRouterTenantCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + ibmCloudLogsRoutingClient, err := meta.(conns.ClientSession).IBMCloudLogsRoutingV0() + if err != nil { + // Error is coming from SDK client, so it doesn't need to be discriminated. + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createTenantOptions := &ibmcloudlogsroutingv0.CreateTenantOptions{} + + createTenantOptions.SetName(d.Get("name").(string)) + var targets []ibmcloudlogsroutingv0.TargetTypePrototypeIntf + for _, v := range d.Get("targets").([]interface{}) { + value := v.(map[string]interface{}) + targetsItem, err := ResourceIBMLogsRouterTenantMapToTargetTypePrototype(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "create", "parse-targets").GetDiag() + } + targets = append(targets, targetsItem) + } + createTenantOptions.SetTargets(targets) + + tenant, _, err := ibmCloudLogsRoutingClient.CreateTenantWithContext(context, createTenantOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateTenantWithContext failed: %s", err.Error()), "ibm_logs_router_tenant", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(tenant.ID.String()) + + return resourceIBMLogsRouterTenantRead(context, d, meta) +} + +func resourceIBMLogsRouterTenantRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + ibmCloudLogsRoutingClient, err := meta.(conns.ClientSession).IBMCloudLogsRoutingV0() + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getTenantDetailOptions := &ibmcloudlogsroutingv0.GetTenantDetailOptions{} + + tenantId := strfmt.UUID(d.Id()) + getTenantDetailOptions.SetTenantID(&tenantId) + + tenant, response, err := ibmCloudLogsRoutingClient.GetTenantDetailWithContext(context, getTenantDetailOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetTenantDetailWithContext failed: %s", err.Error()), "ibm_logs_router_tenant", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + if err = d.Set("name", tenant.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "set-name").GetDiag() + } + targets := []map[string]interface{}{} + for _, targetsItem := range tenant.Targets { + targetsItemMap, err := ResourceIBMLogsRouterTenantTargetTypeToMap(targetsItem) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "targets-to-map").GetDiag() + } + targets = append(targets, targetsItemMap) + } + + saveCredsTarget0 := d.Get("targets.0.parameters.0.access_credential").(string) + saveCredsTarget1 := d.Get("targets.1.parameters.0.access_credential").(string) + if len(targets) == 2 { + if d.Get("targets.1.type").(string) == "logdna" { + targets[0], targets[1] = targets[1], targets[0] + } + } + + if err = d.Set("targets", targets); err != nil { + err = fmt.Errorf("Error setting targets: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "set-targets").GetDiag() + } + if err = d.Set("created_at", tenant.CreatedAt); err != nil { + err = fmt.Errorf("Error setting created_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "set-created_at").GetDiag() + } + if err = d.Set("updated_at", tenant.UpdatedAt); err != nil { + err = fmt.Errorf("Error setting updated_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "set-updated_at").GetDiag() + } + if err = d.Set("crn", tenant.CRN); err != nil { + err = fmt.Errorf("Error setting crn: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "set-crn").GetDiag() + } + if err = d.Set("etag", tenant.Etag); err != nil { + err = fmt.Errorf("Error setting etag: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "set-etag").GetDiag() + } + + rewriteAccessCredential := false + newCRNTarget0, check := d.GetOk("targets.0.log_sink_crn") + if check { + if crn, ok := newCRNTarget0.(string); ok && crn != "" { + if strings.Contains(crn, ":logdna:") { + model := &ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype{} + hostTarget0 := d.Get("targets.0.parameters.0.host").(string) + portTarget0 := int64(d.Get("targets.0.parameters.0.port").(int)) + model.Host = &hostTarget0 + model.Port = &portTarget0 + model.AccessCredential = &saveCredsTarget0 + parameters0Map, err := ResourceIBMLogsRouterTenantTargetParametersTypeLogDnaToMapAccessCredential(model) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "set-access_credential").GetDiag() + } + targets[0]["parameters"] = []map[string]interface{}{parameters0Map} + rewriteAccessCredential = true + } + } + } + + newCRNTarget1, check := d.GetOk("targets.1.log_sink_crn") + if check { + if crn, ok := newCRNTarget1.(string); ok && crn != "" { + if strings.Contains(crn, ":logdna:") { + model := &ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype{} + hostTarget1 := d.Get("targets.1.parameters.0.host").(string) + portTarget1 := int64(d.Get("targets.1.parameters.0.port").(int)) + model.Host = &hostTarget1 + model.Port = &portTarget1 + model.AccessCredential = &saveCredsTarget1 + parameters1Map, err := ResourceIBMLogsRouterTenantTargetParametersTypeLogDnaToMapAccessCredential(model) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "set-access_credential").GetDiag() + } + targets[1]["parameters"] = []map[string]interface{}{parameters1Map} + rewriteAccessCredential = true + } + } + } + + if rewriteAccessCredential { + if err = d.Set("targets", targets); err != nil { + err = fmt.Errorf("Error setting targets: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "read", "set-targets").GetDiag() + } + } + + return nil +} + +func resourceIBMLogsRouterTenantUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + ibmCloudLogsRoutingClient, err := meta.(conns.ClientSession).IBMCloudLogsRoutingV0() + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateTenantOptions := &ibmcloudlogsroutingv0.UpdateTenantOptions{} + + tenantId := strfmt.UUID(d.Id()) + updateTenantOptions.SetTenantID(&tenantId) + + hasChange := false + hasChangeTarget0 := false + hasChangeTarget1 := false + + patchVals := &ibmcloudlogsroutingv0.TenantPatch{} + + if d.HasChange("name") { + newName := d.Get("name").(string) + patchVals.Name = &newName + hasChange = true + } + + updateTenantOptions.SetIfMatch(d.Get("etag").(string)) + + updateTarget0Options := &ibmcloudlogsroutingv0.UpdateTargetOptions{} + target0ID := strfmt.UUID(d.Get("targets.0.id").(string)) + updateTarget0Options.SetTenantID(&tenantId) + updateTarget0Options.SetTargetID(&target0ID) + + patchValsTarget0 := &ibmcloudlogsroutingv0.TargetTypePatch{} + if d.HasChange("targets.0.tenant_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "tenant_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_logs_router_tenant", "update", "tenant_id-forces-new").GetDiag() + } + if d.HasChange("targets.0.log_sink_crn") { + newLogSinkCRN := d.Get("targets.0.log_sink_crn").(string) + patchValsTarget0.LogSinkCRN = &newLogSinkCRN + hasChangeTarget0 = true + } + if d.HasChange("targets.0.name") { + newName := d.Get("targets.0.name").(string) + patchValsTarget0.Name = &newName + hasChangeTarget0 = true + } + if d.HasChange("targets.0.parameters") { + parameters, err := ResourceIBMLogsRouterTargetMapToTargetParametersTypeLogDNAPrototype(d.Get("targets.0.parameters.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "update", "parse-parameters").GetDiag() + } + patchValsTarget0.Parameters = parameters + hasChangeTarget0 = true + } + updateTarget0Options.SetIfMatch(d.Get("targets.0.etag").(string)) + + updateTarget1Options := &ibmcloudlogsroutingv0.UpdateTargetOptions{} + target1ID := strfmt.UUID(d.Get("targets.1.id").(string)) + updateTarget1Options.SetTenantID(&tenantId) + updateTarget1Options.SetTargetID(&target1ID) + + bodyModelMap := map[string]interface{}{} + createTarget1Options := &ibmcloudlogsroutingv0.CreateTargetOptions{} + target1Create := false + if d.Get("targets.1.id").(string) == "" && d.Get("targets.1.log_sink_crn").(string) != "" { + target1Create = true + if _, ok := d.GetOk("targets.1.log_sink_crn"); ok { + bodyModelMap["log_sink_crn"] = d.Get("targets.1.log_sink_crn") + } + if _, ok := d.GetOk("targets.1.name"); ok { + bodyModelMap["name"] = d.Get("targets.1.name") + } + if _, ok := d.GetOk("targets.1.parameters"); ok { + bodyModelMap["parameters"] = d.Get("targets.1.parameters") + } + createTarget1Options.SetTenantID(&tenantId) + convertedModel, err := ResourceIBMLogsRouterTargetMapToTargetTypePrototypeTargetTypeLogDNAPrototype(bodyModelMap) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_target", "create", "parse-request-body").GetDiag() + } + createTarget1Options.TargetTypePrototype = convertedModel + } + + patchValsTarget1 := &ibmcloudlogsroutingv0.TargetTypePatch{} + if d.HasChange("targets.1.tenant_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "tenant_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_logs_router_tenant", "update", "tenant_id-forces-new").GetDiag() + } + if d.HasChange("targets.1.log_sink_crn") { + newLogSinkCRN := d.Get("targets.1.log_sink_crn").(string) + patchValsTarget1.LogSinkCRN = &newLogSinkCRN + hasChangeTarget1 = true + } + if d.HasChange("targets.1.name") { + newName := d.Get("targets.1.name").(string) + patchValsTarget1.Name = &newName + hasChangeTarget1 = true + } + if d.HasChange("targets.1.parameters") { + parameters, err := ResourceIBMLogsRouterTargetMapToTargetParametersTypeLogDNAPrototype(d.Get("targets.1.parameters.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "update", "parse-parameters").GetDiag() + } + patchValsTarget1.Parameters = parameters + hasChangeTarget1 = true + } + updateTarget1Options.SetIfMatch(d.Get("targets.1.etag").(string)) + + if hasChange { + updateTenantOptions.TenantPatch, _ = patchVals.AsPatch() + + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments. + if _, exists := d.GetOk("name"); d.HasChange("name") && !exists { + updateTenantOptions.TenantPatch["name"] = nil + } + + _, _, err = ibmCloudLogsRoutingClient.UpdateTenantWithContext(context, updateTenantOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateTenantWithContext failed: %s", err.Error()), "ibm_logs_router_tenant", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + target0Patched := false + + // second target will be created either logDNA or logs, but first target must be changed first + // if there is a change to the existing target1, we have to apply that first either delete or udpate, then update target 0 + if target1Create && hasChangeTarget0 { + updateTarget0Options.TargetTypePatch, _ = patchValsTarget0.AsPatch() + + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments. + if _, exists := d.GetOk("targets.0.log_sink_crn"); d.HasChange("targets.0.log_sink_crn") && !exists { + updateTarget0Options.TargetTypePatch["log_sink_crn"] = nil + } + if _, exists := d.GetOk("targets.0.name"); d.HasChange("targets.0.name") && !exists { + updateTarget0Options.TargetTypePatch["name"] = nil + } + if _, exists := d.GetOk("targets.0.parameters"); d.HasChange("targets.0.parameters") && !exists { + updateTarget0Options.TargetTypePatch["parameters"] = nil + } + target0Patched = true + + _, newCRN := d.GetChange("targets.0.log_sink_crn") + if crn, ok := newCRN.(string); ok { + if strings.Contains(crn, ":logs:") { + _, _, err = ibmCloudLogsRoutingClient.UpdateLogsTargetWithContext(context, updateTarget0Options) + } else { + _, _, err = ibmCloudLogsRoutingClient.UpdateTargetWithContext(context, updateTarget0Options) + } + } + + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateTargetWithContext failed: %s", err.Error()), "ibm_logs_router_target", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + if target1Create { + _, _, err := ibmCloudLogsRoutingClient.CreateTargetWithContext(context, createTarget1Options) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateTargetWithContext failed: %s", err.Error()), "ibm_logs_router_target", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + } else if hasChangeTarget1 { + target1Delete := false + updateTarget1Options.TargetTypePatch, _ = patchValsTarget1.AsPatch() + + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments. + if _, exists := d.GetOk("targets.1.log_sink_crn"); d.HasChange("targets.1.log_sink_crn") && !exists { + updateTarget1Options.TargetTypePatch["log_sink_crn"] = nil + } + if _, exists := d.GetOk("targets.1.name"); d.HasChange("targets.1.name") && !exists { + updateTarget1Options.TargetTypePatch["name"] = nil + } + if _, exists := d.GetOk("targets.1.parameters"); d.HasChange("targets.1.parameters") && !exists { + updateTarget1Options.TargetTypePatch["parameters"] = nil + target1Delete = true + } + if target1Delete { + deleteTargetOptions := &ibmcloudlogsroutingv0.DeleteTargetOptions{} + deleteTargetOptions.SetTenantID(&tenantId) + deleteTargetOptions.SetTargetID(&target1ID) + _, err = ibmCloudLogsRoutingClient.DeleteTargetWithContext(context, deleteTargetOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteTargetWithContext failed: %s", err.Error()), "ibm_logs_router_target", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + } else { + _, newCRN := d.GetChange("targets.1.log_sink_crn") + if crn, ok := newCRN.(string); ok { + if strings.Contains(crn, ":logs:") { + _, _, err = ibmCloudLogsRoutingClient.UpdateLogsTargetWithContext(context, updateTarget1Options) + } else { + _, _, err = ibmCloudLogsRoutingClient.UpdateTargetWithContext(context, updateTarget1Options) + } + } + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateTargetWithContext failed: %s", err.Error()), "ibm_logs_router_target", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + } + + if hasChangeTarget0 && !target0Patched { + updateTarget0Options.TargetTypePatch, _ = patchValsTarget0.AsPatch() + + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments. + if _, exists := d.GetOk("targets.0.log_sink_crn"); d.HasChange("targets.0.log_sink_crn") && !exists { + updateTarget0Options.TargetTypePatch["log_sink_crn"] = nil + } + if _, exists := d.GetOk("targets.0.name"); d.HasChange("targets.0.name") && !exists { + updateTarget0Options.TargetTypePatch["name"] = nil + } + if _, exists := d.GetOk("targets.0.parameters"); d.HasChange("targets.0.parameters") && !exists { + updateTarget0Options.TargetTypePatch["parameters"] = nil + } + target0Patched = true + // update logs RM access credential + _, newCRN := d.GetChange("targets.0.log_sink_crn") + if crn, ok := newCRN.(string); ok { + if strings.Contains(crn, ":logs:") { + _, _, err = ibmCloudLogsRoutingClient.UpdateLogsTargetWithContext(context, updateTarget0Options) + } else { + _, _, err = ibmCloudLogsRoutingClient.UpdateTargetWithContext(context, updateTarget0Options) + } + } + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateTargetWithContext failed: %s", err.Error()), "ibm_logs_router_target", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIBMLogsRouterTenantRead(context, d, meta) +} + +func resourceIBMLogsRouterTenantDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + ibmCloudLogsRoutingClient, err := meta.(conns.ClientSession).IBMCloudLogsRoutingV0() + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_logs_router_tenant", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteTenantOptions := &ibmcloudlogsroutingv0.DeleteTenantOptions{} + + tenantId := strfmt.UUID(d.Id()) + deleteTenantOptions.SetTenantID(&tenantId) + + _, err = ibmCloudLogsRoutingClient.DeleteTenantWithContext(context, deleteTenantOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteTenantWithContext failed: %s", err.Error()), "ibm_logs_router_tenant", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIBMLogsRouterTenantMapToTargetTypePrototype(modelMap map[string]interface{}) (ibmcloudlogsroutingv0.TargetTypePrototypeIntf, error) { + model := &ibmcloudlogsroutingv0.TargetTypePrototype{} + if modelMap["log_sink_crn"] != nil && modelMap["log_sink_crn"].(string) != "" { + model.LogSinkCRN = core.StringPtr(modelMap["log_sink_crn"].(string)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["parameters"] != nil && len(modelMap["parameters"].([]interface{})) > 0 { + ParametersModel, err := ResourceIBMLogsRouterTenantMapToTargetParametersTypeLogDnaPrototype(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel + } + return model, nil +} + +func ResourceIBMLogsRouterTenantMapToTargetParametersTypeLogDnaPrototype(modelMap map[string]interface{}) (*ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype, error) { + model := &ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype{} + model.Host = core.StringPtr(modelMap["host"].(string)) + model.Port = core.Int64Ptr(int64(modelMap["port"].(int))) + model.AccessCredential = core.StringPtr(modelMap["access_credential"].(string)) + return model, nil +} + +func ResourceIBMLogsRouterTenantMapToTargetTypePrototypeTargetTypeLogDnaPrototype(modelMap map[string]interface{}) (*ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogDnaPrototype, error) { + model := &ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogDnaPrototype{} + model.LogSinkCRN = core.StringPtr(modelMap["log_sink_crn"].(string)) + model.Name = core.StringPtr(modelMap["name"].(string)) + if modelMap["parameters"] != nil && len(modelMap["parameters"].([]interface{})) > 0 { + ParametersModel, err := ResourceIBMLogsRouterTenantMapToTargetParametersTypeLogDnaPrototype(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel + } + return model, nil +} + +func ResourceIBMLogsRouterTenantMapToTargetTypePrototypeTargetTypeLogsPrototype(modelMap map[string]interface{}) (*ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogsPrototype, error) { + model := &ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogsPrototype{} + model.LogSinkCRN = core.StringPtr(modelMap["log_sink_crn"].(string)) + model.Name = core.StringPtr(modelMap["name"].(string)) + if modelMap["parameters"] != nil && len(modelMap["parameters"].([]interface{})) > 0 { + ParametersModel, err := ResourceIBMLogsRouterTenantMapToTargetParametersTypeLogsPrototype(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel + } + return model, nil +} + +func ResourceIBMLogsRouterTenantMapToTargetParametersTypeLogsPrototype(modelMap map[string]interface{}) (*ibmcloudlogsroutingv0.TargetParametersTypeLogsPrototype, error) { + model := &ibmcloudlogsroutingv0.TargetParametersTypeLogsPrototype{} + model.Host = core.StringPtr(modelMap["host"].(string)) + model.Port = core.Int64Ptr(int64(modelMap["port"].(int))) + return model, nil +} + +func ResourceIBMLogsRouterTenantTargetTypeToMap(model ibmcloudlogsroutingv0.TargetTypeIntf) (map[string]interface{}, error) { + if _, ok := model.(*ibmcloudlogsroutingv0.TargetTypeLogDna); ok { + return ResourceIBMLogsRouterTenantTargetTypeLogDnaToMap(model.(*ibmcloudlogsroutingv0.TargetTypeLogDna)) + } else if _, ok := model.(*ibmcloudlogsroutingv0.TargetTypeLogs); ok { + return ResourceIBMLogsRouterTenantTargetTypeLogsToMap(model.(*ibmcloudlogsroutingv0.TargetTypeLogs)) + } else if _, ok := model.(*ibmcloudlogsroutingv0.TargetType); ok { + modelMap := make(map[string]interface{}) + model := model.(*ibmcloudlogsroutingv0.TargetType) + if model.ID != nil { + modelMap["id"] = model.ID.String() + } + if model.LogSinkCRN != nil { + modelMap["log_sink_crn"] = *model.LogSinkCRN + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.Etag != nil { + modelMap["etag"] = *model.Etag + } + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.CreatedAt != nil { + modelMap["created_at"] = *model.CreatedAt + } + if model.UpdatedAt != nil { + modelMap["updated_at"] = *model.UpdatedAt + } + if model.Parameters != nil { + parametersMap, err := ResourceIBMLogsRouterTenantTargetParametersTypeLogDnaToMap(model.Parameters) + if err != nil { + return modelMap, err + } + modelMap["parameters"] = []map[string]interface{}{parametersMap} + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized ibmcloudlogsroutingv0.TargetTypeIntf subtype encountered") + } +} + +func ResourceIBMLogsRouterTenantTargetParametersTypeLogDnaToMap(model *ibmcloudlogsroutingv0.TargetParametersTypeLogDna) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["host"] = *model.Host + modelMap["port"] = flex.IntValue(model.Port) + return modelMap, nil +} + +func ResourceIBMLogsRouterTenantTargetParametersTypeLogDnaToMapAccessCredential(model *ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["host"] = *model.Host + modelMap["port"] = flex.IntValue(model.Port) + modelMap["access_credential"] = *model.AccessCredential // pragma: whitelist secret + return modelMap, nil +} + +func ResourceIBMLogsRouterTenantTargetTypeLogDnaToMap(model *ibmcloudlogsroutingv0.TargetTypeLogDna) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = model.ID.String() + modelMap["log_sink_crn"] = *model.LogSinkCRN + modelMap["name"] = *model.Name + modelMap["etag"] = *model.Etag + modelMap["type"] = *model.Type + modelMap["created_at"] = *model.CreatedAt + modelMap["updated_at"] = *model.UpdatedAt + if model.Parameters != nil { + parametersMap, err := ResourceIBMLogsRouterTenantTargetParametersTypeLogDnaToMap(model.Parameters) + if err != nil { + return modelMap, err + } + modelMap["parameters"] = []map[string]interface{}{parametersMap} + } + return modelMap, nil +} + +func ResourceIBMLogsRouterTenantTargetTypeLogsToMap(model *ibmcloudlogsroutingv0.TargetTypeLogs) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = model.ID.String() + modelMap["log_sink_crn"] = *model.LogSinkCRN + modelMap["name"] = *model.Name + modelMap["etag"] = *model.Etag + modelMap["type"] = *model.Type + modelMap["created_at"] = *model.CreatedAt + modelMap["updated_at"] = *model.UpdatedAt + if model.Parameters != nil { + parametersMap, err := ResourceIBMLogsRouterTenantTargetParametersTypeLogsToMap(model.Parameters) + if err != nil { + return modelMap, err + } + modelMap["parameters"] = []map[string]interface{}{parametersMap} + } + return modelMap, nil +} + +func ResourceIBMLogsRouterTenantTargetParametersTypeLogsToMap(model *ibmcloudlogsroutingv0.TargetParametersTypeLogs) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["host"] = *model.Host + modelMap["port"] = flex.IntValue(model.Port) + return modelMap, nil +} + +func ResourceIBMLogsRouterTargetMapToTargetParametersTypeLogDNAPrototype(modelMap map[string]interface{}) (*ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype, error) { + model := &ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype{} + model.Host = core.StringPtr(modelMap["host"].(string)) + model.Port = core.Int64Ptr(int64(modelMap["port"].(int))) + model.AccessCredential = core.StringPtr(modelMap["access_credential"].(string)) + return model, nil +} + +func ResourceIBMLogsRouterTargetMapToTargetTypePrototypeTargetTypeLogDNAPrototype(modelMap map[string]interface{}) (*ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogDnaPrototype, error) { + model := &ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogDnaPrototype{} + model.LogSinkCRN = core.StringPtr(modelMap["log_sink_crn"].(string)) + model.Name = core.StringPtr(modelMap["name"].(string)) + if modelMap["parameters"] != nil && len(modelMap["parameters"].([]interface{})) > 0 { + ParametersModel, err := ResourceIBMLogsRouterTargetMapToTargetParametersTypeLogDNAPrototype(modelMap["parameters"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Parameters = ParametersModel + } + return model, nil +} diff --git a/ibm/service/logsrouting/resource_ibm_logs-router_tenant_test.go b/ibm/service/logsrouting/resource_ibm_logs-router_tenant_test.go new file mode 100644 index 0000000000..af3559ba46 --- /dev/null +++ b/ibm/service/logsrouting/resource_ibm_logs-router_tenant_test.go @@ -0,0 +1,467 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package logsrouting_test + +import ( + "fmt" + "testing" + + "github.com/go-openapi/strfmt" + "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" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/logsrouting" + . "github.com/IBM-Cloud/terraform-provider-ibm/ibm/unittest" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/logs-router-go-sdk/ibmcloudlogsroutingv0" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMLogsRouterTenantBasic(t *testing.T) { + var conf ibmcloudlogsroutingv0.Tenant + name := fmt.Sprintf("tf-name-%d", acctest.RandIntRange(10, 100)) + host := fmt.Sprintf("www.example.%d.com", acctest.RandIntRange(10, 100)) + crn := "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + nameUpdate := fmt.Sprintf("tf-name-%d", acctest.RandIntRange(10, 100)) + hostUpdate := fmt.Sprintf("www.example.%d.com", acctest.RandIntRange(10, 100)) + crnUpdate := "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMLogsRouterTenantDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMLogsRouterTenantConfigBasic(name, crn, host), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMLogsRouterTenantExists("ibm_logs_router_tenant.logs_router_tenant_instance", conf), + resource.TestCheckResourceAttr("ibm_logs_router_tenant.logs_router_tenant_instance", "name", name), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMLogsRouterTenantConfigBasic(nameUpdate, crnUpdate, hostUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_logs_router_tenant.logs_router_tenant_instance", "name", nameUpdate), + ), + }, + resource.TestStep{ + ResourceName: "ibm_logs_router_tenant.logs_router_tenant_instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"targets.0.parameters.0.access_credential", "targets.1.parameters.0.access_credential"}, + }, + }, + }) +} + +func TestAccIBMLogsRouterTenantAllArgs(t *testing.T) { + var conf ibmcloudlogsroutingv0.Tenant + + name := fmt.Sprintf("tenant-name-%d", acctest.RandIntRange(10, 100)) + host0 := fmt.Sprintf("www.example.%d.com", acctest.RandIntRange(10, 100)) + port0 := acctest.RandIntRange(1, 9999) + target0Name := fmt.Sprintf("target-%s", acctest.RandString(4)) + accessCredential := fmt.Sprintf("access-%s", acctest.RandString(4)) + + nameUpdate := fmt.Sprintf("tenant-name-%d", acctest.RandIntRange(10, 100)) + host0Update := fmt.Sprintf("www.example.%d.com", acctest.RandIntRange(10, 100)) + port0Update := acctest.RandIntRange(1, 9999) + target0NameUpdate := fmt.Sprintf("target-%s", acctest.RandString(4)) + accessCredentialUpdate := fmt.Sprintf("access-%s", acctest.RandString(4)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMLogsRouterTenantDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMLogsRouterTenantConfigAllArgs(name, target0Name, host0, port0, accessCredential), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMLogsRouterTenantExists("ibm_logs_router_tenant.logs_router_tenant_instance", conf), + resource.TestCheckResourceAttr("ibm_logs_router_tenant.logs_router_tenant_instance", "name", name), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMLogsRouterTenantConfigAllArgs(nameUpdate, target0NameUpdate, host0Update, port0Update, accessCredentialUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_logs_router_tenant.logs_router_tenant_instance", "name", nameUpdate), + ), + }, + resource.TestStep{ + ResourceName: "ibm_logs_router_tenant.logs_router_tenant_instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"targets.0.parameters.0.access_credential", "targets.1.parameters.0.access_credential"}, + }, + }, + }) +} + +func testAccCheckIBMLogsRouterTenantConfigBasic(name string, crn string, host string) string { + return fmt.Sprintf(` + resource "ibm_logs_router_tenant" "logs_router_tenant_instance" { + name = "%s" + targets { + log_sink_crn = "%s" + name = "my-log-sink" + parameters { + host = "%s" + port = 1 + access_credential = "%s" + } + } + } + `, name, crn, host, acc.IngestionKey) +} + +func testAccCheckIBMLogsRouterTenantConfigAllArgs(name string, target0Name string, host0 string, port0 int, accessCredential string) string { + return fmt.Sprintf(` + resource "ibm_logs_router_tenant" "logs_router_tenant_instance" { + name = "%s" + targets { + log_sink_crn = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + name = "%s" + parameters { + host = "%s" + port = %d + access_credential = "%s" + } + } + } + `, name, target0Name, host0, port0, accessCredential) +} + +func testAccCheckIBMLogsRouterTenantExists(n string, obj ibmcloudlogsroutingv0.Tenant) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + ibmCloudLogsRoutingClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).IBMCloudLogsRoutingV0() + if err != nil { + return err + } + + getTenantDetailOptions := &ibmcloudlogsroutingv0.GetTenantDetailOptions{} + + tenantId := strfmt.UUID(rs.Primary.ID) + getTenantDetailOptions.SetTenantID(&tenantId) + + tenant, _, err := ibmCloudLogsRoutingClient.GetTenantDetail(getTenantDetailOptions) + if err != nil { + return err + } + + obj = *tenant + return nil + } +} + +func testAccCheckIBMLogsRouterTenantDestroy(s *terraform.State) error { + ibmCloudLogsRoutingClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).IBMCloudLogsRoutingV0() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_logs_router_tenant" { + continue + } + + getTenantDetailOptions := &ibmcloudlogsroutingv0.GetTenantDetailOptions{} + + tenantId := strfmt.UUID(rs.Primary.ID) + getTenantDetailOptions.SetTenantID(&tenantId) + + // Try to find the key + _, response, err := ibmCloudLogsRoutingClient.GetTenantDetail(getTenantDetailOptions) + + if err == nil { + return fmt.Errorf("logs_router_tenant still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for logs_router_tenant (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} + +func TestResourceIBMLogsRouterTenantTargetTypeToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogDnaModel := make(map[string]interface{}) + targetParametersTypeLogDnaModel["host"] = "www.example.com" + targetParametersTypeLogDnaModel["port"] = int(1) + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["log_sink_crn"] = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + model["type"] = "logdna" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["parameters"] = []map[string]interface{}{targetParametersTypeLogDnaModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogDnaModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + targetParametersTypeLogDnaModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogDnaModel.Port = core.Int64Ptr(int64(1)) + + model := new(ibmcloudlogsroutingv0.TargetType) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + model.Type = core.StringPtr("logdna") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.Parameters = targetParametersTypeLogDnaModel + + result, err := logsrouting.ResourceIBMLogsRouterTenantTargetTypeToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIBMLogsRouterTenantTargetParametersTypeLogDnaToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["host"] = "www.example.com" + model["port"] = int(1) + + assert.Equal(t, result, model) + } + + model := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + model.Host = core.StringPtr("www.example.com") + model.Port = core.Int64Ptr(int64(1)) + + result, err := logsrouting.ResourceIBMLogsRouterTenantTargetParametersTypeLogDnaToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIBMLogsRouterTenantTargetTypeLogDnaToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogDnaModel := make(map[string]interface{}) + targetParametersTypeLogDnaModel["host"] = "www.example.com" + targetParametersTypeLogDnaModel["port"] = int(8080) + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["log_sink_crn"] = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + model["type"] = "logdna" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["parameters"] = []map[string]interface{}{targetParametersTypeLogDnaModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogDnaModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDna) + targetParametersTypeLogDnaModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogDnaModel.Port = core.Int64Ptr(int64(8080)) + + model := new(ibmcloudlogsroutingv0.TargetTypeLogDna) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + model.Type = core.StringPtr("logdna") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.Parameters = targetParametersTypeLogDnaModel + + result, err := logsrouting.ResourceIBMLogsRouterTenantTargetTypeLogDnaToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIBMLogsRouterTenantTargetTypeLogsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + targetParametersTypeLogsModel := make(map[string]interface{}) + targetParametersTypeLogsModel["host"] = "www.example.com" + targetParametersTypeLogsModel["port"] = int(8080) + + model := make(map[string]interface{}) + model["id"] = "8717db99-2cfb-4ba6-a033-89c994c2e9f0" + model["log_sink_crn"] = "crn:v1:bluemix:public:logs:eu-de:a/4516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["etag"] = "c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6" + model["type"] = "logs" + model["created_at"] = "2024-06-20T18:30:00.143156Z" + model["updated_at"] = "2024-06-20T18:30:00.143156Z" + model["parameters"] = []map[string]interface{}{targetParametersTypeLogsModel} + + assert.Equal(t, result, model) + } + + targetParametersTypeLogsModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogs) + targetParametersTypeLogsModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogsModel.Port = core.Int64Ptr(int64(8080)) + + model := new(ibmcloudlogsroutingv0.TargetTypeLogs) + model.ID = CreateMockUUID("8717db99-2cfb-4ba6-a033-89c994c2e9f0") + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logs:eu-de:a/4516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Etag = core.StringPtr("c3a43545a7f2675970671ac3a57b8db067a1866b2222e1b950ee8da612e347c6") + model.Type = core.StringPtr("logs") + model.CreatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.UpdatedAt = core.StringPtr("2024-06-20T18:30:00.143156Z") + model.Parameters = targetParametersTypeLogsModel + + result, err := logsrouting.ResourceIBMLogsRouterTenantTargetTypeLogsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIBMLogsRouterTenantTargetParametersTypeLogsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["host"] = "www.example.com" + model["port"] = int(1) + + assert.Equal(t, result, model) + } + + model := new(ibmcloudlogsroutingv0.TargetParametersTypeLogs) + model.Host = core.StringPtr("www.example.com") + model.Port = core.Int64Ptr(int64(1)) + + result, err := logsrouting.ResourceIBMLogsRouterTenantTargetParametersTypeLogsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIBMLogsRouterTenantMapToTargetTypePrototype(t *testing.T) { + checkResult := func(result ibmcloudlogsroutingv0.TargetTypePrototypeIntf) { + targetParametersTypeLogDnaPrototypeModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype) + targetParametersTypeLogDnaPrototypeModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogDnaPrototypeModel.Port = core.Int64Ptr(int64(1)) + targetParametersTypeLogDnaPrototypeModel.AccessCredential = core.StringPtr("ingestion-secret") + + model := new(ibmcloudlogsroutingv0.TargetTypePrototype) + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Parameters = targetParametersTypeLogDnaPrototypeModel + + assert.Equal(t, result, model) + } + + targetParametersTypeLogDnaPrototypeModel := make(map[string]interface{}) + targetParametersTypeLogDnaPrototypeModel["host"] = "www.example.com" + targetParametersTypeLogDnaPrototypeModel["port"] = int(1) + targetParametersTypeLogDnaPrototypeModel["access_credential"] = "ingestion-secret" + + model := make(map[string]interface{}) + model["log_sink_crn"] = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["parameters"] = []interface{}{targetParametersTypeLogDnaPrototypeModel} + + result, err := logsrouting.ResourceIBMLogsRouterTenantMapToTargetTypePrototype(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIBMLogsRouterTenantMapToTargetParametersTypeLogDnaPrototype(t *testing.T) { + checkResult := func(result *ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype) { + model := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype) + model.Host = core.StringPtr("www.example.com") + model.Port = core.Int64Ptr(int64(1)) + model.AccessCredential = core.StringPtr("ingestion-secret") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["host"] = "www.example.com" + model["port"] = int(1) + model["access_credential"] = "ingestion-secret" + + result, err := logsrouting.ResourceIBMLogsRouterTenantMapToTargetParametersTypeLogDnaPrototype(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIBMLogsRouterTenantMapToTargetTypePrototypeTargetTypeLogDnaPrototype(t *testing.T) { + checkResult := func(result *ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogDnaPrototype) { + targetParametersTypeLogDnaPrototypeModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogDnaPrototype) + targetParametersTypeLogDnaPrototypeModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogDnaPrototypeModel.Port = core.Int64Ptr(int64(8080)) + targetParametersTypeLogDnaPrototypeModel.AccessCredential = core.StringPtr("an-ingestion-secret") + + model := new(ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogDnaPrototype) + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Parameters = targetParametersTypeLogDnaPrototypeModel + + assert.Equal(t, result, model) + } + + targetParametersTypeLogDnaPrototypeModel := make(map[string]interface{}) + targetParametersTypeLogDnaPrototypeModel["host"] = "www.example.com" + targetParametersTypeLogDnaPrototypeModel["port"] = int(8080) + targetParametersTypeLogDnaPrototypeModel["access_credential"] = "an-ingestion-secret" + + model := make(map[string]interface{}) + model["log_sink_crn"] = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["parameters"] = []interface{}{targetParametersTypeLogDnaPrototypeModel} + + result, err := logsrouting.ResourceIBMLogsRouterTenantMapToTargetTypePrototypeTargetTypeLogDnaPrototype(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIBMLogsRouterTenantMapToTargetTypePrototypeTargetTypeLogsPrototype(t *testing.T) { + checkResult := func(result *ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogsPrototype) { + targetParametersTypeLogsPrototypeModel := new(ibmcloudlogsroutingv0.TargetParametersTypeLogsPrototype) + targetParametersTypeLogsPrototypeModel.Host = core.StringPtr("www.example.com") + targetParametersTypeLogsPrototypeModel.Port = core.Int64Ptr(int64(8080)) + + model := new(ibmcloudlogsroutingv0.TargetTypePrototypeTargetTypeLogsPrototype) + model.LogSinkCRN = core.StringPtr("crn:v1:bluemix:public:logs:eu-de:a/4516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::") + model.Name = core.StringPtr("my-log-sink") + model.Parameters = targetParametersTypeLogsPrototypeModel + + assert.Equal(t, result, model) + } + + targetParametersTypeLogsPrototypeModel := make(map[string]interface{}) + targetParametersTypeLogsPrototypeModel["host"] = "www.example.com" + targetParametersTypeLogsPrototypeModel["port"] = int(8080) + + model := make(map[string]interface{}) + model["log_sink_crn"] = "crn:v1:bluemix:public:logs:eu-de:a/4516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + model["name"] = "my-log-sink" + model["parameters"] = []interface{}{targetParametersTypeLogsPrototypeModel} + + result, err := logsrouting.ResourceIBMLogsRouterTenantMapToTargetTypePrototypeTargetTypeLogsPrototype(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIBMLogsRouterTenantMapToTargetParametersTypeLogsPrototype(t *testing.T) { + checkResult := func(result *ibmcloudlogsroutingv0.TargetParametersTypeLogsPrototype) { + model := new(ibmcloudlogsroutingv0.TargetParametersTypeLogsPrototype) + model.Host = core.StringPtr("www.example.com") + model.Port = core.Int64Ptr(int64(1)) + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["host"] = "www.example.com" + model["port"] = int(1) + + result, err := logsrouting.ResourceIBMLogsRouterTenantMapToTargetParametersTypeLogsPrototype(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/partnercentersell/README.md b/ibm/service/partnercentersell/README.md new file mode 100644 index 0000000000..9fa78c0c7f --- /dev/null +++ b/ibm/service/partnercentersell/README.md @@ -0,0 +1,11 @@ +# Terraform IBM Provider + +This area is primarily for IBM provider contributors and maintainers. For information on _using_ Terraform and the IBM provider, see the links below. + + +## Handy Links +* [Find out about contributing](../../../CONTRIBUTING.md) to the IBM provider! +* IBM Provider Docs: [Home](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs) +* IBM Provider Docs: [One of the resources](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/onboarding_resource_broker) +* IBM API Docs: [IBM API Docs for ]() +* IBM SDK: [IBM SDK for ](https://github.com/IBM/appconfiguration-go-admin-sdk/tree/master/partnercentersellv1) diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_deployment.go b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_deployment.go new file mode 100644 index 0000000000..4bcc77ef7c --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_deployment.go @@ -0,0 +1,1262 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.94.1-71478489-20240820-161623 + */ + +package partnercentersell + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" +) + +func ResourceIbmOnboardingCatalogDeployment() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIbmOnboardingCatalogDeploymentCreate, + ReadContext: resourceIbmOnboardingCatalogDeploymentRead, + UpdateContext: resourceIbmOnboardingCatalogDeploymentUpdate, + DeleteContext: resourceIbmOnboardingCatalogDeploymentDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "product_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_deployment", "product_id"), + Description: "The unique ID of the product.", + }, + "catalog_product_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_deployment", "catalog_product_id"), + Description: "The unique ID of this global catalog product.", + }, + "catalog_plan_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_deployment", "catalog_plan_id"), + Description: "The unique ID of this global catalog plan.", + }, + "env": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_deployment", "env"), + Description: "The environment to fetch this object from.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_deployment", "name"), + Description: "The programmatic name of this deployment.", + }, + "active": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + Description: "Whether the service is active.", + }, + "disabled": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + Description: "Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled.", + }, + "kind": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_deployment", "kind"), + Description: "The kind of the global catalog object.", + }, + "overview_ui": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The object that contains the service details from the Overview page in global catalog.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "en": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Translated details about the service, for example, display name, short description, and long description.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "display_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The display name of the product.", + }, + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The short description of the product that is displayed in your catalog entry.", + }, + "long_description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The detailed description of your product that is displayed at the beginning of your product page in the catalog. Markdown markup language is supported.", + }, + }, + }, + }, + }, + }, + }, + "tags": &schema.Schema{ + Type: schema.TypeList, + Required: true, + Description: "A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "object_provider": &schema.Schema{ + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Required: true, + Description: "The provider or owner of the product.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name of the provider.", + }, + "email": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The email address of the provider.", + }, + }, + }, + }, + "metadata": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Global catalog deployment metadata.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rc_compatible": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the object is compatible with the resource controller service.", + }, + "ui": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The UI metadata of this service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "strings": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The data strings.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "en": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Translated content of additional information about the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "bullets": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of features that highlights your product's attributes and benefits for users.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The description about the features of the product.", + }, + "description_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The description about the features of the product in translation.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "title": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The descriptive title for the feature.", + }, + "title_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The descriptive title for the feature in translation.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "media": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of supporting media for this product.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "caption": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Provide a descriptive caption that indicates what the media illustrates. This caption is displayed in the catalog.", + }, + "caption_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The brief explanation for your images and videos in translation.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "thumbnail": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The reduced-size version of your images and videos.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The type of the media.", + }, + "url": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The URL that links to the media that shows off the product.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "urls": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The UI based URLs.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "doc_url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for your product documentation.", + }, + "terms_url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for your product's end user license agreement.", + }, + }, + }, + }, + "hidden": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the object is hidden from the consumption catalog.", + }, + "side_by_side_index": &schema.Schema{ + Type: schema.TypeFloat, + Optional: true, + Description: "When the objects are listed side-by-side, this value controls the ordering.", + }, + }, + }, + }, + "service": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The global catalog metadata of the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rc_provisionable": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the service is provisionable by the resource controller service.", + }, + "iam_compatible": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the service is compatible with the IAM service.", + }, + }, + }, + }, + }, + }, + }, + "url": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The global catalog URL of your product.", + }, + "catalog_deployment_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of a global catalog object.", + }, + }, + } +} + +func ResourceIbmOnboardingCatalogDeploymentValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "product_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9]{32}:o:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, + MinValueLength: 71, + MaxValueLength: 71, + }, + validate.ValidateSchema{ + Identifier: "catalog_product_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z\-_\d]+$`, + MinValueLength: 2, + MaxValueLength: 128, + }, + validate.ValidateSchema{ + Identifier: "catalog_plan_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z\-_\d]+$`, + MinValueLength: 2, + MaxValueLength: 128, + }, + validate.ValidateSchema{ + Identifier: "env", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-z]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexp, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-z0-9\-.]+$`, + }, + validate.ValidateSchema{ + Identifier: "kind", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: "deployment", + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_onboarding_catalog_deployment", Schema: validateSchema} + return &resourceValidator +} + +func resourceIbmOnboardingCatalogDeploymentCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createCatalogDeploymentOptions := &partnercentersellv1.CreateCatalogDeploymentOptions{} + + createCatalogDeploymentOptions.SetProductID(d.Get("product_id").(string)) + createCatalogDeploymentOptions.SetCatalogProductID(d.Get("catalog_product_id").(string)) + createCatalogDeploymentOptions.SetCatalogPlanID(d.Get("catalog_plan_id").(string)) + createCatalogDeploymentOptions.SetName(d.Get("name").(string)) + createCatalogDeploymentOptions.SetActive(d.Get("active").(bool)) + createCatalogDeploymentOptions.SetDisabled(d.Get("disabled").(bool)) + createCatalogDeploymentOptions.SetKind(d.Get("kind").(string)) + var tags []string + for _, v := range d.Get("tags").([]interface{}) { + tagsItem := v.(string) + tags = append(tags, tagsItem) + } + createCatalogDeploymentOptions.SetTags(tags) + objectProviderModel, err := ResourceIbmOnboardingCatalogDeploymentMapToCatalogProductProvider(d.Get("object_provider.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "create", "parse-object_provider").GetDiag() + } + createCatalogDeploymentOptions.SetObjectProvider(objectProviderModel) + if _, ok := d.GetOk("overview_ui"); ok { + overviewUiModel, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogOverviewUI(d.Get("overview_ui.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "create", "parse-overview_ui").GetDiag() + } + createCatalogDeploymentOptions.SetOverviewUi(overviewUiModel) + } + if _, ok := d.GetOk("metadata"); ok { + metadataModel, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogDeploymentMetadata(d.Get("metadata.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "create", "parse-metadata").GetDiag() + } + createCatalogDeploymentOptions.SetMetadata(metadataModel) + } + if _, ok := d.GetOk("env"); ok { + createCatalogDeploymentOptions.SetEnv(d.Get("env").(string)) + } + + globalCatalogDeployment, _, err := partnerCenterSellClient.CreateCatalogDeploymentWithContext(context, createCatalogDeploymentOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateCatalogDeploymentWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_deployment", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s/%s/%s", *createCatalogDeploymentOptions.ProductID, *createCatalogDeploymentOptions.CatalogProductID, *createCatalogDeploymentOptions.CatalogPlanID, *globalCatalogDeployment.ID)) + + return resourceIbmOnboardingCatalogDeploymentRead(context, d, meta) +} + +func resourceIbmOnboardingCatalogDeploymentRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getCatalogDeploymentOptions := &partnercentersellv1.GetCatalogDeploymentOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "sep-id-parts").GetDiag() + } + + getCatalogDeploymentOptions.SetProductID(parts[0]) + getCatalogDeploymentOptions.SetCatalogProductID(parts[1]) + getCatalogDeploymentOptions.SetCatalogPlanID(parts[2]) + getCatalogDeploymentOptions.SetCatalogDeploymentID(parts[3]) + if _, ok := d.GetOk("env"); ok { + getCatalogDeploymentOptions.SetEnv(d.Get("env").(string)) + } + + globalCatalogDeployment, response, err := partnerCenterSellClient.GetCatalogDeploymentWithContext(context, getCatalogDeploymentOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetCatalogDeploymentWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_deployment", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if err = d.Set("name", globalCatalogDeployment.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-name").GetDiag() + } + if err = d.Set("active", globalCatalogDeployment.Active); err != nil { + err = fmt.Errorf("Error setting active: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-active").GetDiag() + } + if err = d.Set("disabled", globalCatalogDeployment.Disabled); err != nil { + err = fmt.Errorf("Error setting disabled: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-disabled").GetDiag() + } + if err = d.Set("kind", globalCatalogDeployment.Kind); err != nil { + err = fmt.Errorf("Error setting kind: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-kind").GetDiag() + } + if !core.IsNil(globalCatalogDeployment.OverviewUi) { + overviewUiMap, err := ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUIToMap(globalCatalogDeployment.OverviewUi) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "overview_ui-to-map").GetDiag() + } + if err = d.Set("overview_ui", []map[string]interface{}{overviewUiMap}); err != nil { + err = fmt.Errorf("Error setting overview_ui: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-overview_ui").GetDiag() + } + } + if err = d.Set("tags", globalCatalogDeployment.Tags); err != nil { + err = fmt.Errorf("Error setting tags: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-tags").GetDiag() + } + objectProviderMap, err := ResourceIbmOnboardingCatalogDeploymentCatalogProductProviderToMap(globalCatalogDeployment.ObjectProvider) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "object_provider-to-map").GetDiag() + } + if err = d.Set("object_provider", []map[string]interface{}{objectProviderMap}); err != nil { + err = fmt.Errorf("Error setting object_provider: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-object_provider").GetDiag() + } + if !core.IsNil(globalCatalogDeployment.Metadata) { + metadataMap, err := ResourceIbmOnboardingCatalogDeploymentGlobalCatalogDeploymentMetadataToMap(globalCatalogDeployment.Metadata) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "metadata-to-map").GetDiag() + } + if err = d.Set("metadata", []map[string]interface{}{metadataMap}); err != nil { + err = fmt.Errorf("Error setting metadata: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-metadata").GetDiag() + } + } + if !core.IsNil(globalCatalogDeployment.URL) { + if err = d.Set("url", globalCatalogDeployment.URL); err != nil { + err = fmt.Errorf("Error setting url: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-url").GetDiag() + } + } + if !core.IsNil(globalCatalogDeployment.ID) { + if err = d.Set("catalog_deployment_id", globalCatalogDeployment.ID); err != nil { + err = fmt.Errorf("Error setting catalog_deployment_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "read", "set-catalog_deployment_id").GetDiag() + } + } + + return nil +} + +func resourceIbmOnboardingCatalogDeploymentUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateCatalogDeploymentOptions := &partnercentersellv1.UpdateCatalogDeploymentOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "update", "sep-id-parts").GetDiag() + } + + updateCatalogDeploymentOptions.SetProductID(parts[0]) + updateCatalogDeploymentOptions.SetCatalogProductID(parts[1]) + updateCatalogDeploymentOptions.SetCatalogPlanID(parts[2]) + updateCatalogDeploymentOptions.SetCatalogDeploymentID(parts[3]) + if _, ok := d.GetOk("env"); ok { + updateCatalogDeploymentOptions.SetEnv(d.Get("env").(string)) + } + + hasChange := false + + patchVals := &partnercentersellv1.GlobalCatalogDeploymentPatch{} + if d.HasChange("product_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "product_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_onboarding_catalog_deployment", "update", "product_id-forces-new").GetDiag() + } + if d.HasChange("catalog_product_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "catalog_product_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_onboarding_catalog_deployment", "update", "catalog_product_id-forces-new").GetDiag() + } + if d.HasChange("catalog_plan_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "catalog_plan_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_onboarding_catalog_deployment", "update", "catalog_plan_id-forces-new").GetDiag() + } + if d.HasChange("active") { + newActive := d.Get("active").(bool) + patchVals.Active = &newActive + hasChange = true + } + if d.HasChange("disabled") { + newDisabled := d.Get("disabled").(bool) + patchVals.Disabled = &newDisabled + hasChange = true + } + if d.HasChange("overview_ui") { + overviewUi, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogOverviewUI(d.Get("overview_ui.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "update", "parse-overview_ui").GetDiag() + } + patchVals.OverviewUi = overviewUi + hasChange = true + } + if d.HasChange("tags") { + var tags []string + for _, v := range d.Get("tags").([]interface{}) { + tagsItem := v.(string) + tags = append(tags, tagsItem) + } + patchVals.Tags = tags + hasChange = true + } + if d.HasChange("object_provider") { + objectProvider, err := ResourceIbmOnboardingCatalogDeploymentMapToCatalogProductProvider(d.Get("object_provider.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "update", "parse-object_provider").GetDiag() + } + patchVals.ObjectProvider = objectProvider + hasChange = true + } + if d.HasChange("metadata") { + metadata, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogDeploymentMetadata(d.Get("metadata.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "update", "parse-metadata").GetDiag() + } + patchVals.Metadata = metadata + hasChange = true + } + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateCatalogDeploymentOptions.GlobalCatalogDeploymentPatch = ResourceIbmOnboardingCatalogDeploymentGlobalCatalogDeploymentPatchAsPatch(patchVals, d) + + _, _, err = partnerCenterSellClient.UpdateCatalogDeploymentWithContext(context, updateCatalogDeploymentOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateCatalogDeploymentWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_deployment", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIbmOnboardingCatalogDeploymentRead(context, d, meta) +} + +func resourceIbmOnboardingCatalogDeploymentDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteCatalogDeploymentOptions := &partnercentersellv1.DeleteCatalogDeploymentOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_deployment", "delete", "sep-id-parts").GetDiag() + } + + deleteCatalogDeploymentOptions.SetProductID(parts[0]) + deleteCatalogDeploymentOptions.SetCatalogProductID(parts[1]) + deleteCatalogDeploymentOptions.SetCatalogPlanID(parts[2]) + deleteCatalogDeploymentOptions.SetCatalogDeploymentID(parts[3]) + if _, ok := d.GetOk("env"); ok { + deleteCatalogDeploymentOptions.SetEnv(d.Get("env").(string)) + } + + _, err = partnerCenterSellClient.DeleteCatalogDeploymentWithContext(context, deleteCatalogDeploymentOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteCatalogDeploymentWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_deployment", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToCatalogProductProvider(modelMap map[string]interface{}) (*partnercentersellv1.CatalogProductProvider, error) { + model := &partnercentersellv1.CatalogProductProvider{} + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["email"] != nil && modelMap["email"].(string) != "" { + model.Email = core.StringPtr(modelMap["email"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogOverviewUI(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogOverviewUI, error) { + model := &partnercentersellv1.GlobalCatalogOverviewUI{} + if modelMap["en"] != nil && len(modelMap["en"].([]interface{})) > 0 && modelMap["en"].([]interface{})[0] != nil { + EnModel, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogOverviewUITranslatedContent(modelMap["en"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.En = EnModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogOverviewUITranslatedContent(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogOverviewUITranslatedContent, error) { + model := &partnercentersellv1.GlobalCatalogOverviewUITranslatedContent{} + if modelMap["display_name"] != nil && modelMap["display_name"].(string) != "" { + model.DisplayName = core.StringPtr(modelMap["display_name"].(string)) + } + if modelMap["description"] != nil && modelMap["description"].(string) != "" { + model.Description = core.StringPtr(modelMap["description"].(string)) + } + if modelMap["long_description"] != nil && modelMap["long_description"].(string) != "" { + model.LongDescription = core.StringPtr(modelMap["long_description"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogDeploymentMetadata(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogDeploymentMetadata, error) { + model := &partnercentersellv1.GlobalCatalogDeploymentMetadata{} + if modelMap["rc_compatible"] != nil { + model.RcCompatible = core.BoolPtr(modelMap["rc_compatible"].(bool)) + } + if modelMap["ui"] != nil && len(modelMap["ui"].([]interface{})) > 0 && modelMap["ui"].([]interface{})[0] != nil { + UiModel, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUI(modelMap["ui"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Ui = UiModel + } + if modelMap["service"] != nil && len(modelMap["service"].([]interface{})) > 0 && modelMap["service"].([]interface{})[0] != nil { + ServiceModel, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataService(modelMap["service"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Service = ServiceModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUI(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUI, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUI{} + if modelMap["strings"] != nil && len(modelMap["strings"].([]interface{})) > 0 && modelMap["strings"].([]interface{})[0] != nil { + StringsModel, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIStrings(modelMap["strings"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Strings = StringsModel + } + if modelMap["urls"] != nil && len(modelMap["urls"].([]interface{})) > 0 && modelMap["urls"].([]interface{})[0] != nil { + UrlsModel, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIUrls(modelMap["urls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Urls = UrlsModel + } + if modelMap["hidden"] != nil { + model.Hidden = core.BoolPtr(modelMap["hidden"].(bool)) + } + if modelMap["side_by_side_index"] != nil { + model.SideBySideIndex = core.Float64Ptr(modelMap["side_by_side_index"].(float64)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIStrings(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUIStrings, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUIStrings{} + if modelMap["en"] != nil && len(modelMap["en"].([]interface{})) > 0 && modelMap["en"].([]interface{})[0] != nil { + EnModel, err := ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIStringsContent(modelMap["en"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.En = EnModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIStringsContent(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUIStringsContent, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUIStringsContent{} + if modelMap["bullets"] != nil { + bullets := []partnercentersellv1.CatalogHighlightItem{} + for _, bulletsItem := range modelMap["bullets"].([]interface{}) { + bulletsItemModel, err := ResourceIbmOnboardingCatalogDeploymentMapToCatalogHighlightItem(bulletsItem.(map[string]interface{})) + if err != nil { + return model, err + } + bullets = append(bullets, *bulletsItemModel) + } + model.Bullets = bullets + } + if modelMap["media"] != nil { + media := []partnercentersellv1.CatalogProductMediaItem{} + for _, mediaItem := range modelMap["media"].([]interface{}) { + mediaItemModel, err := ResourceIbmOnboardingCatalogDeploymentMapToCatalogProductMediaItem(mediaItem.(map[string]interface{})) + if err != nil { + return model, err + } + media = append(media, *mediaItemModel) + } + model.Media = media + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToCatalogHighlightItem(modelMap map[string]interface{}) (*partnercentersellv1.CatalogHighlightItem, error) { + model := &partnercentersellv1.CatalogHighlightItem{} + if modelMap["description"] != nil && modelMap["description"].(string) != "" { + model.Description = core.StringPtr(modelMap["description"].(string)) + } + if modelMap["description_i18n"] != nil { + model.DescriptionI18n = make(map[string]string) + for key, value := range modelMap["description_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.DescriptionI18n[key] = str + } + } + } + if modelMap["title"] != nil && modelMap["title"].(string) != "" { + model.Title = core.StringPtr(modelMap["title"].(string)) + } + if modelMap["title_i18n"] != nil { + model.TitleI18n = make(map[string]string) + for key, value := range modelMap["title_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.TitleI18n[key] = str + } + } + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToCatalogProductMediaItem(modelMap map[string]interface{}) (*partnercentersellv1.CatalogProductMediaItem, error) { + model := &partnercentersellv1.CatalogProductMediaItem{} + model.Caption = core.StringPtr(modelMap["caption"].(string)) + if modelMap["caption_i18n"] != nil { + model.CaptionI18n = make(map[string]string) + for key, value := range modelMap["caption_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.CaptionI18n[key] = str + } + } + } + if modelMap["thumbnail"] != nil && modelMap["thumbnail"].(string) != "" { + model.Thumbnail = core.StringPtr(modelMap["thumbnail"].(string)) + } + model.Type = core.StringPtr(modelMap["type"].(string)) + model.URL = core.StringPtr(modelMap["url"].(string)) + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIUrls(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUIUrls, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUIUrls{} + if modelMap["doc_url"] != nil && modelMap["doc_url"].(string) != "" { + model.DocURL = core.StringPtr(modelMap["doc_url"].(string)) + } + if modelMap["terms_url"] != nil && modelMap["terms_url"].(string) != "" { + model.TermsURL = core.StringPtr(modelMap["terms_url"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataService(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataService, error) { + model := &partnercentersellv1.GlobalCatalogMetadataService{} + if modelMap["rc_provisionable"] != nil { + model.RcProvisionable = core.BoolPtr(modelMap["rc_provisionable"].(bool)) + } + if modelMap["iam_compatible"] != nil { + model.IamCompatible = core.BoolPtr(modelMap["iam_compatible"].(bool)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUIToMap(model *partnercentersellv1.GlobalCatalogOverviewUI) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.En != nil { + enMap, err := ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUITranslatedContentToMap(model.En) + if err != nil { + return modelMap, err + } + modelMap["en"] = []map[string]interface{}{enMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUITranslatedContentToMap(model *partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.DisplayName != nil { + modelMap["display_name"] = *model.DisplayName + } + if model.Description != nil { + modelMap["description"] = *model.Description + } + if model.LongDescription != nil { + modelMap["long_description"] = *model.LongDescription + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentCatalogProductProviderToMap(model *partnercentersellv1.CatalogProductProvider) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.Email != nil { + modelMap["email"] = *model.Email + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogDeploymentMetadataToMap(model *partnercentersellv1.GlobalCatalogDeploymentMetadata) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.RcCompatible != nil { + modelMap["rc_compatible"] = *model.RcCompatible + } + if model.Ui != nil { + uiMap, err := ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIToMap(model.Ui) + if err != nil { + return modelMap, err + } + modelMap["ui"] = []map[string]interface{}{uiMap} + } + if model.Service != nil { + serviceMap, err := ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataServiceToMap(model.Service) + if err != nil { + return modelMap, err + } + modelMap["service"] = []map[string]interface{}{serviceMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIToMap(model *partnercentersellv1.GlobalCatalogMetadataUI) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Strings != nil { + stringsMap, err := ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsToMap(model.Strings) + if err != nil { + return modelMap, err + } + modelMap["strings"] = []map[string]interface{}{stringsMap} + } + if model.Urls != nil { + urlsMap, err := ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIUrlsToMap(model.Urls) + if err != nil { + return modelMap, err + } + modelMap["urls"] = []map[string]interface{}{urlsMap} + } + if model.Hidden != nil { + modelMap["hidden"] = *model.Hidden + } + if model.SideBySideIndex != nil { + modelMap["side_by_side_index"] = *model.SideBySideIndex + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsToMap(model *partnercentersellv1.GlobalCatalogMetadataUIStrings) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.En != nil { + enMap, err := ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsContentToMap(model.En) + if err != nil { + return modelMap, err + } + modelMap["en"] = []map[string]interface{}{enMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsContentToMap(model *partnercentersellv1.GlobalCatalogMetadataUIStringsContent) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Bullets != nil { + bullets := []map[string]interface{}{} + for _, bulletsItem := range model.Bullets { + bulletsItemMap, err := ResourceIbmOnboardingCatalogDeploymentCatalogHighlightItemToMap(&bulletsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + bullets = append(bullets, bulletsItemMap) + } + modelMap["bullets"] = bullets + } + if model.Media != nil { + media := []map[string]interface{}{} + for _, mediaItem := range model.Media { + mediaItemMap, err := ResourceIbmOnboardingCatalogDeploymentCatalogProductMediaItemToMap(&mediaItem) // #nosec G601 + if err != nil { + return modelMap, err + } + media = append(media, mediaItemMap) + } + modelMap["media"] = media + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentCatalogHighlightItemToMap(model *partnercentersellv1.CatalogHighlightItem) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Description != nil { + modelMap["description"] = *model.Description + } + if model.DescriptionI18n != nil { + descriptionI18n := make(map[string]interface{}) + for k, v := range model.DescriptionI18n { + descriptionI18n[k] = flex.Stringify(v) + } + modelMap["description_i18n"] = descriptionI18n + } + if model.Title != nil { + modelMap["title"] = *model.Title + } + if model.TitleI18n != nil { + titleI18n := make(map[string]interface{}) + for k, v := range model.TitleI18n { + titleI18n[k] = flex.Stringify(v) + } + modelMap["title_i18n"] = titleI18n + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentCatalogProductMediaItemToMap(model *partnercentersellv1.CatalogProductMediaItem) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["caption"] = *model.Caption + if model.CaptionI18n != nil { + captionI18n := make(map[string]interface{}) + for k, v := range model.CaptionI18n { + captionI18n[k] = flex.Stringify(v) + } + modelMap["caption_i18n"] = captionI18n + } + if model.Thumbnail != nil { + modelMap["thumbnail"] = *model.Thumbnail + } + modelMap["type"] = *model.Type + modelMap["url"] = *model.URL + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIUrlsToMap(model *partnercentersellv1.GlobalCatalogMetadataUIUrls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.DocURL != nil { + modelMap["doc_url"] = *model.DocURL + } + if model.TermsURL != nil { + modelMap["terms_url"] = *model.TermsURL + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataServiceToMap(model *partnercentersellv1.GlobalCatalogMetadataService) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.RcProvisionable != nil { + modelMap["rc_provisionable"] = *model.RcProvisionable + } + if model.IamCompatible != nil { + modelMap["iam_compatible"] = *model.IamCompatible + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogDeploymentPatchAsPatch(patchVals *partnercentersellv1.GlobalCatalogDeploymentPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "active" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["active"] = nil + } + path = "disabled" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["disabled"] = nil + } + path = "overview_ui" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["overview_ui"] = nil + } else if exists && patch["overview_ui"] != nil { + ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUIAsPatch(patch["overview_ui"].(map[string]interface{}), d) + } + path = "tags" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["tags"] = nil + } + path = "object_provider" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["object_provider"] = nil + } else if exists && patch["object_provider"] != nil { + ResourceIbmOnboardingCatalogDeploymentCatalogProductProviderAsPatch(patch["object_provider"].(map[string]interface{}), d) + } + path = "metadata" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["metadata"] = nil + } else if exists && patch["metadata"] != nil { + ResourceIbmOnboardingCatalogDeploymentGlobalCatalogDeploymentMetadataAsPatch(patch["metadata"].(map[string]interface{}), d) + } + + return patch +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogDeploymentMetadataAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.rc_compatible" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["rc_compatible"] = nil + } + path = "metadata.0.ui" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["ui"] = nil + } else if exists && patch["ui"] != nil { + ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIAsPatch(patch["ui"].(map[string]interface{}), d) + } + path = "metadata.0.service" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["service"] = nil + } else if exists && patch["service"] != nil { + ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataServiceAsPatch(patch["service"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataServiceAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.service.0.rc_provisionable" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["rc_provisionable"] = nil + } + path = "metadata.0.service.0.iam_compatible" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["iam_compatible"] = nil + } +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["strings"] = nil + } else if exists && patch["strings"] != nil { + ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsAsPatch(patch["strings"].(map[string]interface{}), d) + } + path = "metadata.0.ui.0.urls" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["urls"] = nil + } else if exists && patch["urls"] != nil { + ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIUrlsAsPatch(patch["urls"].(map[string]interface{}), d) + } + path = "metadata.0.ui.0.hidden" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["hidden"] = nil + } + path = "metadata.0.ui.0.side_by_side_index" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["side_by_side_index"] = nil + } +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIUrlsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.urls.0.doc_url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["doc_url"] = nil + } + path = "metadata.0.ui.0.urls.0.terms_url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["terms_url"] = nil + } +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["en"] = nil + } else if exists && patch["en"] != nil { + ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsContentAsPatch(patch["en"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsContentAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en.0.bullets" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["bullets"] = nil + } else if exists && patch["bullets"] != nil { + ResourceIbmOnboardingCatalogDeploymentCatalogHighlightItemAsPatch(patch["bullets"].([]interface{})[0].(map[string]interface{}), d) + } + path = "metadata.0.ui.0.strings.0.en.0.media" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["media"] = nil + } else if exists && patch["media"] != nil { + ResourceIbmOnboardingCatalogDeploymentCatalogProductMediaItemAsPatch(patch["media"].([]interface{})[0].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogDeploymentCatalogProductMediaItemAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en.0.media.0.caption_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["caption_i18n"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.media.0.thumbnail" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["thumbnail"] = nil + } +} + +func ResourceIbmOnboardingCatalogDeploymentCatalogHighlightItemAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.description_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description_i18n"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.title" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["title"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.title_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["title_i18n"] = nil + } +} + +func ResourceIbmOnboardingCatalogDeploymentCatalogProductProviderAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "object_provider.0.name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["name"] = nil + } + path = "object_provider.0.email" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["email"] = nil + } +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUIAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "overview_ui.0.en" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["en"] = nil + } else if exists && patch["en"] != nil { + ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUITranslatedContentAsPatch(patch["en"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUITranslatedContentAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "overview_ui.0.en.0.display_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["display_name"] = nil + } + path = "overview_ui.0.en.0.description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description"] = nil + } + path = "overview_ui.0.en.0.long_description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["long_description"] = nil + } +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_deployment_test.go b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_deployment_test.go new file mode 100644 index 0000000000..7565649f89 --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_deployment_test.go @@ -0,0 +1,1059 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package partnercentersell_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/partnercentersell" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIbmOnboardingCatalogDeploymentBasic(t *testing.T) { + var conf partnercentersellv1.GlobalCatalogDeployment + productID := acc.PcsOnboardingProductWithCatalogProduct + catalogProductID := acc.PcsOnboardingCatalogProductId + catalogPlanID := acc.PcsOnboardingCatalogPlanId + name := "test-deployment-name-terraform" + active := "true" + disabled := "false" + kind := "deployment" + nameUpdate := "test-deployment-name-terraform" + activeUpdate := "false" + disabledUpdate := "false" + kindUpdate := "deployment" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingCatalogDeploymentDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogDeploymentConfigBasic(productID, catalogProductID, catalogPlanID, name, active, disabled, kind), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingCatalogDeploymentExists("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "catalog_product_id", catalogProductID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "catalog_plan_id", catalogPlanID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "name", name), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "active", active), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "disabled", disabled), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "kind", kind), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogDeploymentConfigBasic(productID, catalogProductID, catalogPlanID, nameUpdate, activeUpdate, disabledUpdate, kindUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "catalog_product_id", catalogProductID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "catalog_plan_id", catalogPlanID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "name", nameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "active", activeUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "disabled", disabledUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "kind", kindUpdate), + ), + }, + }, + }) +} + +func TestAccIbmOnboardingCatalogDeploymentAllArgs(t *testing.T) { + var conf partnercentersellv1.GlobalCatalogDeployment + productID := acc.PcsOnboardingProductWithCatalogProduct + catalogProductID := acc.PcsOnboardingCatalogProductId + catalogPlanID := acc.PcsOnboardingCatalogPlanId + env := "current" + name := "test-deployment-name-terraform" + active := "true" + disabled := "false" + kind := "deployment" + envUpdate := "current" + nameUpdate := "test-deployment-name-terraform" + activeUpdate := "false" + disabledUpdate := "false" + kindUpdate := "deployment" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingCatalogDeploymentDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogDeploymentConfig(productID, catalogProductID, catalogPlanID, env, name, active, disabled, kind), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingCatalogDeploymentExists("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "catalog_product_id", catalogProductID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "catalog_plan_id", catalogPlanID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "env", env), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "name", name), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "active", active), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "disabled", disabled), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "kind", kind), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogDeploymentConfig(productID, catalogProductID, catalogPlanID, envUpdate, nameUpdate, activeUpdate, disabledUpdate, kindUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "catalog_product_id", catalogProductID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "catalog_plan_id", catalogPlanID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "env", envUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "name", nameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "active", activeUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "disabled", disabledUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", "kind", kindUpdate), + ), + }, + resource.TestStep{ + ResourceName: "ibm_onboarding_catalog_deployment.onboarding_catalog_deployment_instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "env", "product_id", "catalog_product_id", "catalog_plan_id", + }, + }, + }, + }) +} + +func testAccCheckIbmOnboardingCatalogDeploymentConfigBasic(productID string, catalogProductID string, catalogPlanID string, name string, active string, disabled string, kind string) string { + return fmt.Sprintf(` + resource "ibm_onboarding_catalog_deployment" "onboarding_catalog_deployment_instance" { + product_id = "%s" + catalog_product_id = "%s" + catalog_plan_id = "%s" + name = "%s" + active = %s + disabled = %s + kind = "%s" + tags = ["sample"] + object_provider { + name = "name" + email = "email@email.com" + } + metadata { + service { + rc_provisionable = true + iam_compatible = true + } + rc_compatible = false + } + } + `, productID, catalogProductID, catalogPlanID, name, active, disabled, kind) +} + +func testAccCheckIbmOnboardingCatalogDeploymentConfig(productID string, catalogProductID string, catalogPlanID string, env string, name string, active string, disabled string, kind string) string { + return fmt.Sprintf(` + + resource "ibm_onboarding_catalog_deployment" "onboarding_catalog_deployment_instance" { + product_id = "%s" + catalog_product_id = "%s" + catalog_plan_id = "%s" + env = "%s" + name = "%s" + active = %s + disabled = %s + kind = "%s" + overview_ui { + en { + display_name = "display_name" + description = "description" + long_description = "long_description" + } + } + tags = ["sample"] + object_provider { + name = "name" + email = "email@email.com" + } + metadata { + rc_compatible = true + service { + rc_provisionable = true + iam_compatible = true + } + ui { + hidden = true + side_by_side_index = 1.0 + } + } + } + `, productID, catalogProductID, catalogPlanID, env, name, active, disabled, kind) +} + +func testAccCheckIbmOnboardingCatalogDeploymentExists(n string, obj partnercentersellv1.GlobalCatalogDeployment) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + + getCatalogDeploymentOptions := &partnercentersellv1.GetCatalogDeploymentOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getCatalogDeploymentOptions.SetProductID(parts[0]) + getCatalogDeploymentOptions.SetCatalogProductID(parts[1]) + getCatalogDeploymentOptions.SetCatalogPlanID(parts[2]) + getCatalogDeploymentOptions.SetCatalogDeploymentID(parts[3]) + + globalCatalogDeployment, _, err := partnerCenterSellClient.GetCatalogDeployment(getCatalogDeploymentOptions) + if err != nil { + return err + } + + obj = *globalCatalogDeployment + return nil + } +} + +func testAccCheckIbmOnboardingCatalogDeploymentDestroy(s *terraform.State) error { + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_onboarding_catalog_deployment" { + continue + } + + getCatalogDeploymentOptions := &partnercentersellv1.GetCatalogDeploymentOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getCatalogDeploymentOptions.SetProductID(parts[0]) + getCatalogDeploymentOptions.SetCatalogProductID(parts[1]) + getCatalogDeploymentOptions.SetCatalogPlanID(parts[2]) + getCatalogDeploymentOptions.SetCatalogDeploymentID(parts[3]) + + // Try to find the key + _, response, err := partnerCenterSellClient.GetCatalogDeployment(getCatalogDeploymentOptions) + + if err == nil { + return fmt.Errorf("onboarding_catalog_deployment still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for onboarding_catalog_deployment (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} + +func TestResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUIToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + globalCatalogOverviewUiTranslatedContentModel := make(map[string]interface{}) + globalCatalogOverviewUiTranslatedContentModel["display_name"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["description"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["long_description"] = "testString" + + model := make(map[string]interface{}) + model["en"] = []map[string]interface{}{globalCatalogOverviewUiTranslatedContentModel} + + assert.Equal(t, result, model) + } + + globalCatalogOverviewUiTranslatedContentModel := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + globalCatalogOverviewUiTranslatedContentModel.DisplayName = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.Description = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.LongDescription = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogOverviewUI) + model.En = globalCatalogOverviewUiTranslatedContentModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUIToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUITranslatedContentToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["display_name"] = "testString" + model["description"] = "testString" + model["long_description"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + model.DisplayName = core.StringPtr("testString") + model.Description = core.StringPtr("testString") + model.LongDescription = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentGlobalCatalogOverviewUITranslatedContentToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentCatalogProductProviderToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.CatalogProductProvider) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentCatalogProductProviderToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentGlobalCatalogDeploymentMetadataToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []map[string]interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + globalCatalogMetadataUiModel := make(map[string]interface{}) + globalCatalogMetadataUiModel["strings"] = []map[string]interface{}{globalCatalogMetadataUiStringsModel} + globalCatalogMetadataUiModel["urls"] = []map[string]interface{}{globalCatalogMetadataUiUrlsModel} + globalCatalogMetadataUiModel["hidden"] = true + globalCatalogMetadataUiModel["side_by_side_index"] = float64(72.5) + + globalCatalogMetadataServiceModel := make(map[string]interface{}) + globalCatalogMetadataServiceModel["rc_provisionable"] = true + globalCatalogMetadataServiceModel["iam_compatible"] = true + + model := make(map[string]interface{}) + model["rc_compatible"] = true + model["ui"] = []map[string]interface{}{globalCatalogMetadataUiModel} + model["service"] = []map[string]interface{}{globalCatalogMetadataServiceModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + globalCatalogMetadataUiModel := new(partnercentersellv1.GlobalCatalogMetadataUI) + globalCatalogMetadataUiModel.Strings = globalCatalogMetadataUiStringsModel + globalCatalogMetadataUiModel.Urls = globalCatalogMetadataUiUrlsModel + globalCatalogMetadataUiModel.Hidden = core.BoolPtr(true) + globalCatalogMetadataUiModel.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + globalCatalogMetadataServiceModel := new(partnercentersellv1.GlobalCatalogMetadataService) + globalCatalogMetadataServiceModel.RcProvisionable = core.BoolPtr(true) + globalCatalogMetadataServiceModel.IamCompatible = core.BoolPtr(true) + + model := new(partnercentersellv1.GlobalCatalogDeploymentMetadata) + model.RcCompatible = core.BoolPtr(true) + model.Ui = globalCatalogMetadataUiModel + model.Service = globalCatalogMetadataServiceModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentGlobalCatalogDeploymentMetadataToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []map[string]interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + model := make(map[string]interface{}) + model["strings"] = []map[string]interface{}{globalCatalogMetadataUiStringsModel} + model["urls"] = []map[string]interface{}{globalCatalogMetadataUiUrlsModel} + model["hidden"] = true + model["side_by_side_index"] = float64(72.5) + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUI) + model.Strings = globalCatalogMetadataUiStringsModel + model.Urls = globalCatalogMetadataUiUrlsModel + model.Hidden = core.BoolPtr(true) + model.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + model := make(map[string]interface{}) + model["en"] = []map[string]interface{}{globalCatalogMetadataUiStringsContentModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + model.En = globalCatalogMetadataUiStringsContentModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsContentToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + model := make(map[string]interface{}) + model["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + model["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + model.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + model.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIStringsContentToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentCatalogHighlightItemToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["description"] = "testString" + model["description_i18n"] = map[string]interface{}{"key1": "testString"} + model["title"] = "testString" + model["title_i18n"] = map[string]interface{}{"key1": "testString"} + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.CatalogHighlightItem) + model.Description = core.StringPtr("testString") + model.DescriptionI18n = map[string]string{"key1": "testString"} + model.Title = core.StringPtr("testString") + model.TitleI18n = map[string]string{"key1": "testString"} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentCatalogHighlightItemToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentCatalogProductMediaItemToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["caption"] = "testString" + model["caption_i18n"] = map[string]interface{}{"key1": "testString"} + model["thumbnail"] = "testString" + model["type"] = "image" + model["url"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.CatalogProductMediaItem) + model.Caption = core.StringPtr("testString") + model.CaptionI18n = map[string]string{"key1": "testString"} + model.Thumbnail = core.StringPtr("testString") + model.Type = core.StringPtr("image") + model.URL = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentCatalogProductMediaItemToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIUrlsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["doc_url"] = "testString" + model["terms_url"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + model.DocURL = core.StringPtr("testString") + model.TermsURL = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataUIUrlsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataServiceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["rc_provisionable"] = true + model["iam_compatible"] = true + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogMetadataService) + model.RcProvisionable = core.BoolPtr(true) + model.IamCompatible = core.BoolPtr(true) + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentGlobalCatalogMetadataServiceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToCatalogProductProvider(t *testing.T) { + checkResult := func(result *partnercentersellv1.CatalogProductProvider) { + model := new(partnercentersellv1.CatalogProductProvider) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToCatalogProductProvider(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogOverviewUI(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogOverviewUI) { + globalCatalogOverviewUiTranslatedContentModel := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + globalCatalogOverviewUiTranslatedContentModel.DisplayName = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.Description = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.LongDescription = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogOverviewUI) + model.En = globalCatalogOverviewUiTranslatedContentModel + + assert.Equal(t, result, model) + } + + globalCatalogOverviewUiTranslatedContentModel := make(map[string]interface{}) + globalCatalogOverviewUiTranslatedContentModel["display_name"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["description"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["long_description"] = "testString" + + model := make(map[string]interface{}) + model["en"] = []interface{}{globalCatalogOverviewUiTranslatedContentModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogOverviewUI(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogOverviewUITranslatedContent(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) { + model := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + model.DisplayName = core.StringPtr("testString") + model.Description = core.StringPtr("testString") + model.LongDescription = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["display_name"] = "testString" + model["description"] = "testString" + model["long_description"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogOverviewUITranslatedContent(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogDeploymentMetadata(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogDeploymentMetadata) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + globalCatalogMetadataUiModel := new(partnercentersellv1.GlobalCatalogMetadataUI) + globalCatalogMetadataUiModel.Strings = globalCatalogMetadataUiStringsModel + globalCatalogMetadataUiModel.Urls = globalCatalogMetadataUiUrlsModel + globalCatalogMetadataUiModel.Hidden = core.BoolPtr(true) + globalCatalogMetadataUiModel.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + globalCatalogMetadataServiceModel := new(partnercentersellv1.GlobalCatalogMetadataService) + globalCatalogMetadataServiceModel.RcProvisionable = core.BoolPtr(true) + globalCatalogMetadataServiceModel.IamCompatible = core.BoolPtr(true) + + model := new(partnercentersellv1.GlobalCatalogDeploymentMetadata) + model.RcCompatible = core.BoolPtr(true) + model.Ui = globalCatalogMetadataUiModel + model.Service = globalCatalogMetadataServiceModel + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + globalCatalogMetadataUiModel := make(map[string]interface{}) + globalCatalogMetadataUiModel["strings"] = []interface{}{globalCatalogMetadataUiStringsModel} + globalCatalogMetadataUiModel["urls"] = []interface{}{globalCatalogMetadataUiUrlsModel} + globalCatalogMetadataUiModel["hidden"] = true + globalCatalogMetadataUiModel["side_by_side_index"] = float64(72.5) + + globalCatalogMetadataServiceModel := make(map[string]interface{}) + globalCatalogMetadataServiceModel["rc_provisionable"] = true + globalCatalogMetadataServiceModel["iam_compatible"] = true + + model := make(map[string]interface{}) + model["rc_compatible"] = true + model["ui"] = []interface{}{globalCatalogMetadataUiModel} + model["service"] = []interface{}{globalCatalogMetadataServiceModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogDeploymentMetadata(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUI(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUI) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUI) + model.Strings = globalCatalogMetadataUiStringsModel + model.Urls = globalCatalogMetadataUiUrlsModel + model.Hidden = core.BoolPtr(true) + model.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + model := make(map[string]interface{}) + model["strings"] = []interface{}{globalCatalogMetadataUiStringsModel} + model["urls"] = []interface{}{globalCatalogMetadataUiUrlsModel} + model["hidden"] = true + model["side_by_side_index"] = float64(72.5) + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUI(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIStrings(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUIStrings) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + model.En = globalCatalogMetadataUiStringsContentModel + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []interface{}{catalogProductMediaItemModel} + + model := make(map[string]interface{}) + model["en"] = []interface{}{globalCatalogMetadataUiStringsContentModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIStrings(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIStringsContent(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUIStringsContent) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + model.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + model.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + model := make(map[string]interface{}) + model["bullets"] = []interface{}{catalogHighlightItemModel} + model["media"] = []interface{}{catalogProductMediaItemModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIStringsContent(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToCatalogHighlightItem(t *testing.T) { + checkResult := func(result *partnercentersellv1.CatalogHighlightItem) { + model := new(partnercentersellv1.CatalogHighlightItem) + model.Description = core.StringPtr("testString") + model.DescriptionI18n = map[string]string{"key1": "testString"} + model.Title = core.StringPtr("testString") + model.TitleI18n = map[string]string{"key1": "testString"} + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["description"] = "testString" + model["description_i18n"] = map[string]interface{}{"key1": "testString"} + model["title"] = "testString" + model["title_i18n"] = map[string]interface{}{"key1": "testString"} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToCatalogHighlightItem(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToCatalogProductMediaItem(t *testing.T) { + checkResult := func(result *partnercentersellv1.CatalogProductMediaItem) { + model := new(partnercentersellv1.CatalogProductMediaItem) + model.Caption = core.StringPtr("testString") + model.CaptionI18n = map[string]string{"key1": "testString"} + model.Thumbnail = core.StringPtr("testString") + model.Type = core.StringPtr("image") + model.URL = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["caption"] = "testString" + model["caption_i18n"] = map[string]interface{}{"key1": "testString"} + model["thumbnail"] = "testString" + model["type"] = "image" + model["url"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToCatalogProductMediaItem(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIUrls(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUIUrls) { + model := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + model.DocURL = core.StringPtr("testString") + model.TermsURL = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["doc_url"] = "testString" + model["terms_url"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataUIUrls(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataService(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataService) { + model := new(partnercentersellv1.GlobalCatalogMetadataService) + model.RcProvisionable = core.BoolPtr(true) + model.IamCompatible = core.BoolPtr(true) + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["rc_provisionable"] = true + model["iam_compatible"] = true + + result, err := partnercentersell.ResourceIbmOnboardingCatalogDeploymentMapToGlobalCatalogMetadataService(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_plan.go b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_plan.go new file mode 100644 index 0000000000..9b41aeebce --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_plan.go @@ -0,0 +1,1237 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.94.1-71478489-20240820-161623 + */ + +package partnercentersell + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" +) + +func ResourceIbmOnboardingCatalogPlan() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIbmOnboardingCatalogPlanCreate, + ReadContext: resourceIbmOnboardingCatalogPlanRead, + UpdateContext: resourceIbmOnboardingCatalogPlanUpdate, + DeleteContext: resourceIbmOnboardingCatalogPlanDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "product_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_plan", "product_id"), + Description: "The unique ID of the product.", + }, + "catalog_product_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_plan", "catalog_product_id"), + Description: "The unique ID of this global catalog product.", + }, + "env": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_plan", "env"), + Description: "The environment to fetch this object from.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_plan", "name"), + Description: "The programmatic name of this plan.", + }, + "active": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + Description: "Whether the service is active.", + }, + "disabled": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + Description: "Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled.", + }, + "kind": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_plan", "kind"), + Description: "The kind of the global catalog object.", + }, + "overview_ui": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The object that contains the service details from the Overview page in global catalog.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "en": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Translated details about the service, for example, display name, short description, and long description.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "display_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The display name of the product.", + }, + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The short description of the product that is displayed in your catalog entry.", + }, + "long_description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The detailed description of your product that is displayed at the beginning of your product page in the catalog. Markdown markup language is supported.", + }, + }, + }, + }, + }, + }, + }, + "tags": &schema.Schema{ + Type: schema.TypeList, + Required: true, + Description: "A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "object_provider": &schema.Schema{ + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Required: true, + Description: "The provider or owner of the product.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name of the provider.", + }, + "email": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The email address of the provider.", + }, + }, + }, + }, + "metadata": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Global catalog plan metadata.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rc_compatible": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the object is compatible with the resource controller service.", + }, + "ui": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The UI metadata of this service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "strings": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The data strings.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "en": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Translated content of additional information about the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "bullets": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of features that highlights your product's attributes and benefits for users.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The description about the features of the product.", + }, + "description_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The description about the features of the product in translation.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "title": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The descriptive title for the feature.", + }, + "title_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The descriptive title for the feature in translation.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "media": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of supporting media for this product.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "caption": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Provide a descriptive caption that indicates what the media illustrates. This caption is displayed in the catalog.", + }, + "caption_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The brief explanation for your images and videos in translation.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "thumbnail": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The reduced-size version of your images and videos.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The type of the media.", + }, + "url": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The URL that links to the media that shows off the product.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "urls": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The UI based URLs.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "doc_url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for your product documentation.", + }, + "terms_url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for your product's end user license agreement.", + }, + }, + }, + }, + "hidden": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the object is hidden from the consumption catalog.", + }, + "side_by_side_index": &schema.Schema{ + Type: schema.TypeFloat, + Optional: true, + Description: "When the objects are listed side-by-side, this value controls the ordering.", + }, + }, + }, + }, + "pricing": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The pricing metadata of this object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The type of the pricing plan.", + }, + "origin": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The source of the pricing information: global_catalog or pricing_catalog.", + }, + }, + }, + }, + }, + }, + }, + "url": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The global catalog URL of your product.", + }, + "catalog_plan_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of a global catalog object.", + }, + }, + } +} + +func ResourceIbmOnboardingCatalogPlanValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "product_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9]{32}:o:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, + MinValueLength: 71, + MaxValueLength: 71, + }, + validate.ValidateSchema{ + Identifier: "catalog_product_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z\-_\d]+$`, + MinValueLength: 2, + MaxValueLength: 128, + }, + validate.ValidateSchema{ + Identifier: "env", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-z]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexp, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-z0-9\-.]+$`, + }, + validate.ValidateSchema{ + Identifier: "kind", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: "plan", + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_onboarding_catalog_plan", Schema: validateSchema} + return &resourceValidator +} + +func resourceIbmOnboardingCatalogPlanCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createCatalogPlanOptions := &partnercentersellv1.CreateCatalogPlanOptions{} + + createCatalogPlanOptions.SetProductID(d.Get("product_id").(string)) + createCatalogPlanOptions.SetCatalogProductID(d.Get("catalog_product_id").(string)) + createCatalogPlanOptions.SetName(d.Get("name").(string)) + createCatalogPlanOptions.SetActive(d.Get("active").(bool)) + createCatalogPlanOptions.SetDisabled(d.Get("disabled").(bool)) + createCatalogPlanOptions.SetKind(d.Get("kind").(string)) + var tags []string + for _, v := range d.Get("tags").([]interface{}) { + tagsItem := v.(string) + tags = append(tags, tagsItem) + } + createCatalogPlanOptions.SetTags(tags) + objectProviderModel, err := ResourceIbmOnboardingCatalogPlanMapToCatalogProductProvider(d.Get("object_provider.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "create", "parse-object_provider").GetDiag() + } + createCatalogPlanOptions.SetObjectProvider(objectProviderModel) + if _, ok := d.GetOk("overview_ui"); ok { + overviewUiModel, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogOverviewUI(d.Get("overview_ui.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "create", "parse-overview_ui").GetDiag() + } + createCatalogPlanOptions.SetOverviewUi(overviewUiModel) + } + if _, ok := d.GetOk("metadata"); ok { + metadataModel, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogPlanMetadata(d.Get("metadata.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "create", "parse-metadata").GetDiag() + } + createCatalogPlanOptions.SetMetadata(metadataModel) + } + if _, ok := d.GetOk("env"); ok { + createCatalogPlanOptions.SetEnv(d.Get("env").(string)) + } + + globalCatalogPlan, _, err := partnerCenterSellClient.CreateCatalogPlanWithContext(context, createCatalogPlanOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateCatalogPlanWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_plan", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s/%s", *createCatalogPlanOptions.ProductID, *createCatalogPlanOptions.CatalogProductID, *globalCatalogPlan.ID)) + + return resourceIbmOnboardingCatalogPlanRead(context, d, meta) +} + +func resourceIbmOnboardingCatalogPlanRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getCatalogPlanOptions := &partnercentersellv1.GetCatalogPlanOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "sep-id-parts").GetDiag() + } + + getCatalogPlanOptions.SetProductID(parts[0]) + getCatalogPlanOptions.SetCatalogProductID(parts[1]) + getCatalogPlanOptions.SetCatalogPlanID(parts[2]) + if _, ok := d.GetOk("env"); ok { + getCatalogPlanOptions.SetEnv(d.Get("env").(string)) + } + + globalCatalogPlan, response, err := partnerCenterSellClient.GetCatalogPlanWithContext(context, getCatalogPlanOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetCatalogPlanWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_plan", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if err = d.Set("name", globalCatalogPlan.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-name").GetDiag() + } + if err = d.Set("active", globalCatalogPlan.Active); err != nil { + err = fmt.Errorf("Error setting active: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-active").GetDiag() + } + if err = d.Set("disabled", globalCatalogPlan.Disabled); err != nil { + err = fmt.Errorf("Error setting disabled: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-disabled").GetDiag() + } + if err = d.Set("kind", globalCatalogPlan.Kind); err != nil { + err = fmt.Errorf("Error setting kind: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-kind").GetDiag() + } + if !core.IsNil(globalCatalogPlan.OverviewUi) { + overviewUiMap, err := ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUIToMap(globalCatalogPlan.OverviewUi) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "overview_ui-to-map").GetDiag() + } + if err = d.Set("overview_ui", []map[string]interface{}{overviewUiMap}); err != nil { + err = fmt.Errorf("Error setting overview_ui: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-overview_ui").GetDiag() + } + } + if err = d.Set("tags", globalCatalogPlan.Tags); err != nil { + err = fmt.Errorf("Error setting tags: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-tags").GetDiag() + } + objectProviderMap, err := ResourceIbmOnboardingCatalogPlanCatalogProductProviderToMap(globalCatalogPlan.ObjectProvider) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "object_provider-to-map").GetDiag() + } + if err = d.Set("object_provider", []map[string]interface{}{objectProviderMap}); err != nil { + err = fmt.Errorf("Error setting object_provider: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-object_provider").GetDiag() + } + if !core.IsNil(globalCatalogPlan.Metadata) { + metadataMap, err := ResourceIbmOnboardingCatalogPlanGlobalCatalogPlanMetadataToMap(globalCatalogPlan.Metadata) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "metadata-to-map").GetDiag() + } + if err = d.Set("metadata", []map[string]interface{}{metadataMap}); err != nil { + err = fmt.Errorf("Error setting metadata: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-metadata").GetDiag() + } + } + if !core.IsNil(globalCatalogPlan.URL) { + if err = d.Set("url", globalCatalogPlan.URL); err != nil { + err = fmt.Errorf("Error setting url: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-url").GetDiag() + } + } + if !core.IsNil(globalCatalogPlan.ID) { + if err = d.Set("catalog_plan_id", globalCatalogPlan.ID); err != nil { + err = fmt.Errorf("Error setting catalog_plan_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "read", "set-catalog_plan_id").GetDiag() + } + } + + return nil +} + +func resourceIbmOnboardingCatalogPlanUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateCatalogPlanOptions := &partnercentersellv1.UpdateCatalogPlanOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "update", "sep-id-parts").GetDiag() + } + + updateCatalogPlanOptions.SetProductID(parts[0]) + updateCatalogPlanOptions.SetCatalogProductID(parts[1]) + updateCatalogPlanOptions.SetCatalogPlanID(parts[2]) + if _, ok := d.GetOk("env"); ok { + updateCatalogPlanOptions.SetEnv(d.Get("env").(string)) + } + + hasChange := false + + patchVals := &partnercentersellv1.GlobalCatalogPlanPatch{} + if d.HasChange("product_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "product_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_onboarding_catalog_plan", "update", "product_id-forces-new").GetDiag() + } + if d.HasChange("catalog_product_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "catalog_product_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_onboarding_catalog_plan", "update", "catalog_product_id-forces-new").GetDiag() + } + if d.HasChange("active") { + newActive := d.Get("active").(bool) + patchVals.Active = &newActive + hasChange = true + } + if d.HasChange("disabled") { + newDisabled := d.Get("disabled").(bool) + patchVals.Disabled = &newDisabled + hasChange = true + } + if d.HasChange("overview_ui") { + overviewUi, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogOverviewUI(d.Get("overview_ui.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "update", "parse-overview_ui").GetDiag() + } + patchVals.OverviewUi = overviewUi + hasChange = true + } + if d.HasChange("tags") { + var tags []string + for _, v := range d.Get("tags").([]interface{}) { + tagsItem := v.(string) + tags = append(tags, tagsItem) + } + patchVals.Tags = tags + hasChange = true + } + if d.HasChange("object_provider") { + objectProvider, err := ResourceIbmOnboardingCatalogPlanMapToCatalogProductProvider(d.Get("object_provider.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "update", "parse-object_provider").GetDiag() + } + patchVals.ObjectProvider = objectProvider + hasChange = true + } + if d.HasChange("metadata") { + metadata, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogPlanMetadata(d.Get("metadata.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "update", "parse-metadata").GetDiag() + } + patchVals.Metadata = metadata + hasChange = true + } + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateCatalogPlanOptions.GlobalCatalogPlanPatch = ResourceIbmOnboardingCatalogPlanGlobalCatalogPlanPatchAsPatch(patchVals, d) + + _, _, err = partnerCenterSellClient.UpdateCatalogPlanWithContext(context, updateCatalogPlanOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateCatalogPlanWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_plan", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIbmOnboardingCatalogPlanRead(context, d, meta) +} + +func resourceIbmOnboardingCatalogPlanDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteCatalogPlanOptions := &partnercentersellv1.DeleteCatalogPlanOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_plan", "delete", "sep-id-parts").GetDiag() + } + + deleteCatalogPlanOptions.SetProductID(parts[0]) + deleteCatalogPlanOptions.SetCatalogProductID(parts[1]) + deleteCatalogPlanOptions.SetCatalogPlanID(parts[2]) + if _, ok := d.GetOk("env"); ok { + deleteCatalogPlanOptions.SetEnv(d.Get("env").(string)) + } + + _, err = partnerCenterSellClient.DeleteCatalogPlanWithContext(context, deleteCatalogPlanOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteCatalogPlanWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_plan", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIbmOnboardingCatalogPlanMapToCatalogProductProvider(modelMap map[string]interface{}) (*partnercentersellv1.CatalogProductProvider, error) { + model := &partnercentersellv1.CatalogProductProvider{} + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["email"] != nil && modelMap["email"].(string) != "" { + model.Email = core.StringPtr(modelMap["email"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogOverviewUI(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogOverviewUI, error) { + model := &partnercentersellv1.GlobalCatalogOverviewUI{} + if modelMap["en"] != nil && len(modelMap["en"].([]interface{})) > 0 && modelMap["en"].([]interface{})[0] != nil { + EnModel, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogOverviewUITranslatedContent(modelMap["en"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.En = EnModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogOverviewUITranslatedContent(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogOverviewUITranslatedContent, error) { + model := &partnercentersellv1.GlobalCatalogOverviewUITranslatedContent{} + if modelMap["display_name"] != nil && modelMap["display_name"].(string) != "" { + model.DisplayName = core.StringPtr(modelMap["display_name"].(string)) + } + if modelMap["description"] != nil && modelMap["description"].(string) != "" { + model.Description = core.StringPtr(modelMap["description"].(string)) + } + if modelMap["long_description"] != nil && modelMap["long_description"].(string) != "" { + model.LongDescription = core.StringPtr(modelMap["long_description"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogPlanMetadata(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogPlanMetadata, error) { + model := &partnercentersellv1.GlobalCatalogPlanMetadata{} + if modelMap["rc_compatible"] != nil { + model.RcCompatible = core.BoolPtr(modelMap["rc_compatible"].(bool)) + } + if modelMap["ui"] != nil && len(modelMap["ui"].([]interface{})) > 0 && modelMap["ui"].([]interface{})[0] != nil { + UiModel, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUI(modelMap["ui"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Ui = UiModel + } + if modelMap["pricing"] != nil && len(modelMap["pricing"].([]interface{})) > 0 && modelMap["pricing"].([]interface{})[0] != nil { + PricingModel, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataPricing(modelMap["pricing"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Pricing = PricingModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUI(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUI, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUI{} + if modelMap["strings"] != nil && len(modelMap["strings"].([]interface{})) > 0 && modelMap["strings"].([]interface{})[0] != nil { + StringsModel, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIStrings(modelMap["strings"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Strings = StringsModel + } + if modelMap["urls"] != nil && len(modelMap["urls"].([]interface{})) > 0 && modelMap["urls"].([]interface{})[0] != nil { + UrlsModel, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIUrls(modelMap["urls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Urls = UrlsModel + } + if modelMap["hidden"] != nil { + model.Hidden = core.BoolPtr(modelMap["hidden"].(bool)) + } + if modelMap["side_by_side_index"] != nil { + model.SideBySideIndex = core.Float64Ptr(modelMap["side_by_side_index"].(float64)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIStrings(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUIStrings, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUIStrings{} + if modelMap["en"] != nil && len(modelMap["en"].([]interface{})) > 0 && modelMap["en"].([]interface{})[0] != nil { + EnModel, err := ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIStringsContent(modelMap["en"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.En = EnModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIStringsContent(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUIStringsContent, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUIStringsContent{} + if modelMap["bullets"] != nil { + bullets := []partnercentersellv1.CatalogHighlightItem{} + for _, bulletsItem := range modelMap["bullets"].([]interface{}) { + bulletsItemModel, err := ResourceIbmOnboardingCatalogPlanMapToCatalogHighlightItem(bulletsItem.(map[string]interface{})) + if err != nil { + return model, err + } + bullets = append(bullets, *bulletsItemModel) + } + model.Bullets = bullets + } + if modelMap["media"] != nil { + media := []partnercentersellv1.CatalogProductMediaItem{} + for _, mediaItem := range modelMap["media"].([]interface{}) { + mediaItemModel, err := ResourceIbmOnboardingCatalogPlanMapToCatalogProductMediaItem(mediaItem.(map[string]interface{})) + if err != nil { + return model, err + } + media = append(media, *mediaItemModel) + } + model.Media = media + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToCatalogHighlightItem(modelMap map[string]interface{}) (*partnercentersellv1.CatalogHighlightItem, error) { + model := &partnercentersellv1.CatalogHighlightItem{} + if modelMap["description"] != nil && modelMap["description"].(string) != "" { + model.Description = core.StringPtr(modelMap["description"].(string)) + } + if modelMap["description_i18n"] != nil { + model.DescriptionI18n = make(map[string]string) + for key, value := range modelMap["description_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.DescriptionI18n[key] = str + } + } + } + if modelMap["title"] != nil && modelMap["title"].(string) != "" { + model.Title = core.StringPtr(modelMap["title"].(string)) + } + if modelMap["title_i18n"] != nil { + model.TitleI18n = make(map[string]string) + for key, value := range modelMap["title_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.TitleI18n[key] = str + } + } + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToCatalogProductMediaItem(modelMap map[string]interface{}) (*partnercentersellv1.CatalogProductMediaItem, error) { + model := &partnercentersellv1.CatalogProductMediaItem{} + model.Caption = core.StringPtr(modelMap["caption"].(string)) + if modelMap["caption_i18n"] != nil { + model.CaptionI18n = make(map[string]string) + for key, value := range modelMap["caption_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.CaptionI18n[key] = str + } + } + } + if modelMap["thumbnail"] != nil && modelMap["thumbnail"].(string) != "" { + model.Thumbnail = core.StringPtr(modelMap["thumbnail"].(string)) + } + model.Type = core.StringPtr(modelMap["type"].(string)) + model.URL = core.StringPtr(modelMap["url"].(string)) + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIUrls(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUIUrls, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUIUrls{} + if modelMap["doc_url"] != nil && modelMap["doc_url"].(string) != "" { + model.DocURL = core.StringPtr(modelMap["doc_url"].(string)) + } + if modelMap["terms_url"] != nil && modelMap["terms_url"].(string) != "" { + model.TermsURL = core.StringPtr(modelMap["terms_url"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataPricing(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataPricing, error) { + model := &partnercentersellv1.GlobalCatalogMetadataPricing{} + if modelMap["type"] != nil && modelMap["type"].(string) != "" { + model.Type = core.StringPtr(modelMap["type"].(string)) + } + if modelMap["origin"] != nil && modelMap["origin"].(string) != "" { + model.Origin = core.StringPtr(modelMap["origin"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUIToMap(model *partnercentersellv1.GlobalCatalogOverviewUI) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.En != nil { + enMap, err := ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUITranslatedContentToMap(model.En) + if err != nil { + return modelMap, err + } + modelMap["en"] = []map[string]interface{}{enMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUITranslatedContentToMap(model *partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.DisplayName != nil { + modelMap["display_name"] = *model.DisplayName + } + if model.Description != nil { + modelMap["description"] = *model.Description + } + if model.LongDescription != nil { + modelMap["long_description"] = *model.LongDescription + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanCatalogProductProviderToMap(model *partnercentersellv1.CatalogProductProvider) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.Email != nil { + modelMap["email"] = *model.Email + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogPlanMetadataToMap(model *partnercentersellv1.GlobalCatalogPlanMetadata) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.RcCompatible != nil { + modelMap["rc_compatible"] = *model.RcCompatible + } + if model.Ui != nil { + uiMap, err := ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIToMap(model.Ui) + if err != nil { + return modelMap, err + } + modelMap["ui"] = []map[string]interface{}{uiMap} + } + if model.Pricing != nil { + pricingMap, err := ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataPricingToMap(model.Pricing) + if err != nil { + return modelMap, err + } + modelMap["pricing"] = []map[string]interface{}{pricingMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIToMap(model *partnercentersellv1.GlobalCatalogMetadataUI) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Strings != nil { + stringsMap, err := ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsToMap(model.Strings) + if err != nil { + return modelMap, err + } + modelMap["strings"] = []map[string]interface{}{stringsMap} + } + if model.Urls != nil { + urlsMap, err := ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIUrlsToMap(model.Urls) + if err != nil { + return modelMap, err + } + modelMap["urls"] = []map[string]interface{}{urlsMap} + } + if model.Hidden != nil { + modelMap["hidden"] = *model.Hidden + } + if model.SideBySideIndex != nil { + modelMap["side_by_side_index"] = *model.SideBySideIndex + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsToMap(model *partnercentersellv1.GlobalCatalogMetadataUIStrings) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.En != nil { + enMap, err := ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsContentToMap(model.En) + if err != nil { + return modelMap, err + } + modelMap["en"] = []map[string]interface{}{enMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsContentToMap(model *partnercentersellv1.GlobalCatalogMetadataUIStringsContent) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Bullets != nil { + bullets := []map[string]interface{}{} + for _, bulletsItem := range model.Bullets { + bulletsItemMap, err := ResourceIbmOnboardingCatalogPlanCatalogHighlightItemToMap(&bulletsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + bullets = append(bullets, bulletsItemMap) + } + modelMap["bullets"] = bullets + } + if model.Media != nil { + media := []map[string]interface{}{} + for _, mediaItem := range model.Media { + mediaItemMap, err := ResourceIbmOnboardingCatalogPlanCatalogProductMediaItemToMap(&mediaItem) // #nosec G601 + if err != nil { + return modelMap, err + } + media = append(media, mediaItemMap) + } + modelMap["media"] = media + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanCatalogHighlightItemToMap(model *partnercentersellv1.CatalogHighlightItem) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Description != nil { + modelMap["description"] = *model.Description + } + if model.DescriptionI18n != nil { + descriptionI18n := make(map[string]interface{}) + for k, v := range model.DescriptionI18n { + descriptionI18n[k] = flex.Stringify(v) + } + modelMap["description_i18n"] = descriptionI18n + } + if model.Title != nil { + modelMap["title"] = *model.Title + } + if model.TitleI18n != nil { + titleI18n := make(map[string]interface{}) + for k, v := range model.TitleI18n { + titleI18n[k] = flex.Stringify(v) + } + modelMap["title_i18n"] = titleI18n + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanCatalogProductMediaItemToMap(model *partnercentersellv1.CatalogProductMediaItem) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["caption"] = *model.Caption + if model.CaptionI18n != nil { + captionI18n := make(map[string]interface{}) + for k, v := range model.CaptionI18n { + captionI18n[k] = flex.Stringify(v) + } + modelMap["caption_i18n"] = captionI18n + } + if model.Thumbnail != nil { + modelMap["thumbnail"] = *model.Thumbnail + } + modelMap["type"] = *model.Type + modelMap["url"] = *model.URL + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIUrlsToMap(model *partnercentersellv1.GlobalCatalogMetadataUIUrls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.DocURL != nil { + modelMap["doc_url"] = *model.DocURL + } + if model.TermsURL != nil { + modelMap["terms_url"] = *model.TermsURL + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataPricingToMap(model *partnercentersellv1.GlobalCatalogMetadataPricing) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Origin != nil { + modelMap["origin"] = *model.Origin + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogPlanPatchAsPatch(patchVals *partnercentersellv1.GlobalCatalogPlanPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "active" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["active"] = nil + } + path = "disabled" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["disabled"] = nil + } + path = "overview_ui" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["overview_ui"] = nil + } else if exists && patch["overview_ui"] != nil { + ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUIAsPatch(patch["overview_ui"].(map[string]interface{}), d) + } + path = "tags" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["tags"] = nil + } + path = "object_provider" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["object_provider"] = nil + } else if exists && patch["object_provider"] != nil { + ResourceIbmOnboardingCatalogPlanCatalogProductProviderAsPatch(patch["object_provider"].(map[string]interface{}), d) + } + path = "metadata" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["metadata"] = nil + } else if exists && patch["metadata"] != nil { + ResourceIbmOnboardingCatalogPlanGlobalCatalogPlanMetadataAsPatch(patch["metadata"].(map[string]interface{}), d) + } + + return patch +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogPlanMetadataAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.rc_compatible" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["rc_compatible"] = nil + } + path = "metadata.0.ui" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["ui"] = nil + } else if exists && patch["ui"] != nil { + ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIAsPatch(patch["ui"].(map[string]interface{}), d) + } + path = "metadata.0.pricing" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["pricing"] = nil + } else if exists && patch["pricing"] != nil { + ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataPricingAsPatch(patch["pricing"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataPricingAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.pricing.0.type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["type"] = nil + } + path = "metadata.0.pricing.0.origin" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["origin"] = nil + } +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["strings"] = nil + } else if exists && patch["strings"] != nil { + ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsAsPatch(patch["strings"].(map[string]interface{}), d) + } + path = "metadata.0.ui.0.urls" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["urls"] = nil + } else if exists && patch["urls"] != nil { + ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIUrlsAsPatch(patch["urls"].(map[string]interface{}), d) + } + path = "metadata.0.ui.0.hidden" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["hidden"] = nil + } + path = "metadata.0.ui.0.side_by_side_index" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["side_by_side_index"] = nil + } +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIUrlsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.urls.0.doc_url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["doc_url"] = nil + } + path = "metadata.0.ui.0.urls.0.terms_url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["terms_url"] = nil + } +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["en"] = nil + } else if exists && patch["en"] != nil { + ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsContentAsPatch(patch["en"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsContentAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en.0.bullets" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["bullets"] = nil + } else if exists && patch["bullets"] != nil { + ResourceIbmOnboardingCatalogPlanCatalogHighlightItemAsPatch(patch["bullets"].([]interface{})[0].(map[string]interface{}), d) + } + path = "metadata.0.ui.0.strings.0.en.0.media" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["media"] = nil + } else if exists && patch["media"] != nil { + ResourceIbmOnboardingCatalogPlanCatalogProductMediaItemAsPatch(patch["media"].([]interface{})[0].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogPlanCatalogProductMediaItemAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en.0.media.0.caption_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["caption_i18n"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.media.0.thumbnail" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["thumbnail"] = nil + } +} + +func ResourceIbmOnboardingCatalogPlanCatalogHighlightItemAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.description_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description_i18n"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.title" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["title"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.title_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["title_i18n"] = nil + } +} + +func ResourceIbmOnboardingCatalogPlanCatalogProductProviderAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "object_provider.0.name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["name"] = nil + } + path = "object_provider.0.email" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["email"] = nil + } +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUIAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "overview_ui.0.en" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["en"] = nil + } else if exists && patch["en"] != nil { + ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUITranslatedContentAsPatch(patch["en"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUITranslatedContentAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "overview_ui.0.en.0.display_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["display_name"] = nil + } + path = "overview_ui.0.en.0.description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description"] = nil + } + path = "overview_ui.0.en.0.long_description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["long_description"] = nil + } +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_plan_test.go b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_plan_test.go new file mode 100644 index 0000000000..640f4ffae9 --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_plan_test.go @@ -0,0 +1,1045 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package partnercentersell_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/partnercentersell" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIbmOnboardingCatalogPlanBasic(t *testing.T) { + var conf partnercentersellv1.GlobalCatalogPlan + productID := acc.PcsOnboardingProductWithCatalogProduct + catalogProductID := acc.PcsOnboardingCatalogProductId + name := "test-plan-name-terraform" + active := "true" + disabled := "false" + kind := "plan" + nameUpdate := "test-plan-name-terraform" + activeUpdate := "false" + disabledUpdate := "false" + kindUpdate := "plan" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingCatalogPlanDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogPlanConfigBasic(productID, catalogProductID, name, active, disabled, kind), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingCatalogPlanExists("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "catalog_product_id", catalogProductID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "name", name), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "active", active), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "disabled", disabled), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "kind", kind), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogPlanConfigBasic(productID, catalogProductID, nameUpdate, activeUpdate, disabledUpdate, kindUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "catalog_product_id", catalogProductID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "name", nameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "active", activeUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "disabled", disabledUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "kind", kindUpdate), + ), + }, + }, + }) +} + +func TestAccIbmOnboardingCatalogPlanAllArgs(t *testing.T) { + var conf partnercentersellv1.GlobalCatalogPlan + productID := acc.PcsOnboardingProductWithCatalogProduct + catalogProductID := acc.PcsOnboardingCatalogProductId + env := "current" + name := "test-plan-name-terraform" + active := "true" + disabled := "false" + kind := "plan" + envUpdate := "current" + nameUpdate := "test-plan-name-terraform" + activeUpdate := "false" + disabledUpdate := "false" + kindUpdate := "plan" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingCatalogPlanDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogPlanConfig(productID, catalogProductID, env, name, active, disabled, kind), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingCatalogPlanExists("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "catalog_product_id", catalogProductID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "env", env), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "name", name), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "active", active), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "disabled", disabled), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "kind", kind), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogPlanConfig(productID, catalogProductID, envUpdate, nameUpdate, activeUpdate, disabledUpdate, kindUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "catalog_product_id", catalogProductID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "env", envUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "name", nameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "active", activeUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "disabled", disabledUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", "kind", kindUpdate), + ), + }, + resource.TestStep{ + ResourceName: "ibm_onboarding_catalog_plan.onboarding_catalog_plan_instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "env", "product_id", "catalog_product_id", + }, + }, + }, + }) +} + +func testAccCheckIbmOnboardingCatalogPlanConfigBasic(productID string, catalogProductID string, name string, active string, disabled string, kind string) string { + return fmt.Sprintf(` + resource "ibm_onboarding_catalog_plan" "onboarding_catalog_plan_instance" { + product_id = "%s" + catalog_product_id = "%s" + name = "%s" + active = %s + disabled = %s + kind = "%s" + tags = ["tag"] + object_provider { + name = "name" + email = "email@email.com" + } + metadata { + rc_compatible = false + pricing { + type = "Paid" + origin = "pricing_catalog" + } + } + } + `, productID, catalogProductID, name, active, disabled, kind) +} + +func testAccCheckIbmOnboardingCatalogPlanConfig(productID string, catalogProductID string, env string, name string, active string, disabled string, kind string) string { + return fmt.Sprintf(` + + resource "ibm_onboarding_catalog_plan" "onboarding_catalog_plan_instance" { + product_id = "%s" + catalog_product_id = "%s" + env = "%s" + name = "%s" + active = %s + disabled = %s + kind = "%s" + overview_ui { + en { + display_name = "display_name" + description = "description" + long_description = "long_description" + } + } + tags = ["tag"] + object_provider { + name = "name" + email = "email@email.com" + } + metadata { + rc_compatible = false + pricing { + type = "paid" + origin = "global_catalog" + } + } + } + `, productID, catalogProductID, env, name, active, disabled, kind) +} + +func testAccCheckIbmOnboardingCatalogPlanExists(n string, obj partnercentersellv1.GlobalCatalogPlan) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + + getCatalogPlanOptions := &partnercentersellv1.GetCatalogPlanOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getCatalogPlanOptions.SetProductID(parts[0]) + getCatalogPlanOptions.SetCatalogProductID(parts[1]) + getCatalogPlanOptions.SetCatalogPlanID(parts[2]) + + globalCatalogPlan, _, err := partnerCenterSellClient.GetCatalogPlan(getCatalogPlanOptions) + if err != nil { + return err + } + + obj = *globalCatalogPlan + return nil + } +} + +func testAccCheckIbmOnboardingCatalogPlanDestroy(s *terraform.State) error { + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_onboarding_catalog_plan" { + continue + } + + getCatalogPlanOptions := &partnercentersellv1.GetCatalogPlanOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getCatalogPlanOptions.SetProductID(parts[0]) + getCatalogPlanOptions.SetCatalogProductID(parts[1]) + getCatalogPlanOptions.SetCatalogPlanID(parts[2]) + + // Try to find the key + _, response, err := partnerCenterSellClient.GetCatalogPlan(getCatalogPlanOptions) + + if err == nil { + return fmt.Errorf("onboarding_catalog_plan still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for onboarding_catalog_plan (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} + +func TestResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUIToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + globalCatalogOverviewUiTranslatedContentModel := make(map[string]interface{}) + globalCatalogOverviewUiTranslatedContentModel["display_name"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["description"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["long_description"] = "testString" + + model := make(map[string]interface{}) + model["en"] = []map[string]interface{}{globalCatalogOverviewUiTranslatedContentModel} + + assert.Equal(t, result, model) + } + + globalCatalogOverviewUiTranslatedContentModel := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + globalCatalogOverviewUiTranslatedContentModel.DisplayName = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.Description = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.LongDescription = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogOverviewUI) + model.En = globalCatalogOverviewUiTranslatedContentModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUIToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUITranslatedContentToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["display_name"] = "testString" + model["description"] = "testString" + model["long_description"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + model.DisplayName = core.StringPtr("testString") + model.Description = core.StringPtr("testString") + model.LongDescription = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanGlobalCatalogOverviewUITranslatedContentToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanCatalogProductProviderToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.CatalogProductProvider) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanCatalogProductProviderToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanGlobalCatalogPlanMetadataToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []map[string]interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + globalCatalogMetadataUiModel := make(map[string]interface{}) + globalCatalogMetadataUiModel["strings"] = []map[string]interface{}{globalCatalogMetadataUiStringsModel} + globalCatalogMetadataUiModel["urls"] = []map[string]interface{}{globalCatalogMetadataUiUrlsModel} + globalCatalogMetadataUiModel["hidden"] = true + globalCatalogMetadataUiModel["side_by_side_index"] = float64(72.5) + + globalCatalogMetadataPricingModel := make(map[string]interface{}) + globalCatalogMetadataPricingModel["type"] = "free" + globalCatalogMetadataPricingModel["origin"] = "global_catalog" + + model := make(map[string]interface{}) + model["rc_compatible"] = true + model["ui"] = []map[string]interface{}{globalCatalogMetadataUiModel} + model["pricing"] = []map[string]interface{}{globalCatalogMetadataPricingModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + globalCatalogMetadataUiModel := new(partnercentersellv1.GlobalCatalogMetadataUI) + globalCatalogMetadataUiModel.Strings = globalCatalogMetadataUiStringsModel + globalCatalogMetadataUiModel.Urls = globalCatalogMetadataUiUrlsModel + globalCatalogMetadataUiModel.Hidden = core.BoolPtr(true) + globalCatalogMetadataUiModel.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + globalCatalogMetadataPricingModel := new(partnercentersellv1.GlobalCatalogMetadataPricing) + globalCatalogMetadataPricingModel.Type = core.StringPtr("free") + globalCatalogMetadataPricingModel.Origin = core.StringPtr("global_catalog") + + model := new(partnercentersellv1.GlobalCatalogPlanMetadata) + model.RcCompatible = core.BoolPtr(true) + model.Ui = globalCatalogMetadataUiModel + model.Pricing = globalCatalogMetadataPricingModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanGlobalCatalogPlanMetadataToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []map[string]interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + model := make(map[string]interface{}) + model["strings"] = []map[string]interface{}{globalCatalogMetadataUiStringsModel} + model["urls"] = []map[string]interface{}{globalCatalogMetadataUiUrlsModel} + model["hidden"] = true + model["side_by_side_index"] = float64(72.5) + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUI) + model.Strings = globalCatalogMetadataUiStringsModel + model.Urls = globalCatalogMetadataUiUrlsModel + model.Hidden = core.BoolPtr(true) + model.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + model := make(map[string]interface{}) + model["en"] = []map[string]interface{}{globalCatalogMetadataUiStringsContentModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + model.En = globalCatalogMetadataUiStringsContentModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsContentToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + model := make(map[string]interface{}) + model["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + model["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + model.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + model.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIStringsContentToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanCatalogHighlightItemToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["description"] = "testString" + model["description_i18n"] = map[string]interface{}{"key1": "testString"} + model["title"] = "testString" + model["title_i18n"] = map[string]interface{}{"key1": "testString"} + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.CatalogHighlightItem) + model.Description = core.StringPtr("testString") + model.DescriptionI18n = map[string]string{"key1": "testString"} + model.Title = core.StringPtr("testString") + model.TitleI18n = map[string]string{"key1": "testString"} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanCatalogHighlightItemToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanCatalogProductMediaItemToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["caption"] = "testString" + model["caption_i18n"] = map[string]interface{}{"key1": "testString"} + model["thumbnail"] = "testString" + model["type"] = "image" + model["url"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.CatalogProductMediaItem) + model.Caption = core.StringPtr("testString") + model.CaptionI18n = map[string]string{"key1": "testString"} + model.Thumbnail = core.StringPtr("testString") + model.Type = core.StringPtr("image") + model.URL = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanCatalogProductMediaItemToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIUrlsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["doc_url"] = "testString" + model["terms_url"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + model.DocURL = core.StringPtr("testString") + model.TermsURL = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataUIUrlsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataPricingToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["type"] = "free" + model["origin"] = "global_catalog" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogMetadataPricing) + model.Type = core.StringPtr("free") + model.Origin = core.StringPtr("global_catalog") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanGlobalCatalogMetadataPricingToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToCatalogProductProvider(t *testing.T) { + checkResult := func(result *partnercentersellv1.CatalogProductProvider) { + model := new(partnercentersellv1.CatalogProductProvider) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToCatalogProductProvider(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToGlobalCatalogOverviewUI(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogOverviewUI) { + globalCatalogOverviewUiTranslatedContentModel := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + globalCatalogOverviewUiTranslatedContentModel.DisplayName = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.Description = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.LongDescription = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogOverviewUI) + model.En = globalCatalogOverviewUiTranslatedContentModel + + assert.Equal(t, result, model) + } + + globalCatalogOverviewUiTranslatedContentModel := make(map[string]interface{}) + globalCatalogOverviewUiTranslatedContentModel["display_name"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["description"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["long_description"] = "testString" + + model := make(map[string]interface{}) + model["en"] = []interface{}{globalCatalogOverviewUiTranslatedContentModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogOverviewUI(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToGlobalCatalogOverviewUITranslatedContent(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) { + model := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + model.DisplayName = core.StringPtr("testString") + model.Description = core.StringPtr("testString") + model.LongDescription = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["display_name"] = "testString" + model["description"] = "testString" + model["long_description"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogOverviewUITranslatedContent(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToGlobalCatalogPlanMetadata(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogPlanMetadata) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + globalCatalogMetadataUiModel := new(partnercentersellv1.GlobalCatalogMetadataUI) + globalCatalogMetadataUiModel.Strings = globalCatalogMetadataUiStringsModel + globalCatalogMetadataUiModel.Urls = globalCatalogMetadataUiUrlsModel + globalCatalogMetadataUiModel.Hidden = core.BoolPtr(true) + globalCatalogMetadataUiModel.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + globalCatalogMetadataPricingModel := new(partnercentersellv1.GlobalCatalogMetadataPricing) + globalCatalogMetadataPricingModel.Type = core.StringPtr("free") + globalCatalogMetadataPricingModel.Origin = core.StringPtr("global_catalog") + + model := new(partnercentersellv1.GlobalCatalogPlanMetadata) + model.RcCompatible = core.BoolPtr(true) + model.Ui = globalCatalogMetadataUiModel + model.Pricing = globalCatalogMetadataPricingModel + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + globalCatalogMetadataUiModel := make(map[string]interface{}) + globalCatalogMetadataUiModel["strings"] = []interface{}{globalCatalogMetadataUiStringsModel} + globalCatalogMetadataUiModel["urls"] = []interface{}{globalCatalogMetadataUiUrlsModel} + globalCatalogMetadataUiModel["hidden"] = true + globalCatalogMetadataUiModel["side_by_side_index"] = float64(72.5) + + globalCatalogMetadataPricingModel := make(map[string]interface{}) + globalCatalogMetadataPricingModel["type"] = "free" + globalCatalogMetadataPricingModel["origin"] = "global_catalog" + + model := make(map[string]interface{}) + model["rc_compatible"] = true + model["ui"] = []interface{}{globalCatalogMetadataUiModel} + model["pricing"] = []interface{}{globalCatalogMetadataPricingModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogPlanMetadata(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUI(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUI) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUI) + model.Strings = globalCatalogMetadataUiStringsModel + model.Urls = globalCatalogMetadataUiUrlsModel + model.Hidden = core.BoolPtr(true) + model.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + model := make(map[string]interface{}) + model["strings"] = []interface{}{globalCatalogMetadataUiStringsModel} + model["urls"] = []interface{}{globalCatalogMetadataUiUrlsModel} + model["hidden"] = true + model["side_by_side_index"] = float64(72.5) + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUI(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIStrings(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUIStrings) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + model.En = globalCatalogMetadataUiStringsContentModel + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []interface{}{catalogProductMediaItemModel} + + model := make(map[string]interface{}) + model["en"] = []interface{}{globalCatalogMetadataUiStringsContentModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIStrings(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIStringsContent(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUIStringsContent) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + model.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + model.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + model := make(map[string]interface{}) + model["bullets"] = []interface{}{catalogHighlightItemModel} + model["media"] = []interface{}{catalogProductMediaItemModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIStringsContent(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToCatalogHighlightItem(t *testing.T) { + checkResult := func(result *partnercentersellv1.CatalogHighlightItem) { + model := new(partnercentersellv1.CatalogHighlightItem) + model.Description = core.StringPtr("testString") + model.DescriptionI18n = map[string]string{"key1": "testString"} + model.Title = core.StringPtr("testString") + model.TitleI18n = map[string]string{"key1": "testString"} + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["description"] = "testString" + model["description_i18n"] = map[string]interface{}{"key1": "testString"} + model["title"] = "testString" + model["title_i18n"] = map[string]interface{}{"key1": "testString"} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToCatalogHighlightItem(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToCatalogProductMediaItem(t *testing.T) { + checkResult := func(result *partnercentersellv1.CatalogProductMediaItem) { + model := new(partnercentersellv1.CatalogProductMediaItem) + model.Caption = core.StringPtr("testString") + model.CaptionI18n = map[string]string{"key1": "testString"} + model.Thumbnail = core.StringPtr("testString") + model.Type = core.StringPtr("image") + model.URL = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["caption"] = "testString" + model["caption_i18n"] = map[string]interface{}{"key1": "testString"} + model["thumbnail"] = "testString" + model["type"] = "image" + model["url"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToCatalogProductMediaItem(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIUrls(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUIUrls) { + model := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + model.DocURL = core.StringPtr("testString") + model.TermsURL = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["doc_url"] = "testString" + model["terms_url"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataUIUrls(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataPricing(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataPricing) { + model := new(partnercentersellv1.GlobalCatalogMetadataPricing) + model.Type = core.StringPtr("free") + model.Origin = core.StringPtr("global_catalog") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["type"] = "free" + model["origin"] = "global_catalog" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogPlanMapToGlobalCatalogMetadataPricing(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_product.go b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_product.go new file mode 100644 index 0000000000..04e550a0a5 --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_product.go @@ -0,0 +1,2010 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.94.1-71478489-20240820-161623 + */ + +package partnercentersell + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" +) + +func ResourceIbmOnboardingCatalogProduct() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIbmOnboardingCatalogProductCreate, + ReadContext: resourceIbmOnboardingCatalogProductRead, + UpdateContext: resourceIbmOnboardingCatalogProductUpdate, + DeleteContext: resourceIbmOnboardingCatalogProductDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "product_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_product", "product_id"), + Description: "The unique ID of the product.", + }, + "env": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_product", "env"), + Description: "The environment to fetch this object from.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_product", "name"), + Description: "The programmatic name of this product.", + }, + "active": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + Description: "Whether the service is active.", + }, + "disabled": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + Description: "Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled.", + }, + "kind": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_catalog_product", "kind"), + Description: "The kind of the global catalog object.", + }, + "overview_ui": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The object that contains the service details from the Overview page in global catalog.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "en": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Translated details about the service, for example, display name, short description, and long description.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "display_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The display name of the product.", + }, + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The short description of the product that is displayed in your catalog entry.", + }, + "long_description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The detailed description of your product that is displayed at the beginning of your product page in the catalog. Markdown markup language is supported.", + }, + }, + }, + }, + }, + }, + }, + "tags": &schema.Schema{ + Type: schema.TypeList, + Required: true, + Description: "A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "images": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Images from the global catalog entry that help illustrate the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "image": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for your product logo.", + }, + }, + }, + }, + "object_provider": &schema.Schema{ + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Required: true, + Description: "The provider or owner of the product.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name of the provider.", + }, + "email": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The email address of the provider.", + }, + }, + }, + }, + "metadata": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The global catalog service metadata object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rc_compatible": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the object is compatible with the resource controller service.", + }, + "ui": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The UI metadata of this service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "strings": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The data strings.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "en": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Translated content of additional information about the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "bullets": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of features that highlights your product's attributes and benefits for users.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The description about the features of the product.", + }, + "description_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The description about the features of the product in translation.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "title": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The descriptive title for the feature.", + }, + "title_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The descriptive title for the feature in translation.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "media": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of supporting media for this product.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "caption": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Provide a descriptive caption that indicates what the media illustrates. This caption is displayed in the catalog.", + }, + "caption_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The brief explanation for your images and videos in translation.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "thumbnail": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The reduced-size version of your images and videos.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The type of the media.", + }, + "url": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The URL that links to the media that shows off the product.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "urls": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The UI based URLs.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "doc_url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for your product documentation.", + }, + "terms_url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for your product's end user license agreement.", + }, + }, + }, + }, + "hidden": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the object is hidden from the consumption catalog.", + }, + "side_by_side_index": &schema.Schema{ + Type: schema.TypeFloat, + Optional: true, + Description: "When the objects are listed side-by-side, this value controls the ordering.", + }, + }, + }, + }, + "service": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The global catalog metadata of the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rc_provisionable": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the service is provisionable by the resource controller service.", + }, + "iam_compatible": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the service is compatible with the IAM service.", + }, + }, + }, + }, + "other": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The additional metadata of the service in global catalog.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "pc": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The metadata of the service owned and managed by Partner Center - Sell.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "support": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The support metadata of the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The support site URL where the support for your service is available.", + }, + "status_url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL where the status of your service is available.", + }, + "locations": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The countries in which your support is available. Provide a list of country codes.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "languages": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The languages in which support is available.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "process": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The description of your support process.", + }, + "process_i18n": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "The description of your support process.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "support_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The type of support provided.", + }, + "support_escalation": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The details of the support escalation process.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "contact": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The support contact information of the escalation team.", + }, + "escalation_wait_time": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The time interval of providing support in units and values.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": &schema.Schema{ + Type: schema.TypeFloat, + Optional: true, + Description: "The number of time units.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The unit of the time.", + }, + }, + }, + }, + "response_wait_time": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The time interval of providing support in units and values.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": &schema.Schema{ + Type: schema.TypeFloat, + Optional: true, + Description: "The number of time units.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The unit of the time.", + }, + }, + }, + }, + }, + }, + }, + "support_details": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The support options for the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The type of support for this support channel.", + }, + "contact": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The contact information for this support channel.", + }, + "response_wait_time": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The time interval of providing support in units and values.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": &schema.Schema{ + Type: schema.TypeFloat, + Optional: true, + Description: "The number of time units.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The unit of the time.", + }, + }, + }, + }, + "availability": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The time period during which support is available for the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "times": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The support hours available for the service.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "day": &schema.Schema{ + Type: schema.TypeFloat, + Optional: true, + Description: "The number of days in a week when support is available for the service.", + }, + "start_time": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The time in the day when support starts for the service.", + }, + "end_time": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The time in the day when support ends for the service.", + }, + }, + }, + }, + "timezone": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The timezones in which support is available. Only relevant if `always_available` is set to false.", + }, + "always_available": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the support for the service is always available.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "url": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The global catalog URL of your product.", + }, + "catalog_product_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of a global catalog object.", + }, + }, + } +} + +func ResourceIbmOnboardingCatalogProductValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "product_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9]{32}:o:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, + MinValueLength: 71, + MaxValueLength: 71, + }, + validate.ValidateSchema{ + Identifier: "env", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-z]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexp, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-z0-9\-.]+$`, + }, + validate.ValidateSchema{ + Identifier: "kind", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: "platform_service, service", + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_onboarding_catalog_product", Schema: validateSchema} + return &resourceValidator +} + +func resourceIbmOnboardingCatalogProductCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createCatalogProductOptions := &partnercentersellv1.CreateCatalogProductOptions{} + + createCatalogProductOptions.SetProductID(d.Get("product_id").(string)) + createCatalogProductOptions.SetName(d.Get("name").(string)) + createCatalogProductOptions.SetActive(d.Get("active").(bool)) + createCatalogProductOptions.SetDisabled(d.Get("disabled").(bool)) + createCatalogProductOptions.SetKind(d.Get("kind").(string)) + var tags []string + for _, v := range d.Get("tags").([]interface{}) { + tagsItem := v.(string) + tags = append(tags, tagsItem) + } + createCatalogProductOptions.SetTags(tags) + objectProviderModel, err := ResourceIbmOnboardingCatalogProductMapToCatalogProductProvider(d.Get("object_provider.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "create", "parse-object_provider").GetDiag() + } + createCatalogProductOptions.SetObjectProvider(objectProviderModel) + if _, ok := d.GetOk("overview_ui"); ok { + overviewUiModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogOverviewUI(d.Get("overview_ui.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "create", "parse-overview_ui").GetDiag() + } + createCatalogProductOptions.SetOverviewUi(overviewUiModel) + } + if _, ok := d.GetOk("images"); ok { + imagesModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductImages(d.Get("images.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "create", "parse-images").GetDiag() + } + createCatalogProductOptions.SetImages(imagesModel) + } + if _, ok := d.GetOk("metadata"); ok { + metadataModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadata(d.Get("metadata.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "create", "parse-metadata").GetDiag() + } + createCatalogProductOptions.SetMetadata(metadataModel) + } + if _, ok := d.GetOk("env"); ok { + createCatalogProductOptions.SetEnv(d.Get("env").(string)) + } + + globalCatalogProduct, _, err := partnerCenterSellClient.CreateCatalogProductWithContext(context, createCatalogProductOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateCatalogProductWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_product", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s", *createCatalogProductOptions.ProductID, *globalCatalogProduct.ID)) + + return resourceIbmOnboardingCatalogProductRead(context, d, meta) +} + +func resourceIbmOnboardingCatalogProductRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getCatalogProductOptions := &partnercentersellv1.GetCatalogProductOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "sep-id-parts").GetDiag() + } + + getCatalogProductOptions.SetProductID(parts[0]) + getCatalogProductOptions.SetCatalogProductID(parts[1]) + if _, ok := d.GetOk("env"); ok { + getCatalogProductOptions.SetEnv(d.Get("env").(string)) + } + + globalCatalogProduct, response, err := partnerCenterSellClient.GetCatalogProductWithContext(context, getCatalogProductOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetCatalogProductWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_product", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if err = d.Set("name", globalCatalogProduct.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-name").GetDiag() + } + if err = d.Set("active", globalCatalogProduct.Active); err != nil { + err = fmt.Errorf("Error setting active: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-active").GetDiag() + } + if err = d.Set("disabled", globalCatalogProduct.Disabled); err != nil { + err = fmt.Errorf("Error setting disabled: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-disabled").GetDiag() + } + if err = d.Set("kind", globalCatalogProduct.Kind); err != nil { + err = fmt.Errorf("Error setting kind: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-kind").GetDiag() + } + if !core.IsNil(globalCatalogProduct.OverviewUi) { + overviewUiMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUIToMap(globalCatalogProduct.OverviewUi) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "overview_ui-to-map").GetDiag() + } + if err = d.Set("overview_ui", []map[string]interface{}{overviewUiMap}); err != nil { + err = fmt.Errorf("Error setting overview_ui: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-overview_ui").GetDiag() + } + } + if err = d.Set("tags", globalCatalogProduct.Tags); err != nil { + err = fmt.Errorf("Error setting tags: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-tags").GetDiag() + } + if !core.IsNil(globalCatalogProduct.Images) { + imagesMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogProductImagesToMap(globalCatalogProduct.Images) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "images-to-map").GetDiag() + } + if err = d.Set("images", []map[string]interface{}{imagesMap}); err != nil { + err = fmt.Errorf("Error setting images: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-images").GetDiag() + } + } + objectProviderMap, err := ResourceIbmOnboardingCatalogProductCatalogProductProviderToMap(globalCatalogProduct.ObjectProvider) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "object_provider-to-map").GetDiag() + } + if err = d.Set("object_provider", []map[string]interface{}{objectProviderMap}); err != nil { + err = fmt.Errorf("Error setting object_provider: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-object_provider").GetDiag() + } + if !core.IsNil(globalCatalogProduct.Metadata) { + metadataMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataToMap(globalCatalogProduct.Metadata) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "metadata-to-map").GetDiag() + } + if err = d.Set("metadata", []map[string]interface{}{metadataMap}); err != nil { + err = fmt.Errorf("Error setting metadata: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-metadata").GetDiag() + } + } + if !core.IsNil(globalCatalogProduct.URL) { + if err = d.Set("url", globalCatalogProduct.URL); err != nil { + err = fmt.Errorf("Error setting url: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-url").GetDiag() + } + } + if !core.IsNil(globalCatalogProduct.ID) { + if err = d.Set("catalog_product_id", globalCatalogProduct.ID); err != nil { + err = fmt.Errorf("Error setting catalog_product_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "read", "set-catalog_product_id").GetDiag() + } + } + + return nil +} + +func resourceIbmOnboardingCatalogProductUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateCatalogProductOptions := &partnercentersellv1.UpdateCatalogProductOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "update", "sep-id-parts").GetDiag() + } + + updateCatalogProductOptions.SetProductID(parts[0]) + updateCatalogProductOptions.SetCatalogProductID(parts[1]) + if _, ok := d.GetOk("env"); ok { + updateCatalogProductOptions.SetEnv(d.Get("env").(string)) + } + + hasChange := false + + patchVals := &partnercentersellv1.GlobalCatalogProductPatch{} + if d.HasChange("product_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "product_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_onboarding_catalog_product", "update", "product_id-forces-new").GetDiag() + } + if d.HasChange("active") { + newActive := d.Get("active").(bool) + patchVals.Active = &newActive + hasChange = true + } + if d.HasChange("disabled") { + newDisabled := d.Get("disabled").(bool) + patchVals.Disabled = &newDisabled + hasChange = true + } + if d.HasChange("overview_ui") { + overviewUi, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogOverviewUI(d.Get("overview_ui.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "update", "parse-overview_ui").GetDiag() + } + patchVals.OverviewUi = overviewUi + hasChange = true + } + if d.HasChange("tags") { + var tags []string + for _, v := range d.Get("tags").([]interface{}) { + tagsItem := v.(string) + tags = append(tags, tagsItem) + } + patchVals.Tags = tags + hasChange = true + } + if d.HasChange("images") { + images, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductImages(d.Get("images.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "update", "parse-images").GetDiag() + } + patchVals.Images = images + hasChange = true + } + if d.HasChange("object_provider") { + objectProvider, err := ResourceIbmOnboardingCatalogProductMapToCatalogProductProvider(d.Get("object_provider.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "update", "parse-object_provider").GetDiag() + } + patchVals.ObjectProvider = objectProvider + hasChange = true + } + if d.HasChange("metadata") { + metadata, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadata(d.Get("metadata.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "update", "parse-metadata").GetDiag() + } + patchVals.Metadata = metadata + hasChange = true + } + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateCatalogProductOptions.GlobalCatalogProductPatch = ResourceIbmOnboardingCatalogProductGlobalCatalogProductPatchAsPatch(patchVals, d) + + _, _, err = partnerCenterSellClient.UpdateCatalogProductWithContext(context, updateCatalogProductOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateCatalogProductWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_product", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIbmOnboardingCatalogProductRead(context, d, meta) +} + +func resourceIbmOnboardingCatalogProductDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteCatalogProductOptions := &partnercentersellv1.DeleteCatalogProductOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_catalog_product", "delete", "sep-id-parts").GetDiag() + } + + deleteCatalogProductOptions.SetProductID(parts[0]) + deleteCatalogProductOptions.SetCatalogProductID(parts[1]) + if _, ok := d.GetOk("env"); ok { + deleteCatalogProductOptions.SetEnv(d.Get("env").(string)) + } + + _, err = partnerCenterSellClient.DeleteCatalogProductWithContext(context, deleteCatalogProductOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteCatalogProductWithContext failed: %s", err.Error()), "ibm_onboarding_catalog_product", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIbmOnboardingCatalogProductMapToCatalogProductProvider(modelMap map[string]interface{}) (*partnercentersellv1.CatalogProductProvider, error) { + model := &partnercentersellv1.CatalogProductProvider{} + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["email"] != nil && modelMap["email"].(string) != "" { + model.Email = core.StringPtr(modelMap["email"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogOverviewUI(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogOverviewUI, error) { + model := &partnercentersellv1.GlobalCatalogOverviewUI{} + if modelMap["en"] != nil && len(modelMap["en"].([]interface{})) > 0 && modelMap["en"].([]interface{})[0] != nil { + EnModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogOverviewUITranslatedContent(modelMap["en"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.En = EnModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogOverviewUITranslatedContent(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogOverviewUITranslatedContent, error) { + model := &partnercentersellv1.GlobalCatalogOverviewUITranslatedContent{} + if modelMap["display_name"] != nil && modelMap["display_name"].(string) != "" { + model.DisplayName = core.StringPtr(modelMap["display_name"].(string)) + } + if modelMap["description"] != nil && modelMap["description"].(string) != "" { + model.Description = core.StringPtr(modelMap["description"].(string)) + } + if modelMap["long_description"] != nil && modelMap["long_description"].(string) != "" { + model.LongDescription = core.StringPtr(modelMap["long_description"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductImages(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogProductImages, error) { + model := &partnercentersellv1.GlobalCatalogProductImages{} + if modelMap["image"] != nil && modelMap["image"].(string) != "" { + model.Image = core.StringPtr(modelMap["image"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadata(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogProductMetadata, error) { + model := &partnercentersellv1.GlobalCatalogProductMetadata{} + if modelMap["rc_compatible"] != nil { + model.RcCompatible = core.BoolPtr(modelMap["rc_compatible"].(bool)) + } + if modelMap["ui"] != nil && len(modelMap["ui"].([]interface{})) > 0 && modelMap["ui"].([]interface{})[0] != nil { + UiModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUI(modelMap["ui"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Ui = UiModel + } + if modelMap["service"] != nil && len(modelMap["service"].([]interface{})) > 0 && modelMap["service"].([]interface{})[0] != nil { + ServiceModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataService(modelMap["service"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Service = ServiceModel + } + if modelMap["other"] != nil && len(modelMap["other"].([]interface{})) > 0 && modelMap["other"].([]interface{})[0] != nil { + OtherModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOther(modelMap["other"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Other = OtherModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUI(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUI, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUI{} + if modelMap["strings"] != nil && len(modelMap["strings"].([]interface{})) > 0 && modelMap["strings"].([]interface{})[0] != nil { + StringsModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIStrings(modelMap["strings"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Strings = StringsModel + } + if modelMap["urls"] != nil && len(modelMap["urls"].([]interface{})) > 0 && modelMap["urls"].([]interface{})[0] != nil { + UrlsModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIUrls(modelMap["urls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Urls = UrlsModel + } + if modelMap["hidden"] != nil { + model.Hidden = core.BoolPtr(modelMap["hidden"].(bool)) + } + if modelMap["side_by_side_index"] != nil { + model.SideBySideIndex = core.Float64Ptr(modelMap["side_by_side_index"].(float64)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIStrings(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUIStrings, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUIStrings{} + if modelMap["en"] != nil && len(modelMap["en"].([]interface{})) > 0 && modelMap["en"].([]interface{})[0] != nil { + EnModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIStringsContent(modelMap["en"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.En = EnModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIStringsContent(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUIStringsContent, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUIStringsContent{} + if modelMap["bullets"] != nil { + bullets := []partnercentersellv1.CatalogHighlightItem{} + for _, bulletsItem := range modelMap["bullets"].([]interface{}) { + bulletsItemModel, err := ResourceIbmOnboardingCatalogProductMapToCatalogHighlightItem(bulletsItem.(map[string]interface{})) + if err != nil { + return model, err + } + bullets = append(bullets, *bulletsItemModel) + } + model.Bullets = bullets + } + if modelMap["media"] != nil { + media := []partnercentersellv1.CatalogProductMediaItem{} + for _, mediaItem := range modelMap["media"].([]interface{}) { + mediaItemModel, err := ResourceIbmOnboardingCatalogProductMapToCatalogProductMediaItem(mediaItem.(map[string]interface{})) + if err != nil { + return model, err + } + media = append(media, *mediaItemModel) + } + model.Media = media + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToCatalogHighlightItem(modelMap map[string]interface{}) (*partnercentersellv1.CatalogHighlightItem, error) { + model := &partnercentersellv1.CatalogHighlightItem{} + if modelMap["description"] != nil && modelMap["description"].(string) != "" { + model.Description = core.StringPtr(modelMap["description"].(string)) + } + if modelMap["description_i18n"] != nil { + model.DescriptionI18n = make(map[string]string) + for key, value := range modelMap["description_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.DescriptionI18n[key] = str + } + } + } + if modelMap["title"] != nil && modelMap["title"].(string) != "" { + model.Title = core.StringPtr(modelMap["title"].(string)) + } + if modelMap["title_i18n"] != nil { + model.TitleI18n = make(map[string]string) + for key, value := range modelMap["title_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.TitleI18n[key] = str + } + } + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToCatalogProductMediaItem(modelMap map[string]interface{}) (*partnercentersellv1.CatalogProductMediaItem, error) { + model := &partnercentersellv1.CatalogProductMediaItem{} + model.Caption = core.StringPtr(modelMap["caption"].(string)) + if modelMap["caption_i18n"] != nil { + model.CaptionI18n = make(map[string]string) + for key, value := range modelMap["caption_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.CaptionI18n[key] = str + } + } + } + if modelMap["thumbnail"] != nil && modelMap["thumbnail"].(string) != "" { + model.Thumbnail = core.StringPtr(modelMap["thumbnail"].(string)) + } + model.Type = core.StringPtr(modelMap["type"].(string)) + model.URL = core.StringPtr(modelMap["url"].(string)) + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIUrls(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataUIUrls, error) { + model := &partnercentersellv1.GlobalCatalogMetadataUIUrls{} + if modelMap["doc_url"] != nil && modelMap["doc_url"].(string) != "" { + model.DocURL = core.StringPtr(modelMap["doc_url"].(string)) + } + if modelMap["terms_url"] != nil && modelMap["terms_url"].(string) != "" { + model.TermsURL = core.StringPtr(modelMap["terms_url"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataService(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogMetadataService, error) { + model := &partnercentersellv1.GlobalCatalogMetadataService{} + if modelMap["rc_provisionable"] != nil { + model.RcProvisionable = core.BoolPtr(modelMap["rc_provisionable"].(bool)) + } + if modelMap["iam_compatible"] != nil { + model.IamCompatible = core.BoolPtr(modelMap["iam_compatible"].(bool)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOther(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogProductMetadataOther, error) { + model := &partnercentersellv1.GlobalCatalogProductMetadataOther{} + if modelMap["pc"] != nil && len(modelMap["pc"].([]interface{})) > 0 && modelMap["pc"].([]interface{})[0] != nil { + PCModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOtherPC(modelMap["pc"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.PC = PCModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOtherPC(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogProductMetadataOtherPC, error) { + model := &partnercentersellv1.GlobalCatalogProductMetadataOtherPC{} + if modelMap["support"] != nil && len(modelMap["support"].([]interface{})) > 0 && modelMap["support"].([]interface{})[0] != nil { + SupportModel, err := ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOtherPCSupport(modelMap["support"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Support = SupportModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOtherPCSupport(modelMap map[string]interface{}) (*partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport, error) { + model := &partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport{} + if modelMap["url"] != nil && modelMap["url"].(string) != "" { + model.URL = core.StringPtr(modelMap["url"].(string)) + } + if modelMap["status_url"] != nil && modelMap["status_url"].(string) != "" { + model.StatusURL = core.StringPtr(modelMap["status_url"].(string)) + } + if modelMap["locations"] != nil { + locations := []string{} + for _, locationsItem := range modelMap["locations"].([]interface{}) { + locations = append(locations, locationsItem.(string)) + } + model.Locations = locations + } + if modelMap["languages"] != nil { + languages := []string{} + for _, languagesItem := range modelMap["languages"].([]interface{}) { + languages = append(languages, languagesItem.(string)) + } + model.Languages = languages + } + if modelMap["process"] != nil && modelMap["process"].(string) != "" { + model.Process = core.StringPtr(modelMap["process"].(string)) + } + if modelMap["process_i18n"] != nil { + model.ProcessI18n = make(map[string]string) + for key, value := range modelMap["process_i18n"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.ProcessI18n[key] = str + } + } + } + if modelMap["support_type"] != nil && modelMap["support_type"].(string) != "" { + model.SupportType = core.StringPtr(modelMap["support_type"].(string)) + } + if modelMap["support_escalation"] != nil && len(modelMap["support_escalation"].([]interface{})) > 0 && modelMap["support_escalation"].([]interface{})[0] != nil { + SupportEscalationModel, err := ResourceIbmOnboardingCatalogProductMapToSupportEscalation(modelMap["support_escalation"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.SupportEscalation = SupportEscalationModel + } + if modelMap["support_details"] != nil { + supportDetails := []partnercentersellv1.SupportDetailsItem{} + for _, supportDetailsItem := range modelMap["support_details"].([]interface{}) { + supportDetailsItemModel, err := ResourceIbmOnboardingCatalogProductMapToSupportDetailsItem(supportDetailsItem.(map[string]interface{})) + if err != nil { + return model, err + } + supportDetails = append(supportDetails, *supportDetailsItemModel) + } + model.SupportDetails = supportDetails + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToSupportEscalation(modelMap map[string]interface{}) (*partnercentersellv1.SupportEscalation, error) { + model := &partnercentersellv1.SupportEscalation{} + if modelMap["contact"] != nil && modelMap["contact"].(string) != "" { + model.Contact = core.StringPtr(modelMap["contact"].(string)) + } + if modelMap["escalation_wait_time"] != nil && len(modelMap["escalation_wait_time"].([]interface{})) > 0 && modelMap["escalation_wait_time"].([]interface{})[0] != nil { + EscalationWaitTimeModel, err := ResourceIbmOnboardingCatalogProductMapToSupportTimeInterval(modelMap["escalation_wait_time"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.EscalationWaitTime = EscalationWaitTimeModel + } + if modelMap["response_wait_time"] != nil && len(modelMap["response_wait_time"].([]interface{})) > 0 && modelMap["response_wait_time"].([]interface{})[0] != nil { + ResponseWaitTimeModel, err := ResourceIbmOnboardingCatalogProductMapToSupportTimeInterval(modelMap["response_wait_time"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ResponseWaitTime = ResponseWaitTimeModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToSupportTimeInterval(modelMap map[string]interface{}) (*partnercentersellv1.SupportTimeInterval, error) { + model := &partnercentersellv1.SupportTimeInterval{} + if modelMap["value"] != nil { + model.Value = core.Float64Ptr(modelMap["value"].(float64)) + } + if modelMap["type"] != nil && modelMap["type"].(string) != "" { + model.Type = core.StringPtr(modelMap["type"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToSupportDetailsItem(modelMap map[string]interface{}) (*partnercentersellv1.SupportDetailsItem, error) { + model := &partnercentersellv1.SupportDetailsItem{} + if modelMap["type"] != nil && modelMap["type"].(string) != "" { + model.Type = core.StringPtr(modelMap["type"].(string)) + } + if modelMap["contact"] != nil && modelMap["contact"].(string) != "" { + model.Contact = core.StringPtr(modelMap["contact"].(string)) + } + if modelMap["response_wait_time"] != nil && len(modelMap["response_wait_time"].([]interface{})) > 0 { + ResponseWaitTimeModel, err := ResourceIbmOnboardingCatalogProductMapToSupportTimeInterval(modelMap["response_wait_time"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ResponseWaitTime = ResponseWaitTimeModel + } + if modelMap["availability"] != nil && len(modelMap["availability"].([]interface{})) > 0 && modelMap["availability"].([]interface{})[0] != nil { + AvailabilityModel, err := ResourceIbmOnboardingCatalogProductMapToSupportDetailsItemAvailability(modelMap["availability"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Availability = AvailabilityModel + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToSupportDetailsItemAvailability(modelMap map[string]interface{}) (*partnercentersellv1.SupportDetailsItemAvailability, error) { + model := &partnercentersellv1.SupportDetailsItemAvailability{} + if modelMap["times"] != nil { + times := []partnercentersellv1.SupportDetailsItemAvailabilityTime{} + for _, timesItem := range modelMap["times"].([]interface{}) { + timesItemModel, err := ResourceIbmOnboardingCatalogProductMapToSupportDetailsItemAvailabilityTime(timesItem.(map[string]interface{})) + if err != nil { + return model, err + } + times = append(times, *timesItemModel) + } + model.Times = times + } + if modelMap["timezone"] != nil && modelMap["timezone"].(string) != "" { + model.Timezone = core.StringPtr(modelMap["timezone"].(string)) + } + if modelMap["always_available"] != nil { + model.AlwaysAvailable = core.BoolPtr(modelMap["always_available"].(bool)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductMapToSupportDetailsItemAvailabilityTime(modelMap map[string]interface{}) (*partnercentersellv1.SupportDetailsItemAvailabilityTime, error) { + model := &partnercentersellv1.SupportDetailsItemAvailabilityTime{} + if modelMap["day"] != nil { + model.Day = core.Float64Ptr(modelMap["day"].(float64)) + } + if modelMap["start_time"] != nil && modelMap["start_time"].(string) != "" { + model.StartTime = core.StringPtr(modelMap["start_time"].(string)) + } + if modelMap["end_time"] != nil && modelMap["end_time"].(string) != "" { + model.EndTime = core.StringPtr(modelMap["end_time"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUIToMap(model *partnercentersellv1.GlobalCatalogOverviewUI) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.En != nil { + enMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUITranslatedContentToMap(model.En) + if err != nil { + return modelMap, err + } + modelMap["en"] = []map[string]interface{}{enMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUITranslatedContentToMap(model *partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.DisplayName != nil { + modelMap["display_name"] = *model.DisplayName + } + if model.Description != nil { + modelMap["description"] = *model.Description + } + if model.LongDescription != nil { + modelMap["long_description"] = *model.LongDescription + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductImagesToMap(model *partnercentersellv1.GlobalCatalogProductImages) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Image != nil { + modelMap["image"] = *model.Image + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductCatalogProductProviderToMap(model *partnercentersellv1.CatalogProductProvider) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.Email != nil { + modelMap["email"] = *model.Email + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataToMap(model *partnercentersellv1.GlobalCatalogProductMetadata) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.RcCompatible != nil { + modelMap["rc_compatible"] = *model.RcCompatible + } + if model.Ui != nil { + uiMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIToMap(model.Ui) + if err != nil { + return modelMap, err + } + modelMap["ui"] = []map[string]interface{}{uiMap} + } + if model.Service != nil { + serviceMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataServiceToMap(model.Service) + if err != nil { + return modelMap, err + } + modelMap["service"] = []map[string]interface{}{serviceMap} + } + if model.Other != nil { + otherMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherToMap(model.Other) + if err != nil { + return modelMap, err + } + modelMap["other"] = []map[string]interface{}{otherMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIToMap(model *partnercentersellv1.GlobalCatalogMetadataUI) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Strings != nil { + stringsMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsToMap(model.Strings) + if err != nil { + return modelMap, err + } + modelMap["strings"] = []map[string]interface{}{stringsMap} + } + if model.Urls != nil { + urlsMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIUrlsToMap(model.Urls) + if err != nil { + return modelMap, err + } + modelMap["urls"] = []map[string]interface{}{urlsMap} + } + if model.Hidden != nil { + modelMap["hidden"] = *model.Hidden + } + if model.SideBySideIndex != nil { + modelMap["side_by_side_index"] = *model.SideBySideIndex + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsToMap(model *partnercentersellv1.GlobalCatalogMetadataUIStrings) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.En != nil { + enMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsContentToMap(model.En) + if err != nil { + return modelMap, err + } + modelMap["en"] = []map[string]interface{}{enMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsContentToMap(model *partnercentersellv1.GlobalCatalogMetadataUIStringsContent) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Bullets != nil { + bullets := []map[string]interface{}{} + for _, bulletsItem := range model.Bullets { + bulletsItemMap, err := ResourceIbmOnboardingCatalogProductCatalogHighlightItemToMap(&bulletsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + bullets = append(bullets, bulletsItemMap) + } + modelMap["bullets"] = bullets + } + if model.Media != nil { + media := []map[string]interface{}{} + for _, mediaItem := range model.Media { + mediaItemMap, err := ResourceIbmOnboardingCatalogProductCatalogProductMediaItemToMap(&mediaItem) // #nosec G601 + if err != nil { + return modelMap, err + } + media = append(media, mediaItemMap) + } + modelMap["media"] = media + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductCatalogHighlightItemToMap(model *partnercentersellv1.CatalogHighlightItem) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Description != nil { + modelMap["description"] = *model.Description + } + if model.DescriptionI18n != nil { + descriptionI18n := make(map[string]interface{}) + for k, v := range model.DescriptionI18n { + descriptionI18n[k] = flex.Stringify(v) + } + modelMap["description_i18n"] = descriptionI18n + } + if model.Title != nil { + modelMap["title"] = *model.Title + } + if model.TitleI18n != nil { + titleI18n := make(map[string]interface{}) + for k, v := range model.TitleI18n { + titleI18n[k] = flex.Stringify(v) + } + modelMap["title_i18n"] = titleI18n + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductCatalogProductMediaItemToMap(model *partnercentersellv1.CatalogProductMediaItem) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["caption"] = *model.Caption + if model.CaptionI18n != nil { + captionI18n := make(map[string]interface{}) + for k, v := range model.CaptionI18n { + captionI18n[k] = flex.Stringify(v) + } + modelMap["caption_i18n"] = captionI18n + } + if model.Thumbnail != nil { + modelMap["thumbnail"] = *model.Thumbnail + } + modelMap["type"] = *model.Type + modelMap["url"] = *model.URL + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIUrlsToMap(model *partnercentersellv1.GlobalCatalogMetadataUIUrls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.DocURL != nil { + modelMap["doc_url"] = *model.DocURL + } + if model.TermsURL != nil { + modelMap["terms_url"] = *model.TermsURL + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataServiceToMap(model *partnercentersellv1.GlobalCatalogMetadataService) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.RcProvisionable != nil { + modelMap["rc_provisionable"] = *model.RcProvisionable + } + if model.IamCompatible != nil { + modelMap["iam_compatible"] = *model.IamCompatible + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherToMap(model *partnercentersellv1.GlobalCatalogProductMetadataOther) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.PC != nil { + pcMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCToMap(model.PC) + if err != nil { + return modelMap, err + } + modelMap["pc"] = []map[string]interface{}{pcMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCToMap(model *partnercentersellv1.GlobalCatalogProductMetadataOtherPC) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Support != nil { + supportMap, err := ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCSupportToMap(model.Support) + if err != nil { + return modelMap, err + } + modelMap["support"] = []map[string]interface{}{supportMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCSupportToMap(model *partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.URL != nil { + modelMap["url"] = *model.URL + } + if model.StatusURL != nil { + modelMap["status_url"] = *model.StatusURL + } + if model.Locations != nil { + modelMap["locations"] = model.Locations + } + if model.Languages != nil { + modelMap["languages"] = model.Languages + } + if model.Process != nil { + modelMap["process"] = *model.Process + } + if model.ProcessI18n != nil { + processI18n := make(map[string]interface{}) + for k, v := range model.ProcessI18n { + processI18n[k] = flex.Stringify(v) + } + modelMap["process_i18n"] = processI18n + } + if model.SupportType != nil { + modelMap["support_type"] = *model.SupportType + } + if model.SupportEscalation != nil { + supportEscalationMap, err := ResourceIbmOnboardingCatalogProductSupportEscalationToMap(model.SupportEscalation) + if err != nil { + return modelMap, err + } + modelMap["support_escalation"] = []map[string]interface{}{supportEscalationMap} + } + if model.SupportDetails != nil { + supportDetails := []map[string]interface{}{} + for _, supportDetailsItem := range model.SupportDetails { + supportDetailsItemMap, err := ResourceIbmOnboardingCatalogProductSupportDetailsItemToMap(&supportDetailsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + supportDetails = append(supportDetails, supportDetailsItemMap) + } + modelMap["support_details"] = supportDetails + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductSupportEscalationToMap(model *partnercentersellv1.SupportEscalation) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Contact != nil { + modelMap["contact"] = *model.Contact + } + if model.EscalationWaitTime != nil { + escalationWaitTimeMap, err := ResourceIbmOnboardingCatalogProductSupportTimeIntervalToMap(model.EscalationWaitTime) + if err != nil { + return modelMap, err + } + modelMap["escalation_wait_time"] = []map[string]interface{}{escalationWaitTimeMap} + } + if model.ResponseWaitTime != nil { + responseWaitTimeMap, err := ResourceIbmOnboardingCatalogProductSupportTimeIntervalToMap(model.ResponseWaitTime) + if err != nil { + return modelMap, err + } + modelMap["response_wait_time"] = []map[string]interface{}{responseWaitTimeMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductSupportTimeIntervalToMap(model *partnercentersellv1.SupportTimeInterval) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Value != nil { + modelMap["value"] = *model.Value + } + if model.Type != nil { + modelMap["type"] = *model.Type + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductSupportDetailsItemToMap(model *partnercentersellv1.SupportDetailsItem) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Contact != nil { + modelMap["contact"] = *model.Contact + } + if model.ResponseWaitTime != nil { + responseWaitTimeMap, err := ResourceIbmOnboardingCatalogProductSupportTimeIntervalToMap(model.ResponseWaitTime) + if err != nil { + return modelMap, err + } + modelMap["response_wait_time"] = []map[string]interface{}{responseWaitTimeMap} + } + if model.Availability != nil { + availabilityMap, err := ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityToMap(model.Availability) + if err != nil { + return modelMap, err + } + modelMap["availability"] = []map[string]interface{}{availabilityMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityToMap(model *partnercentersellv1.SupportDetailsItemAvailability) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Times != nil { + times := []map[string]interface{}{} + for _, timesItem := range model.Times { + timesItemMap, err := ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityTimeToMap(×Item) // #nosec G601 + if err != nil { + return modelMap, err + } + times = append(times, timesItemMap) + } + modelMap["times"] = times + } + if model.Timezone != nil { + modelMap["timezone"] = *model.Timezone + } + if model.AlwaysAvailable != nil { + modelMap["always_available"] = *model.AlwaysAvailable + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityTimeToMap(model *partnercentersellv1.SupportDetailsItemAvailabilityTime) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Day != nil { + modelMap["day"] = *model.Day + } + if model.StartTime != nil { + modelMap["start_time"] = *model.StartTime + } + if model.EndTime != nil { + modelMap["end_time"] = *model.EndTime + } + return modelMap, nil +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductPatchAsPatch(patchVals *partnercentersellv1.GlobalCatalogProductPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "active" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["active"] = nil + } + path = "disabled" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["disabled"] = nil + } + path = "overview_ui" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["overview_ui"] = nil + } else if exists && patch["overview_ui"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUIAsPatch(patch["overview_ui"].(map[string]interface{}), d) + } + path = "tags" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["tags"] = nil + } + path = "images" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["images"] = nil + } else if exists && patch["images"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogProductImagesAsPatch(patch["images"].(map[string]interface{}), d) + } + path = "object_provider" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["object_provider"] = nil + } else if exists && patch["object_provider"] != nil { + ResourceIbmOnboardingCatalogProductCatalogProductProviderAsPatch(patch["object_provider"].(map[string]interface{}), d) + } + path = "metadata" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["metadata"] = nil + } else if exists && patch["metadata"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataAsPatch(patch["metadata"].(map[string]interface{}), d) + } + + return patch +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.rc_compatible" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["rc_compatible"] = nil + } + path = "metadata.0.ui" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["ui"] = nil + } else if exists && patch["ui"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIAsPatch(patch["ui"].(map[string]interface{}), d) + } + path = "metadata.0.service" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["service"] = nil + } else if exists && patch["service"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataServiceAsPatch(patch["service"].(map[string]interface{}), d) + } + path = "metadata.0.other" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["other"] = nil + } else if exists && patch["other"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherAsPatch(patch["other"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.other.0.pc" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["pc"] = nil + } else if exists && patch["pc"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCAsPatch(patch["pc"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.other.0.pc.0.support" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["support"] = nil + } else if exists && patch["support"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCSupportAsPatch(patch["support"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCSupportAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.other.0.pc.0.support.0.url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["url"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.status_url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["status_url"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.locations" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["locations"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.languages" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["languages"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.process" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["process"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.process_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["process_i18n"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.support_type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["support_type"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.support_escalation" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["support_escalation"] = nil + } else if exists && patch["support_escalation"] != nil { + ResourceIbmOnboardingCatalogProductSupportEscalationAsPatch(patch["support_escalation"].(map[string]interface{}), d) + } + path = "metadata.0.other.0.pc.0.support.0.support_details" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["support_details"] = nil + } else if exists && patch["support_details"] != nil { + ResourceIbmOnboardingCatalogProductSupportDetailsItemAsPatch(patch["support_details"].([]interface{})[0].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogProductSupportDetailsItemAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.other.0.pc.0.support.0.support_details.0.type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["type"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.support_details.0.contact" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["contact"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.support_details.0.response_wait_time" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["response_wait_time"] = nil + } else if exists && patch["response_wait_time"] != nil { + ResourceIbmOnboardingCatalogProductSupportTimeIntervalAsPatch(patch["response_wait_time"].(map[string]interface{}), d) + } + path = "metadata.0.other.0.pc.0.support.0.support_details.0.availability" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["availability"] = nil + } else if exists && patch["availability"] != nil { + ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityAsPatch(patch["availability"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.other.0.pc.0.support.0.support_details.0.availability.0.times" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["times"] = nil + } else if exists && patch["times"] != nil { + ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityTimeAsPatch(patch["times"].([]interface{})[0].(map[string]interface{}), d) + } + path = "metadata.0.other.0.pc.0.support.0.support_details.0.availability.0.timezone" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["timezone"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.support_details.0.availability.0.always_available" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["always_available"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityTimeAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.other.0.pc.0.support.0.support_details.0.availability.0.times.0.day" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["day"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.support_details.0.availability.0.times.0.start_time" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["start_time"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.support_details.0.availability.0.times.0.end_time" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["end_time"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductSupportEscalationAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.other.0.pc.0.support.0.support_escalation.0.contact" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["contact"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.support_escalation.0.escalation_wait_time" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["escalation_wait_time"] = nil + } else if exists && patch["escalation_wait_time"] != nil { + ResourceIbmOnboardingCatalogProductSupportTimeIntervalAsPatch(patch["escalation_wait_time"].(map[string]interface{}), d) + } + path = "metadata.0.other.0.pc.0.support.0.support_escalation.0.response_wait_time" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["response_wait_time"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductSupportTimeIntervalAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.other.0.pc.0.support.0.support_details.0.response_wait_time.0.value" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["value"] = nil + } + path = "metadata.0.other.0.pc.0.support.0.support_details.0.response_wait_time.0.type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["type"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataServiceAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.service.0.rc_provisionable" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["rc_provisionable"] = nil + } + path = "metadata.0.service.0.iam_compatible" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["iam_compatible"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["strings"] = nil + } else if exists && patch["strings"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsAsPatch(patch["strings"].(map[string]interface{}), d) + } + path = "metadata.0.ui.0.urls" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["urls"] = nil + } else if exists && patch["urls"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIUrlsAsPatch(patch["urls"].(map[string]interface{}), d) + } + path = "metadata.0.ui.0.hidden" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["hidden"] = nil + } + path = "metadata.0.ui.0.side_by_side_index" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["side_by_side_index"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIUrlsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.urls.0.doc_url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["doc_url"] = nil + } + path = "metadata.0.ui.0.urls.0.terms_url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["terms_url"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["en"] = nil + } else if exists && patch["en"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsContentAsPatch(patch["en"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsContentAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en.0.bullets" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["bullets"] = nil + } else if exists && patch["bullets"] != nil { + ResourceIbmOnboardingCatalogProductCatalogHighlightItemAsPatch(patch["bullets"].([]interface{})[0].(map[string]interface{}), d) + } + path = "metadata.0.ui.0.strings.0.en.0.media" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["media"] = nil + } else if exists && patch["media"] != nil { + ResourceIbmOnboardingCatalogProductCatalogProductMediaItemAsPatch(patch["media"].([]interface{})[0].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogProductCatalogProductMediaItemAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en.0.media.0.caption_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["caption_i18n"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.media.0.thumbnail" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["thumbnail"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductCatalogHighlightItemAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.description_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description_i18n"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.title" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["title"] = nil + } + path = "metadata.0.ui.0.strings.0.en.0.bullets.0.title_i18n" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["title_i18n"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductCatalogProductProviderAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "object_provider.0.name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["name"] = nil + } + path = "object_provider.0.email" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["email"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogProductImagesAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "images.0.image" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["image"] = nil + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUIAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "overview_ui.0.en" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["en"] = nil + } else if exists && patch["en"] != nil { + ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUITranslatedContentAsPatch(patch["en"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUITranslatedContentAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "overview_ui.0.en.0.display_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["display_name"] = nil + } + path = "overview_ui.0.en.0.description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description"] = nil + } + path = "overview_ui.0.en.0.long_description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["long_description"] = nil + } +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_product_test.go b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_product_test.go new file mode 100644 index 0000000000..2d2f993e74 --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_catalog_product_test.go @@ -0,0 +1,2108 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package partnercentersell_test + +import ( + "fmt" + "testing" + + "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" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/partnercentersell" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIbmOnboardingCatalogProductBasic(t *testing.T) { + var conf partnercentersellv1.GlobalCatalogProduct + baseName := fmt.Sprintf("test-name-terraform-%d", acctest.RandIntRange(10, 100)) + productID := acc.PcsOnboardingProductWithApprovedProgrammaticName + name := baseName + active := "true" + disabled := "false" + kind := "service" + nameUpdate := baseName + activeUpdate := "false" + disabledUpdate := "false" + kindUpdate := "service" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingCatalogProductDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogProductConfigBasic(productID, name, active, disabled, kind), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingCatalogProductExists("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "name", name), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "active", active), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "disabled", disabled), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "kind", kind), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogProductConfigBasic(productID, nameUpdate, activeUpdate, disabledUpdate, kindUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "name", nameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "active", activeUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "disabled", disabledUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "kind", kindUpdate), + ), + }, + }, + }) +} + +func TestAccIbmOnboardingCatalogProductAllArgs(t *testing.T) { + var conf partnercentersellv1.GlobalCatalogProduct + productID := acc.PcsOnboardingProductWithApprovedProgrammaticName2 + baseName := fmt.Sprintf("test-name-terraform-%d", acctest.RandIntRange(10, 100)) + env := "current" + name := baseName + active := "true" + disabled := "false" + kind := "service" + envUpdate := "current" + nameUpdate := baseName + activeUpdate := "false" + disabledUpdate := "false" + kindUpdate := "service" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingCatalogProductDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogProductConfig(productID, env, name, active, disabled, kind), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingCatalogProductExists("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "env", env), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "name", name), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "active", active), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "disabled", disabled), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "kind", kind), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingCatalogProductConfig(productID, envUpdate, nameUpdate, activeUpdate, disabledUpdate, kindUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "env", envUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "name", nameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "active", activeUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "disabled", disabledUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_catalog_product.onboarding_catalog_product_instance", "kind", kindUpdate), + ), + }, + resource.TestStep{ + ResourceName: "ibm_onboarding_catalog_product.onboarding_catalog_product_instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "env", "product_id", + }, + }, + }, + }) +} + +func testAccCheckIbmOnboardingCatalogProductConfigBasic(productID string, name string, active string, disabled string, kind string) string { + return fmt.Sprintf(` + resource "ibm_onboarding_catalog_product" "onboarding_catalog_product_instance" { + product_id = "%s" + name = "%s" + active = %s + disabled = %s + kind = "%s" + tags = ["tag", "support_ibm"] + object_provider { + name = "name" + email = "email@emai.com" + } + metadata { + rc_compatible = false + } + } + `, productID, name, active, disabled, kind) +} + +func testAccCheckIbmOnboardingCatalogProductConfig(productID string, env string, name string, active string, disabled string, kind string) string { + return fmt.Sprintf(` + + resource "ibm_onboarding_catalog_product" "onboarding_catalog_product_instance" { + product_id = "%s" + env = "%s" + name = "%s" + active = %s + disabled = %s + kind = "%s" + overview_ui { + en { + display_name = "display_name" + description = "description" + long_description = "long_description" + } + } + tags = ["tag", "support_community"] + images { + image = "image" + } + object_provider { + name = "name" + email = "email@email.com" + } + metadata { + rc_compatible = false + ui { + urls { + doc_url = "doc_url" + terms_url = "terms_url" + } + hidden = true + side_by_side_index = 1.0 + } + service { + rc_provisionable = true + iam_compatible = false + } + other { + pc { + support { + url = "url" + status_url = "status_url" + locations = [ "locations" ] + languages = [ "languages" ] + support_type = "community" + support_escalation { + contact = "contact" + escalation_wait_time { + value = 1.0 + type = "type" + } + response_wait_time { + value = 1.0 + type = "type" + } + } + support_details { + type = "support_site" + contact = "contact" + response_wait_time { + value = 1.0 + type = "type" + } + availability { + times { + day = 1.0 + start_time = "start_time" + end_time = "end_time" + } + timezone = "timezone" + always_available = true + } + } + } + } + } + } + } + `, productID, env, name, active, disabled, kind) +} + +func testAccCheckIbmOnboardingCatalogProductExists(n string, obj partnercentersellv1.GlobalCatalogProduct) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + + getCatalogProductOptions := &partnercentersellv1.GetCatalogProductOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getCatalogProductOptions.SetProductID(parts[0]) + getCatalogProductOptions.SetCatalogProductID(parts[1]) + + globalCatalogProduct, _, err := partnerCenterSellClient.GetCatalogProduct(getCatalogProductOptions) + if err != nil { + return err + } + + obj = *globalCatalogProduct + return nil + } +} + +func testAccCheckIbmOnboardingCatalogProductDestroy(s *terraform.State) error { + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_onboarding_catalog_product" { + continue + } + + getCatalogProductOptions := &partnercentersellv1.GetCatalogProductOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getCatalogProductOptions.SetProductID(parts[0]) + getCatalogProductOptions.SetCatalogProductID(parts[1]) + + // Try to find the key + _, response, err := partnerCenterSellClient.GetCatalogProduct(getCatalogProductOptions) + + if err == nil { + return fmt.Errorf("onboarding_catalog_product still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for onboarding_catalog_product (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUIToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + globalCatalogOverviewUiTranslatedContentModel := make(map[string]interface{}) + globalCatalogOverviewUiTranslatedContentModel["display_name"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["description"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["long_description"] = "testString" + + model := make(map[string]interface{}) + model["en"] = []map[string]interface{}{globalCatalogOverviewUiTranslatedContentModel} + + assert.Equal(t, result, model) + } + + globalCatalogOverviewUiTranslatedContentModel := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + globalCatalogOverviewUiTranslatedContentModel.DisplayName = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.Description = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.LongDescription = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogOverviewUI) + model.En = globalCatalogOverviewUiTranslatedContentModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUIToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUITranslatedContentToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["display_name"] = "testString" + model["description"] = "testString" + model["long_description"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + model.DisplayName = core.StringPtr("testString") + model.Description = core.StringPtr("testString") + model.LongDescription = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogOverviewUITranslatedContentToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogProductImagesToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["image"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogProductImages) + model.Image = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogProductImagesToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductCatalogProductProviderToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.CatalogProductProvider) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductCatalogProductProviderToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []map[string]interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + globalCatalogMetadataUiModel := make(map[string]interface{}) + globalCatalogMetadataUiModel["strings"] = []map[string]interface{}{globalCatalogMetadataUiStringsModel} + globalCatalogMetadataUiModel["urls"] = []map[string]interface{}{globalCatalogMetadataUiUrlsModel} + globalCatalogMetadataUiModel["hidden"] = true + globalCatalogMetadataUiModel["side_by_side_index"] = float64(72.5) + + globalCatalogMetadataServiceModel := make(map[string]interface{}) + globalCatalogMetadataServiceModel["rc_provisionable"] = true + globalCatalogMetadataServiceModel["iam_compatible"] = true + + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportEscalationModel := make(map[string]interface{}) + supportEscalationModel["contact"] = "testString" + supportEscalationModel["escalation_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + supportEscalationModel["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []map[string]interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + supportDetailsItemModel := make(map[string]interface{}) + supportDetailsItemModel["type"] = "support_site" + supportDetailsItemModel["contact"] = "testString" + supportDetailsItemModel["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + supportDetailsItemModel["availability"] = []map[string]interface{}{supportDetailsItemAvailabilityModel} + + globalCatalogProductMetadataOtherPcSupportModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcSupportModel["url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["status_url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["locations"] = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["languages"] = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["process"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["process_i18n"] = map[string]interface{}{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel["support_type"] = "community" + globalCatalogProductMetadataOtherPcSupportModel["support_escalation"] = []map[string]interface{}{supportEscalationModel} + globalCatalogProductMetadataOtherPcSupportModel["support_details"] = []map[string]interface{}{supportDetailsItemModel} + + globalCatalogProductMetadataOtherPcModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcModel["support"] = []map[string]interface{}{globalCatalogProductMetadataOtherPcSupportModel} + + globalCatalogProductMetadataOtherModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherModel["pc"] = []map[string]interface{}{globalCatalogProductMetadataOtherPcModel} + + model := make(map[string]interface{}) + model["rc_compatible"] = true + model["ui"] = []map[string]interface{}{globalCatalogMetadataUiModel} + model["service"] = []map[string]interface{}{globalCatalogMetadataServiceModel} + model["other"] = []map[string]interface{}{globalCatalogProductMetadataOtherModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + globalCatalogMetadataUiModel := new(partnercentersellv1.GlobalCatalogMetadataUI) + globalCatalogMetadataUiModel.Strings = globalCatalogMetadataUiStringsModel + globalCatalogMetadataUiModel.Urls = globalCatalogMetadataUiUrlsModel + globalCatalogMetadataUiModel.Hidden = core.BoolPtr(true) + globalCatalogMetadataUiModel.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + globalCatalogMetadataServiceModel := new(partnercentersellv1.GlobalCatalogMetadataService) + globalCatalogMetadataServiceModel.RcProvisionable = core.BoolPtr(true) + globalCatalogMetadataServiceModel.IamCompatible = core.BoolPtr(true) + + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportEscalationModel := new(partnercentersellv1.SupportEscalation) + supportEscalationModel.Contact = core.StringPtr("testString") + supportEscalationModel.EscalationWaitTime = supportTimeIntervalModel + supportEscalationModel.ResponseWaitTime = supportTimeIntervalModel + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + supportDetailsItemModel := new(partnercentersellv1.SupportDetailsItem) + supportDetailsItemModel.Type = core.StringPtr("support_site") + supportDetailsItemModel.Contact = core.StringPtr("testString") + supportDetailsItemModel.ResponseWaitTime = supportTimeIntervalModel + supportDetailsItemModel.Availability = supportDetailsItemAvailabilityModel + + globalCatalogProductMetadataOtherPcSupportModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) + globalCatalogProductMetadataOtherPcSupportModel.URL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.StatusURL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.Locations = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Languages = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Process = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.ProcessI18n = map[string]string{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel.SupportType = core.StringPtr("community") + globalCatalogProductMetadataOtherPcSupportModel.SupportEscalation = supportEscalationModel + globalCatalogProductMetadataOtherPcSupportModel.SupportDetails = []partnercentersellv1.SupportDetailsItem{*supportDetailsItemModel} + + globalCatalogProductMetadataOtherPcModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPC) + globalCatalogProductMetadataOtherPcModel.Support = globalCatalogProductMetadataOtherPcSupportModel + + globalCatalogProductMetadataOtherModel := new(partnercentersellv1.GlobalCatalogProductMetadataOther) + globalCatalogProductMetadataOtherModel.PC = globalCatalogProductMetadataOtherPcModel + + model := new(partnercentersellv1.GlobalCatalogProductMetadata) + model.RcCompatible = core.BoolPtr(true) + model.Ui = globalCatalogMetadataUiModel + model.Service = globalCatalogMetadataServiceModel + model.Other = globalCatalogProductMetadataOtherModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []map[string]interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + model := make(map[string]interface{}) + model["strings"] = []map[string]interface{}{globalCatalogMetadataUiStringsModel} + model["urls"] = []map[string]interface{}{globalCatalogMetadataUiUrlsModel} + model["hidden"] = true + model["side_by_side_index"] = float64(72.5) + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUI) + model.Strings = globalCatalogMetadataUiStringsModel + model.Urls = globalCatalogMetadataUiUrlsModel + model.Hidden = core.BoolPtr(true) + model.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + model := make(map[string]interface{}) + model["en"] = []map[string]interface{}{globalCatalogMetadataUiStringsContentModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + model.En = globalCatalogMetadataUiStringsContentModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsContentToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + model := make(map[string]interface{}) + model["bullets"] = []map[string]interface{}{catalogHighlightItemModel} + model["media"] = []map[string]interface{}{catalogProductMediaItemModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + model.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + model.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIStringsContentToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductCatalogHighlightItemToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["description"] = "testString" + model["description_i18n"] = map[string]interface{}{"key1": "testString"} + model["title"] = "testString" + model["title_i18n"] = map[string]interface{}{"key1": "testString"} + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.CatalogHighlightItem) + model.Description = core.StringPtr("testString") + model.DescriptionI18n = map[string]string{"key1": "testString"} + model.Title = core.StringPtr("testString") + model.TitleI18n = map[string]string{"key1": "testString"} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductCatalogHighlightItemToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductCatalogProductMediaItemToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["caption"] = "testString" + model["caption_i18n"] = map[string]interface{}{"key1": "testString"} + model["thumbnail"] = "testString" + model["type"] = "image" + model["url"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.CatalogProductMediaItem) + model.Caption = core.StringPtr("testString") + model.CaptionI18n = map[string]string{"key1": "testString"} + model.Thumbnail = core.StringPtr("testString") + model.Type = core.StringPtr("image") + model.URL = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductCatalogProductMediaItemToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIUrlsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["doc_url"] = "testString" + model["terms_url"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + model.DocURL = core.StringPtr("testString") + model.TermsURL = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataUIUrlsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogMetadataServiceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["rc_provisionable"] = true + model["iam_compatible"] = true + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.GlobalCatalogMetadataService) + model.RcProvisionable = core.BoolPtr(true) + model.IamCompatible = core.BoolPtr(true) + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogMetadataServiceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportEscalationModel := make(map[string]interface{}) + supportEscalationModel["contact"] = "testString" + supportEscalationModel["escalation_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + supportEscalationModel["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []map[string]interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + supportDetailsItemModel := make(map[string]interface{}) + supportDetailsItemModel["type"] = "support_site" + supportDetailsItemModel["contact"] = "testString" + supportDetailsItemModel["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + supportDetailsItemModel["availability"] = []map[string]interface{}{supportDetailsItemAvailabilityModel} + + globalCatalogProductMetadataOtherPcSupportModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcSupportModel["url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["status_url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["locations"] = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["languages"] = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["process"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["process_i18n"] = map[string]interface{}{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel["support_type"] = "community" + globalCatalogProductMetadataOtherPcSupportModel["support_escalation"] = []map[string]interface{}{supportEscalationModel} + globalCatalogProductMetadataOtherPcSupportModel["support_details"] = []map[string]interface{}{supportDetailsItemModel} + + globalCatalogProductMetadataOtherPcModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcModel["support"] = []map[string]interface{}{globalCatalogProductMetadataOtherPcSupportModel} + + model := make(map[string]interface{}) + model["pc"] = []map[string]interface{}{globalCatalogProductMetadataOtherPcModel} + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportEscalationModel := new(partnercentersellv1.SupportEscalation) + supportEscalationModel.Contact = core.StringPtr("testString") + supportEscalationModel.EscalationWaitTime = supportTimeIntervalModel + supportEscalationModel.ResponseWaitTime = supportTimeIntervalModel + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + supportDetailsItemModel := new(partnercentersellv1.SupportDetailsItem) + supportDetailsItemModel.Type = core.StringPtr("support_site") + supportDetailsItemModel.Contact = core.StringPtr("testString") + supportDetailsItemModel.ResponseWaitTime = supportTimeIntervalModel + supportDetailsItemModel.Availability = supportDetailsItemAvailabilityModel + + globalCatalogProductMetadataOtherPcSupportModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) + globalCatalogProductMetadataOtherPcSupportModel.URL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.StatusURL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.Locations = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Languages = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Process = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.ProcessI18n = map[string]string{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel.SupportType = core.StringPtr("community") + globalCatalogProductMetadataOtherPcSupportModel.SupportEscalation = supportEscalationModel + globalCatalogProductMetadataOtherPcSupportModel.SupportDetails = []partnercentersellv1.SupportDetailsItem{*supportDetailsItemModel} + + globalCatalogProductMetadataOtherPcModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPC) + globalCatalogProductMetadataOtherPcModel.Support = globalCatalogProductMetadataOtherPcSupportModel + + model := new(partnercentersellv1.GlobalCatalogProductMetadataOther) + model.PC = globalCatalogProductMetadataOtherPcModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportEscalationModel := make(map[string]interface{}) + supportEscalationModel["contact"] = "testString" + supportEscalationModel["escalation_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + supportEscalationModel["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []map[string]interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + supportDetailsItemModel := make(map[string]interface{}) + supportDetailsItemModel["type"] = "support_site" + supportDetailsItemModel["contact"] = "testString" + supportDetailsItemModel["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + supportDetailsItemModel["availability"] = []map[string]interface{}{supportDetailsItemAvailabilityModel} + + globalCatalogProductMetadataOtherPcSupportModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcSupportModel["url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["status_url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["locations"] = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["languages"] = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["process"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["process_i18n"] = map[string]interface{}{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel["support_type"] = "community" + globalCatalogProductMetadataOtherPcSupportModel["support_escalation"] = []map[string]interface{}{supportEscalationModel} + globalCatalogProductMetadataOtherPcSupportModel["support_details"] = []map[string]interface{}{supportDetailsItemModel} + + model := make(map[string]interface{}) + model["support"] = []map[string]interface{}{globalCatalogProductMetadataOtherPcSupportModel} + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportEscalationModel := new(partnercentersellv1.SupportEscalation) + supportEscalationModel.Contact = core.StringPtr("testString") + supportEscalationModel.EscalationWaitTime = supportTimeIntervalModel + supportEscalationModel.ResponseWaitTime = supportTimeIntervalModel + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + supportDetailsItemModel := new(partnercentersellv1.SupportDetailsItem) + supportDetailsItemModel.Type = core.StringPtr("support_site") + supportDetailsItemModel.Contact = core.StringPtr("testString") + supportDetailsItemModel.ResponseWaitTime = supportTimeIntervalModel + supportDetailsItemModel.Availability = supportDetailsItemAvailabilityModel + + globalCatalogProductMetadataOtherPcSupportModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) + globalCatalogProductMetadataOtherPcSupportModel.URL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.StatusURL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.Locations = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Languages = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Process = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.ProcessI18n = map[string]string{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel.SupportType = core.StringPtr("community") + globalCatalogProductMetadataOtherPcSupportModel.SupportEscalation = supportEscalationModel + globalCatalogProductMetadataOtherPcSupportModel.SupportDetails = []partnercentersellv1.SupportDetailsItem{*supportDetailsItemModel} + + model := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPC) + model.Support = globalCatalogProductMetadataOtherPcSupportModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCSupportToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportEscalationModel := make(map[string]interface{}) + supportEscalationModel["contact"] = "testString" + supportEscalationModel["escalation_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + supportEscalationModel["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []map[string]interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + supportDetailsItemModel := make(map[string]interface{}) + supportDetailsItemModel["type"] = "support_site" + supportDetailsItemModel["contact"] = "testString" + supportDetailsItemModel["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + supportDetailsItemModel["availability"] = []map[string]interface{}{supportDetailsItemAvailabilityModel} + + model := make(map[string]interface{}) + model["url"] = "testString" + model["status_url"] = "testString" + model["locations"] = []string{"testString"} + model["languages"] = []string{"testString"} + model["process"] = "testString" + model["process_i18n"] = map[string]interface{}{"key1": "testString"} + model["support_type"] = "community" + model["support_escalation"] = []map[string]interface{}{supportEscalationModel} + model["support_details"] = []map[string]interface{}{supportDetailsItemModel} + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportEscalationModel := new(partnercentersellv1.SupportEscalation) + supportEscalationModel.Contact = core.StringPtr("testString") + supportEscalationModel.EscalationWaitTime = supportTimeIntervalModel + supportEscalationModel.ResponseWaitTime = supportTimeIntervalModel + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + supportDetailsItemModel := new(partnercentersellv1.SupportDetailsItem) + supportDetailsItemModel.Type = core.StringPtr("support_site") + supportDetailsItemModel.Contact = core.StringPtr("testString") + supportDetailsItemModel.ResponseWaitTime = supportTimeIntervalModel + supportDetailsItemModel.Availability = supportDetailsItemAvailabilityModel + + model := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) + model.URL = core.StringPtr("testString") + model.StatusURL = core.StringPtr("testString") + model.Locations = []string{"testString"} + model.Languages = []string{"testString"} + model.Process = core.StringPtr("testString") + model.ProcessI18n = map[string]string{"key1": "testString"} + model.SupportType = core.StringPtr("community") + model.SupportEscalation = supportEscalationModel + model.SupportDetails = []partnercentersellv1.SupportDetailsItem{*supportDetailsItemModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductGlobalCatalogProductMetadataOtherPCSupportToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductSupportEscalationToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + model := make(map[string]interface{}) + model["contact"] = "testString" + model["escalation_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + model["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportEscalation) + model.Contact = core.StringPtr("testString") + model.EscalationWaitTime = supportTimeIntervalModel + model.ResponseWaitTime = supportTimeIntervalModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductSupportEscalationToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductSupportTimeIntervalToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["value"] = float64(72.5) + model["type"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.SupportTimeInterval) + model.Value = core.Float64Ptr(float64(72.5)) + model.Type = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductSupportTimeIntervalToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductSupportDetailsItemToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []map[string]interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + model := make(map[string]interface{}) + model["type"] = "support_site" + model["contact"] = "testString" + model["response_wait_time"] = []map[string]interface{}{supportTimeIntervalModel} + model["availability"] = []map[string]interface{}{supportDetailsItemAvailabilityModel} + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + model := new(partnercentersellv1.SupportDetailsItem) + model.Type = core.StringPtr("support_site") + model.Contact = core.StringPtr("testString") + model.ResponseWaitTime = supportTimeIntervalModel + model.Availability = supportDetailsItemAvailabilityModel + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductSupportDetailsItemToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + model := make(map[string]interface{}) + model["times"] = []map[string]interface{}{supportDetailsItemAvailabilityTimeModel} + model["timezone"] = "testString" + model["always_available"] = true + + assert.Equal(t, result, model) + } + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportDetailsItemAvailability) + model.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + model.Timezone = core.StringPtr("testString") + model.AlwaysAvailable = core.BoolPtr(true) + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityTimeToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["day"] = float64(72.5) + model["start_time"] = "testString" + model["end_time"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + model.Day = core.Float64Ptr(float64(72.5)) + model.StartTime = core.StringPtr("testString") + model.EndTime = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductSupportDetailsItemAvailabilityTimeToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToCatalogProductProvider(t *testing.T) { + checkResult := func(result *partnercentersellv1.CatalogProductProvider) { + model := new(partnercentersellv1.CatalogProductProvider) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToCatalogProductProvider(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogOverviewUI(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogOverviewUI) { + globalCatalogOverviewUiTranslatedContentModel := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + globalCatalogOverviewUiTranslatedContentModel.DisplayName = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.Description = core.StringPtr("testString") + globalCatalogOverviewUiTranslatedContentModel.LongDescription = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogOverviewUI) + model.En = globalCatalogOverviewUiTranslatedContentModel + + assert.Equal(t, result, model) + } + + globalCatalogOverviewUiTranslatedContentModel := make(map[string]interface{}) + globalCatalogOverviewUiTranslatedContentModel["display_name"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["description"] = "testString" + globalCatalogOverviewUiTranslatedContentModel["long_description"] = "testString" + + model := make(map[string]interface{}) + model["en"] = []interface{}{globalCatalogOverviewUiTranslatedContentModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogOverviewUI(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogOverviewUITranslatedContent(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) { + model := new(partnercentersellv1.GlobalCatalogOverviewUITranslatedContent) + model.DisplayName = core.StringPtr("testString") + model.Description = core.StringPtr("testString") + model.LongDescription = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["display_name"] = "testString" + model["description"] = "testString" + model["long_description"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogOverviewUITranslatedContent(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductImages(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogProductImages) { + model := new(partnercentersellv1.GlobalCatalogProductImages) + model.Image = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["image"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductImages(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadata(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogProductMetadata) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + globalCatalogMetadataUiModel := new(partnercentersellv1.GlobalCatalogMetadataUI) + globalCatalogMetadataUiModel.Strings = globalCatalogMetadataUiStringsModel + globalCatalogMetadataUiModel.Urls = globalCatalogMetadataUiUrlsModel + globalCatalogMetadataUiModel.Hidden = core.BoolPtr(true) + globalCatalogMetadataUiModel.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + globalCatalogMetadataServiceModel := new(partnercentersellv1.GlobalCatalogMetadataService) + globalCatalogMetadataServiceModel.RcProvisionable = core.BoolPtr(true) + globalCatalogMetadataServiceModel.IamCompatible = core.BoolPtr(true) + + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportEscalationModel := new(partnercentersellv1.SupportEscalation) + supportEscalationModel.Contact = core.StringPtr("testString") + supportEscalationModel.EscalationWaitTime = supportTimeIntervalModel + supportEscalationModel.ResponseWaitTime = supportTimeIntervalModel + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + supportDetailsItemModel := new(partnercentersellv1.SupportDetailsItem) + supportDetailsItemModel.Type = core.StringPtr("support_site") + supportDetailsItemModel.Contact = core.StringPtr("testString") + supportDetailsItemModel.ResponseWaitTime = supportTimeIntervalModel + supportDetailsItemModel.Availability = supportDetailsItemAvailabilityModel + + globalCatalogProductMetadataOtherPcSupportModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) + globalCatalogProductMetadataOtherPcSupportModel.URL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.StatusURL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.Locations = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Languages = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Process = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.ProcessI18n = map[string]string{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel.SupportType = core.StringPtr("community") + globalCatalogProductMetadataOtherPcSupportModel.SupportEscalation = supportEscalationModel + globalCatalogProductMetadataOtherPcSupportModel.SupportDetails = []partnercentersellv1.SupportDetailsItem{*supportDetailsItemModel} + + globalCatalogProductMetadataOtherPcModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPC) + globalCatalogProductMetadataOtherPcModel.Support = globalCatalogProductMetadataOtherPcSupportModel + + globalCatalogProductMetadataOtherModel := new(partnercentersellv1.GlobalCatalogProductMetadataOther) + globalCatalogProductMetadataOtherModel.PC = globalCatalogProductMetadataOtherPcModel + + model := new(partnercentersellv1.GlobalCatalogProductMetadata) + model.RcCompatible = core.BoolPtr(true) + model.Ui = globalCatalogMetadataUiModel + model.Service = globalCatalogMetadataServiceModel + model.Other = globalCatalogProductMetadataOtherModel + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + globalCatalogMetadataUiModel := make(map[string]interface{}) + globalCatalogMetadataUiModel["strings"] = []interface{}{globalCatalogMetadataUiStringsModel} + globalCatalogMetadataUiModel["urls"] = []interface{}{globalCatalogMetadataUiUrlsModel} + globalCatalogMetadataUiModel["hidden"] = true + globalCatalogMetadataUiModel["side_by_side_index"] = float64(72.5) + + globalCatalogMetadataServiceModel := make(map[string]interface{}) + globalCatalogMetadataServiceModel["rc_provisionable"] = true + globalCatalogMetadataServiceModel["iam_compatible"] = true + + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportEscalationModel := make(map[string]interface{}) + supportEscalationModel["contact"] = "testString" + supportEscalationModel["escalation_wait_time"] = []interface{}{supportTimeIntervalModel} + supportEscalationModel["response_wait_time"] = []interface{}{supportTimeIntervalModel} + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + supportDetailsItemModel := make(map[string]interface{}) + supportDetailsItemModel["type"] = "support_site" + supportDetailsItemModel["contact"] = "testString" + supportDetailsItemModel["response_wait_time"] = []interface{}{supportTimeIntervalModel} + supportDetailsItemModel["availability"] = []interface{}{supportDetailsItemAvailabilityModel} + + globalCatalogProductMetadataOtherPcSupportModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcSupportModel["url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["status_url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["locations"] = []interface{}{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["languages"] = []interface{}{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["process"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["process_i18n"] = map[string]interface{}{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel["support_type"] = "community" + globalCatalogProductMetadataOtherPcSupportModel["support_escalation"] = []interface{}{supportEscalationModel} + globalCatalogProductMetadataOtherPcSupportModel["support_details"] = []interface{}{supportDetailsItemModel} + + globalCatalogProductMetadataOtherPcModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcModel["support"] = []interface{}{globalCatalogProductMetadataOtherPcSupportModel} + + globalCatalogProductMetadataOtherModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherModel["pc"] = []interface{}{globalCatalogProductMetadataOtherPcModel} + + model := make(map[string]interface{}) + model["rc_compatible"] = true + model["ui"] = []interface{}{globalCatalogMetadataUiModel} + model["service"] = []interface{}{globalCatalogMetadataServiceModel} + model["other"] = []interface{}{globalCatalogProductMetadataOtherModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadata(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUI(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUI) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + globalCatalogMetadataUiStringsModel.En = globalCatalogMetadataUiStringsContentModel + + globalCatalogMetadataUiUrlsModel := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + globalCatalogMetadataUiUrlsModel.DocURL = core.StringPtr("testString") + globalCatalogMetadataUiUrlsModel.TermsURL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUI) + model.Strings = globalCatalogMetadataUiStringsModel + model.Urls = globalCatalogMetadataUiUrlsModel + model.Hidden = core.BoolPtr(true) + model.SideBySideIndex = core.Float64Ptr(float64(72.5)) + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []interface{}{catalogProductMediaItemModel} + + globalCatalogMetadataUiStringsModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsModel["en"] = []interface{}{globalCatalogMetadataUiStringsContentModel} + + globalCatalogMetadataUiUrlsModel := make(map[string]interface{}) + globalCatalogMetadataUiUrlsModel["doc_url"] = "testString" + globalCatalogMetadataUiUrlsModel["terms_url"] = "testString" + + model := make(map[string]interface{}) + model["strings"] = []interface{}{globalCatalogMetadataUiStringsModel} + model["urls"] = []interface{}{globalCatalogMetadataUiUrlsModel} + model["hidden"] = true + model["side_by_side_index"] = float64(72.5) + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUI(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIStrings(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUIStrings) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + globalCatalogMetadataUiStringsContentModel := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + globalCatalogMetadataUiStringsContentModel.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStrings) + model.En = globalCatalogMetadataUiStringsContentModel + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + globalCatalogMetadataUiStringsContentModel := make(map[string]interface{}) + globalCatalogMetadataUiStringsContentModel["bullets"] = []interface{}{catalogHighlightItemModel} + globalCatalogMetadataUiStringsContentModel["media"] = []interface{}{catalogProductMediaItemModel} + + model := make(map[string]interface{}) + model["en"] = []interface{}{globalCatalogMetadataUiStringsContentModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIStrings(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIStringsContent(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUIStringsContent) { + catalogHighlightItemModel := new(partnercentersellv1.CatalogHighlightItem) + catalogHighlightItemModel.Description = core.StringPtr("testString") + catalogHighlightItemModel.DescriptionI18n = map[string]string{"key1": "testString"} + catalogHighlightItemModel.Title = core.StringPtr("testString") + catalogHighlightItemModel.TitleI18n = map[string]string{"key1": "testString"} + + catalogProductMediaItemModel := new(partnercentersellv1.CatalogProductMediaItem) + catalogProductMediaItemModel.Caption = core.StringPtr("testString") + catalogProductMediaItemModel.CaptionI18n = map[string]string{"key1": "testString"} + catalogProductMediaItemModel.Thumbnail = core.StringPtr("testString") + catalogProductMediaItemModel.Type = core.StringPtr("image") + catalogProductMediaItemModel.URL = core.StringPtr("testString") + + model := new(partnercentersellv1.GlobalCatalogMetadataUIStringsContent) + model.Bullets = []partnercentersellv1.CatalogHighlightItem{*catalogHighlightItemModel} + model.Media = []partnercentersellv1.CatalogProductMediaItem{*catalogProductMediaItemModel} + + assert.Equal(t, result, model) + } + + catalogHighlightItemModel := make(map[string]interface{}) + catalogHighlightItemModel["description"] = "testString" + catalogHighlightItemModel["description_i18n"] = map[string]interface{}{"key1": "testString"} + catalogHighlightItemModel["title"] = "testString" + catalogHighlightItemModel["title_i18n"] = map[string]interface{}{"key1": "testString"} + + catalogProductMediaItemModel := make(map[string]interface{}) + catalogProductMediaItemModel["caption"] = "testString" + catalogProductMediaItemModel["caption_i18n"] = map[string]interface{}{"key1": "testString"} + catalogProductMediaItemModel["thumbnail"] = "testString" + catalogProductMediaItemModel["type"] = "image" + catalogProductMediaItemModel["url"] = "testString" + + model := make(map[string]interface{}) + model["bullets"] = []interface{}{catalogHighlightItemModel} + model["media"] = []interface{}{catalogProductMediaItemModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIStringsContent(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToCatalogHighlightItem(t *testing.T) { + checkResult := func(result *partnercentersellv1.CatalogHighlightItem) { + model := new(partnercentersellv1.CatalogHighlightItem) + model.Description = core.StringPtr("testString") + model.DescriptionI18n = map[string]string{"key1": "testString"} + model.Title = core.StringPtr("testString") + model.TitleI18n = map[string]string{"key1": "testString"} + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["description"] = "testString" + model["description_i18n"] = map[string]interface{}{"key1": "testString"} + model["title"] = "testString" + model["title_i18n"] = map[string]interface{}{"key1": "testString"} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToCatalogHighlightItem(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToCatalogProductMediaItem(t *testing.T) { + checkResult := func(result *partnercentersellv1.CatalogProductMediaItem) { + model := new(partnercentersellv1.CatalogProductMediaItem) + model.Caption = core.StringPtr("testString") + model.CaptionI18n = map[string]string{"key1": "testString"} + model.Thumbnail = core.StringPtr("testString") + model.Type = core.StringPtr("image") + model.URL = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["caption"] = "testString" + model["caption_i18n"] = map[string]interface{}{"key1": "testString"} + model["thumbnail"] = "testString" + model["type"] = "image" + model["url"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToCatalogProductMediaItem(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIUrls(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataUIUrls) { + model := new(partnercentersellv1.GlobalCatalogMetadataUIUrls) + model.DocURL = core.StringPtr("testString") + model.TermsURL = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["doc_url"] = "testString" + model["terms_url"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataUIUrls(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataService(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogMetadataService) { + model := new(partnercentersellv1.GlobalCatalogMetadataService) + model.RcProvisionable = core.BoolPtr(true) + model.IamCompatible = core.BoolPtr(true) + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["rc_provisionable"] = true + model["iam_compatible"] = true + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogMetadataService(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOther(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogProductMetadataOther) { + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportEscalationModel := new(partnercentersellv1.SupportEscalation) + supportEscalationModel.Contact = core.StringPtr("testString") + supportEscalationModel.EscalationWaitTime = supportTimeIntervalModel + supportEscalationModel.ResponseWaitTime = supportTimeIntervalModel + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + supportDetailsItemModel := new(partnercentersellv1.SupportDetailsItem) + supportDetailsItemModel.Type = core.StringPtr("support_site") + supportDetailsItemModel.Contact = core.StringPtr("testString") + supportDetailsItemModel.ResponseWaitTime = supportTimeIntervalModel + supportDetailsItemModel.Availability = supportDetailsItemAvailabilityModel + + globalCatalogProductMetadataOtherPcSupportModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) + globalCatalogProductMetadataOtherPcSupportModel.URL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.StatusURL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.Locations = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Languages = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Process = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.ProcessI18n = map[string]string{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel.SupportType = core.StringPtr("community") + globalCatalogProductMetadataOtherPcSupportModel.SupportEscalation = supportEscalationModel + globalCatalogProductMetadataOtherPcSupportModel.SupportDetails = []partnercentersellv1.SupportDetailsItem{*supportDetailsItemModel} + + globalCatalogProductMetadataOtherPcModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPC) + globalCatalogProductMetadataOtherPcModel.Support = globalCatalogProductMetadataOtherPcSupportModel + + model := new(partnercentersellv1.GlobalCatalogProductMetadataOther) + model.PC = globalCatalogProductMetadataOtherPcModel + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportEscalationModel := make(map[string]interface{}) + supportEscalationModel["contact"] = "testString" + supportEscalationModel["escalation_wait_time"] = []interface{}{supportTimeIntervalModel} + supportEscalationModel["response_wait_time"] = []interface{}{supportTimeIntervalModel} + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + supportDetailsItemModel := make(map[string]interface{}) + supportDetailsItemModel["type"] = "support_site" + supportDetailsItemModel["contact"] = "testString" + supportDetailsItemModel["response_wait_time"] = []interface{}{supportTimeIntervalModel} + supportDetailsItemModel["availability"] = []interface{}{supportDetailsItemAvailabilityModel} + + globalCatalogProductMetadataOtherPcSupportModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcSupportModel["url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["status_url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["locations"] = []interface{}{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["languages"] = []interface{}{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["process"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["process_i18n"] = map[string]interface{}{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel["support_type"] = "community" + globalCatalogProductMetadataOtherPcSupportModel["support_escalation"] = []interface{}{supportEscalationModel} + globalCatalogProductMetadataOtherPcSupportModel["support_details"] = []interface{}{supportDetailsItemModel} + + globalCatalogProductMetadataOtherPcModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcModel["support"] = []interface{}{globalCatalogProductMetadataOtherPcSupportModel} + + model := make(map[string]interface{}) + model["pc"] = []interface{}{globalCatalogProductMetadataOtherPcModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOther(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOtherPC(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogProductMetadataOtherPC) { + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportEscalationModel := new(partnercentersellv1.SupportEscalation) + supportEscalationModel.Contact = core.StringPtr("testString") + supportEscalationModel.EscalationWaitTime = supportTimeIntervalModel + supportEscalationModel.ResponseWaitTime = supportTimeIntervalModel + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + supportDetailsItemModel := new(partnercentersellv1.SupportDetailsItem) + supportDetailsItemModel.Type = core.StringPtr("support_site") + supportDetailsItemModel.Contact = core.StringPtr("testString") + supportDetailsItemModel.ResponseWaitTime = supportTimeIntervalModel + supportDetailsItemModel.Availability = supportDetailsItemAvailabilityModel + + globalCatalogProductMetadataOtherPcSupportModel := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) + globalCatalogProductMetadataOtherPcSupportModel.URL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.StatusURL = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.Locations = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Languages = []string{"testString"} + globalCatalogProductMetadataOtherPcSupportModel.Process = core.StringPtr("testString") + globalCatalogProductMetadataOtherPcSupportModel.ProcessI18n = map[string]string{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel.SupportType = core.StringPtr("community") + globalCatalogProductMetadataOtherPcSupportModel.SupportEscalation = supportEscalationModel + globalCatalogProductMetadataOtherPcSupportModel.SupportDetails = []partnercentersellv1.SupportDetailsItem{*supportDetailsItemModel} + + model := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPC) + model.Support = globalCatalogProductMetadataOtherPcSupportModel + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportEscalationModel := make(map[string]interface{}) + supportEscalationModel["contact"] = "testString" + supportEscalationModel["escalation_wait_time"] = []interface{}{supportTimeIntervalModel} + supportEscalationModel["response_wait_time"] = []interface{}{supportTimeIntervalModel} + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + supportDetailsItemModel := make(map[string]interface{}) + supportDetailsItemModel["type"] = "support_site" + supportDetailsItemModel["contact"] = "testString" + supportDetailsItemModel["response_wait_time"] = []interface{}{supportTimeIntervalModel} + supportDetailsItemModel["availability"] = []interface{}{supportDetailsItemAvailabilityModel} + + globalCatalogProductMetadataOtherPcSupportModel := make(map[string]interface{}) + globalCatalogProductMetadataOtherPcSupportModel["url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["status_url"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["locations"] = []interface{}{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["languages"] = []interface{}{"testString"} + globalCatalogProductMetadataOtherPcSupportModel["process"] = "testString" + globalCatalogProductMetadataOtherPcSupportModel["process_i18n"] = map[string]interface{}{"key1": "testString"} + globalCatalogProductMetadataOtherPcSupportModel["support_type"] = "community" + globalCatalogProductMetadataOtherPcSupportModel["support_escalation"] = []interface{}{supportEscalationModel} + globalCatalogProductMetadataOtherPcSupportModel["support_details"] = []interface{}{supportDetailsItemModel} + + model := make(map[string]interface{}) + model["support"] = []interface{}{globalCatalogProductMetadataOtherPcSupportModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOtherPC(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOtherPCSupport(t *testing.T) { + checkResult := func(result *partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) { + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportEscalationModel := new(partnercentersellv1.SupportEscalation) + supportEscalationModel.Contact = core.StringPtr("testString") + supportEscalationModel.EscalationWaitTime = supportTimeIntervalModel + supportEscalationModel.ResponseWaitTime = supportTimeIntervalModel + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + supportDetailsItemModel := new(partnercentersellv1.SupportDetailsItem) + supportDetailsItemModel.Type = core.StringPtr("support_site") + supportDetailsItemModel.Contact = core.StringPtr("testString") + supportDetailsItemModel.ResponseWaitTime = supportTimeIntervalModel + supportDetailsItemModel.Availability = supportDetailsItemAvailabilityModel + + model := new(partnercentersellv1.GlobalCatalogProductMetadataOtherPCSupport) + model.URL = core.StringPtr("testString") + model.StatusURL = core.StringPtr("testString") + model.Locations = []string{"testString"} + model.Languages = []string{"testString"} + model.Process = core.StringPtr("testString") + model.ProcessI18n = map[string]string{"key1": "testString"} + model.SupportType = core.StringPtr("community") + model.SupportEscalation = supportEscalationModel + model.SupportDetails = []partnercentersellv1.SupportDetailsItem{*supportDetailsItemModel} + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportEscalationModel := make(map[string]interface{}) + supportEscalationModel["contact"] = "testString" + supportEscalationModel["escalation_wait_time"] = []interface{}{supportTimeIntervalModel} + supportEscalationModel["response_wait_time"] = []interface{}{supportTimeIntervalModel} + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + supportDetailsItemModel := make(map[string]interface{}) + supportDetailsItemModel["type"] = "support_site" + supportDetailsItemModel["contact"] = "testString" + supportDetailsItemModel["response_wait_time"] = []interface{}{supportTimeIntervalModel} + supportDetailsItemModel["availability"] = []interface{}{supportDetailsItemAvailabilityModel} + + model := make(map[string]interface{}) + model["url"] = "testString" + model["status_url"] = "testString" + model["locations"] = []interface{}{"testString"} + model["languages"] = []interface{}{"testString"} + model["process"] = "testString" + model["process_i18n"] = map[string]interface{}{"key1": "testString"} + model["support_type"] = "community" + model["support_escalation"] = []interface{}{supportEscalationModel} + model["support_details"] = []interface{}{supportDetailsItemModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToGlobalCatalogProductMetadataOtherPCSupport(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToSupportEscalation(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportEscalation) { + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportEscalation) + model.Contact = core.StringPtr("testString") + model.EscalationWaitTime = supportTimeIntervalModel + model.ResponseWaitTime = supportTimeIntervalModel + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + model := make(map[string]interface{}) + model["contact"] = "testString" + model["escalation_wait_time"] = []interface{}{supportTimeIntervalModel} + model["response_wait_time"] = []interface{}{supportTimeIntervalModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToSupportEscalation(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToSupportTimeInterval(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportTimeInterval) { + model := new(partnercentersellv1.SupportTimeInterval) + model.Value = core.Float64Ptr(float64(72.5)) + model.Type = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["value"] = float64(72.5) + model["type"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToSupportTimeInterval(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToSupportDetailsItem(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportDetailsItem) { + supportTimeIntervalModel := new(partnercentersellv1.SupportTimeInterval) + supportTimeIntervalModel.Value = core.Float64Ptr(float64(72.5)) + supportTimeIntervalModel.Type = core.StringPtr("testString") + + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + supportDetailsItemAvailabilityModel := new(partnercentersellv1.SupportDetailsItemAvailability) + supportDetailsItemAvailabilityModel.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel.Timezone = core.StringPtr("testString") + supportDetailsItemAvailabilityModel.AlwaysAvailable = core.BoolPtr(true) + + model := new(partnercentersellv1.SupportDetailsItem) + model.Type = core.StringPtr("support_site") + model.Contact = core.StringPtr("testString") + model.ResponseWaitTime = supportTimeIntervalModel + model.Availability = supportDetailsItemAvailabilityModel + + assert.Equal(t, result, model) + } + + supportTimeIntervalModel := make(map[string]interface{}) + supportTimeIntervalModel["value"] = float64(72.5) + supportTimeIntervalModel["type"] = "testString" + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + supportDetailsItemAvailabilityModel := make(map[string]interface{}) + supportDetailsItemAvailabilityModel["times"] = []interface{}{supportDetailsItemAvailabilityTimeModel} + supportDetailsItemAvailabilityModel["timezone"] = "testString" + supportDetailsItemAvailabilityModel["always_available"] = true + + model := make(map[string]interface{}) + model["type"] = "support_site" + model["contact"] = "testString" + model["response_wait_time"] = []interface{}{supportTimeIntervalModel} + model["availability"] = []interface{}{supportDetailsItemAvailabilityModel} + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToSupportDetailsItem(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToSupportDetailsItemAvailability(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportDetailsItemAvailability) { + supportDetailsItemAvailabilityTimeModel := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + supportDetailsItemAvailabilityTimeModel.Day = core.Float64Ptr(float64(72.5)) + supportDetailsItemAvailabilityTimeModel.StartTime = core.StringPtr("testString") + supportDetailsItemAvailabilityTimeModel.EndTime = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportDetailsItemAvailability) + model.Times = []partnercentersellv1.SupportDetailsItemAvailabilityTime{*supportDetailsItemAvailabilityTimeModel} + model.Timezone = core.StringPtr("testString") + model.AlwaysAvailable = core.BoolPtr(true) + + assert.Equal(t, result, model) + } + + supportDetailsItemAvailabilityTimeModel := make(map[string]interface{}) + supportDetailsItemAvailabilityTimeModel["day"] = float64(72.5) + supportDetailsItemAvailabilityTimeModel["start_time"] = "testString" + supportDetailsItemAvailabilityTimeModel["end_time"] = "testString" + + model := make(map[string]interface{}) + model["times"] = []interface{}{supportDetailsItemAvailabilityTimeModel} + model["timezone"] = "testString" + model["always_available"] = true + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToSupportDetailsItemAvailability(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingCatalogProductMapToSupportDetailsItemAvailabilityTime(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportDetailsItemAvailabilityTime) { + model := new(partnercentersellv1.SupportDetailsItemAvailabilityTime) + model.Day = core.Float64Ptr(float64(72.5)) + model.StartTime = core.StringPtr("testString") + model.EndTime = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["day"] = float64(72.5) + model["start_time"] = "testString" + model["end_time"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingCatalogProductMapToSupportDetailsItemAvailabilityTime(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_iam_registration.go b/ibm/service/partnercentersell/resource_ibm_onboarding_iam_registration.go new file mode 100644 index 0000000000..bf70b35b85 --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_iam_registration.go @@ -0,0 +1,3074 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.94.1-71478489-20240820-161623 + */ + +package partnercentersell + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" +) + +func ResourceIbmOnboardingIamRegistration() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIbmOnboardingIamRegistrationCreate, + ReadContext: resourceIbmOnboardingIamRegistrationRead, + UpdateContext: resourceIbmOnboardingIamRegistrationUpdate, + DeleteContext: resourceIbmOnboardingIamRegistrationDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "product_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_iam_registration", "product_id"), + Description: "The unique ID of the product.", + }, + "env": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_iam_registration", "env"), + Description: "The environment to fetch this object from.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_iam_registration", "name"), + Description: "The IAM registration name, which must be the programmatic name of the product.", + }, + "enabled": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the service is enabled or disabled for IAM.", + }, + "service_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_iam_registration", "service_type"), + Description: "The type of the service.", + }, + "actions": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The product access management action.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The unique identifier for the action.", + }, + "roles": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of roles for the action.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "description": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The description for the object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The fallback string for the description object.", + }, + "en": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "English.", + }, + "de": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "German.", + }, + "es": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Spanish.", + }, + "fr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "French.", + }, + "it": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Italian.", + }, + "ja": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Japanese.", + }, + "ko": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Korean.", + }, + "pt_br": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Portuguese (Brazil).", + }, + "zh_tw": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Traditional Chinese.", + }, + "zh_cn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Simplified Chinese.", + }, + }, + }, + }, + "display_name": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The display name of the object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The fallback string for the description object.", + }, + "en": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "English.", + }, + "de": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "German.", + }, + "es": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Spanish.", + }, + "fr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "French.", + }, + "it": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Italian.", + }, + "ja": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Japanese.", + }, + "ko": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Korean.", + }, + "pt_br": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Portuguese (Brazil).", + }, + "zh_tw": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Traditional Chinese.", + }, + "zh_cn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Simplified Chinese.", + }, + }, + }, + }, + "options": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Extra options.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "hidden": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Optional opt-in if action is hidden from customers.", + }, + }, + }, + }, + }, + }, + }, + "additional_policy_scopes": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "List of additional policy scopes.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "display_name": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The display name of the object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The fallback string for the description object.", + }, + "en": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "English.", + }, + "de": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "German.", + }, + "es": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Spanish.", + }, + "fr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "French.", + }, + "it": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Italian.", + }, + "ja": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Japanese.", + }, + "ko": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Korean.", + }, + "pt_br": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Portuguese (Brazil).", + }, + "zh_tw": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Traditional Chinese.", + }, + "zh_cn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Simplified Chinese.", + }, + }, + }, + }, + "parent_ids": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of parent IDs for product access management.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "resource_hierarchy_attribute": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The resource hierarchy key-value pair for composite services.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The resource hierarchy key.", + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The resource hierarchy value.", + }, + }, + }, + }, + "supported_anonymous_accesses": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of supported anonymous accesses.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "attributes": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The attributes for anonymous accesses.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "An account id.", + }, + "service_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name of the service.", + }, + }, + }, + }, + "roles": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The roles of supported anonymous accesses.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "supported_attributes": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of supported attributes.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The supported attribute key.", + }, + "options": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The list of support attribute options.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operators": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The supported attribute operator.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "hidden": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Optional opt-in if attribute is hidden from customers (customer can still use it if they found out themselves).", + }, + "supported_attributes": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of supported patterns.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "policy_types": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of policy types.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "is_empty_value_supported": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Indicate whether the empty value is supported.", + }, + "is_string_exists_false_value_supported": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Indicate whether the false value is supported for stringExists operator.", + }, + "key": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name of attribute.", + }, + "resource_hierarchy": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Resource hierarchy options for composite services.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Hierarchy description key.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Key.", + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Value.", + }, + }, + }, + }, + "value": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Hierarchy description value.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Key.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "display_name": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The display name of the object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The fallback string for the description object.", + }, + "en": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "English.", + }, + "de": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "German.", + }, + "es": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Spanish.", + }, + "fr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "French.", + }, + "it": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Italian.", + }, + "ja": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Japanese.", + }, + "ko": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Korean.", + }, + "pt_br": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Portuguese (Brazil).", + }, + "zh_tw": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Traditional Chinese.", + }, + "zh_cn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Simplified Chinese.", + }, + }, + }, + }, + "description": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The description for the object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The fallback string for the description object.", + }, + "en": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "English.", + }, + "de": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "German.", + }, + "es": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Spanish.", + }, + "fr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "French.", + }, + "it": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Italian.", + }, + "ja": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Japanese.", + }, + "ko": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Korean.", + }, + "pt_br": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Portuguese (Brazil).", + }, + "zh_tw": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Traditional Chinese.", + }, + "zh_cn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Simplified Chinese.", + }, + }, + }, + }, + "ui": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The user interface.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "input_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The type of the input.", + }, + "input_details": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The details of the input.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "They type of the input details.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The provided values of input details.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The values of input details.", + }, + "display_name": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The display name of the object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The fallback string for the description object.", + }, + "en": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "English.", + }, + "de": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "German.", + }, + "es": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Spanish.", + }, + "fr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "French.", + }, + "it": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Italian.", + }, + "ja": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Japanese.", + }, + "ko": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Korean.", + }, + "pt_br": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Portuguese (Brazil).", + }, + "zh_tw": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Traditional Chinese.", + }, + "zh_cn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Simplified Chinese.", + }, + }, + }, + }, + }, + }, + }, + "gst": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Required if type is gst.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "query": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The query to use.", + }, + "value_property_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The value of the property name.", + }, + "label_property_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "One of labelPropertyName or inputOptionLabel is required.", + }, + "input_option_label": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The label for option input.", + }, + }, + }, + }, + "url": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The URL data for user interface.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "url_endpoint": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL of the user interface interface.", + }, + "input_option_label": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The label options for the user interface URL.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "supported_authorization_subjects": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of supported authorization subjects.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "attributes": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The list of supported authorization subject properties.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name of the service.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The type of the service.", + }, + }, + }, + }, + "roles": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of roles for authorization.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "supported_roles": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of roles that you can use to assign access.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The value belonging to the key.", + }, + "description": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The description for the object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The fallback string for the description object.", + }, + "en": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "English.", + }, + "de": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "German.", + }, + "es": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Spanish.", + }, + "fr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "French.", + }, + "it": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Italian.", + }, + "ja": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Japanese.", + }, + "ko": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Korean.", + }, + "pt_br": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Portuguese (Brazil).", + }, + "zh_tw": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Traditional Chinese.", + }, + "zh_cn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Simplified Chinese.", + }, + }, + }, + }, + "display_name": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The display name of the object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The fallback string for the description object.", + }, + "en": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "English.", + }, + "de": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "German.", + }, + "es": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Spanish.", + }, + "fr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "French.", + }, + "it": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Italian.", + }, + "ja": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Japanese.", + }, + "ko": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Korean.", + }, + "pt_br": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Portuguese (Brazil).", + }, + "zh_tw": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Traditional Chinese.", + }, + "zh_cn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Simplified Chinese.", + }, + }, + }, + }, + "options": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The supported role options.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access_policy": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "Optional opt-in to require access control on the role.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "policy_type": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "Optional opt-in to require checking policy type when applying the role.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "account_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Optional opt-in to require checking account type when applying the role.", + }, + }, + }, + }, + }, + }, + }, + "supported_network": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The registration of set of endpoint types that are supported by your service in the `networkType` environment attribute. This constrains the context-based restriction rules specific to the service such that they describe access restrictions on only this set of endpoints.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "environment_attributes": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The environment attribute for support.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name of the key.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of values that belong to the key.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "options": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The list of options for supported networks.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "hidden": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the attribute is hidden or not.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func ResourceIbmOnboardingIamRegistrationValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "product_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9]{32}:o:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, + MinValueLength: 71, + MaxValueLength: 71, + }, + validate.ValidateSchema{ + Identifier: "env", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-z]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexp, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-z0-9\-.]+$`, + }, + validate.ValidateSchema{ + Identifier: "service_type", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Optional: true, + AllowedValues: "platform_service, service", + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_onboarding_iam_registration", Schema: validateSchema} + return &resourceValidator +} + +func resourceIbmOnboardingIamRegistrationCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createIamRegistrationOptions := &partnercentersellv1.CreateIamRegistrationOptions{} + + createIamRegistrationOptions.SetProductID(d.Get("product_id").(string)) + if _, ok := d.GetOk("name"); ok { + createIamRegistrationOptions.SetName(d.Get("name").(string)) + } + if _, ok := d.GetOk("enabled"); ok { + createIamRegistrationOptions.SetEnabled(d.Get("enabled").(bool)) + } + if _, ok := d.GetOk("service_type"); ok { + createIamRegistrationOptions.SetServiceType(d.Get("service_type").(string)) + } + if _, ok := d.GetOk("actions"); ok { + var actions []partnercentersellv1.IamServiceRegistrationAction + for _, v := range d.Get("actions").([]interface{}) { + value := v.(map[string]interface{}) + actionsItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationAction(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "create", "parse-actions").GetDiag() + } + actions = append(actions, *actionsItem) + } + createIamRegistrationOptions.SetActions(actions) + } + if _, ok := d.GetOk("additional_policy_scopes"); ok { + var additionalPolicyScopes []string + for _, v := range d.Get("additional_policy_scopes").([]interface{}) { + additionalPolicyScopesItem := v.(string) + additionalPolicyScopes = append(additionalPolicyScopes, additionalPolicyScopesItem) + } + createIamRegistrationOptions.SetAdditionalPolicyScopes(additionalPolicyScopes) + } + if _, ok := d.GetOk("display_name"); ok { + displayNameModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDisplayNameObject(d.Get("display_name.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "create", "parse-display_name").GetDiag() + } + createIamRegistrationOptions.SetDisplayName(displayNameModel) + } + if _, ok := d.GetOk("parent_ids"); ok { + var parentIds []string + for _, v := range d.Get("parent_ids").([]interface{}) { + parentIdsItem := v.(string) + parentIds = append(parentIds, parentIdsItem) + } + createIamRegistrationOptions.SetParentIds(parentIds) + } + if _, ok := d.GetOk("resource_hierarchy_attribute"); ok { + resourceHierarchyAttributeModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationResourceHierarchyAttribute(d.Get("resource_hierarchy_attribute.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "create", "parse-resource_hierarchy_attribute").GetDiag() + } + createIamRegistrationOptions.SetResourceHierarchyAttribute(resourceHierarchyAttributeModel) + } + if _, ok := d.GetOk("supported_anonymous_accesses"); ok { + var supportedAnonymousAccesses []partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccess + for _, v := range d.Get("supported_anonymous_accesses").([]interface{}) { + value := v.(map[string]interface{}) + supportedAnonymousAccessesItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAnonymousAccess(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "create", "parse-supported_anonymous_accesses").GetDiag() + } + supportedAnonymousAccesses = append(supportedAnonymousAccesses, *supportedAnonymousAccessesItem) + } + createIamRegistrationOptions.SetSupportedAnonymousAccesses(supportedAnonymousAccesses) + } + if _, ok := d.GetOk("supported_attributes"); ok { + var supportedAttributes []partnercentersellv1.IamServiceRegistrationSupportedAttribute + for _, v := range d.Get("supported_attributes").([]interface{}) { + value := v.(map[string]interface{}) + supportedAttributesItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAttribute(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "create", "parse-supported_attributes").GetDiag() + } + supportedAttributes = append(supportedAttributes, *supportedAttributesItem) + } + createIamRegistrationOptions.SetSupportedAttributes(supportedAttributes) + } + if _, ok := d.GetOk("supported_authorization_subjects"); ok { + var supportedAuthorizationSubjects []partnercentersellv1.IamServiceRegistrationSupportedAuthorizationSubject + for _, v := range d.Get("supported_authorization_subjects").([]interface{}) { + value := v.(map[string]interface{}) + supportedAuthorizationSubjectsItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAuthorizationSubject(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "create", "parse-supported_authorization_subjects").GetDiag() + } + supportedAuthorizationSubjects = append(supportedAuthorizationSubjects, *supportedAuthorizationSubjectsItem) + } + createIamRegistrationOptions.SetSupportedAuthorizationSubjects(supportedAuthorizationSubjects) + } + if _, ok := d.GetOk("supported_roles"); ok { + var supportedRoles []partnercentersellv1.IamServiceRegistrationSupportedRole + for _, v := range d.Get("supported_roles").([]interface{}) { + value := v.(map[string]interface{}) + supportedRolesItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedRole(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "create", "parse-supported_roles").GetDiag() + } + supportedRoles = append(supportedRoles, *supportedRolesItem) + } + createIamRegistrationOptions.SetSupportedRoles(supportedRoles) + } + if _, ok := d.GetOk("supported_network"); ok { + supportedNetworkModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedNetwork(d.Get("supported_network.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "create", "parse-supported_network").GetDiag() + } + createIamRegistrationOptions.SetSupportedNetwork(supportedNetworkModel) + } + if _, ok := d.GetOk("env"); ok { + createIamRegistrationOptions.SetEnv(d.Get("env").(string)) + } + + iamServiceRegistration, _, err := partnerCenterSellClient.CreateIamRegistrationWithContext(context, createIamRegistrationOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateIamRegistrationWithContext failed: %s", err.Error()), "ibm_onboarding_iam_registration", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s", *createIamRegistrationOptions.ProductID, *iamServiceRegistration.Name)) + + return resourceIbmOnboardingIamRegistrationRead(context, d, meta) +} + +func resourceIbmOnboardingIamRegistrationRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getIamRegistrationOptions := &partnercentersellv1.GetIamRegistrationOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "sep-id-parts").GetDiag() + } + + getIamRegistrationOptions.SetProductID(parts[0]) + getIamRegistrationOptions.SetProgrammaticName(parts[1]) + if _, ok := d.GetOk("env"); ok { + getIamRegistrationOptions.SetEnv(d.Get("env").(string)) + } + + iamServiceRegistration, response, err := partnerCenterSellClient.GetIamRegistrationWithContext(context, getIamRegistrationOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetIamRegistrationWithContext failed: %s", err.Error()), "ibm_onboarding_iam_registration", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if !core.IsNil(iamServiceRegistration.Name) { + if err = d.Set("name", iamServiceRegistration.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-name").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.Enabled) { + if err = d.Set("enabled", iamServiceRegistration.Enabled); err != nil { + err = fmt.Errorf("Error setting enabled: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-enabled").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.ServiceType) { + if err = d.Set("service_type", iamServiceRegistration.ServiceType); err != nil { + err = fmt.Errorf("Error setting service_type: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-service_type").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.Actions) { + actions := []map[string]interface{}{} + for _, actionsItem := range iamServiceRegistration.Actions { + actionsItemMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionToMap(&actionsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "actions-to-map").GetDiag() + } + actions = append(actions, actionsItemMap) + } + if err = d.Set("actions", actions); err != nil { + err = fmt.Errorf("Error setting actions: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-actions").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.AdditionalPolicyScopes) { + if err = d.Set("additional_policy_scopes", iamServiceRegistration.AdditionalPolicyScopes); err != nil { + err = fmt.Errorf("Error setting additional_policy_scopes: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-additional_policy_scopes").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.DisplayName) { + displayNameMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectToMap(iamServiceRegistration.DisplayName) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "display_name-to-map").GetDiag() + } + if err = d.Set("display_name", []map[string]interface{}{displayNameMap}); err != nil { + err = fmt.Errorf("Error setting display_name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-display_name").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.ParentIds) { + if err = d.Set("parent_ids", iamServiceRegistration.ParentIds); err != nil { + err = fmt.Errorf("Error setting parent_ids: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-parent_ids").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.ResourceHierarchyAttribute) { + resourceHierarchyAttributeMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationResourceHierarchyAttributeToMap(iamServiceRegistration.ResourceHierarchyAttribute) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "resource_hierarchy_attribute-to-map").GetDiag() + } + if err = d.Set("resource_hierarchy_attribute", []map[string]interface{}{resourceHierarchyAttributeMap}); err != nil { + err = fmt.Errorf("Error setting resource_hierarchy_attribute: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-resource_hierarchy_attribute").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.SupportedAnonymousAccesses) { + supportedAnonymousAccesses := []map[string]interface{}{} + for _, supportedAnonymousAccessesItem := range iamServiceRegistration.SupportedAnonymousAccesses { + supportedAnonymousAccessesItemMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessToMap(&supportedAnonymousAccessesItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "supported_anonymous_accesses-to-map").GetDiag() + } + supportedAnonymousAccesses = append(supportedAnonymousAccesses, supportedAnonymousAccessesItemMap) + } + if err = d.Set("supported_anonymous_accesses", supportedAnonymousAccesses); err != nil { + err = fmt.Errorf("Error setting supported_anonymous_accesses: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-supported_anonymous_accesses").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.SupportedAttributes) { + supportedAttributes := []map[string]interface{}{} + for _, supportedAttributesItem := range iamServiceRegistration.SupportedAttributes { + supportedAttributesItemMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAttributeToMap(&supportedAttributesItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "supported_attributes-to-map").GetDiag() + } + supportedAttributes = append(supportedAttributes, supportedAttributesItemMap) + } + if err = d.Set("supported_attributes", supportedAttributes); err != nil { + err = fmt.Errorf("Error setting supported_attributes: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-supported_attributes").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.SupportedAuthorizationSubjects) { + supportedAuthorizationSubjects := []map[string]interface{}{} + for _, supportedAuthorizationSubjectsItem := range iamServiceRegistration.SupportedAuthorizationSubjects { + supportedAuthorizationSubjectsItemMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAuthorizationSubjectToMap(&supportedAuthorizationSubjectsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "supported_authorization_subjects-to-map").GetDiag() + } + supportedAuthorizationSubjects = append(supportedAuthorizationSubjects, supportedAuthorizationSubjectsItemMap) + } + if err = d.Set("supported_authorization_subjects", supportedAuthorizationSubjects); err != nil { + err = fmt.Errorf("Error setting supported_authorization_subjects: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-supported_authorization_subjects").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.SupportedRoles) { + supportedRoles := []map[string]interface{}{} + for _, supportedRolesItem := range iamServiceRegistration.SupportedRoles { + supportedRolesItemMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedRoleToMap(&supportedRolesItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "supported_roles-to-map").GetDiag() + } + supportedRoles = append(supportedRoles, supportedRolesItemMap) + } + if err = d.Set("supported_roles", supportedRoles); err != nil { + err = fmt.Errorf("Error setting supported_roles: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-supported_roles").GetDiag() + } + } + if !core.IsNil(iamServiceRegistration.SupportedNetwork) { + supportedNetworkMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedNetworkToMap(iamServiceRegistration.SupportedNetwork) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "supported_network-to-map").GetDiag() + } + if err = d.Set("supported_network", []map[string]interface{}{supportedNetworkMap}); err != nil { + err = fmt.Errorf("Error setting supported_network: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "read", "set-supported_network").GetDiag() + } + } + + return nil +} + +func resourceIbmOnboardingIamRegistrationUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateIamRegistrationOptions := &partnercentersellv1.UpdateIamRegistrationOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "sep-id-parts").GetDiag() + } + + updateIamRegistrationOptions.SetProductID(parts[0]) + updateIamRegistrationOptions.SetProgrammaticName(parts[1]) + if _, ok := d.GetOk("env"); ok { + updateIamRegistrationOptions.SetEnv(d.Get("env").(string)) + } + + hasChange := false + + patchVals := &partnercentersellv1.IamServiceRegistrationPatch{} + if d.HasChange("product_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "product_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_onboarding_iam_registration", "update", "product_id-forces-new").GetDiag() + } + if d.HasChange("enabled") { + newEnabled := d.Get("enabled").(bool) + patchVals.Enabled = &newEnabled + hasChange = true + } + if d.HasChange("service_type") { + newServiceType := d.Get("service_type").(string) + patchVals.ServiceType = &newServiceType + hasChange = true + } + if d.HasChange("actions") { + var actions []partnercentersellv1.IamServiceRegistrationAction + for _, v := range d.Get("actions").([]interface{}) { + value := v.(map[string]interface{}) + actionsItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationAction(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "parse-actions").GetDiag() + } + actions = append(actions, *actionsItem) + } + patchVals.Actions = actions + hasChange = true + } + if d.HasChange("additional_policy_scopes") { + var additionalPolicyScopes []string + for _, v := range d.Get("additional_policy_scopes").([]interface{}) { + additionalPolicyScopesItem := v.(string) + additionalPolicyScopes = append(additionalPolicyScopes, additionalPolicyScopesItem) + } + patchVals.AdditionalPolicyScopes = additionalPolicyScopes + hasChange = true + } + if d.HasChange("display_name") { + displayName, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDisplayNameObject(d.Get("display_name.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "parse-display_name").GetDiag() + } + patchVals.DisplayName = displayName + hasChange = true + } + if d.HasChange("parent_ids") { + var parentIds []string + for _, v := range d.Get("parent_ids").([]interface{}) { + parentIdsItem := v.(string) + parentIds = append(parentIds, parentIdsItem) + } + patchVals.ParentIds = parentIds + hasChange = true + } + if d.HasChange("resource_hierarchy_attribute") { + resourceHierarchyAttribute, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationResourceHierarchyAttribute(d.Get("resource_hierarchy_attribute.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "parse-resource_hierarchy_attribute").GetDiag() + } + patchVals.ResourceHierarchyAttribute = resourceHierarchyAttribute + hasChange = true + } + if d.HasChange("supported_anonymous_accesses") { + var supportedAnonymousAccesses []partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccess + for _, v := range d.Get("supported_anonymous_accesses").([]interface{}) { + value := v.(map[string]interface{}) + supportedAnonymousAccessesItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAnonymousAccess(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "parse-supported_anonymous_accesses").GetDiag() + } + supportedAnonymousAccesses = append(supportedAnonymousAccesses, *supportedAnonymousAccessesItem) + } + patchVals.SupportedAnonymousAccesses = supportedAnonymousAccesses + hasChange = true + } + if d.HasChange("supported_attributes") { + var supportedAttributes []partnercentersellv1.IamServiceRegistrationSupportedAttribute + for _, v := range d.Get("supported_attributes").([]interface{}) { + value := v.(map[string]interface{}) + supportedAttributesItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAttribute(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "parse-supported_attributes").GetDiag() + } + supportedAttributes = append(supportedAttributes, *supportedAttributesItem) + } + patchVals.SupportedAttributes = supportedAttributes + hasChange = true + } + if d.HasChange("supported_authorization_subjects") { + var supportedAuthorizationSubjects []partnercentersellv1.IamServiceRegistrationSupportedAuthorizationSubject + for _, v := range d.Get("supported_authorization_subjects").([]interface{}) { + value := v.(map[string]interface{}) + supportedAuthorizationSubjectsItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAuthorizationSubject(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "parse-supported_authorization_subjects").GetDiag() + } + supportedAuthorizationSubjects = append(supportedAuthorizationSubjects, *supportedAuthorizationSubjectsItem) + } + patchVals.SupportedAuthorizationSubjects = supportedAuthorizationSubjects + hasChange = true + } + if d.HasChange("supported_roles") { + var supportedRoles []partnercentersellv1.IamServiceRegistrationSupportedRole + for _, v := range d.Get("supported_roles").([]interface{}) { + value := v.(map[string]interface{}) + supportedRolesItem, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedRole(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "parse-supported_roles").GetDiag() + } + supportedRoles = append(supportedRoles, *supportedRolesItem) + } + patchVals.SupportedRoles = supportedRoles + hasChange = true + } + if d.HasChange("supported_network") { + supportedNetwork, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedNetwork(d.Get("supported_network.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "update", "parse-supported_network").GetDiag() + } + patchVals.SupportedNetwork = supportedNetwork + hasChange = true + } + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateIamRegistrationOptions.IamRegistrationPatch = ResourceIbmOnboardingIamRegistrationIamServiceRegistrationPatchAsPatch(patchVals, d) + + _, _, err = partnerCenterSellClient.UpdateIamRegistrationWithContext(context, updateIamRegistrationOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateIamRegistrationWithContext failed: %s", err.Error()), "ibm_onboarding_iam_registration", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIbmOnboardingIamRegistrationRead(context, d, meta) +} + +func resourceIbmOnboardingIamRegistrationDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteIamRegistrationOptions := &partnercentersellv1.DeleteIamRegistrationOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_iam_registration", "delete", "sep-id-parts").GetDiag() + } + + deleteIamRegistrationOptions.SetProductID(parts[0]) + deleteIamRegistrationOptions.SetProgrammaticName(parts[1]) + if _, ok := d.GetOk("env"); ok { + deleteIamRegistrationOptions.SetEnv(d.Get("env").(string)) + } + + _, err = partnerCenterSellClient.DeleteIamRegistrationWithContext(context, deleteIamRegistrationOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteIamRegistrationWithContext failed: %s", err.Error()), "ibm_onboarding_iam_registration", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationAction(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationAction, error) { + model := &partnercentersellv1.IamServiceRegistrationAction{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["roles"] != nil { + roles := []string{} + for _, rolesItem := range modelMap["roles"].([]interface{}) { + roles = append(roles, rolesItem.(string)) + } + model.Roles = roles + } + if modelMap["description"] != nil && len(modelMap["description"].([]interface{})) > 0 && modelMap["description"].([]interface{})[0] != nil { + DescriptionModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDescriptionObject(modelMap["description"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Description = DescriptionModel + } + if modelMap["display_name"] != nil && len(modelMap["display_name"].([]interface{})) > 0 && modelMap["display_name"].([]interface{})[0] != nil { + DisplayNameModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDisplayNameObject(modelMap["display_name"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.DisplayName = DisplayNameModel + } + if modelMap["options"] != nil && len(modelMap["options"].([]interface{})) > 0 && modelMap["options"].([]interface{})[0] != nil { + OptionsModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationActionOptions(modelMap["options"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Options = OptionsModel + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDescriptionObject(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationDescriptionObject, error) { + model := &partnercentersellv1.IamServiceRegistrationDescriptionObject{} + if modelMap["default"] != nil && modelMap["default"].(string) != "" { + model.Default = core.StringPtr(modelMap["default"].(string)) + } + if modelMap["en"] != nil && modelMap["en"].(string) != "" { + model.En = core.StringPtr(modelMap["en"].(string)) + } + if modelMap["de"] != nil && modelMap["de"].(string) != "" { + model.De = core.StringPtr(modelMap["de"].(string)) + } + if modelMap["es"] != nil && modelMap["es"].(string) != "" { + model.Es = core.StringPtr(modelMap["es"].(string)) + } + if modelMap["fr"] != nil && modelMap["fr"].(string) != "" { + model.Fr = core.StringPtr(modelMap["fr"].(string)) + } + if modelMap["it"] != nil && modelMap["it"].(string) != "" { + model.It = core.StringPtr(modelMap["it"].(string)) + } + if modelMap["ja"] != nil && modelMap["ja"].(string) != "" { + model.Ja = core.StringPtr(modelMap["ja"].(string)) + } + if modelMap["ko"] != nil && modelMap["ko"].(string) != "" { + model.Ko = core.StringPtr(modelMap["ko"].(string)) + } + if modelMap["pt_br"] != nil && modelMap["pt_br"].(string) != "" { + model.PtBr = core.StringPtr(modelMap["pt_br"].(string)) + } + if modelMap["zh_tw"] != nil && modelMap["zh_tw"].(string) != "" { + model.ZhTw = core.StringPtr(modelMap["zh_tw"].(string)) + } + if modelMap["zh_cn"] != nil && modelMap["zh_cn"].(string) != "" { + model.ZhCn = core.StringPtr(modelMap["zh_cn"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDisplayNameObject(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationDisplayNameObject, error) { + model := &partnercentersellv1.IamServiceRegistrationDisplayNameObject{} + if modelMap["default"] != nil && modelMap["default"].(string) != "" { + model.Default = core.StringPtr(modelMap["default"].(string)) + } + if modelMap["en"] != nil && modelMap["en"].(string) != "" { + model.En = core.StringPtr(modelMap["en"].(string)) + } + if modelMap["de"] != nil && modelMap["de"].(string) != "" { + model.De = core.StringPtr(modelMap["de"].(string)) + } + if modelMap["es"] != nil && modelMap["es"].(string) != "" { + model.Es = core.StringPtr(modelMap["es"].(string)) + } + if modelMap["fr"] != nil && modelMap["fr"].(string) != "" { + model.Fr = core.StringPtr(modelMap["fr"].(string)) + } + if modelMap["it"] != nil && modelMap["it"].(string) != "" { + model.It = core.StringPtr(modelMap["it"].(string)) + } + if modelMap["ja"] != nil && modelMap["ja"].(string) != "" { + model.Ja = core.StringPtr(modelMap["ja"].(string)) + } + if modelMap["ko"] != nil && modelMap["ko"].(string) != "" { + model.Ko = core.StringPtr(modelMap["ko"].(string)) + } + if modelMap["pt_br"] != nil && modelMap["pt_br"].(string) != "" { + model.PtBr = core.StringPtr(modelMap["pt_br"].(string)) + } + if modelMap["zh_tw"] != nil && modelMap["zh_tw"].(string) != "" { + model.ZhTw = core.StringPtr(modelMap["zh_tw"].(string)) + } + if modelMap["zh_cn"] != nil && modelMap["zh_cn"].(string) != "" { + model.ZhCn = core.StringPtr(modelMap["zh_cn"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationActionOptions(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationActionOptions, error) { + model := &partnercentersellv1.IamServiceRegistrationActionOptions{} + if modelMap["hidden"] != nil { + model.Hidden = core.BoolPtr(modelMap["hidden"].(bool)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationResourceHierarchyAttribute(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationResourceHierarchyAttribute, error) { + model := &partnercentersellv1.IamServiceRegistrationResourceHierarchyAttribute{} + if modelMap["key"] != nil && modelMap["key"].(string) != "" { + model.Key = core.StringPtr(modelMap["key"].(string)) + } + if modelMap["value"] != nil && modelMap["value"].(string) != "" { + model.Value = core.StringPtr(modelMap["value"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAnonymousAccess(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccess, error) { + model := &partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccess{} + if modelMap["attributes"] != nil && len(modelMap["attributes"].([]interface{})) > 0 && modelMap["attributes"].([]interface{})[0] != nil { + AttributesModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAnonymousAccessAttributes(modelMap["attributes"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Attributes = AttributesModel + } + if modelMap["roles"] != nil { + roles := []string{} + for _, rolesItem := range modelMap["roles"].([]interface{}) { + roles = append(roles, rolesItem.(string)) + } + model.Roles = roles + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAnonymousAccessAttributes(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccessAttributes, error) { + model := &partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccessAttributes{} + if modelMap["account_id"] != nil && modelMap["account_id"].(string) != "" { + model.AccountID = core.StringPtr(modelMap["account_id"].(string)) + } + if modelMap["service_name"] != nil && modelMap["service_name"].(string) != "" { + model.ServiceName = core.StringPtr(modelMap["service_name"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAttribute(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationSupportedAttribute, error) { + model := &partnercentersellv1.IamServiceRegistrationSupportedAttribute{} + if modelMap["key"] != nil && modelMap["key"].(string) != "" { + model.Key = core.StringPtr(modelMap["key"].(string)) + } + if modelMap["options"] != nil && len(modelMap["options"].([]interface{})) > 0 && modelMap["options"].([]interface{})[0] != nil { + OptionsModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptions(modelMap["options"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Options = OptionsModel + } + if modelMap["display_name"] != nil && len(modelMap["display_name"].([]interface{})) > 0 && modelMap["display_name"].([]interface{})[0] != nil { + DisplayNameModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDisplayNameObject(modelMap["display_name"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.DisplayName = DisplayNameModel + } + if modelMap["description"] != nil && len(modelMap["description"].([]interface{})) > 0 && modelMap["description"].([]interface{})[0] != nil { + DescriptionModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDescriptionObject(modelMap["description"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Description = DescriptionModel + } + if modelMap["ui"] != nil && len(modelMap["ui"].([]interface{})) > 0 && modelMap["ui"].([]interface{})[0] != nil { + UiModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUi(modelMap["ui"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Ui = UiModel + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptions(modelMap map[string]interface{}) (*partnercentersellv1.SupportedAttributesOptions, error) { + model := &partnercentersellv1.SupportedAttributesOptions{} + if modelMap["operators"] != nil { + operators := []string{} + for _, operatorsItem := range modelMap["operators"].([]interface{}) { + operators = append(operators, operatorsItem.(string)) + } + model.Operators = operators + } + if modelMap["hidden"] != nil { + model.Hidden = core.BoolPtr(modelMap["hidden"].(bool)) + } + if modelMap["supported_attributes"] != nil { + supportedAttributes := []string{} + for _, supportedAttributesItem := range modelMap["supported_attributes"].([]interface{}) { + supportedAttributes = append(supportedAttributes, supportedAttributesItem.(string)) + } + model.SupportedAttributes = supportedAttributes + } + if modelMap["policy_types"] != nil { + policyTypes := []string{} + for _, policyTypesItem := range modelMap["policy_types"].([]interface{}) { + policyTypes = append(policyTypes, policyTypesItem.(string)) + } + model.PolicyTypes = policyTypes + } + if modelMap["is_empty_value_supported"] != nil { + model.IsEmptyValueSupported = core.BoolPtr(modelMap["is_empty_value_supported"].(bool)) + } + if modelMap["is_string_exists_false_value_supported"] != nil { + model.IsStringExistsFalseValueSupported = core.BoolPtr(modelMap["is_string_exists_false_value_supported"].(bool)) + } + if modelMap["key"] != nil && modelMap["key"].(string) != "" { + model.Key = core.StringPtr(modelMap["key"].(string)) + } + if modelMap["resource_hierarchy"] != nil && len(modelMap["resource_hierarchy"].([]interface{})) > 0 && modelMap["resource_hierarchy"].([]interface{})[0] != nil { + ResourceHierarchyModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchy(modelMap["resource_hierarchy"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ResourceHierarchy = ResourceHierarchyModel + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchy(modelMap map[string]interface{}) (*partnercentersellv1.SupportedAttributesOptionsResourceHierarchy, error) { + model := &partnercentersellv1.SupportedAttributesOptionsResourceHierarchy{} + if modelMap["key"] != nil && len(modelMap["key"].([]interface{})) > 0 && modelMap["key"].([]interface{})[0] != nil { + KeyModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchyKey(modelMap["key"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Key = KeyModel + } + if modelMap["value"] != nil && len(modelMap["value"].([]interface{})) > 0 && modelMap["value"].([]interface{})[0] != nil { + ValueModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchyValue(modelMap["value"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Value = ValueModel + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchyKey(modelMap map[string]interface{}) (*partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey, error) { + model := &partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey{} + if modelMap["key"] != nil && modelMap["key"].(string) != "" { + model.Key = core.StringPtr(modelMap["key"].(string)) + } + if modelMap["value"] != nil && modelMap["value"].(string) != "" { + model.Value = core.StringPtr(modelMap["value"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchyValue(modelMap map[string]interface{}) (*partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue, error) { + model := &partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue{} + if modelMap["key"] != nil && modelMap["key"].(string) != "" { + model.Key = core.StringPtr(modelMap["key"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUi(modelMap map[string]interface{}) (*partnercentersellv1.SupportedAttributeUi, error) { + model := &partnercentersellv1.SupportedAttributeUi{} + if modelMap["input_type"] != nil && modelMap["input_type"].(string) != "" { + model.InputType = core.StringPtr(modelMap["input_type"].(string)) + } + if modelMap["input_details"] != nil && len(modelMap["input_details"].([]interface{})) > 0 && modelMap["input_details"].([]interface{})[0] != nil { + InputDetailsModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputDetails(modelMap["input_details"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.InputDetails = InputDetailsModel + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputDetails(modelMap map[string]interface{}) (*partnercentersellv1.SupportedAttributeUiInputDetails, error) { + model := &partnercentersellv1.SupportedAttributeUiInputDetails{} + if modelMap["type"] != nil && modelMap["type"].(string) != "" { + model.Type = core.StringPtr(modelMap["type"].(string)) + } + if modelMap["values"] != nil { + values := []partnercentersellv1.SupportedAttributeUiInputValue{} + for _, valuesItem := range modelMap["values"].([]interface{}) { + valuesItemModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputValue(valuesItem.(map[string]interface{})) + if err != nil { + return model, err + } + values = append(values, *valuesItemModel) + } + model.Values = values + } + if modelMap["gst"] != nil && len(modelMap["gst"].([]interface{})) > 0 && modelMap["gst"].([]interface{})[0] != nil { + GstModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputGst(modelMap["gst"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Gst = GstModel + } + if modelMap["url"] != nil && len(modelMap["url"].([]interface{})) > 0 && modelMap["url"].([]interface{})[0] != nil { + URLModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputURL(modelMap["url"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.URL = URLModel + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputValue(modelMap map[string]interface{}) (*partnercentersellv1.SupportedAttributeUiInputValue, error) { + model := &partnercentersellv1.SupportedAttributeUiInputValue{} + if modelMap["value"] != nil && modelMap["value"].(string) != "" { + model.Value = core.StringPtr(modelMap["value"].(string)) + } + if modelMap["display_name"] != nil && len(modelMap["display_name"].([]interface{})) > 0 && modelMap["display_name"].([]interface{})[0] != nil { + DisplayNameModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDisplayNameObject(modelMap["display_name"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.DisplayName = DisplayNameModel + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputGst(modelMap map[string]interface{}) (*partnercentersellv1.SupportedAttributeUiInputGst, error) { + model := &partnercentersellv1.SupportedAttributeUiInputGst{} + if modelMap["query"] != nil && modelMap["query"].(string) != "" { + model.Query = core.StringPtr(modelMap["query"].(string)) + } + if modelMap["value_property_name"] != nil && modelMap["value_property_name"].(string) != "" { + model.ValuePropertyName = core.StringPtr(modelMap["value_property_name"].(string)) + } + if modelMap["label_property_name"] != nil && modelMap["label_property_name"].(string) != "" { + model.LabelPropertyName = core.StringPtr(modelMap["label_property_name"].(string)) + } + if modelMap["input_option_label"] != nil && modelMap["input_option_label"].(string) != "" { + model.InputOptionLabel = core.StringPtr(modelMap["input_option_label"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputURL(modelMap map[string]interface{}) (*partnercentersellv1.SupportedAttributeUiInputURL, error) { + model := &partnercentersellv1.SupportedAttributeUiInputURL{} + if modelMap["url_endpoint"] != nil && modelMap["url_endpoint"].(string) != "" { + model.UrlEndpoint = core.StringPtr(modelMap["url_endpoint"].(string)) + } + if modelMap["input_option_label"] != nil && modelMap["input_option_label"].(string) != "" { + model.InputOptionLabel = core.StringPtr(modelMap["input_option_label"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAuthorizationSubject(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationSupportedAuthorizationSubject, error) { + model := &partnercentersellv1.IamServiceRegistrationSupportedAuthorizationSubject{} + if modelMap["attributes"] != nil && len(modelMap["attributes"].([]interface{})) > 0 && modelMap["attributes"].([]interface{})[0] != nil { + AttributesModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportAuthorizationSubjectAttribute(modelMap["attributes"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Attributes = AttributesModel + } + if modelMap["roles"] != nil { + roles := []string{} + for _, rolesItem := range modelMap["roles"].([]interface{}) { + roles = append(roles, rolesItem.(string)) + } + model.Roles = roles + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportAuthorizationSubjectAttribute(modelMap map[string]interface{}) (*partnercentersellv1.SupportAuthorizationSubjectAttribute, error) { + model := &partnercentersellv1.SupportAuthorizationSubjectAttribute{} + if modelMap["service_name"] != nil && modelMap["service_name"].(string) != "" { + model.ServiceName = core.StringPtr(modelMap["service_name"].(string)) + } + if modelMap["resource_type"] != nil && modelMap["resource_type"].(string) != "" { + model.ResourceType = core.StringPtr(modelMap["resource_type"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedRole(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationSupportedRole, error) { + model := &partnercentersellv1.IamServiceRegistrationSupportedRole{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["description"] != nil && len(modelMap["description"].([]interface{})) > 0 && modelMap["description"].([]interface{})[0] != nil { + DescriptionModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDescriptionObject(modelMap["description"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Description = DescriptionModel + } + if modelMap["display_name"] != nil && len(modelMap["display_name"].([]interface{})) > 0 && modelMap["display_name"].([]interface{})[0] != nil { + DisplayNameModel, err := ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDisplayNameObject(modelMap["display_name"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.DisplayName = DisplayNameModel + } + if modelMap["options"] != nil && len(modelMap["options"].([]interface{})) > 0 && modelMap["options"].([]interface{})[0] != nil { + OptionsModel, err := ResourceIbmOnboardingIamRegistrationMapToSupportedRoleOptions(modelMap["options"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Options = OptionsModel + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToSupportedRoleOptions(modelMap map[string]interface{}) (*partnercentersellv1.SupportedRoleOptions, error) { + model := &partnercentersellv1.SupportedRoleOptions{} + if modelMap["access_policy"] != nil { + model.AccessPolicy = make(map[string]string) + for key, value := range modelMap["access_policy"].(map[string]interface{}) { + if str, ok := value.(string); ok { + model.AccessPolicy[key] = str + } + } + } + if modelMap["policy_type"] != nil { + policyType := []string{} + for _, policyTypeItem := range modelMap["policy_type"].([]interface{}) { + policyType = append(policyType, policyTypeItem.(string)) + } + model.PolicyType = policyType + } + if modelMap["account_type"] != nil && modelMap["account_type"].(string) != "" { + model.AccountType = core.StringPtr(modelMap["account_type"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedNetwork(modelMap map[string]interface{}) (*partnercentersellv1.IamServiceRegistrationSupportedNetwork, error) { + model := &partnercentersellv1.IamServiceRegistrationSupportedNetwork{} + if modelMap["environment_attributes"] != nil { + environmentAttributes := []partnercentersellv1.EnvironmentAttribute{} + for _, environmentAttributesItem := range modelMap["environment_attributes"].([]interface{}) { + environmentAttributesItemModel, err := ResourceIbmOnboardingIamRegistrationMapToEnvironmentAttribute(environmentAttributesItem.(map[string]interface{})) + if err != nil { + return model, err + } + environmentAttributes = append(environmentAttributes, *environmentAttributesItemModel) + } + model.EnvironmentAttributes = environmentAttributes + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToEnvironmentAttribute(modelMap map[string]interface{}) (*partnercentersellv1.EnvironmentAttribute, error) { + model := &partnercentersellv1.EnvironmentAttribute{} + if modelMap["key"] != nil && modelMap["key"].(string) != "" { + model.Key = core.StringPtr(modelMap["key"].(string)) + } + if modelMap["values"] != nil { + values := []string{} + for _, valuesItem := range modelMap["values"].([]interface{}) { + values = append(values, valuesItem.(string)) + } + model.Values = values + } + if modelMap["options"] != nil && len(modelMap["options"].([]interface{})) > 0 && modelMap["options"].([]interface{})[0] != nil { + OptionsModel, err := ResourceIbmOnboardingIamRegistrationMapToEnvironmentAttributeOptions(modelMap["options"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Options = OptionsModel + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationMapToEnvironmentAttributeOptions(modelMap map[string]interface{}) (*partnercentersellv1.EnvironmentAttributeOptions, error) { + model := &partnercentersellv1.EnvironmentAttributeOptions{} + if modelMap["hidden"] != nil { + model.Hidden = core.BoolPtr(modelMap["hidden"].(bool)) + } + return model, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionToMap(model *partnercentersellv1.IamServiceRegistrationAction) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Roles != nil { + modelMap["roles"] = model.Roles + } + if model.Description != nil { + descriptionMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectToMap(model.Description) + if err != nil { + return modelMap, err + } + modelMap["description"] = []map[string]interface{}{descriptionMap} + } + if model.DisplayName != nil { + displayNameMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectToMap(model.DisplayName) + if err != nil { + return modelMap, err + } + modelMap["display_name"] = []map[string]interface{}{displayNameMap} + } + if model.Options != nil { + optionsMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionOptionsToMap(model.Options) + if err != nil { + return modelMap, err + } + modelMap["options"] = []map[string]interface{}{optionsMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectToMap(model *partnercentersellv1.IamServiceRegistrationDescriptionObject) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Default != nil { + modelMap["default"] = *model.Default + } + if model.En != nil { + modelMap["en"] = *model.En + } + if model.De != nil { + modelMap["de"] = *model.De + } + if model.Es != nil { + modelMap["es"] = *model.Es + } + if model.Fr != nil { + modelMap["fr"] = *model.Fr + } + if model.It != nil { + modelMap["it"] = *model.It + } + if model.Ja != nil { + modelMap["ja"] = *model.Ja + } + if model.Ko != nil { + modelMap["ko"] = *model.Ko + } + if model.PtBr != nil { + modelMap["pt_br"] = *model.PtBr + } + if model.ZhTw != nil { + modelMap["zh_tw"] = *model.ZhTw + } + if model.ZhCn != nil { + modelMap["zh_cn"] = *model.ZhCn + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectToMap(model *partnercentersellv1.IamServiceRegistrationDisplayNameObject) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Default != nil { + modelMap["default"] = *model.Default + } + if model.En != nil { + modelMap["en"] = *model.En + } + if model.De != nil { + modelMap["de"] = *model.De + } + if model.Es != nil { + modelMap["es"] = *model.Es + } + if model.Fr != nil { + modelMap["fr"] = *model.Fr + } + if model.It != nil { + modelMap["it"] = *model.It + } + if model.Ja != nil { + modelMap["ja"] = *model.Ja + } + if model.Ko != nil { + modelMap["ko"] = *model.Ko + } + if model.PtBr != nil { + modelMap["pt_br"] = *model.PtBr + } + if model.ZhTw != nil { + modelMap["zh_tw"] = *model.ZhTw + } + if model.ZhCn != nil { + modelMap["zh_cn"] = *model.ZhCn + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionOptionsToMap(model *partnercentersellv1.IamServiceRegistrationActionOptions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Hidden != nil { + modelMap["hidden"] = *model.Hidden + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationResourceHierarchyAttributeToMap(model *partnercentersellv1.IamServiceRegistrationResourceHierarchyAttribute) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Key != nil { + modelMap["key"] = *model.Key + } + if model.Value != nil { + modelMap["value"] = *model.Value + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessToMap(model *partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccess) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Attributes != nil { + attributesMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessAttributesToMap(model.Attributes) + if err != nil { + return modelMap, err + } + modelMap["attributes"] = []map[string]interface{}{attributesMap} + } + if model.Roles != nil { + modelMap["roles"] = model.Roles + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessAttributesToMap(model *partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccessAttributes) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.AccountID != nil { + modelMap["account_id"] = *model.AccountID + } + if model.ServiceName != nil { + modelMap["service_name"] = *model.ServiceName + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAttributeToMap(model *partnercentersellv1.IamServiceRegistrationSupportedAttribute) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Key != nil { + modelMap["key"] = *model.Key + } + if model.Options != nil { + optionsMap, err := ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsToMap(model.Options) + if err != nil { + return modelMap, err + } + modelMap["options"] = []map[string]interface{}{optionsMap} + } + if model.DisplayName != nil { + displayNameMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectToMap(model.DisplayName) + if err != nil { + return modelMap, err + } + modelMap["display_name"] = []map[string]interface{}{displayNameMap} + } + if model.Description != nil { + descriptionMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectToMap(model.Description) + if err != nil { + return modelMap, err + } + modelMap["description"] = []map[string]interface{}{descriptionMap} + } + if model.Ui != nil { + uiMap, err := ResourceIbmOnboardingIamRegistrationSupportedAttributeUiToMap(model.Ui) + if err != nil { + return modelMap, err + } + modelMap["ui"] = []map[string]interface{}{uiMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsToMap(model *partnercentersellv1.SupportedAttributesOptions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Operators != nil { + modelMap["operators"] = model.Operators + } + if model.Hidden != nil { + modelMap["hidden"] = *model.Hidden + } + if model.SupportedAttributes != nil { + modelMap["supported_attributes"] = model.SupportedAttributes + } + if model.PolicyTypes != nil { + modelMap["policy_types"] = model.PolicyTypes + } + if model.IsEmptyValueSupported != nil { + modelMap["is_empty_value_supported"] = *model.IsEmptyValueSupported + } + if model.IsStringExistsFalseValueSupported != nil { + modelMap["is_string_exists_false_value_supported"] = *model.IsStringExistsFalseValueSupported + } + if model.Key != nil { + modelMap["key"] = *model.Key + } + if model.ResourceHierarchy != nil { + resourceHierarchyMap, err := ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyToMap(model.ResourceHierarchy) + if err != nil { + return modelMap, err + } + modelMap["resource_hierarchy"] = []map[string]interface{}{resourceHierarchyMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyToMap(model *partnercentersellv1.SupportedAttributesOptionsResourceHierarchy) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Key != nil { + keyMap, err := ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyKeyToMap(model.Key) + if err != nil { + return modelMap, err + } + modelMap["key"] = []map[string]interface{}{keyMap} + } + if model.Value != nil { + valueMap, err := ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyValueToMap(model.Value) + if err != nil { + return modelMap, err + } + modelMap["value"] = []map[string]interface{}{valueMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyKeyToMap(model *partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Key != nil { + modelMap["key"] = *model.Key + } + if model.Value != nil { + modelMap["value"] = *model.Value + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyValueToMap(model *partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Key != nil { + modelMap["key"] = *model.Key + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiToMap(model *partnercentersellv1.SupportedAttributeUi) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.InputType != nil { + modelMap["input_type"] = *model.InputType + } + if model.InputDetails != nil { + inputDetailsMap, err := ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputDetailsToMap(model.InputDetails) + if err != nil { + return modelMap, err + } + modelMap["input_details"] = []map[string]interface{}{inputDetailsMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputDetailsToMap(model *partnercentersellv1.SupportedAttributeUiInputDetails) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Values != nil { + values := []map[string]interface{}{} + for _, valuesItem := range model.Values { + valuesItemMap, err := ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputValueToMap(&valuesItem) // #nosec G601 + if err != nil { + return modelMap, err + } + values = append(values, valuesItemMap) + } + modelMap["values"] = values + } + if model.Gst != nil { + gstMap, err := ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputGstToMap(model.Gst) + if err != nil { + return modelMap, err + } + modelMap["gst"] = []map[string]interface{}{gstMap} + } + if model.URL != nil { + urlMap, err := ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputURLToMap(model.URL) + if err != nil { + return modelMap, err + } + modelMap["url"] = []map[string]interface{}{urlMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputValueToMap(model *partnercentersellv1.SupportedAttributeUiInputValue) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Value != nil { + modelMap["value"] = *model.Value + } + if model.DisplayName != nil { + displayNameMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectToMap(model.DisplayName) + if err != nil { + return modelMap, err + } + modelMap["display_name"] = []map[string]interface{}{displayNameMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputGstToMap(model *partnercentersellv1.SupportedAttributeUiInputGst) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Query != nil { + modelMap["query"] = *model.Query + } + if model.ValuePropertyName != nil { + modelMap["value_property_name"] = *model.ValuePropertyName + } + if model.LabelPropertyName != nil { + modelMap["label_property_name"] = *model.LabelPropertyName + } + if model.InputOptionLabel != nil { + modelMap["input_option_label"] = *model.InputOptionLabel + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputURLToMap(model *partnercentersellv1.SupportedAttributeUiInputURL) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.UrlEndpoint != nil { + modelMap["url_endpoint"] = *model.UrlEndpoint + } + if model.InputOptionLabel != nil { + modelMap["input_option_label"] = *model.InputOptionLabel + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAuthorizationSubjectToMap(model *partnercentersellv1.IamServiceRegistrationSupportedAuthorizationSubject) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Attributes != nil { + attributesMap, err := ResourceIbmOnboardingIamRegistrationSupportAuthorizationSubjectAttributeToMap(model.Attributes) + if err != nil { + return modelMap, err + } + modelMap["attributes"] = []map[string]interface{}{attributesMap} + } + if model.Roles != nil { + modelMap["roles"] = model.Roles + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportAuthorizationSubjectAttributeToMap(model *partnercentersellv1.SupportAuthorizationSubjectAttribute) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.ServiceName != nil { + modelMap["service_name"] = *model.ServiceName + } + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedRoleToMap(model *partnercentersellv1.IamServiceRegistrationSupportedRole) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Description != nil { + descriptionMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectToMap(model.Description) + if err != nil { + return modelMap, err + } + modelMap["description"] = []map[string]interface{}{descriptionMap} + } + if model.DisplayName != nil { + displayNameMap, err := ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectToMap(model.DisplayName) + if err != nil { + return modelMap, err + } + modelMap["display_name"] = []map[string]interface{}{displayNameMap} + } + if model.Options != nil { + optionsMap, err := ResourceIbmOnboardingIamRegistrationSupportedRoleOptionsToMap(model.Options) + if err != nil { + return modelMap, err + } + modelMap["options"] = []map[string]interface{}{optionsMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationSupportedRoleOptionsToMap(model *partnercentersellv1.SupportedRoleOptions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.AccessPolicy != nil { + accessPolicy := make(map[string]interface{}) + for k, v := range model.AccessPolicy { + accessPolicy[k] = flex.Stringify(v) + } + modelMap["access_policy"] = accessPolicy + } + if model.PolicyType != nil { + modelMap["policy_type"] = model.PolicyType + } + if model.AccountType != nil { + modelMap["account_type"] = *model.AccountType + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedNetworkToMap(model *partnercentersellv1.IamServiceRegistrationSupportedNetwork) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.EnvironmentAttributes != nil { + environmentAttributes := []map[string]interface{}{} + for _, environmentAttributesItem := range model.EnvironmentAttributes { + environmentAttributesItemMap, err := ResourceIbmOnboardingIamRegistrationEnvironmentAttributeToMap(&environmentAttributesItem) // #nosec G601 + if err != nil { + return modelMap, err + } + environmentAttributes = append(environmentAttributes, environmentAttributesItemMap) + } + modelMap["environment_attributes"] = environmentAttributes + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationEnvironmentAttributeToMap(model *partnercentersellv1.EnvironmentAttribute) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Key != nil { + modelMap["key"] = *model.Key + } + if model.Values != nil { + modelMap["values"] = model.Values + } + if model.Options != nil { + optionsMap, err := ResourceIbmOnboardingIamRegistrationEnvironmentAttributeOptionsToMap(model.Options) + if err != nil { + return modelMap, err + } + modelMap["options"] = []map[string]interface{}{optionsMap} + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationEnvironmentAttributeOptionsToMap(model *partnercentersellv1.EnvironmentAttributeOptions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Hidden != nil { + modelMap["hidden"] = *model.Hidden + } + return modelMap, nil +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationPatchAsPatch(patchVals *partnercentersellv1.IamServiceRegistrationPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "enabled" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["enabled"] = nil + } + path = "service_type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["service_type"] = nil + } + path = "actions" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["actions"] = nil + } else if exists && patch["actions"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionAsPatch(patch["actions"].([]interface{})[0].(map[string]interface{}), d) + } + path = "additional_policy_scopes" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["additional_policy_scopes"] = nil + } + path = "display_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["display_name"] = nil + } + path = "parent_ids" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["parent_ids"] = nil + } + path = "resource_hierarchy_attribute" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["resource_hierarchy_attribute"] = nil + } else if exists && patch["resource_hierarchy_attribute"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationResourceHierarchyAttributeAsPatch(patch["resource_hierarchy_attribute"].(map[string]interface{}), d) + } + path = "supported_anonymous_accesses" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["supported_anonymous_accesses"] = nil + } else if exists && patch["supported_anonymous_accesses"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessAsPatch(patch["supported_anonymous_accesses"].([]interface{})[0].(map[string]interface{}), d) + } + path = "supported_attributes" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["supported_attributes"] = nil + } else if exists && patch["supported_attributes"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAttributeAsPatch(patch["supported_attributes"].([]interface{})[0].(map[string]interface{}), d) + } + path = "supported_authorization_subjects" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["supported_authorization_subjects"] = nil + } else if exists && patch["supported_authorization_subjects"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAuthorizationSubjectAsPatch(patch["supported_authorization_subjects"].([]interface{})[0].(map[string]interface{}), d) + } + path = "supported_roles" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["supported_roles"] = nil + } else if exists && patch["supported_roles"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedRoleAsPatch(patch["supported_roles"].([]interface{})[0].(map[string]interface{}), d) + } + path = "supported_network" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["supported_network"] = nil + } else if exists && patch["supported_network"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedNetworkAsPatch(patch["supported_network"].(map[string]interface{}), d) + } + + return patch +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedNetworkAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_network.0.environment_attributes" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["environment_attributes"] = nil + } else if exists && patch["environment_attributes"] != nil { + ResourceIbmOnboardingIamRegistrationEnvironmentAttributeAsPatch(patch["environment_attributes"].([]interface{})[0].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationEnvironmentAttributeAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_network.0.environment_attributes.0.key" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["key"] = nil + } + path = "supported_network.0.environment_attributes.0.values" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["values"] = nil + } + path = "supported_network.0.environment_attributes.0.options" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["options"] = nil + } else if exists && patch["options"] != nil { + ResourceIbmOnboardingIamRegistrationEnvironmentAttributeOptionsAsPatch(patch["options"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationEnvironmentAttributeOptionsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_network.0.environment_attributes.0.options.0.hidden" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["hidden"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedRoleAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_roles.0.id" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["id"] = nil + } + path = "supported_roles.0.description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description"] = nil + } else if exists && patch["description"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectAsPatch(patch["description"].(map[string]interface{}), d) + } + path = "supported_roles.0.display_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["display_name"] = nil + } else if exists && patch["display_name"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectAsPatch(patch["display_name"].(map[string]interface{}), d) + } + path = "supported_roles.0.options" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["options"] = nil + } else if exists && patch["options"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedRoleOptionsAsPatch(patch["options"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedRoleOptionsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_roles.0.options.0.access_policy" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["access_policy"] = nil + } + path = "supported_roles.0.options.0.policy_type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["policy_type"] = nil + } + path = "supported_roles.0.options.0.account_type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["account_type"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAuthorizationSubjectAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_authorization_subjects.0.attributes" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["attributes"] = nil + } else if exists && patch["attributes"] != nil { + ResourceIbmOnboardingIamRegistrationSupportAuthorizationSubjectAttributeAsPatch(patch["attributes"].(map[string]interface{}), d) + } + path = "supported_authorization_subjects.0.roles" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["roles"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationSupportAuthorizationSubjectAttributeAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_authorization_subjects.0.attributes.0.service_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["service_name"] = nil + } + path = "supported_authorization_subjects.0.attributes.0.resource_type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["resource_type"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAttributeAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.key" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["key"] = nil + } + path = "supported_attributes.0.options" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["options"] = nil + } else if exists && patch["options"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsAsPatch(patch["options"].(map[string]interface{}), d) + } + path = "supported_attributes.0.display_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["display_name"] = nil + } else if exists && patch["display_name"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectAsPatch(patch["display_name"].(map[string]interface{}), d) + } + path = "supported_attributes.0.description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description"] = nil + } else if exists && patch["description"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectAsPatch(patch["description"].(map[string]interface{}), d) + } + path = "supported_attributes.0.ui" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["ui"] = nil + } else if exists && patch["ui"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedAttributeUiAsPatch(patch["ui"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.ui.0.input_type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["input_type"] = nil + } + path = "supported_attributes.0.ui.0.input_details" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["input_details"] = nil + } else if exists && patch["input_details"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputDetailsAsPatch(patch["input_details"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputDetailsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.ui.0.input_details.0.type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["type"] = nil + } + path = "supported_attributes.0.ui.0.input_details.0.values" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["values"] = nil + } else if exists && patch["values"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputValueAsPatch(patch["values"].([]interface{})[0].(map[string]interface{}), d) + } + path = "supported_attributes.0.ui.0.input_details.0.gst" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["gst"] = nil + } else if exists && patch["gst"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputGstAsPatch(patch["gst"].(map[string]interface{}), d) + } + path = "supported_attributes.0.ui.0.input_details.0.url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["url"] = nil + } else if exists && patch["url"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputURLAsPatch(patch["url"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputURLAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.ui.0.input_details.0.url.0.url_endpoint" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["url_endpoint"] = nil + } + path = "supported_attributes.0.ui.0.input_details.0.url.0.input_option_label" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["input_option_label"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputGstAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.ui.0.input_details.0.gst.0.query" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["query"] = nil + } + path = "supported_attributes.0.ui.0.input_details.0.gst.0.value_property_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["value_property_name"] = nil + } + path = "supported_attributes.0.ui.0.input_details.0.gst.0.label_property_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["label_property_name"] = nil + } + path = "supported_attributes.0.ui.0.input_details.0.gst.0.input_option_label" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["input_option_label"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputValueAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.ui.0.input_details.0.values.0.value" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["value"] = nil + } + path = "supported_attributes.0.ui.0.input_details.0.values.0.display_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["display_name"] = nil + } else if exists && patch["display_name"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectAsPatch(patch["display_name"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.options.0.operators" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["operators"] = nil + } + path = "supported_attributes.0.options.0.hidden" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["hidden"] = nil + } + path = "supported_attributes.0.options.0.supported_attributes" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["supported_attributes"] = nil + } + path = "supported_attributes.0.options.0.policy_types" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["policy_types"] = nil + } + path = "supported_attributes.0.options.0.is_empty_value_supported" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["is_empty_value_supported"] = nil + } + path = "supported_attributes.0.options.0.is_string_exists_false_value_supported" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["is_string_exists_false_value_supported"] = nil + } + path = "supported_attributes.0.options.0.key" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["key"] = nil + } + path = "supported_attributes.0.options.0.resource_hierarchy" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["resource_hierarchy"] = nil + } else if exists && patch["resource_hierarchy"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyAsPatch(patch["resource_hierarchy"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.options.0.resource_hierarchy.0.key" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["key"] = nil + } else if exists && patch["key"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyKeyAsPatch(patch["key"].(map[string]interface{}), d) + } + path = "supported_attributes.0.options.0.resource_hierarchy.0.value" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["value"] = nil + } else if exists && patch["value"] != nil { + ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyValueAsPatch(patch["value"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyValueAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.options.0.resource_hierarchy.0.value.0.key" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["key"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyKeyAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_attributes.0.options.0.resource_hierarchy.0.key.0.key" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["key"] = nil + } + path = "supported_attributes.0.options.0.resource_hierarchy.0.key.0.value" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["value"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_anonymous_accesses.0.attributes" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["attributes"] = nil + } else if exists && patch["attributes"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessAttributesAsPatch(patch["attributes"].(map[string]interface{}), d) + } + path = "supported_anonymous_accesses.0.roles" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["roles"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessAttributesAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_anonymous_accesses.0.attributes.0.account_id" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["account_id"] = nil + } + path = "supported_anonymous_accesses.0.attributes.0.service_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["service_name"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationResourceHierarchyAttributeAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "resource_hierarchy_attribute.0.key" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["key"] = nil + } + path = "resource_hierarchy_attribute.0.value" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["value"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "actions.0.id" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["id"] = nil + } + path = "actions.0.roles" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["roles"] = nil + } + path = "actions.0.description" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["description"] = nil + } else if exists && patch["description"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectAsPatch(patch["description"].(map[string]interface{}), d) + } + path = "actions.0.display_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["display_name"] = nil + } else if exists && patch["display_name"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectAsPatch(patch["display_name"].(map[string]interface{}), d) + } + path = "actions.0.options" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["options"] = nil + } else if exists && patch["options"] != nil { + ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionOptionsAsPatch(patch["options"].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionOptionsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "actions.0.options.0.hidden" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["hidden"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_roles.0.display_name.0.default" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["default"] = nil + } + path = "supported_roles.0.display_name.0.en" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["en"] = nil + } + path = "supported_roles.0.display_name.0.de" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["de"] = nil + } + path = "supported_roles.0.display_name.0.es" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["es"] = nil + } + path = "supported_roles.0.display_name.0.fr" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["fr"] = nil + } + path = "supported_roles.0.display_name.0.it" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["it"] = nil + } + path = "supported_roles.0.display_name.0.ja" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["ja"] = nil + } + path = "supported_roles.0.display_name.0.ko" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["ko"] = nil + } + path = "supported_roles.0.display_name.0.pt_br" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["pt_br"] = nil + } + path = "supported_roles.0.display_name.0.zh_tw" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["zh_tw"] = nil + } + path = "supported_roles.0.display_name.0.zh_cn" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["zh_cn"] = nil + } +} + +func ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "supported_roles.0.description.0.default" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["default"] = nil + } + path = "supported_roles.0.description.0.en" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["en"] = nil + } + path = "supported_roles.0.description.0.de" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["de"] = nil + } + path = "supported_roles.0.description.0.es" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["es"] = nil + } + path = "supported_roles.0.description.0.fr" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["fr"] = nil + } + path = "supported_roles.0.description.0.it" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["it"] = nil + } + path = "supported_roles.0.description.0.ja" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["ja"] = nil + } + path = "supported_roles.0.description.0.ko" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["ko"] = nil + } + path = "supported_roles.0.description.0.pt_br" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["pt_br"] = nil + } + path = "supported_roles.0.description.0.zh_tw" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["zh_tw"] = nil + } + path = "supported_roles.0.description.0.zh_cn" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["zh_cn"] = nil + } +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_iam_registration_test.go b/ibm/service/partnercentersell/resource_ibm_onboarding_iam_registration_test.go new file mode 100644 index 0000000000..1fc2d5326c --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_iam_registration_test.go @@ -0,0 +1,2290 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package partnercentersell_test + +import ( + "fmt" + "testing" + + "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" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/partnercentersell" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIbmOnboardingIamRegistrationBasic(t *testing.T) { + var conf partnercentersellv1.IamServiceRegistration + productID := acc.PcsOnboardingProductWithCatalogProduct + name := acc.PcsIamServiceRegistrationId + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingIamRegistrationDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingIamRegistrationConfigBasic(productID, name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingIamRegistrationExists("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "product_id", productID), + ), + }, + }, + }) +} + +func TestAccIbmOnboardingIamRegistrationAllArgs(t *testing.T) { + var conf partnercentersellv1.IamServiceRegistration + productID := acc.PcsOnboardingProductWithCatalogProduct + env := "current" + name := acc.PcsIamServiceRegistrationId + roleDisplayName := fmt.Sprintf("random-%d", acctest.RandIntRange(10, 100)) + iamRegistrationRole := fmt.Sprintf("crn:v1:bluemix:public:%s::::serviceRole:%s", acc.PcsIamServiceRegistrationId, roleDisplayName) + enabled := "true" + serviceType := "platform_service" + envUpdate := "current" + nameUpdate := acc.PcsIamServiceRegistrationId + enabledUpdate := "true" + serviceTypeUpdate := "service" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingIamRegistrationDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingIamRegistrationConfig(productID, env, name, enabled, serviceType, iamRegistrationRole, roleDisplayName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingIamRegistrationExists("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "env", env), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "name", name), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "enabled", enabled), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "service_type", serviceType), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingIamRegistrationConfig(productID, envUpdate, nameUpdate, enabledUpdate, serviceTypeUpdate, iamRegistrationRole, roleDisplayName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "product_id", productID), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "env", envUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "name", nameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "enabled", enabledUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_iam_registration.onboarding_iam_registration_instance", "service_type", serviceTypeUpdate), + ), + }, + resource.TestStep{ + ResourceName: "ibm_onboarding_iam_registration.onboarding_iam_registration_instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "env", "product_id", "service_type"}, + }, + }, + }) +} + +func testAccCheckIbmOnboardingIamRegistrationConfigBasic(productID string, name string) string { + return fmt.Sprintf(` + resource "ibm_onboarding_iam_registration" "onboarding_iam_registration_instance" { + product_id = "%s" + name = "%s" + enabled = true + display_name { + default = "%s" + } + } + `, productID, name, name) +} + +func testAccCheckIbmOnboardingIamRegistrationConfig(productID string, env string, name string, enabled string, serviceType string, iamRegistrationRole string, roleDisplayName string) string { + return fmt.Sprintf(` + + resource "ibm_onboarding_iam_registration" "onboarding_iam_registration_instance" { + product_id = "%s" + env = "%s" + name = "%s" + enabled = %s + service_type = "%s" + actions { + id = "id" + roles = [ "%s" ] + description { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + options { + hidden = true + } + } + additional_policy_scopes = ["%s"] + display_name { + default = "%s" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + parent_ids = ["05ca8653-de25-49fa-a14d-aaa5d373bc21"] + supported_attributes { + key = "testString" + options { + operators = [ "stringEquals" ] + hidden = false + policy_types = [ "access" ] + is_empty_value_supported = true + is_string_exists_false_value_supported = true + supported_attributes = [ ] + } + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + description { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + ui { + input_type = "selector" + input_details { + type = "gst" + values { + value = "testString" + display_name { + default = "testString" + en = "testString" + de = "testString" + es = "testString" + fr = "testString" + it = "testString" + ja = "testString" + ko = "testString" + pt_br = "testString" + zh_tw = "testString" + zh_cn = "testString" + } + } + gst { + query = "query" + value_property_name = "teststring" + input_option_label = "{name} - {instance_id}" + } + } + } + } + supported_authorization_subjects { + attributes { + service_name = "testString" + resource_type = "testString" + } + roles = [ "%s" ] + } + supported_roles { + id = "%s" + description { + default = "desc" + } + display_name { + default = "%s" + } + options { + access_policy = { "key" = "inner" } + policy_type = [ "access" ] + } + } + supported_network { + environment_attributes { + key = "networkType" + values = [ "public" ] + options { + hidden = false + } + } + } + } + `, productID, env, name, enabled, serviceType, iamRegistrationRole, name, name, iamRegistrationRole, iamRegistrationRole, roleDisplayName) +} + +func testAccCheckIbmOnboardingIamRegistrationExists(n string, obj partnercentersellv1.IamServiceRegistration) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + + getIamRegistrationOptions := &partnercentersellv1.GetIamRegistrationOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getIamRegistrationOptions.SetProductID(parts[0]) + getIamRegistrationOptions.SetProgrammaticName(parts[1]) + + iamServiceRegistration, _, err := partnerCenterSellClient.GetIamRegistration(getIamRegistrationOptions) + if err != nil { + return err + } + + obj = *iamServiceRegistration + return nil + } +} + +func testAccCheckIbmOnboardingIamRegistrationDestroy(s *terraform.State) error { + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_onboarding_iam_registration" { + continue + } + + getIamRegistrationOptions := &partnercentersellv1.GetIamRegistrationOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getIamRegistrationOptions.SetProductID(parts[0]) + getIamRegistrationOptions.SetProgrammaticName(parts[1]) + + // Try to find the key + _, response, err := partnerCenterSellClient.GetIamRegistration(getIamRegistrationOptions) + + if err == nil { + return fmt.Errorf("onboarding_iam_registration still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for onboarding_iam_registration (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + iamServiceRegistrationDescriptionObjectModel := make(map[string]interface{}) + iamServiceRegistrationDescriptionObjectModel["default"] = "testString" + iamServiceRegistrationDescriptionObjectModel["en"] = "testString" + iamServiceRegistrationDescriptionObjectModel["de"] = "testString" + iamServiceRegistrationDescriptionObjectModel["es"] = "testString" + iamServiceRegistrationDescriptionObjectModel["fr"] = "testString" + iamServiceRegistrationDescriptionObjectModel["it"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ja"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ko"] = "testString" + iamServiceRegistrationDescriptionObjectModel["pt_br"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_cn"] = "testString" + + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + iamServiceRegistrationActionOptionsModel := make(map[string]interface{}) + iamServiceRegistrationActionOptionsModel["hidden"] = true + + model := make(map[string]interface{}) + model["id"] = "testString" + model["roles"] = []string{"testString"} + model["description"] = []map[string]interface{}{iamServiceRegistrationDescriptionObjectModel} + model["display_name"] = []map[string]interface{}{iamServiceRegistrationDisplayNameObjectModel} + model["options"] = []map[string]interface{}{iamServiceRegistrationActionOptionsModel} + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDescriptionObjectModel := new(partnercentersellv1.IamServiceRegistrationDescriptionObject) + iamServiceRegistrationDescriptionObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhCn = core.StringPtr("testString") + + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + iamServiceRegistrationActionOptionsModel := new(partnercentersellv1.IamServiceRegistrationActionOptions) + iamServiceRegistrationActionOptionsModel.Hidden = core.BoolPtr(true) + + model := new(partnercentersellv1.IamServiceRegistrationAction) + model.ID = core.StringPtr("testString") + model.Roles = []string{"testString"} + model.Description = iamServiceRegistrationDescriptionObjectModel + model.DisplayName = iamServiceRegistrationDisplayNameObjectModel + model.Options = iamServiceRegistrationActionOptionsModel + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["default"] = "testString" + model["en"] = "testString" + model["de"] = "testString" + model["es"] = "testString" + model["fr"] = "testString" + model["it"] = "testString" + model["ja"] = "testString" + model["ko"] = "testString" + model["pt_br"] = "testString" + model["zh_tw"] = "testString" + model["zh_cn"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.IamServiceRegistrationDescriptionObject) + model.Default = core.StringPtr("testString") + model.En = core.StringPtr("testString") + model.De = core.StringPtr("testString") + model.Es = core.StringPtr("testString") + model.Fr = core.StringPtr("testString") + model.It = core.StringPtr("testString") + model.Ja = core.StringPtr("testString") + model.Ko = core.StringPtr("testString") + model.PtBr = core.StringPtr("testString") + model.ZhTw = core.StringPtr("testString") + model.ZhCn = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDescriptionObjectToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["default"] = "testString" + model["en"] = "testString" + model["de"] = "testString" + model["es"] = "testString" + model["fr"] = "testString" + model["it"] = "testString" + model["ja"] = "testString" + model["ko"] = "testString" + model["pt_br"] = "testString" + model["zh_tw"] = "testString" + model["zh_cn"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + model.Default = core.StringPtr("testString") + model.En = core.StringPtr("testString") + model.De = core.StringPtr("testString") + model.Es = core.StringPtr("testString") + model.Fr = core.StringPtr("testString") + model.It = core.StringPtr("testString") + model.Ja = core.StringPtr("testString") + model.Ko = core.StringPtr("testString") + model.PtBr = core.StringPtr("testString") + model.ZhTw = core.StringPtr("testString") + model.ZhCn = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationDisplayNameObjectToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionOptionsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["hidden"] = true + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.IamServiceRegistrationActionOptions) + model.Hidden = core.BoolPtr(true) + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationActionOptionsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationResourceHierarchyAttributeToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["key"] = "testString" + model["value"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.IamServiceRegistrationResourceHierarchyAttribute) + model.Key = core.StringPtr("testString") + model.Value = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationResourceHierarchyAttributeToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + iamServiceRegistrationSupportedAnonymousAccessAttributesModel := make(map[string]interface{}) + iamServiceRegistrationSupportedAnonymousAccessAttributesModel["account_id"] = "testString" + iamServiceRegistrationSupportedAnonymousAccessAttributesModel["service_name"] = "testString" + + model := make(map[string]interface{}) + model["attributes"] = []map[string]interface{}{iamServiceRegistrationSupportedAnonymousAccessAttributesModel} + model["roles"] = []string{"testString"} + + assert.Equal(t, result, model) + } + + iamServiceRegistrationSupportedAnonymousAccessAttributesModel := new(partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccessAttributes) + iamServiceRegistrationSupportedAnonymousAccessAttributesModel.AccountID = core.StringPtr("testString") + iamServiceRegistrationSupportedAnonymousAccessAttributesModel.ServiceName = core.StringPtr("testString") + + model := new(partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccess) + model.Attributes = iamServiceRegistrationSupportedAnonymousAccessAttributesModel + model.Roles = []string{"testString"} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessAttributesToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["account_id"] = "testString" + model["service_name"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccessAttributes) + model.AccountID = core.StringPtr("testString") + model.ServiceName = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAnonymousAccessAttributesToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAttributeToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportedAttributesOptionsResourceHierarchyKeyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyKeyModel["key"] = "testString" + supportedAttributesOptionsResourceHierarchyKeyModel["value"] = "testString" + + supportedAttributesOptionsResourceHierarchyValueModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyValueModel["key"] = "testString" + + supportedAttributesOptionsResourceHierarchyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyModel["key"] = []map[string]interface{}{supportedAttributesOptionsResourceHierarchyKeyModel} + supportedAttributesOptionsResourceHierarchyModel["value"] = []map[string]interface{}{supportedAttributesOptionsResourceHierarchyValueModel} + + supportedAttributesOptionsModel := make(map[string]interface{}) + supportedAttributesOptionsModel["operators"] = []string{"stringEquals"} + supportedAttributesOptionsModel["hidden"] = true + supportedAttributesOptionsModel["supported_attributes"] = []string{"testString"} + supportedAttributesOptionsModel["policy_types"] = []string{"access"} + supportedAttributesOptionsModel["is_empty_value_supported"] = true + supportedAttributesOptionsModel["is_string_exists_false_value_supported"] = true + supportedAttributesOptionsModel["key"] = "testString" + supportedAttributesOptionsModel["resource_hierarchy"] = []map[string]interface{}{supportedAttributesOptionsResourceHierarchyModel} + + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + iamServiceRegistrationDescriptionObjectModel := make(map[string]interface{}) + iamServiceRegistrationDescriptionObjectModel["default"] = "testString" + iamServiceRegistrationDescriptionObjectModel["en"] = "testString" + iamServiceRegistrationDescriptionObjectModel["de"] = "testString" + iamServiceRegistrationDescriptionObjectModel["es"] = "testString" + iamServiceRegistrationDescriptionObjectModel["fr"] = "testString" + iamServiceRegistrationDescriptionObjectModel["it"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ja"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ko"] = "testString" + iamServiceRegistrationDescriptionObjectModel["pt_br"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_cn"] = "testString" + + supportedAttributeUiInputValueModel := make(map[string]interface{}) + supportedAttributeUiInputValueModel["value"] = "testString" + supportedAttributeUiInputValueModel["display_name"] = []map[string]interface{}{iamServiceRegistrationDisplayNameObjectModel} + + supportedAttributeUiInputGstModel := make(map[string]interface{}) + supportedAttributeUiInputGstModel["query"] = "testString" + supportedAttributeUiInputGstModel["value_property_name"] = "testString" + supportedAttributeUiInputGstModel["label_property_name"] = "testString" + supportedAttributeUiInputGstModel["input_option_label"] = "testString" + + supportedAttributeUiInputUrlModel := make(map[string]interface{}) + supportedAttributeUiInputUrlModel["url_endpoint"] = "testString" + supportedAttributeUiInputUrlModel["input_option_label"] = "testString" + + supportedAttributeUiInputDetailsModel := make(map[string]interface{}) + supportedAttributeUiInputDetailsModel["type"] = "testString" + supportedAttributeUiInputDetailsModel["values"] = []map[string]interface{}{supportedAttributeUiInputValueModel} + supportedAttributeUiInputDetailsModel["gst"] = []map[string]interface{}{supportedAttributeUiInputGstModel} + supportedAttributeUiInputDetailsModel["url"] = []map[string]interface{}{supportedAttributeUiInputUrlModel} + + supportedAttributeUiModel := make(map[string]interface{}) + supportedAttributeUiModel["input_type"] = "testString" + supportedAttributeUiModel["input_details"] = []map[string]interface{}{supportedAttributeUiInputDetailsModel} + + model := make(map[string]interface{}) + model["key"] = "testString" + model["options"] = []map[string]interface{}{supportedAttributesOptionsModel} + model["display_name"] = []map[string]interface{}{iamServiceRegistrationDisplayNameObjectModel} + model["description"] = []map[string]interface{}{iamServiceRegistrationDescriptionObjectModel} + model["ui"] = []map[string]interface{}{supportedAttributeUiModel} + + assert.Equal(t, result, model) + } + + supportedAttributesOptionsResourceHierarchyKeyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) + supportedAttributesOptionsResourceHierarchyKeyModel.Key = core.StringPtr("testString") + supportedAttributesOptionsResourceHierarchyKeyModel.Value = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyValueModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) + supportedAttributesOptionsResourceHierarchyValueModel.Key = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchy) + supportedAttributesOptionsResourceHierarchyModel.Key = supportedAttributesOptionsResourceHierarchyKeyModel + supportedAttributesOptionsResourceHierarchyModel.Value = supportedAttributesOptionsResourceHierarchyValueModel + + supportedAttributesOptionsModel := new(partnercentersellv1.SupportedAttributesOptions) + supportedAttributesOptionsModel.Operators = []string{"stringEquals"} + supportedAttributesOptionsModel.Hidden = core.BoolPtr(true) + supportedAttributesOptionsModel.SupportedAttributes = []string{"testString"} + supportedAttributesOptionsModel.PolicyTypes = []string{"access"} + supportedAttributesOptionsModel.IsEmptyValueSupported = core.BoolPtr(true) + supportedAttributesOptionsModel.IsStringExistsFalseValueSupported = core.BoolPtr(true) + supportedAttributesOptionsModel.Key = core.StringPtr("testString") + supportedAttributesOptionsModel.ResourceHierarchy = supportedAttributesOptionsResourceHierarchyModel + + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + iamServiceRegistrationDescriptionObjectModel := new(partnercentersellv1.IamServiceRegistrationDescriptionObject) + iamServiceRegistrationDescriptionObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhCn = core.StringPtr("testString") + + supportedAttributeUiInputValueModel := new(partnercentersellv1.SupportedAttributeUiInputValue) + supportedAttributeUiInputValueModel.Value = core.StringPtr("testString") + supportedAttributeUiInputValueModel.DisplayName = iamServiceRegistrationDisplayNameObjectModel + + supportedAttributeUiInputGstModel := new(partnercentersellv1.SupportedAttributeUiInputGst) + supportedAttributeUiInputGstModel.Query = core.StringPtr("testString") + supportedAttributeUiInputGstModel.ValuePropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.LabelPropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputUrlModel := new(partnercentersellv1.SupportedAttributeUiInputURL) + supportedAttributeUiInputUrlModel.UrlEndpoint = core.StringPtr("testString") + supportedAttributeUiInputUrlModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputDetailsModel := new(partnercentersellv1.SupportedAttributeUiInputDetails) + supportedAttributeUiInputDetailsModel.Type = core.StringPtr("testString") + supportedAttributeUiInputDetailsModel.Values = []partnercentersellv1.SupportedAttributeUiInputValue{*supportedAttributeUiInputValueModel} + supportedAttributeUiInputDetailsModel.Gst = supportedAttributeUiInputGstModel + supportedAttributeUiInputDetailsModel.URL = supportedAttributeUiInputUrlModel + + supportedAttributeUiModel := new(partnercentersellv1.SupportedAttributeUi) + supportedAttributeUiModel.InputType = core.StringPtr("testString") + supportedAttributeUiModel.InputDetails = supportedAttributeUiInputDetailsModel + + model := new(partnercentersellv1.IamServiceRegistrationSupportedAttribute) + model.Key = core.StringPtr("testString") + model.Options = supportedAttributesOptionsModel + model.DisplayName = iamServiceRegistrationDisplayNameObjectModel + model.Description = iamServiceRegistrationDescriptionObjectModel + model.Ui = supportedAttributeUiModel + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAttributeToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportedAttributesOptionsResourceHierarchyKeyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyKeyModel["key"] = "testString" + supportedAttributesOptionsResourceHierarchyKeyModel["value"] = "testString" + + supportedAttributesOptionsResourceHierarchyValueModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyValueModel["key"] = "testString" + + supportedAttributesOptionsResourceHierarchyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyModel["key"] = []map[string]interface{}{supportedAttributesOptionsResourceHierarchyKeyModel} + supportedAttributesOptionsResourceHierarchyModel["value"] = []map[string]interface{}{supportedAttributesOptionsResourceHierarchyValueModel} + + model := make(map[string]interface{}) + model["operators"] = []string{"stringEquals"} + model["hidden"] = true + model["supported_attributes"] = []string{"testString"} + model["policy_types"] = []string{"access"} + model["is_empty_value_supported"] = true + model["is_string_exists_false_value_supported"] = true + model["key"] = "testString" + model["resource_hierarchy"] = []map[string]interface{}{supportedAttributesOptionsResourceHierarchyModel} + + assert.Equal(t, result, model) + } + + supportedAttributesOptionsResourceHierarchyKeyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) + supportedAttributesOptionsResourceHierarchyKeyModel.Key = core.StringPtr("testString") + supportedAttributesOptionsResourceHierarchyKeyModel.Value = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyValueModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) + supportedAttributesOptionsResourceHierarchyValueModel.Key = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchy) + supportedAttributesOptionsResourceHierarchyModel.Key = supportedAttributesOptionsResourceHierarchyKeyModel + supportedAttributesOptionsResourceHierarchyModel.Value = supportedAttributesOptionsResourceHierarchyValueModel + + model := new(partnercentersellv1.SupportedAttributesOptions) + model.Operators = []string{"stringEquals"} + model.Hidden = core.BoolPtr(true) + model.SupportedAttributes = []string{"testString"} + model.PolicyTypes = []string{"access"} + model.IsEmptyValueSupported = core.BoolPtr(true) + model.IsStringExistsFalseValueSupported = core.BoolPtr(true) + model.Key = core.StringPtr("testString") + model.ResourceHierarchy = supportedAttributesOptionsResourceHierarchyModel + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportedAttributesOptionsResourceHierarchyKeyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyKeyModel["key"] = "testString" + supportedAttributesOptionsResourceHierarchyKeyModel["value"] = "testString" + + supportedAttributesOptionsResourceHierarchyValueModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyValueModel["key"] = "testString" + + model := make(map[string]interface{}) + model["key"] = []map[string]interface{}{supportedAttributesOptionsResourceHierarchyKeyModel} + model["value"] = []map[string]interface{}{supportedAttributesOptionsResourceHierarchyValueModel} + + assert.Equal(t, result, model) + } + + supportedAttributesOptionsResourceHierarchyKeyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) + supportedAttributesOptionsResourceHierarchyKeyModel.Key = core.StringPtr("testString") + supportedAttributesOptionsResourceHierarchyKeyModel.Value = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyValueModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) + supportedAttributesOptionsResourceHierarchyValueModel.Key = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchy) + model.Key = supportedAttributesOptionsResourceHierarchyKeyModel + model.Value = supportedAttributesOptionsResourceHierarchyValueModel + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyKeyToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["key"] = "testString" + model["value"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) + model.Key = core.StringPtr("testString") + model.Value = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyKeyToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyValueToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["key"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) + model.Key = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedAttributesOptionsResourceHierarchyValueToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedAttributeUiToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + supportedAttributeUiInputValueModel := make(map[string]interface{}) + supportedAttributeUiInputValueModel["value"] = "testString" + supportedAttributeUiInputValueModel["display_name"] = []map[string]interface{}{iamServiceRegistrationDisplayNameObjectModel} + + supportedAttributeUiInputGstModel := make(map[string]interface{}) + supportedAttributeUiInputGstModel["query"] = "testString" + supportedAttributeUiInputGstModel["value_property_name"] = "testString" + supportedAttributeUiInputGstModel["label_property_name"] = "testString" + supportedAttributeUiInputGstModel["input_option_label"] = "testString" + + supportedAttributeUiInputUrlModel := make(map[string]interface{}) + supportedAttributeUiInputUrlModel["url_endpoint"] = "testString" + supportedAttributeUiInputUrlModel["input_option_label"] = "testString" + + supportedAttributeUiInputDetailsModel := make(map[string]interface{}) + supportedAttributeUiInputDetailsModel["type"] = "testString" + supportedAttributeUiInputDetailsModel["values"] = []map[string]interface{}{supportedAttributeUiInputValueModel} + supportedAttributeUiInputDetailsModel["gst"] = []map[string]interface{}{supportedAttributeUiInputGstModel} + supportedAttributeUiInputDetailsModel["url"] = []map[string]interface{}{supportedAttributeUiInputUrlModel} + + model := make(map[string]interface{}) + model["input_type"] = "testString" + model["input_details"] = []map[string]interface{}{supportedAttributeUiInputDetailsModel} + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + supportedAttributeUiInputValueModel := new(partnercentersellv1.SupportedAttributeUiInputValue) + supportedAttributeUiInputValueModel.Value = core.StringPtr("testString") + supportedAttributeUiInputValueModel.DisplayName = iamServiceRegistrationDisplayNameObjectModel + + supportedAttributeUiInputGstModel := new(partnercentersellv1.SupportedAttributeUiInputGst) + supportedAttributeUiInputGstModel.Query = core.StringPtr("testString") + supportedAttributeUiInputGstModel.ValuePropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.LabelPropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputUrlModel := new(partnercentersellv1.SupportedAttributeUiInputURL) + supportedAttributeUiInputUrlModel.UrlEndpoint = core.StringPtr("testString") + supportedAttributeUiInputUrlModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputDetailsModel := new(partnercentersellv1.SupportedAttributeUiInputDetails) + supportedAttributeUiInputDetailsModel.Type = core.StringPtr("testString") + supportedAttributeUiInputDetailsModel.Values = []partnercentersellv1.SupportedAttributeUiInputValue{*supportedAttributeUiInputValueModel} + supportedAttributeUiInputDetailsModel.Gst = supportedAttributeUiInputGstModel + supportedAttributeUiInputDetailsModel.URL = supportedAttributeUiInputUrlModel + + model := new(partnercentersellv1.SupportedAttributeUi) + model.InputType = core.StringPtr("testString") + model.InputDetails = supportedAttributeUiInputDetailsModel + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedAttributeUiToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputDetailsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + supportedAttributeUiInputValueModel := make(map[string]interface{}) + supportedAttributeUiInputValueModel["value"] = "testString" + supportedAttributeUiInputValueModel["display_name"] = []map[string]interface{}{iamServiceRegistrationDisplayNameObjectModel} + + supportedAttributeUiInputGstModel := make(map[string]interface{}) + supportedAttributeUiInputGstModel["query"] = "testString" + supportedAttributeUiInputGstModel["value_property_name"] = "testString" + supportedAttributeUiInputGstModel["label_property_name"] = "testString" + supportedAttributeUiInputGstModel["input_option_label"] = "testString" + + supportedAttributeUiInputUrlModel := make(map[string]interface{}) + supportedAttributeUiInputUrlModel["url_endpoint"] = "testString" + supportedAttributeUiInputUrlModel["input_option_label"] = "testString" + + model := make(map[string]interface{}) + model["type"] = "testString" + model["values"] = []map[string]interface{}{supportedAttributeUiInputValueModel} + model["gst"] = []map[string]interface{}{supportedAttributeUiInputGstModel} + model["url"] = []map[string]interface{}{supportedAttributeUiInputUrlModel} + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + supportedAttributeUiInputValueModel := new(partnercentersellv1.SupportedAttributeUiInputValue) + supportedAttributeUiInputValueModel.Value = core.StringPtr("testString") + supportedAttributeUiInputValueModel.DisplayName = iamServiceRegistrationDisplayNameObjectModel + + supportedAttributeUiInputGstModel := new(partnercentersellv1.SupportedAttributeUiInputGst) + supportedAttributeUiInputGstModel.Query = core.StringPtr("testString") + supportedAttributeUiInputGstModel.ValuePropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.LabelPropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputUrlModel := new(partnercentersellv1.SupportedAttributeUiInputURL) + supportedAttributeUiInputUrlModel.UrlEndpoint = core.StringPtr("testString") + supportedAttributeUiInputUrlModel.InputOptionLabel = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportedAttributeUiInputDetails) + model.Type = core.StringPtr("testString") + model.Values = []partnercentersellv1.SupportedAttributeUiInputValue{*supportedAttributeUiInputValueModel} + model.Gst = supportedAttributeUiInputGstModel + model.URL = supportedAttributeUiInputUrlModel + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputDetailsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputValueToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + model := make(map[string]interface{}) + model["value"] = "testString" + model["display_name"] = []map[string]interface{}{iamServiceRegistrationDisplayNameObjectModel} + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportedAttributeUiInputValue) + model.Value = core.StringPtr("testString") + model.DisplayName = iamServiceRegistrationDisplayNameObjectModel + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputValueToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputGstToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["query"] = "testString" + model["value_property_name"] = "testString" + model["label_property_name"] = "testString" + model["input_option_label"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.SupportedAttributeUiInputGst) + model.Query = core.StringPtr("testString") + model.ValuePropertyName = core.StringPtr("testString") + model.LabelPropertyName = core.StringPtr("testString") + model.InputOptionLabel = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputGstToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputURLToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["url_endpoint"] = "testString" + model["input_option_label"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.SupportedAttributeUiInputURL) + model.UrlEndpoint = core.StringPtr("testString") + model.InputOptionLabel = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedAttributeUiInputURLToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAuthorizationSubjectToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + supportAuthorizationSubjectAttributeModel := make(map[string]interface{}) + supportAuthorizationSubjectAttributeModel["service_name"] = "testString" + supportAuthorizationSubjectAttributeModel["resource_type"] = "testString" + + model := make(map[string]interface{}) + model["attributes"] = []map[string]interface{}{supportAuthorizationSubjectAttributeModel} + model["roles"] = []string{"testString"} + + assert.Equal(t, result, model) + } + + supportAuthorizationSubjectAttributeModel := new(partnercentersellv1.SupportAuthorizationSubjectAttribute) + supportAuthorizationSubjectAttributeModel.ServiceName = core.StringPtr("testString") + supportAuthorizationSubjectAttributeModel.ResourceType = core.StringPtr("testString") + + model := new(partnercentersellv1.IamServiceRegistrationSupportedAuthorizationSubject) + model.Attributes = supportAuthorizationSubjectAttributeModel + model.Roles = []string{"testString"} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedAuthorizationSubjectToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportAuthorizationSubjectAttributeToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["service_name"] = "testString" + model["resource_type"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.SupportAuthorizationSubjectAttribute) + model.ServiceName = core.StringPtr("testString") + model.ResourceType = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportAuthorizationSubjectAttributeToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedRoleToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + iamServiceRegistrationDescriptionObjectModel := make(map[string]interface{}) + iamServiceRegistrationDescriptionObjectModel["default"] = "testString" + iamServiceRegistrationDescriptionObjectModel["en"] = "testString" + iamServiceRegistrationDescriptionObjectModel["de"] = "testString" + iamServiceRegistrationDescriptionObjectModel["es"] = "testString" + iamServiceRegistrationDescriptionObjectModel["fr"] = "testString" + iamServiceRegistrationDescriptionObjectModel["it"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ja"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ko"] = "testString" + iamServiceRegistrationDescriptionObjectModel["pt_br"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_cn"] = "testString" + + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + supportedRoleOptionsModel := make(map[string]interface{}) + supportedRoleOptionsModel["access_policy"] = map[string]interface{}{"key1": "testString"} + supportedRoleOptionsModel["policy_type"] = []string{"access"} + supportedRoleOptionsModel["account_type"] = "enterprise" + + model := make(map[string]interface{}) + model["id"] = "testString" + model["description"] = []map[string]interface{}{iamServiceRegistrationDescriptionObjectModel} + model["display_name"] = []map[string]interface{}{iamServiceRegistrationDisplayNameObjectModel} + model["options"] = []map[string]interface{}{supportedRoleOptionsModel} + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDescriptionObjectModel := new(partnercentersellv1.IamServiceRegistrationDescriptionObject) + iamServiceRegistrationDescriptionObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhCn = core.StringPtr("testString") + + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + supportedRoleOptionsModel := new(partnercentersellv1.SupportedRoleOptions) + supportedRoleOptionsModel.AccessPolicy = map[string]string{"key1": "testString"} + supportedRoleOptionsModel.PolicyType = []string{"access"} + supportedRoleOptionsModel.AccountType = core.StringPtr("enterprise") + + model := new(partnercentersellv1.IamServiceRegistrationSupportedRole) + model.ID = core.StringPtr("testString") + model.Description = iamServiceRegistrationDescriptionObjectModel + model.DisplayName = iamServiceRegistrationDisplayNameObjectModel + model.Options = supportedRoleOptionsModel + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedRoleToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationSupportedRoleOptionsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["access_policy"] = map[string]interface{}{"key1": "testString"} + model["policy_type"] = []string{"access"} + model["account_type"] = "enterprise" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.SupportedRoleOptions) + model.AccessPolicy = map[string]string{"key1": "testString"} + model.PolicyType = []string{"access"} + model.AccountType = core.StringPtr("enterprise") + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationSupportedRoleOptionsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedNetworkToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + environmentAttributeOptionsModel := make(map[string]interface{}) + environmentAttributeOptionsModel["hidden"] = true + + environmentAttributeModel := make(map[string]interface{}) + environmentAttributeModel["key"] = "testString" + environmentAttributeModel["values"] = []string{"testString"} + environmentAttributeModel["options"] = []map[string]interface{}{environmentAttributeOptionsModel} + + model := make(map[string]interface{}) + model["environment_attributes"] = []map[string]interface{}{environmentAttributeModel} + + assert.Equal(t, result, model) + } + + environmentAttributeOptionsModel := new(partnercentersellv1.EnvironmentAttributeOptions) + environmentAttributeOptionsModel.Hidden = core.BoolPtr(true) + + environmentAttributeModel := new(partnercentersellv1.EnvironmentAttribute) + environmentAttributeModel.Key = core.StringPtr("testString") + environmentAttributeModel.Values = []string{"testString"} + environmentAttributeModel.Options = environmentAttributeOptionsModel + + model := new(partnercentersellv1.IamServiceRegistrationSupportedNetwork) + model.EnvironmentAttributes = []partnercentersellv1.EnvironmentAttribute{*environmentAttributeModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationIamServiceRegistrationSupportedNetworkToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationEnvironmentAttributeToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + environmentAttributeOptionsModel := make(map[string]interface{}) + environmentAttributeOptionsModel["hidden"] = true + + model := make(map[string]interface{}) + model["key"] = "testString" + model["values"] = []string{"testString"} + model["options"] = []map[string]interface{}{environmentAttributeOptionsModel} + + assert.Equal(t, result, model) + } + + environmentAttributeOptionsModel := new(partnercentersellv1.EnvironmentAttributeOptions) + environmentAttributeOptionsModel.Hidden = core.BoolPtr(true) + + model := new(partnercentersellv1.EnvironmentAttribute) + model.Key = core.StringPtr("testString") + model.Values = []string{"testString"} + model.Options = environmentAttributeOptionsModel + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationEnvironmentAttributeToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationEnvironmentAttributeOptionsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["hidden"] = true + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.EnvironmentAttributeOptions) + model.Hidden = core.BoolPtr(true) + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationEnvironmentAttributeOptionsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationAction(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationAction) { + iamServiceRegistrationDescriptionObjectModel := new(partnercentersellv1.IamServiceRegistrationDescriptionObject) + iamServiceRegistrationDescriptionObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhCn = core.StringPtr("testString") + + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + iamServiceRegistrationActionOptionsModel := new(partnercentersellv1.IamServiceRegistrationActionOptions) + iamServiceRegistrationActionOptionsModel.Hidden = core.BoolPtr(true) + + model := new(partnercentersellv1.IamServiceRegistrationAction) + model.ID = core.StringPtr("testString") + model.Roles = []string{"testString"} + model.Description = iamServiceRegistrationDescriptionObjectModel + model.DisplayName = iamServiceRegistrationDisplayNameObjectModel + model.Options = iamServiceRegistrationActionOptionsModel + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDescriptionObjectModel := make(map[string]interface{}) + iamServiceRegistrationDescriptionObjectModel["default"] = "testString" + iamServiceRegistrationDescriptionObjectModel["en"] = "testString" + iamServiceRegistrationDescriptionObjectModel["de"] = "testString" + iamServiceRegistrationDescriptionObjectModel["es"] = "testString" + iamServiceRegistrationDescriptionObjectModel["fr"] = "testString" + iamServiceRegistrationDescriptionObjectModel["it"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ja"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ko"] = "testString" + iamServiceRegistrationDescriptionObjectModel["pt_br"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_cn"] = "testString" + + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + iamServiceRegistrationActionOptionsModel := make(map[string]interface{}) + iamServiceRegistrationActionOptionsModel["hidden"] = true + + model := make(map[string]interface{}) + model["id"] = "testString" + model["roles"] = []interface{}{"testString"} + model["description"] = []interface{}{iamServiceRegistrationDescriptionObjectModel} + model["display_name"] = []interface{}{iamServiceRegistrationDisplayNameObjectModel} + model["options"] = []interface{}{iamServiceRegistrationActionOptionsModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationAction(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDescriptionObject(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationDescriptionObject) { + model := new(partnercentersellv1.IamServiceRegistrationDescriptionObject) + model.Default = core.StringPtr("testString") + model.En = core.StringPtr("testString") + model.De = core.StringPtr("testString") + model.Es = core.StringPtr("testString") + model.Fr = core.StringPtr("testString") + model.It = core.StringPtr("testString") + model.Ja = core.StringPtr("testString") + model.Ko = core.StringPtr("testString") + model.PtBr = core.StringPtr("testString") + model.ZhTw = core.StringPtr("testString") + model.ZhCn = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["default"] = "testString" + model["en"] = "testString" + model["de"] = "testString" + model["es"] = "testString" + model["fr"] = "testString" + model["it"] = "testString" + model["ja"] = "testString" + model["ko"] = "testString" + model["pt_br"] = "testString" + model["zh_tw"] = "testString" + model["zh_cn"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDescriptionObject(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDisplayNameObject(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationDisplayNameObject) { + model := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + model.Default = core.StringPtr("testString") + model.En = core.StringPtr("testString") + model.De = core.StringPtr("testString") + model.Es = core.StringPtr("testString") + model.Fr = core.StringPtr("testString") + model.It = core.StringPtr("testString") + model.Ja = core.StringPtr("testString") + model.Ko = core.StringPtr("testString") + model.PtBr = core.StringPtr("testString") + model.ZhTw = core.StringPtr("testString") + model.ZhCn = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["default"] = "testString" + model["en"] = "testString" + model["de"] = "testString" + model["es"] = "testString" + model["fr"] = "testString" + model["it"] = "testString" + model["ja"] = "testString" + model["ko"] = "testString" + model["pt_br"] = "testString" + model["zh_tw"] = "testString" + model["zh_cn"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationDisplayNameObject(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationActionOptions(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationActionOptions) { + model := new(partnercentersellv1.IamServiceRegistrationActionOptions) + model.Hidden = core.BoolPtr(true) + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["hidden"] = true + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationActionOptions(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationResourceHierarchyAttribute(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationResourceHierarchyAttribute) { + model := new(partnercentersellv1.IamServiceRegistrationResourceHierarchyAttribute) + model.Key = core.StringPtr("testString") + model.Value = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["key"] = "testString" + model["value"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationResourceHierarchyAttribute(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAnonymousAccess(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccess) { + iamServiceRegistrationSupportedAnonymousAccessAttributesModel := new(partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccessAttributes) + iamServiceRegistrationSupportedAnonymousAccessAttributesModel.AccountID = core.StringPtr("testString") + iamServiceRegistrationSupportedAnonymousAccessAttributesModel.ServiceName = core.StringPtr("testString") + + model := new(partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccess) + model.Attributes = iamServiceRegistrationSupportedAnonymousAccessAttributesModel + model.Roles = []string{"testString"} + + assert.Equal(t, result, model) + } + + iamServiceRegistrationSupportedAnonymousAccessAttributesModel := make(map[string]interface{}) + iamServiceRegistrationSupportedAnonymousAccessAttributesModel["account_id"] = "testString" + iamServiceRegistrationSupportedAnonymousAccessAttributesModel["service_name"] = "testString" + + model := make(map[string]interface{}) + model["attributes"] = []interface{}{iamServiceRegistrationSupportedAnonymousAccessAttributesModel} + model["roles"] = []interface{}{"testString"} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAnonymousAccess(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAnonymousAccessAttributes(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccessAttributes) { + model := new(partnercentersellv1.IamServiceRegistrationSupportedAnonymousAccessAttributes) + model.AccountID = core.StringPtr("testString") + model.ServiceName = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["account_id"] = "testString" + model["service_name"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAnonymousAccessAttributes(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAttribute(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationSupportedAttribute) { + supportedAttributesOptionsResourceHierarchyKeyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) + supportedAttributesOptionsResourceHierarchyKeyModel.Key = core.StringPtr("testString") + supportedAttributesOptionsResourceHierarchyKeyModel.Value = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyValueModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) + supportedAttributesOptionsResourceHierarchyValueModel.Key = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchy) + supportedAttributesOptionsResourceHierarchyModel.Key = supportedAttributesOptionsResourceHierarchyKeyModel + supportedAttributesOptionsResourceHierarchyModel.Value = supportedAttributesOptionsResourceHierarchyValueModel + + supportedAttributesOptionsModel := new(partnercentersellv1.SupportedAttributesOptions) + supportedAttributesOptionsModel.Operators = []string{"stringEquals"} + supportedAttributesOptionsModel.Hidden = core.BoolPtr(true) + supportedAttributesOptionsModel.SupportedAttributes = []string{"testString"} + supportedAttributesOptionsModel.PolicyTypes = []string{"access"} + supportedAttributesOptionsModel.IsEmptyValueSupported = core.BoolPtr(true) + supportedAttributesOptionsModel.IsStringExistsFalseValueSupported = core.BoolPtr(true) + supportedAttributesOptionsModel.Key = core.StringPtr("testString") + supportedAttributesOptionsModel.ResourceHierarchy = supportedAttributesOptionsResourceHierarchyModel + + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + iamServiceRegistrationDescriptionObjectModel := new(partnercentersellv1.IamServiceRegistrationDescriptionObject) + iamServiceRegistrationDescriptionObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhCn = core.StringPtr("testString") + + supportedAttributeUiInputValueModel := new(partnercentersellv1.SupportedAttributeUiInputValue) + supportedAttributeUiInputValueModel.Value = core.StringPtr("testString") + supportedAttributeUiInputValueModel.DisplayName = iamServiceRegistrationDisplayNameObjectModel + + supportedAttributeUiInputGstModel := new(partnercentersellv1.SupportedAttributeUiInputGst) + supportedAttributeUiInputGstModel.Query = core.StringPtr("testString") + supportedAttributeUiInputGstModel.ValuePropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.LabelPropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputUrlModel := new(partnercentersellv1.SupportedAttributeUiInputURL) + supportedAttributeUiInputUrlModel.UrlEndpoint = core.StringPtr("testString") + supportedAttributeUiInputUrlModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputDetailsModel := new(partnercentersellv1.SupportedAttributeUiInputDetails) + supportedAttributeUiInputDetailsModel.Type = core.StringPtr("testString") + supportedAttributeUiInputDetailsModel.Values = []partnercentersellv1.SupportedAttributeUiInputValue{*supportedAttributeUiInputValueModel} + supportedAttributeUiInputDetailsModel.Gst = supportedAttributeUiInputGstModel + supportedAttributeUiInputDetailsModel.URL = supportedAttributeUiInputUrlModel + + supportedAttributeUiModel := new(partnercentersellv1.SupportedAttributeUi) + supportedAttributeUiModel.InputType = core.StringPtr("testString") + supportedAttributeUiModel.InputDetails = supportedAttributeUiInputDetailsModel + + model := new(partnercentersellv1.IamServiceRegistrationSupportedAttribute) + model.Key = core.StringPtr("testString") + model.Options = supportedAttributesOptionsModel + model.DisplayName = iamServiceRegistrationDisplayNameObjectModel + model.Description = iamServiceRegistrationDescriptionObjectModel + model.Ui = supportedAttributeUiModel + + assert.Equal(t, result, model) + } + + supportedAttributesOptionsResourceHierarchyKeyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyKeyModel["key"] = "testString" + supportedAttributesOptionsResourceHierarchyKeyModel["value"] = "testString" + + supportedAttributesOptionsResourceHierarchyValueModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyValueModel["key"] = "testString" + + supportedAttributesOptionsResourceHierarchyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyModel["key"] = []interface{}{supportedAttributesOptionsResourceHierarchyKeyModel} + supportedAttributesOptionsResourceHierarchyModel["value"] = []interface{}{supportedAttributesOptionsResourceHierarchyValueModel} + + supportedAttributesOptionsModel := make(map[string]interface{}) + supportedAttributesOptionsModel["operators"] = []interface{}{"stringEquals"} + supportedAttributesOptionsModel["hidden"] = true + supportedAttributesOptionsModel["supported_attributes"] = []interface{}{"testString"} + supportedAttributesOptionsModel["policy_types"] = []interface{}{"access"} + supportedAttributesOptionsModel["is_empty_value_supported"] = true + supportedAttributesOptionsModel["is_string_exists_false_value_supported"] = true + supportedAttributesOptionsModel["key"] = "testString" + supportedAttributesOptionsModel["resource_hierarchy"] = []interface{}{supportedAttributesOptionsResourceHierarchyModel} + + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + iamServiceRegistrationDescriptionObjectModel := make(map[string]interface{}) + iamServiceRegistrationDescriptionObjectModel["default"] = "testString" + iamServiceRegistrationDescriptionObjectModel["en"] = "testString" + iamServiceRegistrationDescriptionObjectModel["de"] = "testString" + iamServiceRegistrationDescriptionObjectModel["es"] = "testString" + iamServiceRegistrationDescriptionObjectModel["fr"] = "testString" + iamServiceRegistrationDescriptionObjectModel["it"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ja"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ko"] = "testString" + iamServiceRegistrationDescriptionObjectModel["pt_br"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_cn"] = "testString" + + supportedAttributeUiInputValueModel := make(map[string]interface{}) + supportedAttributeUiInputValueModel["value"] = "testString" + supportedAttributeUiInputValueModel["display_name"] = []interface{}{iamServiceRegistrationDisplayNameObjectModel} + + supportedAttributeUiInputGstModel := make(map[string]interface{}) + supportedAttributeUiInputGstModel["query"] = "testString" + supportedAttributeUiInputGstModel["value_property_name"] = "testString" + supportedAttributeUiInputGstModel["label_property_name"] = "testString" + supportedAttributeUiInputGstModel["input_option_label"] = "testString" + + supportedAttributeUiInputUrlModel := make(map[string]interface{}) + supportedAttributeUiInputUrlModel["url_endpoint"] = "testString" + supportedAttributeUiInputUrlModel["input_option_label"] = "testString" + + supportedAttributeUiInputDetailsModel := make(map[string]interface{}) + supportedAttributeUiInputDetailsModel["type"] = "testString" + supportedAttributeUiInputDetailsModel["values"] = []interface{}{supportedAttributeUiInputValueModel} + supportedAttributeUiInputDetailsModel["gst"] = []interface{}{supportedAttributeUiInputGstModel} + supportedAttributeUiInputDetailsModel["url"] = []interface{}{supportedAttributeUiInputUrlModel} + + supportedAttributeUiModel := make(map[string]interface{}) + supportedAttributeUiModel["input_type"] = "testString" + supportedAttributeUiModel["input_details"] = []interface{}{supportedAttributeUiInputDetailsModel} + + model := make(map[string]interface{}) + model["key"] = "testString" + model["options"] = []interface{}{supportedAttributesOptionsModel} + model["display_name"] = []interface{}{iamServiceRegistrationDisplayNameObjectModel} + model["description"] = []interface{}{iamServiceRegistrationDescriptionObjectModel} + model["ui"] = []interface{}{supportedAttributeUiModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAttribute(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptions(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedAttributesOptions) { + supportedAttributesOptionsResourceHierarchyKeyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) + supportedAttributesOptionsResourceHierarchyKeyModel.Key = core.StringPtr("testString") + supportedAttributesOptionsResourceHierarchyKeyModel.Value = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyValueModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) + supportedAttributesOptionsResourceHierarchyValueModel.Key = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchy) + supportedAttributesOptionsResourceHierarchyModel.Key = supportedAttributesOptionsResourceHierarchyKeyModel + supportedAttributesOptionsResourceHierarchyModel.Value = supportedAttributesOptionsResourceHierarchyValueModel + + model := new(partnercentersellv1.SupportedAttributesOptions) + model.Operators = []string{"stringEquals"} + model.Hidden = core.BoolPtr(true) + model.SupportedAttributes = []string{"testString"} + model.PolicyTypes = []string{"access"} + model.IsEmptyValueSupported = core.BoolPtr(true) + model.IsStringExistsFalseValueSupported = core.BoolPtr(true) + model.Key = core.StringPtr("testString") + model.ResourceHierarchy = supportedAttributesOptionsResourceHierarchyModel + + assert.Equal(t, result, model) + } + + supportedAttributesOptionsResourceHierarchyKeyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyKeyModel["key"] = "testString" + supportedAttributesOptionsResourceHierarchyKeyModel["value"] = "testString" + + supportedAttributesOptionsResourceHierarchyValueModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyValueModel["key"] = "testString" + + supportedAttributesOptionsResourceHierarchyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyModel["key"] = []interface{}{supportedAttributesOptionsResourceHierarchyKeyModel} + supportedAttributesOptionsResourceHierarchyModel["value"] = []interface{}{supportedAttributesOptionsResourceHierarchyValueModel} + + model := make(map[string]interface{}) + model["operators"] = []interface{}{"stringEquals"} + model["hidden"] = true + model["supported_attributes"] = []interface{}{"testString"} + model["policy_types"] = []interface{}{"access"} + model["is_empty_value_supported"] = true + model["is_string_exists_false_value_supported"] = true + model["key"] = "testString" + model["resource_hierarchy"] = []interface{}{supportedAttributesOptionsResourceHierarchyModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptions(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchy(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedAttributesOptionsResourceHierarchy) { + supportedAttributesOptionsResourceHierarchyKeyModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) + supportedAttributesOptionsResourceHierarchyKeyModel.Key = core.StringPtr("testString") + supportedAttributesOptionsResourceHierarchyKeyModel.Value = core.StringPtr("testString") + + supportedAttributesOptionsResourceHierarchyValueModel := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) + supportedAttributesOptionsResourceHierarchyValueModel.Key = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchy) + model.Key = supportedAttributesOptionsResourceHierarchyKeyModel + model.Value = supportedAttributesOptionsResourceHierarchyValueModel + + assert.Equal(t, result, model) + } + + supportedAttributesOptionsResourceHierarchyKeyModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyKeyModel["key"] = "testString" + supportedAttributesOptionsResourceHierarchyKeyModel["value"] = "testString" + + supportedAttributesOptionsResourceHierarchyValueModel := make(map[string]interface{}) + supportedAttributesOptionsResourceHierarchyValueModel["key"] = "testString" + + model := make(map[string]interface{}) + model["key"] = []interface{}{supportedAttributesOptionsResourceHierarchyKeyModel} + model["value"] = []interface{}{supportedAttributesOptionsResourceHierarchyValueModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchy(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchyKey(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) { + model := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyKey) + model.Key = core.StringPtr("testString") + model.Value = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["key"] = "testString" + model["value"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchyKey(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchyValue(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) { + model := new(partnercentersellv1.SupportedAttributesOptionsResourceHierarchyValue) + model.Key = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["key"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedAttributesOptionsResourceHierarchyValue(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUi(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedAttributeUi) { + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + supportedAttributeUiInputValueModel := new(partnercentersellv1.SupportedAttributeUiInputValue) + supportedAttributeUiInputValueModel.Value = core.StringPtr("testString") + supportedAttributeUiInputValueModel.DisplayName = iamServiceRegistrationDisplayNameObjectModel + + supportedAttributeUiInputGstModel := new(partnercentersellv1.SupportedAttributeUiInputGst) + supportedAttributeUiInputGstModel.Query = core.StringPtr("testString") + supportedAttributeUiInputGstModel.ValuePropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.LabelPropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputUrlModel := new(partnercentersellv1.SupportedAttributeUiInputURL) + supportedAttributeUiInputUrlModel.UrlEndpoint = core.StringPtr("testString") + supportedAttributeUiInputUrlModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputDetailsModel := new(partnercentersellv1.SupportedAttributeUiInputDetails) + supportedAttributeUiInputDetailsModel.Type = core.StringPtr("testString") + supportedAttributeUiInputDetailsModel.Values = []partnercentersellv1.SupportedAttributeUiInputValue{*supportedAttributeUiInputValueModel} + supportedAttributeUiInputDetailsModel.Gst = supportedAttributeUiInputGstModel + supportedAttributeUiInputDetailsModel.URL = supportedAttributeUiInputUrlModel + + model := new(partnercentersellv1.SupportedAttributeUi) + model.InputType = core.StringPtr("testString") + model.InputDetails = supportedAttributeUiInputDetailsModel + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + supportedAttributeUiInputValueModel := make(map[string]interface{}) + supportedAttributeUiInputValueModel["value"] = "testString" + supportedAttributeUiInputValueModel["display_name"] = []interface{}{iamServiceRegistrationDisplayNameObjectModel} + + supportedAttributeUiInputGstModel := make(map[string]interface{}) + supportedAttributeUiInputGstModel["query"] = "testString" + supportedAttributeUiInputGstModel["value_property_name"] = "testString" + supportedAttributeUiInputGstModel["label_property_name"] = "testString" + supportedAttributeUiInputGstModel["input_option_label"] = "testString" + + supportedAttributeUiInputUrlModel := make(map[string]interface{}) + supportedAttributeUiInputUrlModel["url_endpoint"] = "testString" + supportedAttributeUiInputUrlModel["input_option_label"] = "testString" + + supportedAttributeUiInputDetailsModel := make(map[string]interface{}) + supportedAttributeUiInputDetailsModel["type"] = "testString" + supportedAttributeUiInputDetailsModel["values"] = []interface{}{supportedAttributeUiInputValueModel} + supportedAttributeUiInputDetailsModel["gst"] = []interface{}{supportedAttributeUiInputGstModel} + supportedAttributeUiInputDetailsModel["url"] = []interface{}{supportedAttributeUiInputUrlModel} + + model := make(map[string]interface{}) + model["input_type"] = "testString" + model["input_details"] = []interface{}{supportedAttributeUiInputDetailsModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUi(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputDetails(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedAttributeUiInputDetails) { + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + supportedAttributeUiInputValueModel := new(partnercentersellv1.SupportedAttributeUiInputValue) + supportedAttributeUiInputValueModel.Value = core.StringPtr("testString") + supportedAttributeUiInputValueModel.DisplayName = iamServiceRegistrationDisplayNameObjectModel + + supportedAttributeUiInputGstModel := new(partnercentersellv1.SupportedAttributeUiInputGst) + supportedAttributeUiInputGstModel.Query = core.StringPtr("testString") + supportedAttributeUiInputGstModel.ValuePropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.LabelPropertyName = core.StringPtr("testString") + supportedAttributeUiInputGstModel.InputOptionLabel = core.StringPtr("testString") + + supportedAttributeUiInputUrlModel := new(partnercentersellv1.SupportedAttributeUiInputURL) + supportedAttributeUiInputUrlModel.UrlEndpoint = core.StringPtr("testString") + supportedAttributeUiInputUrlModel.InputOptionLabel = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportedAttributeUiInputDetails) + model.Type = core.StringPtr("testString") + model.Values = []partnercentersellv1.SupportedAttributeUiInputValue{*supportedAttributeUiInputValueModel} + model.Gst = supportedAttributeUiInputGstModel + model.URL = supportedAttributeUiInputUrlModel + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + supportedAttributeUiInputValueModel := make(map[string]interface{}) + supportedAttributeUiInputValueModel["value"] = "testString" + supportedAttributeUiInputValueModel["display_name"] = []interface{}{iamServiceRegistrationDisplayNameObjectModel} + + supportedAttributeUiInputGstModel := make(map[string]interface{}) + supportedAttributeUiInputGstModel["query"] = "testString" + supportedAttributeUiInputGstModel["value_property_name"] = "testString" + supportedAttributeUiInputGstModel["label_property_name"] = "testString" + supportedAttributeUiInputGstModel["input_option_label"] = "testString" + + supportedAttributeUiInputUrlModel := make(map[string]interface{}) + supportedAttributeUiInputUrlModel["url_endpoint"] = "testString" + supportedAttributeUiInputUrlModel["input_option_label"] = "testString" + + model := make(map[string]interface{}) + model["type"] = "testString" + model["values"] = []interface{}{supportedAttributeUiInputValueModel} + model["gst"] = []interface{}{supportedAttributeUiInputGstModel} + model["url"] = []interface{}{supportedAttributeUiInputUrlModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputDetails(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputValue(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedAttributeUiInputValue) { + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + model := new(partnercentersellv1.SupportedAttributeUiInputValue) + model.Value = core.StringPtr("testString") + model.DisplayName = iamServiceRegistrationDisplayNameObjectModel + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + model := make(map[string]interface{}) + model["value"] = "testString" + model["display_name"] = []interface{}{iamServiceRegistrationDisplayNameObjectModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputValue(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputGst(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedAttributeUiInputGst) { + model := new(partnercentersellv1.SupportedAttributeUiInputGst) + model.Query = core.StringPtr("testString") + model.ValuePropertyName = core.StringPtr("testString") + model.LabelPropertyName = core.StringPtr("testString") + model.InputOptionLabel = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["query"] = "testString" + model["value_property_name"] = "testString" + model["label_property_name"] = "testString" + model["input_option_label"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputGst(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputURL(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedAttributeUiInputURL) { + model := new(partnercentersellv1.SupportedAttributeUiInputURL) + model.UrlEndpoint = core.StringPtr("testString") + model.InputOptionLabel = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["url_endpoint"] = "testString" + model["input_option_label"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedAttributeUiInputURL(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAuthorizationSubject(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationSupportedAuthorizationSubject) { + supportAuthorizationSubjectAttributeModel := new(partnercentersellv1.SupportAuthorizationSubjectAttribute) + supportAuthorizationSubjectAttributeModel.ServiceName = core.StringPtr("testString") + supportAuthorizationSubjectAttributeModel.ResourceType = core.StringPtr("testString") + + model := new(partnercentersellv1.IamServiceRegistrationSupportedAuthorizationSubject) + model.Attributes = supportAuthorizationSubjectAttributeModel + model.Roles = []string{"testString"} + + assert.Equal(t, result, model) + } + + supportAuthorizationSubjectAttributeModel := make(map[string]interface{}) + supportAuthorizationSubjectAttributeModel["service_name"] = "testString" + supportAuthorizationSubjectAttributeModel["resource_type"] = "testString" + + model := make(map[string]interface{}) + model["attributes"] = []interface{}{supportAuthorizationSubjectAttributeModel} + model["roles"] = []interface{}{"testString"} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedAuthorizationSubject(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportAuthorizationSubjectAttribute(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportAuthorizationSubjectAttribute) { + model := new(partnercentersellv1.SupportAuthorizationSubjectAttribute) + model.ServiceName = core.StringPtr("testString") + model.ResourceType = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["service_name"] = "testString" + model["resource_type"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportAuthorizationSubjectAttribute(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedRole(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationSupportedRole) { + iamServiceRegistrationDescriptionObjectModel := new(partnercentersellv1.IamServiceRegistrationDescriptionObject) + iamServiceRegistrationDescriptionObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDescriptionObjectModel.ZhCn = core.StringPtr("testString") + + iamServiceRegistrationDisplayNameObjectModel := new(partnercentersellv1.IamServiceRegistrationDisplayNameObject) + iamServiceRegistrationDisplayNameObjectModel.Default = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.En = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.De = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Es = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Fr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.It = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ja = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.Ko = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.PtBr = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhTw = core.StringPtr("testString") + iamServiceRegistrationDisplayNameObjectModel.ZhCn = core.StringPtr("testString") + + supportedRoleOptionsModel := new(partnercentersellv1.SupportedRoleOptions) + supportedRoleOptionsModel.AccessPolicy = map[string]string{"key1": "testString"} + supportedRoleOptionsModel.PolicyType = []string{"access"} + supportedRoleOptionsModel.AccountType = core.StringPtr("enterprise") + + model := new(partnercentersellv1.IamServiceRegistrationSupportedRole) + model.ID = core.StringPtr("testString") + model.Description = iamServiceRegistrationDescriptionObjectModel + model.DisplayName = iamServiceRegistrationDisplayNameObjectModel + model.Options = supportedRoleOptionsModel + + assert.Equal(t, result, model) + } + + iamServiceRegistrationDescriptionObjectModel := make(map[string]interface{}) + iamServiceRegistrationDescriptionObjectModel["default"] = "testString" + iamServiceRegistrationDescriptionObjectModel["en"] = "testString" + iamServiceRegistrationDescriptionObjectModel["de"] = "testString" + iamServiceRegistrationDescriptionObjectModel["es"] = "testString" + iamServiceRegistrationDescriptionObjectModel["fr"] = "testString" + iamServiceRegistrationDescriptionObjectModel["it"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ja"] = "testString" + iamServiceRegistrationDescriptionObjectModel["ko"] = "testString" + iamServiceRegistrationDescriptionObjectModel["pt_br"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDescriptionObjectModel["zh_cn"] = "testString" + + iamServiceRegistrationDisplayNameObjectModel := make(map[string]interface{}) + iamServiceRegistrationDisplayNameObjectModel["default"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["en"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["de"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["es"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["fr"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["it"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ja"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["ko"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["pt_br"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_tw"] = "testString" + iamServiceRegistrationDisplayNameObjectModel["zh_cn"] = "testString" + + supportedRoleOptionsModel := make(map[string]interface{}) + supportedRoleOptionsModel["access_policy"] = map[string]interface{}{"key1": "testString"} + supportedRoleOptionsModel["policy_type"] = []interface{}{"access"} + supportedRoleOptionsModel["account_type"] = "enterprise" + + model := make(map[string]interface{}) + model["id"] = "testString" + model["description"] = []interface{}{iamServiceRegistrationDescriptionObjectModel} + model["display_name"] = []interface{}{iamServiceRegistrationDisplayNameObjectModel} + model["options"] = []interface{}{supportedRoleOptionsModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedRole(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToSupportedRoleOptions(t *testing.T) { + checkResult := func(result *partnercentersellv1.SupportedRoleOptions) { + model := new(partnercentersellv1.SupportedRoleOptions) + model.AccessPolicy = map[string]string{"key1": "testString"} + model.PolicyType = []string{"access"} + model.AccountType = core.StringPtr("enterprise") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["access_policy"] = map[string]interface{}{"key1": "testString"} + model["policy_type"] = []interface{}{"access"} + model["account_type"] = "enterprise" + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToSupportedRoleOptions(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedNetwork(t *testing.T) { + checkResult := func(result *partnercentersellv1.IamServiceRegistrationSupportedNetwork) { + environmentAttributeOptionsModel := new(partnercentersellv1.EnvironmentAttributeOptions) + environmentAttributeOptionsModel.Hidden = core.BoolPtr(true) + + environmentAttributeModel := new(partnercentersellv1.EnvironmentAttribute) + environmentAttributeModel.Key = core.StringPtr("testString") + environmentAttributeModel.Values = []string{"testString"} + environmentAttributeModel.Options = environmentAttributeOptionsModel + + model := new(partnercentersellv1.IamServiceRegistrationSupportedNetwork) + model.EnvironmentAttributes = []partnercentersellv1.EnvironmentAttribute{*environmentAttributeModel} + + assert.Equal(t, result, model) + } + + environmentAttributeOptionsModel := make(map[string]interface{}) + environmentAttributeOptionsModel["hidden"] = true + + environmentAttributeModel := make(map[string]interface{}) + environmentAttributeModel["key"] = "testString" + environmentAttributeModel["values"] = []interface{}{"testString"} + environmentAttributeModel["options"] = []interface{}{environmentAttributeOptionsModel} + + model := make(map[string]interface{}) + model["environment_attributes"] = []interface{}{environmentAttributeModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToIamServiceRegistrationSupportedNetwork(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToEnvironmentAttribute(t *testing.T) { + checkResult := func(result *partnercentersellv1.EnvironmentAttribute) { + environmentAttributeOptionsModel := new(partnercentersellv1.EnvironmentAttributeOptions) + environmentAttributeOptionsModel.Hidden = core.BoolPtr(true) + + model := new(partnercentersellv1.EnvironmentAttribute) + model.Key = core.StringPtr("testString") + model.Values = []string{"testString"} + model.Options = environmentAttributeOptionsModel + + assert.Equal(t, result, model) + } + + environmentAttributeOptionsModel := make(map[string]interface{}) + environmentAttributeOptionsModel["hidden"] = true + + model := make(map[string]interface{}) + model["key"] = "testString" + model["values"] = []interface{}{"testString"} + model["options"] = []interface{}{environmentAttributeOptionsModel} + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToEnvironmentAttribute(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingIamRegistrationMapToEnvironmentAttributeOptions(t *testing.T) { + checkResult := func(result *partnercentersellv1.EnvironmentAttributeOptions) { + model := new(partnercentersellv1.EnvironmentAttributeOptions) + model.Hidden = core.BoolPtr(true) + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["hidden"] = true + + result, err := partnercentersell.ResourceIbmOnboardingIamRegistrationMapToEnvironmentAttributeOptions(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_product.go b/ibm/service/partnercentersell/resource_ibm_onboarding_product.go new file mode 100644 index 0000000000..221f7f0b8c --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_product.go @@ -0,0 +1,549 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.94.1-71478489-20240820-161623 + */ + +package partnercentersell + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" +) + +func ResourceIbmOnboardingProduct() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIbmOnboardingProductCreate, + ReadContext: resourceIbmOnboardingProductRead, + UpdateContext: resourceIbmOnboardingProductUpdate, + DeleteContext: resourceIbmOnboardingProductDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_product", "type"), + Description: "The type of the product.", + }, + "primary_contact": &schema.Schema{ + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Required: true, + Description: "The primary contact for your product.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The name of the primary contact for your product.", + }, + "email": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The email address of the primary contact for your product.", + }, + }, + }, + }, + "eccn_number": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The Export Control Classification Number of your product.", + }, + "ero_class": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The ERO class of your product.", + }, + "unspsc": &schema.Schema{ + Type: schema.TypeFloat, + Optional: true, + Description: "The United Nations Standard Products and Services Code of your product.", + }, + "tax_assessment": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The tax assessment type of your product.", + }, + "support": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The support information that is not displayed in the catalog, but available in ServiceNow.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "escalation_contacts": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The list of contacts in case of support escalations.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name of the support escalation contact.", + }, + "email": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The email address of the support escalation contact.", + }, + "role": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The role of the support escalation contact.", + }, + }, + }, + }, + }, + }, + }, + "account_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IBM Cloud account ID of the provider.", + }, + "private_catalog_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the private catalog that contains the product. Only applicable for software type products.", + }, + "private_catalog_offering_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the linked private catalog product. Only applicable for software type products.", + }, + "global_catalog_offering_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of a global catalog object.", + }, + "staging_global_catalog_offering_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of a global catalog object.", + }, + "approver_resource_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the approval workflow of your product.", + }, + }, + } +} + +func ResourceIbmOnboardingProductValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "type", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: "professional_service, service, software", + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_onboarding_product", Schema: validateSchema} + return &resourceValidator +} + +func resourceIbmOnboardingProductCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createOnboardingProductOptions := &partnercentersellv1.CreateOnboardingProductOptions{} + + createOnboardingProductOptions.SetType(d.Get("type").(string)) + primaryContactModel, err := ResourceIbmOnboardingProductMapToPrimaryContact(d.Get("primary_contact.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "create", "parse-primary_contact").GetDiag() + } + createOnboardingProductOptions.SetPrimaryContact(primaryContactModel) + if _, ok := d.GetOk("eccn_number"); ok { + createOnboardingProductOptions.SetEccnNumber(d.Get("eccn_number").(string)) + } + if _, ok := d.GetOk("ero_class"); ok { + createOnboardingProductOptions.SetEroClass(d.Get("ero_class").(string)) + } + if _, ok := d.GetOk("unspsc"); ok { + createOnboardingProductOptions.SetUnspsc(d.Get("unspsc").(float64)) + } + if _, ok := d.GetOk("tax_assessment"); ok { + createOnboardingProductOptions.SetTaxAssessment(d.Get("tax_assessment").(string)) + } + if _, ok := d.GetOk("support"); ok { + supportModel, err := ResourceIbmOnboardingProductMapToOnboardingProductSupport(d.Get("support.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "create", "parse-support").GetDiag() + } + createOnboardingProductOptions.SetSupport(supportModel) + } + + onboardingProduct, _, err := partnerCenterSellClient.CreateOnboardingProductWithContext(context, createOnboardingProductOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateOnboardingProductWithContext failed: %s", err.Error()), "ibm_onboarding_product", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(*onboardingProduct.ID) + + return resourceIbmOnboardingProductRead(context, d, meta) +} + +func resourceIbmOnboardingProductRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getOnboardingProductOptions := &partnercentersellv1.GetOnboardingProductOptions{} + + getOnboardingProductOptions.SetProductID(d.Id()) + + onboardingProduct, response, err := partnerCenterSellClient.GetOnboardingProductWithContext(context, getOnboardingProductOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetOnboardingProductWithContext failed: %s", err.Error()), "ibm_onboarding_product", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if err = d.Set("type", onboardingProduct.Type); err != nil { + err = fmt.Errorf("Error setting type: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-type").GetDiag() + } + primaryContactMap, err := ResourceIbmOnboardingProductPrimaryContactToMap(onboardingProduct.PrimaryContact) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "primary_contact-to-map").GetDiag() + } + if err = d.Set("primary_contact", []map[string]interface{}{primaryContactMap}); err != nil { + err = fmt.Errorf("Error setting primary_contact: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-primary_contact").GetDiag() + } + if !core.IsNil(onboardingProduct.EccnNumber) { + if err = d.Set("eccn_number", onboardingProduct.EccnNumber); err != nil { + err = fmt.Errorf("Error setting eccn_number: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-eccn_number").GetDiag() + } + } + if !core.IsNil(onboardingProduct.EroClass) { + if err = d.Set("ero_class", onboardingProduct.EroClass); err != nil { + err = fmt.Errorf("Error setting ero_class: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-ero_class").GetDiag() + } + } + if !core.IsNil(onboardingProduct.Unspsc) { + if err = d.Set("unspsc", onboardingProduct.Unspsc); err != nil { + err = fmt.Errorf("Error setting unspsc: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-unspsc").GetDiag() + } + } + if !core.IsNil(onboardingProduct.TaxAssessment) { + if err = d.Set("tax_assessment", onboardingProduct.TaxAssessment); err != nil { + err = fmt.Errorf("Error setting tax_assessment: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-tax_assessment").GetDiag() + } + } + if !core.IsNil(onboardingProduct.Support) { + supportMap, err := ResourceIbmOnboardingProductOnboardingProductSupportToMap(onboardingProduct.Support) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "support-to-map").GetDiag() + } + if err = d.Set("support", []map[string]interface{}{supportMap}); err != nil { + err = fmt.Errorf("Error setting support: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-support").GetDiag() + } + } + if !core.IsNil(onboardingProduct.AccountID) { + if err = d.Set("account_id", onboardingProduct.AccountID); err != nil { + err = fmt.Errorf("Error setting account_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-account_id").GetDiag() + } + } + if !core.IsNil(onboardingProduct.PrivateCatalogID) { + if err = d.Set("private_catalog_id", onboardingProduct.PrivateCatalogID); err != nil { + err = fmt.Errorf("Error setting private_catalog_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-private_catalog_id").GetDiag() + } + } + if !core.IsNil(onboardingProduct.PrivateCatalogOfferingID) { + if err = d.Set("private_catalog_offering_id", onboardingProduct.PrivateCatalogOfferingID); err != nil { + err = fmt.Errorf("Error setting private_catalog_offering_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-private_catalog_offering_id").GetDiag() + } + } + if !core.IsNil(onboardingProduct.GlobalCatalogOfferingID) { + if err = d.Set("global_catalog_offering_id", onboardingProduct.GlobalCatalogOfferingID); err != nil { + err = fmt.Errorf("Error setting global_catalog_offering_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-global_catalog_offering_id").GetDiag() + } + } + if !core.IsNil(onboardingProduct.StagingGlobalCatalogOfferingID) { + if err = d.Set("staging_global_catalog_offering_id", onboardingProduct.StagingGlobalCatalogOfferingID); err != nil { + err = fmt.Errorf("Error setting staging_global_catalog_offering_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-staging_global_catalog_offering_id").GetDiag() + } + } + if !core.IsNil(onboardingProduct.ApproverResourceID) { + if err = d.Set("approver_resource_id", onboardingProduct.ApproverResourceID); err != nil { + err = fmt.Errorf("Error setting approver_resource_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "read", "set-approver_resource_id").GetDiag() + } + } + + return nil +} + +func resourceIbmOnboardingProductUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateOnboardingProductOptions := &partnercentersellv1.UpdateOnboardingProductOptions{} + + updateOnboardingProductOptions.SetProductID(d.Id()) + + hasChange := false + + patchVals := &partnercentersellv1.OnboardingProductPatch{} + if d.HasChange("primary_contact") { + primaryContact, err := ResourceIbmOnboardingProductMapToPrimaryContact(d.Get("primary_contact.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "update", "parse-primary_contact").GetDiag() + } + patchVals.PrimaryContact = primaryContact + hasChange = true + } + if d.HasChange("eccn_number") { + newEccnNumber := d.Get("eccn_number").(string) + patchVals.EccnNumber = &newEccnNumber + hasChange = true + } + if d.HasChange("ero_class") { + newEroClass := d.Get("ero_class").(string) + patchVals.EroClass = &newEroClass + hasChange = true + } + if d.HasChange("unspsc") { + newUnspsc := d.Get("unspsc").(float64) + patchVals.Unspsc = &newUnspsc + hasChange = true + } + if d.HasChange("tax_assessment") { + newTaxAssessment := d.Get("tax_assessment").(string) + patchVals.TaxAssessment = &newTaxAssessment + hasChange = true + } + if d.HasChange("support") { + support, err := ResourceIbmOnboardingProductMapToOnboardingProductSupport(d.Get("support.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "update", "parse-support").GetDiag() + } + patchVals.Support = support + hasChange = true + } + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateOnboardingProductOptions.OnboardingProductPatch = ResourceIbmOnboardingProductOnboardingProductPatchAsPatch(patchVals, d) + + _, _, err = partnerCenterSellClient.UpdateOnboardingProductWithContext(context, updateOnboardingProductOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateOnboardingProductWithContext failed: %s", err.Error()), "ibm_onboarding_product", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIbmOnboardingProductRead(context, d, meta) +} + +func resourceIbmOnboardingProductDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_product", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteOnboardingProductOptions := &partnercentersellv1.DeleteOnboardingProductOptions{} + + deleteOnboardingProductOptions.SetProductID(d.Id()) + + _, err = partnerCenterSellClient.DeleteOnboardingProductWithContext(context, deleteOnboardingProductOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteOnboardingProductWithContext failed: %s", err.Error()), "ibm_onboarding_product", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIbmOnboardingProductMapToPrimaryContact(modelMap map[string]interface{}) (*partnercentersellv1.PrimaryContact, error) { + model := &partnercentersellv1.PrimaryContact{} + model.Name = core.StringPtr(modelMap["name"].(string)) + model.Email = core.StringPtr(modelMap["email"].(string)) + return model, nil +} + +func ResourceIbmOnboardingProductMapToOnboardingProductSupport(modelMap map[string]interface{}) (*partnercentersellv1.OnboardingProductSupport, error) { + model := &partnercentersellv1.OnboardingProductSupport{} + if modelMap["escalation_contacts"] != nil { + escalationContacts := []partnercentersellv1.OnboardingProductSupportEscalationContactItems{} + for _, escalationContactsItem := range modelMap["escalation_contacts"].([]interface{}) { + escalationContactsItemModel, err := ResourceIbmOnboardingProductMapToOnboardingProductSupportEscalationContactItems(escalationContactsItem.(map[string]interface{})) + if err != nil { + return model, err + } + escalationContacts = append(escalationContacts, *escalationContactsItemModel) + } + model.EscalationContacts = escalationContacts + } + return model, nil +} + +func ResourceIbmOnboardingProductMapToOnboardingProductSupportEscalationContactItems(modelMap map[string]interface{}) (*partnercentersellv1.OnboardingProductSupportEscalationContactItems, error) { + model := &partnercentersellv1.OnboardingProductSupportEscalationContactItems{} + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["email"] != nil && modelMap["email"].(string) != "" { + model.Email = core.StringPtr(modelMap["email"].(string)) + } + if modelMap["role"] != nil && modelMap["role"].(string) != "" { + model.Role = core.StringPtr(modelMap["role"].(string)) + } + return model, nil +} + +func ResourceIbmOnboardingProductPrimaryContactToMap(model *partnercentersellv1.PrimaryContact) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["name"] = *model.Name + modelMap["email"] = *model.Email + return modelMap, nil +} + +func ResourceIbmOnboardingProductOnboardingProductSupportToMap(model *partnercentersellv1.OnboardingProductSupport) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.EscalationContacts != nil { + escalationContacts := []map[string]interface{}{} + for _, escalationContactsItem := range model.EscalationContacts { + escalationContactsItemMap, err := ResourceIbmOnboardingProductOnboardingProductSupportEscalationContactItemsToMap(&escalationContactsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + escalationContacts = append(escalationContacts, escalationContactsItemMap) + } + modelMap["escalation_contacts"] = escalationContacts + } + return modelMap, nil +} + +func ResourceIbmOnboardingProductOnboardingProductSupportEscalationContactItemsToMap(model *partnercentersellv1.OnboardingProductSupportEscalationContactItems) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.Email != nil { + modelMap["email"] = *model.Email + } + if model.Role != nil { + modelMap["role"] = *model.Role + } + return modelMap, nil +} + +func ResourceIbmOnboardingProductOnboardingProductPatchAsPatch(patchVals *partnercentersellv1.OnboardingProductPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "primary_contact" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["primary_contact"] = nil + } + path = "eccn_number" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["eccn_number"] = nil + } + path = "ero_class" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["ero_class"] = nil + } + path = "unspsc" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["unspsc"] = nil + } + path = "tax_assessment" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["tax_assessment"] = nil + } + path = "support" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["support"] = nil + } else if exists && patch["support"] != nil { + ResourceIbmOnboardingProductOnboardingProductSupportAsPatch(patch["support"].(map[string]interface{}), d) + } + + return patch +} + +func ResourceIbmOnboardingProductOnboardingProductSupportAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "support.0.escalation_contacts" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["escalation_contacts"] = nil + } else if exists && patch["escalation_contacts"] != nil { + ResourceIbmOnboardingProductOnboardingProductSupportEscalationContactItemsAsPatch(patch["escalation_contacts"].([]interface{})[0].(map[string]interface{}), d) + } +} + +func ResourceIbmOnboardingProductOnboardingProductSupportEscalationContactItemsAsPatch(patch map[string]interface{}, d *schema.ResourceData) { + var path string + + path = "support.0.escalation_contacts.0.name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["name"] = nil + } + path = "support.0.escalation_contacts.0.email" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["email"] = nil + } + path = "support.0.escalation_contacts.0.role" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["role"] = nil + } +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_product_test.go b/ibm/service/partnercentersell/resource_ibm_onboarding_product_test.go new file mode 100644 index 0000000000..c69634c93e --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_product_test.go @@ -0,0 +1,301 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package partnercentersell_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/partnercentersell" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIbmOnboardingProductBasic(t *testing.T) { + var conf partnercentersellv1.OnboardingProduct + typeVar := "service" + typeVarUpdate := "service" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingProductDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingProductConfigBasic(typeVar), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingProductExists("ibm_onboarding_product.onboarding_product_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "type", typeVar), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingProductConfigBasic(typeVarUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "type", typeVarUpdate), + ), + }, + }, + }) +} + +func TestAccIbmOnboardingProductAllArgs(t *testing.T) { + var conf partnercentersellv1.OnboardingProduct + typeVar := "service" + eccnNumber := "5D002.C.1" + eroClass := "A6VR" + taxAssessment := "PAAS" + typeVarUpdate := "service" + eccnNumberUpdate := "5D002.C.1" + eroClassUpdate := "A6VR" + taxAssessmentUpdate := "PAAS" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingProductDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingProductConfig(typeVar, eccnNumber, eroClass, taxAssessment), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingProductExists("ibm_onboarding_product.onboarding_product_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "type", typeVar), + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "eccn_number", eccnNumber), + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "ero_class", eroClass), + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "tax_assessment", taxAssessment), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingProductConfig(typeVarUpdate, eccnNumberUpdate, eroClassUpdate, taxAssessmentUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "type", typeVarUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "eccn_number", eccnNumberUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "ero_class", eroClassUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_product.onboarding_product_instance", "tax_assessment", taxAssessmentUpdate), + ), + }, + resource.TestStep{ + ResourceName: "ibm_onboarding_product.onboarding_product_instance", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckIbmOnboardingProductConfigBasic(typeVar string) string { + return fmt.Sprintf(` + resource "ibm_onboarding_product" "onboarding_product_instance" { + type = "%s" + primary_contact { + name = "petra" + email = "petra@ibm.com" + } + } + `, typeVar) +} + +func testAccCheckIbmOnboardingProductConfig(typeVar string, eccnNumber string, eroClass string, taxAssessment string) string { + return fmt.Sprintf(` + + resource "ibm_onboarding_product" "onboarding_product_instance" { + type = "%s" + primary_contact { + name = "name" + email = "petra@email.com" + } + eccn_number = "%s" + ero_class = "%s" + unspsc = "25191503" + tax_assessment = "%s" + } + `, typeVar, eccnNumber, eroClass, taxAssessment) +} + +func testAccCheckIbmOnboardingProductExists(n string, obj partnercentersellv1.OnboardingProduct) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + + getOnboardingProductOptions := &partnercentersellv1.GetOnboardingProductOptions{} + + getOnboardingProductOptions.SetProductID(rs.Primary.ID) + + onboardingProduct, _, err := partnerCenterSellClient.GetOnboardingProduct(getOnboardingProductOptions) + if err != nil { + return err + } + + obj = *onboardingProduct + return nil + } +} + +func testAccCheckIbmOnboardingProductDestroy(s *terraform.State) error { + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_onboarding_product" { + continue + } + + getOnboardingProductOptions := &partnercentersellv1.GetOnboardingProductOptions{} + + getOnboardingProductOptions.SetProductID(rs.Primary.ID) + + // Try to find the key + _, response, err := partnerCenterSellClient.GetOnboardingProduct(getOnboardingProductOptions) + + if err == nil { + return fmt.Errorf("onboarding_product still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for onboarding_product (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} + +func TestResourceIbmOnboardingProductPrimaryContactToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.PrimaryContact) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingProductPrimaryContactToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingProductOnboardingProductSupportToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + onboardingProductSupportEscalationContactItemsModel := make(map[string]interface{}) + onboardingProductSupportEscalationContactItemsModel["name"] = "testString" + onboardingProductSupportEscalationContactItemsModel["email"] = "testString" + onboardingProductSupportEscalationContactItemsModel["role"] = "testString" + + model := make(map[string]interface{}) + model["escalation_contacts"] = []map[string]interface{}{onboardingProductSupportEscalationContactItemsModel} + + assert.Equal(t, result, model) + } + + onboardingProductSupportEscalationContactItemsModel := new(partnercentersellv1.OnboardingProductSupportEscalationContactItems) + onboardingProductSupportEscalationContactItemsModel.Name = core.StringPtr("testString") + onboardingProductSupportEscalationContactItemsModel.Email = core.StringPtr("testString") + onboardingProductSupportEscalationContactItemsModel.Role = core.StringPtr("testString") + + model := new(partnercentersellv1.OnboardingProductSupport) + model.EscalationContacts = []partnercentersellv1.OnboardingProductSupportEscalationContactItems{*onboardingProductSupportEscalationContactItemsModel} + + result, err := partnercentersell.ResourceIbmOnboardingProductOnboardingProductSupportToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingProductOnboardingProductSupportEscalationContactItemsToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + model["role"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.OnboardingProductSupportEscalationContactItems) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + model.Role = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingProductOnboardingProductSupportEscalationContactItemsToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingProductMapToPrimaryContact(t *testing.T) { + checkResult := func(result *partnercentersellv1.PrimaryContact) { + model := new(partnercentersellv1.PrimaryContact) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingProductMapToPrimaryContact(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingProductMapToOnboardingProductSupport(t *testing.T) { + checkResult := func(result *partnercentersellv1.OnboardingProductSupport) { + onboardingProductSupportEscalationContactItemsModel := new(partnercentersellv1.OnboardingProductSupportEscalationContactItems) + onboardingProductSupportEscalationContactItemsModel.Name = core.StringPtr("testString") + onboardingProductSupportEscalationContactItemsModel.Email = core.StringPtr("testString") + onboardingProductSupportEscalationContactItemsModel.Role = core.StringPtr("testString") + + model := new(partnercentersellv1.OnboardingProductSupport) + model.EscalationContacts = []partnercentersellv1.OnboardingProductSupportEscalationContactItems{*onboardingProductSupportEscalationContactItemsModel} + + assert.Equal(t, result, model) + } + + onboardingProductSupportEscalationContactItemsModel := make(map[string]interface{}) + onboardingProductSupportEscalationContactItemsModel["name"] = "testString" + onboardingProductSupportEscalationContactItemsModel["email"] = "testString" + onboardingProductSupportEscalationContactItemsModel["role"] = "testString" + + model := make(map[string]interface{}) + model["escalation_contacts"] = []interface{}{onboardingProductSupportEscalationContactItemsModel} + + result, err := partnercentersell.ResourceIbmOnboardingProductMapToOnboardingProductSupport(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingProductMapToOnboardingProductSupportEscalationContactItems(t *testing.T) { + checkResult := func(result *partnercentersellv1.OnboardingProductSupportEscalationContactItems) { + model := new(partnercentersellv1.OnboardingProductSupportEscalationContactItems) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + model.Role = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + model["role"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingProductMapToOnboardingProductSupportEscalationContactItems(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_registration.go b/ibm/service/partnercentersell/resource_ibm_onboarding_registration.go new file mode 100644 index 0000000000..4a52eed5f2 --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_registration.go @@ -0,0 +1,376 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.94.1-71478489-20240820-161623 + */ + +package partnercentersell + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" +) + +func ResourceIbmOnboardingRegistration() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIbmOnboardingRegistrationCreate, + ReadContext: resourceIbmOnboardingRegistrationRead, + UpdateContext: resourceIbmOnboardingRegistrationUpdate, + DeleteContext: resourceIbmOnboardingRegistrationDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "account_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_registration", "account_id"), + Description: "The ID of your account.", + }, + "company_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_registration", "company_name"), + Description: "The name of your company that is displayed in the IBM Cloud catalog.", + }, + "primary_contact": &schema.Schema{ + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Required: true, + Description: "The primary contact for your product.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The name of the primary contact for your product.", + }, + "email": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The email address of the primary contact for your product.", + }, + }, + }, + }, + "default_private_catalog_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_registration", "default_private_catalog_id"), + Description: "The default private catalog in which products are created.", + }, + "provider_access_group": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_registration", "provider_access_group"), + Description: "The onboarding access group for your team.", + }, + "account_dra_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the IBM Digital Platform Reseller Agreement.", + }, + "account_dpa_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the IBM Digital Provider Agreement.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The time when the registration was created.", + }, + "updated_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The time when the registration was updated.", + }, + }, + } +} + +func ResourceIbmOnboardingRegistrationValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "account_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9]+$`, + MinValueLength: 1, + MaxValueLength: 32, + }, + validate.ValidateSchema{ + Identifier: "company_name", + ValidateFunctionIdentifier: validate.StringLenBetween, + Type: validate.TypeString, + Required: true, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "default_private_catalog_id", + ValidateFunctionIdentifier: validate.ValidateRegexp, + Type: validate.TypeString, + Optional: true, + Regexp: `[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`, + }, + validate.ValidateSchema{ + Identifier: "provider_access_group", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^AccessGroupId-[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`, + MinValueLength: 1, + MaxValueLength: 50, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_onboarding_registration", Schema: validateSchema} + return &resourceValidator +} + +func resourceIbmOnboardingRegistrationCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createRegistrationOptions := &partnercentersellv1.CreateRegistrationOptions{} + + createRegistrationOptions.SetAccountID(d.Get("account_id").(string)) + createRegistrationOptions.SetCompanyName(d.Get("company_name").(string)) + primaryContactModel, err := ResourceIbmOnboardingRegistrationMapToPrimaryContact(d.Get("primary_contact.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "create", "parse-primary_contact").GetDiag() + } + createRegistrationOptions.SetPrimaryContact(primaryContactModel) + if _, ok := d.GetOk("default_private_catalog_id"); ok { + createRegistrationOptions.SetDefaultPrivateCatalogID(d.Get("default_private_catalog_id").(string)) + } + if _, ok := d.GetOk("provider_access_group"); ok { + createRegistrationOptions.SetProviderAccessGroup(d.Get("provider_access_group").(string)) + } + + registration, _, err := partnerCenterSellClient.CreateRegistrationWithContext(context, createRegistrationOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateRegistrationWithContext failed: %s", err.Error()), "ibm_onboarding_registration", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(*registration.ID) + + return resourceIbmOnboardingRegistrationRead(context, d, meta) +} + +func resourceIbmOnboardingRegistrationRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getRegistrationOptions := &partnercentersellv1.GetRegistrationOptions{} + + getRegistrationOptions.SetRegistrationID(d.Id()) + + registration, response, err := partnerCenterSellClient.GetRegistrationWithContext(context, getRegistrationOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetRegistrationWithContext failed: %s", err.Error()), "ibm_onboarding_registration", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if err = d.Set("account_id", registration.AccountID); err != nil { + err = fmt.Errorf("Error setting account_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "set-account_id").GetDiag() + } + if err = d.Set("company_name", registration.CompanyName); err != nil { + err = fmt.Errorf("Error setting company_name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "set-company_name").GetDiag() + } + primaryContactMap, err := ResourceIbmOnboardingRegistrationPrimaryContactToMap(registration.PrimaryContact) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "primary_contact-to-map").GetDiag() + } + if err = d.Set("primary_contact", []map[string]interface{}{primaryContactMap}); err != nil { + err = fmt.Errorf("Error setting primary_contact: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "set-primary_contact").GetDiag() + } + if !core.IsNil(registration.DefaultPrivateCatalogID) { + if err = d.Set("default_private_catalog_id", registration.DefaultPrivateCatalogID); err != nil { + err = fmt.Errorf("Error setting default_private_catalog_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "set-default_private_catalog_id").GetDiag() + } + } + if !core.IsNil(registration.ProviderAccessGroup) { + if err = d.Set("provider_access_group", registration.ProviderAccessGroup); err != nil { + err = fmt.Errorf("Error setting provider_access_group: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "set-provider_access_group").GetDiag() + } + } + if !core.IsNil(registration.AccountDraID) { + if err = d.Set("account_dra_id", registration.AccountDraID); err != nil { + err = fmt.Errorf("Error setting account_dra_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "set-account_dra_id").GetDiag() + } + } + if !core.IsNil(registration.AccountDpaID) { + if err = d.Set("account_dpa_id", registration.AccountDpaID); err != nil { + err = fmt.Errorf("Error setting account_dpa_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "set-account_dpa_id").GetDiag() + } + } + if !core.IsNil(registration.CreatedAt) { + if err = d.Set("created_at", registration.CreatedAt); err != nil { + err = fmt.Errorf("Error setting created_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "set-created_at").GetDiag() + } + } + if !core.IsNil(registration.UpdatedAt) { + if err = d.Set("updated_at", registration.UpdatedAt); err != nil { + err = fmt.Errorf("Error setting updated_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "read", "set-updated_at").GetDiag() + } + } + + return nil +} + +func resourceIbmOnboardingRegistrationUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateRegistrationOptions := &partnercentersellv1.UpdateRegistrationOptions{} + + updateRegistrationOptions.SetRegistrationID(d.Id()) + + hasChange := false + + patchVals := &partnercentersellv1.RegistrationPatch{} + if d.HasChange("company_name") { + newCompanyName := d.Get("company_name").(string) + patchVals.CompanyName = &newCompanyName + hasChange = true + } + if d.HasChange("primary_contact") { + primaryContact, err := ResourceIbmOnboardingRegistrationMapToPrimaryContact(d.Get("primary_contact.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "update", "parse-primary_contact").GetDiag() + } + patchVals.PrimaryContact = primaryContact + hasChange = true + } + if d.HasChange("default_private_catalog_id") { + newDefaultPrivateCatalogID := d.Get("default_private_catalog_id").(string) + patchVals.DefaultPrivateCatalogID = &newDefaultPrivateCatalogID + hasChange = true + } + if d.HasChange("provider_access_group") { + newProviderAccessGroup := d.Get("provider_access_group").(string) + patchVals.ProviderAccessGroup = &newProviderAccessGroup + hasChange = true + } + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateRegistrationOptions.RegistrationPatch = ResourceIbmOnboardingRegistrationRegistrationPatchAsPatch(patchVals, d) + + _, _, err = partnerCenterSellClient.UpdateRegistrationWithContext(context, updateRegistrationOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateRegistrationWithContext failed: %s", err.Error()), "ibm_onboarding_registration", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIbmOnboardingRegistrationRead(context, d, meta) +} + +func resourceIbmOnboardingRegistrationDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_registration", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteRegistrationOptions := &partnercentersellv1.DeleteRegistrationOptions{} + + deleteRegistrationOptions.SetRegistrationID(d.Id()) + + _, err = partnerCenterSellClient.DeleteRegistrationWithContext(context, deleteRegistrationOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteRegistrationWithContext failed: %s", err.Error()), "ibm_onboarding_registration", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIbmOnboardingRegistrationMapToPrimaryContact(modelMap map[string]interface{}) (*partnercentersellv1.PrimaryContact, error) { + model := &partnercentersellv1.PrimaryContact{} + model.Name = core.StringPtr(modelMap["name"].(string)) + model.Email = core.StringPtr(modelMap["email"].(string)) + return model, nil +} + +func ResourceIbmOnboardingRegistrationPrimaryContactToMap(model *partnercentersellv1.PrimaryContact) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["name"] = *model.Name + modelMap["email"] = *model.Email + return modelMap, nil +} + +func ResourceIbmOnboardingRegistrationRegistrationPatchAsPatch(patchVals *partnercentersellv1.RegistrationPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "company_name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["company_name"] = nil + } + path = "primary_contact" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["primary_contact"] = nil + } + path = "default_private_catalog_id" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["default_private_catalog_id"] = nil + } + path = "provider_access_group" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["provider_access_group"] = nil + } + + return patch +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_registration_test.go b/ibm/service/partnercentersell/resource_ibm_onboarding_registration_test.go new file mode 100644 index 0000000000..4c66f2f0dd --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_registration_test.go @@ -0,0 +1,213 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package partnercentersell_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/partnercentersell" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIbmOnboardingRegistrationBasic(t *testing.T) { + var conf partnercentersellv1.Registration + accountID := acc.PcsRegistrationAccountId + companyName := "Test_company" + accountIDUpdate := acc.PcsRegistrationAccountId + companyNameUpdate := "Test_company_up" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingRegistrationDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingRegistrationConfigBasic(accountID, companyName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingRegistrationExists("ibm_onboarding_registration.onboarding_registration_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "account_id", accountID), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "company_name", companyName), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingRegistrationConfigBasic(accountIDUpdate, companyNameUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "account_id", accountIDUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "company_name", companyNameUpdate), + ), + }, + }, + }) +} + +func TestAccIbmOnboardingRegistrationAllArgs(t *testing.T) { + var conf partnercentersellv1.Registration + accountID := acc.PcsRegistrationAccountId + companyName := "Test_company" + defaultPrivateCatalogID := "772b632e-fab4-4c41-b0b7-0a92fa40cf67" + providerAccessGroup := "AccessGroupId-b08e7bb5-d480-4c26-b193-d57dd9311608" + accountIDUpdate := acc.PcsRegistrationAccountId + companyNameUpdate := "Test_company_up" + defaultPrivateCatalogIDUpdate := "772b632e-fab4-4c41-b0b7-0a92fa40cf67" + providerAccessGroupUpdate := "AccessGroupId-b08e7bb5-d480-4c26-b193-d57dd9311608" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingRegistrationDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingRegistrationConfig(accountID, companyName, defaultPrivateCatalogID, providerAccessGroup), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingRegistrationExists("ibm_onboarding_registration.onboarding_registration_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "account_id", accountID), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "company_name", companyName), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "default_private_catalog_id", defaultPrivateCatalogID), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "provider_access_group", providerAccessGroup), + ), + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingRegistrationConfig(accountIDUpdate, companyNameUpdate, defaultPrivateCatalogIDUpdate, providerAccessGroupUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "account_id", accountIDUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "company_name", companyNameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "default_private_catalog_id", defaultPrivateCatalogIDUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_registration.onboarding_registration_instance", "provider_access_group", providerAccessGroupUpdate), + ), + }, + resource.TestStep{ + ResourceName: "ibm_onboarding_registration.onboarding_registration_instance", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckIbmOnboardingRegistrationConfigBasic(accountID string, companyName string) string { + return fmt.Sprintf(` + resource "ibm_onboarding_registration" "onboarding_registration_instance" { + account_id = "%s" + company_name = "%s" + primary_contact { + name = "Petra" + email = "petra@ibm.com" + } + } + `, accountID, companyName) +} + +func testAccCheckIbmOnboardingRegistrationConfig(accountID string, companyName string, defaultPrivateCatalogID string, providerAccessGroup string) string { + return fmt.Sprintf(` + + resource "ibm_onboarding_registration" "onboarding_registration_instance" { + account_id = "%s" + company_name = "%s" + primary_contact { + name = "Petra" + email = "petra@ibm.com" + } + default_private_catalog_id = "%s" + provider_access_group = "%s" + } + `, accountID, companyName, defaultPrivateCatalogID, providerAccessGroup) +} + +func testAccCheckIbmOnboardingRegistrationExists(n string, obj partnercentersellv1.Registration) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + + getRegistrationOptions := &partnercentersellv1.GetRegistrationOptions{} + + getRegistrationOptions.SetRegistrationID(rs.Primary.ID) + + registration, _, err := partnerCenterSellClient.GetRegistration(getRegistrationOptions) + if err != nil { + return err + } + + obj = *registration + return nil + } +} + +func testAccCheckIbmOnboardingRegistrationDestroy(s *terraform.State) error { + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_onboarding_registration" { + continue + } + + getRegistrationOptions := &partnercentersellv1.GetRegistrationOptions{} + + getRegistrationOptions.SetRegistrationID(rs.Primary.ID) + + // Try to find the key + _, response, err := partnerCenterSellClient.GetRegistration(getRegistrationOptions) + + if err == nil { + return fmt.Errorf("onboarding_registration still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for onboarding_registration (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} + +func TestResourceIbmOnboardingRegistrationPrimaryContactToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.PrimaryContact) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingRegistrationPrimaryContactToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingRegistrationMapToPrimaryContact(t *testing.T) { + checkResult := func(result *partnercentersellv1.PrimaryContact) { + model := new(partnercentersellv1.PrimaryContact) + model.Name = core.StringPtr("testString") + model.Email = core.StringPtr("testString") + + assert.Equal(t, result, model) + } + + model := make(map[string]interface{}) + model["name"] = "testString" + model["email"] = "testString" + + result, err := partnercentersell.ResourceIbmOnboardingRegistrationMapToPrimaryContact(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_resource_broker.go b/ibm/service/partnercentersell/resource_ibm_onboarding_resource_broker.go new file mode 100644 index 0000000000..4701d91dbe --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_resource_broker.go @@ -0,0 +1,630 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.94.1-71478489-20240820-161623 + */ + +package partnercentersell + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" +) + +func ResourceIbmOnboardingResourceBroker() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIbmOnboardingResourceBrokerCreate, + ReadContext: resourceIbmOnboardingResourceBrokerRead, + UpdateContext: resourceIbmOnboardingResourceBrokerUpdate, + DeleteContext: resourceIbmOnboardingResourceBrokerDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "env": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_resource_broker", "env"), + Description: "The environment to fetch this object from.", + }, + "auth_username": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The authentication username to reach the broker.", + }, + "auth_password": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The authentication password to reach the broker.", + }, + "auth_scheme": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The supported authentication scheme for the broker.", + }, + "resource_group_crn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The cloud resource name of the resource group.", + }, + "state": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_resource_broker", "state"), + Description: "The state of the broker.", + }, + "broker_url": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The URL associated with the broker application.", + }, + "allow_context_updates": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Description: "Whether the resource controller will call the broker for any context changes to the instance. Currently, the only context related change is an instance name update.", + }, + "catalog_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "To enable the provisioning of your broker, set this parameter value to `service`.", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_resource_broker", "type"), + Description: "The type of the provisioning model.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_onboarding_resource_broker", "name"), + Description: "The name of the broker.", + }, + "region": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The region where the pricing plan is available.", + }, + "account_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the account in which you manage the broker.", + }, + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The cloud resource name (CRN) of the broker.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The time when the service broker was created.", + }, + "updated_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The time when the service broker was updated.", + }, + "deleted_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The time when the service broker was deleted.", + }, + "created_by": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The details of the user who created this broker.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "user_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the user who dispatched this action.", + }, + "user_name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The username of the user who dispatched this action.", + }, + }, + }, + }, + "updated_by": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The details of the user who updated this broker.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "user_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the user who dispatched this action.", + }, + "user_name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The username of the user who dispatched this action.", + }, + }, + }, + }, + "deleted_by": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The details of the user who deleted this broker.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "user_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of the user who dispatched this action.", + }, + "user_name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The username of the user who dispatched this action.", + }, + }, + }, + }, + "guid": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique identifier of the broker.", + }, + "url": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL associated with the broker.", + }, + }, + } +} + +func ResourceIbmOnboardingResourceBrokerValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "env", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-z]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "state", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Optional: true, + AllowedValues: "active, removed", + }, + validate.ValidateSchema{ + Identifier: "type", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: "provision_behind, provision_through", + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[ -~\s]*$`, + MinValueLength: 1, + MaxValueLength: 128, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_onboarding_resource_broker", Schema: validateSchema} + return &resourceValidator +} + +func resourceIbmOnboardingResourceBrokerCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createResourceBrokerOptions := &partnercentersellv1.CreateResourceBrokerOptions{} + + createResourceBrokerOptions.SetAuthUsername(d.Get("auth_username").(string)) + createResourceBrokerOptions.SetAuthPassword(d.Get("auth_password").(string)) + createResourceBrokerOptions.SetAuthScheme(d.Get("auth_scheme").(string)) + createResourceBrokerOptions.SetName(d.Get("name").(string)) + createResourceBrokerOptions.SetBrokerURL(d.Get("broker_url").(string)) + createResourceBrokerOptions.SetType(d.Get("type").(string)) + if _, ok := d.GetOk("resource_group_crn"); ok { + createResourceBrokerOptions.SetResourceGroupCrn(d.Get("resource_group_crn").(string)) + } + if _, ok := d.GetOk("state"); ok { + createResourceBrokerOptions.SetState(d.Get("state").(string)) + } + if _, ok := d.GetOk("allow_context_updates"); ok { + createResourceBrokerOptions.SetAllowContextUpdates(d.Get("allow_context_updates").(bool)) + } + if _, ok := d.GetOk("catalog_type"); ok { + createResourceBrokerOptions.SetCatalogType(d.Get("catalog_type").(string)) + } + if _, ok := d.GetOk("region"); ok { + createResourceBrokerOptions.SetRegion(d.Get("region").(string)) + } + if _, ok := d.GetOk("env"); ok { + createResourceBrokerOptions.SetEnv(d.Get("env").(string)) + } + + broker, _, err := partnerCenterSellClient.CreateResourceBrokerWithContext(context, createResourceBrokerOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateResourceBrokerWithContext failed: %s", err.Error()), "ibm_onboarding_resource_broker", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(*broker.ID) + + return resourceIbmOnboardingResourceBrokerRead(context, d, meta) +} + +func resourceIbmOnboardingResourceBrokerRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getResourceBrokerOptions := &partnercentersellv1.GetResourceBrokerOptions{} + + getResourceBrokerOptions.SetBrokerID(d.Id()) + if _, ok := d.GetOk("env"); ok { + getResourceBrokerOptions.SetEnv(d.Get("env").(string)) + } + + broker, response, err := partnerCenterSellClient.GetResourceBrokerWithContext(context, getResourceBrokerOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetResourceBrokerWithContext failed: %s", err.Error()), "ibm_onboarding_resource_broker", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if err = d.Set("auth_username", broker.AuthUsername); err != nil { + err = fmt.Errorf("Error setting auth_username: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-auth_username").GetDiag() + } + if err = d.Set("auth_password", broker.AuthPassword); err != nil { + err = fmt.Errorf("Error setting auth_password: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-auth_password").GetDiag() + } + if err = d.Set("auth_scheme", broker.AuthScheme); err != nil { + err = fmt.Errorf("Error setting auth_scheme: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-auth_scheme").GetDiag() + } + if !core.IsNil(broker.ResourceGroupCrn) { + if err = d.Set("resource_group_crn", broker.ResourceGroupCrn); err != nil { + err = fmt.Errorf("Error setting resource_group_crn: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-resource_group_crn").GetDiag() + } + } + if !core.IsNil(broker.State) { + if err = d.Set("state", broker.State); err != nil { + err = fmt.Errorf("Error setting state: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-state").GetDiag() + } + } + if err = d.Set("broker_url", broker.BrokerURL); err != nil { + err = fmt.Errorf("Error setting broker_url: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-broker_url").GetDiag() + } + if !core.IsNil(broker.AllowContextUpdates) { + if err = d.Set("allow_context_updates", broker.AllowContextUpdates); err != nil { + err = fmt.Errorf("Error setting allow_context_updates: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-allow_context_updates").GetDiag() + } + } + if !core.IsNil(broker.CatalogType) { + if err = d.Set("catalog_type", broker.CatalogType); err != nil { + err = fmt.Errorf("Error setting catalog_type: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-catalog_type").GetDiag() + } + } + if err = d.Set("type", broker.Type); err != nil { + err = fmt.Errorf("Error setting type: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-type").GetDiag() + } + if err = d.Set("name", broker.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-name").GetDiag() + } + if !core.IsNil(broker.Region) { + if err = d.Set("region", broker.Region); err != nil { + err = fmt.Errorf("Error setting region: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-region").GetDiag() + } + } + if !core.IsNil(broker.AccountID) { + if err = d.Set("account_id", broker.AccountID); err != nil { + err = fmt.Errorf("Error setting account_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-account_id").GetDiag() + } + } + if !core.IsNil(broker.Crn) { + if err = d.Set("crn", broker.Crn); err != nil { + err = fmt.Errorf("Error setting crn: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-crn").GetDiag() + } + } + if !core.IsNil(broker.CreatedAt) { + if err = d.Set("created_at", flex.DateTimeToString(broker.CreatedAt)); err != nil { + err = fmt.Errorf("Error setting created_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-created_at").GetDiag() + } + } + if !core.IsNil(broker.UpdatedAt) { + if err = d.Set("updated_at", flex.DateTimeToString(broker.UpdatedAt)); err != nil { + err = fmt.Errorf("Error setting updated_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-updated_at").GetDiag() + } + } + if !core.IsNil(broker.DeletedAt) { + if err = d.Set("deleted_at", flex.DateTimeToString(broker.DeletedAt)); err != nil { + err = fmt.Errorf("Error setting deleted_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-deleted_at").GetDiag() + } + } + if !core.IsNil(broker.CreatedBy) { + createdByMap, err := ResourceIbmOnboardingResourceBrokerBrokerEventCreatedByUserToMap(broker.CreatedBy) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "created_by-to-map").GetDiag() + } + if err = d.Set("created_by", []map[string]interface{}{createdByMap}); err != nil { + err = fmt.Errorf("Error setting created_by: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-created_by").GetDiag() + } + } + if !core.IsNil(broker.UpdatedBy) { + updatedByMap, err := ResourceIbmOnboardingResourceBrokerBrokerEventUpdatedByUserToMap(broker.UpdatedBy) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "updated_by-to-map").GetDiag() + } + if err = d.Set("updated_by", []map[string]interface{}{updatedByMap}); err != nil { + err = fmt.Errorf("Error setting updated_by: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-updated_by").GetDiag() + } + } + if !core.IsNil(broker.DeletedBy) { + deletedByMap, err := ResourceIbmOnboardingResourceBrokerBrokerEventDeletedByUserToMap(broker.DeletedBy) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "deleted_by-to-map").GetDiag() + } + if err = d.Set("deleted_by", []map[string]interface{}{deletedByMap}); err != nil { + err = fmt.Errorf("Error setting deleted_by: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-deleted_by").GetDiag() + } + } + if !core.IsNil(broker.Guid) { + if err = d.Set("guid", broker.Guid); err != nil { + err = fmt.Errorf("Error setting guid: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-guid").GetDiag() + } + } + if !core.IsNil(broker.URL) { + if err = d.Set("url", broker.URL); err != nil { + err = fmt.Errorf("Error setting url: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "read", "set-url").GetDiag() + } + } + + return nil +} + +func resourceIbmOnboardingResourceBrokerUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateResourceBrokerOptions := &partnercentersellv1.UpdateResourceBrokerOptions{} + + updateResourceBrokerOptions.SetBrokerID(d.Id()) + if _, ok := d.GetOk("env"); ok { + updateResourceBrokerOptions.SetEnv(d.Get("env").(string)) + } + + hasChange := false + + patchVals := &partnercentersellv1.BrokerPatch{} + if d.HasChange("auth_username") { + newAuthUsername := d.Get("auth_username").(string) + patchVals.AuthUsername = &newAuthUsername + hasChange = true + } + if d.HasChange("auth_password") { + newAuthPassword := d.Get("auth_password").(string) + patchVals.AuthPassword = &newAuthPassword + hasChange = true + } + if d.HasChange("auth_scheme") { + newAuthScheme := d.Get("auth_scheme").(string) + patchVals.AuthScheme = &newAuthScheme + hasChange = true + } + if d.HasChange("resource_group_crn") { + newResourceGroupCrn := d.Get("resource_group_crn").(string) + patchVals.ResourceGroupCrn = &newResourceGroupCrn + hasChange = true + } + if d.HasChange("state") { + newState := d.Get("state").(string) + patchVals.State = &newState + hasChange = true + } + if d.HasChange("broker_url") { + newBrokerURL := d.Get("broker_url").(string) + patchVals.BrokerURL = &newBrokerURL + hasChange = true + } + if d.HasChange("allow_context_updates") { + newAllowContextUpdates := d.Get("allow_context_updates").(bool) + patchVals.AllowContextUpdates = &newAllowContextUpdates + hasChange = true + } + if d.HasChange("catalog_type") { + newCatalogType := d.Get("catalog_type").(string) + patchVals.CatalogType = &newCatalogType + hasChange = true + } + if d.HasChange("type") { + newType := d.Get("type").(string) + patchVals.Type = &newType + hasChange = true + } + if d.HasChange("region") { + newRegion := d.Get("region").(string) + patchVals.Region = &newRegion + hasChange = true + } + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateResourceBrokerOptions.BrokerPatch = ResourceIbmOnboardingResourceBrokerBrokerPatchAsPatch(patchVals, d) + + _, _, err = partnerCenterSellClient.UpdateResourceBrokerWithContext(context, updateResourceBrokerOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateResourceBrokerWithContext failed: %s", err.Error()), "ibm_onboarding_resource_broker", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIbmOnboardingResourceBrokerRead(context, d, meta) +} + +func resourceIbmOnboardingResourceBrokerDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + partnerCenterSellClient, err := meta.(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_onboarding_resource_broker", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteResourceBrokerOptions := &partnercentersellv1.DeleteResourceBrokerOptions{} + + deleteResourceBrokerOptions.SetBrokerID(d.Id()) + if _, ok := d.GetOk("env"); ok { + deleteResourceBrokerOptions.SetEnv(d.Get("env").(string)) + } + + _, err = partnerCenterSellClient.DeleteResourceBrokerWithContext(context, deleteResourceBrokerOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteResourceBrokerWithContext failed: %s", err.Error()), "ibm_onboarding_resource_broker", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIbmOnboardingResourceBrokerBrokerEventCreatedByUserToMap(model *partnercentersellv1.BrokerEventCreatedByUser) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.UserID != nil { + modelMap["user_id"] = *model.UserID + } + if model.UserName != nil { + modelMap["user_name"] = *model.UserName + } + return modelMap, nil +} + +func ResourceIbmOnboardingResourceBrokerBrokerEventUpdatedByUserToMap(model *partnercentersellv1.BrokerEventUpdatedByUser) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.UserID != nil { + modelMap["user_id"] = *model.UserID + } + if model.UserName != nil { + modelMap["user_name"] = *model.UserName + } + return modelMap, nil +} + +func ResourceIbmOnboardingResourceBrokerBrokerEventDeletedByUserToMap(model *partnercentersellv1.BrokerEventDeletedByUser) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.UserID != nil { + modelMap["user_id"] = *model.UserID + } + if model.UserName != nil { + modelMap["user_name"] = *model.UserName + } + return modelMap, nil +} + +func ResourceIbmOnboardingResourceBrokerBrokerPatchAsPatch(patchVals *partnercentersellv1.BrokerPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "auth_username" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["auth_username"] = nil + } + path = "auth_password" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["auth_password"] = nil + } + path = "auth_scheme" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["auth_scheme"] = nil + } + path = "resource_group_crn" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["resource_group_crn"] = nil + } + path = "state" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["state"] = nil + } + path = "broker_url" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["broker_url"] = nil + } + path = "allow_context_updates" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["allow_context_updates"] = nil + } + path = "catalog_type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["catalog_type"] = nil + } + path = "type" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["type"] = nil + } + path = "region" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["region"] = nil + } + + return patch +} diff --git a/ibm/service/partnercentersell/resource_ibm_onboarding_resource_broker_test.go b/ibm/service/partnercentersell/resource_ibm_onboarding_resource_broker_test.go new file mode 100644 index 0000000000..33d8d998cf --- /dev/null +++ b/ibm/service/partnercentersell/resource_ibm_onboarding_resource_broker_test.go @@ -0,0 +1,286 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package partnercentersell_test + +import ( + "fmt" + "testing" + + "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" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/partnercentersell" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/partnercentersellv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIbmOnboardingResourceBrokerBasic(t *testing.T) { + var conf partnercentersellv1.Broker + authUsername := "apikey" + authPassword := "random1234" + authScheme := "bearer" + brokerURL := fmt.Sprintf("https://broker-url-for-my-service.com/%d", acctest.RandIntRange(10, 100)) + typeVar := "provision_through" + name := "broker-petra-1" + authUsernameUpdate := "apikey" + authPasswordUpdate := "random1234" + authSchemeUpdate := "bearer" + brokerURLUpdate := fmt.Sprintf("https://broker-url-for-my-service.com/%d", acctest.RandIntRange(10, 100)) + typeVarUpdate := "provision_behind" + nameUpdate := "broker-petra-1" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingResourceBrokerDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingResourceBrokerConfigBasic(authUsername, authPassword, authScheme, brokerURL, typeVar, name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingResourceBrokerExists("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "auth_username", authUsername), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "auth_scheme", authScheme), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "broker_url", brokerURL), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "type", typeVar), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "name", name), + ), + ExpectNonEmptyPlan: true, + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingResourceBrokerConfigBasic(authUsernameUpdate, authPasswordUpdate, authSchemeUpdate, brokerURLUpdate, typeVarUpdate, nameUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "auth_username", authUsernameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "auth_scheme", authSchemeUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "broker_url", brokerURLUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "type", typeVarUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "name", nameUpdate), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccIbmOnboardingResourceBrokerAllArgs(t *testing.T) { + var conf partnercentersellv1.Broker + env := "current" + authUsername := "apikey" + authPassword := "random1234" + authScheme := "bearer" + state := "active" + brokerURL := fmt.Sprintf("https://broker-url-for-my-service.com/%d", acctest.RandIntRange(10, 100)) + allowContextUpdates := "false" + catalogType := "service" + typeVar := "provision_through" + name := "broker-petra-all" + region := "global" + envUpdate := "current" + authUsernameUpdate := "apikey" + authPasswordUpdate := "random1234" + authSchemeUpdate := "bearer" + stateUpdate := "active" + brokerURLUpdate := fmt.Sprintf("https://broker-url-for-my-service.com/%d", acctest.RandIntRange(10, 100)) + allowContextUpdatesUpdate := "true" + catalogTypeUpdate := "service" + typeVarUpdate := "provision_through" + nameUpdate := "broker-petra-all" + regionUpdate := "global" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckPartnerCenterSell(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmOnboardingResourceBrokerDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmOnboardingResourceBrokerConfig(env, authUsername, authPassword, authScheme, state, brokerURL, allowContextUpdates, catalogType, typeVar, name, region), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmOnboardingResourceBrokerExists("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", conf), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "env", env), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "auth_username", authUsername), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "auth_scheme", authScheme), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "state", state), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "broker_url", brokerURL), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "allow_context_updates", allowContextUpdates), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "catalog_type", catalogType), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "type", typeVar), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "name", name), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "region", region), + ), + ExpectNonEmptyPlan: true, + }, + resource.TestStep{ + Config: testAccCheckIbmOnboardingResourceBrokerConfig(envUpdate, authUsernameUpdate, authPasswordUpdate, authSchemeUpdate, stateUpdate, brokerURLUpdate, allowContextUpdatesUpdate, catalogTypeUpdate, typeVarUpdate, nameUpdate, regionUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "env", envUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "auth_username", authUsernameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "auth_scheme", authSchemeUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "state", stateUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "broker_url", brokerURLUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "allow_context_updates", allowContextUpdatesUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "catalog_type", catalogTypeUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "type", typeVarUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "name", nameUpdate), + resource.TestCheckResourceAttr("ibm_onboarding_resource_broker.onboarding_resource_broker_instance", "region", regionUpdate), + ), + ExpectNonEmptyPlan: true, + }, + resource.TestStep{ + ResourceName: "ibm_onboarding_resource_broker.onboarding_resource_broker_instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "env", + }, + }, + }, + }) +} + +func testAccCheckIbmOnboardingResourceBrokerConfigBasic(authUsername string, authPassword string, authScheme string, brokerURL string, typeVar string, name string) string { + return fmt.Sprintf(` + resource "ibm_onboarding_resource_broker" "onboarding_resource_broker_instance" { + auth_username = "%s" + auth_password = "%s" + auth_scheme = "%s" + broker_url = "%s" + type = "%s" + name = "%s" + region = "global" + state = "active" + resource_group_crn = "crn:v1:staging:public:resource-controller::a/f15038e9046e4b9587db0ae76c4cbc26::resource-group:3a3a8ae311d0486c86b0a8c09e56883d" + } + `, authUsername, authPassword, authScheme, brokerURL, typeVar, name) +} + +func testAccCheckIbmOnboardingResourceBrokerConfig(env string, authUsername string, authPassword string, authScheme string, state string, brokerURL string, allowContextUpdates string, catalogType string, typeVar string, name string, region string) string { + return fmt.Sprintf(` + + resource "ibm_onboarding_resource_broker" "onboarding_resource_broker_instance" { + env = "%s" + auth_username = "%s" + auth_password = "%s" + auth_scheme = "%s" + state = "%s" + broker_url = "%s" + allow_context_updates = %s + catalog_type = "%s" + type = "%s" + name = "%s" + region = "%s" + resource_group_crn = "crn:v1:staging:public:resource-controller::a/f15038e9046e4b9587db0ae76c4cbc26::resource-group:3a3a8ae311d0486c86b0a8c09e56883d" + } + `, env, authUsername, authPassword, authScheme, state, brokerURL, allowContextUpdates, catalogType, typeVar, name, region) +} + +func testAccCheckIbmOnboardingResourceBrokerExists(n string, obj partnercentersellv1.Broker) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + + getResourceBrokerOptions := &partnercentersellv1.GetResourceBrokerOptions{} + + getResourceBrokerOptions.SetBrokerID(rs.Primary.ID) + + broker, _, err := partnerCenterSellClient.GetResourceBroker(getResourceBrokerOptions) + if err != nil { + return err + } + + obj = *broker + return nil + } +} + +func testAccCheckIbmOnboardingResourceBrokerDestroy(s *terraform.State) error { + partnerCenterSellClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).PartnerCenterSellV1() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_onboarding_resource_broker" { + continue + } + + getResourceBrokerOptions := &partnercentersellv1.GetResourceBrokerOptions{} + + getResourceBrokerOptions.SetBrokerID(rs.Primary.ID) + + // Try to find the key + resourceBroker, _, err := partnerCenterSellClient.GetResourceBroker(getResourceBrokerOptions) + + if err != nil { + return fmt.Errorf("Error checking for onboarding_resource_broker (%s) has been destroyed: %s", rs.Primary.ID, err) + } else if *resourceBroker.State != "removed" { + return fmt.Errorf("onboarding_resource_broker still exists: %s", rs.Primary.ID) + } + } + + return nil +} + +func TestResourceIbmOnboardingResourceBrokerBrokerEventCreatedByUserToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["user_id"] = "testString" + model["user_name"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.BrokerEventCreatedByUser) + model.UserID = core.StringPtr("testString") + model.UserName = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingResourceBrokerBrokerEventCreatedByUserToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingResourceBrokerBrokerEventUpdatedByUserToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["user_id"] = "testString" + model["user_name"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.BrokerEventUpdatedByUser) + model.UserID = core.StringPtr("testString") + model.UserName = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingResourceBrokerBrokerEventUpdatedByUserToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestResourceIbmOnboardingResourceBrokerBrokerEventDeletedByUserToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["user_id"] = "testString" + model["user_name"] = "testString" + + assert.Equal(t, result, model) + } + + model := new(partnercentersellv1.BrokerEventDeletedByUser) + model.UserID = core.StringPtr("testString") + model.UserName = core.StringPtr("testString") + + result, err := partnercentersell.ResourceIbmOnboardingResourceBrokerBrokerEventDeletedByUserToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/power/data_source_ibm_pi_dhcp.go b/ibm/service/power/data_source_ibm_pi_dhcp.go index 621a7e3d49..9d4d4c3aa8 100644 --- a/ibm/service/power/data_source_ibm_pi_dhcp.go +++ b/ibm/service/power/data_source_ibm_pi_dhcp.go @@ -44,12 +44,12 @@ func DataSourceIBMPIDhcp() *schema.Resource { Description: "List of DHCP Server PVM Instance leases.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - Attr_DhcpLeaseInstanceIP: { + Attr_InstanceIP: { Computed: true, Description: "IP of the PVM Instance.", Type: schema.TypeString, }, - Attr_DhcpLeaseInstanceMac: { + Attr_InstanceMac: { Computed: true, Description: "MAC Address of the PVM Instance.", Type: schema.TypeString, @@ -58,7 +58,7 @@ func DataSourceIBMPIDhcp() *schema.Resource { }, Type: schema.TypeList, }, - Attr_DhcpNetworkID: { + Attr_NetworkID: { Computed: true, Description: "ID of the DHCP Server private network.", Type: schema.TypeString, @@ -99,7 +99,7 @@ func dataSourceIBMPIDhcpRead(ctx context.Context, d *schema.ResourceData, meta i if dhcpServer.Network != nil { dhcpNetwork := dhcpServer.Network if dhcpNetwork.ID != nil { - d.Set(Attr_DhcpNetworkID, *dhcpNetwork.ID) + d.Set(Attr_NetworkID, *dhcpNetwork.ID) } if dhcpNetwork.Name != nil { d.Set(Attr_NetworkName, *dhcpNetwork.Name) @@ -110,8 +110,8 @@ func dataSourceIBMPIDhcpRead(ctx context.Context, d *schema.ResourceData, meta i leaseList := make([]map[string]string, len(dhcpServer.Leases)) for i, lease := range dhcpServer.Leases { leaseList[i] = map[string]string{ - Attr_DhcpLeaseInstanceIP: *lease.InstanceIP, - Attr_DhcpLeaseInstanceMac: *lease.InstanceMacAddress, + Attr_InstanceIP: *lease.InstanceIP, + Attr_InstanceMac: *lease.InstanceMacAddress, } } d.Set(Attr_Leases, leaseList) diff --git a/ibm/service/power/data_source_ibm_pi_dhcps.go b/ibm/service/power/data_source_ibm_pi_dhcps.go index 02344815c1..67377a7d2e 100644 --- a/ibm/service/power/data_source_ibm_pi_dhcps.go +++ b/ibm/service/power/data_source_ibm_pi_dhcps.go @@ -29,7 +29,7 @@ func DataSourceIBMPIDhcps() *schema.Resource { }, // Attributes - Attr_DhcpServers: { + Attr_Servers: { Computed: true, Description: "List of all the DHCP Servers.", Elem: &schema.Resource{ @@ -39,7 +39,7 @@ func DataSourceIBMPIDhcps() *schema.Resource { Description: "ID of the DHCP Server.", Type: schema.TypeString, }, - Attr_DhcpNetworkID: { + Attr_NetworkID: { Computed: true, Description: "ID of the DHCP Server private network.", Type: schema.TypeString, @@ -85,17 +85,17 @@ func dataSourceIBMPIDhcpServersRead(ctx context.Context, d *schema.ResourceData, if dhcpServer.Network != nil { dhcpNetwork := dhcpServer.Network if dhcpNetwork.ID != nil { - d.Set(Attr_DhcpNetworkID, *dhcpNetwork.ID) + server[Attr_NetworkID] = *dhcpNetwork.ID } if dhcpNetwork.Name != nil { - d.Set(Attr_NetworkName, *dhcpNetwork.Name) + server[Attr_NetworkName] = *dhcpNetwork.Name } } servers = append(servers, server) } var genID, _ = uuid.GenerateUUID() d.SetId(genID) - d.Set(Attr_DhcpServers, servers) + d.Set(Attr_Servers, servers) return nil } diff --git a/ibm/service/power/data_source_ibm_pi_instance.go b/ibm/service/power/data_source_ibm_pi_instance.go index 042d623654..c8ac038a9c 100644 --- a/ibm/service/power/data_source_ibm_pi_instance.go +++ b/ibm/service/power/data_source_ibm_pi_instance.go @@ -128,6 +128,12 @@ func DataSourceIBMPIInstance() *schema.Resource { Description: "The MAC address of the instance.", Type: schema.TypeString, }, + Attr_Macaddress: { + Computed: true, + Deprecated: "Deprecated, use mac_address instead", + Description: "The MAC address of the instance.", + Type: schema.TypeString, + }, Attr_NetworkID: { Computed: true, Description: "The network ID of the instance.", diff --git a/ibm/service/power/data_source_ibm_pi_instance_ip.go b/ibm/service/power/data_source_ibm_pi_instance_ip.go index d35c65b126..624affe36e 100644 --- a/ibm/service/power/data_source_ibm_pi_instance_ip.go +++ b/ibm/service/power/data_source_ibm_pi_instance_ip.go @@ -56,7 +56,7 @@ func DataSourceIBMPIInstanceIP() *schema.Resource { Description: "The IP octet of the network that is attached to this instance.", Type: schema.TypeString, }, - Attr_MacAddress: { + Attr_Macaddress: { Computed: true, Description: "The MAC address of the network that is attached to this instance.", Type: schema.TypeString, @@ -96,7 +96,7 @@ func dataSourceIBMPIInstancesIPRead(ctx context.Context, d *schema.ResourceData, d.SetId(network.NetworkID) d.Set(Attr_ExternalIP, network.ExternalIP) d.Set(Attr_IP, network.IPAddress) - d.Set(Attr_MacAddress, network.MacAddress) + d.Set(Attr_Macaddress, network.MacAddress) d.Set(Attr_NetworkID, network.NetworkID) d.Set(Attr_Type, network.Type) diff --git a/ibm/service/power/data_source_ibm_pi_instances.go b/ibm/service/power/data_source_ibm_pi_instances.go index 2ccdebf849..481e4e8ba0 100644 --- a/ibm/service/power/data_source_ibm_pi_instances.go +++ b/ibm/service/power/data_source_ibm_pi_instances.go @@ -104,6 +104,12 @@ func DataSourceIBMPIInstances() *schema.Resource { Description: "The MAC address of the instance.", Type: schema.TypeString, }, + Attr_Macaddress: { + Computed: true, + Deprecated: "Deprecated, use mac_address instead", + Description: "The MAC address of the instance.", + Type: schema.TypeString, + }, Attr_NetworkID: { Computed: true, Description: "The network ID of the instance.", diff --git a/ibm/service/power/data_source_ibm_pi_network_port.go b/ibm/service/power/data_source_ibm_pi_network_port.go index 5fef77e7af..fdd974ed94 100644 --- a/ibm/service/power/data_source_ibm_pi_network_port.go +++ b/ibm/service/power/data_source_ibm_pi_network_port.go @@ -51,12 +51,12 @@ func DataSourceIBMPINetworkPort() *schema.Resource { Description: "Network port href.", Type: schema.TypeString, }, - Attr_IPAddress: { + Attr_IPaddress: { Computed: true, Description: "The IP address of the port.", Type: schema.TypeString, }, - Attr_MacAddress: { + Attr_Macaddress: { Computed: true, Description: "The MAC address of the port.", Type: schema.TypeString, @@ -111,8 +111,8 @@ func flattenNetworkPorts(networkPorts []*models.NetworkPort) interface{} { l := map[string]interface{}{ Attr_Description: i.Description, Attr_Href: i.Href, - Attr_IPAddress: *i.IPAddress, - Attr_MacAddress: *i.MacAddress, + Attr_IPaddress: *i.IPAddress, + Attr_Macaddress: *i.MacAddress, Attr_PortID: *i.PortID, Attr_PublicIP: i.ExternalIP, Attr_Status: *i.Status, diff --git a/ibm/service/power/ibm_pi_constants.go b/ibm/service/power/ibm_pi_constants.go index 7dc644055c..9ab77d13be 100644 --- a/ibm/service/power/ibm_pi_constants.go +++ b/ibm/service/power/ibm_pi_constants.go @@ -10,19 +10,20 @@ const ( Arg_AffinityVolume = "pi_affinity_volume" Arg_AntiAffinityInstances = "pi_anti_affinity_instances" Arg_AntiAffinityVolumes = "pi_anti_affinity_volumes" + Arg_Cidr = "pi_cidr" + Arg_CloudConnectionID = "pi_cloud_connection_id" Arg_CloudConnectionName = "pi_cloud_connection_name" Arg_CloudInstanceID = "pi_cloud_instance_id" + Arg_ConsistencyGroupName = "pi_consistency_group_name" Arg_Datacenter = "pi_datacenter" Arg_DatacenterZone = "pi_datacenter_zone" Arg_DeploymentTarget = "pi_deployment_target" Arg_DeploymentType = "pi_deployment_type" Arg_Description = "pi_description" - Arg_DhcpCidr = "pi_cidr" - Arg_DhcpCloudConnectionID = "pi_cloud_connection_id" - Arg_DhcpDnsServer = "pi_dns_server" Arg_DhcpID = "pi_dhcp_id" Arg_DhcpName = "pi_dhcp_name" Arg_DhcpSnatEnabled = "pi_dhcp_snat_enabled" + Arg_DnsServer = "pi_dns_server" Arg_HealthStatus = "pi_health_status" Arg_Host = "pi_host" Arg_HostGroupID = "pi_host_group_id" @@ -47,7 +48,6 @@ const ( Arg_NetworkName = "pi_network_name" Arg_NetworkPortDescription = "pi_network_port_description" Arg_NetworkPortIPAddress = "pi_network_port_ipaddress" - Arg_PIInstanceSharedProcessorPool = "pi_shared_processor_pool" Arg_PinPolicy = "pi_pin_policy" Arg_PlacementGroupID = "pi_placement_group_id" Arg_PlacementGroupName = "pi_placement_group_name" @@ -92,6 +92,7 @@ const ( Arg_VolumeCloneName = "pi_volume_clone_name" Arg_VolumeCloneTaskID = "pi_volume_clone_task_id" Arg_VolumeGroupID = "pi_volume_group_id" + Arg_VolumeGroupName = "pi_volume_group_name" Arg_VolumeID = "pi_volume_id" Arg_VolumeIDs = "pi_volume_ids" Arg_VolumeName = "pi_volume_name" @@ -102,6 +103,10 @@ const ( Arg_VolumeType = "pi_volume_type" Arg_VTL = "vtl" + // Duplicate Arguments, will be removed as refactoring take course. + PIVolumeGroupID = "pi_volume_group_id" + PIVolumeOnboardingID = "pi_volume_onboarding_id" + // Attributes Attr_Access = "access" Attr_AccessConfig = "access_config" @@ -159,15 +164,7 @@ const ( Attr_Description = "description" Attr_Details = "details" Attr_DhcpID = "dhcp_id" - Attr_DhcpLeaseInstanceIP = "instance_ip" - Attr_DhcpLeaseInstanceMac = "instance_mac" - Attr_DhcpLeases = "leases" Attr_DhcpManaged = "dhcp_managed" - Attr_DhcpNetworkDeprecated = "network" // to deprecate - Attr_DhcpNetworkID = "network_id" - Attr_DhcpNetworkName = "network_name" - Attr_DhcpServers = "servers" - Attr_DhcpStatus = "status" Attr_DisasterRecoveryLocations = "disaster_recovery_locations" Attr_DiskFormat = "disk_format" Attr_DiskType = "disk_type" @@ -208,12 +205,16 @@ const ( Attr_Images = "images" Attr_ImageType = "image_type" Attr_InputVolumes = "input_volumes" + Attr_InstanceID = "instance_id" + Attr_InstanceIP = "instance_ip" + Attr_InstanceMac = "instance_mac" Attr_Instances = "instances" Attr_InstanceSnapshots = "instance_snapshots" Attr_InstanceVolumes = "instance_volumes" Attr_IOThrottleRate = "io_throttle_rate" Attr_IP = "ip" - Attr_IPAddress = "ipaddress" + Attr_IPAddress = "ip_address" + Attr_IPaddress = "ipaddress" Attr_IPOctet = "ipoctet" Attr_IsActive = "is_active" Attr_Jumbo = "jumbo" @@ -228,7 +229,8 @@ const ( Attr_LicenseRepositoryCapacity = "license_repository_capacity" Attr_LicenseType = "license_type" Attr_Location = "location" - Attr_MacAddress = "macaddress" + Attr_MacAddress = "mac_address" + Attr_Macaddress = "macaddress" Attr_MasterChangedVolumeName = "master_changed_volume_name" Attr_MasterVolumeName = "master_volume_name" Attr_Max = "max" @@ -264,9 +266,8 @@ const ( Attr_NumberOfVolumes = "number_of_volumes" Attr_Onboardings = "onboardings" Attr_OperatingSystem = "operating_system" + Attr_OSType = "os_type" Attr_PercentComplete = "percent_complete" - Attr_PIInstanceSharedProcessorPool = "shared_processor_pool" - Attr_PIInstanceSharedProcessorPoolID = "shared_processor_pool_id" Attr_PinPolicy = "pin_policy" Attr_PlacementGroupID = "placement_group_id" Attr_PlacementGroups = "placement_groups" @@ -304,6 +305,7 @@ const ( Attr_SAPS = "saps" Attr_Secondaries = "secondaries" Attr_ServerName = "server_name" + Attr_Servers = "servers" Attr_Shareable = "shreable" Attr_SharedCoreRatio = "shared_core_ratio" Attr_SharedProcessorPool = "shared_processor_pool" @@ -317,14 +319,12 @@ const ( Attr_SharedProcessorPoolInstanceMemory = "memory" Attr_SharedProcessorPoolInstanceName = "name" Attr_SharedProcessorPoolInstances = "instances" - Attr_SharedProcessorPoolInstanceStatus = "status" Attr_SharedProcessorPoolInstanceUncapped = "uncapped" Attr_SharedProcessorPoolInstanceVcpus = "vcpus" Attr_SharedProcessorPoolName = "name" Attr_SharedProcessorPoolPlacementGroups = "spp_placement_groups" Attr_SharedProcessorPoolReservedCores = "reserved_cores" Attr_SharedProcessorPools = "shared_processor_pools" - Attr_SharedProcessorPoolStatus = "status" Attr_SharedProcessorPoolStatusDetail = "status_detail" Attr_Size = "size" Attr_SnapshotID = "snapshot_id" @@ -378,8 +378,10 @@ const ( Attr_Vendor = "vendor" Attr_VirtualCoresAssigned = "virtual_cores_assigned" Attr_VLanID = "vlan_id" + Attr_VolumeGroupID = "volume_group_id" Attr_VolumeGroupName = "volume_group_name" Attr_VolumeGroups = "volume_groups" + Attr_VolumeGroupStatus = "volume_group_status" Attr_VolumeID = "volume_id" Attr_VolumeIDs = "volume_ids" Attr_VolumePool = "volume_pool" @@ -400,6 +402,18 @@ const ( Attr_WorkspaceType = "pi_workspace_type" Attr_WWN = "wwn" + // Duplicate Attributes, will be removed as refactoring take course. + PICloudConnectionClassicGreSource = "gre_source_address" + PICloudConnectionConnectionMode = "connection_mode" + PICloudConnectionIBMIPAddress = "ibm_ip_address" + PICloudConnectionId = "cloud_connection_id" + PICloudConnectionPort = "port" + PICloudConnectionUserIPAddress = "user_ip_address" + PIDRLocation = "location" + PIPlacementGroupID = "placement_group_id" + PIPlacementGroupMembers = "members" + PIVPNConnectionDeadPeerDetectionAction = "action" + // OS Type OS_IBMI = "ibmi" StockVTL = "stock-vtl" @@ -423,6 +437,7 @@ const ( Netweaver = "Netweaver" None = "none" OK = "OK" + PER = "power-edge-router" Prefix = "prefix" Private = "private" Public = "public" @@ -451,12 +466,12 @@ const ( State_Adding = "adding" State_Available = "available" State_Build = "build" - State_BUILD = "BUILD" + State_Building = "building" State_Completed = "completed" + State_Configuring = "configuring" State_Creating = "creating" State_Deleted = "deleted" State_Deleting = "deleting" - State_DELETING = "DELETING" State_Down = "down" State_Error = "error" State_ERROR = "ERROR" @@ -465,70 +480,36 @@ const ( State_Inactive = "inactive" State_InProgress = "in progress" State_InUse = "in-use" - State_NotFound = "Not Found" + State_NotFound = "not found" State_Pending = "pending" State_PENDING = "PENDING" State_PendingReclamation = "pending_reclamation" State_Provisioning = "provisioning" State_Removed = "removed" + State_Resize = "resize" State_RESIZE = "RESIZE" State_Retry = "retry" State_Shutoff = "shutoff" + State_Stopping = "stopping" State_SHUTOFF = "SHUTOFF" State_Up = "up" + State_Updating = "updating" + State_VerifyResize = "verify_resize" Status_Active = "ACTIVE" Status_Deleting = "deleting" Status_Error = "ERROR" Status_Pending = "PENDING" Status_Shutoff = "SHUTOFF" - // TODO: Second Half Cleanup, remove extra variables - - // SAP Profile - PISAPProfiles = "profiles" - PISAPProfileCertified = "certified" - PISAPProfileCores = "cores" - PISAPProfileMemory = "memory" - PISAPProfileID = "profile_id" - PISAPProfileType = "type" - - //Added timeout values for warning and active status - warningTimeOut = 60 * time.Second - activeTimeOut = 2 * time.Minute + // Timeout values + Timeout_Active = 2 * time.Minute + Timeout_Delay = 60 * time.Second + Timeout_Warning = 60 * time.Second - PIConsoleLanguageCode = "pi_language_code" - PICloudConnectionId = "cloud_connection_id" - PICloudConnectionStatus = "status" - PICloudConnectionIBMIPAddress = "ibm_ip_address" - PICloudConnectionUserIPAddress = "user_ip_address" - PICloudConnectionPort = "port" - PICloudConnectionClassicGreSource = "gre_source_address" - PICloudConnectionConnectionMode = "connection_mode" - PIInstanceDeploymentType = "pi_deployment_type" - PIInstanceMigratable = "pi_migratable" - PIInstanceNetwork = "pi_network" - PIInstanceStoragePool = "pi_storage_pool" - PIInstanceStorageType = "pi_storage_type" - PISAPInstanceProfileID = "pi_sap_profile_id" - PISAPInstanceDeploymentType = "pi_sap_deployment_type" - PIInstanceSharedProcessorPool = "pi_shared_processor_pool" - PIInstanceStorageConnection = "pi_storage_connection" - PIInstanceStoragePoolAffinity = "pi_storage_pool_affinity" - - PIInstanceUserData = "pi_user_data" - PIInstanceVolumeIds = "pi_volume_ids" - - // Placement Group - PIPlacementGroupID = "placement_group_id" - PIPlacementGroupMembers = "members" + // TODO: Second Half Cleanup, remove extra variables - // Volume - PIVolumeIds = "pi_volume_ids" - PIAffinityPolicy = "pi_affinity_policy" - PIAffinityVolume = "pi_affinity_volume" - PIAffinityInstance = "pi_affinity_instance" - PIAntiAffinityInstances = "pi_anti_affinity_instances" - PIAntiAffinityVolumes = "pi_anti_affinity_volumes" + PIConsoleLanguageCode = "pi_language_code" + PIInstanceMigratable = "pi_migratable" // Volume Clone PIVolumeCloneName = "pi_volume_clone_name" @@ -538,18 +519,12 @@ const ( // IBM PI Volume Group PIVolumeGroupName = "pi_volume_group_name" PIVolumeGroupConsistencyGroupName = "pi_consistency_group_name" - PIVolumeGroupID = "pi_volume_group_id" PIVolumeGroupAction = "pi_volume_group_action" - PIVolumeOnboardingID = "pi_volume_onboarding_id" - - // Disaster Recovery Location - PIDRLocation = "location" // VPN PIVPNConnectionId = "connection_id" PIVPNConnectionStatus = "connection_status" PIVPNConnectionDeadPeerDetection = "dead_peer_detections" - PIVPNConnectionDeadPeerDetectionAction = "action" PIVPNConnectionDeadPeerDetectionInterval = "interval" PIVPNConnectionDeadPeerDetectionThreshold = "threshold" PIVPNConnectionLocalGatewayAddress = "local_gateway_address" @@ -563,5 +538,4 @@ const ( PIWorkspaceDatacenter = "pi_datacenter" PIWorkspaceResourceGroup = "pi_resource_group_id" PIWorkspacePlan = "pi_plan" - PIVirtualOpticalDevice = "pi_virtual_optical_device" ) diff --git a/ibm/service/power/resource_ibm_pi_cloud_connection.go b/ibm/service/power/resource_ibm_pi_cloud_connection.go index a8a1771891..76da0e4932 100644 --- a/ibm/service/power/resource_ibm_pi_cloud_connection.go +++ b/ibm/service/power/resource_ibm_pi_cloud_connection.go @@ -130,7 +130,7 @@ func ResourceIBMPICloudConnection() *schema.Resource { Computed: true, Description: "Cloud connection ID", }, - PICloudConnectionStatus: { + Attr_Status: { Type: schema.TypeString, Computed: true, Description: "Link status", @@ -443,7 +443,7 @@ func resourceIBMPICloudConnectionRead(ctx context.Context, d *schema.ResourceDat d.Set(helpers.PICloudConnectionMetered, cloudConnection.Metered) d.Set(PICloudConnectionIBMIPAddress, cloudConnection.IbmIPAddress) d.Set(PICloudConnectionUserIPAddress, cloudConnection.UserIPAddress) - d.Set(PICloudConnectionStatus, cloudConnection.LinkStatus) + d.Set(Attr_Status, cloudConnection.LinkStatus) d.Set(PICloudConnectionPort, cloudConnection.Port) d.Set(helpers.PICloudConnectionSpeed, cloudConnection.Speed) d.Set(helpers.PICloudInstanceId, cloudInstanceID) diff --git a/ibm/service/power/resource_ibm_pi_dhcp.go b/ibm/service/power/resource_ibm_pi_dhcp.go index 595ea85cf4..acfd7eabc5 100644 --- a/ibm/service/power/resource_ibm_pi_dhcp.go +++ b/ibm/service/power/resource_ibm_pi_dhcp.go @@ -7,17 +7,18 @@ import ( "context" "fmt" "log" + "strings" "time" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - - st "github.com/IBM-Cloud/power-go-client/clients/instance" + "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/power-go-client/errors" "github.com/IBM-Cloud/power-go-client/power/client/p_cloud_service_d_h_c_p" "github.com/IBM-Cloud/power-go-client/power/models" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) func ResourceIBMPIDhcp() *schema.Resource { @@ -32,86 +33,85 @@ func ResourceIBMPIDhcp() *schema.Resource { }, Schema: map[string]*schema.Schema{ - // Required Arguments - Arg_CloudInstanceID: { - Type: schema.TypeString, - Required: true, - Description: "PI cloud instance ID", - ForceNew: true, - }, - - // Optional Arguments - Arg_DhcpCidr: { - Type: schema.TypeString, - Optional: true, + // Arguments + Arg_Cidr: { Description: "Optional cidr for DHCP private network", ForceNew: true, - }, - Arg_DhcpCloudConnectionID: { - Type: schema.TypeString, Optional: true, + Type: schema.TypeString, + }, + Arg_CloudConnectionID: { Description: "Optional cloud connection uuid to connect with DHCP private network", ForceNew: true, - }, - Arg_DhcpDnsServer: { - Type: schema.TypeString, Optional: true, - Description: "Optional DNS Server for DHCP service", - ForceNew: true, + Type: schema.TypeString, + }, + Arg_CloudInstanceID: { + Description: "PI cloud instance ID", + ForceNew: true, + Required: true, + Type: schema.TypeString, + ValidateFunc: validation.NoZeroValues, }, Arg_DhcpName: { - Type: schema.TypeString, - Optional: true, Description: "Optional name of DHCP Service (will be prefixed by DHCP identifier)", ForceNew: true, + Optional: true, + Type: schema.TypeString, }, Arg_DhcpSnatEnabled: { - Type: schema.TypeBool, - Optional: true, Default: true, Description: "Indicates if SNAT will be enabled for the DHCP service", ForceNew: true, + Optional: true, + Type: schema.TypeBool, + }, + Arg_DnsServer: { + Description: "Optional DNS Server for DHCP service", + ForceNew: true, + Optional: true, + Type: schema.TypeString, }, // Attributes Attr_DhcpID: { - Type: schema.TypeString, Computed: true, Description: "The ID of the DHCP Server", + Type: schema.TypeString, }, - Attr_DhcpLeases: { - Type: schema.TypeList, + Attr_Leases: { Computed: true, Description: "The list of DHCP Server PVM Instance leases", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - Attr_DhcpLeaseInstanceIP: { - Type: schema.TypeString, + Attr_InstanceIP: { Computed: true, Description: "The IP of the PVM Instance", - }, - Attr_DhcpLeaseInstanceMac: { Type: schema.TypeString, + }, + Attr_InstanceMac: { Computed: true, Description: "The MAC Address of the PVM Instance", + Type: schema.TypeString, }, }, }, + Type: schema.TypeList, }, - Attr_DhcpNetworkID: { - Type: schema.TypeString, + Attr_NetworkID: { Computed: true, Description: "The ID of the DHCP Server private network", - }, - Attr_DhcpNetworkName: { Type: schema.TypeString, + }, + Attr_NetworkName: { Computed: true, Description: "The name of the DHCP Server private network", - }, - Attr_DhcpStatus: { Type: schema.TypeString, + }, + Attr_Status: { Computed: true, Description: "The status of the DHCP Server", + Type: schema.TypeString, }, }, } @@ -130,15 +130,15 @@ func resourceIBMPIDhcpCreate(ctx context.Context, d *schema.ResourceData, meta i // arguments cloudInstanceID := d.Get(Arg_CloudInstanceID).(string) - if cidr, ok := d.GetOk(Arg_DhcpCidr); ok { + if cidr, ok := d.GetOk(Arg_Cidr); ok { c := cidr.(string) body.Cidr = &c } - if cloudConnectionID, ok := d.GetOk(Arg_DhcpCloudConnectionID); ok { + if cloudConnectionID, ok := d.GetOk(Arg_CloudConnectionID); ok { c := cloudConnectionID.(string) body.CloudConnectionID = &c } - if dnsServer, ok := d.GetOk(Arg_DhcpDnsServer); ok { + if dnsServer, ok := d.GetOk(Arg_DnsServer); ok { d := dnsServer.(string) body.DNSServer = &d } @@ -150,7 +150,7 @@ func resourceIBMPIDhcpCreate(ctx context.Context, d *schema.ResourceData, meta i body.SnatEnabled = &snatEnabled // create dhcp - client := st.NewIBMPIDhcpClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIDhcpClient(ctx, sess, cloudInstanceID) dhcpServer, err := client.Create(body) if err != nil { log.Printf("[DEBUG] create DHCP failed %v", err) @@ -169,7 +169,6 @@ func resourceIBMPIDhcpCreate(ctx context.Context, d *schema.ResourceData, meta i } func resourceIBMPIDhcpRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - // session sess, err := meta.(conns.ClientSession).IBMPISession() if err != nil { @@ -183,7 +182,7 @@ func resourceIBMPIDhcpRead(ctx context.Context, d *schema.ResourceData, meta int } // get dhcp - client := st.NewIBMPIDhcpClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIDhcpClient(ctx, sess, cloudInstanceID) dhcpServer, err := client.Get(dhcpID) if err != nil { uErr := errors.Unwrap(err) @@ -200,15 +199,15 @@ func resourceIBMPIDhcpRead(ctx context.Context, d *schema.ResourceData, meta int // set attributes d.SetId(fmt.Sprintf("%s/%s", cloudInstanceID, *dhcpServer.ID)) d.Set(Attr_DhcpID, *dhcpServer.ID) - d.Set(Attr_DhcpStatus, *dhcpServer.Status) + d.Set(Attr_Status, *dhcpServer.Status) if dhcpServer.Network != nil { dhcpNetwork := dhcpServer.Network if dhcpNetwork.ID != nil { - d.Set(Attr_DhcpNetworkID, *dhcpNetwork.ID) + d.Set(Attr_NetworkID, *dhcpNetwork.ID) } if dhcpNetwork.Name != nil { - d.Set(Attr_DhcpNetworkName, *dhcpNetwork.Name) + d.Set(Attr_NetworkName, *dhcpNetwork.Name) } } @@ -216,17 +215,17 @@ func resourceIBMPIDhcpRead(ctx context.Context, d *schema.ResourceData, meta int leaseList := make([]map[string]string, len(dhcpServer.Leases)) for i, lease := range dhcpServer.Leases { leaseList[i] = map[string]string{ - Attr_DhcpLeaseInstanceIP: *lease.InstanceIP, - Attr_DhcpLeaseInstanceMac: *lease.InstanceMacAddress, + Attr_InstanceIP: *lease.InstanceIP, + Attr_InstanceMac: *lease.InstanceMacAddress, } } - d.Set(Attr_DhcpLeases, leaseList) + d.Set(Attr_Leases, leaseList) } return nil } -func resourceIBMPIDhcpDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceIBMPIDhcpDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { // session sess, err := meta.(conns.ClientSession).IBMPISession() if err != nil { @@ -240,7 +239,7 @@ func resourceIBMPIDhcpDelete(ctx context.Context, d *schema.ResourceData, meta i } // delete dhcp - client := st.NewIBMPIDhcpClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIDhcpClient(ctx, sess, cloudInstanceID) err = client.Delete(dhcpID) if err != nil { uErr := errors.Unwrap(err) @@ -264,20 +263,20 @@ func resourceIBMPIDhcpDelete(ctx context.Context, d *schema.ResourceData, meta i return nil } -func waitForIBMPIDhcpStatus(ctx context.Context, client *st.IBMPIDhcpClient, dhcpID string, timeout time.Duration) (interface{}, error) { - stateConf := &resource.StateChangeConf{ - Pending: []string{"building"}, - Target: []string{"active"}, +func waitForIBMPIDhcpStatus(ctx context.Context, client *instance.IBMPIDhcpClient, dhcpID string, timeout time.Duration) (interface{}, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{State_Building}, + Target: []string{State_Active}, Refresh: func() (interface{}, string, error) { dhcpServer, err := client.Get(dhcpID) if err != nil { log.Printf("[DEBUG] get DHCP failed %v", err) return nil, "", err } - if *dhcpServer.Status != Status_Active { - return dhcpServer, "building", nil + if strings.ToLower(*dhcpServer.Status) != State_Active { + return dhcpServer, State_Building, nil } - return dhcpServer, "active", nil + return dhcpServer, State_Active, nil }, Timeout: timeout, Delay: 10 * time.Second, @@ -286,17 +285,17 @@ func waitForIBMPIDhcpStatus(ctx context.Context, client *st.IBMPIDhcpClient, dhc return stateConf.WaitForStateContext(ctx) } -func waitForIBMPIDhcpDeleted(ctx context.Context, client *st.IBMPIDhcpClient, dhcpID string, timeout time.Duration) (interface{}, error) { - stateConf := &resource.StateChangeConf{ - Pending: []string{"deleting"}, - Target: []string{"deleted"}, +func waitForIBMPIDhcpDeleted(ctx context.Context, client *instance.IBMPIDhcpClient, dhcpID string, timeout time.Duration) (interface{}, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{State_Deleting}, + Target: []string{State_Deleted}, Refresh: func() (interface{}, string, error) { dhcpServer, err := client.Get(dhcpID) if err != nil { log.Printf("[DEBUG] dhcp does not exist %v", err) - return dhcpServer, "deleted", nil + return dhcpServer, State_Deleted, nil } - return dhcpServer, "deleting", nil + return dhcpServer, State_Deleting, nil }, Timeout: timeout, Delay: 10 * time.Second, diff --git a/ibm/service/power/resource_ibm_pi_dhcp_test.go b/ibm/service/power/resource_ibm_pi_dhcp_test.go index 169936d6fa..87ecc8a512 100644 --- a/ibm/service/power/resource_ibm_pi_dhcp_test.go +++ b/ibm/service/power/resource_ibm_pi_dhcp_test.go @@ -10,13 +10,12 @@ import ( "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + + "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "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" - - st "github.com/IBM-Cloud/power-go-client/clients/instance" ) func TestAccIBMPIDhcpbasic(t *testing.T) { @@ -52,7 +51,7 @@ func testAccCheckIBMPIDhcpDestroy(s *terraform.State) error { return err } - client := st.NewIBMPIDhcpClient(context.Background(), sess, cloudInstanceID) + client := instance.NewIBMPIDhcpClient(context.Background(), sess, cloudInstanceID) _, err = client.Get(dhcpID) if err == nil { return fmt.Errorf("PI DHCP still exists: %s", rs.Primary.ID) @@ -61,6 +60,7 @@ func testAccCheckIBMPIDhcpDestroy(s *terraform.State) error { return nil } + func testAccCheckIBMPIDhcpExists(n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -80,7 +80,7 @@ func testAccCheckIBMPIDhcpExists(n string) resource.TestCheckFunc { if err != nil { return err } - client := st.NewIBMPIDhcpClient(context.Background(), sess, cloudInstanceID) + client := instance.NewIBMPIDhcpClient(context.Background(), sess, cloudInstanceID) _, err = client.Get(dhcpID) if err != nil { @@ -93,10 +93,9 @@ func testAccCheckIBMPIDhcpExists(n string) resource.TestCheckFunc { func testAccCheckIBMPIDhcpConfig() string { return fmt.Sprintf(` - resource "ibm_pi_dhcp" "dhcp_service" { - pi_cloud_instance_id = "%s" - } - `, acc.Pi_cloud_instance_id) + resource "ibm_pi_dhcp" "dhcp_service" { + pi_cloud_instance_id = "%s" + }`, acc.Pi_cloud_instance_id) } func TestAccIBMPIDhcpWithCidrName(t *testing.T) { @@ -130,8 +129,7 @@ func testAccCheckIBMPIDhcpWithCidrNameConfig(name string) string { pi_cloud_instance_id = "%[1]s" pi_dhcp_name = "%[2]s" pi_cidr = "192.168.103.0/24" - } - `, acc.Pi_cloud_instance_id, name) + }`, acc.Pi_cloud_instance_id, name) } func TestAccIBMPIDhcpSNAT(t *testing.T) { @@ -154,9 +152,8 @@ func TestAccIBMPIDhcpSNAT(t *testing.T) { func testAccCheckIBMPIDhcpConfigWithSNATDisabled() string { return fmt.Sprintf(` - resource "ibm_pi_dhcp" "dhcp_service" { - pi_cloud_instance_id = "%s" - pi_dhcp_snat_enabled = false - } - `, acc.Pi_cloud_instance_id) + resource "ibm_pi_dhcp" "dhcp_service" { + pi_cloud_instance_id = "%s" + pi_dhcp_snat_enabled = false + }`, acc.Pi_cloud_instance_id) } diff --git a/ibm/service/power/resource_ibm_pi_image.go b/ibm/service/power/resource_ibm_pi_image.go index fa3bdff737..e42f54ff3a 100644 --- a/ibm/service/power/resource_ibm_pi_image.go +++ b/ibm/service/power/resource_ibm_pi_image.go @@ -123,41 +123,41 @@ func ResourceIBMPIImage() *schema.Resource { Description: "Storage pool where the image will be loaded, if provided then pi_affinity_policy will be ignored", ForceNew: true, }, - PIAffinityPolicy: { + Arg_AffinityPolicy: { Type: schema.TypeString, Optional: true, Description: "Affinity policy for image; ignored if pi_image_storage_pool provided; for policy affinity requires one of pi_affinity_instance or pi_affinity_volume to be specified; for policy anti-affinity requires one of pi_anti_affinity_instances or pi_anti_affinity_volumes to be specified", ValidateFunc: validate.ValidateAllowedStringValues([]string{"affinity", "anti-affinity"}), ForceNew: true, }, - PIAffinityVolume: { + Arg_AffinityVolume: { Type: schema.TypeString, Optional: true, Description: "Volume (ID or Name) to base storage affinity policy against; required if requesting affinity and pi_affinity_instance is not provided", - ConflictsWith: []string{PIAffinityInstance}, + ConflictsWith: []string{Arg_AffinityInstance}, ForceNew: true, }, - PIAffinityInstance: { + Arg_AffinityInstance: { Type: schema.TypeString, Optional: true, Description: "PVM Instance (ID or Name) to base storage affinity policy against; required if requesting storage affinity and pi_affinity_volume is not provided", - ConflictsWith: []string{PIAffinityVolume}, + ConflictsWith: []string{Arg_AffinityVolume}, ForceNew: true, }, - PIAntiAffinityVolumes: { + Arg_AntiAffinityVolumes: { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "List of volumes to base storage anti-affinity policy against; required if requesting anti-affinity and pi_anti_affinity_instances is not provided", - ConflictsWith: []string{PIAntiAffinityInstances}, + ConflictsWith: []string{Arg_AntiAffinityInstances}, ForceNew: true, }, - PIAntiAffinityInstances: { + Arg_AntiAffinityInstances: { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "List of pvmInstances to base storage anti-affinity policy against; required if requesting anti-affinity and pi_anti_affinity_volumes is not provided", - ConflictsWith: []string{PIAntiAffinityVolumes}, + ConflictsWith: []string{Arg_AntiAffinityVolumes}, ForceNew: true, }, Arg_ImageImportDetails: { @@ -261,27 +261,27 @@ func resourceIBMPIImageCreate(ctx context.Context, d *schema.ResourceData, meta if v, ok := d.GetOk(helpers.PIImageStoragePool); ok { body.StoragePool = v.(string) } - if ap, ok := d.GetOk(PIAffinityPolicy); ok { + if ap, ok := d.GetOk(Arg_AffinityPolicy); ok { policy := ap.(string) affinity := &models.StorageAffinity{ AffinityPolicy: &policy, } if policy == "affinity" { - if av, ok := d.GetOk(PIAffinityVolume); ok { + if av, ok := d.GetOk(Arg_AffinityVolume); ok { afvol := av.(string) affinity.AffinityVolume = &afvol } - if ai, ok := d.GetOk(PIAffinityInstance); ok { + if ai, ok := d.GetOk(Arg_AffinityInstance); ok { afins := ai.(string) affinity.AffinityPVMInstance = &afins } } else { - if avs, ok := d.GetOk(PIAntiAffinityVolumes); ok { + if avs, ok := d.GetOk(Arg_AntiAffinityVolumes); ok { afvols := flex.ExpandStringList(avs.([]interface{})) affinity.AntiAffinityVolumes = afvols } - if ais, ok := d.GetOk(PIAntiAffinityInstances); ok { + if ais, ok := d.GetOk(Arg_AntiAffinityInstances); ok { afinss := flex.ExpandStringList(ais.([]interface{})) affinity.AntiAffinityPVMInstances = afinss } diff --git a/ibm/service/power/resource_ibm_pi_image_test.go b/ibm/service/power/resource_ibm_pi_image_test.go index d8da222c07..c50bda620f 100644 --- a/ibm/service/power/resource_ibm_pi_image_test.go +++ b/ibm/service/power/resource_ibm_pi_image_test.go @@ -96,11 +96,11 @@ func testAccCheckIBMPIImageExists(n string) resource.TestCheckFunc { func testAccCheckIBMPIImageConfig(name string) string { return fmt.Sprintf(` resource "ibm_pi_image" "power_image" { - pi_image_name = "%s" - pi_image_id = "IBMi-74-01-001" - pi_cloud_instance_id = "%s" + pi_cloud_instance_id = "%[2]s" + pi_image_id = "%[3]s" + pi_image_name = "%[1]s" } - `, name, acc.Pi_cloud_instance_id) + `, name, acc.Pi_cloud_instance_id, acc.Pi_image) } func TestAccIBMPIImageCOSPublicImport(t *testing.T) { @@ -130,7 +130,7 @@ func testAccCheckIBMPIImageCOSPublicConfig(name string) string { pi_cloud_instance_id = "%[2]s" pi_image_bucket_name = "%[3]s" pi_image_bucket_access = "public" - pi_image_bucket_region = "us-south" + pi_image_bucket_region = "us-east" pi_image_bucket_file_name = "%[4]s" pi_image_storage_type = "tier1" } diff --git a/ibm/service/power/resource_ibm_pi_instance.go b/ibm/service/power/resource_ibm_pi_instance.go index 8aa1bffb7c..111ab08889 100644 --- a/ibm/service/power/resource_ibm_pi_instance.go +++ b/ibm/service/power/resource_ibm_pi_instance.go @@ -16,8 +16,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - st "github.com/IBM-Cloud/power-go-client/clients/instance" - "github.com/IBM-Cloud/power-go-client/helpers" + "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/power-go-client/power/models" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" @@ -39,114 +38,44 @@ func ResourceIBMPIInstance() *schema.Resource { }, Schema: map[string]*schema.Schema{ - - helpers.PICloudInstanceId: { - Type: schema.TypeString, - ForceNew: true, - Required: true, - Description: "This is the Power Instance id that is assigned to the account", - }, - helpers.PIInstanceLicenseRepositoryCapacity: { - Type: schema.TypeInt, - Optional: true, - Computed: true, - Deprecated: "This field is deprecated.", - Description: "The VTL license repository capacity TB value", - }, - "status": { - Type: schema.TypeString, - Computed: true, - Description: "PI instance status", - }, - "min_processors": { - Type: schema.TypeFloat, - Computed: true, - Description: "Minimum number of the CPUs", - }, - "min_memory": { - Type: schema.TypeFloat, - Computed: true, - Description: "Minimum memory", - }, - "max_processors": { - Type: schema.TypeFloat, - Computed: true, - Description: "Maximum number of processors", - }, - "max_memory": { - Type: schema.TypeFloat, - Computed: true, - Description: "Maximum memory size", - }, - helpers.PIInstanceVolumeIds: { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - DiffSuppressFunc: flex.ApplyOnce, - Description: "List of PI volumes", - }, - helpers.PIInstanceUserData: { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Description: "Base64 encoded data to be passed in for invoking a cloud init script", - }, - helpers.PIInstanceStorageType: { - Type: schema.TypeString, - Optional: true, - Computed: true, - Description: "Storage type for server deployment; if pi_storage_type is not provided the storage type will default to tier3", - }, - PIInstanceStoragePool: { - Type: schema.TypeString, - Optional: true, - Computed: true, - Description: "Storage Pool for server deployment; if provided then pi_storage_pool_affinity will be ignored; Only valid when you deploy one of the IBM supplied stock images. Storage pool for a custom image (an imported image or an image that is created from a VM capture) defaults to the storage pool the image was created in", + // Arguments + Arg_AffinityInstance: { + ConflictsWith: []string{Arg_AffinityVolume}, + Description: "PVM Instance (ID or Name) to base storage affinity policy against; required if requesting storage affinity and pi_affinity_volume is not provided", + Optional: true, + Type: schema.TypeString, }, - PIAffinityPolicy: { - Type: schema.TypeString, - Optional: true, + Arg_AffinityPolicy: { Description: "Affinity policy for pvm instance being created; ignored if pi_storage_pool provided; for policy affinity requires one of pi_affinity_instance or pi_affinity_volume to be specified; for policy anti-affinity requires one of pi_anti_affinity_instances or pi_anti_affinity_volumes to be specified", - ValidateFunc: validate.ValidateAllowedStringValues([]string{"affinity", "anti-affinity"}), + Optional: true, + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{Affinity, AntiAffinity}), }, - PIAffinityVolume: { - Type: schema.TypeString, - Optional: true, + Arg_AffinityVolume: { + ConflictsWith: []string{Arg_AffinityInstance}, Description: "Volume (ID or Name) to base storage affinity policy against; required if requesting affinity and pi_affinity_instance is not provided", - ConflictsWith: []string{PIAffinityInstance}, - }, - PIAffinityInstance: { - Type: schema.TypeString, Optional: true, - Description: "PVM Instance (ID or Name) to base storage affinity policy against; required if requesting storage affinity and pi_affinity_volume is not provided", - ConflictsWith: []string{PIAffinityVolume}, + Type: schema.TypeString, }, - PIAntiAffinityVolumes: { - Type: schema.TypeList, - Optional: true, + Arg_AntiAffinityInstances: { + ConflictsWith: []string{Arg_AntiAffinityVolumes}, + Description: "List of pvmInstances to base storage anti-affinity policy against; required if requesting anti-affinity and pi_anti_affinity_volumes is not provided", Elem: &schema.Schema{Type: schema.TypeString}, - Description: "List of volumes to base storage anti-affinity policy against; required if requesting anti-affinity and pi_anti_affinity_instances is not provided", - ConflictsWith: []string{PIAntiAffinityInstances}, - }, - PIAntiAffinityInstances: { - Type: schema.TypeList, Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Description: "List of pvmInstances to base storage anti-affinity policy against; required if requesting anti-affinity and pi_anti_affinity_volumes is not provided", - ConflictsWith: []string{PIAntiAffinityVolumes}, + Type: schema.TypeList, }, - helpers.PIInstanceStorageConnection: { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.ValidateAllowedStringValues([]string{"vSCSI"}), - Description: "Storage Connectivity Group for server deployment", + Arg_AntiAffinityVolumes: { + ConflictsWith: []string{Arg_AntiAffinityInstances}, + Description: "List of volumes to base storage anti-affinity policy against; required if requesting anti-affinity and pi_anti_affinity_instances is not provided", + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + Type: schema.TypeList, }, - PIInstanceStoragePoolAffinity: { - Type: schema.TypeBool, - Optional: true, - Default: true, - Description: "Indicates if all volumes attached to the server must reside in the same storage pool", + Arg_CloudInstanceID: { + Description: "This is the Power Instance id that is assigned to the account", + ForceNew: true, + Required: true, + Type: schema.TypeString, }, Arg_DeploymentTarget: { Description: "The deployment of a dedicated host.", @@ -169,233 +98,306 @@ func ResourceIBMPIInstance() *schema.Resource { MaxItems: 1, Type: schema.TypeSet, }, - PIInstanceNetwork: { - Type: schema.TypeList, + Arg_DeploymentType: { + Description: "Custom Deployment Type Information", + ForceNew: true, + Optional: true, + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{DeploymentTypeEpic, DeploymentTypeVMNoStorage}), + }, + Arg_HealthStatus: { + Default: OK, + Description: "Allow the user to set the status of the lpar so that they can connect to it faster", + Optional: true, + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{OK, Warning}), + }, + Arg_IBMiCSS: { + Description: "IBM i Cloud Storage Solution", + Optional: true, + Type: schema.TypeBool, + }, + Arg_IBMiPHA: { + Description: "IBM i Power High Availability", + Optional: true, + Type: schema.TypeBool, + }, + Arg_IBMiRDSUsers: { + Description: "IBM i Rational Dev Studio Number of User Licenses", + Optional: true, + Type: schema.TypeInt, + }, + Arg_ImageID: { + Description: "PI instance image id", DiffSuppressFunc: flex.ApplyOnce, Required: true, + Type: schema.TypeString, + }, + Arg_InstanceName: { + Description: "PI Instance name", + Required: true, + Type: schema.TypeString, + }, + Arg_KeyPairName: { + Description: "SSH key name", + ForceNew: true, + Optional: true, + Type: schema.TypeString, + }, + Arg_LicenseRepositoryCapacity: { + Computed: true, + Deprecated: "This field is deprecated.", + Description: "The VTL license repository capacity TB value", + Optional: true, + Type: schema.TypeInt, + }, + Arg_Memory: { + Computed: true, + ConflictsWith: []string{Arg_SAPProfileID}, + Description: "Memory size", + Optional: true, + Type: schema.TypeFloat, + }, + Arg_Network: { Description: "List of one or more networks to attach to the instance", + DiffSuppressFunc: flex.ApplyOnce, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "ip_address": { + Attr_IPAddress: { Type: schema.TypeString, Optional: true, Computed: true, }, - "mac_address": { + Attr_MacAddress: { Type: schema.TypeString, Computed: true, }, - "network_id": { + Attr_NetworkID: { Type: schema.TypeString, Required: true, }, - "network_name": { + Attr_NetworkName: { Type: schema.TypeString, Computed: true, }, - "type": { + Attr_Type: { Type: schema.TypeString, Computed: true, }, - "external_ip": { + Attr_ExternalIP: { Type: schema.TypeString, Computed: true, }, }, }, + Required: true, + Type: schema.TypeList, }, - helpers.PIPlacementGroupID: { - Type: schema.TypeString, - Optional: true, - Description: "Placement group ID", - }, - Arg_PIInstanceSharedProcessorPool: { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - ConflictsWith: []string{PISAPInstanceProfileID}, - Description: "Shared Processor Pool the instance is deployed on", - }, - Attr_PIInstanceSharedProcessorPoolID: { - Type: schema.TypeString, - Computed: true, - Description: "Shared Processor Pool ID the instance is deployed on", - }, - "health_status": { - Type: schema.TypeString, - Computed: true, - Description: "PI Instance health status", + Arg_PinPolicy: { + Default: None, + Description: "Pin Policy of the instance", + Optional: true, + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{None, Soft, Hard}), }, - "instance_id": { - Type: schema.TypeString, + Arg_PlacementGroupID: { + Description: "Placement group ID", Computed: true, - Description: "Instance ID", - }, - "pin_policy": { + Optional: true, Type: schema.TypeString, - Computed: true, - Description: "PIN Policy of the Instance", - }, - helpers.PIInstanceImageId: { - Type: schema.TypeString, - Required: true, - Description: "PI instance image id", - DiffSuppressFunc: flex.ApplyOnce, }, - helpers.PIInstanceProcessors: { - Type: schema.TypeFloat, + Arg_ProcType: { + Computed: true, + ConflictsWith: []string{Arg_SAPProfileID}, + Description: "Instance processor type", Optional: true, + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{Dedicated, Shared, Capped}), + }, + Arg_Processors: { Computed: true, - ConflictsWith: []string{PISAPInstanceProfileID}, + ConflictsWith: []string{Arg_SAPProfileID}, Description: "Processors count", - }, - helpers.PIInstanceName: { - Type: schema.TypeString, - Required: true, - Description: "PI Instance name", - }, - helpers.PIInstanceProcType: { - Type: schema.TypeString, Optional: true, - Computed: true, - ValidateFunc: validate.ValidateAllowedStringValues([]string{"dedicated", "shared", "capped"}), - ConflictsWith: []string{PISAPInstanceProfileID}, - Description: "Instance processor type", + Type: schema.TypeFloat, }, - helpers.PIInstanceSSHKeyName: { - Type: schema.TypeString, + Arg_Replicants: { + Default: 1, + Description: "PI Instance replicas count", ForceNew: true, Optional: true, - Description: "SSH key name", - }, - helpers.PIInstanceMemory: { - Type: schema.TypeFloat, - Optional: true, - Computed: true, - ConflictsWith: []string{PISAPInstanceProfileID}, - Description: "Memory size", + Type: schema.TypeInt, }, - PIInstanceDeploymentType: { + Arg_ReplicationPolicy: { + Default: None, + Description: "Replication policy for the PI Instance", + ForceNew: true, + Optional: true, Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{Affinity, AntiAffinity, None}), + }, + Arg_ReplicationScheme: { + Default: Suffix, + Description: "Replication scheme", ForceNew: true, Optional: true, - ValidateFunc: validate.ValidateAllowedStringValues([]string{"EPIC", "VMNoStorage"}), - Description: "Custom Deployment Type Information", + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{Prefix, Suffix}), }, - PISAPInstanceProfileID: { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{helpers.PIInstanceProcessors, helpers.PIInstanceMemory, helpers.PIInstanceProcType}, + Arg_SAPProfileID: { + ConflictsWith: []string{Arg_Processors, Arg_Memory, Arg_ProcType}, Description: "SAP Profile ID for the amount of cores and memory", + Optional: true, + Type: schema.TypeString, }, - PISAPInstanceDeploymentType: { - Type: schema.TypeString, + Arg_SAPDeploymentType: { + Description: "Custom SAP Deployment Type Information", ForceNew: true, Optional: true, - Description: "Custom SAP Deployment Type Information", + Type: schema.TypeString, }, - PIVirtualOpticalDevice: { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.ValidateAllowedStringValues([]string{"attach"}), - Description: "Virtual Machine's Cloud Initialization Virtual Optical Device", + Arg_SharedProcessorPool: { + ConflictsWith: []string{Arg_SAPProfileID}, + Description: "Shared Processor Pool the instance is deployed on", + ForceNew: true, + Optional: true, + Type: schema.TypeString, }, - helpers.PIInstanceSystemType: { + Arg_StoragePool: { + Computed: true, + Description: "Storage Pool for server deployment; if provided then pi_storage_pool_affinity will be ignored; Only valid when you deploy one of the IBM supplied stock images. Storage pool for a custom image (an imported image or an image that is created from a VM capture) defaults to the storage pool the image was created in", + Optional: true, Type: schema.TypeString, - ForceNew: true, + }, + Arg_StoragePoolAffinity: { + Default: true, + Description: "Indicates if all volumes attached to the server must reside in the same storage pool", Optional: true, - Computed: true, - Description: "PI Instance system type", + Type: schema.TypeBool, }, - helpers.PIInstanceReplicants: { - Type: schema.TypeInt, - ForceNew: true, + Arg_StorageType: { + Computed: true, + Description: "Storage type for server deployment; if pi_storage_type is not provided the storage type will default to tier3", Optional: true, - Default: 1, - Description: "PI Instance replicas count", + Type: schema.TypeString, }, - helpers.PIInstanceReplicationPolicy: { - Type: schema.TypeString, - ForceNew: true, + Arg_StorageConnection: { + Description: "Storage Connectivity Group for server deployment", Optional: true, - ValidateFunc: validate.ValidateAllowedStringValues([]string{"affinity", "anti-affinity", "none"}), - Default: "none", - Description: "Replication policy for the PI Instance", - }, - helpers.PIInstanceReplicationScheme: { Type: schema.TypeString, - ForceNew: true, - Optional: true, - ValidateFunc: validate.ValidateAllowedStringValues([]string{"prefix", "suffix"}), - Default: "suffix", - Description: "Replication scheme", + ValidateFunc: validate.ValidateAllowedStringValues([]string{vSCSI}), }, - helpers.PIInstanceProgress: { - Type: schema.TypeFloat, + Arg_SysType: { Computed: true, - Description: "Progress of the operation", + Description: "PI Instance system type", + ForceNew: true, + Optional: true, + Type: schema.TypeString, }, - helpers.PIInstancePinPolicy: { - Type: schema.TypeString, + Arg_UserData: { + Description: "Base64 encoded data to be passed in for invoking a cloud init script", + ForceNew: true, + Optional: true, + Type: schema.TypeString, + }, + Arg_VirtualCoresAssigned: { + Computed: true, + Description: "Virtual Cores Assigned to the PVMInstance", + Optional: true, + Type: schema.TypeInt, + }, + Arg_VirtualOpticalDevice: { + Description: "Virtual Machine's Cloud Initialization Virtual Optical Device", Optional: true, - Description: "Pin Policy of the instance", - Default: "none", - ValidateFunc: validate.ValidateAllowedStringValues([]string{"none", "soft", "hard"}), + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{Attach}), + }, + Arg_VolumeIDs: { + Description: "List of PI volumes", + DiffSuppressFunc: flex.ApplyOnce, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + Set: schema.HashString, + Type: schema.TypeSet, }, - "operating_system": { + + // Attributes + Attr_HealthStatus: { + Computed: true, + Description: "PI Instance health status", Type: schema.TypeString, + }, + Attr_IBMiRDS: { Computed: true, - Description: "Operating System", + Description: "IBM i Rational Dev Studio", + Optional: false, + Required: false, + Type: schema.TypeBool, }, - "os_type": { + Attr_InstanceID: { + Computed: true, + Description: "Instance ID", Type: schema.TypeString, + }, + Attr_MaxMemory: { Computed: true, - Description: "OS Type", + Description: "Maximum memory size", + Type: schema.TypeFloat, }, - helpers.PIInstanceHealthStatus: { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.ValidateAllowedStringValues([]string{helpers.PIInstanceHealthOk, helpers.PIInstanceHealthWarning}), - Default: "OK", - Description: "Allow the user to set the status of the lpar so that they can connect to it faster", + Attr_MaxProcessors: { + Computed: true, + Description: "Maximum number of processors", + Type: schema.TypeFloat, }, - helpers.PIVirtualCoresAssigned: { + Attr_MaxVirtualCores: { + Computed: true, + Description: "Maximum Virtual Cores Assigned to the PVMInstance", Type: schema.TypeInt, - Optional: true, + }, + Attr_MinMemory: { Computed: true, - Description: "Virtual Cores Assigned to the PVMInstance", + Description: "Minimum memory", + Type: schema.TypeFloat, }, - "max_virtual_cores": { - Type: schema.TypeInt, + Attr_MinProcessors: { Computed: true, - Description: "Maximum Virtual Cores Assigned to the PVMInstance", + Description: "Minimum number of the CPUs", + Type: schema.TypeFloat, }, - "min_virtual_cores": { - Type: schema.TypeInt, + Attr_MinVirtualCores: { Computed: true, Description: "Minimum Virtual Cores Assigned to the PVMInstance", + Type: schema.TypeInt, }, - Arg_IBMiCSS: { - Type: schema.TypeBool, - Optional: true, - Description: "IBM i Cloud Storage Solution", + Attr_OperatingSystem: { + Computed: true, + Description: "Operating System", + Type: schema.TypeString, }, - Arg_IBMiPHA: { - Type: schema.TypeBool, - Optional: true, - Description: "IBM i Power High Availability", + Attr_OSType: { + Computed: true, + Description: "OS Type", + Type: schema.TypeString, }, - Attr_IBMiRDS: { - Type: schema.TypeBool, - Optional: false, - Required: false, + Attr_PinPolicy: { Computed: true, - Description: "IBM i Rational Dev Studio", + Description: "PIN Policy of the Instance", + Type: schema.TypeString, }, - Arg_IBMiRDSUsers: { - Type: schema.TypeInt, - Optional: true, - Description: "IBM i Rational Dev Studio Number of User Licenses", + Attr_Progress: { + Computed: true, + Description: "Progress of the operation", + Type: schema.TypeFloat, + }, + Attr_SharedProcessorPoolID: { + Computed: true, + Description: "Shared Processor Pool ID the instance is deployed on", + Type: schema.TypeString, + }, + Attr_Status: { + Computed: true, + Description: "PI instance status", + Type: schema.TypeString, }, Attr_Fault: { Computed: true, @@ -412,13 +414,13 @@ func resourceIBMPIInstanceCreate(ctx context.Context, d *schema.ResourceData, me if err != nil { return diag.FromErr(err) } - cloudInstanceID := d.Get(helpers.PICloudInstanceId).(string) - client := st.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) - sapClient := st.NewIBMPISAPInstanceClient(ctx, sess, cloudInstanceID) - imageClient := st.NewIBMPIImageClient(ctx, sess, cloudInstanceID) + cloudInstanceID := d.Get(Arg_CloudInstanceID).(string) + client := instance.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) + sapClient := instance.NewIBMPISAPInstanceClient(ctx, sess, cloudInstanceID) + imageClient := instance.NewIBMPIImageClient(ctx, sess, cloudInstanceID) var pvmList *models.PVMInstanceList - if _, ok := d.GetOk(PISAPInstanceProfileID); ok { + if _, ok := d.GetOk(Arg_SAPProfileID); ok { pvmList, err = createSAPInstance(d, sapClient) } else { pvmList, err = createPVMInstance(d, client, imageClient) @@ -428,7 +430,7 @@ func resourceIBMPIInstanceCreate(ctx context.Context, d *schema.ResourceData, me } var instanceReadyStatus string - if r, ok := d.GetOk(helpers.PIInstanceHealthStatus); ok { + if r, ok := d.GetOk(Arg_HealthStatus); ok { instanceReadyStatus = r.(string) } @@ -441,13 +443,13 @@ func resourceIBMPIInstanceCreate(ctx context.Context, d *schema.ResourceData, me d.SetId(id) for _, s := range *pvmList { - if dt, ok := d.GetOk(PIInstanceDeploymentType); ok && dt.(string) == "VMNoStorage" { - _, err = isWaitForPIInstanceShutoff(ctx, client, *s.PvmInstanceID, instanceReadyStatus) + if dt, ok := d.GetOk(Arg_DeploymentType); ok && dt.(string) == DeploymentTypeVMNoStorage { + _, err = isWaitForPIInstanceShutoff(ctx, client, *s.PvmInstanceID, instanceReadyStatus, d.Timeout(schema.TimeoutCreate)) if err != nil { return diag.FromErr(err) } } else { - _, err = isWaitForPIInstanceAvailable(ctx, client, *s.PvmInstanceID, instanceReadyStatus) + _, err = isWaitForPIInstanceAvailable(ctx, client, *s.PvmInstanceID, instanceReadyStatus, d.Timeout(schema.TimeoutCreate)) if err != nil { return diag.FromErr(err) } @@ -457,7 +459,7 @@ func resourceIBMPIInstanceCreate(ctx context.Context, d *schema.ResourceData, me // If Storage Pool Affinity is given as false we need to update the vm instance. // Default value is true which indicates that all volumes attached to the server // must reside in the same storage pool. - storagePoolAffinity := d.Get(PIInstanceStoragePoolAffinity).(bool) + storagePoolAffinity := d.Get(Arg_StoragePoolAffinity).(bool) if !storagePoolAffinity { for _, s := range *pvmList { body := &models.PVMInstanceUpdate{ @@ -471,7 +473,7 @@ func resourceIBMPIInstanceCreate(ctx context.Context, d *schema.ResourceData, me } } // If virtual optical device provided then update cloud initialization - if vod, ok := d.GetOk(PIVirtualOpticalDevice); ok { + if vod, ok := d.GetOk(Arg_VirtualOpticalDevice); ok { for _, s := range *pvmList { body := &models.PVMInstanceUpdate{ CloudInitialization: &models.CloudInitialization{ @@ -502,74 +504,74 @@ func resourceIBMPIInstanceRead(ctx context.Context, d *schema.ResourceData, meta cloudInstanceID := idArr[0] instanceID := idArr[1] - client := st.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) powervmdata, err := client.Get(instanceID) if err != nil { return diag.FromErr(err) } - d.Set(helpers.PIInstanceMemory, powervmdata.Memory) - d.Set(helpers.PIInstanceProcessors, powervmdata.Processors) + d.Set(Arg_Memory, powervmdata.Memory) + d.Set(Arg_Processors, powervmdata.Processors) if powervmdata.Status != nil { - d.Set("status", powervmdata.Status) + d.Set(Attr_Status, powervmdata.Status) } - d.Set(helpers.PIInstanceProcType, powervmdata.ProcType) - d.Set("min_processors", powervmdata.Minproc) - d.Set(helpers.PIInstanceProgress, powervmdata.Progress) + d.Set(Arg_ProcType, powervmdata.ProcType) + d.Set(Attr_MinProcessors, powervmdata.Minproc) + d.Set(Attr_Progress, powervmdata.Progress) if powervmdata.StorageType != nil && *powervmdata.StorageType != "" { - d.Set(helpers.PIInstanceStorageType, powervmdata.StorageType) + d.Set(Arg_StorageType, powervmdata.StorageType) } - d.Set(PIInstanceStoragePool, powervmdata.StoragePool) - d.Set(PIInstanceStoragePoolAffinity, powervmdata.StoragePoolAffinity) - d.Set(helpers.PICloudInstanceId, cloudInstanceID) - d.Set("instance_id", powervmdata.PvmInstanceID) - d.Set(helpers.PIInstanceName, powervmdata.ServerName) - d.Set(helpers.PIInstanceImageId, powervmdata.ImageID) - if *powervmdata.PlacementGroup != "none" { - d.Set(helpers.PIPlacementGroupID, powervmdata.PlacementGroup) + d.Set(Arg_StoragePool, powervmdata.StoragePool) + d.Set(Arg_StoragePoolAffinity, powervmdata.StoragePoolAffinity) + d.Set(Arg_CloudInstanceID, cloudInstanceID) + d.Set(Attr_InstanceID, powervmdata.PvmInstanceID) + d.Set(Arg_InstanceName, powervmdata.ServerName) + d.Set(Arg_ImageID, powervmdata.ImageID) + if *powervmdata.PlacementGroup != None { + d.Set(Arg_PlacementGroupID, powervmdata.PlacementGroup) } - d.Set(Arg_PIInstanceSharedProcessorPool, powervmdata.SharedProcessorPool) - d.Set(Attr_PIInstanceSharedProcessorPoolID, powervmdata.SharedProcessorPoolID) + d.Set(Arg_SharedProcessorPool, powervmdata.SharedProcessorPool) + d.Set(Attr_SharedProcessorPoolID, powervmdata.SharedProcessorPoolID) networksMap := []map[string]interface{}{} if powervmdata.Networks != nil { for _, n := range powervmdata.Networks { if n != nil { v := map[string]interface{}{ - "ip_address": n.IPAddress, - "mac_address": n.MacAddress, - "network_id": n.NetworkID, - "network_name": n.NetworkName, - "type": n.Type, - "external_ip": n.ExternalIP, + Attr_IPAddress: n.IPAddress, + Attr_MacAddress: n.MacAddress, + Attr_NetworkID: n.NetworkID, + Attr_NetworkName: n.NetworkName, + Attr_Type: n.Type, + Attr_ExternalIP: n.ExternalIP, } networksMap = append(networksMap, v) } } } - d.Set(PIInstanceNetwork, networksMap) + d.Set(Arg_Network, networksMap) if powervmdata.SapProfile != nil && powervmdata.SapProfile.ProfileID != nil { - d.Set(PISAPInstanceProfileID, powervmdata.SapProfile.ProfileID) + d.Set(Arg_SAPProfileID, powervmdata.SapProfile.ProfileID) } - d.Set(helpers.PIInstanceSystemType, powervmdata.SysType) - d.Set("min_memory", powervmdata.Minmem) - d.Set("max_processors", powervmdata.Maxproc) - d.Set("max_memory", powervmdata.Maxmem) - d.Set("pin_policy", powervmdata.PinPolicy) - d.Set("operating_system", powervmdata.OperatingSystem) - d.Set("os_type", powervmdata.OsType) + d.Set(Arg_SysType, powervmdata.SysType) + d.Set(Attr_MinMemory, powervmdata.Minmem) + d.Set(Attr_MaxProcessors, powervmdata.Maxproc) + d.Set(Attr_MaxMemory, powervmdata.Maxmem) + d.Set(Attr_PinPolicy, powervmdata.PinPolicy) + d.Set(Attr_OperatingSystem, powervmdata.OperatingSystem) + d.Set(Attr_OSType, powervmdata.OsType) if powervmdata.Health != nil { - d.Set("health_status", powervmdata.Health.Status) + d.Set(Attr_HealthStatus, powervmdata.Health.Status) } if powervmdata.VirtualCores != nil { - d.Set(helpers.PIVirtualCoresAssigned, powervmdata.VirtualCores.Assigned) - d.Set("max_virtual_cores", powervmdata.VirtualCores.Max) - d.Set("min_virtual_cores", powervmdata.VirtualCores.Min) + d.Set(Arg_VirtualCoresAssigned, powervmdata.VirtualCores.Assigned) + d.Set(Attr_MaxVirtualCores, powervmdata.VirtualCores.Max) + d.Set(Attr_MinVirtualCores, powervmdata.VirtualCores.Min) } - d.Set(helpers.PIInstanceLicenseRepositoryCapacity, powervmdata.LicenseRepositoryCapacity) - d.Set(PIInstanceDeploymentType, powervmdata.DeploymentType) + d.Set(Arg_LicenseRepositoryCapacity, powervmdata.LicenseRepositoryCapacity) + d.Set(Arg_DeploymentType, powervmdata.DeploymentType) if powervmdata.SoftwareLicenses != nil { d.Set(Arg_IBMiCSS, powervmdata.SoftwareLicenses.IbmiCSS) d.Set(Arg_IBMiPHA, powervmdata.SoftwareLicenses.IbmiPHA) @@ -590,13 +592,13 @@ func resourceIBMPIInstanceRead(ctx context.Context, d *schema.ResourceData, meta func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - name := d.Get(helpers.PIInstanceName).(string) - mem := d.Get(helpers.PIInstanceMemory).(float64) - procs := d.Get(helpers.PIInstanceProcessors).(float64) - processortype := d.Get(helpers.PIInstanceProcType).(string) - assignedVirtualCores := int64(d.Get(helpers.PIVirtualCoresAssigned).(int)) + name := d.Get(Arg_InstanceName).(string) + mem := d.Get(Arg_Memory).(float64) + procs := d.Get(Arg_Processors).(float64) + processortype := d.Get(Arg_ProcType).(string) + assignedVirtualCores := int64(d.Get(Arg_VirtualCoresAssigned).(int)) - if d.Get("health_status") == "WARNING" { + if d.Get(Attr_HealthStatus) == Warning { return diag.Errorf("the operation cannot be performed when the lpar health in the WARNING State") } @@ -610,40 +612,41 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me return diag.FromErr(err) } - client := st.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) // Check if cloud instance is capable of changing virtual cores - cloudInstanceClient := st.NewIBMPICloudInstanceClient(ctx, sess, cloudInstanceID) + cloudInstanceClient := instance.NewIBMPICloudInstanceClient(ctx, sess, cloudInstanceID) cloudInstance, err := cloudInstanceClient.Get(cloudInstanceID) if err != nil { return diag.FromErr(err) } cores_enabled := checkCloudInstanceCapability(cloudInstance, CUSTOM_VIRTUAL_CORES) - if d.HasChanges(helpers.PIInstanceName, PIVirtualOpticalDevice) { + if d.HasChanges(Arg_InstanceName, Arg_VirtualOpticalDevice) { body := &models.PVMInstanceUpdate{} - if d.HasChange(helpers.PIInstanceName) { + if d.HasChange(Arg_InstanceName) { body.ServerName = name } - if d.HasChange(PIVirtualOpticalDevice) { - body.CloudInitialization.VirtualOpticalDevice = d.Get(PIVirtualOpticalDevice).(string) + if d.HasChange(Arg_VirtualOpticalDevice) { + body.CloudInitialization.VirtualOpticalDevice = d.Get(Arg_VirtualOpticalDevice).(string) } _, err = client.Update(instanceID, body) if err != nil { return diag.Errorf("failed to update the lpar: %v", err) } - _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, "OK") + _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, OK, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } } - if d.HasChange(helpers.PIInstanceProcType) { + if d.HasChange(Arg_ProcType) { // Stop the lpar - if d.Get("status") == "SHUTOFF" { + status := d.Get(Attr_Status).(string) + if strings.ToLower(status) == State_Shutoff { log.Printf("the lpar is in the shutoff state. Nothing to do . Moving on ") } else { - err := stopLparForResourceChange(ctx, client, instanceID) + err := stopLparForResourceChange(ctx, client, instanceID, d) if err != nil { return diag.FromErr(err) } @@ -662,20 +665,20 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me if err != nil { return diag.FromErr(err) } - _, err = isWaitForPIInstanceStopped(ctx, client, instanceID) + _, err = isWaitForPIInstanceStopped(ctx, client, instanceID, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } // Start the lpar - err := startLparAfterResourceChange(ctx, client, instanceID) + err := startLparAfterResourceChange(ctx, client, instanceID, d) if err != nil { return diag.FromErr(err) } } // Virtual core will be updated only if service instance capability is enabled - if d.HasChange(helpers.PIVirtualCoresAssigned) { + if d.HasChange(Arg_VirtualCoresAssigned) { body := &models.PVMInstanceUpdate{ VirtualCores: &models.VirtualCores{Assigned: &assignedVirtualCores}, } @@ -683,18 +686,17 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me if err != nil { return diag.Errorf("failed to update the lpar with the change for virtual cores: %v", err) } - _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, "OK") + _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, OK, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } } // Start of the change for Memory and Processors - if d.HasChange(helpers.PIInstanceMemory) || d.HasChange(helpers.PIInstanceProcessors) { + if d.HasChange(Arg_Memory) || d.HasChange(Arg_Processors) { - maxMemLpar := d.Get("max_memory").(float64) - maxCPULpar := d.Get("max_processors").(float64) - //log.Printf("the required memory is set to [%d] and current max memory is set to [%d] ", int(mem), int(maxMemLpar)) + maxMemLpar := d.Get(Attr_MaxMemory).(float64) + maxCPULpar := d.Get(Attr_MaxProcessors).(float64) if mem > maxMemLpar || procs > maxCPULpar { log.Printf("Will require a shutdown to perform the change") @@ -703,13 +705,11 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me log.Printf("maxCPULpar is set to %f", maxCPULpar) } - //if d.GetOkExists("reboot_for_resource_change") - - instanceState := d.Get("status") + instanceState := d.Get(Attr_Status).(string) log.Printf("the instance state is %s", instanceState) - if (mem > maxMemLpar || procs > maxCPULpar) && instanceState != "SHUTOFF" { - err = performChangeAndReboot(ctx, client, instanceID, cloudInstanceID, mem, procs) + if (mem > maxMemLpar || procs > maxCPULpar) && strings.ToLower(instanceState) != State_Shutoff { + err = performChangeAndReboot(ctx, client, d, instanceID, mem, procs) if err != nil { return diag.FromErr(err) } @@ -730,13 +730,13 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me if err != nil { return diag.Errorf("failed to update the lpar with the change %v", err) } - if instanceState == "SHUTOFF" { - _, err = isWaitforPIInstanceUpdate(ctx, client, instanceID) + if strings.ToLower(instanceState) == State_Shutoff { + _, err = isWaitforPIInstanceUpdate(ctx, client, instanceID, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } } else { - _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, "OK") + _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, Arg_HealthStatus, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } @@ -746,8 +746,8 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me // License repository capacity will be updated only if service instance is a vtl instance // might need to check if lrc was set - if d.HasChange(helpers.PIInstanceLicenseRepositoryCapacity) { - lrc := d.Get(helpers.PIInstanceLicenseRepositoryCapacity).(int64) + if d.HasChange(Arg_LicenseRepositoryCapacity) { + lrc := d.Get(Arg_LicenseRepositoryCapacity).(int64) body := &models.PVMInstanceUpdate{ LicenseRepositoryCapacity: lrc, } @@ -755,25 +755,26 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me if err != nil { return diag.Errorf("failed to update the lpar with the change for license repository capacity %s", err) } - _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, "OK") + _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, OK, d.Timeout(schema.TimeoutUpdate)) if err != nil { diag.FromErr(err) } } - if d.HasChange(PISAPInstanceProfileID) { + if d.HasChange(Arg_SAPProfileID) { // Stop the lpar - if d.Get("status") == "SHUTOFF" { + status := d.Get(Attr_Status).(string) + if strings.ToLower(status) == State_Shutoff { log.Printf("the lpar is in the shutoff state. Nothing to do... Moving on ") } else { - err := stopLparForResourceChange(ctx, client, instanceID) + err := stopLparForResourceChange(ctx, client, instanceID, d) if err != nil { return diag.FromErr(err) } } // Update the profile id - profileID := d.Get(PISAPInstanceProfileID).(string) + profileID := d.Get(Arg_SAPProfileID).(string) body := &models.PVMInstanceUpdate{ SapProfileID: profileID, } @@ -783,19 +784,19 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me } // Wait for the resize to complete and status to reset - _, err = isWaitForPIInstanceStopped(ctx, client, instanceID) + _, err = isWaitForPIInstanceStopped(ctx, client, instanceID, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } // Start the lpar - err := startLparAfterResourceChange(ctx, client, instanceID) + err := startLparAfterResourceChange(ctx, client, instanceID, d) if err != nil { return diag.FromErr(err) } } - if d.HasChange(PIInstanceStoragePoolAffinity) { - storagePoolAffinity := d.Get(PIInstanceStoragePoolAffinity).(bool) + if d.HasChange(Arg_StoragePoolAffinity) { + storagePoolAffinity := d.Get(Arg_StoragePoolAffinity).(bool) body := &models.PVMInstanceUpdate{ StoragePoolAffinity: &storagePoolAffinity, } @@ -806,10 +807,10 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me } } - if d.HasChange(helpers.PIPlacementGroupID) { - pgClient := st.NewIBMPIPlacementGroupClient(ctx, sess, cloudInstanceID) + if d.HasChange(Arg_PlacementGroupID) { + pgClient := instance.NewIBMPIPlacementGroupClient(ctx, sess, cloudInstanceID) - oldRaw, newRaw := d.GetChange(helpers.PIPlacementGroupID) + oldRaw, newRaw := d.GetChange(Arg_PlacementGroupID) old := oldRaw.(string) new := newRaw.(string) @@ -826,7 +827,7 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me return diag.FromErr(err) } } else { - _, err = isWaitForPIInstancePlacementGroupDelete(ctx, pgClient, *pgID.ID, instanceID) + _, err = isWaitForPIInstancePlacementGroupDelete(ctx, pgClient, *pgID.ID, instanceID, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } @@ -843,7 +844,7 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me if err != nil { return diag.FromErr(err) } else { - _, err = isWaitForPIInstancePlacementGroupAdd(ctx, pgClient, *pgID.ID, instanceID) + _, err = isWaitForPIInstancePlacementGroupAdd(ctx, pgClient, *pgID.ID, instanceID, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } @@ -851,10 +852,11 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me } } if d.HasChanges(Arg_IBMiCSS, Arg_IBMiPHA, Arg_IBMiRDSUsers) { - if d.Get("status") == "ACTIVE" { + status := d.Get(Attr_Status).(string) + if strings.ToLower(status) == State_Active { log.Printf("the lpar is in the Active state, continuing with update") } else { - _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, "OK") + _, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, OK, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } @@ -875,7 +877,7 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me if err != nil { return diag.FromErr(err) } - _, err = isWaitForPIInstanceSoftwareLicenses(ctx, client, instanceID, sl) + _, err = isWaitForPIInstanceSoftwareLicenses(ctx, client, instanceID, sl, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } @@ -895,7 +897,7 @@ func resourceIBMPIInstanceDelete(ctx context.Context, d *schema.ResourceData, me } cloudInstanceID := idArr[0] - client := st.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) for _, instanceID := range idArr[1:] { err = client.Delete(instanceID) if err != nil { @@ -904,7 +906,7 @@ func resourceIBMPIInstanceDelete(ctx context.Context, d *schema.ResourceData, me } for _, instanceID := range idArr[1:] { - _, err = isWaitForPIInstanceDeleted(ctx, client, instanceID) + _, err = isWaitForPIInstanceDeleted(ctx, client, instanceID, d.Timeout(schema.TimeoutUpdate)) if err != nil { return diag.FromErr(err) } @@ -914,54 +916,54 @@ func resourceIBMPIInstanceDelete(ctx context.Context, d *schema.ResourceData, me return nil } -func isWaitForPIInstanceDeleted(ctx context.Context, client *st.IBMPIInstanceClient, id string) (interface{}, error) { +func isWaitForPIInstanceDeleted(ctx context.Context, client *instance.IBMPIInstanceClient, id string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for (%s) to be deleted.", id) stateConf := &retry.StateChangeConf{ - Pending: []string{"retry", helpers.PIInstanceDeleting}, - Target: []string{helpers.PIInstanceNotFound}, + Pending: []string{State_Retry, State_Deleting}, + Target: []string{State_NotFound}, Refresh: isPIInstanceDeleteRefreshFunc(client, id), - Delay: 10 * time.Second, - MinTimeout: 10 * time.Second, - Timeout: 10 * time.Minute, + Delay: Timeout_Delay, + MinTimeout: Timeout_Active, + Timeout: timeout, } return stateConf.WaitForStateContext(ctx) } -func isPIInstanceDeleteRefreshFunc(client *st.IBMPIInstanceClient, id string) retry.StateRefreshFunc { +func isPIInstanceDeleteRefreshFunc(client *instance.IBMPIInstanceClient, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { pvm, err := client.Get(id) if err != nil { log.Printf("The power vm does not exist") - return pvm, helpers.PIInstanceNotFound, nil + return pvm, State_NotFound, nil } - return pvm, helpers.PIInstanceDeleting, nil + return pvm, State_Deleting, nil } } -func isWaitForPIInstanceAvailable(ctx context.Context, client *st.IBMPIInstanceClient, id string, instanceReadyStatus string) (interface{}, error) { +func isWaitForPIInstanceAvailable(ctx context.Context, client *instance.IBMPIInstanceClient, id string, instanceReadyStatus string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for PIInstance (%s) to be available and active ", id) - queryTimeOut := activeTimeOut - if instanceReadyStatus == helpers.PIInstanceHealthWarning { - queryTimeOut = warningTimeOut + queryTimeOut := Timeout_Active + if instanceReadyStatus == Warning { + queryTimeOut = Timeout_Warning } stateConf := &retry.StateChangeConf{ - Pending: []string{"PENDING", helpers.PIInstanceBuilding, helpers.PIInstanceHealthWarning}, - Target: []string{helpers.PIInstanceAvailable, helpers.PIInstanceHealthOk, "ERROR", "", "SHUTOFF"}, + Pending: []string{State_Pending, State_Build, Warning}, + Target: []string{State_Active, OK, State_Error, "", State_Shutoff}, Refresh: isPIInstanceRefreshFunc(client, id, instanceReadyStatus), - Delay: 30 * time.Second, + Delay: Timeout_Delay, MinTimeout: queryTimeOut, - Timeout: 120 * time.Minute, + Timeout: timeout, } return stateConf.WaitForStateContext(ctx) } -func isPIInstanceRefreshFunc(client *st.IBMPIInstanceClient, id, instanceReadyStatus string) retry.StateRefreshFunc { +func isPIInstanceRefreshFunc(client *instance.IBMPIInstanceClient, id, instanceReadyStatus string) retry.StateRefreshFunc { return func() (interface{}, string, error) { pvm, err := client.Get(id) @@ -969,10 +971,10 @@ func isPIInstanceRefreshFunc(client *st.IBMPIInstanceClient, id, instanceReadySt return nil, "", err } // Check for `instanceReadyStatus` health status and also the final health status "OK" - if *pvm.Status == helpers.PIInstanceAvailable && (pvm.Health.Status == instanceReadyStatus || pvm.Health.Status == helpers.PIInstanceHealthOk) { - return pvm, helpers.PIInstanceAvailable, nil + if strings.ToLower(*pvm.Status) == State_Active && (pvm.Health.Status == instanceReadyStatus || pvm.Health.Status == OK) { + return pvm, State_Active, nil } - if *pvm.Status == "ERROR" { + if strings.ToLower(*pvm.Status) == State_Error { if pvm.Fault != nil { err = fmt.Errorf("failed to create the lpar: %s", pvm.Fault.Message) } else { @@ -981,28 +983,26 @@ func isPIInstanceRefreshFunc(client *st.IBMPIInstanceClient, id, instanceReadySt return pvm, *pvm.Status, err } - return pvm, helpers.PIInstanceBuilding, nil + return pvm, State_Build, nil } } -func isWaitForPIInstancePlacementGroupAdd(ctx context.Context, client *st.IBMPIPlacementGroupClient, pgID string, id string) (interface{}, error) { +func isWaitForPIInstancePlacementGroupAdd(ctx context.Context, client *instance.IBMPIPlacementGroupClient, pgID string, id string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for PIInstance Placement Group (%s) to be updated ", id) - queryTimeOut := activeTimeOut - stateConf := &retry.StateChangeConf{ Pending: []string{State_Adding}, Target: []string{State_Added}, Refresh: isPIInstancePlacementGroupAddRefreshFunc(client, pgID, id), - Delay: 30 * time.Second, - MinTimeout: queryTimeOut, - Timeout: 10 * time.Minute, + Delay: Timeout_Delay, + MinTimeout: Timeout_Active, + Timeout: timeout, } return stateConf.WaitForStateContext(ctx) } -func isPIInstancePlacementGroupAddRefreshFunc(client *st.IBMPIPlacementGroupClient, pgID string, id string) retry.StateRefreshFunc { +func isPIInstancePlacementGroupAddRefreshFunc(client *instance.IBMPIPlacementGroupClient, pgID string, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { pg, err := client.Get(pgID) if err != nil { @@ -1017,24 +1017,24 @@ func isPIInstancePlacementGroupAddRefreshFunc(client *st.IBMPIPlacementGroupClie } } -func isWaitForPIInstancePlacementGroupDelete(ctx context.Context, client *st.IBMPIPlacementGroupClient, pgID string, id string) (interface{}, error) { +func isWaitForPIInstancePlacementGroupDelete(ctx context.Context, client *instance.IBMPIPlacementGroupClient, pgID string, id string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for PIInstance Placement Group (%s) to be updated ", id) - queryTimeOut := activeTimeOut + queryTimeOut := Timeout_Active stateConf := &retry.StateChangeConf{ Pending: []string{State_Deleting}, Target: []string{State_Deleted}, Refresh: isPIInstancePlacementGroupDeleteRefreshFunc(client, pgID, id), - Delay: 30 * time.Second, + Delay: Timeout_Delay, MinTimeout: queryTimeOut, - Timeout: 10 * time.Minute, + Timeout: timeout, } return stateConf.WaitForStateContext(ctx) } -func isPIInstancePlacementGroupDeleteRefreshFunc(client *st.IBMPIPlacementGroupClient, pgID string, id string) retry.StateRefreshFunc { +func isPIInstancePlacementGroupDeleteRefreshFunc(client *instance.IBMPIPlacementGroupClient, pgID string, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { pg, err := client.Get(pgID) if err != nil { @@ -1049,24 +1049,24 @@ func isPIInstancePlacementGroupDeleteRefreshFunc(client *st.IBMPIPlacementGroupC } } -func isWaitForPIInstanceSoftwareLicenses(ctx context.Context, client *st.IBMPIInstanceClient, id string, softwareLicenses *models.SoftwareLicenses) (interface{}, error) { +func isWaitForPIInstanceSoftwareLicenses(ctx context.Context, client *instance.IBMPIInstanceClient, id string, softwareLicenses *models.SoftwareLicenses, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for PIInstance Software Licenses (%s) to be updated ", id) - queryTimeOut := activeTimeOut + queryTimeOut := Timeout_Active stateConf := &retry.StateChangeConf{ - Pending: []string{"notdone"}, - Target: []string{"done"}, + Pending: []string{State_InProgress}, + Target: []string{State_Available}, Refresh: isPIInstanceSoftwareLicensesRefreshFunc(client, id, softwareLicenses), - Delay: 90 * time.Second, + Delay: Timeout_Delay, MinTimeout: queryTimeOut, - Timeout: 120 * time.Minute, + Timeout: timeout, } return stateConf.WaitForStateContext(ctx) } -func isPIInstanceSoftwareLicensesRefreshFunc(client *st.IBMPIInstanceClient, id string, softwareLicenses *models.SoftwareLicenses) retry.StateRefreshFunc { +func isPIInstanceSoftwareLicensesRefreshFunc(client *instance.IBMPIInstanceClient, id string, softwareLicenses *models.SoftwareLicenses) retry.StateRefreshFunc { return func() (interface{}, string, error) { pvm, err := client.Get(id) @@ -1077,13 +1077,13 @@ func isPIInstanceSoftwareLicensesRefreshFunc(client *st.IBMPIInstanceClient, id // Check that each software license we modified has been updated if softwareLicenses.IbmiCSS != nil { if *softwareLicenses.IbmiCSS != *pvm.SoftwareLicenses.IbmiCSS { - return pvm, "notdone", nil + return pvm, State_InProgress, nil } } if softwareLicenses.IbmiPHA != nil { if *softwareLicenses.IbmiPHA != *pvm.SoftwareLicenses.IbmiPHA { - return pvm, "notdone", nil + return pvm, State_InProgress, nil } } @@ -1091,48 +1091,48 @@ func isPIInstanceSoftwareLicensesRefreshFunc(client *st.IBMPIInstanceClient, id // If the update set IBMiRDS to false, don't check IBMiRDSUsers as it will be updated on the terraform side on the read if !*softwareLicenses.IbmiRDS { if *softwareLicenses.IbmiRDS != *pvm.SoftwareLicenses.IbmiRDS { - return pvm, "notdone", nil + return pvm, State_InProgress, nil } } else if (*softwareLicenses.IbmiRDS != *pvm.SoftwareLicenses.IbmiRDS) || (softwareLicenses.IbmiRDSUsers != pvm.SoftwareLicenses.IbmiRDSUsers) { - return pvm, "notdone", nil + return pvm, State_InProgress, nil } } - return pvm, "done", nil + return pvm, State_Available, nil } } -func isWaitForPIInstanceShutoff(ctx context.Context, client *st.IBMPIInstanceClient, id string, instanceReadyStatus string) (interface{}, error) { +func isWaitForPIInstanceShutoff(ctx context.Context, client *instance.IBMPIInstanceClient, id string, instanceReadyStatus string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for PIInstance (%s) to be shutoff and health active ", id) - queryTimeOut := activeTimeOut - if instanceReadyStatus == helpers.PIInstanceHealthWarning { - queryTimeOut = warningTimeOut + queryTimeOut := Timeout_Active + if instanceReadyStatus == Warning { + queryTimeOut = Timeout_Warning } stateConf := &retry.StateChangeConf{ - Pending: []string{Status_Pending, helpers.PIInstanceBuilding, helpers.PIInstanceHealthWarning}, - Target: []string{helpers.PIInstanceHealthOk, Status_Error, "", Status_Shutoff}, + Pending: []string{State_Pending, State_Build, Warning}, + Target: []string{OK, State_Error, "", State_Shutoff}, Refresh: isPIInstanceShutoffRefreshFunc(client, id, instanceReadyStatus), - Delay: 30 * time.Second, + Delay: Timeout_Delay, MinTimeout: queryTimeOut, - Timeout: 120 * time.Minute, + Timeout: timeout, } return stateConf.WaitForStateContext(ctx) } -func isPIInstanceShutoffRefreshFunc(client *st.IBMPIInstanceClient, id, instanceReadyStatus string) retry.StateRefreshFunc { +func isPIInstanceShutoffRefreshFunc(client *instance.IBMPIInstanceClient, id, instanceReadyStatus string) retry.StateRefreshFunc { return func() (interface{}, string, error) { pvm, err := client.Get(id) if err != nil { return nil, "", err } - if *pvm.Status == Status_Shutoff && (pvm.Health.Status == instanceReadyStatus || pvm.Health.Status == helpers.PIInstanceHealthOk) { - return pvm, Status_Shutoff, nil + if strings.ToLower(*pvm.Status) == State_Shutoff && (pvm.Health.Status == instanceReadyStatus || pvm.Health.Status == OK) { + return pvm, State_Shutoff, nil } - if *pvm.Status == Status_Error { + if strings.ToLower(*pvm.Status) == State_Error { if pvm.Fault != nil { err = fmt.Errorf("failed to create the lpar: %s", pvm.Fault.Message) } else { @@ -1141,7 +1141,7 @@ func isPIInstanceShutoffRefreshFunc(client *st.IBMPIInstanceClient, id, instance return pvm, *pvm.Status, err } - return pvm, helpers.PIInstanceBuilding, nil + return pvm, State_Build, nil } } @@ -1154,22 +1154,22 @@ func encodeBase64(userData string) string { return userData } -func isWaitForPIInstanceStopped(ctx context.Context, client *st.IBMPIInstanceClient, id string) (interface{}, error) { +func isWaitForPIInstanceStopped(ctx context.Context, client *instance.IBMPIInstanceClient, id string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for PIInstance (%s) to be stopped and powered off ", id) stateConf := &retry.StateChangeConf{ - Pending: []string{"STOPPING", "RESIZE", "VERIFY_RESIZE", helpers.PIInstanceHealthWarning}, - Target: []string{"OK", "SHUTOFF"}, + Pending: []string{State_Stopping, State_Resize, State_VerifyResize, Warning}, + Target: []string{OK, State_Shutoff}, Refresh: isPIInstanceRefreshFuncOff(client, id), - Delay: 10 * time.Second, - MinTimeout: 2 * time.Minute, // This is the time that the client will execute to check the status of the request - Timeout: 30 * time.Minute, + Delay: Timeout_Delay, + MinTimeout: Timeout_Active, // This is the time that the client will execute to check the status of the request + Timeout: timeout, } return stateConf.WaitForStateContext(ctx) } -func isPIInstanceRefreshFuncOff(client *st.IBMPIInstanceClient, id string) retry.StateRefreshFunc { +func isPIInstanceRefreshFuncOff(client *instance.IBMPIInstanceClient, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { log.Printf("Calling the check Refresh status of the pvm instance %s", id) @@ -1177,45 +1177,45 @@ func isPIInstanceRefreshFuncOff(client *st.IBMPIInstanceClient, id string) retry if err != nil { return nil, "", err } - if *pvm.Status == "SHUTOFF" && pvm.Health.Status == helpers.PIInstanceHealthOk { - return pvm, "SHUTOFF", nil + if strings.ToLower(*pvm.Status) == State_Shutoff && pvm.Health.Status == OK { + return pvm, State_Shutoff, nil } - return pvm, "STOPPING", nil + return pvm, State_Stopping, nil } } -func stopLparForResourceChange(ctx context.Context, client *st.IBMPIInstanceClient, id string) error { +func stopLparForResourceChange(ctx context.Context, client *instance.IBMPIInstanceClient, id string, d *schema.ResourceData) error { body := &models.PVMInstanceAction{ //Action: flex.PtrToString("stop"), - Action: flex.PtrToString("immediate-shutdown"), + Action: flex.PtrToString(Action_ImmediateShutdown), } err := client.Action(id, body) if err != nil { return fmt.Errorf("failed to perform the stop action on the pvm instance %v", err) } - _, err = isWaitForPIInstanceStopped(ctx, client, id) + _, err = isWaitForPIInstanceStopped(ctx, client, id, d.Timeout(schema.TimeoutUpdate)) return err } // Start the lpar -func startLparAfterResourceChange(ctx context.Context, client *st.IBMPIInstanceClient, id string) error { +func startLparAfterResourceChange(ctx context.Context, client *instance.IBMPIInstanceClient, id string, d *schema.ResourceData) error { body := &models.PVMInstanceAction{ - Action: flex.PtrToString("start"), + Action: flex.PtrToString(Action_Start), } err := client.Action(id, body) if err != nil { return fmt.Errorf("failed to perform the start action on the pvm instance %v", err) } - _, err = isWaitForPIInstanceAvailable(ctx, client, id, "OK") + _, err = isWaitForPIInstanceAvailable(ctx, client, id, OK, d.Timeout(schema.TimeoutUpdate)) return err } // Stop / Modify / Start only when the lpar is off limits -func performChangeAndReboot(ctx context.Context, client *st.IBMPIInstanceClient, id, cloudInstanceID string, mem, procs float64) error { +func performChangeAndReboot(ctx context.Context, client *instance.IBMPIInstanceClient, d *schema.ResourceData, id string, mem, procs float64) error { /* These are the steps 1. Stop the lpar - Check if the lpar is SHUTOFF @@ -1226,7 +1226,7 @@ func performChangeAndReboot(ctx context.Context, client *st.IBMPIInstanceClient, //Execute the stop log.Printf("Calling the stop lpar for Resource Change code ..") - err := stopLparForResourceChange(ctx, client, id) + err := stopLparForResourceChange(ctx, client, id, d) if err != nil { return err } @@ -1241,14 +1241,14 @@ func performChangeAndReboot(ctx context.Context, client *st.IBMPIInstanceClient, return fmt.Errorf("failed to update the lpar with the change, %s", updateErr) } - _, err = isWaitforPIInstanceUpdate(ctx, client, id) + _, err = isWaitforPIInstanceUpdate(ctx, client, id, d.Timeout(schema.TimeoutUpdate)) if err != nil { return fmt.Errorf("failed to get an update from the Service after the resource change, %s", err) } // Now we can start the lpar log.Printf("Calling the start lpar After the Resource Change code ..") - err = startLparAfterResourceChange(ctx, client, id) + err = startLparAfterResourceChange(ctx, client, id, d) if err != nil { return err } @@ -1257,22 +1257,22 @@ func performChangeAndReboot(ctx context.Context, client *st.IBMPIInstanceClient, } -func isWaitforPIInstanceUpdate(ctx context.Context, client *st.IBMPIInstanceClient, id string) (interface{}, error) { +func isWaitforPIInstanceUpdate(ctx context.Context, client *instance.IBMPIInstanceClient, id string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for PIInstance (%s) to be ACTIVE or SHUTOFF AFTER THE RESIZE Due to DLPAR Operation ", id) stateConf := &retry.StateChangeConf{ - Pending: []string{"RESIZE", "VERIFY_RESIZE"}, - Target: []string{"ACTIVE", "SHUTOFF", helpers.PIInstanceHealthOk}, + Pending: []string{State_Resize, State_VerifyResize}, + Target: []string{State_Active, State_Shutoff, OK}, Refresh: isPIInstanceShutAfterResourceChange(client, id), - Delay: 10 * time.Second, + Delay: Timeout_Delay, MinTimeout: 5 * time.Minute, - Timeout: 60 * time.Minute, + Timeout: timeout, } return stateConf.WaitForStateContext(ctx) } -func isPIInstanceShutAfterResourceChange(client *st.IBMPIInstanceClient, id string) retry.StateRefreshFunc { +func isPIInstanceShutAfterResourceChange(client *instance.IBMPIInstanceClient, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { pvm, err := client.Get(id) @@ -1280,12 +1280,12 @@ func isPIInstanceShutAfterResourceChange(client *st.IBMPIInstanceClient, id stri return nil, "", err } - if *pvm.Status == "SHUTOFF" && pvm.Health.Status == helpers.PIInstanceHealthOk { + if strings.ToLower(*pvm.Status) == State_Shutoff && pvm.Health.Status == OK { log.Printf("The lpar is now off after the resource change...") - return pvm, "SHUTOFF", nil + return pvm, State_Shutoff, nil } - return pvm, "RESIZE", nil + return pvm, State_Resize, nil } } @@ -1294,8 +1294,8 @@ func expandPVMNetworks(networks []interface{}) []*models.PVMInstanceAddNetwork { for _, v := range networks { network := v.(map[string]interface{}) pvmInstanceNetwork := &models.PVMInstanceAddNetwork{ - IPAddress: network["ip_address"].(string), - NetworkID: flex.PtrToString(network["network_id"].(string)), + IPAddress: network[Attr_IPAddress].(string), + NetworkID: flex.PtrToString(network[Attr_NetworkID].(string)), } pvmNetworks = append(pvmNetworks, pvmInstanceNetwork) } @@ -1313,24 +1313,24 @@ func checkCloudInstanceCapability(cloudInstance *models.CloudInstance, custom_ca return false } -func createSAPInstance(d *schema.ResourceData, sapClient *st.IBMPISAPInstanceClient) (*models.PVMInstanceList, error) { +func createSAPInstance(d *schema.ResourceData, sapClient *instance.IBMPISAPInstanceClient) (*models.PVMInstanceList, error) { - name := d.Get(helpers.PIInstanceName).(string) - profileID := d.Get(PISAPInstanceProfileID).(string) - imageid := d.Get(helpers.PIInstanceImageId).(string) + name := d.Get(Arg_InstanceName).(string) + profileID := d.Get(Arg_SAPProfileID).(string) + imageid := d.Get(Arg_ImageID).(string) - pvmNetworks := expandPVMNetworks(d.Get(PIInstanceNetwork).([]interface{})) + pvmNetworks := expandPVMNetworks(d.Get(Arg_Network).([]interface{})) var replicants int64 - if r, ok := d.GetOk(helpers.PIInstanceReplicants); ok { + if r, ok := d.GetOk(Arg_Replicants); ok { replicants = int64(r.(int)) } var replicationpolicy string - if r, ok := d.GetOk(helpers.PIInstanceReplicationPolicy); ok { + if r, ok := d.GetOk(Arg_ReplicationPolicy); ok { replicationpolicy = r.(string) } var replicationNamingScheme string - if r, ok := d.GetOk(helpers.PIInstanceReplicationScheme); ok { + if r, ok := d.GetOk(Arg_ReplicationScheme); ok { replicationNamingScheme = r.(string) } instances := &models.PVMInstanceMultiCreate{ @@ -1347,62 +1347,62 @@ func createSAPInstance(d *schema.ResourceData, sapClient *st.IBMPISAPInstanceCli ProfileID: &profileID, } - if v, ok := d.GetOk(PISAPInstanceDeploymentType); ok { + if v, ok := d.GetOk(Arg_SAPDeploymentType); ok { body.DeploymentType = v.(string) } - if v, ok := d.GetOk(helpers.PIInstanceVolumeIds); ok { + if v, ok := d.GetOk(Arg_VolumeIDs); ok { volids := flex.ExpandStringList((v.(*schema.Set)).List()) if len(volids) > 0 { body.VolumeIDs = volids } } - if p, ok := d.GetOk(helpers.PIInstancePinPolicy); ok { + if p, ok := d.GetOk(Arg_PinPolicy); ok { pinpolicy := p.(string) - if d.Get(helpers.PIInstancePinPolicy) == "soft" || d.Get(helpers.PIInstancePinPolicy) == "hard" { + if d.Get(Arg_PinPolicy) == Soft || d.Get(Arg_PinPolicy) == Hard { body.PinPolicy = models.PinPolicy(pinpolicy) } } - if v, ok := d.GetOk(helpers.PIInstanceSSHKeyName); ok { + if v, ok := d.GetOk(Arg_KeyPairName); ok { sshkey := v.(string) body.SSHKeyName = sshkey } - if u, ok := d.GetOk(helpers.PIInstanceUserData); ok { + if u, ok := d.GetOk(Arg_UserData); ok { userData := u.(string) body.UserData = encodeBase64(userData) } - if sys, ok := d.GetOk(helpers.PIInstanceSystemType); ok { + if sys, ok := d.GetOk(Arg_SysType); ok { body.SysType = sys.(string) } - if st, ok := d.GetOk(helpers.PIInstanceStorageType); ok { + if st, ok := d.GetOk(Arg_StorageType); ok { body.StorageType = st.(string) } - if sp, ok := d.GetOk(PIInstanceStoragePool); ok { + if sp, ok := d.GetOk(Arg_StoragePool); ok { body.StoragePool = sp.(string) } - if ap, ok := d.GetOk(PIAffinityPolicy); ok { + if ap, ok := d.GetOk(Arg_AffinityPolicy); ok { policy := ap.(string) affinity := &models.StorageAffinity{ AffinityPolicy: &policy, } - if policy == "affinity" { - if av, ok := d.GetOk(PIAffinityVolume); ok { + if policy == Affinity { + if av, ok := d.GetOk(Arg_AffinityVolume); ok { afvol := av.(string) affinity.AffinityVolume = &afvol } - if ai, ok := d.GetOk(PIAffinityInstance); ok { + if ai, ok := d.GetOk(Arg_AffinityInstance); ok { afins := ai.(string) affinity.AffinityPVMInstance = &afins } } else { - if avs, ok := d.GetOk(PIAntiAffinityVolumes); ok { + if avs, ok := d.GetOk(Arg_AntiAffinityVolumes); ok { afvols := flex.ExpandStringList(avs.([]interface{})) affinity.AntiAffinityVolumes = afvols } - if ais, ok := d.GetOk(PIAntiAffinityInstances); ok { + if ais, ok := d.GetOk(Arg_AntiAffinityInstances); ok { afinss := flex.ExpandStringList(ais.([]interface{})) affinity.AntiAffinityPVMInstances = afinss } @@ -1410,7 +1410,7 @@ func createSAPInstance(d *schema.ResourceData, sapClient *st.IBMPISAPInstanceCli body.StorageAffinity = affinity } - if pg, ok := d.GetOk(helpers.PIPlacementGroupID); ok { + if pg, ok := d.GetOk(Arg_PlacementGroupID); ok { body.PlacementGroup = pg.(string) } if deploymentTarget, ok := d.GetOk(Arg_DeploymentTarget); ok { @@ -1427,62 +1427,62 @@ func createSAPInstance(d *schema.ResourceData, sapClient *st.IBMPISAPInstanceCli return pvmList, nil } -func createPVMInstance(d *schema.ResourceData, client *st.IBMPIInstanceClient, imageClient *st.IBMPIImageClient) (*models.PVMInstanceList, error) { +func createPVMInstance(d *schema.ResourceData, client *instance.IBMPIInstanceClient, imageClient *instance.IBMPIImageClient) (*models.PVMInstanceList, error) { - name := d.Get(helpers.PIInstanceName).(string) - imageid := d.Get(helpers.PIInstanceImageId).(string) + name := d.Get(Arg_InstanceName).(string) + imageid := d.Get(Arg_ImageID).(string) var mem, procs float64 var systype, processortype string - if v, ok := d.GetOk(helpers.PIInstanceMemory); ok { + if v, ok := d.GetOk(Arg_Memory); ok { mem = v.(float64) } else { - return nil, fmt.Errorf("%s is required for creating pvm instances", helpers.PIInstanceMemory) + return nil, fmt.Errorf("%s is required for creating pvm instances", Arg_Memory) } - if v, ok := d.GetOk(helpers.PIInstanceProcessors); ok { + if v, ok := d.GetOk(Arg_Processors); ok { procs = v.(float64) } else { - return nil, fmt.Errorf("%s is required for creating pvm instances", helpers.PIInstanceProcessors) + return nil, fmt.Errorf("%s is required for creating pvm instances", Arg_Processors) } - if v, ok := d.GetOk(helpers.PIInstanceSystemType); ok { + if v, ok := d.GetOk(Arg_SysType); ok { systype = v.(string) } else { - return nil, fmt.Errorf("%s is required for creating pvm instances", helpers.PIInstanceSystemType) + return nil, fmt.Errorf("%s is required for creating pvm instances", Arg_SysType) } - if v, ok := d.GetOk(helpers.PIInstanceProcType); ok { + if v, ok := d.GetOk(Arg_ProcType); ok { processortype = v.(string) } else { - return nil, fmt.Errorf("%s is required for creating pvm instances", helpers.PIInstanceProcType) + return nil, fmt.Errorf("%s is required for creating pvm instances", Arg_ProcType) } - pvmNetworks := expandPVMNetworks(d.Get(PIInstanceNetwork).([]interface{})) + pvmNetworks := expandPVMNetworks(d.Get(Arg_Network).([]interface{})) var volids []string - if v, ok := d.GetOk(helpers.PIInstanceVolumeIds); ok { + if v, ok := d.GetOk(Arg_VolumeIDs); ok { volids = flex.ExpandStringList((v.(*schema.Set)).List()) } var replicants float64 - if r, ok := d.GetOk(helpers.PIInstanceReplicants); ok { + if r, ok := d.GetOk(Arg_Replicants); ok { replicants = float64(r.(int)) } var replicationpolicy string - if r, ok := d.GetOk(helpers.PIInstanceReplicationPolicy); ok { + if r, ok := d.GetOk(Arg_ReplicationPolicy); ok { replicationpolicy = r.(string) } var replicationNamingScheme string - if r, ok := d.GetOk(helpers.PIInstanceReplicationScheme); ok { + if r, ok := d.GetOk(Arg_ReplicationScheme); ok { replicationNamingScheme = r.(string) } var pinpolicy string - if p, ok := d.GetOk(helpers.PIInstancePinPolicy); ok { + if p, ok := d.GetOk(Arg_PinPolicy); ok { pinpolicy = p.(string) if pinpolicy == "" { - pinpolicy = "none" + pinpolicy = None } } var userData string - if u, ok := d.GetOk(helpers.PIInstanceUserData); ok { + if u, ok := d.GetOk(Arg_UserData); ok { userData = u.(string) } @@ -1499,55 +1499,55 @@ func createPVMInstance(d *schema.ResourceData, client *st.IBMPIInstanceClient, i ReplicantAffinityPolicy: flex.PtrToString(replicationpolicy), Networks: pvmNetworks, } - if s, ok := d.GetOk(helpers.PIInstanceSSHKeyName); ok { + if s, ok := d.GetOk(Arg_KeyPairName); ok { sshkey := s.(string) body.KeyPairName = sshkey } if len(volids) > 0 { body.VolumeIDs = volids } - if d.Get(helpers.PIInstancePinPolicy) == "soft" || d.Get(helpers.PIInstancePinPolicy) == "hard" { + if d.Get(Arg_PinPolicy) == Soft || d.Get(Arg_PinPolicy) == Hard { body.PinPolicy = models.PinPolicy(pinpolicy) } var assignedVirtualCores int64 - if a, ok := d.GetOk(helpers.PIVirtualCoresAssigned); ok { + if a, ok := d.GetOk(Arg_VirtualCoresAssigned); ok { assignedVirtualCores = int64(a.(int)) body.VirtualCores = &models.VirtualCores{Assigned: &assignedVirtualCores} } - if st, ok := d.GetOk(helpers.PIInstanceStorageType); ok { + if st, ok := d.GetOk(Arg_StorageType); ok { body.StorageType = st.(string) } - if sp, ok := d.GetOk(PIInstanceStoragePool); ok { + if sp, ok := d.GetOk(Arg_StoragePool); ok { body.StoragePool = sp.(string) } - if dt, ok := d.GetOk(PIInstanceDeploymentType); ok { + if dt, ok := d.GetOk(Arg_DeploymentType); ok { body.DeploymentType = dt.(string) } - if ap, ok := d.GetOk(PIAffinityPolicy); ok { + if ap, ok := d.GetOk(Arg_AffinityPolicy); ok { policy := ap.(string) affinity := &models.StorageAffinity{ AffinityPolicy: &policy, } - if policy == "affinity" { - if av, ok := d.GetOk(PIAffinityVolume); ok { + if policy == Affinity { + if av, ok := d.GetOk(Arg_AffinityVolume); ok { afvol := av.(string) affinity.AffinityVolume = &afvol } - if ai, ok := d.GetOk(PIAffinityInstance); ok { + if ai, ok := d.GetOk(Arg_AffinityInstance); ok { afins := ai.(string) affinity.AffinityPVMInstance = &afins } } else { - if avs, ok := d.GetOk(PIAntiAffinityVolumes); ok { + if avs, ok := d.GetOk(Arg_AntiAffinityVolumes); ok { afvols := flex.ExpandStringList(avs.([]interface{})) affinity.AntiAffinityVolumes = afvols } - if ais, ok := d.GetOk(PIAntiAffinityInstances); ok { + if ais, ok := d.GetOk(Arg_AntiAffinityInstances); ok { afinss := flex.ExpandStringList(ais.([]interface{})) affinity.AntiAffinityPVMInstances = afinss } @@ -1555,15 +1555,15 @@ func createPVMInstance(d *schema.ResourceData, client *st.IBMPIInstanceClient, i body.StorageAffinity = affinity } - if sc, ok := d.GetOk(helpers.PIInstanceStorageConnection); ok { + if sc, ok := d.GetOk(Arg_StorageConnection); ok { body.StorageConnection = sc.(string) } - if pg, ok := d.GetOk(helpers.PIPlacementGroupID); ok { + if pg, ok := d.GetOk(Arg_PlacementGroupID); ok { body.PlacementGroup = pg.(string) } - if spp, ok := d.GetOk(Arg_PIInstanceSharedProcessorPool); ok { + if spp, ok := d.GetOk(Arg_SharedProcessorPool); ok { body.SharedProcessorPool = spp.(string) } imageData, err := imageClient.GetStockImage(imageid) @@ -1574,9 +1574,9 @@ func createPVMInstance(d *schema.ResourceData, client *st.IBMPIInstanceClient, i return nil, fmt.Errorf("image doesn't exist. %e", err) } } - if lrc, ok := d.GetOk(helpers.PIInstanceLicenseRepositoryCapacity); ok { + if lrc, ok := d.GetOk(Arg_LicenseRepositoryCapacity); ok { - if imageData.Specifications.ImageType == "stock-vtl" { + if imageData.Specifications.ImageType == StockVTL { body.LicenseRepositoryCapacity = int64(lrc.(int)) } else { return nil, fmt.Errorf("pi_license_repository_capacity should only be used when creating VTL instances. %e", err) diff --git a/ibm/service/power/resource_ibm_pi_instance_test.go b/ibm/service/power/resource_ibm_pi_instance_test.go index 6f282814dd..9a0edc79f3 100644 --- a/ibm/service/power/resource_ibm_pi_instance_test.go +++ b/ibm/service/power/resource_ibm_pi_instance_test.go @@ -7,19 +7,20 @@ import ( "context" "errors" "fmt" + "strings" "testing" "time" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/power" "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" st "github.com/IBM-Cloud/power-go-client/clients/instance" - "github.com/IBM-Cloud/power-go-client/helpers" ) func testAccCheckIBMPIInstanceConfig(name, instanceHealthStatus string) string { @@ -30,33 +31,33 @@ func testAccCheckIBMPIInstanceConfig(name, instanceHealthStatus string) string { pi_ssh_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR" } data "ibm_pi_image" "power_image" { - pi_image_name = "%[3]s" pi_cloud_instance_id = "%[1]s" + pi_image_name = "%[3]s" } data "ibm_pi_network" "power_networks" { pi_cloud_instance_id = "%[1]s" pi_network_name = "%[4]s" } resource "ibm_pi_volume" "power_volume" { - pi_volume_size = 20 + pi_cloud_instance_id = "%[1]s" pi_volume_name = "%[2]s" - pi_volume_shareable = true pi_volume_pool = data.ibm_pi_image.power_image.storage_pool + pi_volume_shareable = true + pi_volume_size = 20 pi_volume_type = "%[6]s" - pi_cloud_instance_id = "%[1]s" } resource "ibm_pi_instance" "power_instance" { - pi_memory = "2" - pi_processors = "0.25" - pi_instance_name = "%[2]s" - pi_proc_type = "shared" + pi_cloud_instance_id = "%[1]s" + pi_health_status = "%[5]s" pi_image_id = data.ibm_pi_image.power_image.id + pi_instance_name = "%[2]s" pi_key_pair_name = ibm_pi_key.key.name - pi_sys_type = "s922" - pi_cloud_instance_id = "%[1]s" + pi_memory = "2" + pi_proc_type = "shared" + pi_processors = "0.25" pi_storage_pool = data.ibm_pi_image.power_image.storage_pool pi_storage_type = "%[6]s" - pi_health_status = "%[5]s" + pi_sys_type = "s922" pi_volume_ids = [ibm_pi_volume.power_volume.volume_id] pi_network { network_id = data.ibm_pi_network.power_networks.id @@ -73,28 +74,29 @@ func testAccCheckIBMPIInstanceDeploymentTypeConfig(name, instanceHealthStatus, e pi_ssh_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR" } data "ibm_pi_image" "power_image" { - pi_image_name = "%[3]s" pi_cloud_instance_id = "%[1]s" + pi_image_name = "%[3]s" } data "ibm_pi_network" "power_networks" { pi_cloud_instance_id = "%[1]s" pi_network_name = "%[4]s" } resource "ibm_pi_instance" "power_instance" { - pi_memory = "2" - pi_processors = "1" - pi_instance_name = "%[2]s" - pi_proc_type = "dedicated" + pi_cloud_instance_id = "%[1]s" + pi_deployment_type = "%[6]s" + pi_health_status = "%[5]s" pi_image_id = data.ibm_pi_image.power_image.id + pi_instance_name = "%[2]s" pi_key_pair_name = ibm_pi_key.key.name - pi_sys_type = "%[7]s" - pi_cloud_instance_id = "%[1]s" + pi_memory = "2" + pi_proc_type = "dedicated" + pi_processors = "1" pi_storage_type = "%[8]s" - pi_health_status = "%[5]s" + pi_sys_type = "%[7]s" pi_network { network_id = data.ibm_pi_network.power_networks.id } - pi_deployment_type = "%[6]s" + } `, acc.Pi_cloud_instance_id, name, acc.Pi_image, acc.Pi_network_name, instanceHealthStatus, epic, systype, acc.PiStorageType) } @@ -111,26 +113,27 @@ func testAccCheckIBMPIInstanceIBMiLicense(name, instanceHealthStatus string, IBM } resource "ibm_pi_volume" "power_volume" { pi_cloud_instance_id = "%[1]s" - pi_volume_size = 1 pi_volume_name = "%[2]s" + pi_volume_size = 1 pi_volume_type = "tier3" } resource "ibm_pi_instance" "power_instance" { - pi_memory = "2" - pi_processors = "0.25" + pi_cloud_instance_id = "%[1]s" + pi_health_status = "%[5]s" + pi_ibmi_css = %[6]t + pi_ibmi_rds_users = %[7]d + pi_image_id = data.ibm_pi_image.power_image.id pi_instance_name = "%[2]s" + pi_memory = "2" pi_proc_type = "shared" - pi_image_id = data.ibm_pi_image.power_image.id - pi_sys_type = "s922" - pi_cloud_instance_id = "%[1]s" + pi_processors = "0.25" pi_storage_pool = data.ibm_pi_image.power_image.storage_pool - pi_health_status = "%[5]s" + pi_sys_type = "s922" pi_volume_ids = [ibm_pi_volume.power_volume.volume_id] pi_network { network_id = data.ibm_pi_network.power_networks.id } - pi_ibmi_css = %[6]t - pi_ibmi_rds_users = %[7]d + }`, acc.Pi_cloud_instance_id, name, acc.Pi_image, acc.Pi_network_name, instanceHealthStatus, IBMiCSS, IBMiRDSUsers) } @@ -142,27 +145,27 @@ func testAccIBMPIInstanceNetworkConfig(name, privateNetIP string) string { pi_ssh_key = "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEArb2aK0mekAdbYdY9rwcmeNSxqVCwez3WZTYEq+1Nwju0x5/vQFPSD2Kp9LpKBbxx3OVLN4VffgGUJznz9DAr7veLkWaf3iwEil6U4rdrhBo32TuDtoBwiczkZ9gn1uJzfIaCJAJdnO80Kv9k0smbQFq5CSb9H+F5VGyFue/iVd5/b30MLYFAz6Jg1GGWgw8yzA4Gq+nO7HtyuA2FnvXdNA3yK/NmrTiPCdJAtEPZkGu9LcelkQ8y90ArlKfjtfzGzYDE4WhOufFxyWxciUePh425J2eZvElnXSdGha+FCfYjQcvqpCVoBAG70U4fJBGjB+HL/GpCXLyiYXPrSnzC9w==" } resource "ibm_pi_network" "power_networks" { + pi_cidr = "192.168.17.0/24" pi_cloud_instance_id = "%[1]s" - pi_network_name = "%[2]s" - pi_network_type = "vlan" pi_dns = ["127.0.0.1"] pi_gateway = "192.168.17.2" - pi_cidr = "192.168.17.0/24" + pi_network_name = "%[2]s" + pi_network_type = "vlan" pi_ipaddress_range { pi_ending_ip_address = "192.168.17.254" pi_starting_ip_address = "192.168.17.3" } } resource "ibm_pi_instance" "power_instance" { - pi_memory = "2" - pi_processors = "0.25" - pi_instance_name = "%[2]s" - pi_proc_type = "shared" + pi_cloud_instance_id = "%[1]s" pi_image_id = "%[4]s" + pi_instance_name = "%[2]s" pi_key_pair_name = ibm_pi_key.key.name - pi_sys_type = "e980" + pi_memory = "2" + pi_proc_type = "shared" + pi_processors = "0.25" pi_storage_type = "tier3" - pi_cloud_instance_id = "%[1]s" + pi_sys_type = "s922" pi_network { network_id = resource.ibm_pi_network.power_networks.network_id ip_address = "%[3]s" @@ -186,16 +189,16 @@ func testAccIBMPIInstanceVTLConfig(name string) string { } resource "ibm_pi_instance" "vtl_instance" { - pi_memory = "22" - pi_processors = "2" + pi_cloud_instance_id = "%[1]s" + pi_image_id = "%[3]s" pi_instance_name = "%[2]s" + pi_key_pair_name = ibm_pi_key.vtl_key.name pi_license_repository_capacity = "3" + pi_memory = "22" pi_proc_type = "shared" - pi_image_id = "%[3]s" - pi_key_pair_name = ibm_pi_key.vtl_key.name - pi_sys_type = "s922" - pi_cloud_instance_id = "%[1]s" + pi_processors = "2" pi_storage_type = "tier1" + pi_sys_type = "s922" pi_network { network_id = ibm_pi_network.vtl_network.network_id } @@ -206,23 +209,30 @@ func testAccIBMPIInstanceVTLConfig(name string) string { func testAccCheckIBMPIInstanceReplicantConfig(name string) string { return fmt.Sprintf(` + resource "ibm_pi_volume" "power_volume" { + pi_cloud_instance_id = "%[1]s" + pi_volume_name = "%[2]s" + pi_volume_shareable = true + pi_volume_size = 1 + pi_volume_type = "tier3" + } resource "ibm_pi_instance" "power_instance" { pi_cloud_instance_id = "%[1]s" - pi_memory = "2" - pi_processors = "1" + pi_image_id = "%[3]s" pi_instance_name = "%[2]s" + pi_memory = "2" pi_proc_type = "shared" - pi_image_id = "%[3]s" - pi_sys_type = "s922" - pi_volume_ids = ["%[5]s"] - pi_network { - network_id = "%[4]s" - } + pi_processors = "1" pi_replicants = 3 pi_replication_policy = "affinity" pi_replication_scheme = "suffix" + pi_sys_type = "s922" + pi_volume_ids = [resource.ibm_pi_volume.power_volume.volume_id] + pi_network { + network_id = "%[4]s" + } } - `, acc.Pi_cloud_instance_id, name, acc.Pi_image, acc.Pi_network_name, acc.Pi_volume_name) + `, acc.Pi_cloud_instance_id, name, acc.Pi_image, acc.Pi_network_name) } func testAccCheckIBMPIInstanceDeplomentTargetConfig(name string) string { @@ -317,7 +327,7 @@ func TestAccIBMPIInstanceBasic(t *testing.T) { CheckDestroy: testAccCheckIBMPIInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckIBMPIInstanceConfig(name, helpers.PIInstanceHealthWarning), + Config: testAccCheckIBMPIInstanceConfig(name, power.Warning), Check: resource.ComposeTestCheckFunc( testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), @@ -353,7 +363,7 @@ func TestAccIBMPIInstanceDeploymentType(t *testing.T) { CheckDestroy: testAccCheckIBMPIInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckIBMPIInstanceDeploymentTypeConfig(name, helpers.PIInstanceHealthOk, "EPIC", "e980"), + Config: testAccCheckIBMPIInstanceDeploymentTypeConfig(name, power.OK, "EPIC", "e980"), Check: resource.ComposeTestCheckFunc( testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), @@ -372,24 +382,24 @@ func TestAccIBMPIInstanceIBMiLicense(t *testing.T) { CheckDestroy: testAccCheckIBMPIInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckIBMPIInstanceIBMiLicense(name, helpers.PIInstanceHealthOk, true, 2), + Config: testAccCheckIBMPIInstanceIBMiLicense(name, power.OK, true, 2), Check: resource.ComposeTestCheckFunc( testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), - resource.TestCheckResourceAttr(instanceRes, "status", "ACTIVE"), + resource.TestCheckResourceAttr(instanceRes, "status", strings.ToUpper(power.State_Active)), resource.TestCheckResourceAttr(instanceRes, "pi_ibmi_css", "true"), - resource.TestCheckResourceAttr(instanceRes, "pi_ibmi_rds", "true"), + resource.TestCheckResourceAttr(instanceRes, "ibmi_rds", "true"), resource.TestCheckResourceAttr(instanceRes, "pi_ibmi_rds_users", "2"), ), }, { - Config: testAccCheckIBMPIInstanceIBMiLicense(name, helpers.PIInstanceHealthOk, false, 0), + Config: testAccCheckIBMPIInstanceIBMiLicense(name, power.OK, false, 0), Check: resource.ComposeTestCheckFunc( testAccCheckIBMPIInstanceExists(instanceRes), - testAccCheckIBMPIInstanceStatus(instanceRes, "ACTIVE"), + testAccCheckIBMPIInstanceStatus(instanceRes, strings.ToUpper(power.State_Active)), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), resource.TestCheckResourceAttr(instanceRes, "pi_ibmi_css", "false"), - resource.TestCheckResourceAttr(instanceRes, "pi_ibmi_rds", "false"), + resource.TestCheckResourceAttr(instanceRes, "ibmi_rds", "false"), resource.TestCheckResourceAttr(instanceRes, "pi_ibmi_rds_users", "0"), ), }, @@ -410,7 +420,7 @@ func TestAccIBMPIInstanceReplicant(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_replicants", "3"), - resource.TestCheckResourceAttr(instanceRes, "pi_replication_policy", "affinity"), + resource.TestCheckResourceAttr(instanceRes, "pi_replication_policy", power.Affinity), resource.TestCheckResourceAttr(instanceRes, "pi_replication_scheme", "suffix"), ), ExpectNonEmptyPlan: true, @@ -491,23 +501,32 @@ func TestAccIBMPISAPInstance(t *testing.T) { }, }) } + func testAccIBMPISAPInstanceConfig(name, sapProfile string) string { return fmt.Sprintf(` + resource "ibm_pi_network" "power_network" { - pi_cloud_instance_id = "%[1]s" - pi_network_name = "%[2]s" - pi_network_type = "pub-vlan" + pi_cidr = "192.168.17.0/24" + pi_cloud_instance_id = "%[1]s" + pi_dns = ["127.0.0.1"] + pi_gateway = "192.168.17.2" + pi_network_name = "%[2]s" + pi_network_type = "vlan" + pi_ipaddress_range { + pi_ending_ip_address = "192.168.17.254" + pi_starting_ip_address = "192.168.17.3" + } } resource "ibm_pi_instance" "sap" { pi_cloud_instance_id = "%[1]s" + pi_health_status = "OK" + pi_image_id = "%[4]s" pi_instance_name = "%[2]s" pi_sap_profile_id = "%[3]s" - pi_image_id = "%[4]s" pi_storage_type = "tier1" pi_network { - network_id = ibm_pi_network.power_network.network_id - } - pi_health_status = "OK" + network_id = resource.ibm_pi_network.power_network.network_id + } } `, acc.Pi_cloud_instance_id, name, sapProfile, acc.Pi_sap_image) } @@ -521,7 +540,7 @@ func TestAccIBMPIInstanceMixedStorage(t *testing.T) { CheckDestroy: testAccCheckIBMPIInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccIBMPIInstanceMixedStorage(name), + Config: testAccIBMPIInstanceMixedStorage(name, power.Warning), Check: resource.ComposeTestCheckFunc( testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), @@ -532,7 +551,7 @@ func TestAccIBMPIInstanceMixedStorage(t *testing.T) { }) } -func testAccIBMPIInstanceMixedStorage(name string) string { +func testAccIBMPIInstanceMixedStorage(name, healthStatus string) string { return fmt.Sprintf(` resource "ibm_pi_key" "key" { pi_cloud_instance_id = "%[1]s" @@ -542,36 +561,37 @@ func testAccIBMPIInstanceMixedStorage(name string) string { resource "ibm_pi_network" "power_network" { pi_cloud_instance_id = "%[1]s" pi_network_name = "%[2]s" - pi_network_type = "pub-vlan" + pi_network_type = "vlan" + pi_cidr = "192.168.17.0/24" } resource "ibm_pi_volume" "power_volume" { pi_cloud_instance_id = "%[1]s" - pi_volume_size = 20 pi_volume_name = "%[2]s" pi_volume_shareable = true + pi_volume_size = 20 pi_volume_type = "tier3" } resource "ibm_pi_instance" "instance" { pi_cloud_instance_id = "%[1]s" - pi_memory = "2" - pi_processors = "0.25" + pi_image_id = "%[3]s" pi_instance_name = "%[2]s" - pi_proc_type = "shared" - pi_image_id = "ca4ea55f-b329-4cf5-bdce-d2f38cfc6da3" pi_key_pair_name = ibm_pi_key.key.name - pi_sys_type = "s922" - pi_storage_type = "tier1" + pi_memory = "2" + pi_proc_type = "shared" + pi_processors = "0.25" pi_storage_pool_affinity = false + pi_storage_type = "tier1" + pi_sys_type = "s922" pi_network { network_id = ibm_pi_network.power_network.network_id } } resource "ibm_pi_volume_attach" "power_attach_volume"{ pi_cloud_instance_id = "%[1]s" - pi_volume_id = ibm_pi_volume.power_volume.volume_id pi_instance_id = ibm_pi_instance.instance.instance_id + pi_volume_id = ibm_pi_volume.power_volume.volume_id } - `, acc.Pi_cloud_instance_id, name) + `, acc.Pi_cloud_instance_id, name, acc.Pi_image) } func TestAccIBMPIInstanceUpdateActiveState(t *testing.T) { @@ -583,17 +603,17 @@ func TestAccIBMPIInstanceUpdateActiveState(t *testing.T) { CheckDestroy: testAccCheckIBMPIInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckIBMPIActiveInstanceConfigUpdate(name, helpers.PIInstanceHealthOk, "0.25", "2"), + Config: testAccCheckIBMPIActiveInstanceConfigUpdate(name, power.OK, "0.25", "2"), Check: resource.ComposeTestCheckFunc( testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), - resource.TestCheckResourceAttr(instanceRes, "status", "ACTIVE"), + resource.TestCheckResourceAttr(instanceRes, "status", strings.ToUpper(power.State_Active)), ), }, { - Config: testAccCheckIBMPIActiveInstanceConfigUpdate(name, helpers.PIInstanceHealthOk, "0.5", "4"), + Config: testAccCheckIBMPIActiveInstanceConfigUpdate(name, power.OK, "0.5", "4"), Check: resource.ComposeTestCheckFunc( - testAccCheckIBMPIInstanceStatus(instanceRes, "ACTIVE"), + testAccCheckIBMPIInstanceStatus(instanceRes, strings.ToUpper(power.State_Active)), testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), ), @@ -612,16 +632,16 @@ func TestAccIBMPIInstanceUpdateStoppedState(t *testing.T) { CheckDestroy: testAccCheckIBMPIInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckIBMPIStoppedInstanceConfigUpdate(name, helpers.PIInstanceHealthOk, "0.25", "2", "stop"), + Config: testAccCheckIBMPIStoppedInstanceConfigUpdate(name, power.OK, "0.25", "2", "stop"), Check: resource.ComposeTestCheckFunc( testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), ), }, { - Config: testAccCheckIBMPIStoppedInstanceConfigUpdate(name, helpers.PIInstanceHealthOk, "0.5", "4", "stop"), + Config: testAccCheckIBMPIStoppedInstanceConfigUpdate(name, power.OK, "0.5", "4", "stop"), Check: resource.ComposeTestCheckFunc( - testAccCheckIBMPIInstanceStatus(instanceRes, "SHUTOFF"), + testAccCheckIBMPIInstanceStatus(instanceRes, strings.ToUpper(power.State_Shutoff)), testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), ), @@ -634,31 +654,31 @@ func TestAccIBMPIInstanceUpdateStoppedState(t *testing.T) { func testAccCheckIBMPIActiveInstanceConfigUpdate(name, instanceHealthStatus, proc, memory string) string { return fmt.Sprintf(` data "ibm_pi_image" "power_image" { - pi_image_name = "%[3]s" pi_cloud_instance_id = "%[1]s" + pi_image_name = "%[3]s" } data "ibm_pi_network" "power_networks" { pi_cloud_instance_id = "%[1]s" pi_network_name = "%[4]s" } resource "ibm_pi_volume" "power_volume" { - pi_volume_size = 20 + pi_cloud_instance_id = "%[1]s" pi_volume_name = "%[2]s" - pi_volume_shareable = true pi_volume_pool = data.ibm_pi_image.power_image.storage_pool - pi_cloud_instance_id = "%[1]s" + pi_volume_shareable = true + pi_volume_size = 20 } resource "ibm_pi_instance" "power_instance" { - pi_memory = "%[7]s" - pi_processors = "%[6]s" + pi_cloud_instance_id = "%[1]s" + pi_health_status = "%[5]s" + pi_image_id = data.ibm_pi_image.power_image.id pi_instance_name = "%[2]s" + pi_memory = "%[7]s" + pi_pin_policy = "none" pi_proc_type = "shared" - pi_image_id = data.ibm_pi_image.power_image.id - pi_sys_type = "s922" - pi_cloud_instance_id = "%[1]s" + pi_processors = "%[6]s" pi_storage_pool = data.ibm_pi_image.power_image.storage_pool - pi_pin_policy = "none" - pi_health_status = "%[5]s" + pi_sys_type = "s922" pi_volume_ids = [ibm_pi_volume.power_volume.volume_id] pi_network { network_id = data.ibm_pi_network.power_networks.id @@ -670,41 +690,41 @@ func testAccCheckIBMPIActiveInstanceConfigUpdate(name, instanceHealthStatus, pro func testAccCheckIBMPIStoppedInstanceConfigUpdate(name, instanceHealthStatus, proc, memory, action string) string { return fmt.Sprintf(` data "ibm_pi_image" "power_image" { - pi_image_name = "%[3]s" pi_cloud_instance_id = "%[1]s" + pi_image_name = "%[3]s" } data "ibm_pi_network" "power_networks" { pi_cloud_instance_id = "%[1]s" pi_network_name = "%[4]s" } resource "ibm_pi_volume" "power_volume" { - pi_volume_size = 20 + pi_cloud_instance_id = "%[1]s" pi_volume_name = "%[2]s" - pi_volume_shareable = true pi_volume_pool = data.ibm_pi_image.power_image.storage_pool - pi_cloud_instance_id = "%[1]s" + pi_volume_shareable = true + pi_volume_size = 20 } resource "ibm_pi_instance" "power_instance" { - pi_memory = "%[7]s" - pi_processors = "%[6]s" + pi_cloud_instance_id = "%[1]s" + pi_health_status = "%[5]s" + pi_image_id = data.ibm_pi_image.power_image.id pi_instance_name = "%[2]s" + pi_memory = "%[7]s" + pi_pin_policy = "none" pi_proc_type = "shared" - pi_image_id = data.ibm_pi_image.power_image.id - pi_sys_type = "s922" - pi_cloud_instance_id = "%[1]s" + pi_processors = "%[6]s" pi_storage_pool = data.ibm_pi_image.power_image.storage_pool - pi_pin_policy = "none" - pi_health_status = "%[5]s" + pi_sys_type = "s922" pi_volume_ids = [ibm_pi_volume.power_volume.volume_id] pi_network { network_id = data.ibm_pi_network.power_networks.id } } resource "ibm_pi_instance_action" "power_instance_action" { - pi_cloud_instance_id = "%[1]s" - pi_instance_id = ibm_pi_instance.power_instance.instance_id pi_action = "%[8]s" + pi_cloud_instance_id = "%[1]s" pi_health_status = "%[5]s" + pi_instance_id = ibm_pi_instance.power_instance.instance_id } `, acc.Pi_cloud_instance_id, name, acc.Pi_image, acc.Pi_network_name, instanceHealthStatus, proc, memory, action) } @@ -756,7 +776,7 @@ func TestAccIBMPIInstanceDeploymentTypeNoStorage(t *testing.T) { CheckDestroy: testAccCheckIBMPIInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckIBMPIInstanceDeploymentTypeConfig(name, helpers.PIInstanceHealthOk, "VMNoStorage", "s922"), + Config: testAccCheckIBMPIInstanceDeploymentTypeConfig(name, power.OK, "VMNoStorage", "s922"), Check: resource.ComposeTestCheckFunc( testAccCheckIBMPIInstanceExists(instanceRes), resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), diff --git a/ibm/service/power/resource_ibm_pi_network.go b/ibm/service/power/resource_ibm_pi_network.go index 51ba24ea98..5842599a2b 100644 --- a/ibm/service/power/resource_ibm_pi_network.go +++ b/ibm/service/power/resource_ibm_pi_network.go @@ -17,7 +17,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - st "github.com/IBM-Cloud/power-go-client/clients/instance" + "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/power-go-client/helpers" "github.com/IBM-Cloud/power-go-client/power/models" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" @@ -74,7 +74,6 @@ func ResourceIBMPINetwork() *schema.Resource { Optional: true, Computed: true, Description: "PI network gateway", - ForceNew: true, }, helpers.PINetworkJumbo: { Type: schema.TypeBool, @@ -148,7 +147,7 @@ func resourceIBMPINetworkCreate(ctx context.Context, d *schema.ResourceData, met networkname := d.Get(helpers.PINetworkName).(string) networktype := d.Get(helpers.PINetworkType).(string) - client := st.NewIBMPINetworkClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPINetworkClient(ctx, sess, cloudInstanceID) var body = &models.NetworkCreate{ Type: &networktype, Name: networkname, @@ -199,7 +198,17 @@ func resourceIBMPINetworkCreate(ctx context.Context, d *schema.ResourceData, met body.Gateway = gateway body.Cidr = networkcidr } - + wsclient := instance.NewIBMPIWorkspacesClient(ctx, sess, cloudInstanceID) + wsData, err := wsclient.Get(cloudInstanceID) + if err != nil { + return diag.FromErr(err) + } + if wsData.Capabilities[PER] { + _, err = waitForPERWorkspaceActive(ctx, wsclient, cloudInstanceID, d.Timeout(schema.TimeoutRead)) + if err != nil { + return diag.FromErr(err) + } + } networkResponse, err := client.Create(body) if err != nil { return diag.FromErr(err) @@ -228,7 +237,7 @@ func resourceIBMPINetworkRead(ctx context.Context, d *schema.ResourceData, meta return diag.FromErr(err) } - networkC := st.NewIBMPINetworkClient(ctx, sess, cloudInstanceID) + networkC := instance.NewIBMPINetworkClient(ctx, sess, cloudInstanceID) networkdata, err := networkC.Get(networkID) if err != nil { return diag.FromErr(err) @@ -272,17 +281,22 @@ func resourceIBMPINetworkUpdate(ctx context.Context, d *schema.ResourceData, met return diag.FromErr(err) } - if d.HasChanges(helpers.PINetworkName, helpers.PINetworkDNS, helpers.PINetworkIPAddressRange) { - networkC := st.NewIBMPINetworkClient(ctx, sess, cloudInstanceID) + if d.HasChanges(helpers.PINetworkName, helpers.PINetworkDNS, helpers.PINetworkGateway, helpers.PINetworkIPAddressRange) { + networkC := instance.NewIBMPINetworkClient(ctx, sess, cloudInstanceID) body := &models.NetworkUpdate{ DNSServers: flex.ExpandStringList((d.Get(helpers.PINetworkDNS).(*schema.Set)).List()), } networkType := d.Get(helpers.PINetworkType).(string) - if d.HasChange(helpers.PINetworkIPAddressRange) { + if d.HasChange(helpers.PINetworkIPAddressRange) || d.HasChange(helpers.PINetworkGateway) { if networkType == Vlan { - body.IPAddressRanges = getIPAddressRanges(d.Get(helpers.PINetworkIPAddressRange).([]interface{})) + if d.HasChange(helpers.PINetworkIPAddressRange) { + body.IPAddressRanges = getIPAddressRanges(d.Get(helpers.PINetworkIPAddressRange).([]interface{})) + } + if d.HasChange(helpers.PINetworkGateway) { + body.Gateway = flex.PtrToString(d.Get(helpers.PINetworkGateway).(string)) + } } else { - return diag.Errorf("%v type does not allow ip-address range update", networkType) + return diag.Errorf("%v type does not allow ip-address range or gateway update", networkType) } } @@ -312,7 +326,7 @@ func resourceIBMPINetworkDelete(ctx context.Context, d *schema.ResourceData, met return diag.FromErr(err) } - client := st.NewIBMPINetworkClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPINetworkClient(ctx, sess, cloudInstanceID) err = client.Delete(networkID) if err != nil { return diag.FromErr(err) @@ -327,7 +341,7 @@ func resourceIBMPINetworkDelete(ctx context.Context, d *schema.ResourceData, met return nil } -func isWaitForIBMPINetworkAvailable(ctx context.Context, client *st.IBMPINetworkClient, id string, timeout time.Duration) (interface{}, error) { +func isWaitForIBMPINetworkAvailable(ctx context.Context, client *instance.IBMPINetworkClient, id string, timeout time.Duration) (interface{}, error) { stateConf := &resource.StateChangeConf{ Pending: []string{"retry", helpers.PINetworkProvisioning}, Target: []string{"NETWORK_READY"}, @@ -340,7 +354,7 @@ func isWaitForIBMPINetworkAvailable(ctx context.Context, client *st.IBMPINetwork return stateConf.WaitForStateContext(ctx) } -func isIBMPINetworkRefreshFunc(client *st.IBMPINetworkClient, id string) resource.StateRefreshFunc { +func isIBMPINetworkRefreshFunc(client *instance.IBMPINetworkClient, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { network, err := client.Get(id) if err != nil { @@ -355,7 +369,7 @@ func isIBMPINetworkRefreshFunc(client *st.IBMPINetworkClient, id string) resourc } } -func isWaitForIBMPINetworkDeleted(ctx context.Context, client *st.IBMPINetworkClient, id string, timeout time.Duration) (interface{}, error) { +func isWaitForIBMPINetworkDeleted(ctx context.Context, client *instance.IBMPINetworkClient, id string, timeout time.Duration) (interface{}, error) { stateConf := &retry.StateChangeConf{ Pending: []string{State_Found}, Target: []string{State_NotFound}, @@ -368,7 +382,7 @@ func isWaitForIBMPINetworkDeleted(ctx context.Context, client *st.IBMPINetworkCl return stateConf.WaitForStateContext(ctx) } -func isIBMPINetworkRefreshDeleteFunc(client *st.IBMPINetworkClient, id string) resource.StateRefreshFunc { +func isIBMPINetworkRefreshDeleteFunc(client *instance.IBMPINetworkClient, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { network, err := client.Get(id) if err != nil { @@ -438,3 +452,39 @@ func getIPAddressRanges(ipAddressRanges []interface{}) []*models.IPAddressRange } return ipRanges } +func waitForPERWorkspaceActive(ctx context.Context, client *instance.IBMPIWorkspacesClient, id string, timeout time.Duration) (interface{}, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{State_Inactive, State_Configuring}, + Target: []string{State_Active}, + Refresh: isPERWorkspaceRefreshFunc(client, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + return stateConf.WaitForStateContext(ctx) +} + +func isPERWorkspaceRefreshFunc(client *instance.IBMPIWorkspacesClient, id string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + ws, err := client.Get(id) + if err != nil { + return nil, "", err + } + // Check for backward compatibility for legacy workspace. + if ws.Details.PowerEdgeRouter == nil { + return ws, State_Active, nil + } + if *(ws.Details.PowerEdgeRouter.State) == State_Active { + return ws, State_Active, nil + } + if *(ws.Details.PowerEdgeRouter.State) == State_Inactive { + return ws, State_Inactive, nil + } + if *(ws.Details.PowerEdgeRouter.State) == State_Error { + return ws, *ws.Details.PowerEdgeRouter.State, fmt.Errorf("[ERROR] workspace PER configuration failed to initialize. Please try again later") + } + + return ws, State_Configuring, nil + } +} diff --git a/ibm/service/power/resource_ibm_pi_shared_processor_pool.go b/ibm/service/power/resource_ibm_pi_shared_processor_pool.go index 66a8f2338a..5bc4aa2d33 100644 --- a/ibm/service/power/resource_ibm_pi_shared_processor_pool.go +++ b/ibm/service/power/resource_ibm_pi_shared_processor_pool.go @@ -98,13 +98,13 @@ func ResourceIBMPISharedProcessorPool() *schema.Resource { Description: "The host ID where the shared processor pool resides", }, - Attr_SharedProcessorPoolStatus: { + Attr_Status: { Type: schema.TypeString, Computed: true, Description: "The status of the shared processor pool", }, - Attr_SharedProcessorPoolStatusDetail: { + Attr_StatusDetail: { Type: schema.TypeString, Computed: true, Description: "The status details of the shared processor pool", @@ -153,7 +153,7 @@ func ResourceIBMPISharedProcessorPool() *schema.Resource { Computed: true, Description: "The server instance name", }, - Attr_SharedProcessorPoolInstanceStatus: { + Attr_Status: { Type: schema.TypeString, Computed: true, Description: "Status of the server", @@ -218,7 +218,7 @@ func isWaitForPISharedProcessorPoolAvailable(ctx context.Context, d *schema.Reso Target: []string{"active", "failed", ""}, Refresh: isPISharedProcessorPoolRefreshFunc(client, id, sharedProcessorPoolReadyStatus), Delay: 20 * time.Second, - MinTimeout: activeTimeOut, + MinTimeout: Timeout_Active, Timeout: d.Timeout(schema.TimeoutCreate), } @@ -293,7 +293,7 @@ func resourceIBMPISharedProcessorPoolRead(ctx context.Context, d *schema.Resourc d.Set(Attr_SharedProcessorPoolPlacementGroups, pgIDs) } d.Set(Attr_SharedProcessorPoolHostID, response.SharedProcessorPool.HostID) - d.Set(Attr_SharedProcessorPoolStatus, response.SharedProcessorPool.Status) + d.Set(Attr_Status, response.SharedProcessorPool.Status) d.Set(Attr_SharedProcessorPoolStatusDetail, response.SharedProcessorPool.StatusDetail) serversMap := []map[string]interface{}{} @@ -307,7 +307,7 @@ func resourceIBMPISharedProcessorPoolRead(ctx context.Context, d *schema.Resourc Attr_SharedProcessorPoolInstanceId: s.ID, Attr_SharedProcessorPoolInstanceMemory: s.Memory, Attr_SharedProcessorPoolInstanceName: s.Name, - Attr_SharedProcessorPoolInstanceStatus: s.Status, + Attr_Status: s.Status, Attr_SharedProcessorPoolInstanceVcpus: s.Vcpus, } serversMap = append(serversMap, v) diff --git a/ibm/service/power/resource_ibm_pi_snapshot.go b/ibm/service/power/resource_ibm_pi_snapshot.go index 1a49e51db5..37b8d232a6 100644 --- a/ibm/service/power/resource_ibm_pi_snapshot.go +++ b/ibm/service/power/resource_ibm_pi_snapshot.go @@ -239,8 +239,8 @@ func resourceIBMPISnapshotDelete(ctx context.Context, d *schema.ResourceData, me func isWaitForPIInstanceSnapshotAvailable(ctx context.Context, client *instance.IBMPISnapshotClient, id string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for PIInstance Snapshot (%s) to be available and active ", id) stateConf := &retry.StateChangeConf{ - Pending: []string{State_InProgress, State_BUILD}, - Target: []string{State_Available, State_ACTIVE}, + Pending: []string{State_InProgress, State_Build}, + Target: []string{State_Available, State_Active}, Refresh: isPIInstanceSnapshotRefreshFunc(client, id), Delay: 30 * time.Second, MinTimeout: 2 * time.Minute, @@ -270,7 +270,7 @@ func isWaitForPIInstanceSnapshotDeleted(ctx context.Context, client *instance.IB log.Printf("Waiting for (%s) to be deleted.", id) stateConf := &retry.StateChangeConf{ - Pending: []string{State_Retry, State_DELETING}, + Pending: []string{State_Retry, State_Deleting}, Target: []string{State_NotFound}, Refresh: isPIInstanceSnapshotDeleteRefreshFunc(client, id), Delay: 10 * time.Second, diff --git a/ibm/service/power/resource_ibm_pi_volume_group.go b/ibm/service/power/resource_ibm_pi_volume_group.go index 921a19c5ac..a1031973fd 100644 --- a/ibm/service/power/resource_ibm_pi_volume_group.go +++ b/ibm/service/power/resource_ibm_pi_volume_group.go @@ -10,15 +10,15 @@ import ( "log" "time" - st "github.com/IBM-Cloud/power-go-client/clients/instance" - "github.com/IBM-Cloud/power-go-client/helpers" + "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/power-go-client/power/client/p_cloud_volume_groups" "github.com/IBM-Cloud/power-go-client/power/models" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) func ResourceIBMPIVolumeGroup() *schema.Resource { @@ -35,51 +35,78 @@ func ResourceIBMPIVolumeGroup() *schema.Resource { Delete: schema.DefaultTimeout(10 * time.Minute), }, Schema: map[string]*schema.Schema{ - helpers.PICloudInstanceId: { - Type: schema.TypeString, - Required: true, - Description: "Cloud Instance ID - This is the service_instance_id.", + // Arguments + Arg_CloudInstanceID: { + Description: "The GUID of the service instance associated with an account.", + Required: true, + Type: schema.TypeString, + ValidateFunc: validation.NoZeroValues, }, - PIVolumeGroupName: { - Type: schema.TypeString, + Arg_ConsistencyGroupName: { + ConflictsWith: []string{Arg_VolumeGroupName}, + Description: "The name of consistency group at storage controller level", Optional: true, - Description: "Volume Group Name to create", - ConflictsWith: []string{PIVolumeGroupConsistencyGroupName}, - }, - PIVolumeGroupConsistencyGroupName: { Type: schema.TypeString, + }, + Arg_VolumeGroupName: { + ConflictsWith: []string{Arg_ConsistencyGroupName}, + Description: "Volume Group Name to create", Optional: true, - Description: "The name of consistency group at storage controller level", - ConflictsWith: []string{PIVolumeGroupName}, + Type: schema.TypeString, }, - PIVolumeIds: { - Type: schema.TypeSet, - Required: true, + Arg_VolumeIDs: { + Description: "List of volumes to add in volume group", Elem: &schema.Schema{Type: schema.TypeString}, + Required: true, Set: schema.HashString, - Description: "List of volumes to add in volume group", + Type: schema.TypeSet, }, - // Computed Attributes - "volume_group_id": { - Type: schema.TypeString, + // Attributes + Attr_ConsistencyGroupName: { Computed: true, - Description: "Volume Group ID", - }, - "volume_group_status": { + Description: "Consistency Group Name if volume is a part of volume group", Type: schema.TypeString, - Computed: true, - Description: "Volume Group Status", }, - "replication_status": { - Type: schema.TypeString, + Attr_ReplicationStatus: { Computed: true, Description: "Volume Group Replication Status", + Type: schema.TypeString, + }, + Attr_StatusDescriptionErrors: { + Computed: true, + Description: "The status details of the volume group.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Key: { + Computed: true, + Description: "The volume group error key.", + Type: schema.TypeString, + }, + Attr_Message: { + Computed: true, + Description: "The failure message providing more details about the error key.", + Type: schema.TypeString, + }, + Attr_VolumeIDs: { + Computed: true, + Description: "List of volume IDs, which failed to be added to or removed from the volume group, with the given error.", + Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + }, + }, + }, + Type: schema.TypeSet, }, - "consistency_group_name": { + Attr_VolumeGroupID: { + Computed: true, + Description: "Volume Group ID", Type: schema.TypeString, + }, + Attr_VolumeGroupStatus: { Computed: true, - Description: "Consistency Group Name if volume is a part of volume group", + Description: "Volume Group Status", + Type: schema.TypeString, }, }, } @@ -91,20 +118,20 @@ func resourceIBMPIVolumeGroupCreate(ctx context.Context, d *schema.ResourceData, return diag.FromErr(err) } - vgName := d.Get(PIVolumeGroupName).(string) - cloudInstanceID := d.Get(helpers.PICloudInstanceId).(string) + vgName := d.Get(Arg_VolumeGroupName).(string) + cloudInstanceID := d.Get(Arg_CloudInstanceID).(string) body := &models.VolumeGroupCreate{ Name: vgName, } - volids := flex.ExpandStringList((d.Get(PIVolumeIds).(*schema.Set)).List()) + volids := flex.ExpandStringList((d.Get(Arg_VolumeIDs).(*schema.Set)).List()) body.VolumeIDs = volids - if v, ok := d.GetOk(PIVolumeGroupConsistencyGroupName); ok { + if v, ok := d.GetOk(Arg_ConsistencyGroupName); ok { body.ConsistencyGroupName = v.(string) } - client := st.NewIBMPIVolumeGroupClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIVolumeGroupClient(ctx, sess, cloudInstanceID) vg, err := client.CreateVolumeGroup(body) if err != nil { return diag.FromErr(err) @@ -131,20 +158,22 @@ func resourceIBMPIVolumeGroupRead(ctx context.Context, d *schema.ResourceData, m return diag.FromErr(err) } - client := st.NewIBMPIVolumeGroupClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIVolumeGroupClient(ctx, sess, cloudInstanceID) vg, err := client.GetDetails(vgID) if err != nil { return diag.FromErr(err) } - d.Set("volume_group_id", vg.ID) - d.Set("volume_group_status", vg.Status) - d.Set("consistency_group_name", vg.ConsistencyGroupName) - d.Set("replication_status", vg.ReplicationStatus) - d.Set(PIVolumeGroupName, vg.Name) - d.Set(PIVolumeIds, vg.VolumeIDs) - d.Set("status_description_errors", flattenVolumeGroupStatusDescription(vg.StatusDescription.Errors)) + d.Set(Arg_VolumeGroupName, vg.Name) + d.Set(Arg_VolumeIDs, vg.VolumeIDs) + d.Set(Attr_ConsistencyGroupName, vg.ConsistencyGroupName) + d.Set(Attr_ReplicationStatus, vg.ReplicationStatus) + if vg.StatusDescription != nil { + d.Set(Attr_StatusDescriptionErrors, flattenVolumeGroupStatusDescription(vg.StatusDescription.Errors)) + } + d.Set(Attr_VolumeGroupID, vg.ID) + d.Set(Attr_VolumeGroupStatus, vg.Status) return nil } @@ -161,9 +190,9 @@ func resourceIBMPIVolumeGroupUpdate(ctx context.Context, d *schema.ResourceData, return diag.FromErr(err) } - client := st.NewIBMPIVolumeGroupClient(ctx, sess, cloudInstanceID) - if d.HasChanges(PIVolumeIds) { - old, new := d.GetChange(PIVolumeIds) + client := instance.NewIBMPIVolumeGroupClient(ctx, sess, cloudInstanceID) + if d.HasChanges(Arg_VolumeIDs) { + old, new := d.GetChange(Arg_VolumeIDs) oldList := old.(*schema.Set) newList := new.(*schema.Set) body := &models.VolumeGroupUpdate{ @@ -193,9 +222,9 @@ func resourceIBMPIVolumeGroupDelete(ctx context.Context, d *schema.ResourceData, return diag.FromErr(err) } - client := st.NewIBMPIVolumeGroupClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIVolumeGroupClient(ctx, sess, cloudInstanceID) - volids := flex.ExpandStringList((d.Get(PIVolumeIds).(*schema.Set)).List()) + volids := flex.ExpandStringList((d.Get(Arg_VolumeIDs).(*schema.Set)).List()) if len(volids) > 0 { body := &models.VolumeGroupUpdate{ RemoveVolumes: volids, @@ -222,12 +251,12 @@ func resourceIBMPIVolumeGroupDelete(ctx context.Context, d *schema.ResourceData, d.SetId("") return nil } -func isWaitForIBMPIVolumeGroupAvailable(ctx context.Context, client *st.IBMPIVolumeGroupClient, id string, timeout time.Duration) (interface{}, error) { +func isWaitForIBMPIVolumeGroupAvailable(ctx context.Context, client *instance.IBMPIVolumeGroupClient, id string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for Volume Group (%s) to be available.", id) - stateConf := &resource.StateChangeConf{ - Pending: []string{"retry", helpers.PIVolumeProvisioning}, - Target: []string{helpers.PIVolumeProvisioningDone}, + stateConf := &retry.StateChangeConf{ + Pending: []string{State_Retry, State_Creating}, + Target: []string{State_Available}, Refresh: isIBMPIVolumeGroupRefreshFunc(client, id), Delay: 10 * time.Second, MinTimeout: 2 * time.Minute, @@ -237,25 +266,25 @@ func isWaitForIBMPIVolumeGroupAvailable(ctx context.Context, client *st.IBMPIVol return stateConf.WaitForStateContext(ctx) } -func isIBMPIVolumeGroupRefreshFunc(client *st.IBMPIVolumeGroupClient, id string) resource.StateRefreshFunc { +func isIBMPIVolumeGroupRefreshFunc(client *instance.IBMPIVolumeGroupClient, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { vg, err := client.Get(id) if err != nil { return nil, "", err } - if vg.Status == "available" { - return vg, helpers.PIVolumeProvisioningDone, nil + if vg.Status == State_Available { + return vg, State_Available, nil } - return vg, helpers.PIVolumeProvisioning, nil + return vg, State_Creating, nil } } -func isWaitForIBMPIVolumeGroupDeleted(ctx context.Context, client *st.IBMPIVolumeGroupClient, id string, timeout time.Duration) (interface{}, error) { - stateConf := &resource.StateChangeConf{ - Pending: []string{"deleting", "updating"}, - Target: []string{"deleted"}, +func isWaitForIBMPIVolumeGroupDeleted(ctx context.Context, client *instance.IBMPIVolumeGroupClient, id string, timeout time.Duration) (interface{}, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{State_Deleting, State_Updating}, + Target: []string{State_Deleted}, Refresh: isIBMPIVolumeGroupDeleteRefreshFunc(client, id), Delay: 10 * time.Second, MinTimeout: 2 * time.Minute, @@ -264,7 +293,7 @@ func isWaitForIBMPIVolumeGroupDeleted(ctx context.Context, client *st.IBMPIVolum return stateConf.WaitForStateContext(ctx) } -func isIBMPIVolumeGroupDeleteRefreshFunc(client *st.IBMPIVolumeGroupClient, id string) resource.StateRefreshFunc { +func isIBMPIVolumeGroupDeleteRefreshFunc(client *instance.IBMPIVolumeGroupClient, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { vg, err := client.Get(id) if err != nil { @@ -272,13 +301,13 @@ func isIBMPIVolumeGroupDeleteRefreshFunc(client *st.IBMPIVolumeGroupClient, id s switch uErr.(type) { case *p_cloud_volume_groups.PcloudVolumegroupsGetNotFound: log.Printf("[DEBUG] volume-group does not exist while deleteing %v", err) - return vg, "deleted", nil + return vg, State_Deleted, nil } return nil, "", err } if vg == nil { - return vg, "deleted", nil + return vg, State_Deleted, nil } - return vg, "deleting", nil + return vg, State_Deleting, nil } } diff --git a/ibm/service/power/resource_ibm_pi_volume_group_test.go b/ibm/service/power/resource_ibm_pi_volume_group_test.go index 5d55c1981b..b7b2a01473 100644 --- a/ibm/service/power/resource_ibm_pi_volume_group_test.go +++ b/ibm/service/power/resource_ibm_pi_volume_group_test.go @@ -10,8 +10,9 @@ import ( "log" "testing" - st "github.com/IBM-Cloud/power-go-client/clients/instance" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + + "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -54,7 +55,6 @@ func TestAccIBMPIVolumeGroupUpdate(t *testing.T) { } func testAccCheckIBMPIVolumeGroupDestroy(s *terraform.State) error { - sess, err := acc.TestAccProvider.Meta().(conns.ClientSession).IBMPISession() if err != nil { return err @@ -67,7 +67,7 @@ func testAccCheckIBMPIVolumeGroupDestroy(s *terraform.State) error { if err != nil { return err } - vgC := st.NewIBMPIVolumeGroupClient(context.Background(), sess, cloudInstanceID) + vgC := instance.NewIBMPIVolumeGroupClient(context.Background(), sess, cloudInstanceID) vg, err := vgC.Get(vgID) if err == nil { log.Println("volume-group*****", vg.Status) @@ -77,9 +77,9 @@ func testAccCheckIBMPIVolumeGroupDestroy(s *terraform.State) error { return nil } + func testAccCheckIBMPIVolumeGroupExists(n string) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] if !ok { @@ -98,7 +98,7 @@ func testAccCheckIBMPIVolumeGroupExists(n string) resource.TestCheckFunc { if err != nil { return err } - client := st.NewIBMPIVolumeGroupClient(context.Background(), sess, cloudInstanceID) + client := instance.NewIBMPIVolumeGroupClient(context.Background(), sess, cloudInstanceID) _, err = client.Get(vgID) if err != nil { @@ -111,44 +111,44 @@ func testAccCheckIBMPIVolumeGroupExists(n string) resource.TestCheckFunc { func testAccCheckIBMPIVolumeGroupConfig(name string) string { return volumeConfig(name, acc.Pi_cloud_instance_id) + fmt.Sprintf(` - resource "ibm_pi_volume_group" "power_volume_group"{ - pi_volume_group_name = "%[1]s" - pi_cloud_instance_id = "%[2]s" - pi_volume_ids = [ibm_pi_volume.power_volume[0].volume_id,ibm_pi_volume.power_volume[1].volume_id] - } + resource "ibm_pi_volume_group" "power_volume_group" { + pi_volume_group_name = "%[1]s" + pi_cloud_instance_id = "%[2]s" + pi_volume_ids = [ibm_pi_volume.power_volume[0].volume_id,ibm_pi_volume.power_volume[1].volume_id] + } `, name, acc.Pi_cloud_instance_id) } func testAccCheckIBMPIVolumeGroupUpdateConfig(name string) string { return volumeConfig(name, acc.Pi_cloud_instance_id) + fmt.Sprintf(` - resource "ibm_pi_volume_group" "power_volume_group"{ - pi_volume_group_name = "%[1]s" - pi_cloud_instance_id = "%[2]s" - pi_volume_ids = [ibm_pi_volume.power_volume[2].volume_id] - } + resource "ibm_pi_volume_group" "power_volume_group" { + pi_volume_group_name = "%[1]s" + pi_cloud_instance_id = "%[2]s" + pi_volume_ids = [ibm_pi_volume.power_volume[2].volume_id] + } `, name, acc.Pi_cloud_instance_id) } func testAccCheckIBMPIVolumeGroupEmptyVolumeConfig(name string) string { return volumeConfig(name, acc.Pi_cloud_instance_id) + fmt.Sprintf(` - resource "ibm_pi_volume_group" "power_volume_group"{ - pi_volume_group_name = "%[1]s" - pi_cloud_instance_id = "%[2]s" - pi_volume_ids = [] - } + resource "ibm_pi_volume_group" "power_volume_group" { + pi_volume_group_name = "%[1]s" + pi_cloud_instance_id = "%[2]s" + pi_volume_ids = [] + } `, name, acc.Pi_cloud_instance_id) } func volumeConfig(name, cloud_instance_id string) string { return fmt.Sprintf(` - resource "ibm_pi_volume" "power_volume" { - count = 3 - pi_volume_size = 2 - pi_volume_name = "%[1]s-${count.index}" - pi_volume_shareable = true - pi_volume_pool = "%[3]s" - pi_cloud_instance_id = "%[2]s" - pi_replication_enabled = true - } + resource "ibm_pi_volume" "power_volume" { + count = 3 + pi_volume_size = 2 + pi_volume_name = "%[1]s-${count.index}" + pi_volume_shareable = true + pi_volume_pool = "%[3]s" + pi_cloud_instance_id = "%[2]s" + pi_replication_enabled = true + } `, name, cloud_instance_id, acc.PiStoragePool) } diff --git a/ibm/service/resourcecontroller/data_source_ibm_resource_instance.go b/ibm/service/resourcecontroller/data_source_ibm_resource_instance.go index a3b5679c8c..59cf8b8cc6 100644 --- a/ibm/service/resourcecontroller/data_source_ibm_resource_instance.go +++ b/ibm/service/resourcecontroller/data_source_ibm_resource_instance.go @@ -94,6 +94,13 @@ func DataSourceIBMResourceInstance() *schema.Resource { Description: "Guid of resource instance", }, + // ### Modification addded onetime_credentials to Resource scehama + "onetime_credentials": { + Type: schema.TypeBool, + Computed: true, + Description: "onetime_credentials of resource instance", + }, + "parameters_json": { Description: "Parameters asociated with instance in json string", Type: schema.TypeString, @@ -270,6 +277,8 @@ func DataSourceIBMResourceInstanceRead(d *schema.ResourceData, meta interface{}) d.Set(flex.ResourceName, instance.Name) d.Set(flex.ResourceCRN, instance.CRN) d.Set(flex.ResourceStatus, instance.State) + // ### Modifiction : Setting the onetime credientials + d.Set("onetime_credentials", instance.OnetimeCredentials) if instance.Parameters != nil { params, err := json.Marshal(instance.Parameters) if err != nil { diff --git a/ibm/service/resourcecontroller/data_source_ibm_resource_key.go b/ibm/service/resourcecontroller/data_source_ibm_resource_key.go index 9a1bf688f4..fd8cb9b45a 100644 --- a/ibm/service/resourcecontroller/data_source_ibm_resource_key.go +++ b/ibm/service/resourcecontroller/data_source_ibm_resource_key.go @@ -58,6 +58,13 @@ func DataSourceIBMResourceKey() *schema.Resource { Description: "Status of resource key", }, + // ### Modification addded onetime_credentials to Resource scehama + "onetime_credentials": { + Type: schema.TypeBool, + Computed: true, + Description: "onetime_credentials of resource key", + }, + "credentials": { Description: "Credentials asociated with the key", Sensitive: true, @@ -162,6 +169,8 @@ func dataSourceIBMResourceKeyRead(d *schema.ResourceData, meta interface{}) erro d.Set("role", roleCrn[strings.LastIndex(roleCrn, ":")+1:]) } + // ### Modification for onetime_credientails + d.Set("onetime_credentials", key.OnetimeCredentials) d.Set("credentials", flex.Flatten(key.Credentials)) creds, err := json.Marshal(key.Credentials) if err != nil { diff --git a/ibm/service/resourcecontroller/resource_ibm_resource_instance.go b/ibm/service/resourcecontroller/resource_ibm_resource_instance.go index 7962aaeb3a..acadc93b7e 100644 --- a/ibm/service/resourcecontroller/resource_ibm_resource_instance.go +++ b/ibm/service/resourcecontroller/resource_ibm_resource_instance.go @@ -15,7 +15,7 @@ import ( rc "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" "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/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/bluemix-go/models" @@ -25,13 +25,14 @@ import ( ) const ( - RsInstanceSuccessStatus = "active" - RsInstanceProgressStatus = "in progress" - RsInstanceProvisioningStatus = "provisioning" - RsInstanceInactiveStatus = "inactive" - RsInstanceFailStatus = "failed" - RsInstanceRemovedStatus = "removed" - RsInstanceReclamation = "pending_reclamation" + RsInstanceSuccessStatus = "active" + RsInstanceProgressStatus = "in progress" + RsInstanceProvisioningStatus = "provisioning" + RsInstanceInactiveStatus = "inactive" + RsInstanceFailStatus = "failed" + RsInstanceRemovedStatus = "removed" + RsInstanceReclamation = "pending_reclamation" + RsInstanceUpdateSuccessStatus = "succeeded" ) func ResourceIBMResourceInstance() *schema.Resource { @@ -94,6 +95,13 @@ func ResourceIBMResourceInstance() *schema.Resource { "resource_group_id"), }, + // ### Modification : Adding onetime_credientails into the response scehama + "onetime_credentials": { + Description: "A boolean that dictates if the onetime_credentials is true or false.", + Type: schema.TypeBool, + Computed: true, + }, + "parameters": { Type: schema.TypeMap, Optional: true, @@ -595,6 +603,8 @@ func ResourceIBMResourceInstanceRead(d *schema.ResourceData, meta interface{}) e } d.Set("plan", servicePlan) d.Set("guid", instance.GUID) + // ### Modificataion : Setting "onetime_credentials" + d.Set("onetime_credentials", instance.OnetimeCredentials) if instance.Parameters != nil { if endpoint, ok := instance.Parameters["service-endpoints"]; ok { d.Set("service_endpoints", endpoint) @@ -733,12 +743,14 @@ func ResourceIBMResourceInstanceUpdate(d *schema.ResourceData, meta interface{}) } } } - serviceEndpoints := d.Get("service_endpoints").(string) - if serviceEndpoints != "" { - endpoint := d.Get("service_endpoints").(string) - params["service-endpoints"] = endpoint - } else if _, ok := instance.Parameters["service-endpoints"]; ok { - params["service-endpoints"] = instance.Parameters["service-endpoints"] + if _, ok := params["service-endpoints"]; !ok { + serviceEndpoints := d.Get("service_endpoints").(string) + if serviceEndpoints != "" { + endpoint := d.Get("service_endpoints").(string) + params["service-endpoints"] = endpoint + } else if _, ok := instance.Parameters["service-endpoints"]; ok { + params["service-endpoints"] = instance.Parameters["service-endpoints"] + } } } @@ -844,7 +856,7 @@ func waitForResourceInstanceCreate(d *schema.ResourceData, meta interface{}) (in ID: &instanceID, } - stateConf := &resource.StateChangeConf{ + stateConf := &retry.StateChangeConf{ Pending: []string{RsInstanceProgressStatus, RsInstanceInactiveStatus, RsInstanceProvisioningStatus}, Target: []string{RsInstanceSuccessStatus}, Refresh: func() (interface{}, string, error) { @@ -856,7 +868,7 @@ func waitForResourceInstanceCreate(d *schema.ResourceData, meta interface{}) (in return nil, "", fmt.Errorf("[ERROR] Get the resource 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 resource instance %s failed: %v", d.Id(), err) + return instance, *instance.State, fmt.Errorf("[ERROR] The resource instance '%s' creation failed: %v", d.Id(), err) } return instance, *instance.State, nil }, @@ -865,7 +877,7 @@ func waitForResourceInstanceCreate(d *schema.ResourceData, meta interface{}) (in MinTimeout: 10 * time.Second, } - return stateConf.WaitForState() + return stateConf.WaitForStateContext(context.Background()) } func waitForResourceInstanceUpdate(d *schema.ResourceData, meta interface{}) (interface{}, error) { @@ -878,9 +890,9 @@ func waitForResourceInstanceUpdate(d *schema.ResourceData, meta interface{}) (in ID: &instanceID, } - stateConf := &resource.StateChangeConf{ + stateConf := &retry.StateChangeConf{ Pending: []string{RsInstanceProgressStatus, RsInstanceInactiveStatus}, - Target: []string{RsInstanceSuccessStatus}, + Target: []string{RsInstanceSuccessStatus, RsInstanceUpdateSuccessStatus}, Refresh: func() (interface{}, string, error) { instance, resp, err := rsConClient.GetResourceInstance(&resourceInstanceGet) if err != nil { @@ -889,17 +901,24 @@ func waitForResourceInstanceUpdate(d *schema.ResourceData, meta interface{}) (in } return nil, "", fmt.Errorf("[ERROR] Get the resource 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 resource instance %s failed: %v", d.Id(), err) + if instance.LastOperation != nil && instance.LastOperation.Async != nil && *instance.LastOperation.Async { + if *instance.LastOperation.State == RsInstanceFailStatus { + return instance, *instance.LastOperation.State, fmt.Errorf("[ERROR] The resource instance '%s' update failed: %v", d.Id(), err) + } + return instance, *instance.LastOperation.State, nil + } else { + if *instance.State == RsInstanceFailStatus { + return instance, *instance.State, fmt.Errorf("[ERROR] The resource instance '%s' update failed: %v", d.Id(), err) + } + return instance, *instance.State, nil } - return instance, *instance.State, nil }, Timeout: d.Timeout(schema.TimeoutUpdate), Delay: 10 * time.Second, MinTimeout: 10 * time.Second, } - return stateConf.WaitForState() + return stateConf.WaitForStateContext(context.Background()) } func waitForResourceInstanceDelete(d *schema.ResourceData, meta interface{}) (interface{}, error) { @@ -911,7 +930,7 @@ func waitForResourceInstanceDelete(d *schema.ResourceData, meta interface{}) (in resourceInstanceGet := rc.GetResourceInstanceOptions{ ID: &instanceID, } - stateConf := &resource.StateChangeConf{ + stateConf := &retry.StateChangeConf{ Pending: []string{RsInstanceProgressStatus, RsInstanceInactiveStatus, RsInstanceSuccessStatus}, Target: []string{RsInstanceRemovedStatus, RsInstanceReclamation}, Refresh: func() (interface{}, string, error) { @@ -923,7 +942,7 @@ func waitForResourceInstanceDelete(d *schema.ResourceData, meta interface{}) (in return nil, "", fmt.Errorf("[ERROR] Get the resource 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 resource instance %s failed to delete: %v", d.Id(), err) + return instance, *instance.State, fmt.Errorf("[ERROR] The resource instance '%s' deletion failed: %v", d.Id(), err) } return instance, *instance.State, nil }, @@ -932,7 +951,7 @@ func waitForResourceInstanceDelete(d *schema.ResourceData, meta interface{}) (in MinTimeout: 10 * time.Second, } - return stateConf.WaitForState() + return stateConf.WaitForStateContext(context.Background()) } func FilterDeployments(deployments []models.ServiceDeployment, location string) ([]models.ServiceDeployment, map[string]bool) { diff --git a/ibm/service/resourcecontroller/resource_ibm_resource_instance_test.go b/ibm/service/resourcecontroller/resource_ibm_resource_instance_test.go index d40146555f..4543f0eb96 100644 --- a/ibm/service/resourcecontroller/resource_ibm_resource_instance_test.go +++ b/ibm/service/resourcecontroller/resource_ibm_resource_instance_test.go @@ -423,3 +423,46 @@ func testAccCheckIBMResourceInstanceServiceendpoints(serviceName string) string `, serviceName) } + +// /#### Adding new test case for onetime_credentials +func TestAccIBMResourceInstanceWithOnetimeCredentials(t *testing.T) { + serviceName := fmt.Sprintf("tf-Pgress-%d", acctest.RandIntRange(10, 100)) + resourceName := "ibm_resource_instance.instance" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMResourceInstanceDestroy, + Steps: []resource.TestStep{ + + { + Config: testAccCheckIBMResourceInstanceOnetimeCredentals(serviceName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMResourceInstanceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", serviceName), + resource.TestCheckResourceAttr(resourceName, "service", "cloud-object-storage"), + resource.TestCheckResourceAttr(resourceName, "plan", "lite"), + resource.TestCheckResourceAttr(resourceName, "location", "global"), + ), + }, + }, + }) +} + +func testAccCheckIBMResourceInstanceOnetimeCredentals(serviceName string) string { + return fmt.Sprintf(` + + resource "ibm_resource_instance" "instance" { + name = "%s" + location = "global" + service = "cloud-object-storage" + plan = "lite" + parameters = { + onetime_credentials = true, + } + + + } + + `, serviceName) +} diff --git a/ibm/service/resourcecontroller/resource_ibm_resource_key.go b/ibm/service/resourcecontroller/resource_ibm_resource_key.go index 55e3a83ded..5f693ddfc3 100644 --- a/ibm/service/resourcecontroller/resource_ibm_resource_key.go +++ b/ibm/service/resourcecontroller/resource_ibm_resource_key.go @@ -75,7 +75,12 @@ func ResourceIBMResourceKey() *schema.Resource { DiffSuppressFunc: flex.ApplyOnce, Description: "Arbitrary parameters to pass. Must be a JSON object", }, - + // ### Modification addded onetime_credentials to Resource scehama + "onetime_credentials": { + Type: schema.TypeBool, + Computed: true, + Description: "onetime_credentials of resource key", + }, "credentials": { Description: "Credentials asociated with the key", Type: schema.TypeMap, @@ -366,6 +371,8 @@ func resourceIBMResourceKeyRead(d *schema.ResourceData, meta interface{}) error d.Set("resource_group_id", *resourceKey.ResourceGroupID) d.Set("source_crn", *resourceKey.SourceCRN) d.Set("state", *resourceKey.State) + // ### Modificataion : Setting "onetime_credentials" + d.Set("onetime_credentials", *resourceKey.OnetimeCredentials) d.Set("iam_compatible", *resourceKey.IamCompatible) d.Set("resource_instance_url", *resourceKey.ResourceInstanceURL) if resourceKey.CreatedAt != nil { diff --git a/ibm/service/resourcemanager/resource_ibm_resource_group.go b/ibm/service/resourcemanager/resource_ibm_resource_group.go index 13dac090e0..f69da9ab2e 100644 --- a/ibm/service/resourcemanager/resource_ibm_resource_group.go +++ b/ibm/service/resourcemanager/resource_ibm_resource_group.go @@ -6,9 +6,12 @@ package resourcemanager import ( "fmt" "log" + "time" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" rg "github.com/IBM/platform-services-go-sdk/resourcemanagerv2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -21,6 +24,10 @@ func ResourceIBMResourceGroup() *schema.Resource { Exists: resourceIBMResourceGroupExists, Importer: &schema.ResourceImporter{}, + Timeouts: &schema.ResourceTimeout{ + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -222,7 +229,35 @@ func resourceIBMResourceGroupDelete(d *schema.ResourceData, meta interface{}) er log.Printf("[WARN] Resource Group is not found") return nil } - return fmt.Errorf("[ERROR] Error Deleting resource group: %s with response code %s", err, resp) + if resp != nil && resp.StatusCode == 500 { + err = retry.Retry(d.Timeout(schema.TimeoutDelete), func() *retry.RetryError { + resp, err = rMgtClient.DeleteResourceGroup(&resourceGroupDelete) + if err != nil { + if resp != nil && resp.StatusCode == 500 { + return resource.RetryableError(err) + } + if resp != nil && resp.StatusCode == 404 { + log.Printf("[WARN] Resource Group is not found") + return nil + } + return resource.NonRetryableError(err) + } + return nil + }) + if conns.IsResourceTimeoutError(err) { + resp, err = rMgtClient.DeleteResourceGroup(&resourceGroupDelete) + } + if err != nil { + if resp != nil && resp.StatusCode == 404 { + log.Printf("[WARN] Resource Group is not found") + return nil + } + return fmt.Errorf("[ERROR] Error Deleting resource group: %s with response code %s", err, resp) + } + } else { + + return fmt.Errorf("[ERROR] Error Deleting resource group: %s with response code %s", err, resp) + } } d.SetId("") diff --git a/ibm/service/satellite/data_source_ibm_satellite_location.go b/ibm/service/satellite/data_source_ibm_satellite_location.go index c1c8651fcf..fde706eb39 100644 --- a/ibm/service/satellite/data_source_ibm_satellite_location.go +++ b/ibm/service/satellite/data_source_ibm_satellite_location.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Copyright IBM Corp. 2017, 2024 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package satellite @@ -9,11 +9,12 @@ import ( "time" "github.com/IBM-Cloud/container-services-go-sdk/kubernetesserviceapiv1" - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/go-sdk-core/v5/core" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" ) func DataSourceIBMSatelliteLocation() *schema.Resource { @@ -31,6 +32,18 @@ func DataSourceIBMSatelliteLocation() *schema.Resource { Computed: true, Description: "The IBM Cloud metro from which the Satellite location is managed", }, + "physical_address": { + Type: schema.TypeString, + Computed: true, + Description: "An optional physical address of the new Satellite location which is deployed on premise", + }, + "capabilities": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + Description: "The satellite capabilities attached to the location", + }, "description": { Type: schema.TypeString, Computed: true, @@ -166,6 +179,8 @@ func dataSourceIBMSatelliteLocationRead(d *schema.ResourceData, meta interface{} var instance *kubernetesserviceapiv1.MultishiftGetController var response *core.DetailedResponse + // TO-DO: resource.Retry, resource.RetryError, resource.RetryableError and resource.NonRetryableError + // seem to be deprecated. This shall be replaced. err = resource.Retry(1*time.Minute, func() *resource.RetryError { instance, response, err = satClient.GetSatelliteLocation(getSatLocOptions) if err != nil || instance == nil { @@ -187,6 +202,12 @@ func dataSourceIBMSatelliteLocationRead(d *schema.ResourceData, meta interface{} d.SetId(*instance.ID) d.Set("location", location) d.Set("description", *instance.Description) + if instance.PhysicalAddress != nil { + d.Set("physical_address", *instance.PhysicalAddress) + } + if instance.CapabilitiesManagedBySatellite != nil { + d.Set("capabilities", instance.CapabilitiesManagedBySatellite) + } if instance.CoreosEnabled != nil { d.Set("coreos_enabled", *instance.CoreosEnabled) } diff --git a/ibm/service/satellite/data_source_ibm_satellite_location_nlb_dns_test.go b/ibm/service/satellite/data_source_ibm_satellite_location_nlb_dns_test.go index 0d6d095029..8a2263c49b 100644 --- a/ibm/service/satellite/data_source_ibm_satellite_location_nlb_dns_test.go +++ b/ibm/service/satellite/data_source_ibm_satellite_location_nlb_dns_test.go @@ -7,21 +7,25 @@ import ( "fmt" "testing" - acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" - + "github.com/IBM-Cloud/container-services-go-sdk/kubernetesserviceapiv1" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" ) func TestAccIBMSatelliteLocationNLBDNSListBasic(t *testing.T) { name := fmt.Sprintf("tf-satellitelocation-%d", acctest.RandIntRange(10, 100)) managed_from := "wdc04" + physical_address := "test location address" + capabilities := []kubernetesserviceapiv1.CapabilityManagedBySatellite{kubernetesserviceapiv1.OnPrem} + resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, Providers: acc.TestAccProviders, Steps: []resource.TestStep{ { - Config: testAccCheckIBMSatelliteLocationNLBDNSListConfig(name, managed_from), + Config: testAccCheckIBMSatelliteLocationNLBDNSListConfig(name, managed_from, physical_address, capabilities), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.ibm_satellite_location_nlb_dns.dns_list", "id"), ), @@ -30,8 +34,8 @@ func TestAccIBMSatelliteLocationNLBDNSListBasic(t *testing.T) { }) } -func testAccCheckIBMSatelliteLocationNLBDNSListConfig(name, managed_from string) string { - return testAccCheckSatelliteLocationDataSource(name, managed_from) + ` +func testAccCheckIBMSatelliteLocationNLBDNSListConfig(name, managed_from, physical_address string, capabilities []kubernetesserviceapiv1.CapabilityManagedBySatellite) string { + return testAccCheckSatelliteLocationDataSource(name, managed_from, physical_address, capabilities) + ` data ibm_satellite_location_nlb_dns dns_list { location = ibm_satellite_location.location.id } diff --git a/ibm/service/satellite/data_source_ibm_satellite_location_test.go b/ibm/service/satellite/data_source_ibm_satellite_location_test.go index 5c820689b4..5364e053f6 100644 --- a/ibm/service/satellite/data_source_ibm_satellite_location_test.go +++ b/ibm/service/satellite/data_source_ibm_satellite_location_test.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Copyright IBM Corp. 2017, 2024 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package satellite_test @@ -7,15 +7,18 @@ import ( "fmt" "testing" - acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" - + "github.com/IBM-Cloud/container-services-go-sdk/kubernetesserviceapiv1" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" ) func TestAccSatelliteLocationDataSourceBasic(t *testing.T) { name := fmt.Sprintf("tf-satellitelocation-%d", acctest.RandIntRange(10, 100)) managed_from := "wdc04" + physical_address := "test-road 10, 111 test-place, testcountry" + capabilities := []kubernetesserviceapiv1.CapabilityManagedBySatellite{kubernetesserviceapiv1.OnPrem} resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -23,29 +26,34 @@ func TestAccSatelliteLocationDataSourceBasic(t *testing.T) { Steps: []resource.TestStep{ { - Config: testAccCheckSatelliteLocationDataSource(name, managed_from), + Config: testAccCheckSatelliteLocationDataSource(name, managed_from, physical_address, capabilities), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("ibm_satellite_location.location", "location", name), resource.TestCheckResourceAttr("ibm_satellite_location.location", "managed_from", managed_from), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "physical_address", physical_address), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "capabilities.#", "1"), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "capabilities.0", "on-prem"), ), }, }, }) } -func testAccCheckSatelliteLocationDataSource(name, managed_from string) string { +func testAccCheckSatelliteLocationDataSource(name, managed_from string, physical_address string, capabilities []kubernetesserviceapiv1.CapabilityManagedBySatellite) string { return fmt.Sprintf(` resource "ibm_satellite_location" "location" { location = "%s" managed_from = "%s" + physical_address = "%s" description = "satellite service" zones = ["us-east-1", "us-east-2", "us-east-3"] tags = ["env:dev"] + capabilities = %q } data "ibm_satellite_location" "test_location" { location = ibm_satellite_location.location.id -}`, name, managed_from) +}`, name, managed_from, physical_address, capabilities) } diff --git a/ibm/service/satellite/resource_ibm_satellite_cluster_worker_pool.go b/ibm/service/satellite/resource_ibm_satellite_cluster_worker_pool.go index 0eb93846c4..82d4af921b 100644 --- a/ibm/service/satellite/resource_ibm_satellite_cluster_worker_pool.go +++ b/ibm/service/satellite/resource_ibm_satellite_cluster_worker_pool.go @@ -364,7 +364,7 @@ func resourceIBMSatelliteClusterWorkerPoolUpdate(d *schema.ResourceData, meta in clusterNameOrID := d.Get("cluster").(string) workerPoolName := d.Get("name").(string) count := d.Get("worker_count").(int) - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -446,7 +446,7 @@ func resourceIBMSatelliteClusterWorkerPoolDelete(d *schema.ResourceData, meta in return err } - targetEnv, err := getVpcClusterTargetHeader(d, meta) + targetEnv, err := getVpcClusterTargetHeader(d) if err != nil { return err } @@ -472,7 +472,7 @@ func resourceIBMSatelliteClusterWorkerPoolDelete(d *schema.ResourceData, meta in d.SetId("") return nil } -func getVpcClusterTargetHeader(d *schema.ResourceData, meta interface{}) (v2.ClusterTargetHeader, error) { +func getVpcClusterTargetHeader(d *schema.ResourceData) (v2.ClusterTargetHeader, error) { targetEnv := v2.ClusterTargetHeader{} var resourceGroup string if rg, ok := d.GetOk("resource_group_id"); ok { diff --git a/ibm/service/satellite/resource_ibm_satellite_location.go b/ibm/service/satellite/resource_ibm_satellite_location.go index ccb0d40b81..41d43c1750 100644 --- a/ibm/service/satellite/resource_ibm_satellite_location.go +++ b/ibm/service/satellite/resource_ibm_satellite_location.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Copyright IBM Corp. 2017, 2024 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package satellite @@ -11,13 +11,14 @@ import ( "time" "github.com/IBM-Cloud/container-services-go-sdk/kubernetesserviceapiv1" - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" "github.com/IBM/go-sdk-core/v5/core" "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/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" ) const ( @@ -93,6 +94,21 @@ func ResourceIBMSatelliteLocation() *schema.Resource { }, Description: "The IBM Cloud metro from which the Satellite location is managed", }, + "physical_address": { + Type: schema.TypeString, + DiffSuppressFunc: flex.ApplyOnce, + Optional: true, + Description: "An optional physical address of the new Satellite location which is deployed on premise", + }, + "capabilities": { + Type: schema.TypeSet, + DiffSuppressFunc: flex.ApplyOnce, + Optional: true, + RequiredWith: []string{"physical_address"}, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + Description: "The satellite capabilities attached to the location", + }, "description": { Type: schema.TypeString, Optional: true, @@ -237,7 +253,24 @@ func ResourceIBMSatelliteLocationValidator() *validate.ResourceValidator { Optional: true, Regexp: `^[A-Za-z0-9:_ .-]+$`, MinValueLength: 1, - MaxValueLength: 128}) + MaxValueLength: 128, + }, + validate.ValidateSchema{ + Identifier: "physical_address", + ValidateFunctionIdentifier: validate.StringLenBetween, + Type: validate.TypeString, + Optional: true, + MinValueLength: 0, + MaxValueLength: 400, + }, + validate.ValidateSchema{ + Identifier: "capabilities", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Optional: true, + AllowedValues: "on-prem", + }, + ) ibmSatelliteLocationValidator := validate.ResourceValidator{ResourceName: "ibm_satellite_location", Schema: validateSchema} return &ibmSatelliteLocationValidator @@ -272,6 +305,16 @@ func resourceIBMSatelliteLocationCreate(d *schema.ResourceData, meta interface{} createSatLocOptions.LoggingAccountID = &logAccID } + if v, ok := d.GetOk("physical_address"); ok { + addr := v.(string) + createSatLocOptions.PhysicalAddress = &addr + } + + if v, ok := d.GetOk("capabilities"); ok { + z := v.(*schema.Set) + createSatLocOptions.CapabilitiesManagedBySatellite = flex.FlattenSatelliteCapabilities(z) + } + if v, ok := d.GetOk("description"); ok { desc := v.(string) createSatLocOptions.Description = &desc @@ -351,6 +394,14 @@ func resourceIBMSatelliteLocationRead(d *schema.ResourceData, meta interface{}) d.Set("description", *instance.Description) } + if instance.PhysicalAddress != nil { + d.Set("physical_address", *instance.PhysicalAddress) + } + + if instance.CapabilitiesManagedBySatellite != nil { + d.Set("capabilities", instance.CapabilitiesManagedBySatellite) + } + if instance.CoreosEnabled != nil { d.Set("coreos_enabled", *instance.CoreosEnabled) } diff --git a/ibm/service/satellite/resource_ibm_satellite_location_test.go b/ibm/service/satellite/resource_ibm_satellite_location_test.go index 3892f0a03d..b6f9f3c66e 100644 --- a/ibm/service/satellite/resource_ibm_satellite_location_test.go +++ b/ibm/service/satellite/resource_ibm_satellite_location_test.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Copyright IBM Corp. 2017, 2024 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package satellite_test @@ -7,20 +7,22 @@ import ( "fmt" "testing" - acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" - "github.com/IBM-Cloud/container-services-go-sdk/kubernetesserviceapiv1" "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" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" ) func TestAccSatelliteLocation_Basic(t *testing.T) { var instance string name := fmt.Sprintf("tf-satellitelocation-%d", acctest.RandIntRange(10, 100)) managed_from := "wdc04" + physical_address := "test-road 10, 111 test-place, testcountry" coreos_enabled := "true" + capabilities := []kubernetesserviceapiv1.CapabilityManagedBySatellite{kubernetesserviceapiv1.OnPrem} resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -29,12 +31,15 @@ func TestAccSatelliteLocation_Basic(t *testing.T) { Steps: []resource.TestStep{ { - Config: testAccCheckSatelliteLocationCreate(name, managed_from, coreos_enabled, "", ""), + Config: testAccCheckSatelliteLocationCreate(name, managed_from, physical_address, coreos_enabled, "", "", capabilities), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckSatelliteLocationExists("ibm_satellite_location.location", instance), resource.TestCheckResourceAttr("ibm_satellite_location.location", "location", name), resource.TestCheckResourceAttr("ibm_satellite_location.location", "managed_from", managed_from), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "physical_address", physical_address), resource.TestCheckResourceAttr("ibm_satellite_location.location", "coreos_enabled", coreos_enabled), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "capabilities.#", "1"), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "capabilities.0", "on-prem"), ), }, }, @@ -45,7 +50,9 @@ func TestAccSatelliteLocation_Import(t *testing.T) { var instance string name := fmt.Sprintf("tf_location_%d", acctest.RandIntRange(10, 100)) managed_from := "wdc04" + physical_address := "test-road 10, 111 test-place, testcountry" coreos_enabled := "true" + capabilities := []kubernetesserviceapiv1.CapabilityManagedBySatellite{kubernetesserviceapiv1.OnPrem} resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -54,11 +61,14 @@ func TestAccSatelliteLocation_Import(t *testing.T) { Steps: []resource.TestStep{ { - Config: testAccCheckSatelliteLocationCreate(name, managed_from, coreos_enabled, "", ""), + Config: testAccCheckSatelliteLocationCreate(name, managed_from, physical_address, coreos_enabled, "", "", capabilities), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckSatelliteLocationExists("ibm_satellite_location.location", instance), resource.TestCheckResourceAttr("ibm_satellite_location.location", "location", name), resource.TestCheckResourceAttr("ibm_satellite_location.location", "managed_from", managed_from), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "physical_address", physical_address), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "capabilities.#", "1"), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "capabilities.0", "on-prem"), ), }, { @@ -74,9 +84,11 @@ func TestAccSatelliteLocation_PodAndServiceSubnet(t *testing.T) { var instance string name := fmt.Sprintf("tf-satellitelocation-%d", acctest.RandIntRange(10, 100)) managed_from := "wdc04" + physical_address := "test-road 10, 111 test-place, testcountry" coreos_enabled := "true" pod_subnet := "10.69.0.0/16" service_subnet := "192.168.42.0/24" + capabilities := []kubernetesserviceapiv1.CapabilityManagedBySatellite{kubernetesserviceapiv1.OnPrem} resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -84,14 +96,17 @@ func TestAccSatelliteLocation_PodAndServiceSubnet(t *testing.T) { Steps: []resource.TestStep{ { - Config: testAccCheckSatelliteLocationCreate(name, managed_from, coreos_enabled, pod_subnet, service_subnet), + Config: testAccCheckSatelliteLocationCreate(name, managed_from, physical_address, coreos_enabled, pod_subnet, service_subnet, capabilities), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckSatelliteLocationExists("ibm_satellite_location.location", instance), resource.TestCheckResourceAttr("ibm_satellite_location.location", "location", name), resource.TestCheckResourceAttr("ibm_satellite_location.location", "managed_from", managed_from), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "physical_address", physical_address), resource.TestCheckResourceAttr("ibm_satellite_location.location", "coreos_enabled", coreos_enabled), resource.TestCheckResourceAttr("ibm_satellite_location.location", "pod_subnet", pod_subnet), resource.TestCheckResourceAttr("ibm_satellite_location.location", "service_subnet", service_subnet), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "capabilities.#", "1"), + resource.TestCheckResourceAttr("ibm_satellite_location.location", "capabilities.0", "on-prem"), ), }, }, @@ -154,7 +169,7 @@ func testAccCheckSatelliteLocationDestroy(s *terraform.State) error { return nil } -func testAccCheckSatelliteLocationCreate(name, managed_from string, coreos_enabled string, pod_subnet, service_subnet string) string { +func testAccCheckSatelliteLocationCreate(name, managed_from string, physical_address string, coreos_enabled string, pod_subnet, service_subnet string, capabilities []kubernetesserviceapiv1.CapabilityManagedBySatellite) string { return fmt.Sprintf(` data "ibm_resource_group" "res_group" { @@ -164,6 +179,7 @@ func testAccCheckSatelliteLocationCreate(name, managed_from string, coreos_enabl resource "ibm_satellite_location" "location" { location = "%s" managed_from = "%s" + physical_address = "%s" coreos_enabled = "%s" description = "test" zones = ["us-east-1", "us-east-2", "us-east-3"] @@ -171,7 +187,8 @@ func testAccCheckSatelliteLocationCreate(name, managed_from string, coreos_enabl tags = ["env:dev"] pod_subnet = "%s" service_subnet = "%s" + capabilities = %q } -`, name, managed_from, coreos_enabled, pod_subnet, service_subnet) +`, name, managed_from, physical_address, coreos_enabled, pod_subnet, service_subnet, capabilities) } diff --git a/ibm/service/scc/data_source_ibm_scc_control_libraries.go b/ibm/service/scc/data_source_ibm_scc_control_libraries.go index fd7c49104c..6ee380e9b6 100644 --- a/ibm/service/scc/data_source_ibm_scc_control_libraries.go +++ b/ibm/service/scc/data_source_ibm_scc_control_libraries.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" ) @@ -135,27 +136,27 @@ func dataSourceIbmSccControlLibrariesRead(context context.Context, d *schema.Res pager, err := securityandcompliancecenterapiClient.NewControlLibrariesPager(listControlLibrariesOptions) if err != nil { log.Printf("[DEBUG] ListControlLibrarysWithContext failed %s", err) - return diag.FromErr(fmt.Errorf("ListControlLibrarysWithContext failed %s", err)) + return diag.FromErr(flex.FmtErrorf("ListControlLibrarysWithContext failed %s", err)) } controlLibraryList, err := pager.GetAll() if err != nil { log.Printf("[DEBUG] ListControlLibrarysWithContext failed %s", err) - return diag.FromErr(fmt.Errorf("ListControlLibrarysWithContext failed %s", err)) + return diag.FromErr(flex.FmtErrorf("ListControlLibrarysWithContext failed %s", err)) } d.SetId(fmt.Sprintf("%s/control_libraries", d.Get("instance_id").(string))) if err = d.Set("instance_id", d.Get("instance_id")); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id %s", err)) } controlLibraries := []map[string]interface{}{} for _, cl := range controlLibraryList { modelMap, err := dataSourceIbmSccControlLibraryToMap(&cl) if err != nil { - return diag.FromErr(fmt.Errorf("Error setting control library:%v\n%s", cl, err)) + return diag.FromErr(flex.FmtErrorf("Error setting control library:%v\n%s", cl, err)) } controlLibraries = append(controlLibraries, modelMap) } if err = d.Set("control_libraries", controlLibraries); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_libraries: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_libraries: %s", err)) } return nil } diff --git a/ibm/service/scc/data_source_ibm_scc_control_library.go b/ibm/service/scc/data_source_ibm_scc_control_library.go index fe7b9df7b0..f05e62fad0 100644 --- a/ibm/service/scc/data_source_ibm_scc_control_library.go +++ b/ibm/service/scc/data_source_ibm_scc_control_library.go @@ -287,65 +287,65 @@ func dataSourceIbmSccControlLibraryRead(context context.Context, d *schema.Resou controlLibrary, response, err := securityandcompliancecenterapiClient.GetControlLibraryWithContext(context, getControlLibraryOptions) if err != nil { log.Printf("[DEBUG] GetControlLibraryWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetControlLibraryWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetControlLibraryWithContext failed %s\n%s", err, response)) } d.SetId(fmt.Sprintf("%s", *getControlLibraryOptions.ControlLibrariesID)) if err = d.Set("account_id", controlLibrary.AccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting account_id: %s", err)) } if err = d.Set("control_library_name", controlLibrary.ControlLibraryName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_library_name: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_library_name: %s", err)) } if err = d.Set("control_library_description", controlLibrary.ControlLibraryDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_library_description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_library_description: %s", err)) } if err = d.Set("control_library_type", controlLibrary.ControlLibraryType); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_library_type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_library_type: %s", err)) } if err = d.Set("version_group_label", controlLibrary.VersionGroupLabel); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version_group_label: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting version_group_label: %s", err)) } if err = d.Set("control_library_version", controlLibrary.ControlLibraryVersion); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_library_version: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_library_version: %s", err)) } if err = d.Set("created_on", flex.DateTimeToString(controlLibrary.CreatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } if err = d.Set("created_by", controlLibrary.CreatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_by: %s", err)) } if err = d.Set("updated_on", flex.DateTimeToString(controlLibrary.UpdatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_on: %s", err)) } if err = d.Set("updated_by", controlLibrary.UpdatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_by: %s", err)) } if err = d.Set("latest", controlLibrary.Latest); err != nil { - return diag.FromErr(fmt.Errorf("Error setting latest: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting latest: %s", err)) } if err = d.Set("hierarchy_enabled", controlLibrary.HierarchyEnabled); err != nil { - return diag.FromErr(fmt.Errorf("Error setting hierarchy_enabled: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting hierarchy_enabled: %s", err)) } if err = d.Set("controls_count", flex.IntValue(controlLibrary.ControlsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls_count: %s", err)) } if err = d.Set("control_parents_count", flex.IntValue(controlLibrary.ControlParentsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_parents_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_parents_count: %s", err)) } controls := []map[string]interface{}{} @@ -359,7 +359,7 @@ func dataSourceIbmSccControlLibraryRead(context context.Context, d *schema.Resou } } if err = d.Set("controls", controls); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_instance_settings.go b/ibm/service/scc/data_source_ibm_scc_instance_settings.go index 4ba27e9dbb..468999fe87 100644 --- a/ibm/service/scc/data_source_ibm_scc_instance_settings.go +++ b/ibm/service/scc/data_source_ibm_scc_instance_settings.go @@ -5,13 +5,13 @@ package scc import ( "context" - "fmt" "log" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" ) @@ -103,7 +103,7 @@ func dataSourceIbmSccInstanceSettingsRead(context context.Context, d *schema.Res return nil } log.Printf("[DEBUG] GetSettingsWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetSettingsWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetSettingsWithContext failed %s\n%s", err, response)) } if !core.IsNil(settings.EventNotifications) { @@ -113,7 +113,7 @@ func dataSourceIbmSccInstanceSettingsRead(context context.Context, d *schema.Res } if err = d.Set("event_notifications", []map[string]interface{}{eventNotificationsMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting event_notifications: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting event_notifications: %s", err)) } } if !core.IsNil(settings.ObjectStorage) { @@ -122,7 +122,7 @@ func dataSourceIbmSccInstanceSettingsRead(context context.Context, d *schema.Res return diag.FromErr(err) } if err = d.Set("object_storage", []map[string]interface{}{objectStorageMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting object_storage: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting object_storage: %s", err)) } } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_latest_reports.go b/ibm/service/scc/data_source_ibm_scc_latest_reports.go index d6c48d2e4b..d09c980075 100644 --- a/ibm/service/scc/data_source_ibm_scc_latest_reports.go +++ b/ibm/service/scc/data_source_ibm_scc_latest_reports.go @@ -5,7 +5,6 @@ package scc import ( "context" - "fmt" "log" "time" @@ -313,13 +312,13 @@ func dataSourceIbmSccLatestReportsRead(context context.Context, d *schema.Resour reportLatest, response, err := resultsClient.GetLatestReportsWithContext(context, getLatestReportsOptions) if err != nil { log.Printf("[DEBUG] GetLatestReportsWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetLatestReportsWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetLatestReportsWithContext failed %s\n%s", err, response)) } d.SetId(dataSourceIbmSccLatestReportsID(d)) if err = d.Set("home_account_id", reportLatest.HomeAccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting home_account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting home_account_id: %s", err)) } controlsSummary := []map[string]interface{}{} @@ -331,7 +330,7 @@ func dataSourceIbmSccLatestReportsRead(context context.Context, d *schema.Resour controlsSummary = append(controlsSummary, modelMap) } if err = d.Set("controls_summary", controlsSummary); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls_summary %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls_summary %s", err)) } evaluationsSummary := []map[string]interface{}{} @@ -343,7 +342,7 @@ func dataSourceIbmSccLatestReportsRead(context context.Context, d *schema.Resour evaluationsSummary = append(evaluationsSummary, modelMap) } if err = d.Set("evaluations_summary", evaluationsSummary); err != nil { - return diag.FromErr(fmt.Errorf("Error setting evaluations_summary %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting evaluations_summary %s", err)) } score := []map[string]interface{}{} @@ -355,7 +354,7 @@ func dataSourceIbmSccLatestReportsRead(context context.Context, d *schema.Resour score = append(score, modelMap) } if err = d.Set("score", score); err != nil { - return diag.FromErr(fmt.Errorf("Error setting score %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting score %s", err)) } reports := []map[string]interface{}{} @@ -369,7 +368,7 @@ func dataSourceIbmSccLatestReportsRead(context context.Context, d *schema.Resour } } if err = d.Set("reports", reports); err != nil { - return diag.FromErr(fmt.Errorf("Error setting reports %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting reports %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_profile.go b/ibm/service/scc/data_source_ibm_scc_profile.go index 1974088603..d847cce942 100644 --- a/ibm/service/scc/data_source_ibm_scc_profile.go +++ b/ibm/service/scc/data_source_ibm_scc_profile.go @@ -333,65 +333,65 @@ func dataSourceIbmSccProfileRead(context context.Context, d *schema.ResourceData profile, response, err := securityandcompliancecenterapiClient.GetProfileWithContext(context, getProfileOptions) if err != nil { log.Printf("[DEBUG] GetProfileWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetProfileWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetProfileWithContext failed %s\n%s", err, response)) } d.SetId(fmt.Sprintf("%s", *getProfileOptions.ProfileID)) if err = d.Set("profile_name", profile.ProfileName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_name: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_name: %s", err)) } if err = d.Set("profile_description", profile.ProfileDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_description: %s", err)) } if err = d.Set("profile_type", profile.ProfileType); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_type: %s", err)) } if err = d.Set("profile_version", profile.ProfileVersion); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_version: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_version: %s", err)) } if err = d.Set("version_group_label", profile.VersionGroupLabel); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version_group_label: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting version_group_label: %s", err)) } if err = d.Set("latest", profile.Latest); err != nil { - return diag.FromErr(fmt.Errorf("Error setting latest: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting latest: %s", err)) } if err = d.Set("hierarchy_enabled", profile.HierarchyEnabled); err != nil { - return diag.FromErr(fmt.Errorf("Error setting hierarchy_enabled: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting hierarchy_enabled: %s", err)) } if err = d.Set("created_by", profile.CreatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_by: %s", err)) } if err = d.Set("created_on", flex.DateTimeToString(profile.CreatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } if err = d.Set("updated_by", profile.UpdatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_by: %s", err)) } if err = d.Set("updated_on", flex.DateTimeToString(profile.UpdatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_on: %s", err)) } if err = d.Set("controls_count", flex.IntValue(profile.ControlsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls_count: %s", err)) } if err = d.Set("control_parents_count", flex.IntValue(profile.ControlParentsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_parents_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_parents_count: %s", err)) } if err = d.Set("attachments_count", flex.IntValue(profile.AttachmentsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attachments_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attachments_count: %s", err)) } controls := []map[string]interface{}{} @@ -405,7 +405,7 @@ func dataSourceIbmSccProfileRead(context context.Context, d *schema.ResourceData } } if err = d.Set("controls", controls); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls %s", err)) } defaultParameters := []map[string]interface{}{} @@ -419,7 +419,7 @@ func dataSourceIbmSccProfileRead(context context.Context, d *schema.ResourceData } } if err = d.Set("default_parameters", defaultParameters); err != nil { - return diag.FromErr(fmt.Errorf("Error setting default_parameters %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting default_parameters %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_profile_attachment.go b/ibm/service/scc/data_source_ibm_scc_profile_attachment.go index 64ee30e057..553805223a 100644 --- a/ibm/service/scc/data_source_ibm_scc_profile_attachment.go +++ b/ibm/service/scc/data_source_ibm_scc_profile_attachment.go @@ -242,21 +242,21 @@ func dataSourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Re attachmentItem, response, err := securityandcompliancecenterapiClient.GetProfileAttachmentWithContext(context, getProfileAttachmentOptions) if err != nil { log.Printf("[DEBUG] GetProfileAttachmentWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetProfileAttachmentWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetProfileAttachmentWithContext failed %s\n%s", err, response)) } d.SetId(fmt.Sprintf("%s/%s", *getProfileAttachmentOptions.AttachmentID, *getProfileAttachmentOptions.ProfileID)) if err = d.Set("attachment_item_id", attachmentItem.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attachment_item_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attachment_item_id: %s", err)) } if err = d.Set("account_id", attachmentItem.AccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting account_id: %s", err)) } if err = d.Set("instance_id", attachmentItem.InstanceID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } scope := []map[string]interface{}{} @@ -270,31 +270,31 @@ func dataSourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Re } } if err = d.Set("scope", scope); err != nil { - return diag.FromErr(fmt.Errorf("Error setting scope %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting scope %s", err)) } if err = d.Set("created_on", flex.DateTimeToString(attachmentItem.CreatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } if err = d.Set("created_by", attachmentItem.CreatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_by: %s", err)) } if err = d.Set("updated_on", flex.DateTimeToString(attachmentItem.UpdatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_on: %s", err)) } if err = d.Set("updated_by", attachmentItem.UpdatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_by: %s", err)) } if err = d.Set("status", attachmentItem.Status); err != nil { - return diag.FromErr(fmt.Errorf("Error setting status: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting status: %s", err)) } if err = d.Set("schedule", attachmentItem.Schedule); err != nil { - return diag.FromErr(fmt.Errorf("Error setting schedule: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting schedule: %s", err)) } notifications := []map[string]interface{}{} @@ -306,7 +306,7 @@ func dataSourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Re notifications = append(notifications, modelMap) } if err = d.Set("notifications", notifications); err != nil { - return diag.FromErr(fmt.Errorf("Error setting notifications %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting notifications %s", err)) } attachmentParameters := []map[string]interface{}{} @@ -320,7 +320,7 @@ func dataSourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Re } } if err = d.Set("attachment_parameters", attachmentParameters); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attachment_parameters %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attachment_parameters %s", err)) } lastScan := []map[string]interface{}{} @@ -332,19 +332,19 @@ func dataSourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Re lastScan = append(lastScan, modelMap) } if err = d.Set("last_scan", lastScan); err != nil { - return diag.FromErr(fmt.Errorf("Error setting last_scan %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting last_scan %s", err)) } if err = d.Set("next_scan_time", flex.DateTimeToString(attachmentItem.NextScanTime)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting next_scan_time: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting next_scan_time: %s", err)) } if err = d.Set("name", attachmentItem.Name); err != nil { - return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting name: %s", err)) } if err = d.Set("description", attachmentItem.Description); err != nil { - return diag.FromErr(fmt.Errorf("Error setting description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting description: %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_profiles.go b/ibm/service/scc/data_source_ibm_scc_profiles.go index 51bad45806..c203834eb4 100644 --- a/ibm/service/scc/data_source_ibm_scc_profiles.go +++ b/ibm/service/scc/data_source_ibm_scc_profiles.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" ) @@ -129,27 +130,27 @@ func dataSourceIbmSccProfilesRead(context context.Context, d *schema.ResourceDat pager, err := securityandcompliancecenterapiClient.NewProfilesPager(listProfilesOptions) if err != nil { log.Printf("[DEBUG] ListProfilesWithContext failed %s", err) - return diag.FromErr(fmt.Errorf("ListProfilesWithContext failed %s", err)) + return diag.FromErr(flex.FmtErrorf("ListProfilesWithContext failed %s", err)) } profileList, err := pager.GetAll() if err != nil { log.Printf("[DEBUG] ListProfilesWithContext failed %s", err) - return diag.FromErr(fmt.Errorf("ListProfilesWithContext failed %s", err)) + return diag.FromErr(flex.FmtErrorf("ListProfilesWithContext failed %s", err)) } d.SetId(fmt.Sprintf("%s/profiles", d.Get("instance_id").(string))) if err = d.Set("instance_id", d.Get("instance_id")); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id %s", err)) } profiles := []map[string]interface{}{} for _, profile := range profileList { modelMap, err := dataSourceIbmSccProfileToMap(&profile) if err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile:%v\n%s", profile, err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile:%v\n%s", profile, err)) } profiles = append(profiles, modelMap) } if err = d.Set("profiles", profiles); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profiles: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profiles: %s", err)) } return nil } diff --git a/ibm/service/scc/data_source_ibm_scc_provider_type.go b/ibm/service/scc/data_source_ibm_scc_provider_type.go index 40446c10bd..9e52f6afa1 100644 --- a/ibm/service/scc/data_source_ibm_scc_provider_type.go +++ b/ibm/service/scc/data_source_ibm_scc_provider_type.go @@ -5,7 +5,6 @@ package scc import ( "context" - "fmt" "log" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -126,45 +125,45 @@ func dataSourceIbmSccProviderTypeRead(context context.Context, d *schema.Resourc providerTypeItem, response, err := securityAndComplianceCenterApIsClient.GetProviderTypeByIDWithContext(context, getProviderTypeByIdOptions) if err != nil { log.Printf("[DEBUG] GetProviderTypeByIDWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetProviderTypeByIDWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetProviderTypeByIDWithContext failed %s\n%s", err, response)) } d.SetId(*providerTypeItem.ID) if err = d.Set("id", providerTypeItem.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting id: %s", err)) } if err = d.Set("type", providerTypeItem.Type); err != nil { - return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting type: %s", err)) } if err = d.Set("name", providerTypeItem.Name); err != nil { - return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting name: %s", err)) } if err = d.Set("description", providerTypeItem.Description); err != nil { - return diag.FromErr(fmt.Errorf("Error setting description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting description: %s", err)) } if err = d.Set("s2s_enabled", providerTypeItem.S2sEnabled); err != nil { - return diag.FromErr(fmt.Errorf("Error setting s2s_enabled: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting s2s_enabled: %s", err)) } if err = d.Set("instance_limit", flex.IntValue(providerTypeItem.InstanceLimit)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_limit: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_limit: %s", err)) } if err = d.Set("mode", providerTypeItem.Mode); err != nil { - return diag.FromErr(fmt.Errorf("Error setting mode: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting mode: %s", err)) } if err = d.Set("data_type", providerTypeItem.DataType); err != nil { - return diag.FromErr(fmt.Errorf("Error setting data_type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting data_type: %s", err)) } if err = d.Set("icon", providerTypeItem.Icon); err != nil { - return diag.FromErr(fmt.Errorf("Error setting icon: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting icon: %s", err)) } label := []map[string]interface{}{} @@ -176,7 +175,7 @@ func dataSourceIbmSccProviderTypeRead(context context.Context, d *schema.Resourc label = append(label, modelMap) } if err = d.Set("label", label); err != nil { - return diag.FromErr(fmt.Errorf("Error setting label %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting label %s", err)) } if providerTypeItem.Attributes != nil { @@ -186,19 +185,19 @@ func dataSourceIbmSccProviderTypeRead(context context.Context, d *schema.Resourc } if err = d.Set("attributes", flex.Flatten(convertedMap)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attributes: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attributes: %s", err)) } if err != nil { - return diag.FromErr(fmt.Errorf("Error setting attributes %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attributes %s", err)) } } if err = d.Set("created_at", flex.DateTimeToString(providerTypeItem.CreatedAt)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_at: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_at: %s", err)) } if err = d.Set("updated_at", flex.DateTimeToString(providerTypeItem.UpdatedAt)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_at: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_at: %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_provider_type_collection.go b/ibm/service/scc/data_source_ibm_scc_provider_type_collection.go index 35c21de13d..a87be24ee3 100644 --- a/ibm/service/scc/data_source_ibm_scc_provider_type_collection.go +++ b/ibm/service/scc/data_source_ibm_scc_provider_type_collection.go @@ -6,7 +6,6 @@ package scc import ( "context" "encoding/json" - "fmt" "log" "time" @@ -130,7 +129,7 @@ func dataSourceIbmSccProviderTypeCollectionRead(context context.Context, d *sche providerTypesCollection, response, err := securityAndComplianceCenterApIsClient.ListProviderTypesWithContext(context, listProviderTypesOptions) if err != nil { log.Printf("[DEBUG] ListProviderTypesWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ListProviderTypesWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("ListProviderTypesWithContext failed %s\n%s", err, response)) } d.SetId(dataSourceIbmSccProviderTypeCollectionID(d)) @@ -146,7 +145,7 @@ func dataSourceIbmSccProviderTypeCollectionRead(context context.Context, d *sche } } if err = d.Set("provider_types", providerTypes); err != nil { - return diag.FromErr(fmt.Errorf("Error setting provider_types %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting provider_types %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_provider_type_instance.go b/ibm/service/scc/data_source_ibm_scc_provider_type_instance.go index ce95151b29..ea19afc83b 100644 --- a/ibm/service/scc/data_source_ibm_scc_provider_type_instance.go +++ b/ibm/service/scc/data_source_ibm_scc_provider_type_instance.go @@ -79,21 +79,21 @@ func dataSourceIbmSccProviderTypeInstanceRead(context context.Context, d *schema providerTypeInstanceItem, response, err := securityAndComplianceCenterApIsClient.GetProviderTypeInstanceWithContext(context, getProviderTypeInstanceOptions) if err != nil { log.Printf("[DEBUG] GetProviderTypeInstanceWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetProviderTypeInstanceWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetProviderTypeInstanceWithContext failed %s\n%s", err, response)) } d.SetId(fmt.Sprintf("%s/%s", *getProviderTypeInstanceOptions.ProviderTypeID, *getProviderTypeInstanceOptions.ProviderTypeInstanceID)) if err = d.Set("provider_type_instance_item_id", providerTypeInstanceItem.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting provider_type_instance_item_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting provider_type_instance_item_id: %s", err)) } if err = d.Set("type", providerTypeInstanceItem.Type); err != nil { - return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting type: %s", err)) } if err = d.Set("name", providerTypeInstanceItem.Name); err != nil { - return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting name: %s", err)) } attributes := map[string]interface{}{} @@ -101,15 +101,15 @@ func dataSourceIbmSccProviderTypeInstanceRead(context context.Context, d *schema attributes = providerTypeInstanceItem.Attributes } if err = d.Set("attributes", attributes); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attributes %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attributes %s", err)) } if err = d.Set("created_at", flex.DateTimeToString(providerTypeInstanceItem.CreatedAt)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_at: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_at: %s", err)) } if err = d.Set("updated_at", flex.DateTimeToString(providerTypeInstanceItem.UpdatedAt)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_at: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_at: %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_provider_types.go b/ibm/service/scc/data_source_ibm_scc_provider_types.go index 7605931886..291200c5fc 100644 --- a/ibm/service/scc/data_source_ibm_scc_provider_types.go +++ b/ibm/service/scc/data_source_ibm_scc_provider_types.go @@ -124,7 +124,7 @@ func dataSourceIbmSccProviderTypesRead(context context.Context, d *schema.Resour providerTypeItems, response, err := securityAndComplianceCenterApIsClient.ListProviderTypesWithContext(context, listProviderTypesByIdOptions) if err != nil { log.Printf("[DEBUG] GetProviderTypeByIDWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetProviderTypeByIDWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetProviderTypeByIDWithContext failed %s\n%s", err, response)) } d.SetId(fmt.Sprintf("%s/provider_types", d.Get("instance_id").(string))) @@ -133,12 +133,12 @@ func dataSourceIbmSccProviderTypesRead(context context.Context, d *schema.Resour for _, providerType := range providerTypeItems.ProviderTypes { modelMap, err := dataSourceIbmSccProviderToMap(&providerType) if err != nil { - return diag.FromErr(fmt.Errorf("Error setting provider_type: %v\n%s", providerType, err)) + return diag.FromErr(flex.FmtErrorf("Error setting provider_type: %v\n%s", providerType, err)) } providerTypes = append(providerTypes, modelMap) } if err = d.Set("provider_types", providerTypes); err != nil { - return diag.FromErr(fmt.Errorf("Error setting provider_types: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting provider_types: %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_report.go b/ibm/service/scc/data_source_ibm_scc_report.go index e3e8f366cc..b5cbd3645d 100644 --- a/ibm/service/scc/data_source_ibm_scc_report.go +++ b/ibm/service/scc/data_source_ibm_scc_report.go @@ -5,13 +5,13 @@ package scc import ( "context" - "fmt" "log" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" ) @@ -193,37 +193,37 @@ func dataSourceIbmSccReportRead(context context.Context, d *schema.ResourceData, report, response, err := resultsClient.GetReportWithContext(context, getReportOptions) if err != nil { log.Printf("[DEBUG] GetReportWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetReportWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetReportWithContext failed %s\n%s", err, response)) } d.SetId(*report.ID) if err = d.Set("id", report.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting id: %s", err)) } if err = d.Set("group_id", report.GroupID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting group_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting group_id: %s", err)) } if err = d.Set("created_on", report.CreatedOn); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } if err = d.Set("scan_time", report.ScanTime); err != nil { - return diag.FromErr(fmt.Errorf("Error setting scan_time: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting scan_time: %s", err)) } if err = d.Set("type", report.Type); err != nil { - return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting type: %s", err)) } if err = d.Set("cos_object", report.CosObject); err != nil { - return diag.FromErr(fmt.Errorf("Error setting cos_object: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting cos_object: %s", err)) } if err = d.Set("instance_id", report.InstanceID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } account := []map[string]interface{}{} @@ -235,7 +235,7 @@ func dataSourceIbmSccReportRead(context context.Context, d *schema.ResourceData, account = append(account, modelMap) } if err = d.Set("account", account); err != nil { - return diag.FromErr(fmt.Errorf("Error setting account %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting account %s", err)) } profile := []map[string]interface{}{} @@ -247,7 +247,7 @@ func dataSourceIbmSccReportRead(context context.Context, d *schema.ResourceData, profile = append(profile, modelMap) } if err = d.Set("profile", profile); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile %s", err)) } attachment := []map[string]interface{}{} @@ -259,7 +259,7 @@ func dataSourceIbmSccReportRead(context context.Context, d *schema.ResourceData, attachment = append(attachment, modelMap) } if err = d.Set("attachment", attachment); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attachment %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attachment %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_report_controls.go b/ibm/service/scc/data_source_ibm_scc_report_controls.go index 798707827a..178c02f738 100644 --- a/ibm/service/scc/data_source_ibm_scc_report_controls.go +++ b/ibm/service/scc/data_source_ibm_scc_report_controls.go @@ -5,7 +5,6 @@ package scc import ( "context" - "fmt" "log" "time" @@ -324,33 +323,33 @@ func dataSourceIbmSccReportControlsRead(context context.Context, d *schema.Resou reportControls, response, err := resultsClient.GetReportControlsWithContext(context, getReportControlsOptions) if err != nil { log.Printf("[DEBUG] GetReportControlsWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetReportControlsWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetReportControlsWithContext failed %s\n%s", err, response)) } d.SetId(dataSourceIbmSccReportControlsID(d)) if err = d.Set("total_count", flex.IntValue(reportControls.TotalCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting total_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting total_count: %s", err)) } if err = d.Set("compliant_count", flex.IntValue(reportControls.CompliantCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting compliant_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting compliant_count: %s", err)) } if err = d.Set("not_compliant_count", flex.IntValue(reportControls.NotCompliantCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting not_compliant_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting not_compliant_count: %s", err)) } if err = d.Set("unable_to_perform_count", flex.IntValue(reportControls.UnableToPerformCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting unable_to_perform_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting unable_to_perform_count: %s", err)) } if err = d.Set("user_evaluation_required_count", flex.IntValue(reportControls.UserEvaluationRequiredCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting user_evaluation_required_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting user_evaluation_required_count: %s", err)) } if err = d.Set("home_account_id", reportControls.HomeAccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting home_account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting home_account_id: %s", err)) } controls := []map[string]interface{}{} @@ -364,7 +363,7 @@ func dataSourceIbmSccReportControlsRead(context context.Context, d *schema.Resou } } if err = d.Set("controls", controls); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_report_evaluations.go b/ibm/service/scc/data_source_ibm_scc_report_evaluations.go index 1b2b34c304..7f9bcc39dc 100644 --- a/ibm/service/scc/data_source_ibm_scc_report_evaluations.go +++ b/ibm/service/scc/data_source_ibm_scc_report_evaluations.go @@ -295,7 +295,7 @@ func dataSourceIbmSccReportEvaluationsRead(context context.Context, d *schema.Re allItems, err := pager.GetAll() if err != nil { log.Printf("[DEBUG] ReportEvaluationsPager.GetAll() failed %s", err) - return diag.FromErr(fmt.Errorf("ReportEvaluationsPager.GetAll() failed %s", err)) + return diag.FromErr(flex.FmtErrorf("ReportEvaluationsPager.GetAll() failed %s", err)) } d.SetId(dataSourceIbmSccReportEvaluationsID(d)) @@ -310,7 +310,7 @@ func dataSourceIbmSccReportEvaluationsRead(context context.Context, d *schema.Re } if err = d.Set("evaluations", mapSlice); err != nil { - return diag.FromErr(fmt.Errorf("Error setting evaluations %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting evaluations %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_report_resources.go b/ibm/service/scc/data_source_ibm_scc_report_resources.go index 5fe353e6d6..98df3436a1 100644 --- a/ibm/service/scc/data_source_ibm_scc_report_resources.go +++ b/ibm/service/scc/data_source_ibm_scc_report_resources.go @@ -5,7 +5,6 @@ package scc import ( "context" - "fmt" "log" "time" @@ -206,7 +205,7 @@ func dataSourceIbmSccReportResourcesRead(context context.Context, d *schema.Reso allItems, err := pager.GetAll() if err != nil { log.Printf("[DEBUG] ReportResourcesPager.GetAll() failed %s", err) - return diag.FromErr(fmt.Errorf("ReportResourcesPager.GetAll() failed %s", err)) + return diag.FromErr(flex.FmtErrorf("ReportResourcesPager.GetAll() failed %s", err)) } d.SetId(dataSourceIbmSccReportResourcesID(d)) @@ -221,7 +220,7 @@ func dataSourceIbmSccReportResourcesRead(context context.Context, d *schema.Reso } if err = d.Set("resources", mapSlice); err != nil { - return diag.FromErr(fmt.Errorf("Error setting resources %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting resources %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_report_rule.go b/ibm/service/scc/data_source_ibm_scc_report_rule.go index b920a20c56..b5f9924902 100644 --- a/ibm/service/scc/data_source_ibm_scc_report_rule.go +++ b/ibm/service/scc/data_source_ibm_scc_report_rule.go @@ -5,13 +5,13 @@ package scc import ( "context" - "fmt" "log" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" ) @@ -102,45 +102,45 @@ func dataSourceIbmSccReportRuleRead(context context.Context, d *schema.ResourceD ruleInfo, response, err := resultsClient.GetReportRuleWithContext(context, getReportRuleOptions) if err != nil { log.Printf("[DEBUG] GetReportRuleWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetReportRuleWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetReportRuleWithContext failed %s\n%s", err, response)) } d.SetId(*ruleInfo.ID) if err = d.Set("id", ruleInfo.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting id: %s", err)) } if err = d.Set("type", ruleInfo.Type); err != nil { - return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting type: %s", err)) } if err = d.Set("description", ruleInfo.Description); err != nil { - return diag.FromErr(fmt.Errorf("Error setting description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting description: %s", err)) } if err = d.Set("version", ruleInfo.Version); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting version: %s", err)) } if err = d.Set("account_id", ruleInfo.AccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting account_id: %s", err)) } if err = d.Set("created_on", ruleInfo.CreatedOn); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } if err = d.Set("created_by", ruleInfo.CreatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_by: %s", err)) } if err = d.Set("updated_on", ruleInfo.UpdatedOn); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_on: %s", err)) } if err = d.Set("updated_by", ruleInfo.UpdatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_by: %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_report_summary.go b/ibm/service/scc/data_source_ibm_scc_report_summary.go index ebac6cd966..bd4f22d9cf 100644 --- a/ibm/service/scc/data_source_ibm_scc_report_summary.go +++ b/ibm/service/scc/data_source_ibm_scc_report_summary.go @@ -5,7 +5,6 @@ package scc import ( "context" - "fmt" "log" "time" @@ -307,13 +306,13 @@ func dataSourceIbmSccReportSummaryRead(context context.Context, d *schema.Resour reportSummary, response, err := resultsClient.GetReportSummaryWithContext(context, getReportSummaryOptions) if err != nil { log.Printf("[DEBUG] GetReportSummaryWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetReportSummaryWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetReportSummaryWithContext failed %s\n%s", err, response)) } d.SetId(dataSourceIbmSccReportSummaryID(d)) if err = d.Set("isntance_id", reportSummary.IsntanceID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting isntance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting isntance_id: %s", err)) } account := []map[string]interface{}{} @@ -325,7 +324,7 @@ func dataSourceIbmSccReportSummaryRead(context context.Context, d *schema.Resour account = append(account, modelMap) } if err = d.Set("account", account); err != nil { - return diag.FromErr(fmt.Errorf("Error setting account %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting account %s", err)) } score := []map[string]interface{}{} @@ -337,7 +336,7 @@ func dataSourceIbmSccReportSummaryRead(context context.Context, d *schema.Resour score = append(score, modelMap) } if err = d.Set("score", score); err != nil { - return diag.FromErr(fmt.Errorf("Error setting score %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting score %s", err)) } controls := []map[string]interface{}{} @@ -349,7 +348,7 @@ func dataSourceIbmSccReportSummaryRead(context context.Context, d *schema.Resour controls = append(controls, modelMap) } if err = d.Set("controls", controls); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls %s", err)) } evaluations := []map[string]interface{}{} @@ -361,7 +360,7 @@ func dataSourceIbmSccReportSummaryRead(context context.Context, d *schema.Resour evaluations = append(evaluations, modelMap) } if err = d.Set("evaluations", evaluations); err != nil { - return diag.FromErr(fmt.Errorf("Error setting evaluations %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting evaluations %s", err)) } resources := []map[string]interface{}{} @@ -373,7 +372,7 @@ func dataSourceIbmSccReportSummaryRead(context context.Context, d *schema.Resour resources = append(resources, modelMap) } if err = d.Set("resources", resources); err != nil { - return diag.FromErr(fmt.Errorf("Error setting resources %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting resources %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_report_tags.go b/ibm/service/scc/data_source_ibm_scc_report_tags.go index 270dc45ff2..32b3427a56 100644 --- a/ibm/service/scc/data_source_ibm_scc_report_tags.go +++ b/ibm/service/scc/data_source_ibm_scc_report_tags.go @@ -5,7 +5,6 @@ package scc import ( "context" - "fmt" "log" "time" @@ -13,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" ) @@ -77,7 +77,7 @@ func dataSourceIbmSccReportTagsRead(context context.Context, d *schema.ResourceD reportTags, response, err := resultsClient.GetReportTagsWithContext(context, getReportTagsOptions) if err != nil { log.Printf("[DEBUG] GetReportTagsWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetReportTagsWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetReportTagsWithContext failed %s\n%s", err, response)) } d.SetId(dataSourceIbmSccReportTagsID(d)) @@ -91,7 +91,7 @@ func dataSourceIbmSccReportTagsRead(context context.Context, d *schema.ResourceD tags = append(tags, modelMap) } if err = d.Set("tags", tags); err != nil { - return diag.FromErr(fmt.Errorf("Error setting tags %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting tags %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_report_violation_drift.go b/ibm/service/scc/data_source_ibm_scc_report_violation_drift.go index 8a4487f084..da5106debf 100644 --- a/ibm/service/scc/data_source_ibm_scc_report_violation_drift.go +++ b/ibm/service/scc/data_source_ibm_scc_report_violation_drift.go @@ -5,7 +5,6 @@ package scc import ( "context" - "fmt" "log" "time" @@ -122,13 +121,13 @@ func dataSourceIbmSccReportViolationDriftRead(context context.Context, d *schema reportViolationsDrift, response, err := resultsClient.GetReportViolationsDriftWithContext(context, getReportViolationsDriftOptions) if err != nil { log.Printf("[DEBUG] GetReportViolationsDriftWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetReportViolationsDriftWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetReportViolationsDriftWithContext failed %s\n%s", err, response)) } d.SetId(dataSourceIbmSccReportViolationDriftID(d)) if err = d.Set("home_account_id", reportViolationsDrift.HomeAccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting home_account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting home_account_id: %s", err)) } dataPoints := []map[string]interface{}{} @@ -142,7 +141,7 @@ func dataSourceIbmSccReportViolationDriftRead(context context.Context, d *schema } } if err = d.Set("data_points", dataPoints); err != nil { - return diag.FromErr(fmt.Errorf("Error setting data_points %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting data_points %s", err)) } return nil diff --git a/ibm/service/scc/data_source_ibm_scc_rule.go b/ibm/service/scc/data_source_ibm_scc_rule.go index a41bd61f5d..85c89bf093 100644 --- a/ibm/service/scc/data_source_ibm_scc_rule.go +++ b/ibm/service/scc/data_source_ibm_scc_rule.go @@ -118,47 +118,7 @@ func DataSourceIbmSccRule() *schema.Resource { Computed: true, Description: "The rule target.", Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "service_name": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The target service name.", - }, - "service_display_name": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The display name of the target service.", - }, - "resource_kind": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The target resource kind.", - }, - "additional_target_attributes": &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Description: "The list of targets supported properties.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The additional target attribute name.", - }, - "operator": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The operator.", - }, - "value": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The value.", - }, - }, - }, - }, - }, + Schema: getTargetSchema(), }, }, "required_config": &schema.Schema{ @@ -166,202 +126,7 @@ func DataSourceIbmSccRule() *schema.Resource { Computed: true, Description: "The required configurations.", Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The required config description.", - }, - "and": &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Description: "The `AND` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The required config description.", - }, - "or": &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Description: "The `OR` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The required config description.", - }, - "property": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The property.", - }, - "operator": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The operator.", - }, - "value": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "and": &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Description: "The `AND` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The required config description.", - }, - "property": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The property.", - }, - "operator": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The operator.", - }, - "value": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "property": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The property.", - }, - "operator": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The operator.", - }, - "value": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "or": &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Description: "The `OR` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The required config description.", - }, - "or": &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Description: "The `OR` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The required config description.", - }, - "property": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The property.", - }, - "operator": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The operator.", - }, - "value": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "and": &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Description: "The `AND` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The required config description.", - }, - "property": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The property.", - }, - "operator": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The operator.", - }, - "value": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "property": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The property.", - }, - "operator": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The operator.", - }, - "value": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "property": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The property.", - }, - "operator": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "The operator.", - }, - "value": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - Description: "Schema for any JSON type.", - }, - }, + Schema: getRequiredConfigSchema(0), }, }, "labels": &schema.Schema{ @@ -390,45 +155,45 @@ func dataSourceIbmSccRuleRead(context context.Context, d *schema.ResourceData, m rule, response, err := configManagerClient.GetRuleWithContext(context, getRuleOptions) if err != nil { log.Printf("[DEBUG] GetRuleWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetRuleWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetRuleWithContext failed %s\n%s", err, response)) } d.SetId(fmt.Sprintf("%s", *getRuleOptions.RuleID)) if err = d.Set("created_on", flex.DateTimeToString(rule.CreatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } if err = d.Set("created_by", rule.CreatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_by: %s", err)) } if err = d.Set("updated_on", flex.DateTimeToString(rule.UpdatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_on: %s", err)) } if err = d.Set("updated_by", rule.UpdatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_by: %s", err)) } if err = d.Set("id", rule.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting id: %s", err)) } if err = d.Set("account_id", rule.AccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting account_id: %s", err)) } if err = d.Set("description", rule.Description); err != nil { - return diag.FromErr(fmt.Errorf("Error setting description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting description: %s", err)) } if err = d.Set("type", rule.Type); err != nil { - return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting type: %s", err)) } if err = d.Set("version", rule.Version); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting version: %s", err)) } importVar := []map[string]interface{}{} @@ -440,12 +205,12 @@ func dataSourceIbmSccRuleRead(context context.Context, d *schema.ResourceData, m importVar = append(importVar, modelMap) } if err = d.Set("import", importVar); err != nil { - return diag.FromErr(fmt.Errorf("Error setting import %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting import %s", err)) } target := []map[string]interface{}{} if rule.Target != nil { - modelMap, err := dataSourceIbmSccRuleTargetToMap(rule.Target) + modelMap, err := targetToModelMap(rule.Target) if err != nil { return diag.FromErr(err) } @@ -453,23 +218,23 @@ func dataSourceIbmSccRuleRead(context context.Context, d *schema.ResourceData, m } if err = d.Set("target", target); err != nil { - return diag.FromErr(fmt.Errorf("Error setting target %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting target %s", err)) } if err = d.Set("labels", rule.Labels); err != nil { - return diag.FromErr(fmt.Errorf("Error setting labels: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting labels: %s", err)) } requiredConfig := []map[string]interface{}{} if rule.RequiredConfig != nil { - modelMap, err := dataSourceIbmSccRuleRequiredConfigToMap(rule.RequiredConfig) + modelMap, err := requiredConfigToModelMap(rule.RequiredConfig) if err != nil { return diag.FromErr(err) } requiredConfig = append(requiredConfig, modelMap) } if err = d.Set("required_config", requiredConfig); err != nil { - return diag.FromErr(fmt.Errorf("Error setting required_config %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting required_config %s", err)) } return nil @@ -507,253 +272,3 @@ func dataSourceIbmSccRuleParameterToMap(model *securityandcompliancecenterapiv3. } return modelMap, nil } - -func dataSourceIbmSccRuleTargetToMap(model *securityandcompliancecenterapiv3.Target) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - modelMap["service_name"] = model.ServiceName - if model.ServiceDisplayName != nil { - modelMap["service_display_name"] = model.ServiceDisplayName - } - modelMap["resource_kind"] = model.ResourceKind - if model.AdditionalTargetAttributes != nil { - additionalTargetAttributes := []map[string]interface{}{} - for _, additionalTargetAttributesItem := range model.AdditionalTargetAttributes { - additionalTargetAttributesItemMap, err := dataSourceIbmSccRuleAdditionalTargetAttributeToMap(&additionalTargetAttributesItem) - if err != nil { - return modelMap, err - } - additionalTargetAttributes = append(additionalTargetAttributes, additionalTargetAttributesItemMap) - } - modelMap["additional_target_attributes"] = additionalTargetAttributes - } - return modelMap, nil -} - -func dataSourceIbmSccRuleAdditionalTargetAttributeToMap(model *securityandcompliancecenterapiv3.AdditionalTargetAttribute) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Name != nil { - modelMap["name"] = model.Name - } - if model.Operator != nil { - modelMap["operator"] = model.Operator - } - if model.Value != nil { - modelMap["value"] = model.Value - } - return modelMap, nil -} - -func dataSourceIbmSccRuleRequiredConfigToMap(model securityandcompliancecenterapiv3.RequiredConfigIntf) (map[string]interface{}, error) { - if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigAnd); ok { - return dataSourceIbmSccRuleRequiredConfigAndToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigAnd)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigOr); ok { - return dataSourceIbmSccRuleRequiredConfigOrToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigOr)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase); ok { - return dataSourceIbmSccRuleRequiredConfigRequiredConfigBaseToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfig); ok { - modelMap := make(map[string]interface{}) - model := model.(*securityandcompliancecenterapiv3.RequiredConfig) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.And != nil { - and := []map[string]interface{}{} - for _, andItem := range model.And { - andItemMap, err := dataSourceIbmSccRuleRequiredConfigItemsToMap(andItem) - if err != nil { - return modelMap, err - } - and = append(and, andItemMap) - } - modelMap["and"] = and - } - if model.Or != nil { - or := []map[string]interface{}{} - for _, orItem := range model.Or { - orItemMap, err := dataSourceIbmSccRuleRequiredConfigItemsToMap(orItem) - if err != nil { - return modelMap, err - } - or = append(or, orItemMap) - } - modelMap["or"] = or - } - if model.Property != nil { - modelMap["property"] = model.Property - } - if model.Operator != nil { - modelMap["operator"] = model.Operator - } - if model.Value != nil { - modelMap["value"] = model.Value - } - return modelMap, nil - } else { - return nil, fmt.Errorf("Unrecognized securityandcompliancecenterapiv3.RequiredConfigIntf subtype encountered") - } -} - -func dataSourceIbmSccRuleRequiredConfigItemsToMap(model securityandcompliancecenterapiv3.RequiredConfigItemsIntf) (map[string]interface{}, error) { - if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigOr); ok { - return dataSourceIbmSccRuleRequiredConfigItemsRequiredConfigOrToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigOr)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigAnd); ok { - return dataSourceIbmSccRuleRequiredConfigItemsRequiredConfigAndToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigAnd)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigBase); ok { - return dataSourceIbmSccRuleRequiredConfigItemsRequiredConfigBaseToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigBase)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigItems); ok { - modelMap := make(map[string]interface{}) - model := model.(*securityandcompliancecenterapiv3.RequiredConfigItems) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.Or != nil { - or := []map[string]interface{}{} - for _, orItem := range model.Or { - orItemMap, err := dataSourceIbmSccRuleRequiredConfigItemsToMap(orItem) - if err != nil { - return modelMap, err - } - or = append(or, orItemMap) - } - modelMap["or"] = or - } - if model.And != nil { - and := []map[string]interface{}{} - for _, andItem := range model.And { - andItemMap, err := dataSourceIbmSccRuleRequiredConfigItemsToMap(andItem) - if err != nil { - return modelMap, err - } - and = append(and, andItemMap) - } - modelMap["and"] = and - } - if model.Property != nil { - modelMap["property"] = model.Property - } - if model.Operator != nil { - modelMap["operator"] = model.Operator - } - if model.Value != nil { - modelMap["value"] = model.Value - } - return modelMap, nil - } else { - return nil, fmt.Errorf("Unrecognized securityandcompliancecenterapiv3.RequiredConfigItemsIntf subtype encountered") - } -} - -func dataSourceIbmSccRuleRequiredConfigBaseToMap(model *securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - modelMap["property"] = model.Property - modelMap["operator"] = model.Operator - if model.Value != nil { - modelMap["value"] = model.Value - } - return modelMap, nil -} - -func dataSourceIbmSccRuleRequiredConfigItemsRequiredConfigOrToMap(model *securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigOr) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.Or != nil { - or := []map[string]interface{}{} - for _, orItem := range model.Or { - orItemMap, err := dataSourceIbmSccRuleRequiredConfigItemsToMap(orItem.(*securityandcompliancecenterapiv3.RequiredConfigItems)) - if err != nil { - return modelMap, err - } - or = append(or, orItemMap) - } - modelMap["or"] = or - } - return modelMap, nil -} - -func dataSourceIbmSccRuleRequiredConfigItemsRequiredConfigAndToMap(model *securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigAnd) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.And != nil { - and := []map[string]interface{}{} - for _, andItem := range model.And { - andItemMap, err := dataSourceIbmSccRuleRequiredConfigItemsToMap(andItem.(*securityandcompliancecenterapiv3.RequiredConfigItems)) - if err != nil { - return modelMap, err - } - and = append(and, andItemMap) - } - modelMap["and"] = and - } - return modelMap, nil -} - -func dataSourceIbmSccRuleRequiredConfigItemsRequiredConfigBaseToMap(model *securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigBase) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - modelMap["property"] = model.Property - modelMap["operator"] = model.Operator - if model.Value != nil { - modelMap["value"] = model.Value - } - return modelMap, nil -} - -func dataSourceIbmSccRuleRequiredConfigAndToMap(model *securityandcompliancecenterapiv3.RequiredConfigRequiredConfigAnd) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.And != nil { - and := []map[string]interface{}{} - for _, andItem := range model.And { - andItemMap, err := dataSourceIbmSccRuleRequiredConfigItemsToMap(andItem) - if err != nil { - return modelMap, err - } - and = append(and, andItemMap) - } - modelMap["and"] = and - } - return modelMap, nil -} - -func dataSourceIbmSccRuleRequiredConfigOrToMap(model *securityandcompliancecenterapiv3.RequiredConfigRequiredConfigOr) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.Or != nil { - or := []map[string]interface{}{} - for _, orItem := range model.Or { - orItemMap, err := dataSourceIbmSccRuleRequiredConfigItemsToMap(orItem) - if err != nil { - return modelMap, err - } - or = append(or, orItemMap) - } - modelMap["or"] = or - } - return modelMap, nil -} - -func dataSourceIbmSccRuleRequiredConfigRequiredConfigBaseToMap(model *securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - modelMap["property"] = model.Property - modelMap["operator"] = model.Operator - if model.Value != nil { - modelMap["value"] = model.Value - } - return modelMap, nil -} diff --git a/ibm/service/scc/data_source_ibm_scc_rule_test.go b/ibm/service/scc/data_source_ibm_scc_rule_test.go index a7218bdaf8..e79fe4ccac 100644 --- a/ibm/service/scc/data_source_ibm_scc_rule_test.go +++ b/ibm/service/scc/data_source_ibm_scc_rule_test.go @@ -75,6 +75,100 @@ func TestAccIbmSccRuleDataSourceAllArgs(t *testing.T) { }) } +func TestAccIbmSccRuleDataSourcePreexistingOrIps(t *testing.T) { + // rule with a required_config using "or" and "ips_not_equal" + ruleID := "rule-9407e5a8-ec51-4228-a01a-0f32364224a6" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckScc(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIbmSccRuleDataSourcePreExistingRuleID(acc.SccInstanceID, ruleID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "rule_id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "created_on"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "created_by"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "updated_on"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "updated_by"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "account_id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "description"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "type"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "version"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "import.#"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "target.#"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "required_config.#"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "labels.#"), + resource.TestCheckResourceAttr("data.ibm_scc_rule.scc_rule_instance", "required_config.0.or.1.value", "[0.0.0.0/0]"), + ), + }, + }, + }) +} +func TestAccIbmSccRuleDataSourcePreexistingAndNumerical(t *testing.T) { + // rule with a required_config using "and" and numerical value + ruleID := "rule-0e5151b1-9caf-433c-b4e5-be3d505e458e" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckScc(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIbmSccRuleDataSourcePreExistingRuleID(acc.SccInstanceID, ruleID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "rule_id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "created_on"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "created_by"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "updated_on"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "updated_by"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "account_id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "description"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "type"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "version"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "import.#"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "target.#"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "required_config.#"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "labels.#"), + resource.TestCheckResourceAttr("data.ibm_scc_rule.scc_rule_instance", "required_config.0.and.1.value", "0"), + ), + }, + }, + }) +} +func TestAccIbmSccRuleDataSourcePreexistingSubRuleAny(t *testing.T) { + // rule with a required_config using a subRule + ruleID := "rule-5910ed25-7ad7-42d0-8e42-905df0123346" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckScc(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIbmSccRuleDataSourcePreExistingRuleID(acc.SccInstanceID, ruleID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "rule_id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "created_on"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "created_by"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "updated_on"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "updated_by"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "account_id"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "description"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "type"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "version"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "import.#"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "target.#"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "required_config.#"), + resource.TestCheckResourceAttrSet("data.ibm_scc_rule.scc_rule_instance", "labels.#"), + resource.TestCheckResourceAttr("data.ibm_scc_rule.scc_rule_instance", "required_config.0.and.0.any.0.required_config.0.value", "${this-logdnaat}.region_id"), + ), + }, + }, + }) +} + func testAccCheckIbmSccRuleDataSourceConfigBasic(instanceID string, ruleDescription string) string { return fmt.Sprintf(` resource "ibm_scc_rule" "scc_rule_instance" { @@ -132,3 +226,12 @@ func testAccCheckIbmSccRuleDataSourceConfig(instanceID string, ruleDescription s } `, instanceID, ruleDescription, ruleVersion) } + +func testAccCheckIbmSccRuleDataSourcePreExistingRuleID(instanceID string, ruleID string) string { + return fmt.Sprintf(` + data "ibm_scc_rule" "scc_rule_instance" { + instance_id = "%s" + rule_id = "%s" + } + `, instanceID, ruleID) +} diff --git a/ibm/service/scc/ibm_scc_utilities.go b/ibm/service/scc/ibm_scc_utilities.go index baacbede0e..23056ce459 100644 --- a/ibm/service/scc/ibm_scc_utilities.go +++ b/ibm/service/scc/ibm_scc_utilities.go @@ -4,13 +4,20 @@ package scc import ( + "fmt" "strings" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + + "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -const INSTANCE_ID = "instance_id" +const ( + INSTANCE_ID = "instance_id" + MAX_REQUIRED_CONFIG_DEPTH = 5 +) // AddSchemaData will add the Schemas 'instance_id' and 'region' to the resource func AddSchemaData(resource *schema.Resource) *schema.Resource { @@ -41,3 +48,459 @@ func setRegionData(d *schema.ResourceData, region string) error { } return nil } + +// getRequiredConfigSchema will return the schema for a scc rule required_config. This schema is recursive. +func getRequiredConfigSchema(currentDepth int) map[string]*schema.Schema { + baseMap := map[string]*schema.Schema{ + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The programmatic name of the IBM Cloud service that you want to target with the rule or template.", + }, + "property": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name of the additional attribute that you want to use to further qualify the target.Options differ depending on the service or resource that you are targeting with a rule or template. For more information, refer to the service documentation.", + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "", + Description: "The value that you want to apply to `value` field. Options differ depending on the rule or template that you configure. For more information, refer to the service documentation.", + }, + "operator": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The way in which the `name` field is compared to its value.There are three types of operators: string, numeric, and boolean.", + ValidateFunc: validate.InvokeValidator("ibm_scc_rule", "operator"), + }, + } + if currentDepth > MAX_REQUIRED_CONFIG_DEPTH { + return baseMap + } + + baseMap["and"] = &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "A list of property conditions where all items need to be satisfied", + Elem: &schema.Resource{ + Schema: getRequiredConfigSchema(currentDepth + 1), + }, + } + + baseMap["or"] = &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "A list of property conditions where any item needs to be satisfied", + Elem: &schema.Resource{ + Schema: getRequiredConfigSchema(currentDepth + 1), + }, + } + + baseMap["all"] = &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "A condition with the SubRule all logical operator.", + Elem: &schema.Resource{ + Schema: getSubRuleSchema(currentDepth + 1), + }, + } + + baseMap["all_if"] = &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "A condition with the SubRule all_ifexists logical operator.", + Elem: &schema.Resource{ + Schema: getSubRuleSchema(currentDepth + 1), + }, + } + + baseMap["any"] = &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "A condition with the SubRule any logical operator.", + Elem: &schema.Resource{ + Schema: getSubRuleSchema(currentDepth + 1), + }, + } + + baseMap["any_if"] = &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "A condition with the SubRule any_ifexists logical operator.", + Elem: &schema.Resource{ + Schema: getSubRuleSchema(currentDepth + 1), + }, + } + return baseMap +} + +// getTargetSchema returns a terraform Schema defining the attributes of a Target object +func getTargetSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "service_name": { + Type: schema.TypeString, + Required: true, + Description: "The target service name.", + }, + "service_display_name": { + Type: schema.TypeString, + Optional: true, + Description: "The display name of the target service.", + // Manual Intervention + DiffSuppressFunc: func(_, oldVal, newVal string, d *schema.ResourceData) bool { + if newVal == "" { + return true + } + if strings.ToLower(oldVal) == strings.ToLower(newVal) { + return true + } + return false + }, + // End Manual Intervention + }, + "reference_name": { + Type: schema.TypeString, + Optional: true, + Description: "The target reference name", + }, + "resource_kind": { + Type: schema.TypeString, + Required: true, + Description: "The target resource kind.", + }, + "additional_target_attributes": { + Type: schema.TypeList, + Optional: true, + Description: "The list of targets supported properties.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + Description: "The additional target attribute name.", + }, + "operator": { + Type: schema.TypeString, + Optional: true, + Description: "The operator.", + }, + "value": { + Type: schema.TypeString, + Optional: true, + Description: "The value.", + }, + }, + }, + }, + } +} + +// getSubRuleSchema returns a terraform Schema that define attributes of a subRule +func getSubRuleSchema(currentDepth int) map[string]*schema.Schema { + return map[string]*schema.Schema{ + "required_config": { + Description: "The requirements that must be met to determine the resource's level of compliance in accordance with the rule. Use logical operators (and/or) to define multiple property checks and conditions. To define requirements for a rule, list one or more property check objects in the and array. To add conditions to a property check, use or.", + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: getRequiredConfigSchema(currentDepth + 1), + }, + MaxItems: 1, + }, + "target": { + Description: "The requirements that must be met to determine the resource's level of compliance in accordance with the rule. Use logical operators (and/or) to define multiple property checks and conditions. To define requirements for a rule, list one or more property check objects in the and array. To add conditions to a property check, use or.", + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: getTargetSchema(), + }, + MaxItems: 1, + }, + } +} + +// requiredConfigItemsToListMap will dicipher the list of conditions and return a []map[string]interface{} to abide to the +// terraform type TypeList +func requiredConfigItemsToListMap(items securityandcompliancecenterapiv3.RequiredConfigItems) ([]map[string]interface{}, error) { + rcItems := []map[string]interface{}{} + for _, rcItem := range items { + rcMap, err := requiredConfigToModelMap(rcItem) + if err != nil { + return []map[string]interface{}{}, err + } + rcItems = append(rcItems, rcMap) + } + return rcItems, nil +} + +// requiredConfigSubRuleToMap will dicipher the sub rule brought in and return a []map[string]interface{} for the terraform +// state file +func requiredConfigSubRuleToMap(subRule *securityandcompliancecenterapiv3.RequiredConfigSubRule) ([]map[string]interface{}, error) { + srMap := make(map[string]interface{}) + subRuleTarget, err := targetToModelMap(subRule.Target) + if err != nil { + return []map[string]interface{}{}, err + } + srMap["target"] = []interface{}{subRuleTarget} + subRuleConfig, err := requiredConfigToModelMap(subRule.RequiredConfig) + if err != nil { + return []map[string]interface{}{}, err + } + srMap["required_config"] = []interface{}{subRuleConfig} + return []map[string]interface{}{srMap}, nil +} + +// ibmSccRuleRequiredConfigToMap will dicipher a scc rule required_config and return back to a map[string]interface{} +// for the terraform state file +func requiredConfigToModelMap(model securityandcompliancecenterapiv3.RequiredConfigIntf) (map[string]interface{}, error) { + if rc, ok := model.(*securityandcompliancecenterapiv3.RequiredConfig); ok { + modelMap := make(map[string]interface{}) + if rc.Description != nil { + modelMap["description"] = rc.Description + } + if rc.And != nil { + if rcItems, err := requiredConfigItemsToListMap(rc.And); err != nil { + return map[string]interface{}{}, err + } else { + modelMap["and"] = rcItems + } + } + if rc.Or != nil { + if rcItems, err := requiredConfigItemsToListMap(rc.Or); err != nil { + return map[string]interface{}{}, err + } else { + modelMap["or"] = rcItems + } + } + // sub rules + if rc.All != nil { + if subRule, err := requiredConfigSubRuleToMap(rc.All); err != nil { + return map[string]interface{}{}, err + } else { + modelMap["all"] = subRule + } + } + if rc.AllIf != nil { + if subRule, err := requiredConfigSubRuleToMap(rc.AllIf); err != nil { + return map[string]interface{}{}, err + } else { + modelMap["all_if"] = subRule + } + } + if rc.Any != nil { + if subRule, err := requiredConfigSubRuleToMap(rc.Any); err != nil { + return map[string]interface{}{}, err + } else { + modelMap["any"] = subRule + } + } + if rc.AnyIf != nil { + if subRule, err := requiredConfigSubRuleToMap(rc.AnyIf); err != nil { + return map[string]interface{}{}, err + } else { + modelMap["any_if"] = subRule + } + } + // base condition handling + if rc.Property != nil { + modelMap["property"] = rc.Property + } + if rc.Operator != nil { + modelMap["operator"] = rc.Operator + } + if rc.Value != nil { + // rc.Value can be implicitly cast as a []interface, it needs to be stringified + if valList, ok := rc.Value.([]interface{}); ok { + s := make([]string, len(valList)) + for i, v := range valList { + s[i] = fmt.Sprint(v) + } + modelMap["value"] = fmt.Sprintf("[%s]", strings.Join(s, ",")) + } else { + modelMap["value"] = rc.Value + } + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized securityandcompliancecenterapiv3.RequiredConfigIntf subtype encountered %#v", model) + } +} + +// listMapToSccSubRule is a helper function that converts a map into a SubRule +func listMapToSccSubRule(subRuleModel []interface{}) (*securityandcompliancecenterapiv3.RequiredConfigSubRule, error) { + subRule := securityandcompliancecenterapiv3.RequiredConfigSubRule{} + subMap := subRuleModel[0].(map[string]interface{}) + target, err := modelMapToTarget(subMap["target"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return &subRule, err + } + subRule.Target = target + rc, err := modelMapToRequiredConfig(subMap["required_config"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return &subRule, err + } + subRule.RequiredConfig = rc.(*securityandcompliancecenterapiv3.RequiredConfig) + return &subRule, nil +} + +// modelMapToRequiredConfig converts the map to a RequiredConfig +func modelMapToRequiredConfig(modelMap map[string]interface{}) (securityandcompliancecenterapiv3.RequiredConfigIntf, error) { + model := &securityandcompliancecenterapiv3.RequiredConfig{} + if modelMap["description"] != nil && modelMap["description"].(string) != "" { + model.Description = core.StringPtr(modelMap["description"].(string)) + } + if modelMap["or"] != nil { + or := []securityandcompliancecenterapiv3.RequiredConfigIntf{} + for _, orItem := range modelMap["or"].([]interface{}) { + orItemModel, err := modelMapToRequiredConfig(orItem.(map[string]interface{})) + if err != nil { + return model, err + } + or = append(or, orItemModel) + } + model.Or = or + } + if modelMap["and"] != nil { + and := []securityandcompliancecenterapiv3.RequiredConfigIntf{} + for _, andItem := range modelMap["and"].([]interface{}) { + andItemModel, err := modelMapToRequiredConfig(andItem.(map[string]interface{})) + if err != nil { + return model, err + } + and = append(and, andItemModel) + } + model.And = and + } + if anySM, ok := modelMap["any"].([]interface{}); ok && len(anySM) > 0 { + anySubRule, err := listMapToSccSubRule(anySM) + if err != nil { + return model, err + } + model.Any = anySubRule + } + if anyIfSM, ok := modelMap["any_if"].([]interface{}); ok && len(anyIfSM) > 0 { + anyIfSubRule, err := listMapToSccSubRule(anyIfSM) + if err != nil { + return model, err + } + model.AnyIf = anyIfSubRule + } + if allSM, ok := modelMap["all"].([]interface{}); ok && len(allSM) > 0 { + allSubRule, err := listMapToSccSubRule(allSM) + if err != nil { + return model, err + } + model.All = allSubRule + } + if allIfSM, ok := modelMap["all_if"].([]interface{}); ok && len(allIfSM) > 0 { + allIfSubRule, err := listMapToSccSubRule(allIfSM) + if err != nil { + return model, err + } + model.AllIf = allIfSubRule + } + if modelMap["property"] != nil && modelMap["property"].(string) != "" { + model.Property = core.StringPtr(modelMap["property"].(string)) + } + if modelMap["operator"] != nil && modelMap["operator"].(string) != "" { + model.Operator = core.StringPtr(modelMap["operator"].(string)) + } + if modelMap["value"] != nil && len(modelMap["value"].(string)) > 0 { + // model.Value = modelMap["value"].(string) + sLit := strings.Trim(modelMap["value"].(string), "[]") + sList := strings.Split(sLit, ",") + if len(sList) == 1 { + model.Value = modelMap["value"].(string) + } else { + model.Value = sList + } + } + + return model, nil +} + +// modelMapToTarget transforms a map and transforms into a Target object +func modelMapToTarget(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.Target, error) { + model := &securityandcompliancecenterapiv3.Target{} + model.ServiceName = core.StringPtr(modelMap["service_name"].(string)) + if modelMap["service_display_name"] != nil && modelMap["service_display_name"].(string) != "" { + model.ServiceDisplayName = core.StringPtr(modelMap["service_display_name"].(string)) + } + if modelMap["reference_name"] != nil && modelMap["reference_name"].(string) != "" { + model.ReferenceName = core.StringPtr(modelMap["reference_name"].(string)) + } + model.ResourceKind = core.StringPtr(modelMap["resource_kind"].(string)) + if modelMap["additional_target_attributes"] != nil { + additionalTargetAttributes := []securityandcompliancecenterapiv3.AdditionalTargetAttribute{} + for _, additionalTargetAttributesItem := range modelMap["additional_target_attributes"].([]interface{}) { + additionalTargetAttributesItemModel, err := ruleMapToAdditionalTargetAttribute(additionalTargetAttributesItem.(map[string]interface{})) + if err != nil { + return model, err + } + additionalTargetAttributes = append(additionalTargetAttributes, *additionalTargetAttributesItemModel) + } + model.AdditionalTargetAttributes = additionalTargetAttributes + } + return model, nil +} + +// ruleMapToAdditionalTargetAttribute will convert a given map to a AdditionalTargetAttribute object +func ruleMapToAdditionalTargetAttribute(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.AdditionalTargetAttribute, error) { + model := &securityandcompliancecenterapiv3.AdditionalTargetAttribute{} + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["operator"] != nil && modelMap["operator"].(string) != "" { + model.Operator = core.StringPtr(modelMap["operator"].(string)) + } + if modelMap["value"] != nil && modelMap["value"].(string) != "" { + model.Value = core.StringPtr(modelMap["value"].(string)) + } + return model, nil +} + +// targetToModelMap will convert a Target object to a map for the terraform state file. +func targetToModelMap(model *securityandcompliancecenterapiv3.Target) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + + modelMap["service_name"] = model.ServiceName + + modelMap["resource_kind"] = model.ResourceKind + + if model.ReferenceName != nil { + modelMap["reference_name"] = model.ReferenceName + } + + if model.ServiceDisplayName != nil { + modelMap["service_display_name"] = model.ServiceDisplayName + } + + if model.AdditionalTargetAttributes != nil { + additionalTargetAttributes := []map[string]interface{}{} + for _, additionalTargetAttributesItem := range model.AdditionalTargetAttributes { + additionalTargetAttributesItemMap, err := ruleAdditionalTargetAttributeToMap(&additionalTargetAttributesItem) + if err != nil { + return modelMap, err + } + additionalTargetAttributes = append(additionalTargetAttributes, additionalTargetAttributesItemMap) + } + modelMap["additional_target_attributes"] = additionalTargetAttributes + } + return modelMap, nil +} + +// converts a AdditionalTargetAttribute object into a map for the terraform state file. +func ruleAdditionalTargetAttributeToMap(model *securityandcompliancecenterapiv3.AdditionalTargetAttribute) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Name != nil { + modelMap["name"] = model.Name + } + if model.Operator != nil { + modelMap["operator"] = model.Operator + } + if model.Value != nil { + modelMap["value"] = model.Value + } + return modelMap, nil +} diff --git a/ibm/service/scc/resource_ibm_scc_control_library.go b/ibm/service/scc/resource_ibm_scc_control_library.go index e656c7d7de..1906b0f3a4 100644 --- a/ibm/service/scc/resource_ibm_scc_control_library.go +++ b/ibm/service/scc/resource_ibm_scc_control_library.go @@ -5,7 +5,6 @@ package scc import ( "context" - "fmt" "log" "math/big" "strconv" @@ -378,13 +377,13 @@ func resourceIbmSccControlLibraryCreate(context context.Context, d *schema.Resou convertedModel, err := resourceIbmSccControlLibraryMapToControlLibraryPrototype(bodyModelMap) if err != nil { log.Printf("[DEBUG] CreateCustomControlLibraryWithContext failed %s\n", err) - return diag.FromErr(fmt.Errorf("CreateCustomControlLibraryWithContext failed %s\n", err)) + return diag.FromErr(flex.FmtErrorf("CreateCustomControlLibraryWithContext failed %s\n", err)) } createCustomControlLibraryOptions = convertedModel controlLibrary, response, err := securityandcompliancecenterapiClient.CreateCustomControlLibraryWithContext(context, createCustomControlLibraryOptions) if err != nil { log.Printf("[DEBUG] CreateCustomControlLibraryWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("CreateCustomControlLibraryWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("CreateCustomControlLibraryWithContext failed %s\n%s", err, response)) } d.SetId(instance_id + "/" + *controlLibrary.ID) @@ -413,41 +412,41 @@ func resourceIbmSccControlLibraryRead(context context.Context, d *schema.Resourc return nil } log.Printf("[DEBUG] GetControlLibraryWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetControlLibraryWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetControlLibraryWithContext failed %s\n%s", err, response)) } if err = d.Set("instance_id", parts[0]); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } if err = d.Set("control_library_id", controlLibrary.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_library_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_library_id: %s", err)) } if err = d.Set("control_library_name", controlLibrary.ControlLibraryName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_library_name: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_library_name: %s", err)) } if err = d.Set("control_library_description", controlLibrary.ControlLibraryDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_library_description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_library_description: %s", err)) } if err = d.Set("control_library_type", controlLibrary.ControlLibraryType); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_library_type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_library_type: %s", err)) } if !core.IsNil(controlLibrary.VersionGroupLabel) { if err = d.Set("version_group_label", controlLibrary.VersionGroupLabel); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version_group_label: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting version_group_label: %s", err)) } } if !core.IsNil(controlLibrary.ControlLibraryVersion) { if err = d.Set("control_library_version", controlLibrary.ControlLibraryVersion); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_library_version: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_library_version: %s", err)) } } if !core.IsNil(controlLibrary.Latest) { if err = d.Set("latest", controlLibrary.Latest); err != nil { - return diag.FromErr(fmt.Errorf("Error setting latest: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting latest: %s", err)) } } if !core.IsNil(controlLibrary.ControlsCount) { if err = d.Set("controls_count", flex.IntValue(controlLibrary.ControlsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls_count: %s", err)) } } controls := []map[string]interface{}{} @@ -459,41 +458,41 @@ func resourceIbmSccControlLibraryRead(context context.Context, d *schema.Resourc controls = append(controls, controlsItemMap) } if err = d.Set("controls", controls); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls: %s", err)) } if !core.IsNil(controlLibrary.AccountID) { if err = d.Set("account_id", controlLibrary.AccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting account_id: %s", err)) } } if !core.IsNil(controlLibrary.CreatedOn) { if err = d.Set("created_on", flex.DateTimeToString(controlLibrary.CreatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } } if !core.IsNil(controlLibrary.CreatedBy) { if err = d.Set("created_by", controlLibrary.CreatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_by: %s", err)) } } if !core.IsNil(controlLibrary.UpdatedOn) { if err = d.Set("updated_on", flex.DateTimeToString(controlLibrary.UpdatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_on: %s", err)) } } if !core.IsNil(controlLibrary.UpdatedBy) { if err = d.Set("updated_by", controlLibrary.UpdatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_by: %s", err)) } } if !core.IsNil(controlLibrary.HierarchyEnabled) { if err = d.Set("hierarchy_enabled", controlLibrary.HierarchyEnabled); err != nil { - return diag.FromErr(fmt.Errorf("Error setting hierarchy_enabled: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting hierarchy_enabled: %s", err)) } } if !core.IsNil(controlLibrary.ControlParentsCount) { if err = d.Set("control_parents_count", flex.IntValue(controlLibrary.ControlParentsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_parents_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_parents_count: %s", err)) } } @@ -529,7 +528,7 @@ func resourceIbmSccControlLibraryUpdate(context context.Context, d *schema.Resou for _, controlsItem := range d.Get("controls").([]interface{}) { controlsItemModel, err := resourceIbmSccControlLibraryMapToControlsInControlLib(controlsItem.(map[string]interface{})) if err != nil { - return diag.FromErr(fmt.Errorf("ReplaceCustomControlLibraryWithContext failed %s\n", err)) + return diag.FromErr(flex.FmtErrorf("ReplaceCustomControlLibraryWithContext failed %s\n", err)) } replaceCustomControlLibraryOptions.Controls = append(replaceCustomControlLibraryOptions.Controls, *controlsItemModel) } @@ -554,7 +553,7 @@ func resourceIbmSccControlLibraryUpdate(context context.Context, d *schema.Resou for _, controlsItem := range d.Get("controls").([]interface{}) { controlsItemModel, err := resourceIbmSccControlLibraryMapToControlsInControlLib(controlsItem.(map[string]interface{})) if err != nil { - return diag.FromErr(fmt.Errorf("ReplaceCustomControlLibraryWithContext failed %s\n", err)) + return diag.FromErr(flex.FmtErrorf("ReplaceCustomControlLibraryWithContext failed %s\n", err)) } replaceCustomControlLibraryOptions.Controls = append(replaceCustomControlLibraryOptions.Controls, *controlsItemModel) } @@ -562,7 +561,7 @@ func resourceIbmSccControlLibraryUpdate(context context.Context, d *schema.Resou _, response, err := securityandcompliancecenterapiClient.ReplaceCustomControlLibraryWithContext(context, replaceCustomControlLibraryOptions) if err != nil { log.Printf("[DEBUG] ReplaceCustomControlLibraryWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ReplaceCustomControlLibraryWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("ReplaceCustomControlLibraryWithContext failed %s\n%s", err, response)) } } @@ -587,7 +586,7 @@ func resourceIbmSccControlLibraryDelete(context context.Context, d *schema.Resou _, response, err := securityandcompliancecenterapiClient.DeleteCustomControlLibraryWithContext(context, deleteCustomControlLibraryOptions) if err != nil { log.Printf("[DEBUG] DeleteCustomControlLibraryWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteCustomControlLibraryWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("DeleteCustomControlLibraryWithContext failed %s\n%s", err, response)) } d.SetId("") diff --git a/ibm/service/scc/resource_ibm_scc_control_library_test.go b/ibm/service/scc/resource_ibm_scc_control_library_test.go index 27f392c8f8..4b3d380fe7 100644 --- a/ibm/service/scc/resource_ibm_scc_control_library_test.go +++ b/ibm/service/scc/resource_ibm_scc_control_library_test.go @@ -14,6 +14,7 @@ import ( acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" ) @@ -217,7 +218,7 @@ func testAccCheckIbmSccControlLibraryExists(n string, obj securityandcompliancec return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", n) + return flex.FmtErrorf("Not found: %s", n) } securityandcompliancecenterapiClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).SecurityAndComplianceCenterV3() @@ -261,9 +262,9 @@ func testAccCheckIbmSccControlLibraryDestroy(s *terraform.State) error { _, response, err := securityandcompliancecenterapiClient.GetControlLibrary(getControlLibraryOptions) if err == nil { - return fmt.Errorf("scc_control_library still exists: %s", rs.Primary.ID) + return flex.FmtErrorf("scc_control_library still exists: %s", rs.Primary.ID) } else if response.StatusCode != 404 { - return fmt.Errorf("Error checking for scc_control_library (%s) has been destroyed: %s", rs.Primary.ID, err) + return flex.FmtErrorf("Error checking for scc_control_library (%s) has been destroyed: %s", rs.Primary.ID, err) } } diff --git a/ibm/service/scc/resource_ibm_scc_instance_settings.go b/ibm/service/scc/resource_ibm_scc_instance_settings.go index deecd0f438..f501c00919 100644 --- a/ibm/service/scc/resource_ibm_scc_instance_settings.go +++ b/ibm/service/scc/resource_ibm_scc_instance_settings.go @@ -3,13 +3,13 @@ package scc import ( "context" "errors" - "fmt" "log" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" @@ -147,7 +147,7 @@ func resourceIbmSccInstanceSettingsCreate(context context.Context, d *schema.Res _, response, err := adminClient.UpdateSettingsWithContext(context, updateSettingsOptions) if err != nil { log.Printf("[DEBUG] UpdateSettingsWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("UpdateSettingsWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("UpdateSettingsWithContext failed %s\n%s", err, response)) } d.SetId(instance_id) @@ -172,11 +172,11 @@ func resourceIbmSccInstanceSettingsRead(context context.Context, d *schema.Resou return nil } log.Printf("[DEBUG] GetSettingsWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetSettingsWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetSettingsWithContext failed %s\n%s", err, response)) } if err = d.Set("instance_id", instance_id); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } if !core.IsNil(settings.EventNotifications) { eventNotificationsMap, err := resourceIbmSccInstanceSettingsEventNotificationsToMap(settings.EventNotifications) @@ -184,7 +184,7 @@ func resourceIbmSccInstanceSettingsRead(context context.Context, d *schema.Resou return diag.FromErr(err) } if err = d.Set("event_notifications", []map[string]interface{}{eventNotificationsMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting event_notifications: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting event_notifications: %s", err)) } } if !core.IsNil(settings.ObjectStorage) { @@ -193,7 +193,7 @@ func resourceIbmSccInstanceSettingsRead(context context.Context, d *schema.Resou return diag.FromErr(err) } if err = d.Set("object_storage", []map[string]interface{}{objectStorageMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting object_storage: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting object_storage: %s", err)) } } @@ -237,7 +237,7 @@ func resourceIbmSccInstanceSettingsUpdate(context context.Context, d *schema.Res _, response, err := adminClient.UpdateSettingsWithContext(context, updateSettingsOptions) if err != nil { log.Printf("[DEBUG] UpdateSettingsWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("UpdateSettingsWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("UpdateSettingsWithContext failed %s\n%s", err, response)) } } diff --git a/ibm/service/scc/resource_ibm_scc_instance_settings_test.go b/ibm/service/scc/resource_ibm_scc_instance_settings_test.go index ba476bf939..c74b3947d8 100644 --- a/ibm/service/scc/resource_ibm_scc_instance_settings_test.go +++ b/ibm/service/scc/resource_ibm_scc_instance_settings_test.go @@ -12,6 +12,7 @@ import ( acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" ) @@ -92,7 +93,7 @@ func testAccCheckIbmSccInstanceSettingsExists(n string, obj securityandcomplianc return func(s *terraform.State) error { _, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", n) + return flex.FmtErrorf("Not found: %s", n) } adminClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).SecurityAndComplianceCenterV3() @@ -131,7 +132,7 @@ func testAccCheckIbmSccInstanceSettingsDestroy(s *terraform.State) error { // Deleting a instance_settings_resource doesn't delete the entity _, response, err := adminClient.GetSettings(getSettingsOptions) if response.StatusCode != 200 { - return fmt.Errorf("Error checking for scc_instance_settings (%s) has been destroyed: %s", rs.Primary.ID, err) + return flex.FmtErrorf("Error checking for scc_instance_settings (%s) has been destroyed: %s", rs.Primary.ID, err) } } diff --git a/ibm/service/scc/resource_ibm_scc_profile.go b/ibm/service/scc/resource_ibm_scc_profile.go index 677cd38bac..821986e784 100644 --- a/ibm/service/scc/resource_ibm_scc_profile.go +++ b/ibm/service/scc/resource_ibm_scc_profile.go @@ -5,7 +5,6 @@ package scc import ( "context" - "fmt" "log" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -388,7 +387,7 @@ func resourceIbmSccProfileCreate(context context.Context, d *schema.ResourceData profile, response, err := securityandcompliancecenterapiClient.CreateProfileWithContext(context, createProfileOptions) if err != nil { log.Printf("[DEBUG] CreateProfileWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("CreateProfileWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("CreateProfileWithContext failed %s\n%s", err, response)) } d.SetId(instance_id + "/" + *profile.ID) @@ -419,23 +418,23 @@ func resourceIbmSccProfileRead(context context.Context, d *schema.ResourceData, return nil } log.Printf("[DEBUG] GetProfileWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetProfileWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetProfileWithContext failed %s\n%s", err, response)) } if err = d.Set("instance_id", parts[0]); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } if err = d.Set("profile_id", parts[1]); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_id: %s", err)) } if err = d.Set("profile_name", profile.ProfileName); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_name: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_name: %s", err)) } if err = d.Set("profile_description", profile.ProfileDescription); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_description: %s", err)) } if err = d.Set("profile_type", profile.ProfileType); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_type: %s", err)) } controls := []map[string]interface{}{} for _, controlsItem := range profile.Controls { @@ -446,7 +445,7 @@ func resourceIbmSccProfileRead(context context.Context, d *schema.ResourceData, controls = append(controls, controlsItemMap) } if err = d.Set("controls", controls); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls: %s", err)) } if len(profile.DefaultParameters) > 0 { defaultParameters := []map[string]interface{}{} @@ -458,67 +457,67 @@ func resourceIbmSccProfileRead(context context.Context, d *schema.ResourceData, defaultParameters = append(defaultParameters, defaultParametersItemMap) } if err = d.Set("default_parameters", defaultParameters); err != nil { - return diag.FromErr(fmt.Errorf("Error setting default_parameters: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting default_parameters: %s", err)) } } if !core.IsNil(profile.ProfileVersion) { if err = d.Set("profile_version", profile.ProfileVersion); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_version: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_version: %s", err)) } } if !core.IsNil(profile.VersionGroupLabel) { if err = d.Set("version_group_label", profile.VersionGroupLabel); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version_group_label: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting version_group_label: %s", err)) } } if !core.IsNil(profile.InstanceID) { if err = d.Set("instance_id", profile.InstanceID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } } if !core.IsNil(profile.Latest) { if err = d.Set("latest", profile.Latest); err != nil { - return diag.FromErr(fmt.Errorf("Error setting latest: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting latest: %s", err)) } } if !core.IsNil(profile.HierarchyEnabled) { if err = d.Set("hierarchy_enabled", profile.HierarchyEnabled); err != nil { - return diag.FromErr(fmt.Errorf("Error setting hierarchy_enabled: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting hierarchy_enabled: %s", err)) } } if !core.IsNil(profile.CreatedBy) { if err = d.Set("created_by", profile.CreatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_by: %s", err)) } } if !core.IsNil(profile.CreatedOn) { if err = d.Set("created_on", flex.DateTimeToString(profile.CreatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } } if !core.IsNil(profile.UpdatedBy) { if err = d.Set("updated_by", profile.UpdatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_by: %s", err)) } } if !core.IsNil(profile.UpdatedOn) { if err = d.Set("updated_on", flex.DateTimeToString(profile.UpdatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_on: %s", err)) } } if !core.IsNil(profile.ControlsCount) { if err = d.Set("controls_count", flex.IntValue(profile.ControlsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting controls_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting controls_count: %s", err)) } } if !core.IsNil(profile.ControlParentsCount) { if err = d.Set("control_parents_count", flex.IntValue(profile.ControlParentsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting control_parents_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting control_parents_count: %s", err)) } } if !core.IsNil(profile.AttachmentsCount) { if err = d.Set("attachments_count", flex.IntValue(profile.AttachmentsCount)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attachments_count: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attachments_count: %s", err)) } } @@ -582,7 +581,7 @@ func resourceIbmSccProfileUpdate(context context.Context, d *schema.ResourceData _, response, err := securityandcompliancecenterapiClient.ReplaceProfileWithContext(context, replaceProfileOptions) if err != nil { log.Printf("[DEBUG] ReplaceProfileWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ReplaceProfileWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("ReplaceProfileWithContext failed %s\n%s", err, response)) } } @@ -607,7 +606,7 @@ func resourceIbmSccProfileDelete(context context.Context, d *schema.ResourceData _, response, err := securityandcompliancecenterapiClient.DeleteCustomProfileWithContext(context, deleteCustomProfileOptions) if err != nil { log.Printf("[DEBUG] DeleteCustomProfileWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteCustomProfileWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("DeleteCustomProfileWithContext failed %s\n%s", err, response)) } d.SetId("") diff --git a/ibm/service/scc/resource_ibm_scc_profile_attachment.go b/ibm/service/scc/resource_ibm_scc_profile_attachment.go index f511416cda..82001de388 100644 --- a/ibm/service/scc/resource_ibm_scc_profile_attachment.go +++ b/ibm/service/scc/resource_ibm_scc_profile_attachment.go @@ -6,7 +6,10 @@ package scc import ( "context" "fmt" + "hash/crc32" "log" + "strconv" + "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -166,7 +169,7 @@ func ResourceIbmSccProfileAttachment() *schema.Resource { Optional: true, Description: "The profile parameters for the attachment.", Elem: schemaAttachmentParameters(), - Set: hashAttachmentParameters, + Set: attachmentParametersSchemaSetFunc("assessment_id", "parameter_name", "parameter_display_name", "parameter_type", "parameter_value"), }, "last_scan": { Type: schema.TypeList, @@ -236,13 +239,49 @@ func ResourceIbmSccProfileAttachmentValidator() *validate.ResourceValidator { // hashAttachmentParameters will determine how to hash the AttachmentParameters schema.Resource // It uses the 'assessment_id' in order to determine the difference. -func hashAttachmentParameters(v interface{}) int { - if v == nil { - return 0 +func attachmentParametersSchemaSetFunc(keys ...string) schema.SchemaSetFunc { + return func(v interface{}) int { + var str strings.Builder + + if m, ok := v.(map[string]interface{}); ok { + for _, key := range keys { + if v, ok := m[key]; ok { + switch v := v.(type) { + case bool: + str.WriteRune('-') + str.WriteString(strconv.FormatBool(v)) + case int: + str.WriteRune('-') + str.WriteString(strconv.Itoa(v)) + case string: + str.WriteRune('-') + str.WriteString(v) + case []interface{}: + str.WriteRune('-') + s := make([]string, len(v)) + for i, v := range v { + s[i] = fmt.Sprint(v) + } + str.WriteString(fmt.Sprintf("[%s]", strings.Join(s, ","))) + } + } + } + } + + return stringHashcode(str.String()) } - m := v.(map[string]interface{}) - id := (m["assessment_id"]).(string) - return schema.HashString(id) +} + +func stringHashcode(s string) int { + v := int(crc32.ChecksumIEEE([]byte(s))) + if v >= 0 { + return v + } + if -v >= 0 { + return -v + } + // v == MinInt + return 0 } // schemaAttachmentParameters returns a *schema.Resource for AttachmentParameters @@ -331,7 +370,7 @@ func resourceIbmSccProfileAttachmentCreate(context context.Context, d *schema.Re attachmentPrototype, response, err := securityandcompliancecenterapiClient.CreateAttachmentWithContext(context, createAttachmentOptions) if err != nil { log.Printf("[DEBUG] CreateAttachmentWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("CreateAttachmentWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("CreateAttachmentWithContext failed %s\n%s", err, response)) } d.SetId(fmt.Sprintf("%s/%s/%s", instance_id, *createAttachmentOptions.ProfileID, *attachmentPrototype.Attachments[0].ID)) @@ -363,25 +402,25 @@ func resourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Reso return nil } log.Printf("[DEBUG] GetProfileAttachmentWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetProfileAttachmentWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetProfileAttachmentWithContext failed %s\n%s", err, response)) } if err = d.Set("instance_id", parts[0]); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } if !core.IsNil(attachmentItem.ID) { if err = d.Set("profile_attachment_id", attachmentItem.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_id: %s", err)) } } if !core.IsNil(attachmentItem.ProfileID) { if err = d.Set("profile_id", attachmentItem.ProfileID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting profile_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting profile_id: %s", err)) } } if !core.IsNil(attachmentItem.AccountID) { if err = d.Set("account_id", attachmentItem.AccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting account_id: %s", err)) } } if !core.IsNil(attachmentItem.Scope) { @@ -394,37 +433,37 @@ func resourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Reso scope = append(scope, scopeItemMap) } if err = d.Set("scope", scope); err != nil { - return diag.FromErr(fmt.Errorf("Error setting scope: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting scope: %s", err)) } } if !core.IsNil(attachmentItem.CreatedOn) { if err = d.Set("created_on", flex.DateTimeToString(attachmentItem.CreatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } } if !core.IsNil(attachmentItem.CreatedBy) { if err = d.Set("created_by", attachmentItem.CreatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_by: %s", err)) } } if !core.IsNil(attachmentItem.UpdatedOn) { if err = d.Set("updated_on", flex.DateTimeToString(attachmentItem.UpdatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_on: %s", err)) } } if !core.IsNil(attachmentItem.UpdatedBy) { if err = d.Set("updated_by", attachmentItem.UpdatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_by: %s", err)) } } if !core.IsNil(attachmentItem.Status) { if err = d.Set("status", attachmentItem.Status); err != nil { - return diag.FromErr(fmt.Errorf("Error setting status: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting status: %s", err)) } } if !core.IsNil(attachmentItem.Schedule) { if err = d.Set("schedule", attachmentItem.Schedule); err != nil { - return diag.FromErr(fmt.Errorf("Error setting schedule: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting schedule: %s", err)) } } if !core.IsNil(attachmentItem.Notifications) { @@ -433,11 +472,13 @@ func resourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Reso return diag.FromErr(err) } if err = d.Set("notifications", []map[string]interface{}{notificationsMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting notifications: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting notifications: %s", err)) } } if !core.IsNil(attachmentItem.AttachmentParameters) { - attachmentParameters := &schema.Set{F: hashAttachmentParameters} + attachmentParameters := &schema.Set{ + F: attachmentParametersSchemaSetFunc("assessment_id", "parameter_name", "parameter_display_name", "parameter_type", "parameter_value"), + } for _, attachmentParametersItem := range attachmentItem.AttachmentParameters { attachmentParametersItemMap, err := resourceIbmSccProfileAttachmentAttachmentParameterPrototypeToMap(&attachmentParametersItem) if err != nil { @@ -446,7 +487,7 @@ func resourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Reso attachmentParameters.Add(attachmentParametersItemMap) } if err = d.Set("attachment_parameters", attachmentParameters); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attachment_parameters: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attachment_parameters: %s", err)) } } if !core.IsNil(attachmentItem.LastScan) { @@ -455,27 +496,27 @@ func resourceIbmSccProfileAttachmentRead(context context.Context, d *schema.Reso return diag.FromErr(err) } if err = d.Set("last_scan", []map[string]interface{}{lastScanMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting last_scan: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting last_scan: %s", err)) } } if !core.IsNil(attachmentItem.NextScanTime) { if err = d.Set("next_scan_time", flex.DateTimeToString(attachmentItem.NextScanTime)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting next_scan_time: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting next_scan_time: %s", err)) } } if !core.IsNil(attachmentItem.Name) { if err = d.Set("name", attachmentItem.Name); err != nil { - return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting name: %s", err)) } } if !core.IsNil(attachmentItem.Description) { if err = d.Set("description", attachmentItem.Description); err != nil { - return diag.FromErr(fmt.Errorf("Error setting description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting description: %s", err)) } } if !core.IsNil(attachmentItem.ID) { if err = d.Set("attachment_id", attachmentItem.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attachment_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attachment_id: %s", err)) } } @@ -502,7 +543,7 @@ func resourceIbmSccProfileAttachmentUpdate(context context.Context, d *schema.Re hasChange := false if d.HasChange("profile_id") { - return diag.FromErr(fmt.Errorf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + return diag.FromErr(flex.FmtErrorf("Cannot update resource property \"%s\" with the ForceNew annotation."+ " The resource must be re-created to update this property.", "profile_id")) } @@ -549,9 +590,15 @@ func resourceIbmSccProfileAttachmentUpdate(context context.Context, d *schema.Re if replaceProfileAttachmentOptions.Name == nil { replaceProfileAttachmentOptions.SetName(d.Get("name").(string)) } + if replaceProfileAttachmentOptions.Status == nil { + replaceProfileAttachmentOptions.SetStatus(d.Get("status").(string)) + } if replaceProfileAttachmentOptions.Schedule == nil { replaceProfileAttachmentOptions.SetSchedule(d.Get("schedule").(string)) } + if replaceProfileAttachmentOptions.Description == nil { + replaceProfileAttachmentOptions.SetDescription(d.Get("description").(string)) + } if replaceProfileAttachmentOptions.Notifications == nil { notificationsItem := d.Get("notifications.0").(map[string]interface{}) updateNotifications, err := resourceIbmSccProfileAttachmentMapToAttachmentsNotificationsPrototype(notificationsItem) @@ -560,6 +607,9 @@ func resourceIbmSccProfileAttachmentUpdate(context context.Context, d *schema.Re } replaceProfileAttachmentOptions.SetNotifications(updateNotifications) } + if replaceProfileAttachmentOptions.Status == nil { + replaceProfileAttachmentOptions.SetSchedule(d.Get("status").(string)) + } if len(replaceProfileAttachmentOptions.Scope) == 0 { scope := []securityandcompliancecenterapiv3.MultiCloudScope{} for _, scopeItem := range d.Get("scope").([]interface{}) { @@ -574,7 +624,7 @@ func resourceIbmSccProfileAttachmentUpdate(context context.Context, d *schema.Re _, response, err := securityandcompliancecenterapiClient.ReplaceProfileAttachmentWithContext(context, replaceProfileAttachmentOptions) if err != nil { log.Printf("[DEBUG] ReplaceProfileAttachmentWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ReplaceProfileAttachmentWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("ReplaceProfileAttachmentWithContext failed %s\n%s", err, response)) } } @@ -601,7 +651,7 @@ func resourceIbmSccProfileAttachmentDelete(context context.Context, d *schema.Re _, response, err := securityandcompliancecenterapiClient.DeleteProfileAttachmentWithContext(context, deleteProfileAttachmentOptions) if err != nil { log.Printf("[DEBUG] DeleteProfileAttachmentWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteProfileAttachmentWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("DeleteProfileAttachmentWithContext failed %s\n%s", err, response)) } d.SetId("") @@ -912,15 +962,15 @@ func resourceIbmSccProfileAttachmentAttachmentParameterPrototypeToMap(model *sec if model.ParameterName != nil { modelMap["parameter_name"] = flex.StringValue(model.ParameterName) } - if model.ParameterValue != nil { - modelMap["parameter_value"] = flex.StringValue(model.ParameterValue) - } if model.ParameterDisplayName != nil { modelMap["parameter_display_name"] = flex.StringValue(model.ParameterDisplayName) } if model.ParameterType != nil { modelMap["parameter_type"] = flex.StringValue(model.ParameterType) } + if model.ParameterValue != nil { + modelMap["parameter_value"] = flex.StringValue(model.ParameterValue) + } return modelMap, nil } diff --git a/ibm/service/scc/resource_ibm_scc_profile_attachment_test.go b/ibm/service/scc/resource_ibm_scc_profile_attachment_test.go index d652fb1f30..70ddd11f5d 100644 --- a/ibm/service/scc/resource_ibm_scc_profile_attachment_test.go +++ b/ibm/service/scc/resource_ibm_scc_profile_attachment_test.go @@ -50,11 +50,40 @@ func TestAccIbmSccProfileAttachmentAllArgs(t *testing.T) { }, resource.TestStep{ Config: testAccCheckIbmSccProfileAttachmentConfig(acc.SccInstanceID), - Check: resource.ComposeAggregateTestCheckFunc(), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmSccProfileAttachmentExists("ibm_scc_profile_attachment.scc_profile_attachment_instance", conf), + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.#", "5"), + ), }, resource.TestStep{ Config: testAccCheckIbmSccProfileAttachmentConfigChange(acc.SccInstanceID), - Check: resource.ComposeAggregateTestCheckFunc(), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmSccProfileAttachmentExists("ibm_scc_profile_attachment.scc_profile_attachment_instance", conf), + // verify if all attachment_parameters are stored in the state + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.#", "5"), + // verify the changes to rule-7c5f6385-67e4-4edf-bec8-c722558b2dec + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.0.assessment_id", "rule-7c5f6385-67e4-4edf-bec8-c722558b2dec"), + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.0.parameter_value", "23"), + // verify the changes to rule-9653d2c7-6290-4128-a5a3-65487ba40370 + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.1.assessment_id", "rule-9653d2c7-6290-4128-a5a3-65487ba40370"), + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.1.parameter_value", "1234"), + // verify the changes to rule-e16fcfea-fe21-4d30-a721-423611481fea + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.2.assessment_id", "rule-e16fcfea-fe21-4d30-a721-423611481fea"), + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.2.parameter_value", "['1.2', '1.3']"), + // verify the changes to rule-f1e80ee7-88d5-4bf2-b42f-c863bb24601c + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.3.assessment_id", "rule-f1e80ee7-88d5-4bf2-b42f-c863bb24601c"), + resource.TestCheckResourceAttr( + "ibm_scc_profile_attachment.scc_profile_attachment_instance", "attachment_parameters.3.parameter_value", "4000"), + ), }, resource.TestStep{ ResourceName: "ibm_scc_profile_attachment.scc_profile_attachment_instance", @@ -138,7 +167,7 @@ func testAccCheckIbmSccProfileAttachmentConfigBasic(instanceID string) string { } } schedule = "every_30_days" - status = "enabled" + status = "disabled" notifications { enabled = false controls { @@ -168,7 +197,7 @@ func testAccCheckIbmSccProfileAttachmentConfig(instanceID string) string { resource "ibm_scc_profile_attachment" "scc_profile_attachment_instance" { instance_id = "%s" - profile_id = local.scc_profiles_map["CIS IBM Cloud Foundations Benchmark"] + profile_id = local.scc_profiles_map["CIS IBM Cloud Foundations Benchmark v1.1.0"] name = "profile_attachment_name" description = "scc_profile_attachment_description" scope { @@ -235,6 +264,7 @@ func testAccCheckIbmSccProfileAttachmentConfig(instanceID string) string { `, instanceID, instanceID) } +// Returns a terraform change where the attachment_parameters are modified slightly. func testAccCheckIbmSccProfileAttachmentConfigChange(instanceID string) string { return fmt.Sprintf(` locals { @@ -253,7 +283,7 @@ func testAccCheckIbmSccProfileAttachmentConfigChange(instanceID string) string { resource "ibm_scc_profile_attachment" "scc_profile_attachment_instance" { instance_id = "%s" - profile_id = local.scc_profiles_map["CIS IBM Cloud Foundations Benchmark"] + profile_id = local.scc_profiles_map["CIS IBM Cloud Foundations Benchmark v1.1.0"] name = "profile_attachment_name" description = "scc_profile_attachment_description" scope { @@ -285,7 +315,7 @@ func testAccCheckIbmSccProfileAttachmentConfigChange(instanceID string) string { parameter_type = "string_list" } attachment_parameters { - parameter_value = "22" + parameter_value = "8080" assessment_id = "rule-f9137be8-2490-4afb-8cd5-a201cb167eb2" assessment_type = "automated" parameter_display_name = "Network ACL rule for allowed IPs to SSH port" @@ -293,7 +323,7 @@ func testAccCheckIbmSccProfileAttachmentConfigChange(instanceID string) string { parameter_type = "numeric" } attachment_parameters { - parameter_value = "22" + parameter_value = "23" assessment_id = "rule-7c5f6385-67e4-4edf-bec8-c722558b2dec" assessment_type = "automated" parameter_display_name = "Security group rule SSH allow port number" @@ -301,18 +331,18 @@ func testAccCheckIbmSccProfileAttachmentConfigChange(instanceID string) string { parameter_type = "numeric" } attachment_parameters { - parameter_value = "3389" - assessment_id = "rule-9653d2c7-6290-4128-a5a3-65487ba40370" + parameter_value = "4000" + assessment_id = "rule-f1e80ee7-88d5-4bf2-b42f-c863bb24601c" assessment_type = "automated" - parameter_display_name = "Security group rule RDP allow port number" + parameter_display_name = "Disallowed IPs for ingress to RDP port" parameter_name = "rdp_port" parameter_type = "numeric" } attachment_parameters { - parameter_value = "3389" - assessment_id = "rule-f1e80ee7-88d5-4bf2-b42f-c863bb24601c" + parameter_value = "1234" + assessment_id = "rule-9653d2c7-6290-4128-a5a3-65487ba40370" assessment_type = "automated" - parameter_display_name = "Disallowed IPs for ingress to RDP port" + parameter_display_name = "Security group rule RDP allow port number" parameter_name = "rdp_port" parameter_type = "numeric" } @@ -325,7 +355,7 @@ func testAccCheckIbmSccProfileAttachmentExists(n string, obj securityandcomplian return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", n) + return flex.FmtErrorf("Not found: %s", n) } securityandcompliancecenterapiClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).SecurityAndComplianceCenterV3() @@ -379,9 +409,9 @@ func testAccCheckIbmSccProfileAttachmentDestroy(s *terraform.State) error { _, response, err := securityandcompliancecenterapiClient.GetProfileAttachment(getProfileAttachmentOptions) if err == nil { - return fmt.Errorf("scc_profile_attachment still exists: %s", rs.Primary.ID) + return flex.FmtErrorf("scc_profile_attachment still exists: %s", rs.Primary.ID) } else if response.StatusCode != 404 { - return fmt.Errorf("Error checking for scc_profile_attachment (%s) has been destroyed: %s", rs.Primary.ID, err) + return flex.FmtErrorf("Error checking for scc_profile_attachment (%s) has been destroyed: %s", rs.Primary.ID, err) } } diff --git a/ibm/service/scc/resource_ibm_scc_profile_test.go b/ibm/service/scc/resource_ibm_scc_profile_test.go index a08c7338aa..9ecb68ac6c 100644 --- a/ibm/service/scc/resource_ibm_scc_profile_test.go +++ b/ibm/service/scc/resource_ibm_scc_profile_test.go @@ -14,6 +14,7 @@ import ( acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/scc-go-sdk/v5/securityandcompliancecenterapiv3" ) @@ -223,7 +224,7 @@ func testAccCheckIbmSccProfileExists(n string, obj securityandcompliancecenterap return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", n) + return flex.FmtErrorf("Not found: %s", n) } securityandcompliancecenterapiClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).SecurityAndComplianceCenterV3() @@ -267,9 +268,9 @@ func testAccCheckIbmSccProfileDestroy(s *terraform.State) error { _, response, err := securityandcompliancecenterapiClient.GetProfile(getProfileOptions) if err == nil { - return fmt.Errorf("scc_profile still exists: %s", rs.Primary.ID) + return flex.FmtErrorf("scc_profile still exists: %s", rs.Primary.ID) } else if response.StatusCode != 404 { - return fmt.Errorf("Error checking for scc_profile (%s) has been destroyed: %s", rs.Primary.ID, err) + return flex.FmtErrorf("Error checking for scc_profile (%s) has been destroyed: %s", rs.Primary.ID, err) } } diff --git a/ibm/service/scc/resource_ibm_scc_provider_type_instance.go b/ibm/service/scc/resource_ibm_scc_provider_type_instance.go index a9b4c4faca..551e5bafba 100644 --- a/ibm/service/scc/resource_ibm_scc_provider_type_instance.go +++ b/ibm/service/scc/resource_ibm_scc_provider_type_instance.go @@ -116,7 +116,7 @@ func resourceIbmSccProviderTypeInstanceCreate(context context.Context, d *schema providerTypeInstanceItem, response, err := securityAndComplianceCenterApIsClient.CreateProviderTypeInstanceWithContext(context, createProviderTypeInstanceOptions) if err != nil { log.Printf("[DEBUG] CreateProviderTypeInstanceWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("CreateProviderTypeInstanceWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("CreateProviderTypeInstanceWithContext failed %s\n%s", err, response)) } d.SetId(fmt.Sprintf("%s/%s/%s", instanceID, *createProviderTypeInstanceOptions.ProviderTypeID, *providerTypeInstanceItem.ID)) @@ -148,15 +148,15 @@ func resourceIbmSccProviderTypeInstanceRead(context context.Context, d *schema.R return nil } log.Printf("[DEBUG] GetProviderTypeInstanceWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetProviderTypeInstanceWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetProviderTypeInstanceWithContext failed %s\n%s", err, response)) } if err = d.Set("instance_id", parts[0]); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } if err = d.Set("name", providerTypeInstanceItem.Name); err != nil { - return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting name: %s", err)) } attributesMap, err := resourceIbmSccProviderTypeInstanceProviderTypeInstanceAttributesToMap(providerTypeInstanceItem.Attributes) @@ -165,31 +165,31 @@ func resourceIbmSccProviderTypeInstanceRead(context context.Context, d *schema.R } if err = d.Set("attributes", attributesMap); err != nil { - return diag.FromErr(fmt.Errorf("Error setting attributes: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting attributes: %s", err)) } if !core.IsNil(providerTypeInstanceItem.Type) { if err = d.Set("type", providerTypeInstanceItem.Type); err != nil { - return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting type: %s", err)) } } if !core.IsNil(providerTypeInstanceItem.CreatedAt) { if err = d.Set("created_at", flex.DateTimeToString(providerTypeInstanceItem.CreatedAt)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_at: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_at: %s", err)) } } if !core.IsNil(providerTypeInstanceItem.UpdatedAt) { if err = d.Set("updated_at", flex.DateTimeToString(providerTypeInstanceItem.UpdatedAt)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_at: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_at: %s", err)) } } if !core.IsNil(providerTypeInstanceItem.ID) { if err = d.Set("provider_type_instance_id", providerTypeInstanceItem.ID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting provider_type_instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting provider_type_instance_id: %s", err)) } } if err = d.Set("provider_type_id", parts[1]); err != nil { - return diag.FromErr(fmt.Errorf("Error setting provider_type_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting provider_type_id: %s", err)) } return nil @@ -216,7 +216,7 @@ func resourceIbmSccProviderTypeInstanceUpdate(context context.Context, d *schema hasChange := false if d.HasChange("provider_type_id") { - return diag.FromErr(fmt.Errorf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + return diag.FromErr(flex.FmtErrorf("Cannot update resource property \"%s\" with the ForceNew annotation."+ " The resource must be re-created to update this property.", "provider_type_id")) } if d.HasChange("attributes") { @@ -232,7 +232,7 @@ func resourceIbmSccProviderTypeInstanceUpdate(context context.Context, d *schema _, response, err := securityAndComplianceCenterApIsClient.UpdateProviderTypeInstanceWithContext(context, updateProviderTypeInstanceOptions) if err != nil { log.Printf("[DEBUG] UpdateProviderTypeInstanceWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("UpdateProviderTypeInstanceWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("UpdateProviderTypeInstanceWithContext failed %s\n%s", err, response)) } } @@ -259,7 +259,7 @@ func resourceIbmSccProviderTypeInstanceDelete(context context.Context, d *schema response, err := securityAndComplianceCenterApIsClient.DeleteProviderTypeInstanceWithContext(context, deleteProviderTypeInstanceOptions) if err != nil { log.Printf("[DEBUG] DeleteProviderTypeInstanceWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteProviderTypeInstanceWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("DeleteProviderTypeInstanceWithContext failed %s\n%s", err, response)) } d.SetId("") diff --git a/ibm/service/scc/resource_ibm_scc_provider_type_instance_test.go b/ibm/service/scc/resource_ibm_scc_provider_type_instance_test.go index bbbe2da180..a52c91dc6e 100644 --- a/ibm/service/scc/resource_ibm_scc_provider_type_instance_test.go +++ b/ibm/service/scc/resource_ibm_scc_provider_type_instance_test.go @@ -102,7 +102,7 @@ func testAccCheckIbmSccProviderTypeInstanceExists(n string, obj securityandcompl return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", n) + return flex.FmtErrorf("Not found: %s", n) } securityAndComplianceCenterApIsClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).SecurityAndComplianceCenterV3() @@ -156,9 +156,9 @@ func testAccCheckIbmSccProviderTypeInstanceDestroy(s *terraform.State) error { _, response, err := securityAndComplianceCenterApIsClient.GetProviderTypeInstance(getProviderTypeInstanceOptions) if err == nil { - return fmt.Errorf("scc_provider_type_instance still exists: %s", rs.Primary.ID) + return flex.FmtErrorf("scc_provider_type_instance still exists: %s", rs.Primary.ID) } else if response.StatusCode != 404 { - return fmt.Errorf("Error checking for scc_provider_type_instance (%s) has been destroyed: %s", rs.Primary.ID, err) + return flex.FmtErrorf("Error checking for scc_provider_type_instance (%s) has been destroyed: %s", rs.Primary.ID, err) } } diff --git a/ibm/service/scc/resource_ibm_scc_rule.go b/ibm/service/scc/resource_ibm_scc_rule.go index 625219baed..cc046c34b4 100644 --- a/ibm/service/scc/resource_ibm_scc_rule.go +++ b/ibm/service/scc/resource_ibm_scc_rule.go @@ -5,10 +5,7 @@ package scc import ( "context" - "fmt" "log" - "reflect" - "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -168,202 +165,7 @@ func ResourceIbmSccRule() *schema.Resource { Required: true, Description: "The required configurations.", Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": { - Type: schema.TypeString, - Optional: true, - Description: "The required config description.", - }, - "and": { - Type: schema.TypeList, - Optional: true, - Description: "The `AND` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": { - Type: schema.TypeString, - Optional: true, - Description: "The required config description.", - }, - "or": { - Type: schema.TypeList, - Optional: true, - Description: "The `OR` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": { - Type: schema.TypeString, - Optional: true, - Description: "The required config description.", - }, - "property": { - Type: schema.TypeString, - Required: true, - Description: "The property.", - }, - "operator": { - Type: schema.TypeString, - Required: true, - Description: "The operator.", - }, - "value": { - Type: schema.TypeString, - Optional: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "and": { - Type: schema.TypeList, - Optional: true, - Description: "The `AND` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": { - Type: schema.TypeString, - Optional: true, - Description: "The required config description.", - }, - "property": { - Type: schema.TypeString, - Required: true, - Description: "The property.", - }, - "operator": { - Type: schema.TypeString, - Required: true, - Description: "The operator.", - }, - "value": { - Type: schema.TypeString, - Optional: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "property": { - Type: schema.TypeString, - Optional: true, - Description: "The property.", - }, - "operator": { - Type: schema.TypeString, - Optional: true, - Description: "The operator.", - }, - "value": { - Type: schema.TypeString, - Optional: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "or": { - Type: schema.TypeList, - Optional: true, - Description: "The `OR` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": { - Type: schema.TypeString, - Optional: true, - Description: "The required config description.", - }, - "or": { - Type: schema.TypeList, - Optional: true, - Description: "The `OR` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": { - Type: schema.TypeString, - Optional: true, - Description: "The required config description.", - }, - "property": { - Type: schema.TypeString, - Required: true, - Description: "The property.", - }, - "operator": { - Type: schema.TypeString, - Required: true, - Description: "The operator.", - }, - "value": { - Type: schema.TypeString, - Optional: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "and": { - Type: schema.TypeList, - Optional: true, - Description: "The `AND` required configurations.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "description": { - Type: schema.TypeString, - Optional: true, - Description: "The required config description.", - }, - "property": { - Type: schema.TypeString, - Required: true, - Description: "The property.", - }, - "operator": { - Type: schema.TypeString, - Required: true, - Description: "The operator.", - }, - "value": { - Type: schema.TypeString, - Optional: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "property": { - Type: schema.TypeString, - Optional: true, - Description: "The property.", - }, - "operator": { - Type: schema.TypeString, - Optional: true, - Description: "The operator.", - }, - "value": { - Type: schema.TypeString, - Optional: true, - Description: "Schema for any JSON type.", - }, - }, - }, - }, - "property": { - Type: schema.TypeString, - Optional: true, - Description: "The property.", - }, - "operator": { - Type: schema.TypeString, - Optional: true, - Description: "The operator.", - }, - "value": { - Type: schema.TypeString, - Optional: true, - Description: "Schema for any JSON type.", - }, - }, + Schema: getRequiredConfigSchema(0), }, }, "target": { @@ -373,58 +175,7 @@ func ResourceIbmSccRule() *schema.Resource { Required: true, Description: "The rule target.", Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "service_name": { - Type: schema.TypeString, - Required: true, - Description: "The target service name.", - }, - "service_display_name": { - Type: schema.TypeString, - Optional: true, - Description: "The display name of the target service.", - // Manual Intervention - DiffSuppressFunc: func(_, oldVal, newVal string, d *schema.ResourceData) bool { - if newVal == "" { - return true - } - if strings.ToLower(oldVal) == strings.ToLower(newVal) { - return true - } - return false - }, - // End Manual Intervention - }, - "resource_kind": { - Type: schema.TypeString, - Required: true, - Description: "The target resource kind.", - }, - "additional_target_attributes": { - Type: schema.TypeList, - Optional: true, - Description: "The list of targets supported properties.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Optional: true, - Description: "The additional target attribute name.", - }, - "operator": { - Type: schema.TypeString, - Optional: true, - Description: "The operator.", - }, - "value": { - Type: schema.TypeString, - Optional: true, - Description: "The value.", - }, - }, - }, - }, - }, + Schema: getTargetSchema(), }, }, "type": { @@ -489,13 +240,13 @@ func resourceIbmSccRuleCreate(context context.Context, d *schema.ResourceData, m createRuleOptions.SetDescription(d.Get("description").(string)) // Manual Intervention - targetModel, err := resourceIbmSccRuleMapToTarget(d.Get("target.0").(map[string]interface{})) + targetModel, err := modelMapToTarget(d.Get("target.0").(map[string]interface{})) // End Manual Intervention if err != nil { return diag.FromErr(err) } createRuleOptions.SetTarget(targetModel) - requiredConfigModel, err := resourceIbmSccRuleMapToRequiredConfig(d.Get("required_config.0").(map[string]interface{})) + requiredConfigModel, err := modelMapToRequiredConfig(d.Get("required_config.0").(map[string]interface{})) if err != nil { return diag.FromErr(err) } @@ -524,7 +275,7 @@ func resourceIbmSccRuleCreate(context context.Context, d *schema.ResourceData, m rule, response, err := configManagerClient.CreateRuleWithContext(context, createRuleOptions) if err != nil { log.Printf("[DEBUG] CreateRuleWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("CreateRuleWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("CreateRuleWithContext failed %s\n%s", err, response)) } d.SetId(instance_id + "/" + *rule.ID) @@ -554,27 +305,27 @@ func resourceIbmSccRuleRead(context context.Context, d *schema.ResourceData, met return nil } log.Printf("[DEBUG] GetRuleWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("GetRuleWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("GetRuleWithContext failed %s\n%s", err, response)) } // Manual Intervention if err = d.Set("instance_id", parts[0]); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } if err = d.Set("rule_id", parts[1]); err != nil { - return diag.FromErr(fmt.Errorf("Error setting instance_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting instance_id: %s", err)) } if err = d.Set("etag", response.Headers.Get("ETag")); err != nil { - return diag.FromErr(fmt.Errorf("Error setting etag: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting etag: %s", err)) } // End Manual Intervention if err = d.Set("description", rule.Description); err != nil { - return diag.FromErr(fmt.Errorf("Error setting description: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting description: %s", err)) } if !core.IsNil(rule.Version) { if err = d.Set("version", rule.Version); err != nil { - return diag.FromErr(fmt.Errorf("Error setting version: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting version: %s", err)) } } @@ -584,47 +335,46 @@ func resourceIbmSccRuleRead(context context.Context, d *schema.ResourceData, met return diag.FromErr(err) } if err = d.Set("import", []map[string]interface{}{importVarMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting import: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting import: %s", err)) } } - targetMap, err := resourceIbmSccRuleTargetToMap(rule.Target) + targetMap, err := targetToModelMap(rule.Target) if err != nil { return diag.FromErr(err) } if err = d.Set("target", []map[string]interface{}{targetMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting target: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting target: %s", err)) } - requiredConfigMap, err := resourceIbmSccRuleRequiredConfigToMap(rule.RequiredConfig) + requiredConfigMap, err := requiredConfigToModelMap(rule.RequiredConfig) if err != nil { return diag.FromErr(err) } if err = d.Set("required_config", []map[string]interface{}{requiredConfigMap}); err != nil { - return diag.FromErr(fmt.Errorf("Error setting required_config: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting required_config: %s", err)) } if !core.IsNil(rule.Labels) { - log.Printf("[INFO] rule.Labels = %v\n", rule.Labels) if err = d.Set("labels", rule.Labels); err != nil { - return diag.FromErr(fmt.Errorf("Error setting labels: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting labels: %s", err)) } } if err = d.Set("created_on", flex.DateTimeToString(rule.CreatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_on: %s", err)) } if err = d.Set("created_by", rule.CreatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting created_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting created_by: %s", err)) } if err = d.Set("updated_on", flex.DateTimeToString(rule.UpdatedOn)); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_on: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_on: %s", err)) } if err = d.Set("updated_by", rule.UpdatedBy); err != nil { - return diag.FromErr(fmt.Errorf("Error setting updated_by: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting updated_by: %s", err)) } if err = d.Set("account_id", rule.AccountID); err != nil { - return diag.FromErr(fmt.Errorf("Error setting account_id: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting account_id: %s", err)) } if err = d.Set("type", rule.Type); err != nil { - return diag.FromErr(fmt.Errorf("Error setting type: %s", err)) + return diag.FromErr(flex.FmtErrorf("Error setting type: %s", err)) } return nil @@ -650,12 +400,12 @@ func resourceIbmSccRuleUpdate(context context.Context, d *schema.ResourceData, m if d.HasChange("description") || d.HasChange("target") || d.HasChange("required_config") { replaceRuleOptions.SetDescription(d.Get("description").(string)) - target, err := resourceIbmSccRuleMapToTarget(d.Get("target.0").(map[string]interface{})) + target, err := modelMapToTarget(d.Get("target.0").(map[string]interface{})) if err != nil { return diag.FromErr(err) } replaceRuleOptions.SetTarget(target) - requiredConfig, err := resourceIbmSccRuleMapToRequiredConfig(d.Get("required_config.0").(map[string]interface{})) + requiredConfig, err := modelMapToRequiredConfig(d.Get("required_config.0").(map[string]interface{})) if err != nil { return diag.FromErr(err) } @@ -697,7 +447,7 @@ func resourceIbmSccRuleUpdate(context context.Context, d *schema.ResourceData, m _, response, err := configManagerClient.ReplaceRuleWithContext(context, replaceRuleOptions) if err != nil { log.Printf("[DEBUG] ReplaceRuleWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("ReplaceRuleWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("ReplaceRuleWithContext failed %s\n%s", err, response)) } } @@ -722,7 +472,7 @@ func resourceIbmSccRuleDelete(context context.Context, d *schema.ResourceData, m response, err := configManagerClient.DeleteRuleWithContext(context, deleteRuleOptions) if err != nil { log.Printf("[DEBUG] DeleteRuleWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteRuleWithContext failed %s\n%s", err, response)) + return diag.FromErr(flex.FmtErrorf("DeleteRuleWithContext failed %s\n%s", err, response)) } d.SetId("") @@ -730,270 +480,6 @@ func resourceIbmSccRuleDelete(context context.Context, d *schema.ResourceData, m return nil } -func resourceIbmSccRuleMapToTarget(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.Target, error) { - model := &securityandcompliancecenterapiv3.Target{} - model.ServiceName = core.StringPtr(modelMap["service_name"].(string)) - if modelMap["service_display_name"] != nil && modelMap["service_display_name"].(string) != "" { - model.ServiceDisplayName = core.StringPtr(modelMap["service_display_name"].(string)) - } - model.ResourceKind = core.StringPtr(modelMap["resource_kind"].(string)) - if modelMap["additional_target_attributes"] != nil { - additionalTargetAttributes := []securityandcompliancecenterapiv3.AdditionalTargetAttribute{} - for _, additionalTargetAttributesItem := range modelMap["additional_target_attributes"].([]interface{}) { - additionalTargetAttributesItemModel, err := resourceIbmSccRuleMapToAdditionalTargetAttribute(additionalTargetAttributesItem.(map[string]interface{})) - if err != nil { - return model, err - } - additionalTargetAttributes = append(additionalTargetAttributes, *additionalTargetAttributesItemModel) - } - model.AdditionalTargetAttributes = additionalTargetAttributes - } - return model, nil -} - -func resourceIbmSccRuleMapToAdditionalTargetAttribute(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.AdditionalTargetAttribute, error) { - model := &securityandcompliancecenterapiv3.AdditionalTargetAttribute{} - if modelMap["name"] != nil && modelMap["name"].(string) != "" { - model.Name = core.StringPtr(modelMap["name"].(string)) - } - if modelMap["operator"] != nil && modelMap["operator"].(string) != "" { - model.Operator = core.StringPtr(modelMap["operator"].(string)) - } - if modelMap["value"] != nil && modelMap["value"].(string) != "" { - model.Value = core.StringPtr(modelMap["value"].(string)) - } - return model, nil -} - -func resourceIbmSccRuleMapToRequiredConfig(modelMap map[string]interface{}) (securityandcompliancecenterapiv3.RequiredConfigIntf, error) { - model := &securityandcompliancecenterapiv3.RequiredConfig{} - if modelMap["description"] != nil && modelMap["description"].(string) != "" { - model.Description = core.StringPtr(modelMap["description"].(string)) - } - if modelMap["and"] != nil { - and := []securityandcompliancecenterapiv3.RequiredConfigItemsIntf{} - for _, andItem := range modelMap["and"].([]interface{}) { - andItemModel, err := resourceIbmSccRuleMapToRequiredConfigItems(andItem.(map[string]interface{})) - if err != nil { - return model, err - } - and = append(and, andItemModel) - } - model.And = and - } - if modelMap["or"] != nil { - or := []securityandcompliancecenterapiv3.RequiredConfigItemsIntf{} - for _, orItem := range modelMap["or"].([]interface{}) { - orItemModel, err := resourceIbmSccRuleMapToRequiredConfigItems(orItem.(map[string]interface{})) - if err != nil { - return model, err - } - or = append(or, orItemModel) - } - model.Or = or - } - if modelMap["property"] != nil && modelMap["property"].(string) != "" { - model.Property = core.StringPtr(modelMap["property"].(string)) - } - if modelMap["operator"] != nil && modelMap["operator"].(string) != "" { - model.Operator = core.StringPtr(modelMap["operator"].(string)) - } - // Manual Intervention - if modelMap["value"] != nil && len(modelMap["value"].(string)) > 0 { - // model.Value = modelMap["value"].(string) - sLit := strings.Trim(modelMap["value"].(string), "[]") - sList := strings.Split(sLit, ",") - if len(sList) == 1 { - model.Value = modelMap["value"].(string) - } else { - model.Value = sList - } - - } - // End Manual Intervention - return model, nil -} - -func resourceIbmSccRuleMapToRequiredConfigItems(modelMap map[string]interface{}) (securityandcompliancecenterapiv3.RequiredConfigItemsIntf, error) { - model := &securityandcompliancecenterapiv3.RequiredConfigItems{} - if modelMap["description"] != nil && modelMap["description"].(string) != "" { - model.Description = core.StringPtr(modelMap["description"].(string)) - } - if modelMap["or"] != nil { - or := []securityandcompliancecenterapiv3.RequiredConfigItemsIntf{} - for _, orItem := range modelMap["or"].([]interface{}) { - orItemModel, err := resourceIbmSccRuleMapToRequiredConfigItems(orItem.(map[string]interface{})) - if err != nil { - return model, err - } - or = append(or, orItemModel) - } - model.Or = or - } - if modelMap["and"] != nil { - and := []securityandcompliancecenterapiv3.RequiredConfigItemsIntf{} - for _, andItem := range modelMap["and"].([]interface{}) { - andItemModel, err := resourceIbmSccRuleMapToRequiredConfigItems(andItem.(map[string]interface{})) - if err != nil { - return model, err - } - and = append(and, andItemModel) - } - model.And = and - } - if modelMap["property"] != nil && modelMap["property"].(string) != "" { - model.Property = core.StringPtr(modelMap["property"].(string)) - } - if modelMap["operator"] != nil && modelMap["operator"].(string) != "" { - model.Operator = core.StringPtr(modelMap["operator"].(string)) - } - // Manual Intervention - if modelMap["value"] != nil && len(modelMap["value"].(string)) > 0 { - // model.Value = modelMap["value"].(string) - sLit := strings.Trim(modelMap["value"].(string), "[]") - sList := strings.Split(sLit, ",") - if len(sList) == 1 { - model.Value = modelMap["value"].(string) - } else { - model.Value = sList - } - } - // Manual Intervention - return model, nil -} - -func resourceIbmSccRuleMapToRequiredConfigBase(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase, error) { - model := &securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase{} - if modelMap["description"] != nil && modelMap["description"].(string) != "" { - model.Description = core.StringPtr(modelMap["description"].(string)) - } - model.Property = core.StringPtr(modelMap["property"].(string)) - model.Operator = core.StringPtr(modelMap["operator"].(string)) - if modelMap["value"] != nil && len(modelMap["value"].(string)) > 0 { - sLit := strings.Trim(modelMap["value"].(string), "[]") - sList := strings.Split(sLit, ",") - if len(sList) == 1 { - model.Value = modelMap["value"].(string) - } else { - model.Value = sList - } - } - return model, nil -} - -func resourceIbmSccRuleMapToRequiredConfigItemsRequiredConfigOrDepth1(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigOr, error) { - model := &securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigOr{} - if modelMap["description"] != nil && modelMap["description"].(string) != "" { - model.Description = core.StringPtr(modelMap["description"].(string)) - } - if modelMap["or"] != nil { - or := []securityandcompliancecenterapiv3.RequiredConfigItemsIntf{} - for _, orItem := range modelMap["or"].([]interface{}) { - orItemModel, err := resourceIbmSccRuleMapToRequiredConfigItemsRequiredConfigBase(orItem.(map[string]interface{})) - if err != nil { - return model, err - } - or = append(or, orItemModel) - } - model.Or = or - } - if modelMap["and"] != nil { - or := []securityandcompliancecenterapiv3.RequiredConfigItemsIntf{} - for _, orItem := range modelMap["and"].([]interface{}) { - orItemModel, err := resourceIbmSccRuleMapToRequiredConfigItemsRequiredConfigBase(orItem.(map[string]interface{})) - if err != nil { - return model, err - } - or = append(or, orItemModel) - } - model.Or = or - } - return model, nil -} - -func resourceIbmSccRuleMapToRequiredConfigItemsRequiredConfigAndDepth1(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigAnd, error) { - model := &securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigAnd{} - if modelMap["description"] != nil && modelMap["description"].(string) != "" { - model.Description = core.StringPtr(modelMap["description"].(string)) - } - if modelMap["and"] != nil { - and := []securityandcompliancecenterapiv3.RequiredConfigItemsIntf{} - for _, andItem := range modelMap["and"].([]interface{}) { - andItemModel, err := resourceIbmSccRuleMapToRequiredConfigItemsRequiredConfigBase(andItem.(map[string]interface{})) - if err != nil { - return model, err - } - and = append(and, andItemModel) - } - model.And = and - } - return model, nil -} - -func resourceIbmSccRuleMapToRequiredConfigItemsRequiredConfigBase(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigBase, error) { - model := &securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigBase{} - if modelMap["description"] != nil && modelMap["description"].(string) != "" { - model.Description = core.StringPtr(modelMap["description"].(string)) - } - model.Property = core.StringPtr(modelMap["property"].(string)) - model.Operator = core.StringPtr(modelMap["operator"].(string)) - if modelMap["value"] != nil { - model.Value = modelMap["value"].(string) - } - return model, nil -} - -func resourceIbmSccRuleMapToRequiredConfigAnd(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigAnd, error) { - model := &securityandcompliancecenterapiv3.RequiredConfigRequiredConfigAnd{} - if modelMap["description"] != nil && modelMap["description"].(string) != "" { - model.Description = core.StringPtr(modelMap["description"].(string)) - } - if modelMap["and"] != nil { - and := []securityandcompliancecenterapiv3.RequiredConfigItemsIntf{} - for _, andItem := range modelMap["and"].([]interface{}) { - andItemModel, err := resourceIbmSccRuleMapToRequiredConfigItems(andItem.(map[string]interface{})) - if err != nil { - return model, err - } - and = append(and, andItemModel) - } - model.And = and - } - return model, nil -} - -func resourceIbmSccRuleMapToRequiredConfigOr(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigOr, error) { - model := &securityandcompliancecenterapiv3.RequiredConfigRequiredConfigOr{} - if modelMap["description"] != nil && modelMap["description"].(string) != "" { - model.Description = core.StringPtr(modelMap["description"].(string)) - } - if modelMap["or"] != nil { - or := []securityandcompliancecenterapiv3.RequiredConfigItemsIntf{} - for _, orItem := range modelMap["or"].([]interface{}) { - orItemModel, err := resourceIbmSccRuleMapToRequiredConfigItems(orItem.(map[string]interface{})) - if err != nil { - return model, err - } - or = append(or, orItemModel) - } - model.Or = or - } - return model, nil -} - -func resourceIbmSccRuleMapToRequiredConfigRequiredConfigBase(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase, error) { - model := &securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase{} - if modelMap["description"] != nil && modelMap["description"].(string) != "" { - model.Description = core.StringPtr(modelMap["description"].(string)) - } - model.Property = core.StringPtr(modelMap["property"].(string)) - model.Operator = core.StringPtr(modelMap["operator"].(string)) - if modelMap["value"] != nil { - model.Value = modelMap["value"].(string) - } - return model, nil -} - func resourceIbmSccRuleMapToImport(modelMap map[string]interface{}) (*securityandcompliancecenterapiv3.Import, error) { model := &securityandcompliancecenterapiv3.Import{} if modelMap["parameters"] != nil { @@ -1059,302 +545,3 @@ func resourceIbmSccRuleParameterToMap(model *securityandcompliancecenterapiv3.Pa } return modelMap, nil } - -func resourceIbmSccRuleTargetToMap(model *securityandcompliancecenterapiv3.Target) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - modelMap["service_name"] = model.ServiceName - if model.ServiceDisplayName != nil { - modelMap["service_display_name"] = model.ServiceDisplayName - } - modelMap["resource_kind"] = model.ResourceKind - if model.AdditionalTargetAttributes != nil { - additionalTargetAttributes := []map[string]interface{}{} - for _, additionalTargetAttributesItem := range model.AdditionalTargetAttributes { - additionalTargetAttributesItemMap, err := resourceIbmSccRuleAdditionalTargetAttributeToMap(&additionalTargetAttributesItem) - if err != nil { - return modelMap, err - } - additionalTargetAttributes = append(additionalTargetAttributes, additionalTargetAttributesItemMap) - } - modelMap["additional_target_attributes"] = additionalTargetAttributes - } - return modelMap, nil -} - -func resourceIbmSccRuleAdditionalTargetAttributeToMap(model *securityandcompliancecenterapiv3.AdditionalTargetAttribute) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Name != nil { - modelMap["name"] = model.Name - } - if model.Operator != nil { - modelMap["operator"] = model.Operator - } - if model.Value != nil { - modelMap["value"] = model.Value - } - return modelMap, nil -} - -func resourceIbmSccRuleRequiredConfigToMap(model securityandcompliancecenterapiv3.RequiredConfigIntf) (map[string]interface{}, error) { - if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigAnd); ok { - return resourceIbmSccRuleRequiredConfigAndToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigAnd)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigOr); ok { - return resourceIbmSccRuleRequiredConfigOrToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigOr)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase); ok { - return resourceIbmSccRuleRequiredConfigRequiredConfigBaseToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfig); ok { - modelMap := make(map[string]interface{}) - model := model.(*securityandcompliancecenterapiv3.RequiredConfig) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.And != nil { - and := []map[string]interface{}{} - for _, andItem := range model.And { - andItemMap, err := resourceIbmSccRuleRequiredConfigItemsToMap(andItem) - if err != nil { - return modelMap, err - } - and = append(and, andItemMap) - } - modelMap["and"] = and - } - if model.Or != nil { - or := []map[string]interface{}{} - for _, orItem := range model.Or { - orItemMap, err := resourceIbmSccRuleRequiredConfigItemsToMap(orItem) - if err != nil { - return modelMap, err - } - or = append(or, orItemMap) - } - modelMap["or"] = or - } - if model.Property != nil { - modelMap["property"] = model.Property - } - if model.Operator != nil { - modelMap["operator"] = model.Operator - } - // Manual Intervention - if model.Value != nil { - // model.Value is a schema.TypeString, so it needs to converted to String Type - switch v := model.Value.(type) { - case string: - modelMap["value"] = v - case []interface{}: - lst := []string{} - for _, val := range v { - vStr := "'" + val.(string) + "'" - lst = append(lst, vStr) - } - modelMap["value"] = "[" + strings.Join(lst, ",") + "]" - } - } - // End Manual Intervention - return modelMap, nil - } else { - return nil, fmt.Errorf("Unrecognized securityandcompliancecenterapiv3.RequiredConfigIntf subtype encountered") - } -} - -func resourceIbmSccRuleRequiredConfigItemsToMap(model securityandcompliancecenterapiv3.RequiredConfigItemsIntf) (map[string]interface{}, error) { - if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigOr); ok { - return resourceIbmSccRuleRequiredConfigItemsRequiredConfigOrDepth1ToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigOr)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigAnd); ok { - return resourceIbmSccRuleRequiredConfigItemsRequiredConfigAndDepth1ToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigAnd)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigBase); ok { - return resourceIbmSccRuleRequiredConfigItemsRequiredConfigBaseToMap(model.(*securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigBase)) - } else if _, ok := model.(*securityandcompliancecenterapiv3.RequiredConfigItems); ok { - modelMap := make(map[string]interface{}) - model := model.(*securityandcompliancecenterapiv3.RequiredConfigItems) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.Or != nil { - or := []map[string]interface{}{} - for _, orItem := range model.Or { - orItemMap, err := resourceIbmSccRuleRequiredConfigItemsToMap(orItem) - if err != nil { - return modelMap, err - } - or = append(or, orItemMap) - } - modelMap["or"] = or - } - if model.And != nil { - and := []map[string]interface{}{} - for _, andItem := range model.And { - andItemMap, err := resourceIbmSccRuleRequiredConfigItemsToMap(andItem) - if err != nil { - return modelMap, err - } - and = append(and, andItemMap) - } - modelMap["and"] = and - } - if model.Property != nil { - modelMap["property"] = model.Property - } - if model.Operator != nil { - modelMap["operator"] = model.Operator - } - // Manual Intervention - if model.Value != nil { - // modelMap["value"] = model.Value - switch v := model.Value.(type) { - case string: - modelMap["value"] = v - case []interface{}: - lst := []string{} - for _, val := range v { - vStr := val.(string) - lst = append(lst, vStr) - } - modelMap["value"] = strings.Join(lst, ",") - } - } - // End Manual Intervention - return modelMap, nil - } else { - return nil, fmt.Errorf("Unrecognized securityandcompliancecenterapiv3.RequiredConfigItemsIntf subtype encountered") - } -} - -func resourceIbmSccRuleRequiredConfigBaseToMap(model *securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigBase) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - modelMap["property"] = model.Property - modelMap["operator"] = model.Operator - if model.Value != nil { - modelMap["value"] = model.Value - } - return modelMap, nil -} - -func resourceIbmSccRuleRequiredConfigItemsRequiredConfigOrDepth1ToMap(model *securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigOr) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.Or != nil { - or := []map[string]interface{}{} - for _, orItem := range model.Or { - orItemMap, err := resourceIbmSccRuleRequiredConfigItemsToMap(orItem) - if err != nil { - return modelMap, err - } - or = append(or, orItemMap) - } - modelMap["or"] = or - } - return modelMap, nil -} - -func resourceIbmSccRuleRequiredConfigItemsRequiredConfigAndDepth1ToMap(model *securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigAnd) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.And != nil { - and := []map[string]interface{}{} - for _, andItem := range model.And { - andItemMap, err := resourceIbmSccRuleRequiredConfigItemsToMap(andItem) - if err != nil { - return modelMap, err - } - and = append(and, andItemMap) - } - modelMap["and"] = and - } - return modelMap, nil -} - -func resourceIbmSccRuleRequiredConfigItemsRequiredConfigBaseToMap(model *securityandcompliancecenterapiv3.RequiredConfigItemsRequiredConfigBase) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - modelMap["property"] = model.Property - modelMap["operator"] = model.Operator - if model.Value != nil { - // modelMap["value"] = model.Value - switch v := model.Value.(type) { - case string: - modelMap["value"] = v - case []string: - s := strings.Join(v, ",") - modelMap["value"] = s - default: - fmt.Printf("******** the type is %v\n", reflect.TypeOf(v)) - } - } - return modelMap, nil -} - -func resourceIbmSccRuleRequiredConfigAndToMap(model *securityandcompliancecenterapiv3.RequiredConfigRequiredConfigAnd) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.And != nil { - and := []map[string]interface{}{} - for _, andItem := range model.And { - andItemMap, err := resourceIbmSccRuleRequiredConfigItemsToMap(andItem) - if err != nil { - return modelMap, err - } - and = append(and, andItemMap) - } - modelMap["and"] = and - } - return modelMap, nil -} - -func resourceIbmSccRuleRequiredConfigOrToMap(model *securityandcompliancecenterapiv3.RequiredConfigRequiredConfigOr) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - if model.Or != nil { - or := []map[string]interface{}{} - for _, orItem := range model.Or { - orItemMap, err := resourceIbmSccRuleRequiredConfigItemsToMap(orItem) - if err != nil { - return modelMap, err - } - or = append(or, orItemMap) - } - modelMap["or"] = or - } - return modelMap, nil -} - -func resourceIbmSccRuleRequiredConfigRequiredConfigBaseToMap(model *securityandcompliancecenterapiv3.RequiredConfigRequiredConfigBase) (map[string]interface{}, error) { - modelMap := make(map[string]interface{}) - if model.Description != nil { - modelMap["description"] = model.Description - } - modelMap["property"] = model.Property - modelMap["operator"] = model.Operator - // Manual Intervention - if model.Value != nil { - // model.Value is a schema.TypeString, so it needs to converted to String Type - switch v := model.Value.(type) { - case string: - modelMap["value"] = v - case []interface{}: - lst := []string{} - for _, val := range v { - vStr := "'" + val.(string) + "'" - lst = append(lst, vStr) - } - modelMap["value"] = "[" + "'" + strings.Join(lst, ",") + "'" + "]" - } - } - // End Manual Intervention - - return modelMap, nil -} diff --git a/ibm/service/scc/resource_ibm_scc_rule_test.go b/ibm/service/scc/resource_ibm_scc_rule_test.go index d79a2b7bba..d8af238f04 100644 --- a/ibm/service/scc/resource_ibm_scc_rule_test.go +++ b/ibm/service/scc/resource_ibm_scc_rule_test.go @@ -61,6 +61,7 @@ func TestAccIbmSccRuleAllArgs(t *testing.T) { testAccCheckIbmSccRuleExists("ibm_scc_rule.scc_rule_instance", conf), resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "description", description), resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "version", version), + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "required_config.0.and.0.or.2.value", "[\"0.0.0.0/0\"]"), ), }, { @@ -79,6 +80,80 @@ func TestAccIbmSccRuleAllArgs(t *testing.T) { }) } +func TestAccIbmSccRuleSubRuleBasic(t *testing.T) { + var conf securityandcompliancecenterapiv3.Rule + description := fmt.Sprintf("tf_description_%d", acctest.RandIntRange(10, 100)) + version := fmt.Sprintf("0.0.%d", acctest.RandIntRange(10, 100)) + descriptionUpdate := fmt.Sprintf("tf_description_%d", acctest.RandIntRange(10, 100)) + versionUpdate := fmt.Sprintf("0.0.%d", acctest.RandIntRange(2, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckScc(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmSccRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIbmSccRuleConfigSubRule(acc.SccInstanceID, description, version), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmSccRuleExists("ibm_scc_rule.scc_rule_instance", conf), + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "description", description), + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "version", version), + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "required_config.0.or.1.any_if.0.required_config.0.value", "[\"us-south\",\"us-east\"]"), + ), + }, + { + Config: testAccCheckIbmSccRuleConfigSubRule(acc.SccInstanceID, descriptionUpdate, versionUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "description", descriptionUpdate), + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "version", versionUpdate), + ), + }, + { + ResourceName: "ibm_scc_rule.scc_rule_instance", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccIbmSccRuleWithNumberRC(t *testing.T) { + var conf securityandcompliancecenterapiv3.Rule + description := fmt.Sprintf("tf_description_%d", acctest.RandIntRange(10, 100)) + version := fmt.Sprintf("0.0.%d", acctest.RandIntRange(1, 10)) + descriptionUpdate := fmt.Sprintf("tf_description_%d", acctest.RandIntRange(10, 100)) + versionUpdate := fmt.Sprintf("0.0.%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheckScc(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmSccRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIbmSccRuleConfigNumVal(acc.SccInstanceID, description, version), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmSccRuleExists("ibm_scc_rule.scc_rule_instance", conf), + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "description", description), + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "version", version), + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "required_config.0.and.0.value", "0"), + ), + }, + { + Config: testAccCheckIbmSccRuleConfigNumVal(acc.SccInstanceID, descriptionUpdate, versionUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "description", descriptionUpdate), + resource.TestCheckResourceAttr("ibm_scc_rule.scc_rule_instance", "version", versionUpdate), + ), + }, + { + ResourceName: "ibm_scc_rule.scc_rule_instance", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckIbmSccRuleConfigBasic(instanceID string, description string) string { return fmt.Sprintf(` resource "ibm_scc_rule" "scc_rule_instance" { @@ -116,7 +191,6 @@ func testAccCheckIbmSccRuleConfigBasic(instanceID string, description string) st func testAccCheckIbmSccRuleConfig(instanceID string, description string, version string) string { return fmt.Sprintf(` - resource "ibm_scc_rule" "scc_rule_instance" { instance_id = "%s" description = "%s" @@ -141,17 +215,102 @@ func testAccCheckIbmSccRuleConfig(instanceID string, description string, version required_config { and { or { - description = "description" + description = "description 1" property = "storage_class" operator = "string_equals" value = "smart" } or { - description = "description" + description = "description 2" property = "storage_class" operator = "string_equals" value = "cold" } + or { + description = "description 3" + property = "firewall.allowed_ip" + operator = "ips_equals" + value = jsonencode(["0.0.0.0/0"]) + } + } + } + labels = ["FIXME"] + } + `, instanceID, description, version) +} + +func testAccCheckIbmSccRuleConfigNumVal(instanceID string, description string, version string) string { + return fmt.Sprintf(` + resource "ibm_scc_rule" "scc_rule_instance" { + instance_id = "%s" + description = "%s" + version = "%s" + target { + service_name = "is.load-balancer" + resource_kind = "instance" + additional_target_attributes { + name = "profile_family" + operator = "string_equals" + value = "application" + } + } + required_config { + and { + property = "app_lb_pools_with_multiple_members_count" + operator = "num_not_equals" + value = "0" + } + and { + property = "app_lb_pools_without_multiple_members_count" + operator = "num_not_equals" + value = "0" + } + } + labels = ["FIXME"] + } + `, instanceID, description, version) +} + +func testAccCheckIbmSccRuleConfigSubRule(instanceID string, description string, version string) string { + return fmt.Sprintf(` + + resource "ibm_scc_rule" "scc_rule_instance" { + instance_id = "%s" + description = "%s" + version = "%s" + target { + service_name = "atracker" + resource_kind = "target" + reference_name = "this-target" + additional_target_attributes { + name = "type" + operator = "string_equals" + value = "cloud_object_storage" + } + } + required_config { + or { + property = "route_attached" + operator = "is_false" + + } + or { + any_if { + target { + service_name = "cloud-object-storage" + resource_kind = "bucket" + additional_target_attributes { + name = "location" + operator = "strings_in_list" + value = "$${this-target}.bucket_name" + } + } + required_config { + property = "location" + operator = "strings_in_list" + value = jsonencode(["us-south","us-east"]) + } + } } } labels = ["FIXME"] diff --git a/ibm/service/secretsmanager/data_source_ibm_sm_configurations.go b/ibm/service/secretsmanager/data_source_ibm_sm_configurations.go index 910c861998..8b950a1d17 100644 --- a/ibm/service/secretsmanager/data_source_ibm_sm_configurations.go +++ b/ibm/service/secretsmanager/data_source_ibm_sm_configurations.go @@ -36,6 +36,12 @@ func DataSourceIbmSmConfigurations() *schema.Resource { Optional: true, Description: "Filter secrets by groups. You can apply multiple filters by using a comma-separated list of secret group IDs. If you need to filter secrets that are in the default secret group, use the `default` keyword.", }, + "secret_types": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "Filter secrets by secret types.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, "total_count": &schema.Schema{ Type: schema.TypeInt, Computed: true, @@ -132,6 +138,59 @@ func DataSourceIbmSmConfigurations() *schema.Resource { Computed: true, Description: "The name of the intermediate certificate authority.", }, + "crypto_key": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The data that is associated with a cryptographic key.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified.", + }, + "label": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified.", + }, + "allow_generate_key": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "The indication of whether a new key is generated by the crypto provider if the given key name cannot be found.", + }, + "provider": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The data that is associated with a cryptographic provider.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type of cryptographic provider.", + }, + "instance_crn": &schema.Schema{ + Description: "The HPCS instance CRN.", + Computed: true, + Type: schema.TypeString, + }, + "pin_iam_credentials_secret_id": &schema.Schema{ + Description: "The secret Id of iam credentials with api key to access HPCS instance.", + Computed: true, + Type: schema.TypeString, + }, + "private_keystore_id": &schema.Schema{ + Description: "The HPCS private key store space id.", + Computed: true, + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, }, }, }, @@ -160,6 +219,14 @@ func dataSourceIbmSmConfigurationsRead(context context.Context, d *schema.Resour searchStr := search.(string) listConfigurationsOptions.SetSearch(searchStr) } + if _, ok := d.GetOk("secret_types"); ok { + secretTypes := d.Get("secret_types").([]interface{}) + parsedTypes := make([]string, len(secretTypes)) + for i, v := range secretTypes { + parsedTypes[i] = fmt.Sprint(v) + } + listConfigurationsOptions.SetSecretTypes(parsedTypes) + } var pager *secretsmanagerv2.ConfigurationsPager pager, err = secretsManagerClient.NewConfigurationsPager(listConfigurationsOptions) @@ -268,6 +335,7 @@ func dataSourceIbmSmConfigurationsConfigurationMetadataToMap(model secretsmanage if model.CertificateAuthority != nil { modelMap["certificate_authority"] = *model.CertificateAuthority } + return modelMap, nil } else { return nil, fmt.Errorf("Unrecognized secretsmanagerv2.ConfigurationMetadataIntf subtype encountered") @@ -318,6 +386,13 @@ func dataSourceIbmSmConfigurationsPrivateCertificateConfigurationIntermediateCAM if model.SigningMethod != nil { modelMap["signing_method"] = *model.SigningMethod } + if model.CryptoKey != nil { + cryptoModelMap, err := resourceIbmSmPrivateCertificateConfigurationCryptoKeyToMap(model.CryptoKey) + if err != nil { + return modelMap, err + } + modelMap["crypto_key"] = []map[string]interface{}{cryptoModelMap} + } return modelMap, nil } @@ -382,6 +457,13 @@ func dataSourceIbmSmConfigurationsPrivateCertificateConfigurationRootCAMetadataT if model.Status != nil { modelMap["status"] = *model.Status } + if model.CryptoKey != nil { + cryptoModelMap, err := resourceIbmSmPrivateCertificateConfigurationCryptoKeyToMap(model.CryptoKey) + if err != nil { + return modelMap, err + } + modelMap["crypto_key"] = []map[string]interface{}{cryptoModelMap} + } return modelMap, nil } diff --git a/ibm/service/secretsmanager/data_source_ibm_sm_configurations_test.go b/ibm/service/secretsmanager/data_source_ibm_sm_configurations_test.go index 34698d82b3..1b7b23c688 100644 --- a/ibm/service/secretsmanager/data_source_ibm_sm_configurations_test.go +++ b/ibm/service/secretsmanager/data_source_ibm_sm_configurations_test.go @@ -27,6 +27,22 @@ func TestAccIbmSmConfigurationsDataSourceBasic(t *testing.T) { }) } +func TestAccIbmSmConfigurationsDataSourceCryptoKey(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmSmConfigurationsDataSourceConfigCryptoKey(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_sm_configurations.sm_configurations", "id"), + resource.TestCheckResourceAttrSet("data.ibm_sm_configurations.sm_configurations", "configurations.#"), + ), + }, + }, + }) +} + func testAccCheckIbmSmConfigurationsDataSourceConfigBasic() string { return fmt.Sprintf(` resource "ibm_sm_iam_credentials_configuration" "sm_iam_credentials_configuration_instance" { @@ -83,3 +99,12 @@ func testAccCheckIbmSmConfigurationsDataSourceConfigBasic() string { acc.SecretsManagerPublicCertificateClassicInfrastructureUsername, acc.SecretsManagerPublicCertificateClassicInfrastructurePassword, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion) } + +func testAccCheckIbmSmConfigurationsDataSourceConfigCryptoKey() string { + return privateCertificateIntermediateCAConfigCryptoKey() + fmt.Sprintf(` + data "ibm_sm_configurations" "sm_configurations" { + instance_id = "%s" + region = "%s" + } + `, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion) +} diff --git a/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_intermediate_ca.go b/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_intermediate_ca.go index 682e627829..43c50c46a8 100644 --- a/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_intermediate_ca.go +++ b/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_intermediate_ca.go @@ -198,6 +198,59 @@ func DataSourceIbmSmPrivateCertificateConfigurationIntermediateCA() *schema.Reso Computed: true, Description: "The date a secret is expired. The date format follows RFC 3339.", }, + "crypto_key": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The data that is associated with a cryptographic key.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified.", + }, + "label": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified.", + }, + "allow_generate_key": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "The indication of whether a new key is generated by the crypto provider if the given key name cannot be found.", + }, + "provider": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The data that is associated with a cryptographic provider.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type of cryptographic provider.", + }, + "instance_crn": &schema.Schema{ + Description: "The HPCS instance CRN.", + Computed: true, + Type: schema.TypeString, + }, + "pin_iam_credentials_secret_id": &schema.Schema{ + Description: "The secret Id of iam credentials with api key to access HPCS instance.", + Computed: true, + Type: schema.TypeString, + }, + "private_keystore_id": &schema.Schema{ + Description: "The HPCS private key store space id.", + Computed: true, + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, "data": &schema.Schema{ Type: schema.TypeList, Computed: true, @@ -360,6 +413,18 @@ func dataSourceIbmSmPrivateCertificateConfigurationIntermediateCARead(context co return diag.FromErr(fmt.Errorf("Error setting expiration_date: %s", err)) } + if privateCertificateConfigurationIntermediateCA.CryptoKey != nil { + cryptoKeyMap, err := resourceIbmSmPrivateCertificateConfigurationCryptoKeyToMap(privateCertificateConfigurationIntermediateCA.CryptoKey) + if err != nil { + return diag.FromErr(err) + } + if len(cryptoKeyMap) > 0 { + if err = d.Set("crypto_key", []map[string]interface{}{cryptoKeyMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting crypto_key: %s", err)) + } + } + } + data := []map[string]interface{}{} if privateCertificateConfigurationIntermediateCA.Data != nil { modelMap, err := dataSourceIbmSmPrivateCertificateConfigurationIntermediateCAPrivateCertificateCADataToMap(privateCertificateConfigurationIntermediateCA.Data) diff --git a/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_intermediate_ca_test.go b/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_intermediate_ca_test.go index 9115c848a2..e347ec2d13 100644 --- a/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_intermediate_ca_test.go +++ b/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_intermediate_ca_test.go @@ -35,6 +35,30 @@ func TestAccIbmSmPrivateCertificateConfigurationIntermediateCADataSourceBasic(t }) } +func TestAccIbmSmPrivateCertificateConfigurationIntermediateCADataSourceCryptoKey(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmSmPrivateCertificateConfigurationIntermediateCADataSourceConfigCryptoKey(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "id"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "name"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "config_type"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "secret_type"), + //resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "created_by"), + //resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "created_at"), + //resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "updated_at"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "signing_method"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "common_name"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_certificate_configuration_intermediate_ca_crypto_key", "crypto_key.#"), + ), + }, + }, + }) +} + func testAccCheckIbmSmPrivateCertificateConfigurationIntermediateCADataSourceConfigBasic() string { return fmt.Sprintf(` resource "ibm_sm_private_certificate_configuration_root_ca" "ibm_sm_private_certificate_configuration_root_ca_instance" { @@ -62,3 +86,12 @@ func testAccCheckIbmSmPrivateCertificateConfigurationIntermediateCADataSourceCon } `, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion) } + +func testAccCheckIbmSmPrivateCertificateConfigurationIntermediateCADataSourceConfigCryptoKey() string { + return privateCertificateIntermediateCAConfigCryptoKey() + fmt.Sprintf(` + data "ibm_sm_private_certificate_configuration_intermediate_ca" "sm_private_certificate_configuration_intermediate_ca_crypto_key" { + instance_id = "%s" + region = "%s" + name = ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_cert_intermediate_ca_crypto_key.name + }`, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion) +} diff --git a/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_root_ca.go b/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_root_ca.go index 29f119c593..68a90a5690 100644 --- a/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_root_ca.go +++ b/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_root_ca.go @@ -221,6 +221,59 @@ func DataSourceIbmSmPrivateCertificateConfigurationRootCA() *schema.Resource { Computed: true, Description: "The date a secret is expired. The date format follows RFC 3339.", }, + "crypto_key": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The data that is associated with a cryptographic key.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified.", + }, + "label": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified.", + }, + "allow_generate_key": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "The indication of whether a new key is generated by the crypto provider if the given key name cannot be found.", + }, + "provider": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The data that is associated with a cryptographic provider.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type of cryptographic provider.", + }, + "instance_crn": &schema.Schema{ + Description: "The HPCS instance CRN.", + Computed: true, + Type: schema.TypeString, + }, + "pin_iam_credentials_secret_id": &schema.Schema{ + Description: "The secret Id of iam credentials with api key to access HPCS instance.", + Computed: true, + Type: schema.TypeString, + }, + "private_keystore_id": &schema.Schema{ + Description: "The HPCS private key store space id.", + Computed: true, + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, "data": &schema.Schema{ Type: schema.TypeList, Computed: true, @@ -446,6 +499,18 @@ func dataSourceIbmSmPrivateCertificateConfigurationRootCARead(context context.Co return diag.FromErr(fmt.Errorf("Error setting expiration_date: %s", err)) } + if privateCertificateConfigurationRootCA.CryptoKey != nil { + cryptoKeyMap, err := resourceIbmSmPrivateCertificateConfigurationCryptoKeyToMap(privateCertificateConfigurationRootCA.CryptoKey) + if err != nil { + return diag.FromErr(err) + } + if len(cryptoKeyMap) > 0 { + if err = d.Set("crypto_key", []map[string]interface{}{cryptoKeyMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting crypto_key: %s", err)) + } + } + } + if privateCertificateConfigurationRootCA.Data != nil { dataMap, err := dataSourceIbmSmPrivateCertificateConfigurationRootCAPrivateCertificateCADataToMap(privateCertificateConfigurationRootCA.Data) if err != nil { diff --git a/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_root_ca_test.go b/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_root_ca_test.go index 2a1ad944da..a2b2dfe0af 100644 --- a/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_root_ca_test.go +++ b/ibm/service/secretsmanager/data_source_ibm_sm_private_certificate_configuration_root_ca_test.go @@ -34,6 +34,29 @@ func TestAccIbmSmPrivateCertificateConfigurationRootCADataSourceBasic(t *testing }) } +func TestAccIbmSmPrivateCertificateConfigurationRootCADataSourceCryptoKey(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIbmSmPrivateCertificateConfigurationRootCADataSourceConfigCryptoKey(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_root_ca.sm_private_certificate_configuration_root_ca_crypto_key", "id"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_root_ca.sm_private_certificate_configuration_root_ca_crypto_key", "name"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_root_ca.sm_private_certificate_configuration_root_ca_crypto_key", "config_type"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_root_ca.sm_private_certificate_configuration_root_ca_crypto_key", "secret_type"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_root_ca.sm_private_certificate_configuration_root_ca_crypto_key", "created_by"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_root_ca.sm_private_certificate_configuration_root_ca_crypto_key", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_root_ca.sm_private_certificate_configuration_root_ca_crypto_key", "updated_at"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_root_ca.sm_private_certificate_configuration_root_ca_crypto_key", "common_name"), + resource.TestCheckResourceAttrSet("data.ibm_sm_private_certificate_configuration_root_ca.sm_private_certificate_configuration_root_ca_crypto_key", "crypto_key.#"), + ), + }, + }, + }) +} + func testAccCheckIbmSmPrivateCertificateConfigurationRootCADataSourceConfigBasic() string { return fmt.Sprintf(` resource "ibm_sm_private_certificate_configuration_root_ca" "ibm_sm_private_certificate_configuration_root_ca_instance" { @@ -52,3 +75,13 @@ func testAccCheckIbmSmPrivateCertificateConfigurationRootCADataSourceConfigBasic } `, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion) } + +func testAccCheckIbmSmPrivateCertificateConfigurationRootCADataSourceConfigCryptoKey() string { + return privateCertificateRootCAConfigCryptoKey() + fmt.Sprintf(` + data "ibm_sm_private_certificate_configuration_root_ca" "sm_private_certificate_configuration_root_ca_crypto_key" { + instance_id = "%s" + region = "%s" + name = ibm_sm_private_certificate_configuration_root_ca.sm_private_cert_root_ca_crypto_key.name + }`, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion) + +} diff --git a/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_intermediate_ca.go b/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_intermediate_ca.go index 221f227363..e82d66747c 100644 --- a/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_intermediate_ca.go +++ b/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_intermediate_ca.go @@ -235,6 +235,78 @@ func ResourceIbmSmPrivateCertificateConfigurationIntermediateCA() *schema.Resour Computed: true, Description: "The date a secret is expired. The date format follows RFC 3339.", }, + "crypto_key": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "The data that is associated with a cryptographic key.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified.", + }, + "label": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified.", + }, + "allow_generate_key": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The indication of whether a new key is generated by the crypto provider if the given key name cannot be found.", + }, + "provider": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: "The data that is associated with a cryptographic provider.", + MaxItems: 1, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The type of cryptographic provider.", + }, + "instance_crn": &schema.Schema{ + Description: "The HPCS instance CRN.", + Optional: true, + Computed: true, + ForceNew: true, + Type: schema.TypeString, + }, + "pin_iam_credentials_secret_id": &schema.Schema{ + Description: "The secret Id of iam credentials with api key to access HPCS instance.", + Optional: true, + Computed: true, + ForceNew: true, + Type: schema.TypeString, + }, + "private_keystore_id": &schema.Schema{ + Description: "The HPCS private key store space id.", + Optional: true, + Computed: true, + ForceNew: true, + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, "data": &schema.Schema{ Type: schema.TypeList, Computed: true, @@ -529,10 +601,62 @@ func resourceIbmSmPrivateCertificateConfigurationIntermediateCARead(context cont return diag.FromErr(fmt.Errorf("Error setting data: %s", err)) } } - + if configuration.CryptoKey != nil { + cryptoKeyMap, err := resourceIbmSmPrivateCertificateConfigurationCryptoKeyToMap(configuration.CryptoKey) + if err != nil { + return diag.FromErr(err) + } + if len(cryptoKeyMap) > 0 { + if err = d.Set("crypto_key", []map[string]interface{}{cryptoKeyMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting crypto_key: %s", err)) + } + } + } return nil } +func resourceIbmSmPrivateCertificateConfigurationCryptoKeyToMap(model *secretsmanagerv2.PrivateCertificateCryptoKey) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.ID != nil { + modelMap["id"] = model.ID + } + if model.Label != nil { + modelMap["label"] = model.Label + } + if model.AllowGenerateKey != nil { + modelMap["allow_generate_key"] = model.AllowGenerateKey + } + if model.Provider != nil { + providerModelMap, err := resourceIbmSmPrivateCertificateConfigurationCryptoKeyProviderToMap(model.Provider) + if err != nil { + return modelMap, err + } + modelMap["provider"] = []map[string]interface{}{providerModelMap} + } + + return modelMap, nil +} + +func resourceIbmSmPrivateCertificateConfigurationCryptoKeyProviderToMap(providerModelIntf secretsmanagerv2.PrivateCertificateCryptoProviderIntf) (map[string]interface{}, error) { + providerModelMap := make(map[string]interface{}) + providerModel := providerModelIntf.(*secretsmanagerv2.PrivateCertificateCryptoProviderHPCS) + + if providerModel.Type != nil { + providerModelMap["type"] = providerModel.Type + } + if providerModel.InstanceCrn != nil { + providerModelMap["instance_crn"] = providerModel.InstanceCrn + } + if providerModel.PinIamCredentialsSecretID != nil { + providerModelMap["pin_iam_credentials_secret_id"] = providerModel.PinIamCredentialsSecretID + } + if providerModel.PrivateKeystoreID != nil { + providerModelMap["private_keystore_id"] = providerModel.PrivateKeystoreID + } + + return providerModelMap, nil +} + func resourceIbmSmPrivateCertificateConfigurationIntermediateCAUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { secretsManagerClient, err := meta.(conns.ClientSession).SecretsManagerV2() if err != nil { @@ -737,9 +861,58 @@ func resourceIbmSmPrivateCertificateConfigurationIntermediateCAMapToConfiguratio } model.PostalCode = postalCode } + if _, ok := d.GetOk("crypto_key"); ok { + if len(d.Get("crypto_key").([]interface{})) > 0 { + CryptoKeyModel, err := resourceIbmSmPrivateCertificateConfigurationMapToPrivateCertificateConfigurationCryptoKey(d.Get("crypto_key").([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.CryptoKey = CryptoKeyModel + } + } return model, nil } +func resourceIbmSmPrivateCertificateConfigurationMapToPrivateCertificateConfigurationCryptoKey(modelMap map[string]interface{}) (*secretsmanagerv2.PrivateCertificateCryptoKey, error) { + model := &secretsmanagerv2.PrivateCertificateCryptoKey{} + if modelMap["id"] != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["label"] != "" { + model.Label = core.StringPtr(modelMap["label"].(string)) + } + if modelMap["allow_generate_key"] != nil { + model.AllowGenerateKey = core.BoolPtr(modelMap["allow_generate_key"].(bool)) + } + if modelMap["provider"] != nil && len(modelMap["provider"].([]interface{})) > 0 { + providerModel, err := resourceIbmSmPrivateCertificateConfigurationMapToPrivateCertificateConfigurationCryptoKeyProvider(modelMap["provider"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Provider = providerModel + } + + return model, nil +} + +func resourceIbmSmPrivateCertificateConfigurationMapToPrivateCertificateConfigurationCryptoKeyProvider(modelMapProvider map[string]interface{}) (secretsmanagerv2.PrivateCertificateCryptoProviderIntf, error) { + modelProvider := &secretsmanagerv2.PrivateCertificateCryptoProviderHPCS{} + if modelMapProvider["type"] != "" { + modelProvider.Type = core.StringPtr(modelMapProvider["type"].(string)) + } + if modelMapProvider["instance_crn"] != "" { + modelProvider.InstanceCrn = core.StringPtr(modelMapProvider["instance_crn"].(string)) + } + if modelMapProvider["pin_iam_credentials_secret_id"] != "" { + modelProvider.PinIamCredentialsSecretID = core.StringPtr(modelMapProvider["pin_iam_credentials_secret_id"].(string)) + } + if modelMapProvider["private_keystore_id"] != "" { + modelProvider.PrivateKeystoreID = core.StringPtr(modelMapProvider["private_keystore_id"].(string)) + } + + return modelProvider, nil +} + func resourceIbmSmPrivateCertificateConfigurationIntermediateCAPrivateCertificateCADataToMap(modelIntf secretsmanagerv2.PrivateCertificateCADataIntf) (map[string]interface{}, error) { modelMap := make(map[string]interface{}) model := modelIntf.(*secretsmanagerv2.PrivateCertificateCAData) diff --git a/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_intermediate_ca_test.go b/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_intermediate_ca_test.go index 198899427c..0983c1c3e0 100644 --- a/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_intermediate_ca_test.go +++ b/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_intermediate_ca_test.go @@ -76,6 +76,31 @@ func TestAccIbmSmPrivateCertificateConfigurationIntermediateCAllArgs(t *testing. }) } +func TestAccIbmSmPrivateCertificateConfigurationIntermediateCACryptoKey(t *testing.T) { + resourceName := "ibm_sm_private_certificate_configuration_intermediate_ca.sm_private_cert_intermediate_ca_crypto_key" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmSmPrivateCertificateConfigurationIntermediateCADestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: privateCertificateIntermediateCAConfigCryptoKey(), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmSmPrivateCertificateConfigurationIntermediateCAExists(resourceName, 94680000., 259200, false, true, true), + ), + }, + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"crl_expiry", "max_ttl", "max_path_length", + "permitted_dns_domains", "ttl", "use_csr_values"}, + }, + }, + }) +} + func rootCaConfig() string { return fmt.Sprintf(` @@ -142,6 +167,39 @@ func privateCertificateIntermediateCAConfigAllArgs(maxTtl, crlExpiry, crlDisable crlDistributionPointsEncoded, issuingCertificatesUrlsEncoded) } +func privateCertificateIntermediateCAConfigCryptoKey() string { + return privateCertificateRootCAConfigCryptoKey() + fmt.Sprintf(` + resource "ibm_sm_private_certificate_configuration_intermediate_ca" "sm_private_cert_intermediate_ca_crypto_key" { + depends_on = [ibm_sm_private_certificate_configuration_root_ca.sm_private_cert_root_ca_crypto_key] + instance_id = "%s" + region = "%s" + name = "intermediate-ca-terraform-private-cert-test" + max_ttl = "26300h" + ttl = "2190h" + issuing_certificates_urls_encoded = true + crl_distribution_points_encoded = true + crl_disable = false + key_type = "rsa" + key_bits = 4096 + signing_method = "internal" + issuer = ibm_sm_private_certificate_configuration_root_ca.sm_private_cert_root_ca_crypto_key.name + common_name = "ibm.com" + crypto_key { + allow_generate_key = true + label = "tf_test" + provider { + type = "%s" + instance_crn = "%s" + pin_iam_credentials_secret_id = ibm_sm_iam_credentials_secret.sm_iam_credentials_secret_instance_crypto_key.secret_id + private_keystore_id = "%s" + } + } + }`, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion, + acc.SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderType, + acc.SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderInstanceCrn, + acc.SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderPrivateKeystoreId) +} + func testAccCheckIbmSmPrivateCertificateConfigurationIntermediateCAExists(resourceName string, maxTtl, crlExpiry int, crlDisable, crlDistributionPointsEncoded, issuingCertificatesUrlsEncoded bool) resource.TestCheckFunc { diff --git a/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_root_ca.go b/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_root_ca.go index 88f3e2a823..e51d97856c 100644 --- a/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_root_ca.go +++ b/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_root_ca.go @@ -219,6 +219,78 @@ func ResourceIbmSmPrivateCertificateConfigurationRootCA() *schema.Resource { Description: "The postal code values to define in the subject field of the resulting certificate.", Elem: &schema.Schema{Type: schema.TypeString}, }, + "crypto_key": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "The data that is associated with a cryptographic key.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified.", + }, + "label": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified.", + }, + "allow_generate_key": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The indication of whether a new key is generated by the crypto provider if the given key name cannot be found.", + }, + "provider": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: "The data that is associated with a cryptographic provider.", + MaxItems: 1, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The type of cryptographic provider.", + }, + "instance_crn": &schema.Schema{ + Description: "The HPCS instance CRN.", + Optional: true, + Computed: true, + ForceNew: true, + Type: schema.TypeString, + }, + "pin_iam_credentials_secret_id": &schema.Schema{ + Description: "The secret Id of iam credentials with api key to access HPCS instance.", + Optional: true, + Computed: true, + ForceNew: true, + Type: schema.TypeString, + }, + "private_keystore_id": &schema.Schema{ + Description: "The HPCS private key store space id.", + Optional: true, + Computed: true, + ForceNew: true, + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, "serial_number": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -525,6 +597,17 @@ func resourceIbmSmPrivateCertificateConfigurationRootCARead(context context.Cont return diag.FromErr(fmt.Errorf("Error setting data: %s", err)) } } + if configuration.CryptoKey != nil { + cryptoKeyMap, err := resourceIbmSmPrivateCertificateConfigurationCryptoKeyToMap(configuration.CryptoKey) + if err != nil { + return diag.FromErr(err) + } + if len(cryptoKeyMap) > 0 { + if err = d.Set("crypto_key", []map[string]interface{}{cryptoKeyMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting crypto_key: %s", err)) + } + } + } return nil } @@ -741,7 +824,15 @@ func resourceIbmSmPrivateCertificateConfigurationRootCAMapToConfigurationPrototy } model.PostalCode = postalCodeParsed } - + if _, ok := d.GetOk("crypto_key"); ok { + if len(d.Get("crypto_key").([]interface{})) > 0 { + CryptoKeyModel, err := resourceIbmSmPrivateCertificateConfigurationMapToPrivateCertificateConfigurationCryptoKey(d.Get("crypto_key").([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.CryptoKey = CryptoKeyModel + } + } return model, nil } diff --git a/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_root_ca_test.go b/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_root_ca_test.go index f0ce03db80..7d3d10de13 100644 --- a/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_root_ca_test.go +++ b/ibm/service/secretsmanager/resource_ibm_sm_private_certificate_configuration_root_ca_test.go @@ -79,6 +79,30 @@ func TestAccIbmSmPrivateCertificateConfigurationRootCAllArgs(t *testing.T) { }) } +func TestAccIbmSmPrivateCertificateConfigurationRootCACryptoKey(t *testing.T) { + resourceName := "ibm_sm_private_certificate_configuration_root_ca.sm_private_cert_root_ca_crypto_key" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmSmPrivateCertificateConfigurationRootCADestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: privateCertificateRootCAConfigCryptoKey(), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmSmPrivateCertificateConfigurationRootCAExists(resourceName, 157788000, 259200, false, true, true), + ), + }, + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"crl_expiry", "max_ttl", "ttl"}, + }, + }, + }) +} + var rootCaBasicConfigFormat = ` resource "ibm_sm_private_certificate_configuration_root_ca" "sm_private_cert_root_ca_basic" { instance_id = "%s" @@ -120,6 +144,60 @@ var rootCaFullConfigFormat = ` postal_code = ["12345"] }` +func iamCredentialsSecretConfigCryptoKey() string { + return fmt.Sprintf(` + resource "ibm_sm_iam_credentials_secret" "sm_iam_credentials_secret_instance_crypto_key" { + instance_id = "%s" + region = "%s" + name = "iam-credentials-for-crypto-key-terraform-tests" + service_id = "%s" + reuse_api_key = true + ttl = "259200" + rotation { + auto_rotate = true + interval = 1 + unit = "day" + } + depends_on = [ + ibm_sm_iam_credentials_configuration.sm_iam_credentials_configuration_instance + ] + }`, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion, + acc.SecretsManagerPrivateCertificateConfigurationCryptoKeyIAMSecretServiceId) +} + +func privateCertificateRootCAConfigCryptoKey() string { + return iamCredentialsEngineConfig() + iamCredentialsSecretConfigCryptoKey() + fmt.Sprintf(` + resource "ibm_sm_private_certificate_configuration_root_ca" "sm_private_cert_root_ca_crypto_key" { + depends_on = [ibm_sm_iam_credentials_secret.sm_iam_credentials_secret_instance_crypto_key] + instance_id = "%s" + region = "%s" + name = "root-ca-terraform-private-cert-test" + max_ttl = "43830h" + ttl = "2190h" + crl_disable = false + crl_expiry = "72h" + crl_distribution_points_encoded = true + issuing_certificates_urls_encoded = true + key_type = "rsa" + key_bits = 4096 + common_name = "ibm.com" + alt_names = ["ddd.com", "aaa.com"] + crypto_key { + allow_generate_key = true + label = "tf_test" + provider { + type = "%s" + instance_crn = "%s" + pin_iam_credentials_secret_id = ibm_sm_iam_credentials_secret.sm_iam_credentials_secret_instance_crypto_key.secret_id + private_keystore_id = "%s" + } + } + }`, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion, + acc.SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderType, + acc.SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderInstanceCrn, + acc.SecretsManagerPrivateCertificateConfigurationCryptoKeyProviderPrivateKeystoreId) +} + func privateCertificateRootCAConfigBasic() string { return fmt.Sprintf(rootCaBasicConfigFormat, acc.SecretsManagerInstanceID, acc.SecretsManagerInstanceRegion) } diff --git a/ibm/service/vpc/data_source_ibm_is_bare_metal_server.go b/ibm/service/vpc/data_source_ibm_is_bare_metal_server.go index 61bf02c0fb..87bc367cfa 100644 --- a/ibm/service/vpc/data_source_ibm_is_bare_metal_server.go +++ b/ibm/service/vpc/data_source_ibm_is_bare_metal_server.go @@ -382,6 +382,40 @@ func DataSourceIBMIsBareMetalServer() *schema.Resource { }, }, }, + "virtual_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The virtual network interface for this bare metal server network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this virtual network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this virtual network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, }, }, @@ -592,6 +626,40 @@ func DataSourceIBMIsBareMetalServer() *schema.Resource { }, }, }, + "virtual_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The virtual network interface for this bare metal server network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this virtual network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this virtual network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, }, }, @@ -609,6 +677,11 @@ func DataSourceIBMIsBareMetalServer() *schema.Resource { Computed: true, Description: "image name", }, + isBareMetalServerFirmwareUpdateTypeAvailable: { + Type: schema.TypeString, + Computed: true, + Description: "The type of firmware update available", + }, isBareMetalServerProfile: { Type: schema.TypeString, Computed: true, @@ -817,6 +890,11 @@ func dataSourceIBMISBareMetalServerRead(context context.Context, d *schema.Resou if err = d.Set("identifier", *bms.ID); err != nil { return diag.FromErr(fmt.Errorf("[ERROR] Error setting identifier: %s", err)) } + if bms.Firmware != nil && bms.Firmware.Update != nil { + if err = d.Set(isBareMetalServerFirmwareUpdateTypeAvailable, *bms.Firmware.Update); err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error setting availble firmware update type: %s", err)) + } + } //enable secure boot if err = d.Set(isBareMetalServerEnableSecureBoot, bms.EnableSecureBoot); err != nil { @@ -1109,6 +1187,21 @@ func dataSourceIBMIsBareMetalServerBareMetalServerNetworkAttachmentReferenceToMa return modelMap, err } modelMap["subnet"] = []map[string]interface{}{subnetMap} + virtualNetworkInterfaceMap, err := dataSourceIBMIsBareMetalServerVirtualNetworkInterfaceReferenceAttachmentContextToMap(model.VirtualNetworkInterface) + if err != nil { + return modelMap, err + } + modelMap["virtual_network_interface"] = []map[string]interface{}{virtualNetworkInterfaceMap} + return modelMap, nil +} + +func dataSourceIBMIsBareMetalServerVirtualNetworkInterfaceReferenceAttachmentContextToMap(model *vpcv1.VirtualNetworkInterfaceReferenceAttachmentContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = model.CRN + modelMap["href"] = model.Href + modelMap["id"] = model.ID + modelMap["name"] = model.Name + modelMap["resource_type"] = model.ResourceType return modelMap, nil } diff --git a/ibm/service/vpc/data_source_ibm_is_bare_metal_server_test.go b/ibm/service/vpc/data_source_ibm_is_bare_metal_server_test.go index 6b7ae253ce..469bbf108f 100644 --- a/ibm/service/vpc/data_source_ibm_is_bare_metal_server_test.go +++ b/ibm/service/vpc/data_source_ibm_is_bare_metal_server_test.go @@ -50,6 +50,34 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE }, }) } + +func TestAccIBMISBMSDataSource_firmwareUpdate(t *testing.T) { + var server string + resName := "data.ibm_is_bare_metal_server.test1" + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf-server-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tfip-subnet-%d", acctest.RandIntRange(10, 100)) + publicKey := strings.TrimSpace(` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR +`) + sshname := fmt.Sprintf("tf-sshname-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMISBMSDataSourceConfig(vpcname, subnetname, sshname, publicKey, name), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISBareMetalServerExists("ibm_is_bare_metal_server.testacc_bms", server), + resource.TestCheckResourceAttr( + resName, "name", name), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "firmware_update_type_available"), + ), + }, + }, + }) +} func TestAccIBMISBMSDataSourceVNI_basic(t *testing.T) { var server string resName := "data.ibm_is_bare_metal_server.test1" @@ -89,6 +117,15 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "primary_network_attachment.0.primary_ip.#"), resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "primary_network_attachment.0.resource_type"), resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "primary_network_attachment.0.subnet.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "primary_network_attachment.0.virtual_network_interface.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "network_attachments.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "network_attachments.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "network_attachments.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "network_attachments.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "network_attachments.0.primary_ip.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "network_attachments.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "network_attachments.0.subnet.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_bare_metal_server.test1", "network_attachments.0.virtual_network_interface.#"), ), }, }, diff --git a/ibm/service/vpc/data_source_ibm_is_bare_metal_servers.go b/ibm/service/vpc/data_source_ibm_is_bare_metal_servers.go index 7847f5b48c..f639006c02 100644 --- a/ibm/service/vpc/data_source_ibm_is_bare_metal_servers.go +++ b/ibm/service/vpc/data_source_ibm_is_bare_metal_servers.go @@ -425,6 +425,40 @@ func DataSourceIBMIsBareMetalServers() *schema.Resource { }, }, }, + "virtual_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The virtual network interface for this bare metal server network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this virtual network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this virtual network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, }, }, @@ -564,6 +598,40 @@ func DataSourceIBMIsBareMetalServers() *schema.Resource { }, }, }, + "virtual_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The virtual network interface for this bare metal server network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this virtual network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this virtual network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, }, }, @@ -652,6 +720,11 @@ func DataSourceIBMIsBareMetalServers() *schema.Resource { Computed: true, Description: "image id", }, + isBareMetalServerFirmwareUpdateTypeAvailable: { + Type: schema.TypeString, + Computed: true, + Description: "The type of firmware update available", + }, isBareMetalServerProfile: { Type: schema.TypeString, Computed: true, @@ -1080,6 +1153,9 @@ func dataSourceIBMISBareMetalServersRead(context context.Context, d *schema.Reso } l[isBareMetalServerImage] = *initialization.Image.ID + if bms.Firmware != nil && bms.Firmware.Update != nil { + l[isBareMetalServerFirmwareUpdateTypeAvailable] = *bms.Firmware.Update + } keyListList := []string{} for i := 0; i < len(initialization.Keys); i++ { diff --git a/ibm/service/vpc/data_source_ibm_is_bare_metal_servers_test.go b/ibm/service/vpc/data_source_ibm_is_bare_metal_servers_test.go index c3315d12f2..6a72db102d 100644 --- a/ibm/service/vpc/data_source_ibm_is_bare_metal_servers_test.go +++ b/ibm/service/vpc/data_source_ibm_is_bare_metal_servers_test.go @@ -48,6 +48,34 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE }) } +func TestAccIBMISBMSsDataSource_firmwareUpdate(t *testing.T) { + resName := "data.ibm_is_bare_metal_servers.test1" + var server string + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf-server-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tfip-subnet-%d", acctest.RandIntRange(10, 100)) + publicKey := strings.TrimSpace(` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR +`) + sshname := fmt.Sprintf("tf-sshname-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISBMSsDataSourceConfig(vpcname, subnetname, sshname, publicKey, name), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISBareMetalServerExists("ibm_is_bare_metal_server.testacc_bms", server), + resource.TestCheckResourceAttrSet(resName, "servers.0.name"), + resource.TestCheckResourceAttrSet(resName, "servers.0.id"), + resource.TestCheckResourceAttrSet(resName, "servers.0.firmware_update_type_available"), + ), + }, + }, + }) +} + func testAccCheckIBMISBMSsDataSourceConfig(vpcname, subnetname, sshname, publicKey, name string) string { // status filter defaults to empty return testAccCheckIBMISBareMetalServerConfig(vpcname, subnetname, sshname, publicKey, name) + fmt.Sprintf(` @@ -90,6 +118,15 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE resource.TestCheckResourceAttrSet(resName, "servers.0.primary_network_attachment.0.primary_ip.#"), resource.TestCheckResourceAttrSet(resName, "servers.0.primary_network_attachment.0.resource_type"), resource.TestCheckResourceAttrSet(resName, "servers.0.primary_network_attachment.0.subnet.#"), + resource.TestCheckResourceAttrSet(resName, "servers.0.primary_network_attachment.0.virtual_network_interface.#"), + resource.TestCheckResourceAttrSet(resName, "servers.0.network_attachments.#"), + resource.TestCheckResourceAttrSet(resName, "servers.0.network_attachments.0.href"), + resource.TestCheckResourceAttrSet(resName, "servers.0.network_attachments.0.id"), + resource.TestCheckResourceAttrSet(resName, "servers.0.network_attachments.0.name"), + resource.TestCheckResourceAttrSet(resName, "servers.0.network_attachments.0.primary_ip.#"), + resource.TestCheckResourceAttrSet(resName, "servers.0.network_attachments.0.resource_type"), + resource.TestCheckResourceAttrSet(resName, "servers.0.network_attachments.0.subnet.#"), + resource.TestCheckResourceAttrSet(resName, "servers.0.network_attachments.0.virtual_network_interface.#"), ), }, }, diff --git a/ibm/service/vpc/data_source_ibm_is_instance.go b/ibm/service/vpc/data_source_ibm_is_instance.go index 7650388cc4..d2148851a6 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance.go +++ b/ibm/service/vpc/data_source_ibm_is_instance.go @@ -550,6 +550,40 @@ func DataSourceIBMISInstance() *schema.Resource { }, }, }, + "virtual_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The virtual network interface for this instance network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this virtual network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this virtual network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, }, }, @@ -760,6 +794,40 @@ func DataSourceIBMISInstance() *schema.Resource { }, }, }, + "virtual_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The virtual network interface for this instance network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this virtual network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this virtual network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, }, }, @@ -1747,6 +1815,21 @@ func dataSourceIBMIsInstanceInstanceNetworkAttachmentReferenceToMap(model *vpcv1 return modelMap, err } modelMap["subnet"] = []map[string]interface{}{subnetMap} + virtualNetworkInterfaceMap, err := dataSourceIBMIsInstanceVirtualNetworkInterfaceReferenceAttachmentContextToMap(model.VirtualNetworkInterface) + if err != nil { + return modelMap, err + } + modelMap["virtual_network_interface"] = []map[string]interface{}{virtualNetworkInterfaceMap} + return modelMap, nil +} + +func dataSourceIBMIsInstanceVirtualNetworkInterfaceReferenceAttachmentContextToMap(model *vpcv1.VirtualNetworkInterfaceReferenceAttachmentContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = model.CRN + modelMap["href"] = model.Href + modelMap["id"] = model.ID + modelMap["name"] = model.Name + modelMap["resource_type"] = model.ResourceType return modelMap, nil } func dataSourceIBMIsInstanceInstanceNetworkAttachmentReferenceDeletedToMap(model *vpcv1.InstanceNetworkAttachmentReferenceDeleted) (map[string]interface{}, error) { diff --git a/ibm/service/vpc/data_source_ibm_is_instance_test.go b/ibm/service/vpc/data_source_ibm_is_instance_test.go index 89d3a62b7a..325f292f73 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_test.go @@ -115,10 +115,22 @@ func TestAccIBMISInstanceDataSource_vni(t *testing.T) { resName, "primary_network_attachment.0.id"), resource.TestCheckResourceAttr( resName, "primary_network_attachment.0.name", "test-vni"), + resource.TestCheckResourceAttr( + resName, "primary_network_attachment.0.virtual_network_interface.#", "1"), resource.TestCheckResourceAttrSet( resName, "primary_network_attachment.0.primary_ip.#"), resource.TestCheckResourceAttrSet( resName, "primary_network_attachment.0.subnet.#"), + resource.TestCheckResourceAttrSet( + resName, "network_attachments.#"), + resource.TestCheckResourceAttrSet( + resName, "network_attachments.0.id"), + resource.TestCheckResourceAttr( + resName, "network_attachments.0.virtual_network_interface.#", "1"), + resource.TestCheckResourceAttrSet( + resName, "network_attachments.0.primary_ip.#"), + resource.TestCheckResourceAttrSet( + resName, "network_attachments.0.subnet.#"), ), }, }, @@ -302,6 +314,11 @@ resource "ibm_is_virtual_network_interface" "testacc_vni"{ allow_ip_spoofing = true subnet = ibm_is_subnet.testacc_subnet.id } +resource "ibm_is_virtual_network_interface" "testacc_vni2"{ + name = "%s-2" + allow_ip_spoofing = true + subnet = ibm_is_subnet.testacc_subnet.id +} resource "ibm_is_instance" "testacc_instance" { name = "%s" @@ -313,6 +330,12 @@ resource "ibm_is_instance" "testacc_instance" { id = ibm_is_virtual_network_interface.testacc_vni.id } } + network_attachments { + name = "test-vni-sec" + virtual_network_interface { + id = ibm_is_virtual_network_interface.testacc_vni2.id + } + } vpc = ibm_is_vpc.testacc_vpc.id zone = "%s" keys = [ibm_is_ssh_key.testacc_sshkey.id] @@ -321,7 +344,7 @@ data "ibm_is_instance" "ds_instance" { name = ibm_is_instance.testacc_instance.name private_key = file("./test-fixtures/.ssh/id_rsa") passphrase = "" -}`, vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, sshname, vniname, instanceName, acc.IsWinImage, acc.InstanceProfileName, acc.ISZoneName) +}`, vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, sshname, vniname, vniname, instanceName, acc.IsWinImage, acc.InstanceProfileName, acc.ISZoneName) } func testAccCheckIBMISInstanceDataSourcePKCS8SSHConfig(vpcname, subnetname, sshname, instanceName string) string { return fmt.Sprintf(` diff --git a/ibm/service/vpc/data_source_ibm_is_instances.go b/ibm/service/vpc/data_source_ibm_is_instances.go index 0b544de1e0..7a26fcf196 100644 --- a/ibm/service/vpc/data_source_ibm_is_instances.go +++ b/ibm/service/vpc/data_source_ibm_is_instances.go @@ -571,6 +571,40 @@ func DataSourceIBMISInstances() *schema.Resource { }, }, }, + "virtual_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The virtual network interface for this instance network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this virtual network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this virtual network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, }, }, @@ -829,6 +863,40 @@ func DataSourceIBMISInstances() *schema.Resource { }, }, }, + "virtual_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The virtual network interface for this instance network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this virtual network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this virtual network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, }, }, diff --git a/ibm/service/vpc/data_source_ibm_is_instances_test.go b/ibm/service/vpc/data_source_ibm_is_instances_test.go index 7d119635b0..ef027ed2c9 100644 --- a/ibm/service/vpc/data_source_ibm_is_instances_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instances_test.go @@ -124,6 +124,10 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE resource.TestCheckResourceAttrSet(resName, "instances.0.vcpu.0.manufacturer"), resource.TestCheckResourceAttrSet(resName, "instances.0.primary_network_attachment.#"), resource.TestCheckResourceAttr(resName, "instances.0.primary_network_attachment.#", "1"), + resource.TestCheckResourceAttr(resName, "instances.0.primary_network_attachment.0.virtual_network_interface.#", "1"), + resource.TestCheckResourceAttrSet(resName, "instances.0.network_attachments.#"), + resource.TestCheckResourceAttr(resName, "instances.0.network_attachments.#", "2"), + resource.TestCheckResourceAttr(resName, "instances.0.network_attachments.0.virtual_network_interface.#", "1"), ), }, }, diff --git a/ibm/service/vpc/data_source_ibm_is_share.go b/ibm/service/vpc/data_source_ibm_is_share.go index e5bd0c5559..48100560e9 100644 --- a/ibm/service/vpc/data_source_ibm_is_share.go +++ b/ibm/service/vpc/data_source_ibm_is_share.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/vpc-go-sdk/vpcv1" ) @@ -34,6 +35,12 @@ func DataSourceIbmIsShare() *schema.Resource { ExactlyOneOf: []string{"share", "name"}, Description: "Name of the share.", }, + "allowed_transit_encryption_modes": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Allowed transit encryption modes", + }, "created_at": { Type: schema.TypeString, Computed: true, @@ -334,6 +341,49 @@ func DataSourceIbmIsShare() *schema.Resource { }, }, }, + "mount_targets": { + Type: schema.TypeList, + Computed: true, + Description: "Mount targets for the file share.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "deleted": { + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates the referenced resource has been deleted and providessome supplementary information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "more_info": { + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about deleted resources.", + }, + }, + }, + }, + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL for this share target.", + }, + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this share target.", + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: "The user-defined name for this share target.", + }, + "resource_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of resource referenced.", + }, + }, + }, + }, "zone": { Type: schema.TypeString, Computed: true, @@ -358,6 +408,130 @@ func DataSourceIbmIsShare() *schema.Resource { Set: flex.ResourceIBMVPCHash, Description: "List of tags", }, + "origin_share": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The origin share this accessor share is referring to.This property will be present when the `accessor_binding_role` is `accessor`.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this file share.", + }, + "deleted": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates the referenced resource has been deleted, and providessome supplementary information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about deleted resources.", + }, + }, + }, + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this file share.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this file share.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this share. The name is unique across all shares in the region.", + }, + "remote": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this account.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "region": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this region.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this region.", + }, + }, + }, + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "accessor_binding_role": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The accessor binding role of this file share:- `none`: This file share is not participating in access with another file share- `origin`: This file share is the origin for one or more file shares (which may be in other accounts)- `accessor`: This file share is providing access to another file share (which may be in another account).", + }, + "accessor_bindings": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The accessor bindings for this file share. Each accessor binding identifies a resource (possibly in another account) with access to this file share's data.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this share accessor binding.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this share accessor binding.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, } } @@ -461,6 +635,32 @@ func dataSourceIbmIsShareRead(context context.Context, d *schema.ResourceData, m if share.AccessControlMode != nil { d.Set("access_control_mode", *share.AccessControlMode) } + if !core.IsNil(share.AllowedTransitEncryptionModes) { + if err = d.Set("allowed_transit_encryption_modes", share.AllowedTransitEncryptionModes); err != nil { + err = fmt.Errorf("Error setting allowed_transit_encryption_modes: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_share", "read", "set-allowed_transit_encryption_modes").GetDiag() + } + } + if err = d.Set("accessor_binding_role", share.AccessorBindingRole); err != nil { + err = fmt.Errorf("Error setting accessor_binding_role: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_share", "read", "set-accessor_binding_role").GetDiag() + } + accessorBindings := []map[string]interface{}{} + for _, accessorBindingsItem := range share.AccessorBindings { + accessorBindingsItemMap := ResourceIBMIsShareShareAccessorBindingReferenceToMap(&accessorBindingsItem) + accessorBindings = append(accessorBindings, accessorBindingsItemMap) + } + if err = d.Set("accessor_bindings", accessorBindings); err != nil { + err = fmt.Errorf("Error setting accessor_bindings: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_share", "read", "set-accessor_bindings").GetDiag() + } + if !core.IsNil(share.OriginShare) { + originShareMap := ResourceIBMIsShareShareReferenceToMap(share.OriginShare) + if err = d.Set("origin_share", []map[string]interface{}{originShareMap}); err != nil { + err = fmt.Errorf("Error setting origin_share: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_share", "read", "set-origin_share").GetDiag() + } + } if share.Profile != nil { err = d.Set("profile", *share.Profile.Name) if err != nil { @@ -514,6 +714,10 @@ func dataSourceIbmIsShareRead(context context.Context, d *schema.ResourceData, m if err != nil { return diag.FromErr(fmt.Errorf("Error setting targets %s", err)) } + err = d.Set("mount_targets", dataSourceShareFlattenTargets(share.MountTargets)) + if err != nil { + return diag.FromErr(fmt.Errorf("Error setting targets %s", err)) + } } if share.Zone != nil { diff --git a/ibm/service/vpc/data_source_ibm_is_share_accessor_binding.go b/ibm/service/vpc/data_source_ibm_is_share_accessor_binding.go new file mode 100644 index 0000000000..16432fa551 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_share_accessor_binding.go @@ -0,0 +1,322 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.90.0-5aad763d-20240506-203857 + */ + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsShareAccessorBinding() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsShareAccessorBindingRead, + + Schema: map[string]*schema.Schema{ + "share": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The file share identifier.", + }, + "accessor_binding": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The file share accessor binding identifier.", + }, + "accessor": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The accessor for this share accessor binding.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this file share.", + }, + "deleted": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates the referenced resource has been deleted, and providessome supplementary information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about deleted resources.", + }, + }, + }, + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this file share.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this file share.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this share. The name is unique across all shares in the region.", + }, + "remote": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this account.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "region": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this region.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this region.", + }, + }, + }, + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the share accessor binding was created.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this share accessor binding.", + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the file share accessor binding.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + } +} + +func dataSourceIBMIsShareAccessorBindingRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + // Error is coming from SDK client, so it doesn't need to be discriminated. + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_share_accessor_binding", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getShareAccessorBindingOptions := &vpcv1.GetShareAccessorBindingOptions{} + + getShareAccessorBindingOptions.SetShareID(d.Get("share").(string)) + getShareAccessorBindingOptions.SetID(d.Get("accessor_binding").(string)) + + shareAccessorBinding, _, err := vpcClient.GetShareAccessorBindingWithContext(context, getShareAccessorBindingOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetShareAccessorBindingWithContext failed: %s", err.Error()), "(Data) ibm_is_share_accessor_binding", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(*shareAccessorBinding.ID) + + accessor := []map[string]interface{}{} + if shareAccessorBinding.Accessor != nil { + modelMap, err := DataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorToMap(shareAccessorBinding.Accessor) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_share_accessor_binding", "read", "accessor-to-map").GetDiag() + } + accessor = append(accessor, modelMap) + } + if err = d.Set("accessor", accessor); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting accessor: %s", err), "(Data) ibm_is_share_accessor_binding", "read", "set-accessor").GetDiag() + } + + if err = d.Set("created_at", flex.DateTimeToString(shareAccessorBinding.CreatedAt)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting created_at: %s", err), "(Data) ibm_is_share_accessor_binding", "read", "set-created_at").GetDiag() + } + + if err = d.Set("href", shareAccessorBinding.Href); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting href: %s", err), "(Data) ibm_is_share_accessor_binding", "read", "set-href").GetDiag() + } + + if err = d.Set("lifecycle_state", shareAccessorBinding.LifecycleState); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_state: %s", err), "(Data) ibm_is_share_accessor_binding", "read", "set-lifecycle_state").GetDiag() + } + + if err = d.Set("resource_type", shareAccessorBinding.ResourceType); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting resource_type: %s", err), "(Data) ibm_is_share_accessor_binding", "read", "set-resource_type").GetDiag() + } + + return nil +} + +func DataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorToMap(model vpcv1.ShareAccessorBindingAccessorIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ShareAccessorBindingAccessorShareReference); ok { + return DataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorShareReferenceToMap(model.(*vpcv1.ShareAccessorBindingAccessorShareReference)) + } else if _, ok := model.(*vpcv1.ShareAccessorBindingAccessorWatsonxMachineLearningReference); ok { + return DataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorWatsonxMachineLearningReferenceToMap(model.(*vpcv1.ShareAccessorBindingAccessorWatsonxMachineLearningReference)) + } else if _, ok := model.(*vpcv1.ShareAccessorBindingAccessor); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ShareAccessorBindingAccessor) + if model.CRN != nil { + modelMap["crn"] = *model.CRN + } + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsShareAccessorBindingShareReferenceDeletedToMap(model.Deleted) + if err != nil { + return modelMap, err + } + modelMap["deleted"] = []map[string]interface{}{deletedMap} + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.Remote != nil { + remoteMap, err := DataSourceIBMIsShareAccessorBindingShareRemoteToMap(model.Remote) + if err != nil { + return modelMap, err + } + modelMap["remote"] = []map[string]interface{}{remoteMap} + } + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ShareAccessorBindingAccessorIntf subtype encountered") + } +} + +func DataSourceIBMIsShareAccessorBindingShareReferenceDeletedToMap(model *vpcv1.ShareReferenceDeleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingShareRemoteToMap(model *vpcv1.ShareRemote) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Account != nil { + accountMap, err := DataSourceIBMIsShareAccessorBindingAccountReferenceToMap(model.Account) + if err != nil { + return modelMap, err + } + modelMap["account"] = []map[string]interface{}{accountMap} + } + if model.Region != nil { + regionMap, err := DataSourceIBMIsShareAccessorBindingRegionReferenceToMap(model.Region) + if err != nil { + return modelMap, err + } + modelMap["region"] = []map[string]interface{}{regionMap} + } + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingAccountReferenceToMap(model *vpcv1.AccountReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingRegionReferenceToMap(model *vpcv1.RegionReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorShareReferenceToMap(model *vpcv1.ShareAccessorBindingAccessorShareReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsShareAccessorBindingShareReferenceDeletedToMap(model.Deleted) + if err != nil { + return modelMap, err + } + modelMap["deleted"] = []map[string]interface{}{deletedMap} + } + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + if model.Remote != nil { + remoteMap, err := DataSourceIBMIsShareAccessorBindingShareRemoteToMap(model.Remote) + if err != nil { + return modelMap, err + } + modelMap["remote"] = []map[string]interface{}{remoteMap} + } + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorWatsonxMachineLearningReferenceToMap(model *vpcv1.ShareAccessorBindingAccessorWatsonxMachineLearningReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_share_accessor_binding_test.go b/ibm/service/vpc/data_source_ibm_is_share_accessor_binding_test.go new file mode 100644 index 0000000000..ffbadde4a5 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_share_accessor_binding_test.go @@ -0,0 +1,281 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.90.0-5aad763d-20240506-203857 + */ + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsShareAccessorBindingDataSourceBasic(t *testing.T) { + subnetName := fmt.Sprintf("tf-subnet-%d", acctest.RandIntRange(10, 100)) + vpcname := fmt.Sprintf("tf-vpc-name-%d", acctest.RandIntRange(10, 100)) + shareName := fmt.Sprintf("tf-share-%d", acctest.RandIntRange(10, 100)) + shareName1 := fmt.Sprintf("tf-share1-%d", acctest.RandIntRange(10, 100)) + tEMode1 := "user_managed" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsShareAccessorBindingDataSourceConfigBasic(vpcname, subnetName, tEMode1, shareName, shareName1), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_binding.is_share_accessor_binding_instance", "share"), + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_binding.is_share_accessor_binding_instance", "accessor.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_binding.is_share_accessor_binding_instance", "accessor.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_binding.is_share_accessor_binding_instance", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_binding.is_share_accessor_binding_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_binding.is_share_accessor_binding_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_binding.is_share_accessor_binding_instance", "resource_type"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsShareAccessorBindingDataSourceConfigBasic(vpcName, sname, tEMode, shareName, shareName1 string) string { + return testAccCheckIbmIsShareConfigOriginShareConfig(vpcName, sname, tEMode, shareName, shareName1) + fmt.Sprintf(` + data "ibm_is_share_accessor_bindings" "bindings" { + depends_on = [ibm_is_share.is_share_accessor] + share = ibm_is_share.is_share.id + } + data "ibm_is_share_accessor_binding" "is_share_accessor_binding_instance" { + share = ibm_is_share.is_share.id + accessor_binding = data.ibm_is_share_accessor_bindings.bindings.accessor_bindings.0.id + } + `) +} + +func TestDataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + shareReferenceDeletedModel := make(map[string]interface{}) + shareReferenceDeletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + accountReferenceModel := make(map[string]interface{}) + accountReferenceModel["id"] = "bb1b52262f7441a586f49068482f1e60" + accountReferenceModel["resource_type"] = "account" + + regionReferenceModel := make(map[string]interface{}) + regionReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south" + regionReferenceModel["name"] = "us-south" + + shareRemoteModel := make(map[string]interface{}) + shareRemoteModel["account"] = []map[string]interface{}{accountReferenceModel} + shareRemoteModel["region"] = []map[string]interface{}{regionReferenceModel} + + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::share:0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["deleted"] = []map[string]interface{}{shareReferenceDeletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["id"] = "0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["name"] = "my-share" + model["remote"] = []map[string]interface{}{shareRemoteModel} + model["resource_type"] = "share" + + assert.Equal(t, result, model) + } + + shareReferenceDeletedModel := new(vpcv1.ShareReferenceDeleted) + shareReferenceDeletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + accountReferenceModel := new(vpcv1.AccountReference) + accountReferenceModel.ID = core.StringPtr("bb1b52262f7441a586f49068482f1e60") + accountReferenceModel.ResourceType = core.StringPtr("account") + + regionReferenceModel := new(vpcv1.RegionReference) + regionReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south") + regionReferenceModel.Name = core.StringPtr("us-south") + + shareRemoteModel := new(vpcv1.ShareRemote) + shareRemoteModel.Account = accountReferenceModel + shareRemoteModel.Region = regionReferenceModel + + model := new(vpcv1.ShareAccessorBindingAccessor) + model.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::share:0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.Deleted = shareReferenceDeletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.ID = core.StringPtr("0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.Name = core.StringPtr("my-share") + model.Remote = shareRemoteModel + model.ResourceType = core.StringPtr("share") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingShareReferenceDeletedToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ShareReferenceDeleted) + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingShareReferenceDeletedToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingShareRemoteToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + accountReferenceModel := make(map[string]interface{}) + accountReferenceModel["id"] = "bb1b52262f7441a586f49068482f1e60" + accountReferenceModel["resource_type"] = "account" + + regionReferenceModel := make(map[string]interface{}) + regionReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south" + regionReferenceModel["name"] = "us-south" + + model := make(map[string]interface{}) + model["account"] = []map[string]interface{}{accountReferenceModel} + model["region"] = []map[string]interface{}{regionReferenceModel} + + assert.Equal(t, result, model) + } + + accountReferenceModel := new(vpcv1.AccountReference) + accountReferenceModel.ID = core.StringPtr("bb1b52262f7441a586f49068482f1e60") + accountReferenceModel.ResourceType = core.StringPtr("account") + + regionReferenceModel := new(vpcv1.RegionReference) + regionReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south") + regionReferenceModel.Name = core.StringPtr("us-south") + + model := new(vpcv1.ShareRemote) + model.Account = accountReferenceModel + model.Region = regionReferenceModel + + result, err := vpc.DataSourceIBMIsShareAccessorBindingShareRemoteToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingAccountReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["id"] = "bb1b52262f7441a586f49068482f1e60" + model["resource_type"] = "account" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.AccountReference) + model.ID = core.StringPtr("bb1b52262f7441a586f49068482f1e60") + model.ResourceType = core.StringPtr("account") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingAccountReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingRegionReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south" + model["name"] = "us-south" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.RegionReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south") + model.Name = core.StringPtr("us-south") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingRegionReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorShareReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + shareReferenceDeletedModel := make(map[string]interface{}) + shareReferenceDeletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + accountReferenceModel := make(map[string]interface{}) + accountReferenceModel["id"] = "bb1b52262f7441a586f49068482f1e60" + accountReferenceModel["resource_type"] = "account" + + regionReferenceModel := make(map[string]interface{}) + regionReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south" + regionReferenceModel["name"] = "us-south" + + shareRemoteModel := make(map[string]interface{}) + shareRemoteModel["account"] = []map[string]interface{}{accountReferenceModel} + shareRemoteModel["region"] = []map[string]interface{}{regionReferenceModel} + + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::share:0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["deleted"] = []map[string]interface{}{shareReferenceDeletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["id"] = "0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["name"] = "my-share" + model["remote"] = []map[string]interface{}{shareRemoteModel} + model["resource_type"] = "share" + + assert.Equal(t, result, model) + } + + shareReferenceDeletedModel := new(vpcv1.ShareReferenceDeleted) + shareReferenceDeletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + accountReferenceModel := new(vpcv1.AccountReference) + accountReferenceModel.ID = core.StringPtr("bb1b52262f7441a586f49068482f1e60") + accountReferenceModel.ResourceType = core.StringPtr("account") + + regionReferenceModel := new(vpcv1.RegionReference) + regionReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south") + regionReferenceModel.Name = core.StringPtr("us-south") + + shareRemoteModel := new(vpcv1.ShareRemote) + shareRemoteModel.Account = accountReferenceModel + shareRemoteModel.Region = regionReferenceModel + + model := new(vpcv1.ShareAccessorBindingAccessorShareReference) + model.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::share:0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.Deleted = shareReferenceDeletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.ID = core.StringPtr("0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.Name = core.StringPtr("my-share") + model.Remote = shareRemoteModel + model.ResourceType = core.StringPtr("share") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorShareReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorWatsonxMachineLearningReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:pm-20:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34:6500f05d-a5b5-4ecf-91ba-0d12b9dee607" + model["resource_type"] = "watsonx_machine_learning" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ShareAccessorBindingAccessorWatsonxMachineLearningReference) + model.CRN = core.StringPtr("crn:v1:bluemix:public:pm-20:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34:6500f05d-a5b5-4ecf-91ba-0d12b9dee607") + model.ResourceType = core.StringPtr("watsonx_machine_learning") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingShareAccessorBindingAccessorWatsonxMachineLearningReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_share_accessor_bindings.go b/ibm/service/vpc/data_source_ibm_is_share_accessor_bindings.go new file mode 100644 index 0000000000..8649fa6a09 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_share_accessor_bindings.go @@ -0,0 +1,345 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.90.0-5aad763d-20240506-203857 + */ + +package vpc + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsShareAccessorBindings() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsShareAccessorBindingsRead, + + Schema: map[string]*schema.Schema{ + "share": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The file share identifier.", + }, + "accessor_bindings": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "Collection of share accessor bindings.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "accessor": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The accessor for this share accessor binding.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this file share.", + }, + "deleted": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates the referenced resource has been deleted, and providessome supplementary information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about deleted resources.", + }, + }, + }, + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this file share.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this file share.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this share. The name is unique across all shares in the region.", + }, + "remote": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this account.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "region": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this region.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this region.", + }, + }, + }, + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the share accessor binding was created.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this share accessor binding.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this share accessor binding.", + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the file share accessor binding.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsShareAccessorBindingsRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_share_accessor_bindings", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + listShareAccessorBindingsOptions := &vpcv1.ListShareAccessorBindingsOptions{} + + listShareAccessorBindingsOptions.SetID(d.Get("share").(string)) + + var pager *vpcv1.ShareAccessorBindingsPager + pager, err = vpcClient.NewShareAccessorBindingsPager(listShareAccessorBindingsOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_share_accessor_bindings", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + allItems, err := pager.GetAll() + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ShareAccessorBindingsPager.GetAll() failed %s", err), "(Data) ibm_is_share_accessor_bindings", "read") + log.Printf("[DEBUG] %s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMIsShareAccessorBindingsID(d)) + + mapSlice := []map[string]interface{}{} + for _, modelItem := range allItems { + modelMap, err := DataSourceIBMIsShareAccessorBindingsShareAccessorBindingToMap(&modelItem) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_share_accessor_bindings", "read") + return tfErr.GetDiag() + } + mapSlice = append(mapSlice, modelMap) + } + + if err = d.Set("accessor_bindings", mapSlice); err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting accessor_bindings %s", err), "(Data) ibm_is_share_accessor_bindings", "read") + return tfErr.GetDiag() + } + + return nil +} + +// dataSourceIBMIsShareAccessorBindingsID returns a reasonable ID for the list. +func dataSourceIBMIsShareAccessorBindingsID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func DataSourceIBMIsShareAccessorBindingsShareAccessorBindingToMap(model *vpcv1.ShareAccessorBinding) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + accessorMap, err := DataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorToMap(model.Accessor) + if err != nil { + return modelMap, err + } + modelMap["accessor"] = []map[string]interface{}{accessorMap} + modelMap["created_at"] = model.CreatedAt.String() + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["lifecycle_state"] = *model.LifecycleState + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorToMap(model vpcv1.ShareAccessorBindingAccessorIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ShareAccessorBindingAccessorShareReference); ok { + return DataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorShareReferenceToMap(model.(*vpcv1.ShareAccessorBindingAccessorShareReference)) + } else if _, ok := model.(*vpcv1.ShareAccessorBindingAccessorWatsonxMachineLearningReference); ok { + return DataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorWatsonxMachineLearningReferenceToMap(model.(*vpcv1.ShareAccessorBindingAccessorWatsonxMachineLearningReference)) + } else if _, ok := model.(*vpcv1.ShareAccessorBindingAccessor); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ShareAccessorBindingAccessor) + if model.CRN != nil { + modelMap["crn"] = *model.CRN + } + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsShareAccessorBindingsShareReferenceDeletedToMap(model.Deleted) + if err != nil { + return modelMap, err + } + modelMap["deleted"] = []map[string]interface{}{deletedMap} + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.Remote != nil { + remoteMap, err := DataSourceIBMIsShareAccessorBindingsShareRemoteToMap(model.Remote) + if err != nil { + return modelMap, err + } + modelMap["remote"] = []map[string]interface{}{remoteMap} + } + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ShareAccessorBindingAccessorIntf subtype encountered") + } +} + +func DataSourceIBMIsShareAccessorBindingsShareReferenceDeletedToMap(model *vpcv1.ShareReferenceDeleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingsShareRemoteToMap(model *vpcv1.ShareRemote) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Account != nil { + accountMap, err := DataSourceIBMIsShareAccessorBindingsAccountReferenceToMap(model.Account) + if err != nil { + return modelMap, err + } + modelMap["account"] = []map[string]interface{}{accountMap} + } + if model.Region != nil { + regionMap, err := DataSourceIBMIsShareAccessorBindingsRegionReferenceToMap(model.Region) + if err != nil { + return modelMap, err + } + modelMap["region"] = []map[string]interface{}{regionMap} + } + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingsAccountReferenceToMap(model *vpcv1.AccountReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingsRegionReferenceToMap(model *vpcv1.RegionReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorShareReferenceToMap(model *vpcv1.ShareAccessorBindingAccessorShareReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsShareAccessorBindingsShareReferenceDeletedToMap(model.Deleted) + if err != nil { + return modelMap, err + } + modelMap["deleted"] = []map[string]interface{}{deletedMap} + } + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + if model.Remote != nil { + remoteMap, err := DataSourceIBMIsShareAccessorBindingsShareRemoteToMap(model.Remote) + if err != nil { + return modelMap, err + } + modelMap["remote"] = []map[string]interface{}{remoteMap} + } + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorWatsonxMachineLearningReferenceToMap(model *vpcv1.ShareAccessorBindingAccessorWatsonxMachineLearningReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_share_accessor_bindings_test.go b/ibm/service/vpc/data_source_ibm_is_share_accessor_bindings_test.go new file mode 100644 index 0000000000..f717e6b047 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_share_accessor_bindings_test.go @@ -0,0 +1,349 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +/* + * IBM OpenAPI Terraform Generator Version: 3.90.0-5aad763d-20240506-203857 + */ + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + . "github.com/IBM-Cloud/terraform-provider-ibm/ibm/unittest" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsShareAccessorBindingsDataSourceBasic(t *testing.T) { + subnetName := fmt.Sprintf("tf-subnet-%d", acctest.RandIntRange(10, 100)) + vpcname := fmt.Sprintf("tf-vpc-name-%d", acctest.RandIntRange(10, 100)) + shareName := fmt.Sprintf("tf-share-%d", acctest.RandIntRange(10, 100)) + shareName1 := fmt.Sprintf("tf-share1-%d", acctest.RandIntRange(10, 100)) + tEMode1 := "user_managed" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsShareAccessorBindingsDataSourceConfigBasic(vpcname, subnetName, tEMode1, shareName, shareName1), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_bindings.is_share_accessor_bindings_instance", "accessor_bindings.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_bindings.is_share_accessor_bindings_instance", "accessor_bindings.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_bindings.is_share_accessor_bindings_instance", "accessor_bindings.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_share_accessor_bindings.is_share_accessor_bindings_instance", "accessor_bindings.0.accessor.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsShareAccessorBindingsDataSourceConfigBasic(vpcName, sname, tEMode, shareName, shareName1 string) string { + return testAccCheckIbmIsShareConfigOriginShareConfig(vpcName, sname, tEMode, shareName, shareName1) + fmt.Sprintf(` + data "ibm_is_share_accessor_bindings" "is_share_accessor_bindings_instance" { + depends_on = [ibm_is_share.is_share_accessor] + share = ibm_is_share.is_share.id + } + `) +} + +func TestDataSourceIBMIsShareAccessorBindingsShareAccessorBindingToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + shareReferenceDeletedModel := make(map[string]interface{}) + shareReferenceDeletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + accountReferenceModel := make(map[string]interface{}) + accountReferenceModel["id"] = "bb1b52262f7441a586f49068482f1e60" + accountReferenceModel["resource_type"] = "account" + + regionReferenceModel := make(map[string]interface{}) + regionReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south" + regionReferenceModel["name"] = "us-south" + + shareRemoteModel := make(map[string]interface{}) + shareRemoteModel["account"] = []map[string]interface{}{accountReferenceModel} + shareRemoteModel["region"] = []map[string]interface{}{regionReferenceModel} + + shareAccessorBindingAccessorModel := make(map[string]interface{}) + shareAccessorBindingAccessorModel["crn"] = "crn:v1:bluemix:public:pm-20:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34:6500f05d-a5b5-4ecf-91ba-0d12b9dee607" + shareAccessorBindingAccessorModel["deleted"] = []map[string]interface{}{shareReferenceDeletedModel} + shareAccessorBindingAccessorModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58" + shareAccessorBindingAccessorModel["id"] = "0fe9e5d8-0a4d-4818-96ec-e99708644a58" + shareAccessorBindingAccessorModel["name"] = "my-share" + shareAccessorBindingAccessorModel["remote"] = []map[string]interface{}{shareRemoteModel} + shareAccessorBindingAccessorModel["resource_type"] = "watsonx_machine_learning" + + model := make(map[string]interface{}) + model["accessor"] = []map[string]interface{}{shareAccessorBindingAccessorModel} + model["created_at"] = "2019-01-01T12:00:00.000Z" + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58/accessor_bindings/r134-ae9bdc18-aed0-4392-841c-142d3300674f" + model["id"] = "r134-ce9dac18-dea0-4392-841c-142d3300674f" + model["lifecycle_state"] = "stable" + model["resource_type"] = "share_accessor_binding" + + assert.Equal(t, result, model) + } + + shareReferenceDeletedModel := new(vpcv1.ShareReferenceDeleted) + shareReferenceDeletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + accountReferenceModel := new(vpcv1.AccountReference) + accountReferenceModel.ID = core.StringPtr("bb1b52262f7441a586f49068482f1e60") + accountReferenceModel.ResourceType = core.StringPtr("account") + + regionReferenceModel := new(vpcv1.RegionReference) + regionReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south") + regionReferenceModel.Name = core.StringPtr("us-south") + + shareRemoteModel := new(vpcv1.ShareRemote) + shareRemoteModel.Account = accountReferenceModel + shareRemoteModel.Region = regionReferenceModel + + shareAccessorBindingAccessorModel := new(vpcv1.ShareAccessorBindingAccessorShareReference) + shareAccessorBindingAccessorModel.CRN = core.StringPtr("crn:v1:bluemix:public:pm-20:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34:6500f05d-a5b5-4ecf-91ba-0d12b9dee607") + shareAccessorBindingAccessorModel.Deleted = shareReferenceDeletedModel + shareAccessorBindingAccessorModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58") + shareAccessorBindingAccessorModel.ID = core.StringPtr("0fe9e5d8-0a4d-4818-96ec-e99708644a58") + shareAccessorBindingAccessorModel.Name = core.StringPtr("my-share") + shareAccessorBindingAccessorModel.Remote = shareRemoteModel + shareAccessorBindingAccessorModel.ResourceType = core.StringPtr("watsonx_machine_learning") + + model := new(vpcv1.ShareAccessorBinding) + model.Accessor = shareAccessorBindingAccessorModel + model.CreatedAt = CreateMockDateTime("2019-01-01T12:00:00.000Z") + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58/accessor_bindings/r134-ae9bdc18-aed0-4392-841c-142d3300674f") + model.ID = core.StringPtr("r134-ce9dac18-dea0-4392-841c-142d3300674f") + model.LifecycleState = core.StringPtr("stable") + model.ResourceType = core.StringPtr("share_accessor_binding") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingsShareAccessorBindingToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + shareReferenceDeletedModel := make(map[string]interface{}) + shareReferenceDeletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + accountReferenceModel := make(map[string]interface{}) + accountReferenceModel["id"] = "bb1b52262f7441a586f49068482f1e60" + accountReferenceModel["resource_type"] = "account" + + regionReferenceModel := make(map[string]interface{}) + regionReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south" + regionReferenceModel["name"] = "us-south" + + shareRemoteModel := make(map[string]interface{}) + shareRemoteModel["account"] = []map[string]interface{}{accountReferenceModel} + shareRemoteModel["region"] = []map[string]interface{}{regionReferenceModel} + + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::share:0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["deleted"] = []map[string]interface{}{shareReferenceDeletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["id"] = "0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["name"] = "my-share" + model["remote"] = []map[string]interface{}{shareRemoteModel} + model["resource_type"] = "share" + + assert.Equal(t, result, model) + } + + shareReferenceDeletedModel := new(vpcv1.ShareReferenceDeleted) + shareReferenceDeletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + accountReferenceModel := new(vpcv1.AccountReference) + accountReferenceModel.ID = core.StringPtr("bb1b52262f7441a586f49068482f1e60") + accountReferenceModel.ResourceType = core.StringPtr("account") + + regionReferenceModel := new(vpcv1.RegionReference) + regionReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south") + regionReferenceModel.Name = core.StringPtr("us-south") + + shareRemoteModel := new(vpcv1.ShareRemote) + shareRemoteModel.Account = accountReferenceModel + shareRemoteModel.Region = regionReferenceModel + + model := new(vpcv1.ShareAccessorBindingAccessor) + model.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::share:0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.Deleted = shareReferenceDeletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.ID = core.StringPtr("0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.Name = core.StringPtr("my-share") + model.Remote = shareRemoteModel + model.ResourceType = core.StringPtr("share") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingsShareReferenceDeletedToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ShareReferenceDeleted) + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingsShareReferenceDeletedToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingsShareRemoteToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + accountReferenceModel := make(map[string]interface{}) + accountReferenceModel["id"] = "bb1b52262f7441a586f49068482f1e60" + accountReferenceModel["resource_type"] = "account" + + regionReferenceModel := make(map[string]interface{}) + regionReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south" + regionReferenceModel["name"] = "us-south" + + model := make(map[string]interface{}) + model["account"] = []map[string]interface{}{accountReferenceModel} + model["region"] = []map[string]interface{}{regionReferenceModel} + + assert.Equal(t, result, model) + } + + accountReferenceModel := new(vpcv1.AccountReference) + accountReferenceModel.ID = core.StringPtr("bb1b52262f7441a586f49068482f1e60") + accountReferenceModel.ResourceType = core.StringPtr("account") + + regionReferenceModel := new(vpcv1.RegionReference) + regionReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south") + regionReferenceModel.Name = core.StringPtr("us-south") + + model := new(vpcv1.ShareRemote) + model.Account = accountReferenceModel + model.Region = regionReferenceModel + + result, err := vpc.DataSourceIBMIsShareAccessorBindingsShareRemoteToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingsAccountReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["id"] = "bb1b52262f7441a586f49068482f1e60" + model["resource_type"] = "account" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.AccountReference) + model.ID = core.StringPtr("bb1b52262f7441a586f49068482f1e60") + model.ResourceType = core.StringPtr("account") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingsAccountReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingsRegionReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south" + model["name"] = "us-south" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.RegionReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south") + model.Name = core.StringPtr("us-south") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingsRegionReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorShareReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + shareReferenceDeletedModel := make(map[string]interface{}) + shareReferenceDeletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + accountReferenceModel := make(map[string]interface{}) + accountReferenceModel["id"] = "bb1b52262f7441a586f49068482f1e60" + accountReferenceModel["resource_type"] = "account" + + regionReferenceModel := make(map[string]interface{}) + regionReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south" + regionReferenceModel["name"] = "us-south" + + shareRemoteModel := make(map[string]interface{}) + shareRemoteModel["account"] = []map[string]interface{}{accountReferenceModel} + shareRemoteModel["region"] = []map[string]interface{}{regionReferenceModel} + + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::share:0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["deleted"] = []map[string]interface{}{shareReferenceDeletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["id"] = "0fe9e5d8-0a4d-4818-96ec-e99708644a58" + model["name"] = "my-share" + model["remote"] = []map[string]interface{}{shareRemoteModel} + model["resource_type"] = "share" + + assert.Equal(t, result, model) + } + + shareReferenceDeletedModel := new(vpcv1.ShareReferenceDeleted) + shareReferenceDeletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + accountReferenceModel := new(vpcv1.AccountReference) + accountReferenceModel.ID = core.StringPtr("bb1b52262f7441a586f49068482f1e60") + accountReferenceModel.ResourceType = core.StringPtr("account") + + regionReferenceModel := new(vpcv1.RegionReference) + regionReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south") + regionReferenceModel.Name = core.StringPtr("us-south") + + shareRemoteModel := new(vpcv1.ShareRemote) + shareRemoteModel.Account = accountReferenceModel + shareRemoteModel.Region = regionReferenceModel + + model := new(vpcv1.ShareAccessorBindingAccessorShareReference) + model.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::share:0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.Deleted = shareReferenceDeletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/shares/0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.ID = core.StringPtr("0fe9e5d8-0a4d-4818-96ec-e99708644a58") + model.Name = core.StringPtr("my-share") + model.Remote = shareRemoteModel + model.ResourceType = core.StringPtr("share") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorShareReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorWatsonxMachineLearningReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:pm-20:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34:6500f05d-a5b5-4ecf-91ba-0d12b9dee607" + model["resource_type"] = "watsonx_machine_learning" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ShareAccessorBindingAccessorWatsonxMachineLearningReference) + model.CRN = core.StringPtr("crn:v1:bluemix:public:pm-20:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34:6500f05d-a5b5-4ecf-91ba-0d12b9dee607") + model.ResourceType = core.StringPtr("watsonx_machine_learning") + + result, err := vpc.DataSourceIBMIsShareAccessorBindingsShareAccessorBindingAccessorWatsonxMachineLearningReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_share_test.go b/ibm/service/vpc/data_source_ibm_is_share_test.go index 180bc65cdd..d50e4d4e09 100644 --- a/ibm/service/vpc/data_source_ibm_is_share_test.go +++ b/ibm/service/vpc/data_source_ibm_is_share_test.go @@ -72,6 +72,7 @@ func TestAccIbmIsShareDataSourceAllArgs(t *testing.T) { resource.TestCheckResourceAttrSet("data.ibm_is_share.is_share", "zone"), resource.TestCheckResourceAttr("data.ibm_is_share.is_share", "tags.0", "sr1"), resource.TestCheckResourceAttr("data.ibm_is_share.is_share", "tags.1", "sr2"), + resource.TestCheckResourceAttrSet("data.ibm_is_share.is_share", "accessor_binding_role"), ), }, }, @@ -100,6 +101,7 @@ func testAccCheckIbmIsShareDataSourceConfig(vpcName, shareName string, shareSize name = "%s" } resource "ibm_is_share" "is_share" { + allowed_transit_encryption_modes = ["user_managed", "none"] zone = "us-south-2" name = "%s" size = %d diff --git a/ibm/service/vpc/data_source_ibm_is_shares.go b/ibm/service/vpc/data_source_ibm_is_shares.go index f4829e0671..0ee814a270 100644 --- a/ibm/service/vpc/data_source_ibm_is_shares.go +++ b/ibm/service/vpc/data_source_ibm_is_shares.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/vpc-go-sdk/vpcv1" ) @@ -38,6 +39,12 @@ func DataSourceIbmIsShares() *schema.Resource { Description: "Collection of file shares.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "allowed_transit_encryption_modes": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Allowed transit encryption modes", + }, "access_control_mode": { Type: schema.TypeString, Computed: true, @@ -372,6 +379,130 @@ func DataSourceIbmIsShares() *schema.Resource { Set: flex.ResourceIBMVPCHash, Description: "List of tags", }, + "origin_share": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The origin share this accessor share is referring to.This property will be present when the `accessor_binding_role` is `accessor`.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this file share.", + }, + "deleted": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates the referenced resource has been deleted, and providessome supplementary information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about deleted resources.", + }, + }, + }, + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this file share.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this file share.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this share. The name is unique across all shares in the region.", + }, + "remote": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this account.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "region": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this region.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this region.", + }, + }, + }, + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "accessor_binding_role": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The accessor binding role of this file share:- `none`: This file share is not participating in access with another file share- `origin`: This file share is the origin for one or more file shares (which may be in other accounts)- `accessor`: This file share is providing access to another file share (which may be in another account).", + }, + "accessor_bindings": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The accessor bindings for this file share. Each accessor binding identifies a resource (possibly in another account) with access to this file share's data.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this share accessor binding.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this share accessor binding.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, }, }, @@ -511,6 +642,24 @@ func dataSourceShareCollectionSharesToMap(meta interface{}, sharesItem vpcv1.Sha if sharesItem.AccessControlMode != nil { sharesMap["access_control_mode"] = *&sharesItem.AccessControlMode } + if !core.IsNil(sharesItem.AllowedTransitEncryptionModes) { + sharesMap["allowed_transit_encryption_modes"] = sharesItem.AllowedTransitEncryptionModes + } + if sharesItem.AccessorBindingRole != nil { + sharesMap["accessor_binding_role"] = sharesItem.AccessorBindingRole + } + accessorBindings := []map[string]interface{}{} + for _, accessorBindingsItem := range sharesItem.AccessorBindings { + accessorBindingsItemMap := ResourceIBMIsShareShareAccessorBindingReferenceToMap(&accessorBindingsItem) + accessorBindings = append(accessorBindings, accessorBindingsItemMap) + } + sharesMap["accessor_bindings"] = accessorBindings + + if !core.IsNil(sharesItem.OriginShare) { + originShareMap := ResourceIBMIsShareShareReferenceToMap(sharesItem.OriginShare) + + sharesMap["origin_share"] = []map[string]interface{}{originShareMap} + } sharesMap["replication_role"] = *sharesItem.ReplicationRole sharesMap["replication_status"] = *sharesItem.ReplicationStatus diff --git a/ibm/service/vpc/data_source_ibm_is_shares_test.go b/ibm/service/vpc/data_source_ibm_is_shares_test.go index 954bc13149..34fd6f9c78 100644 --- a/ibm/service/vpc/data_source_ibm_is_shares_test.go +++ b/ibm/service/vpc/data_source_ibm_is_shares_test.go @@ -52,6 +52,7 @@ func TestAccIbmIsSharesDataSourceAllArgs(t *testing.T) { resource.TestCheckResourceAttrSet("data.ibm_is_shares.is_shares", "shares.0.name"), resource.TestCheckResourceAttrSet("data.ibm_is_shares.is_shares", "shares.0.resource_type"), resource.TestCheckResourceAttrSet("data.ibm_is_shares.is_shares", "shares.0.size"), + resource.TestCheckResourceAttrSet("data.ibm_is_shares.is_shares", "shares.0.accessor_binding_role"), resource.TestCheckResourceAttrSet("data.ibm_is_shares.is_shares", "total_count"), ), }, diff --git a/ibm/service/vpc/resource_ibm_is_bare_metal_server.go b/ibm/service/vpc/resource_ibm_is_bare_metal_server.go index 5bc8c240bf..f0e3502abd 100644 --- a/ibm/service/vpc/resource_ibm_is_bare_metal_server.go +++ b/ibm/service/vpc/resource_ibm_is_bare_metal_server.go @@ -65,6 +65,7 @@ const ( isBareMetalServerStatusReasonsMoreInfo = "more_info" isBareMetalServerDeleteType = "delete_type" isBareMetalServerImage = "image" + isBareMetalServerFirmwareUpdateTypeAvailable = "firmware_update_type_available" isBareMetalServerKeys = "keys" isBareMetalServerUserData = "user_data" isBareMetalServerNicName = "name" @@ -174,6 +175,7 @@ func ResourceIBMIsBareMetalServer() *schema.Resource { }, isBareMetalServerBandwidth: { Type: schema.TypeInt, + Optional: true, Computed: true, Description: "The total bandwidth (in megabits per second)", }, @@ -217,6 +219,11 @@ func ResourceIBMIsBareMetalServer() *schema.Resource { Computed: true, Description: "The CRN for this bare metal server", }, + isBareMetalServerFirmwareUpdateTypeAvailable: { + Type: schema.TypeString, + Computed: true, + Description: "The type of firmware update available", + }, isBareMetalServerDisks: { Type: schema.TypeList, Computed: true, @@ -1058,17 +1065,16 @@ func ResourceIBMIsBareMetalServer() *schema.Resource { }, isBareMetalServerKeys: { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - DiffSuppressFunc: flex.ApplyOnce, - Description: "SSH key Ids for the bare metal server", + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + Description: "SSH key Ids for the bare metal server", }, isBareMetalServerImage: { Type: schema.TypeString, - ForceNew: true, + ForceNew: false, Required: true, Description: "image id", }, @@ -1081,7 +1087,7 @@ func ResourceIBMIsBareMetalServer() *schema.Resource { isBareMetalServerUserData: { Type: schema.TypeString, - ForceNew: true, + ForceNew: false, Optional: true, Description: "User data given for the bare metal server", }, @@ -1240,6 +1246,10 @@ func resourceIBMISBareMetalServerCreate(context context.Context, d *schema.Resou imageStr = image.(string) } + if bandwidthIntf, ok := d.GetOk(isBareMetalServerBandwidth); ok { + bandwidth := int64(bandwidthIntf.(int)) + options.Bandwidth = &bandwidth + } // enable secure boot if _, ok := d.GetOkExists(isBareMetalServerEnableSecureBoot); ok { @@ -1943,6 +1953,9 @@ func bareMetalServerGet(context context.Context, d *schema.ResourceData, meta in } d.Set(isBareMetalServerCPU, cpuList) d.Set(isBareMetalServerCRN, *bms.CRN) + if bms.Firmware != nil && bms.Firmware.Update != nil { + d.Set(isBareMetalServerFirmwareUpdateTypeAvailable, *bms.Firmware.Update) + } //enable secure boot if err = d.Set(isBareMetalServerEnableSecureBoot, bms.EnableSecureBoot); err != nil { @@ -2344,6 +2357,50 @@ func bareMetalServerUpdate(context context.Context, d *schema.ResourceData, meta if err != nil { return err } + if d.HasChange("image") || d.HasChange("keys") || d.HasChange("user_data") { + stopServerIfStartingForInitialization := false + newImageId := d.Get("image").(string) + initializationPatch := &vpcv1.ReplaceBareMetalServerInitializationOptions{ + ID: &id, + Image: &vpcv1.ImageIdentityByID{ + ID: &newImageId, + }, + } + // apply the user data file, if its not updated use the existing + newUserData := d.Get("user_data").(string) + initializationPatch.UserData = &newUserData + // apply the keys, if its not updated use the existing + keySet := d.Get(isBareMetalServerKeys).(*schema.Set) + if keySet.Len() != 0 { + keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) + for i, key := range keySet.List() { + keystr := key.(string) + keyobjs[i] = &vpcv1.KeyIdentity{ + ID: &keystr, + } + } + initializationPatch.Keys = keyobjs + } + + stopServerIfStartingForInitialization, err = resourceStopServerIfRunning(id, "hard", d, context, sess, stopServerIfStartingForInitialization) + if err != nil { + return err + } + _, res, err := sess.ReplaceBareMetalServerInitialization(initializationPatch) + if err != nil { + return fmt.Errorf("ReplaceBareMetalServerInitialization failed %s\n%s", err, res) + } + _, err = isWaitForBareMetalServerStoppedOnReload(sess, d.Id(), d.Timeout(schema.TimeoutUpdate), d) + if err != nil { + return err + } + if stopServerIfStartingForInitialization { + _, err = resourceStartServerIfStopped(id, "hard", d, context, sess, stopServerIfStartingForInitialization) + if err != nil { + return err + } + } + } isServerStopped := false // network attachments @@ -3427,6 +3484,12 @@ func bareMetalServerUpdate(context context.Context, d *schema.ResourceData, meta bmsPatchModel := &vpcv1.BareMetalServerPatch{} flag := false + if d.HasChange(isBareMetalServerBandwidth) && !d.IsNewResource() { + bandwidth := int64(d.Get(isBareMetalServerBandwidth).(int)) + bmsPatchModel.Bandwidth = &bandwidth + flag = true + } + if d.HasChange(isBareMetalServerEnableSecureBoot) { newEnableSecureBoot := d.Get(isBareMetalServerEnableSecureBoot).(bool) bmsPatchModel.EnableSecureBoot = &newEnableSecureBoot @@ -3781,6 +3844,73 @@ func isBareMetalServerRefreshFunc(client *vpcv1.VpcV1, id string, d *schema.Reso return bms, isBareMetalServerStatusPending, nil } } +func isWaitForBareMetalServerStoppedOnReload(client *vpcv1.VpcV1, id string, timeout time.Duration, d *schema.ResourceData) (interface{}, error) { + log.Printf("Waiting for Bare Metal Server (%s) to be stopped for reload success.", id) + communicator := make(chan interface{}) + stateConf := &resource.StateChangeConf{ + Pending: []string{isBareMetalServerStatusPending, isBareMetalServerActionStatusStarting, "reinitializing"}, + Target: []string{isBareMetalServerStatusRunning, isBareMetalServerStatusFailed, "stopped"}, + Refresh: isBareMetalServerRefreshFuncForReload(client, id, d, communicator), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + return stateConf.WaitForState() +} + +func isBareMetalServerRefreshFuncForReload(client *vpcv1.VpcV1, id string, d *schema.ResourceData, communicator chan interface{}) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + bmsgetoptions := &vpcv1.GetBareMetalServerOptions{ + ID: &id, + } + bms, response, err := client.GetBareMetalServer(bmsgetoptions) + if err != nil { + return nil, "", fmt.Errorf("[ERROR] Error getting Bare Metal Server: %s\n%s", err, response) + } + d.Set(isBareMetalServerStatus, *bms.Status) + + select { + case data := <-communicator: + return nil, "", data.(error) + default: + fmt.Println("no message sent") + } + + if *bms.Status == "running" || *bms.Status == "failed" { + // let know the isRestartStartAction() to stop + close(communicator) + if *bms.Status == "failed" { + bmsStatusReason := bms.StatusReasons + + //set the status reasons + if bms.StatusReasons != nil { + statusReasonsList := make([]map[string]interface{}, 0) + for _, sr := range bms.StatusReasons { + currentSR := map[string]interface{}{} + if sr.Code != nil && sr.Message != nil { + currentSR[isBareMetalServerStatusReasonsCode] = *sr.Code + currentSR[isBareMetalServerStatusReasonsMessage] = *sr.Message + if sr.MoreInfo != nil { + currentSR[isBareMetalServerStatusReasonsMoreInfo] = *sr.MoreInfo + } + statusReasonsList = append(statusReasonsList, currentSR) + } + } + d.Set(isBareMetalServerStatusReasons, statusReasonsList) + } + + out, err := json.MarshalIndent(bmsStatusReason, "", " ") + if err != nil { + return bms, *bms.Status, fmt.Errorf("[ERROR] The Bare Metal Server (%s) went into failed state during the operation \n [WARNING] Running terraform apply again will remove the tainted bare metal server and attempt to create the bare metal server again replacing the previous configuration", *bms.ID) + } + return bms, *bms.Status, fmt.Errorf("[ERROR] Bare Metal Server (%s) went into failed state during the operation \n (%+v) \n [WARNING] Running terraform apply again will remove the tainted Bare Metal Server and attempt to create the Bare Metal Server again replacing the previous configuration", *bms.ID, string(out)) + } + return bms, *bms.Status, nil + + } + return bms, *bms.Status, nil + } +} func isWaitForBareMetalServerActionStop(bmsC *vpcv1.VpcV1, timeout time.Duration, id string, d *schema.ResourceData) (interface{}, error) { communicator := make(chan interface{}) diff --git a/ibm/service/vpc/resource_ibm_is_bare_metal_server_initialization.go b/ibm/service/vpc/resource_ibm_is_bare_metal_server_initialization.go new file mode 100644 index 0000000000..5619823a8d --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_bare_metal_server_initialization.go @@ -0,0 +1,222 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "encoding/json" + "fmt" + "log" + "time" + + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func ResourceIBMIsBareMetalServerInitialization() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMISBareMetalServerInitializationCreate, + ReadContext: resourceIBMISBareMetalServerInitializationRead, + DeleteContext: resourceIBMISBareMetalServerInitializationDelete, + Importer: &schema.ResourceImporter{}, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(15 * time.Minute), + Update: schema.DefaultTimeout(15 * time.Minute), + Delete: schema.DefaultTimeout(15 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + + isBareMetalServerID: { + Type: schema.TypeString, + ForceNew: true, + Required: true, + Description: "Bare metal server identifier", + }, + isBareMetalServerImage: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The image to be used when provisioning the bare metal server.", + }, + isBareMetalServerKeys: { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + Description: "SSH key Ids for the bare metal server", + }, + "user_data": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Bare metal server user data to replace initialization", + }, + }, + } +} + +func resourceIBMISBareMetalServerInitializationCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + + var bareMetalServerId, userdata, image string + if bmsId, ok := d.GetOk(isBareMetalServerID); ok { + bareMetalServerId = bmsId.(string) + } + if userdataOk, ok := d.GetOk("user_data"); ok { + userdata = userdataOk.(string) + } + if imageOk, ok := d.GetOk("image"); ok { + image = imageOk.(string) + } + + sess, err := vpcClient(meta) + if err != nil { + return diag.FromErr(err) + } + stopServerIfStartingForInitialization := false + options := &vpcv1.GetBareMetalServerInitializationOptions{ + ID: &bareMetalServerId, + } + stopServerIfStartingForInitialization, err = resourceStopServerIfRunning(bareMetalServerId, "hard", d, context, sess, stopServerIfStartingForInitialization) + if err != nil { + return diag.FromErr(err) + } + init, response, err := sess.GetBareMetalServerInitializationWithContext(context, options) + if err != nil || init == nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error get bare metal server initialization (%s) err %s\n%s", bareMetalServerId, err, response)) + } + d.SetId(bareMetalServerId) + + initializationReplaceOptions := &vpcv1.ReplaceBareMetalServerInitializationOptions{ + ID: &bareMetalServerId, + Image: &vpcv1.ImageIdentityByID{ + ID: &image, + }, + UserData: &userdata, + } + keySet := d.Get(isBareMetalServerKeys).(*schema.Set) + if keySet.Len() != 0 { + keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) + for i, key := range keySet.List() { + keystr := key.(string) + keyobjs[i] = &vpcv1.KeyIdentity{ + ID: &keystr, + } + } + initializationReplaceOptions.Keys = keyobjs + } + initInitializationReplace, response, err := sess.ReplaceBareMetalServerInitializationWithContext(context, initializationReplaceOptions) + if err != nil || initInitializationReplace == nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error initialization replacing bare metal server (%s) err %s\n%s", bareMetalServerId, err, response)) + } + + _, err = isWaitForBareMetalServerInitializationStopped(sess, bareMetalServerId, d.Timeout(schema.TimeoutUpdate), d) + if err != nil { + return diag.FromErr(err) + } + if stopServerIfStartingForInitialization { + _, err = resourceStartServerIfStopped(bareMetalServerId, "hard", d, context, sess, stopServerIfStartingForInitialization) + if err != nil { + return diag.FromErr(err) + } + } + err = BareMetalServerInitializationGet(d, sess, bareMetalServerId) + if err != nil { + return diag.FromErr(err) + } + return nil +} + +func BareMetalServerInitializationGet(d *schema.ResourceData, sess *vpcv1.VpcV1, bareMetalServerId string) error { + + options := &vpcv1.GetBareMetalServerInitializationOptions{ + ID: &bareMetalServerId, + } + init, response, err := sess.GetBareMetalServerInitialization(options) + if err != nil || init == nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + return fmt.Errorf("[ERROR] Error fetching bare metal server (%s) initialization err %s\n%s", bareMetalServerId, err, response) + } + + d.Set(isBareMetalServerID, bareMetalServerId) + return nil +} + +func resourceIBMISBareMetalServerInitializationRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var bareMetalServerId string + if bmsId, ok := d.GetOk(isBareMetalServerID); ok { + bareMetalServerId = bmsId.(string) + } + sess, err := vpcClient(meta) + if err != nil { + return diag.FromErr(err) + } + err = BareMetalServerInitializationGet(d, sess, bareMetalServerId) + if err != nil { + return diag.FromErr(err) + } + return nil +} +func resourceIBMISBareMetalServerInitializationDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + d.SetId("") + + return nil +} + +func isWaitForBareMetalServerInitializationStopped(client *vpcv1.VpcV1, id string, timeout time.Duration, d *schema.ResourceData) (interface{}, error) { + log.Printf("Waiting for Bare Metal Server (%s) to be stopped for reload success.", id) + communicator := make(chan interface{}) + stateConf := &resource.StateChangeConf{ + Pending: []string{isBareMetalServerStatusPending, isBareMetalServerActionStatusStarting, "reinitializing"}, + Target: []string{isBareMetalServerStatusRunning, isBareMetalServerStatusFailed, "stopped"}, + Refresh: isBareMetalServerInitializationRefreshFunc(client, id, d, communicator), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + return stateConf.WaitForState() +} + +func isBareMetalServerInitializationRefreshFunc(client *vpcv1.VpcV1, id string, d *schema.ResourceData, communicator chan interface{}) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + bmsgetoptions := &vpcv1.GetBareMetalServerOptions{ + ID: &id, + } + bms, response, err := client.GetBareMetalServer(bmsgetoptions) + if err != nil { + return nil, "", fmt.Errorf("[ERROR] Error getting Bare Metal Server: %s\n%s", err, response) + } + + select { + case data := <-communicator: + return nil, "", data.(error) + default: + fmt.Println("no message sent") + } + + if *bms.Status == "running" || *bms.Status == "failed" { + // let know the isRestartStartAction() to stop + close(communicator) + if *bms.Status == "failed" { + bmsStatusReason := bms.StatusReasons + + out, err := json.MarshalIndent(bmsStatusReason, "", " ") + if err != nil { + return bms, *bms.Status, fmt.Errorf("[ERROR] The Bare Metal Server (%s) went into failed state during the operation \n [WARNING] Running terraform apply again will remove the tainted bare metal server and attempt to create the bare metal server again replacing the previous configuration", *bms.ID) + } + return bms, *bms.Status, fmt.Errorf("[ERROR] Bare Metal Server (%s) went into failed state during the operation \n (%+v) \n [WARNING] Running terraform apply again will remove the tainted Bare Metal Server and attempt to create the Bare Metal Server again replacing the previous configuration", *bms.ID, string(out)) + } + return bms, *bms.Status, nil + + } + return bms, *bms.Status, nil + } +} diff --git a/ibm/service/vpc/resource_ibm_is_bare_metal_server_initialization_test.go b/ibm/service/vpc/resource_ibm_is_bare_metal_server_initialization_test.go new file mode 100644 index 0000000000..8adca3301e --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_bare_metal_server_initialization_test.go @@ -0,0 +1,140 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "strings" + "testing" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccReinitIBMISBareMetalServerreinitbasic(t *testing.T) { + var server string + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf-server-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tfip-subnet-%d", acctest.RandIntRange(10, 100)) + publicKey := strings.TrimSpace(` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR +`) + sshname := fmt.Sprintf("tf-sshname-%d", acctest.RandIntRange(10, 100)) + userdata := "a" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISBareMetalServerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISBareMetalServerInitializationReplaceConfig(vpcname, subnetname, sshname, publicKey, name, userdata), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISBareMetalServerExists("ibm_is_bare_metal_server.testacc_bms", server), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "zone", acc.ISZoneName), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "user_data", userdata), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "image", acc.IsBareMetalServerImage), + ), + }, + { + Config: testAccCheckIBMISBareMetalServerInitializationReplaceConfigUpdate(vpcname, subnetname, sshname, publicKey, name, userdata, userdata), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISBareMetalServerExists("ibm_is_bare_metal_server.testacc_bms", server), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "zone", acc.ISZoneName), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "user_data", userdata), + resource.TestCheckResourceAttrSet( + "ibm_is_bare_metal_server_initialization.testacc_bms_initialization", "id"), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "image", acc.IsBareMetalServerImage), + ), + }, + }, + }) +} + +func testAccCheckIBMISBareMetalServerInitializationReplaceConfig(vpcname, subnetname, sshname, publicKey, name, userData1 string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + total_ipv4_address_count = 16 + } + + resource "ibm_is_ssh_key" "testacc_sshkey" { + name = "%s" + public_key = "%s" + } + + resource "ibm_is_bare_metal_server" "testacc_bms" { + profile = "%s" + name = "%s" + image = "%s" + zone = "%s" + user_data = "%s" + keys = [ibm_is_ssh_key.testacc_sshkey.id] + primary_network_interface { + subnet = ibm_is_subnet.testacc_subnet.id + } + vpc = ibm_is_vpc.testacc_vpc.id + } + +`, vpcname, subnetname, acc.ISZoneName, sshname, publicKey, acc.IsBareMetalServerProfileName, name, acc.IsBareMetalServerImage, acc.ISZoneName, userData1) +} +func testAccCheckIBMISBareMetalServerInitializationReplaceConfigUpdate(vpcname, subnetname, sshname, publicKey, name, userData1, userData2 string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + total_ipv4_address_count = 16 + } + + resource "ibm_is_ssh_key" "testacc_sshkey" { + name = "%s" + public_key = "%s" + } + + resource "ibm_is_bare_metal_server" "testacc_bms" { + profile = "%s" + name = "%s" + image = "%s" + zone = "%s" + user_data = "%s" + keys = [ibm_is_ssh_key.testacc_sshkey.id] + primary_network_interface { + subnet = ibm_is_subnet.testacc_subnet.id + } + vpc = ibm_is_vpc.testacc_vpc.id + lifecycle { + ignore_changes = [ image, keys, user_data ] + } + } + resource "ibm_is_bare_metal_server_initialization" "testacc_bms_initialization" { + bare_metal_server = ibm_is_bare_metal_server.testacc_bms.id + image = "%s" + keys = [ibm_is_ssh_key.testacc_sshkey.id] + user_data = "%s" + } + +`, vpcname, subnetname, acc.ISZoneName, sshname, publicKey, acc.IsBareMetalServerProfileName, name, acc.IsBareMetalServerImage, acc.ISZoneName, userData1, acc.IsBareMetalServerImage2, userData2) +} diff --git a/ibm/service/vpc/resource_ibm_is_bare_metal_server_test.go b/ibm/service/vpc/resource_ibm_is_bare_metal_server_test.go index 545ff26719..3a96f58756 100644 --- a/ibm/service/vpc/resource_ibm_is_bare_metal_server_test.go +++ b/ibm/service/vpc/resource_ibm_is_bare_metal_server_test.go @@ -46,6 +46,77 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE }, }) } + +func TestAccIBMISBareMetalServer_firmwareUpdate(t *testing.T) { + var server string + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf-server-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tfip-subnet-%d", acctest.RandIntRange(10, 100)) + publicKey := strings.TrimSpace(` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR +`) + sshname := fmt.Sprintf("tf-sshname-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISBareMetalServerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISBareMetalServerConfig(vpcname, subnetname, sshname, publicKey, name), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISBareMetalServerExists("ibm_is_bare_metal_server.testacc_bms", server), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "name", name), + resource.TestCheckResourceAttrSet( + "ibm_is_bare_metal_server.testacc_bms", "firmware_update_type_available"), + ), + }, + }, + }) +} + +func TestAccIBMISBareMetalServer_bandwidth(t *testing.T) { + var server string + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + pipName := fmt.Sprintf("tf-vpc-pip-%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf-server-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tfip-subnet-%d", acctest.RandIntRange(10, 100)) + publicKey := strings.TrimSpace(` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR +`) + sshname := fmt.Sprintf("tf-sshname-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISBareMetalServerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISBareMetalServerBandwidthConfig(vpcname, subnetname, sshname, publicKey, name, pipName, 10000), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISBareMetalServerExists("ibm_is_bare_metal_server.testacc_bms", server), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "zone", acc.ISZoneName), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "bandwidth", "10000"), + ), + }, + { + Config: testAccCheckIBMISBareMetalServerBandwidthConfig(vpcname, subnetname, sshname, publicKey, name, pipName, 25000), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISBareMetalServerExists("ibm_is_bare_metal_server.testacc_bms", server), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "bandwidth", "25000"), + ), + }, + }, + }) +} func TestAccIBMISBareMetalServerVNI_basic(t *testing.T) { var server string vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) @@ -486,6 +557,48 @@ func testAccCheckIBMISBareMetalServerConfig(vpcname, subnetname, sshname, public } `, vpcname, subnetname, acc.ISZoneName, sshname, publicKey, acc.IsBareMetalServerProfileName, name, acc.IsBareMetalServerImage, acc.ISZoneName) } + +func testAccCheckIBMISBareMetalServerBandwidthConfig(vpcname, subnetname, sshname, publicKey, name, pipName string, bandwidth int) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + total_ipv4_address_count = 16 + } + + resource "ibm_is_ssh_key" "testacc_sshkey" { + name = "%s" + public_key = "%s" + } + + resource "ibm_is_bare_metal_server" "testacc_bms" { + bandwidth = %d + profile = "%s" + name = "%s" + image = "%s" + zone = "%s" + keys = [ibm_is_ssh_key.testacc_sshkey.id] + primary_network_attachment { + virtual_network_interface { + auto_delete = true + enable_infrastructure_nat = true + primary_ip { + name = "%s" + } + subnet = ibm_is_subnet.testacc_subnet.id + } + allowed_vlans = [100, 102] + } + vpc = ibm_is_vpc.testacc_vpc.id + } +`, vpcname, subnetname, acc.ISZoneName, sshname, publicKey, bandwidth, acc.IsBareMetalServerProfileName, name, acc.IsBareMetalServerImage, acc.ISZoneName, pipName) +} + func testAccCheckIBMISBareMetalServerVNIConfig(vpcname, subnetname, sshname, publicKey, vniname, name string) string { return fmt.Sprintf(` resource "ibm_is_vpc" "testacc_vpc" { @@ -509,6 +622,12 @@ func testAccCheckIBMISBareMetalServerVNIConfig(vpcname, subnetname, sshname, pub enable_infrastructure_nat = true allow_ip_spoofing = true } + resource "ibm_is_virtual_network_interface" "testacc_vni2"{ + name = "%s-1" + subnet = ibm_is_subnet.testacc_subnet.id + enable_infrastructure_nat = true + allow_ip_spoofing = true + } resource "ibm_is_bare_metal_server" "testacc_bms" { profile = "%s" name = "%s" @@ -522,9 +641,16 @@ func testAccCheckIBMISBareMetalServerVNIConfig(vpcname, subnetname, sshname, pub } allowed_vlans = [100, 102] } + network_attachments { + name = "test-vni-200-202" + virtual_network_interface { + id = ibm_is_virtual_network_interface.testacc_vni2.id + } + allowed_vlans = [200, 202] + } vpc = ibm_is_vpc.testacc_vpc.id } -`, vpcname, subnetname, acc.ISZoneName, sshname, publicKey, vniname, acc.IsBareMetalServerProfileName, name, acc.IsBareMetalServerImage, acc.ISZoneName) +`, vpcname, subnetname, acc.ISZoneName, sshname, publicKey, vniname, vniname, acc.IsBareMetalServerProfileName, name, acc.IsBareMetalServerImage, acc.ISZoneName) } func testAccCheckIBMISBareMetalServerVNIPSFMConfig(vpcname, subnetname, sshname, publicKey, vniname1, vniname2, psfm1, psfm2, name string) string { @@ -852,3 +978,89 @@ func testAccCheckIBMISBareMetalServerReservedIpConfig(vpcname, subnetname, sshna } `, vpcname, subnetname, acc.ISZoneName, sshname, publicKey, acc.IsBareMetalServerProfileName, name, acc.IsBareMetalServerImage, acc.ISZoneName) } + +func TestAccIBMISBareMetalServer_updateInitialization(t *testing.T) { + var server string + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf-server-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tfip-subnet-%d", acctest.RandIntRange(10, 100)) + userdata1 := "a" + userdata2 := "b" + publicKey := strings.TrimSpace(` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR +`) + sshname := fmt.Sprintf("tf-sshname-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISBareMetalServerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISBareMetalServerInitializationConfig(vpcname, subnetname, sshname, publicKey, name, acc.IsBareMetalServerImage, userdata1), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISBareMetalServerExists("ibm_is_bare_metal_server.testacc_bms", server), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "zone", acc.ISZoneName), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "image", acc.IsBareMetalServerImage), + resource.TestCheckResourceAttrSet( + "ibm_is_bare_metal_server.testacc_bms", "keys.#"), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "user_data", userdata1), + ), + }, + { + Config: testAccCheckIBMISBareMetalServerInitializationConfig(vpcname, subnetname, sshname, publicKey, name, acc.IsBareMetalServerImage2, userdata2), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISBareMetalServerExists("ibm_is_bare_metal_server.testacc_bms", server), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "zone", acc.ISZoneName), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "image", acc.IsBareMetalServerImage2), + resource.TestCheckResourceAttrSet( + "ibm_is_bare_metal_server.testacc_bms", "keys.#"), + resource.TestCheckResourceAttr( + "ibm_is_bare_metal_server.testacc_bms", "user_data", userdata2), + ), + }, + }, + }) +} + +func testAccCheckIBMISBareMetalServerInitializationConfig(vpcname, subnetname, sshname, publicKey, name, image, userdata string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + total_ipv4_address_count = 16 + } + + resource "ibm_is_ssh_key" "testacc_sshkey" { + name = "%s" + public_key = "%s" + } + + resource "ibm_is_bare_metal_server" "testacc_bms" { + profile = "%s" + name = "%s" + image = "%s" + zone = "%s" + user_data = "%s" + keys = [ibm_is_ssh_key.testacc_sshkey.id] + primary_network_interface { + subnet = ibm_is_subnet.testacc_subnet.id + } + vpc = ibm_is_vpc.testacc_vpc.id + } +`, vpcname, subnetname, acc.ISZoneName, sshname, publicKey, acc.IsBareMetalServerProfileName, name, image, acc.ISZoneName, userdata) +} diff --git a/ibm/service/vpc/resource_ibm_is_instance.go b/ibm/service/vpc/resource_ibm_is_instance.go index e716131d17..72d6fcb543 100644 --- a/ibm/service/vpc/resource_ibm_is_instance.go +++ b/ibm/service/vpc/resource_ibm_is_instance.go @@ -400,7 +400,7 @@ func ResourceIBMISInstance() *schema.Resource { Optional: true, ForceNew: true, ConflictsWith: []string{"catalog_offering.0.version_crn"}, - RequiredWith: []string{isInstanceZone, isInstancePrimaryNetworkInterface, isInstanceKeys, isInstanceVPC, isInstanceProfile}, + RequiredWith: []string{isInstanceZone, isInstancePrimaryNetworkInterface, isInstanceVPC, isInstanceProfile}, Description: "Identifies a catalog offering by a unique CRN property", }, isInstanceCatalogOfferingVersionCrn: { @@ -408,7 +408,7 @@ func ResourceIBMISInstance() *schema.Resource { Optional: true, ForceNew: true, ConflictsWith: []string{"catalog_offering.0.offering_crn"}, - RequiredWith: []string{isInstanceZone, isInstancePrimaryNetworkInterface, isInstanceKeys, isInstanceVPC, isInstanceProfile}, + RequiredWith: []string{isInstanceZone, isInstancePrimaryNetworkInterface, isInstanceVPC, isInstanceProfile}, Description: "Identifies a version of a catalog offering by a unique CRN property", }, isInstanceCatalogOfferingPlanCrn: { @@ -1143,7 +1143,7 @@ func ResourceIBMISInstance() *schema.Resource { Optional: true, ConflictsWith: []string{"boot_volume.0.snapshot", "boot_volume.0.snapshot_crn", "catalog_offering.0.offering_crn", "catalog_offering.0.version_crn", "boot_volume.0.volume_id"}, AtLeastOneOf: []string{isInstanceImage, isInstanceSourceTemplate, "boot_volume.0.snapshot", "boot_volume.0.snapshot_crn", "catalog_offering.0.offering_crn", "catalog_offering.0.version_crn", "boot_volume.0.volume_id"}, - RequiredWith: []string{isInstanceZone, isInstanceKeys, isInstanceVPC, isInstanceProfile}, + RequiredWith: []string{isInstanceZone, isInstanceVPC, isInstanceProfile}, Description: "image id", }, @@ -1159,7 +1159,7 @@ func ResourceIBMISInstance() *schema.Resource { Optional: true, ForceNew: true, Computed: true, - RequiredWith: []string{isInstanceZone, isInstanceProfile, isInstanceKeys, isInstanceVPC}, + RequiredWith: []string{isInstanceZone, isInstanceProfile, isInstanceVPC}, AtLeastOneOf: []string{isInstanceImage, isInstanceSourceTemplate, "boot_volume.0.volume_id", "boot_volume.0.snapshot", "boot_volume.0.snapshot_crn", "catalog_offering.0.offering_crn", "catalog_offering.0.version_crn"}, ConflictsWith: []string{isInstanceImage, isInstanceSourceTemplate, "boot_volume.0.snapshot", "boot_volume.0.snapshot_crn", "boot_volume.0.name", "boot_volume.0.encryption", "catalog_offering.0.offering_crn", "catalog_offering.0.version_crn"}, Description: "The unique identifier for this volume", @@ -1179,7 +1179,7 @@ func ResourceIBMISInstance() *schema.Resource { isInstanceVolumeSnapshot: { Type: schema.TypeString, - RequiredWith: []string{isInstanceZone, isInstanceProfile, isInstanceKeys, isInstanceVPC}, + RequiredWith: []string{isInstanceZone, isInstanceProfile, isInstanceVPC}, AtLeastOneOf: []string{isInstanceImage, isInstanceSourceTemplate, "boot_volume.0.snapshot", "boot_volume.0.snapshot_crn", "catalog_offering.0.offering_crn", "catalog_offering.0.version_crn", "boot_volume.0.volume_id"}, ConflictsWith: []string{isInstanceImage, isInstanceSourceTemplate, "catalog_offering.0.offering_crn", "catalog_offering.0.version_crn", "boot_volume.0.volume_id", "boot_volume.0.snapshot_crn"}, Optional: true, @@ -1188,7 +1188,7 @@ func ResourceIBMISInstance() *schema.Resource { }, isInstanceVolumeSnapshotCrn: { Type: schema.TypeString, - RequiredWith: []string{isInstanceZone, isInstanceProfile, isInstanceKeys, isInstanceVPC}, + RequiredWith: []string{isInstanceZone, isInstanceProfile, isInstanceVPC}, AtLeastOneOf: []string{isInstanceImage, isInstanceSourceTemplate, "boot_volume.0.snapshot", "boot_volume.0.snapshot_crn", "catalog_offering.0.offering_crn", "catalog_offering.0.version_crn", "boot_volume.0.volume_id"}, ConflictsWith: []string{isInstanceImage, isInstanceSourceTemplate, "catalog_offering.0.offering_crn", "catalog_offering.0.version_crn", "boot_volume.0.volume_id", "boot_volume.0.snapshot"}, Optional: true, @@ -2121,16 +2121,18 @@ func instanceCreateByImage(d *schema.ResourceData, meta interface{}, profile, na instanceproto.NetworkInterfaces = intfs } - keySet := d.Get(isInstanceKeys).(*schema.Set) - if keySet.Len() != 0 { - keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) - for i, key := range keySet.List() { - keystr := key.(string) - keyobjs[i] = &vpcv1.KeyIdentity{ - ID: &keystr, + if keySetIntf, ok := d.GetOk(isInstanceKeys); ok { + keySet := keySetIntf.(*schema.Set) + if keySet.Len() != 0 { + keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) + for i, key := range keySet.List() { + keystr := key.(string) + keyobjs[i] = &vpcv1.KeyIdentity{ + ID: &keystr, + } } + instanceproto.Keys = keyobjs } - instanceproto.Keys = keyobjs } if userdata, ok := d.GetOk(isInstanceUserData); ok { @@ -2568,16 +2570,18 @@ func instanceCreateByCatalogOffering(d *schema.ResourceData, meta interface{}, p instanceproto.NetworkInterfaces = intfs } - keySet := d.Get(isInstanceKeys).(*schema.Set) - if keySet.Len() != 0 { - keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) - for i, key := range keySet.List() { - keystr := key.(string) - keyobjs[i] = &vpcv1.KeyIdentity{ - ID: &keystr, + if keySetIntf, ok := d.GetOk(isInstanceKeys); ok { + keySet := keySetIntf.(*schema.Set) + if keySet.Len() != 0 { + keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) + for i, key := range keySet.List() { + keystr := key.(string) + keyobjs[i] = &vpcv1.KeyIdentity{ + ID: &keystr, + } } + instanceproto.Keys = keyobjs } - instanceproto.Keys = keyobjs } if userdata, ok := d.GetOk(isInstanceUserData); ok { @@ -2994,16 +2998,18 @@ func instanceCreateByTemplate(d *schema.ResourceData, meta interface{}, profile, instanceproto.NetworkInterfaces = intfs } - keySet := d.Get(isInstanceKeys).(*schema.Set) - if keySet.Len() != 0 { - keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) - for i, key := range keySet.List() { - keystr := key.(string) - keyobjs[i] = &vpcv1.KeyIdentity{ - ID: &keystr, + if keySetIntf, ok := d.GetOk(isInstanceKeys); ok { + keySet := keySetIntf.(*schema.Set) + if keySet.Len() != 0 { + keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) + for i, key := range keySet.List() { + keystr := key.(string) + keyobjs[i] = &vpcv1.KeyIdentity{ + ID: &keystr, + } } + instanceproto.Keys = keyobjs } - instanceproto.Keys = keyobjs } if userdata, ok := d.GetOk(isInstanceUserData); ok { @@ -3427,16 +3433,18 @@ func instanceCreateBySnapshot(d *schema.ResourceData, meta interface{}, profile, instanceproto.NetworkInterfaces = intfs } - keySet := d.Get(isInstanceKeys).(*schema.Set) - if keySet.Len() != 0 { - keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) - for i, key := range keySet.List() { - keystr := key.(string) - keyobjs[i] = &vpcv1.KeyIdentity{ - ID: &keystr, + if keySetIntf, ok := d.GetOk(isInstanceKeys); ok { + keySet := keySetIntf.(*schema.Set) + if keySet.Len() != 0 { + keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) + for i, key := range keySet.List() { + keystr := key.(string) + keyobjs[i] = &vpcv1.KeyIdentity{ + ID: &keystr, + } } + instanceproto.Keys = keyobjs } - instanceproto.Keys = keyobjs } if userdata, ok := d.GetOk(isInstanceUserData); ok { @@ -3826,16 +3834,18 @@ func instanceCreateByVolume(d *schema.ResourceData, meta interface{}, profile, n instanceproto.NetworkInterfaces = intfs } - keySet := d.Get(isInstanceKeys).(*schema.Set) - if keySet.Len() != 0 { - keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) - for i, key := range keySet.List() { - keystr := key.(string) - keyobjs[i] = &vpcv1.KeyIdentity{ - ID: &keystr, + if keySetIntf, ok := d.GetOk(isInstanceKeys); ok { + keySet := keySetIntf.(*schema.Set) + if keySet.Len() != 0 { + keyobjs := make([]vpcv1.KeyIdentityIntf, keySet.Len()) + for i, key := range keySet.List() { + keystr := key.(string) + keyobjs[i] = &vpcv1.KeyIdentity{ + ID: &keystr, + } } + instanceproto.Keys = keyobjs } - instanceproto.Keys = keyobjs } if userdata, ok := d.GetOk(isInstanceUserData); ok { diff --git a/ibm/service/vpc/resource_ibm_is_instance_test.go b/ibm/service/vpc/resource_ibm_is_instance_test.go index 229fba272d..e1e34f5e2d 100644 --- a/ibm/service/vpc/resource_ibm_is_instance_test.go +++ b/ibm/service/vpc/resource_ibm_is_instance_test.go @@ -75,6 +75,60 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE }, }) } + +func TestAccIBMISInstanceWithoutKeys_basic(t *testing.T) { + var instance string + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf-instnace-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tf-subnet-%d", acctest.RandIntRange(10, 100)) + userData1 := "a" + userData2 := "b" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceWithoutKeysConfig(vpcname, subnetname, name, userData1), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISInstanceExists("ibm_is_instance.testacc_instance", instance), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "user_data", userData1), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "zone", acc.ISZoneName), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "vcpu.#"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "vcpu.0.manufacturer"), + ), + }, + { + Config: testAccCheckIBMISInstanceWithoutKeysConfig(vpcname, subnetname, name, userData2), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISInstanceExists("ibm_is_instance.testacc_instance", instance), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "user_data", userData2), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "zone", acc.ISZoneName), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "primary_network_interface.0.port_speed"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "vcpu.#"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "vcpu.0.manufacturer"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "numa_count"), + ), + }, + }, + }) +} + func TestAccIBMISInstance_concom(t *testing.T) { var instance string vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) @@ -1403,6 +1457,37 @@ func testAccCheckIBMISInstanceConfig(vpcname, subnetname, sshname, publicKey, na } }`, vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, sshname, publicKey, name, acc.IsImage, acc.InstanceProfileName, userData, acc.ISZoneName) } + +func testAccCheckIBMISInstanceWithoutKeysConfig(vpcname, subnetname, name, userData string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + ipv4_cidr_block = "%s" + } + + resource "ibm_is_instance" "testacc_instance" { + name = "%s" + image = "%s" + profile = "%s" + primary_network_interface { + subnet = ibm_is_subnet.testacc_subnet.id + } + user_data = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + network_interfaces { + subnet = ibm_is_subnet.testacc_subnet.id + name = "eth1" + } + }`, vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, name, acc.IsImage, acc.InstanceProfileName, userData, acc.ISZoneName) +} + func testAccCheckIBMISInstanceConComConfig(vpcname, subnetname, sshname, publicKey, name, userData string, esb bool) string { return fmt.Sprintf(` resource "ibm_is_vpc" "testacc_vpc" { diff --git a/ibm/service/vpc/resource_ibm_is_lb_listener_policy_test.go b/ibm/service/vpc/resource_ibm_is_lb_listener_policy_test.go index 75af6db710..89823aa520 100644 --- a/ibm/service/vpc/resource_ibm_is_lb_listener_policy_test.go +++ b/ibm/service/vpc/resource_ibm_is_lb_listener_policy_test.go @@ -263,6 +263,51 @@ func TestAccIBMISLBListenerPolicyHttpRedirectNew_basic(t *testing.T) { }, }) } + +func TestAccIBMISLBListenerPolicyParameterizedRedirectNew_basic(t *testing.T) { + var lb string + vpcname := fmt.Sprintf("tflblis-vpc-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tflblis-subnet-%d", acctest.RandIntRange(10, 100)) + lbname := fmt.Sprintf("tflblis%d", acctest.RandIntRange(10, 100)) + lbpolicyname := fmt.Sprintf("tflblispol%d", acctest.RandIntRange(10, 100)) + protocol1 := "https" + port1 := "9086" + url := "https://{host}:8080/{port}/{host}/{path}" + urlUpdate := "{protocol}://test.{host}:80/{path}" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISLBListenerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISLBListenerPolicyParameterizedRedirectNewConfig(vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, lbname, port1, protocol1, lbpolicyname, url), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISLBListenerExists("ibm_is_lb_listener_policy.lb_listener_policy", lb), + resource.TestCheckResourceAttr( + "ibm_is_lb.testacc_LB", "name", lbname), + resource.TestCheckResourceAttr( + "ibm_is_lb_listener_policy.lb_listener_policy", "target.0.http_status_code", "302"), + resource.TestCheckResourceAttr( + "ibm_is_lb_listener_policy.lb_listener_policy", "target.0.url", url), + ), + }, + { + Config: testAccCheckIBMISLBListenerPolicyParameterizedRedirectNewConfig(vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, lbname, port1, protocol1, lbpolicyname, urlUpdate), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISLBListenerExists("ibm_is_lb_listener_policy.lb_listener_policy", lb), + resource.TestCheckResourceAttr( + "ibm_is_lb.testacc_LB", "name", lbname), + resource.TestCheckResourceAttr( + "ibm_is_lb_listener_policy.lb_listener_policy", "target.0.http_status_code", "302"), + resource.TestCheckResourceAttr( + "ibm_is_lb_listener_policy.lb_listener_policy", "target.0.url", urlUpdate), + ), + }, + }, + }) +} + func testAccCheckIBMISLBListenerPolicyDestroy(s *terraform.State) error { sess, _ := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() @@ -790,6 +835,42 @@ func testAccCheckIBMISLBListenerPolicyHttpsRedirectNewConfigRemoveUri(vpcname, s priority = 2 }`, vpcname, subnetname, zone, cidr, lbname, acc.LbListerenerCertificateInstance, acc.LbListerenerCertificateInstance, lbpolicyname) +} + +func testAccCheckIBMISLBListenerPolicyParameterizedRedirectNewConfig(vpcname, subnetname, zone, cidr, lbname, port, protocol, lbpolicyname, url string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = "${ibm_is_vpc.testacc_vpc.id}" + zone = "%s" + ipv4_cidr_block = "%s" + } + resource "ibm_is_lb" "testacc_LB" { + name = "%s" + subnets = ["${ibm_is_subnet.testacc_subnet.id}"] + type = "private" + } + resource "ibm_is_lb_listener" "lb_listener1"{ + lb = ibm_is_lb.testacc_LB.id + port = "9086" + protocol = "http" + } + + resource "ibm_is_lb_listener_policy" "lb_listener_policy" { + name = "%s" + lb = ibm_is_lb.testacc_LB.id + listener = ibm_is_lb_listener.lb_listener1.listener_id + action = "redirect" + target { + http_status_code = 302 + url = "%s" + } + priority = 2 + }`, vpcname, subnetname, zone, cidr, lbname, lbpolicyname, url) + } func testAccCheckIBMISLBListenerPolicyHttpsRedirectConfigUpdate(vpcname, subnetname, zone, cidr, lbname, port, protocol, lbpolicyname string) string { return fmt.Sprintf(` diff --git a/ibm/service/vpc/resource_ibm_is_lb_pool.go b/ibm/service/vpc/resource_ibm_is_lb_pool.go index e1a2ccd382..fa219040ae 100644 --- a/ibm/service/vpc/resource_ibm_is_lb_pool.go +++ b/ibm/service/vpc/resource_ibm_is_lb_pool.go @@ -279,9 +279,6 @@ func resourceIBMISLBPoolCreate(d *schema.ResourceData, meta interface{}) error { if hmp, ok := d.GetOk(isLBPoolHealthMonitorPort); ok { healthMonitorPort = int64(hmp.(int)) } - isLBKey := "load_balancer_key_" + lbID - conns.IbmMutexKV.Lock(isLBKey) - defer conns.IbmMutexKV.Unlock(isLBKey) err := lbPoolCreate(d, meta, name, lbID, algorithm, protocol, healthType, spType, cName, healthMonitorURL, pProtocol, healthDelay, maxRetries, healthTimeOut, healthMonitorPort) if err != nil { diff --git a/ibm/service/vpc/resource_ibm_is_share.go b/ibm/service/vpc/resource_ibm_is_share.go index 96b6681574..e48458c171 100644 --- a/ibm/service/vpc/resource_ibm_is_share.go +++ b/ibm/service/vpc/resource_ibm_is_share.go @@ -53,6 +53,13 @@ func ResourceIbmIsShare() *schema.Resource { ), Schema: map[string]*schema.Schema{ + "allowed_transit_encryption_modes": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Allowed transit encryption modes", + }, "encryption_key": { Type: schema.TypeString, Optional: true, @@ -104,8 +111,8 @@ func ResourceIbmIsShare() *schema.Resource { Type: schema.TypeInt, Optional: true, Computed: true, - ExactlyOneOf: []string{"size", "source_share", "source_share_crn"}, - ConflictsWith: []string{"replication_cron_spec", "source_share", "source_share_crn"}, + ExactlyOneOf: []string{"size", "source_share", "source_share_crn", "origin_share.0.id", "origin_share.0.crn"}, + ConflictsWith: []string{"replication_cron_spec", "source_share", "source_share_crn", "origin_share.0.id", "origin_share.0.crn"}, ValidateFunc: validate.InvokeValidator("ibm_is_share", "size"), Description: "The size of the file share rounded up to the next gigabyte.", }, @@ -289,14 +296,15 @@ func ResourceIbmIsShare() *schema.Resource { }, "profile": { Type: schema.TypeString, - Required: true, + Optional: true, + Computed: true, Description: "The globally unique name for this share profile.", }, "replica_share": &schema.Schema{ Type: schema.TypeList, MaxItems: 1, Optional: true, - ConflictsWith: []string{"source_share"}, + ConflictsWith: []string{"source_share", "origin_share.0.id", "origin_share.0.crn"}, Description: "Configuration for a replica file share to create and associate with this file share. Ifunspecified, a replica may be subsequently added by creating a new file share with a`source_share` referencing this file share.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -568,7 +576,7 @@ func ResourceIbmIsShare() *schema.Resource { Optional: true, ForceNew: true, Computed: true, - ConflictsWith: []string{"replica_share", "size", "source_share_crn"}, + ConflictsWith: []string{"replica_share", "size", "source_share_crn", "origin_share.0.id", "origin_share.0.crn"}, RequiredWith: []string{"replication_cron_spec"}, Description: "The ID of the source file share for this replica file share. The specified file share must not already have a replica, and must not be a replica.", }, @@ -577,16 +585,118 @@ func ResourceIbmIsShare() *schema.Resource { Optional: true, ForceNew: true, Computed: true, - ConflictsWith: []string{"replica_share", "size", "source_share"}, + ConflictsWith: []string{"replica_share", "size", "source_share", "origin_share.0.id", "origin_share.0.crn"}, RequiredWith: []string{"replication_cron_spec"}, Description: "The CRN of the source file share for this replica file share. The specified file share must not already have a replica, and must not be a replica.", }, + "origin_share": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + ConflictsWith: []string{"replica_share", "size", "source_share", "source_share_crn"}, + Description: "The origin share this accessor share is referring to.This property will be present when the `accessor_binding_role` is `accessor`.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"origin_share.0.id"}, + Description: "The CRN for this file share.", + }, + "deleted": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates the referenced resource has been deleted, and providessome supplementary information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about deleted resources.", + }, + }, + }, + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this file share.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"origin_share.0.crn"}, + Description: "The unique identifier for this file share.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this share. The name is unique across all shares in the region.", + }, + "remote": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this account.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "region": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this region.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this region.", + }, + }, + }, + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, "replication_cron_spec": &schema.Schema{ Type: schema.TypeString, Optional: true, DiffSuppressFunc: suppressCronSpecDiff, Computed: true, - ConflictsWith: []string{"replica_share", "size"}, + ConflictsWith: []string{"replica_share", "size", "origin_share.0.id", "origin_share.0.crn"}, Description: "The cron specification for the file share replication schedule.Replication of a share can be scheduled to occur at most once per hour.", }, "replication_role": &schema.Schema{ @@ -695,6 +805,32 @@ func ResourceIbmIsShare() *schema.Resource { }, }, }, + "lifecycle_reasons": { + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current lifecycle_state (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": { + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state", + }, + + "message": { + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + + "more_info": { + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, "lifecycle_state": { Type: schema.TypeString, Computed: true, @@ -702,7 +838,8 @@ func ResourceIbmIsShare() *schema.Resource { }, "zone": { Type: schema.TypeString, - Required: true, + Optional: true, + Computed: true, ForceNew: true, Description: "The globally unique name of the zone this file share will reside in.", }, @@ -747,11 +884,41 @@ func ResourceIbmIsShare() *schema.Resource { Computed: true, Description: "The type of resource referenced.", }, + "accessor_binding_role": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The accessor binding role of this file share:- `none`: This file share is not participating in access with another file share- `origin`: This file share is the origin for one or more file shares (which may be in other accounts)- `accessor`: This file share is providing access to another file share (which may be in another account).", + }, + "accessor_bindings": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The accessor bindings for this file share. Each accessor binding identifies a resource (possibly in another account) with access to this file share's data.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this share accessor binding.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this share accessor binding.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, }, } } func ResourceIbmIsShareValidator() *validate.ResourceValidator { + allowed_transit_encryption_modes := "none, user_managed" validateSchema := make([]validate.ValidateSchema, 1) validateSchema = append(validateSchema, validate.ValidateSchema{ @@ -797,6 +964,14 @@ func ResourceIbmIsShareValidator() *validate.ResourceValidator { MinValueLength: 1, MaxValueLength: 128, }, + + validate.ValidateSchema{ + Identifier: isIpSecAuthenticationAlg, + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Optional: true, + AllowedValues: allowed_transit_encryption_modes, + }, ) resourceValidator := validate.ResourceValidator{ResourceName: "ibm_is_share", Schema: validateSchema} @@ -816,6 +991,13 @@ func resourceIbmIsShareCreate(context context.Context, d *schema.ResourceData, m accessControlMode := accessControlModeIntf.(string) sharePrototype.AccessControlMode = &accessControlMode } + if allowedTransitEncryptionModesIntf, ok := d.GetOk("allowed_transit_encryption_modes"); ok { + allowedTransitEncryptionModes := []string{} + for _, allowedTransitEncryptionModesItem := range allowedTransitEncryptionModesIntf.([]interface{}) { + allowedTransitEncryptionModes = append(allowedTransitEncryptionModes, allowedTransitEncryptionModesItem.(string)) + } + sharePrototype.AllowedTransitEncryptionModes = allowedTransitEncryptionModes + } if encryptionKeyIntf, ok := d.GetOk("encryption_key"); ok { encryptionKey := encryptionKeyIntf.(string) encryptionKeyIdentity := &vpcv1.EncryptionKeyIdentity{ @@ -908,8 +1090,8 @@ func resourceIbmIsShareCreate(context context.Context, d *schema.ResourceData, m } sharePrototype.ReplicaShare = replicaShare } - } else { - sourceShare := d.Get("source_share").(string) + } else if sourceShareIntf, sShareok := d.GetOk("source_share"); sShareok { + sourceShare := sourceShareIntf.(string) if sourceShare != "" { sharePrototype.SourceShare = &vpcv1.ShareIdentity{ ID: &sourceShare, @@ -925,6 +1107,12 @@ func resourceIbmIsShareCreate(context context.Context, d *schema.ResourceData, m replicationCronSpec := d.Get("replication_cron_spec").(string) sharePrototype.ReplicationCronSpec = &replicationCronSpec + } else { + originShare := d.Get("origin_share") + OriginShareModel := ResourceIBMIsShareMapToShareIdentity(originShare.([]interface{})[0].(map[string]interface{})) + + sharePrototype.OriginShare = OriginShareModel + } if iopsIntf, ok := d.GetOk("iops"); ok { @@ -1088,6 +1276,19 @@ func resourceIbmIsShareRead(context context.Context, d *schema.ResourceData, met return diag.FromErr(fmt.Errorf("Error setting access_control_mode: %s", err)) } } + if !core.IsNil(share.AllowedTransitEncryptionModes) { + if err = d.Set("allowed_transit_encryption_modes", share.AllowedTransitEncryptionModes); err != nil { + err = fmt.Errorf("Error setting allowed_transit_encryption_modes: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_share", "read", "set-allowed_transit_encryption_modes").GetDiag() + } + } + if !core.IsNil(share.OriginShare) { + originShareMap := ResourceIBMIsShareShareReferenceToMap(share.OriginShare) + if err = d.Set("origin_share", []map[string]interface{}{originShareMap}); err != nil { + err = fmt.Errorf("Error setting origin_share: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_share", "read", "set-origin_share").GetDiag() + } + } if err = d.Set("iops", flex.IntValue(share.Iops)); err != nil { return diag.FromErr(fmt.Errorf("Error setting iops: %s", err)) } @@ -1107,6 +1308,21 @@ func resourceIbmIsShareRead(context context.Context, d *schema.ResourceData, met if err = d.Set("size", flex.IntValue(share.Size)); err != nil { return diag.FromErr(fmt.Errorf("Error setting size: %s", err)) } + if err = d.Set("accessor_binding_role", share.AccessorBindingRole); err != nil { + err = fmt.Errorf("Error setting accessor_binding_role: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_share", "read", "set-accessor_binding_role").GetDiag() + } + accessorBindings := []map[string]interface{}{} + for _, accessorBindingsItem := range share.AccessorBindings { + + accessorBindingsItemMap := ResourceIBMIsShareShareAccessorBindingReferenceToMap(&accessorBindingsItem) + accessorBindings = append(accessorBindings, accessorBindingsItemMap) + + } + if err = d.Set("accessor_bindings", accessorBindings); err != nil { + err = fmt.Errorf("Error setting accessor_bindings: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_share", "read", "set-accessor_bindings").GetDiag() + } targets := make([]map[string]interface{}, 0) if share.MountTargets != nil { for _, targetsItem := range share.MountTargets { @@ -1177,6 +1393,11 @@ func resourceIbmIsShareRead(context context.Context, d *schema.ResourceData, met if err = d.Set("href", share.Href); err != nil { return diag.FromErr(fmt.Errorf("Error setting href: %s", err)) } + if share.LifecycleReasons != nil { + if err := d.Set("lifecycle_reasons", resourceShareLifecycleReasons(share.LifecycleReasons)); err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Error setting lifecycle_reasons: %s", err)) + } + } if err = d.Set("lifecycle_state", share.LifecycleState); err != nil { return diag.FromErr(fmt.Errorf("Error setting lifecycle_state: %s", err)) } @@ -1653,6 +1874,15 @@ func shareUpdate(vpcClient *vpcv1.VpcV1, context context.Context, d *schema.Reso hasChange = true } } + if d.HasChange("allowed_transit_encryption_modes") { + var allowedTransitEncryptionModes []string + for _, v := range d.Get("allowed_transit_encryption_modes").([]interface{}) { + allowedTransitEncryptionModesItem := v.(string) + allowedTransitEncryptionModes = append(allowedTransitEncryptionModes, allowedTransitEncryptionModesItem) + } + sharePatchModel.AllowedTransitEncryptionModes = allowedTransitEncryptionModes + hasChange = true + } } if d.HasChange(replicationCronSpec) { replicationCronSpecStr := d.Get(replicationCronSpec).(string) @@ -1912,3 +2142,85 @@ func shareUpdate(vpcClient *vpcv1.VpcV1, context context.Context, d *schema.Reso } return nil } +func ResourceIBMIsShareShareAccessorBindingReferenceToMap(model *vpcv1.ShareAccessorBindingReference) map[string]interface{} { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["resource_type"] = *model.ResourceType + return modelMap +} +func ResourceIBMIsShareMapToShareIdentity(modelMap map[string]interface{}) vpcv1.ShareIdentityIntf { + model := &vpcv1.ShareIdentity{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["crn"] != nil && modelMap["crn"].(string) != "" { + model.CRN = core.StringPtr(modelMap["crn"].(string)) + } + return model +} +func ResourceIBMIsShareShareReferenceToMap(model *vpcv1.ShareReference) map[string]interface{} { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap := ResourceIBMIsShareShareReferenceDeletedToMap(model.Deleted) + modelMap["deleted"] = []map[string]interface{}{deletedMap} + } + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + if model.Remote != nil { + remoteMap := ResourceIBMIsShareShareRemoteToMap(model.Remote) + modelMap["remote"] = []map[string]interface{}{remoteMap} + } + modelMap["resource_type"] = *model.ResourceType + return modelMap +} +func ResourceIBMIsShareShareRemoteToMap(model *vpcv1.ShareRemote) map[string]interface{} { + modelMap := make(map[string]interface{}) + if model.Account != nil { + accountMap := ResourceIBMIsShareAccountReferenceToMap(model.Account) + + modelMap["account"] = []map[string]interface{}{accountMap} + } + if model.Region != nil { + regionMap := ResourceIBMIsShareRegionReferenceToMap(model.Region) + + modelMap["region"] = []map[string]interface{}{regionMap} + } + return modelMap +} + +func ResourceIBMIsShareAccountReferenceToMap(model *vpcv1.AccountReference) map[string]interface{} { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + modelMap["resource_type"] = *model.ResourceType + return modelMap +} + +func ResourceIBMIsShareRegionReferenceToMap(model *vpcv1.RegionReference) map[string]interface{} { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap +} +func ResourceIBMIsShareShareReferenceDeletedToMap(model *vpcv1.ShareReferenceDeleted) map[string]interface{} { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap +} +func resourceShareLifecycleReasons(lifecycleReasons []vpcv1.ShareLifecycleReason) (lifecycleReasonsList []map[string]interface{}) { + lifecycleReasonsList = make([]map[string]interface{}, 0) + for _, lr := range lifecycleReasons { + currentLR := map[string]interface{}{} + if lr.Code != nil && lr.Message != nil { + currentLR["code"] = *lr.Code + currentLR["message"] = *lr.Message + if lr.MoreInfo != nil { + currentLR["more_info"] = *lr.MoreInfo + } + lifecycleReasonsList = append(lifecycleReasonsList, currentLR) + } + } + return lifecycleReasonsList +} diff --git a/ibm/service/vpc/resource_ibm_is_share_delete_accessor_binding.go b/ibm/service/vpc/resource_ibm_is_share_delete_accessor_binding.go new file mode 100644 index 0000000000..e334e57f80 --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_share_delete_accessor_binding.go @@ -0,0 +1,118 @@ +// Copyright IBM Corp. 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func ResourceIbmIsShareDeleteAccessorBinding() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIbmIsShareDeleteAccessorBindingCreate, + ReadContext: resourceIbmIsShareDeleteAccessorBindingRead, + UpdateContext: resourceIbmIsShareDeleteAccessorBindingUpdate, + DeleteContext: resourceIbmIsShareDeleteAccessorBindingDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "share": { + Type: schema.TypeString, + Required: true, + Description: "The file share identifier.", + }, + "accessor_binding": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: flex.ApplyOnce, + Description: "The accessor binding id", + }, + }, + } +} + +func resourceIbmIsShareDeleteAccessorBindingCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + return diag.FromErr(err) + } + + share_id := d.Get("share").(string) + + bindingId := d.Get("accessor_binding").(string) + + deleteAccessBindingOptions := &vpcv1.DeleteShareAccessorBindingOptions{ + ShareID: &share_id, + ID: &bindingId, + } + response, err := vpcClient.DeleteShareAccessorBindingWithContext(context, deleteAccessBindingOptions) + if err != nil { + log.Printf("[DEBUG] DeleteShareAccessorBindingWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("[ERROR] DeleteShareAccessorBindingWithContext failed %s\n%s", err, response)) + } + + _, err = isWaitForShareAccessorBindingDeleted(context, vpcClient, share_id, bindingId, d, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return diag.FromErr(err) + } + d.SetId(share_id) + return nil +} + +func isWaitForShareAccessorBindingDeleted(context context.Context, vpcClient *vpcv1.VpcV1, shareid, bindingId string, d *schema.ResourceData, timeout time.Duration) (interface{}, error) { + log.Printf("Waiting for share accessor binding (%s) to be deleted.", shareid) + + stateConf := &resource.StateChangeConf{ + Pending: []string{"pending", "deleting"}, + Target: []string{"done"}, + Refresh: isShareAccessorBindingRefreshFunc(context, vpcClient, shareid, bindingId, d), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + return stateConf.WaitForState() +} + +func isShareAccessorBindingRefreshFunc(context context.Context, vpcClient *vpcv1.VpcV1, shareid string, bindingId string, d *schema.ResourceData) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + bindingOptions := &vpcv1.GetShareAccessorBindingOptions{ + ShareID: &shareid, + ID: &bindingId, + } + + shareBinding, response, err := vpcClient.GetShareAccessorBindingWithContext(context, bindingOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + return shareBinding, "done", nil + } + return nil, "", fmt.Errorf("Error Getting Target: %s\n%s", err, response) + } + return shareBinding, *shareBinding.LifecycleState, nil + } +} + +func resourceIbmIsShareDeleteAccessorBindingRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func resourceIbmIsShareDeleteAccessorBindingUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + + return nil +} + +func resourceIbmIsShareDeleteAccessorBindingDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + + return nil +} diff --git a/ibm/service/vpc/resource_ibm_is_share_delete_accessor_binding_test.go b/ibm/service/vpc/resource_ibm_is_share_delete_accessor_binding_test.go new file mode 100644 index 0000000000..cc581c92df --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_share_delete_accessor_binding_test.go @@ -0,0 +1,86 @@ +// Copyright IBM Corp. 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccIbmIsShareDeleteAccessorBinding(t *testing.T) { + var conf vpcv1.Share + + // name := fmt.Sprintf("tf-fs-name-%d", acctest.RandIntRange(10, 100)) + subnetName := fmt.Sprintf("tf-subnet-%d", acctest.RandIntRange(10, 100)) + vpcname := fmt.Sprintf("tf-vpc-name-%d", acctest.RandIntRange(10, 100)) + shareName := fmt.Sprintf("tf-share-%d", acctest.RandIntRange(10, 100)) + shareName1 := fmt.Sprintf("tf-share1-%d", acctest.RandIntRange(10, 100)) + shareName2 := fmt.Sprintf("tf-share2-%d", acctest.RandIntRange(10, 100)) + tEMode1 := "user_managed" + // tEMode2 := "none" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmIsShareDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIbmIsShareConfigOriginShareConfig(vpcname, subnetName, tEMode1, shareName, shareName1), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmIsShareExists("ibm_is_share.is_share", conf), + resource.TestCheckResourceAttr("ibm_is_share.is_share", "name", shareName), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "id"), + resource.TestCheckResourceAttr("ibm_is_share.is_share", "allowed_transit_encryption_modes.0", tEMode1), + resource.TestCheckResourceAttr("ibm_is_share.is_share_accessor", "allowed_transit_encryption_modes.0", tEMode1), + resource.TestCheckResourceAttr("ibm_is_share.is_share_accessor", "accessor_binding_role", "accessor"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.crn"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.id"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.href"), + ), + }, + { + Config: testAccCheckIbmIsShareDeleteAccessorBindingConfig(vpcname, subnetName, tEMode1, shareName, shareName1, shareName2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmIsShareExists("ibm_is_share.is_share", conf), + resource.TestCheckResourceAttr("ibm_is_share.is_share", "name", shareName), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "id"), + resource.TestCheckResourceAttr("ibm_is_share.is_share", "allowed_transit_encryption_modes.0", tEMode1), + resource.TestCheckResourceAttr("ibm_is_share.is_share_accessor", "allowed_transit_encryption_modes.0", tEMode1), + resource.TestCheckResourceAttr("ibm_is_share.is_share", "accessor_binding_role", "origin"), + resource.TestCheckResourceAttr("ibm_is_share.is_share_accessor", "accessor_binding_role", "accessor"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.crn"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.id"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.href"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "accessor_bindings.#"), + ), + }, + }, + }) +} + +func testAccCheckIbmIsShareDeleteAccessorBindingConfig(vpcName, sname, tEMode, shareName, shareName1, shareName2 string) string { + return testAccCheckIbmIsShareConfigOriginShareConfig(vpcName, sname, tEMode, shareName, shareName1) + fmt.Sprintf(` + resource "ibm_is_share" "is_share_accessor1" { + name = "%s" + origin_share{ + crn = ibm_is_share.is_share.crn + } + + } + data "ibm_is_share_accessor_bindings" "bindings" { + depends_on = [ibm_is_share.is_share_accessor] + share = ibm_is_share.is_share.id + } + resource "ibm_is_share_delete_accessor_binding" "delete_binding" { + share = ibm_is_share.is_share.id + accessor_binding = data.ibm_is_share_accessor_bindings.bindings.accessor_bindings.0.id + } + `, shareName2) +} diff --git a/ibm/service/vpc/resource_ibm_is_share_test.go b/ibm/service/vpc/resource_ibm_is_share_test.go index d0a2a94c11..a9f5ce9eb2 100644 --- a/ibm/service/vpc/resource_ibm_is_share_test.go +++ b/ibm/service/vpc/resource_ibm_is_share_test.go @@ -238,6 +238,58 @@ func TestAccIbmIsShareVNIID(t *testing.T) { }) } +func TestAccIbmIsShareOriginShare(t *testing.T) { + var conf vpcv1.Share + + // name := fmt.Sprintf("tf-fs-name-%d", acctest.RandIntRange(10, 100)) + subnetName := fmt.Sprintf("tf-subnet-%d", acctest.RandIntRange(10, 100)) + vpcname := fmt.Sprintf("tf-vpc-name-%d", acctest.RandIntRange(10, 100)) + shareName := fmt.Sprintf("tf-share-%d", acctest.RandIntRange(10, 100)) + shareName1 := fmt.Sprintf("tf-share1-%d", acctest.RandIntRange(10, 100)) + tEMode1 := "user_managed" + // tEMode2 := "none" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIbmIsShareDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIbmIsShareConfigOriginShareConfig(vpcname, subnetName, tEMode1, shareName, shareName1), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmIsShareExists("ibm_is_share.is_share", conf), + resource.TestCheckResourceAttr("ibm_is_share.is_share", "name", shareName), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "id"), + resource.TestCheckResourceAttr("ibm_is_share.is_share", "allowed_transit_encryption_modes.0", tEMode1), + resource.TestCheckResourceAttr("ibm_is_share.is_share_accessor", "allowed_transit_encryption_modes.0", tEMode1), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "accessor_binding_role"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.crn"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.id"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.href"), + ), + }, + { + Config: testAccCheckIbmIsShareConfigOriginShareConfig(vpcname, subnetName, tEMode1, shareName, shareName1), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIbmIsShareExists("ibm_is_share.is_share", conf), + resource.TestCheckResourceAttr("ibm_is_share.is_share", "name", shareName), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "id"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "allowed_transit_encryption_modes.#"), + resource.TestCheckResourceAttr("ibm_is_share.is_share", "allowed_transit_encryption_modes.0", tEMode1), + resource.TestCheckResourceAttr("ibm_is_share.is_share_accessor", "allowed_transit_encryption_modes.0", tEMode1), + resource.TestCheckResourceAttr("ibm_is_share.is_share_accessor", "name", shareName1), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "accessor_binding_role"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "accessor_bindings.#"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.crn"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.id"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_share.is_share_accessor", "origin_share.0.href"), + ), + }, + }, + }) +} + func testAccCheckIbmIsShareConfigVNIID(vpcName, sname, targetName, vniName, shareName string) string { return fmt.Sprintf(` data "ibm_resource_group" "group" { @@ -271,6 +323,36 @@ func testAccCheckIbmIsShareConfigVNIID(vpcName, sname, targetName, vniName, shar `, vpcName, sname, acc.ISCIDR, vniName, shareName, targetName) } +func testAccCheckIbmIsShareConfigOriginShareConfig(vpcName, sname, tEMode, shareName, shareName1 string) string { + return fmt.Sprintf(` + + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "us-south-1" + ipv4_cidr_block = "%s" + } + resource "ibm_is_share" "is_share" { + allowed_transit_encryption_modes = ["%s"] + zone = "us-south-1" + size = 220 + name = "%s" + profile = "dp2" + } + + resource "ibm_is_share" "is_share_accessor" { + name = "%s" + origin_share{ + crn = ibm_is_share.is_share.crn + } + + } + `, vpcName, sname, acc.ISCIDR, tEMode, shareName, shareName1) +} + func testAccCheckIbmIsShareConfigBasic(name string) string { return fmt.Sprintf(` resource "ibm_is_share" "is_share" { diff --git a/ibm/service/vpc/resource_ibm_is_virtual_network_interface.go b/ibm/service/vpc/resource_ibm_is_virtual_network_interface.go index 30ceb60379..b860dd2180 100644 --- a/ibm/service/vpc/resource_ibm_is_virtual_network_interface.go +++ b/ibm/service/vpc/resource_ibm_is_virtual_network_interface.go @@ -925,11 +925,15 @@ func resourceIBMIsVirtualNetworkInterfaceDelete(context context.Context, d *sche deleteVirtualNetworkInterfacesOptions.SetID(d.Id()) - response, err := sess.DeleteVirtualNetworkInterfacesWithContext(context, deleteVirtualNetworkInterfacesOptions) + vni, response, err := sess.DeleteVirtualNetworkInterfacesWithContext(context, deleteVirtualNetworkInterfacesOptions) if err != nil { log.Printf("[DEBUG] DeleteVirtualNetworkInterfacesWithContext failed %s\n%s", err, response) return diag.FromErr(fmt.Errorf("DeleteVirtualNetworkInterfacesWithContext failed %s\n%s", err, response)) } + _, err = isWaitForVirtualNetworkInterfaceDeleted(sess, d.Id(), d.Timeout(schema.TimeoutDelete), vni) + if err != nil { + return diag.FromErr(err) + } d.SetId("") @@ -1107,6 +1111,42 @@ func isVirtualNetworkInterfaceRefreshFunc(client *vpcv1.VpcV1, id string) resour return vni, *vni.LifecycleState, nil } } +func isWaitForVirtualNetworkInterfaceDeleted(client *vpcv1.VpcV1, id string, timeout time.Duration, vni *vpcv1.VirtualNetworkInterface) (interface{}, error) { + log.Printf("Waiting for VirtualNetworkInterface (%s) to be deleted.", id) + + stateConf := &resource.StateChangeConf{ + Pending: []string{"", "pending", "deleting", "updating", "waiting"}, + Target: []string{"done", "failed", "stable", "suspended"}, + Refresh: isVirtualNetworkInterfaceDeleteRefreshFunc(client, vni, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + + return stateConf.WaitForState() +} + +func isVirtualNetworkInterfaceDeleteRefreshFunc(client *vpcv1.VpcV1, vnir *vpcv1.VirtualNetworkInterface, id string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + vnigetoptions := &vpcv1.GetVirtualNetworkInterfaceOptions{ + ID: &id, + } + vni, response, err := client.GetVirtualNetworkInterface(vnigetoptions) + if err != nil { + if response.StatusCode == 404 { + return vnir, "done", nil + } + return vni, "failed", fmt.Errorf("[ERROR] Error getting vni: %s\n%s", err, response) + } + if *vni.LifecycleState == "failed" || *vni.LifecycleState == "suspended" { + return vni, *vni.LifecycleState, fmt.Errorf("[ERROR] Error VirtualNetworkInterface in : %s state", *vni.LifecycleState) + } + if *vni.LifecycleState == "stable" { + return vni, *vni.LifecycleState, fmt.Errorf("[ERROR] Error VirtualNetworkInterface in : %s state", *vni.LifecycleState) + } + return vni, *vni.LifecycleState, nil + } +} func resourceIBMIsVirtualNetworkInterfaceVirtualNetworkInterfaceTargetInstanceNetworkAttachmentReferenceVirtualNetworkInterfaceContextToMap(model *vpcv1.VirtualNetworkInterfaceTargetInstanceNetworkAttachmentReferenceVirtualNetworkInterfaceContext) (map[string]interface{}, error) { modelMap := make(map[string]interface{}) diff --git a/ibm/service/vpc/resource_ibm_is_volume.go b/ibm/service/vpc/resource_ibm_is_volume.go index b485aa94c7..0fcf79e00a 100644 --- a/ibm/service/vpc/resource_ibm_is_volume.go +++ b/ibm/service/vpc/resource_ibm_is_volume.go @@ -686,12 +686,12 @@ func volGet(d *schema.ResourceData, meta interface{}, id string) error { d.Set(isVolumeHealthReasons, healthReasonsList) } // catalog + catalogList := make([]map[string]interface{}, 0) if vol.CatalogOffering != nil { versionCrn := "" if vol.CatalogOffering.Version != nil && vol.CatalogOffering.Version.CRN != nil { versionCrn = *vol.CatalogOffering.Version.CRN } - catalogList := make([]map[string]interface{}, 0) catalogMap := map[string]interface{}{} if versionCrn != "" { catalogMap[isVolumeCatalogOfferingVersionCrn] = versionCrn @@ -710,8 +710,8 @@ func volGet(d *schema.ResourceData, meta interface{}, id string) error { } } catalogList = append(catalogList, catalogMap) - d.Set(isVolumeCatalogOffering, catalogList) } + d.Set(isVolumeCatalogOffering, catalogList) controller, err := flex.GetBaseController(meta) if err != nil { return err diff --git a/metadata/provider_metadata.json b/metadata/provider_metadata.json index 5a1742ce20..a922094661 100644 --- a/metadata/provider_metadata.json +++ b/metadata/provider_metadata.json @@ -109098,7 +109098,7 @@ "description": "The name of the Cloud Internet database service", "immutable": true, "required": true, - "options": "databases-for-etcd, databases-for-postgresql, databases-for-redis, databases-for-elasticsearch, databases-for-mongodb, messages-for-rabbitmq, databases-for-mysql, databases-for-cassandra, databases-for-enterprisedb" + "options": "databases-for-etcd, databases-for-postgresql, databases-for-redis, databases-for-elasticsearch, databases-for-mongodb, messages-for-rabbitmq, databases-for-mysql, databases-for-enterprisedb" }, { "name": "tags", @@ -109446,18 +109446,6 @@ "type": "TypeList", "computed": true, "elem": { - "bundlebase64": { - "name": "bundlebase64", - "type": "TypeString", - "description": "Cassandra base64 encoding", - "computed": true - }, - "bundlename": { - "name": "bundlename", - "type": "TypeString", - "description": "Cassandra Bundle Name", - "computed": true - }, "certbase64": { "name": "certbase64", "type": "TypeString", diff --git a/version/version.go b/version/version.go index 8a638f33b8..899fc33ad3 100644 --- a/version/version.go +++ b/version/version.go @@ -5,7 +5,7 @@ import ( ) // Version is the current provider main version -const Version = "1.67.1" +const Version = "1.69.0" // GitCommit is the git commit that was compiled. This will be filled in by the compiler. var GitCommit string diff --git a/website/allowed-subcategories.txt b/website/allowed-subcategories.txt index 5416d7813f..09d6aa3a2a 100644 --- a/website/allowed-subcategories.txt +++ b/website/allowed-subcategories.txt @@ -25,9 +25,11 @@ Identity & Access Management (IAM) Internet services Key Management Service Kubernetes Service +Logs Routing Metrics Router MQ on Cloud Object Storage +Partner Center Sell Power Systems Privileged Access Gateway Project diff --git a/website/docs/d/cbr_zone_addresses.html.markdown b/website/docs/d/cbr_zone_addresses.html.markdown new file mode 100644 index 0000000000..164567b16d --- /dev/null +++ b/website/docs/d/cbr_zone_addresses.html.markdown @@ -0,0 +1,55 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_cbr_zone_addresses" +description: |- + Get information about cbr_zone_addresses +subcategory: "Context Based Restrictions" +--- + +# ibm_cbr_zone_addresses + +Provides a read-only data source for cbr_zone_addresses. You can then reference the fields of the data source in other resources within the same configuration using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_cbr_zone_addresses" "cbr_zone_addresses" { + zone_addresses_id = "zone_addresses_id" +} +``` + +## Argument Reference + +Review the argument reference that you can specify for your data source. + +* `zone_addresses_id` - (Required, Forces new resource, String) The ID of a zone addresses resource. + +## Attribute Reference + +In addition to all argument references listed, you can access the following attribute references after your data source is created. + +* `id` - The unique identifier of the cbr_zone_addresses. + +* `zone_id` - (String) The id of the zone in which the addresses are included. + * Constraints: The maximum length is `32` characters. The minimum length is `32` characters. The value must match regular expression `/^[a-fA-F0-9]{32}$/`. + +* `addresses` - (List) The list of addresses included in the zone. + * Constraints: The maximum length is `1000` items. The minimum length is `1` items. +Nested scheme for **addresses**: + * `ref` - (List) A service reference value. + Nested scheme for **ref**: + * `account_id` - (String) The id of the account owning the service. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9\-]+$/`. + * `location` - (String) The location. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9a-z\-]+$/`. + * `service_instance` - (String) The service instance. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9a-z\-/]+$/`. + * `service_name` - (String) The service name. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9a-z\-]+$/`. + * `service_type` - (String) The service type. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9a-z_]+$/`. + * `type` - (String) The type of address. + * Constraints: Allowable values are: `ipAddress`, `ipRange`, `subnet`, `vpc`, `serviceRef`. + * `value` - (String) The IP address. + * Constraints: The maximum length is `45` characters. The minimum length is `2` characters. The value must match regular expression `/^[a-zA-Z0-9:.]+$/`. + diff --git a/website/docs/d/cd_tekton_pipeline.html.markdown b/website/docs/d/cd_tekton_pipeline.html.markdown index ea9ec48c00..57a70aed00 100644 --- a/website/docs/d/cd_tekton_pipeline.html.markdown +++ b/website/docs/d/cd_tekton_pipeline.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline -Provides a read-only data source to retrieve information about a cd_tekton_pipeline. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. +Provides a read-only data source for cd_tekton_pipeline. You can then reference the fields of the data source in other resources within the same configuration using interpolation syntax. ## Example Usage @@ -20,14 +20,14 @@ data "ibm_cd_tekton_pipeline" "cd_tekton_pipeline" { ## Argument Reference -You can specify the following arguments for this data source. +Review the argument reference that you can specify for your data source. * `pipeline_id` - (Required, Forces new resource, String) ID of current instance. * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. ## Attribute Reference -After your data source is created, you can read values from the following attributes. +In addition to all argument references listed, you can access the following attribute references after your data source is created. * `id` - The unique identifier of the cd_tekton_pipeline. * `build_number` - (Integer) The latest pipeline run build number. If this property is absent, the pipeline hasn't had any pipeline runs. @@ -61,11 +61,11 @@ Nested schema for **definitions**: * `type` - (String) The only supported source type is "git", indicating that the source is a git repository. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^git$/`. -* `enable_notifications` - (Boolean) Flag whether to enable notifications for this pipeline. When enabled, pipeline run events will be published on all slack integration specified channels in the parent toolchain. If omitted, this feature is disabled by default. +* `enable_notifications` - (Boolean) Flag to enable notifications for this pipeline. If enabled, the Tekton pipeline run events will be published to all the destinations specified by the Slack and Event Notifications integrations in the parent toolchain. If omitted, this feature is disabled by default. -* `enable_partial_cloning` - (Boolean) Flag whether to enable partial cloning for this pipeline. When partial clone is enabled, only the files contained within the paths specified in definition repositories are read and cloned, this means that symbolic links might not work. If omitted, this feature is disabled by default. +* `enable_partial_cloning` - (Boolean) Flag to enable partial cloning for this pipeline. When partial clone is enabled, only the files contained within the paths specified in definition repositories are read and cloned, this means that symbolic links might not work. If omitted, this feature is disabled by default. -* `enabled` - (Boolean) Flag whether this pipeline is enabled. +* `enabled` - (Boolean) Flag to check if the trigger is enabled. * Constraints: The default value is `true`. * `href` - (String) API URL for interacting with the pipeline. @@ -93,18 +93,15 @@ Nested schema for **properties**: * Constraints: Allowable values are: `secure`, `text`, `integration`, `single_select`, `appconfig`. * `value` - (String) Property value. Any string value is valid. * Constraints: The maximum length is `4096` characters. The minimum length is `0` characters. The value must match regular expression `/^.*$/`. - * `resource_group` - (List) The resource group in which the pipeline was created. Nested schema for **resource_group**: * `id` - (String) ID. * Constraints: The maximum length is `64` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_]+$/`. - * `runs_url` - (String) URL for this pipeline showing the list of pipeline runs. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. * `status` - (String) Pipeline status. * Constraints: Allowable values are: `configured`, `configuring`. - * `toolchain` - (List) Toolchain object containing references to the parent toolchain. Nested schema for **toolchain**: * `crn` - (String) The CRN for the toolchain that contains the Tekton pipeline. @@ -115,16 +112,18 @@ Nested schema for **toolchain**: * `triggers` - (List) Tekton pipeline triggers list. * Constraints: The maximum length is `1024` items. The minimum length is `0` items. Nested schema for **triggers**: - * `cron` - (String) Only needed for timer triggers. Cron expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: 0 *_/2 * * * - every 2 hours. + * `cron` - (String) Only needed for timer triggers. CRON expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: The CRON expression 0 *_/2 * * * - translates to - every 2 hours. * Constraints: The maximum length is `253` characters. The minimum length is `5` characters. The value must match regular expression `/^[-0-9a-zA-Z,\\*\/ ]{5,253}$/`. - * `enabled` - (Boolean) Flag whether the trigger is enabled. + * `enabled` - (Boolean) Flag to check if the trigger is enabled. * Constraints: The default value is `true`. * `event_listener` - (String) Event listener name. The name of the event listener to which the trigger is associated. The event listeners are defined in the definition repositories of the Tekton pipeline. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `events` - (List) Only needed for Git triggers. List of events to which a Git trigger listens. Choose one or more from: 'push', 'pull_request' and 'pull_request_closed'. For SCM repositories that use 'merge request' events, such events map to the equivalent 'pull request' events. + * `events` - (List) Either 'events' or 'filter' is required specifically for Git triggers. Stores a list of events that a Git trigger listens to. Choose one or more from 'push', 'pull_request', and 'pull_request_closed'. If SCM repositories use the 'merge request' term, they correspond to the generic term i.e. 'pull request'. * Constraints: Allowable list items are: `push`, `pull_request`, `pull_request_closed`. The maximum length is `3` items. The minimum length is `0` items. * `favorite` - (Boolean) Mark the trigger as a favorite. * Constraints: The default value is `false`. + * `filter` - (String) Either 'events' or 'filter' can be used. Stores the CEL (Common Expression Language) expression value which is used for event filtering against the Git webhook payloads. + * Constraints: The maximum length is `4096` characters. The minimum length is `1` character. The value must match regular expression `/^.*$/`. * `href` - (String) API URL for interacting with the trigger. Only included when fetching the list of pipeline triggers. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. * `id` - (String) The Trigger ID. @@ -132,7 +131,7 @@ Nested schema for **triggers**: * `max_concurrent_runs` - (Integer) Defines the maximum number of concurrent runs for this trigger. If omitted then the concurrency limit is disabled for this trigger. * `name` - (String) Trigger name. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^([a-zA-Z0-9]{1,2}|[a-zA-Z0-9][0-9a-zA-Z-_.: \/\\(\\)\\[\\]]{1,251}[a-zA-Z0-9])$/`. - * `properties` - (List) Optional trigger properties used to override or supplement the pipeline properties when triggering a pipeline run. + * `properties` - (List) Optional trigger properties are used to override or supplement the pipeline properties when triggering a pipeline run. * Constraints: The maximum length is `1024` items. The minimum length is `0` items. Nested schema for **properties**: * `enum` - (List) Options for `single_select` property type. Only needed for `single_select` property type. @@ -148,7 +147,7 @@ Nested schema for **triggers**: * Constraints: Allowable values are: `secure`, `text`, `integration`, `single_select`, `appconfig`. * `value` - (String) Property value. Any string value is valid. * Constraints: The maximum length is `4096` characters. The minimum length is `0` characters. The value must match regular expression `/^.*$/`. - * `secret` - (List) Only needed for generic webhook trigger type. Secret used to start generic webhook trigger. + * `secret` - (List) Only needed for Generic Webhook trigger type. The secret is used to start the Generic Webhook trigger. Nested schema for **secret**: * `algorithm` - (String) Algorithm used for `digest_matches` secret type. Only needed for `digest_matches` secret type. * Constraints: Allowable values are: `md4`, `md5`, `sha1`, `sha256`, `sha384`, `sha512`, `sha512_224`, `sha512_256`, `ripemd160`. @@ -165,11 +164,11 @@ Nested schema for **triggers**: * `properties` - (List) Properties of the source, which define the URL of the repository and a branch or pattern. Nested schema for **properties**: * `blind_connection` - (Boolean) True if the repository server is not addressable on the public internet. IBM Cloud will not be able to validate the connection details you provide. - * `branch` - (String) Name of a branch from the repo. One of branch or pattern must be specified, but only one or the other. + * `branch` - (String) Name of a branch from the repo. Only one of branch, pattern, or filter should be specified. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `hook_id` - (String) ID of the webhook from the repo. Computed upon creation of the trigger. + * `hook_id` - (String) Repository webhook ID. It is generated upon trigger creation. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `pattern` - (String) The pattern of Git branch or tag to which to listen. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags/branches in the repository. The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. One of branch or pattern must be specified, but only one or the other. + * `pattern` - (String) The pattern of Git branch or tag. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags or branches in the repository.The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. Only one of branch, pattern, or filter should be specified. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.:@=$&^\/\\?\\!\\*\\+\\[\\]\\(\\)\\{\\}\\|\\\\]*$/`. * `tool` - (List) Reference to the repository tool in the parent toolchain. Nested schema for **tool**: @@ -181,7 +180,7 @@ Nested schema for **triggers**: * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^git$/`. * `tags` - (List) Optional trigger tags array. * Constraints: The list items must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. The maximum length is `128` items. The minimum length is `0` items. - * `timezone` - (String) Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the cron activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones. + * `timezone` - (String) Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the CRON activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z+_., \/]{1,253}$/`. * `type` - (String) Trigger type. * Constraints: Allowable values are: `manual`, `scm`, `timer`, `generic`. @@ -197,7 +196,6 @@ Nested schema for **triggers**: * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. * `updated_at` - (String) Standard RFC 3339 Date Time String. - * `worker` - (List) Details of the worker used to run the pipeline. Nested schema for **worker**: * `id` - (String) ID of the worker. diff --git a/website/docs/d/cd_tekton_pipeline_definition.html.markdown b/website/docs/d/cd_tekton_pipeline_definition.html.markdown index eb8d6b1fa8..1348def3eb 100644 --- a/website/docs/d/cd_tekton_pipeline_definition.html.markdown +++ b/website/docs/d/cd_tekton_pipeline_definition.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline_definition -Provides a read-only data source to retrieve information about a cd_tekton_pipeline_definition. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. +Provides a read-only data source for cd_tekton_pipeline_definition. You can then reference the fields of the data source in other resources within the same configuration using interpolation syntax. ## Example Usage @@ -21,7 +21,7 @@ data "ibm_cd_tekton_pipeline_definition" "cd_tekton_pipeline_definition" { ## Argument Reference -You can specify the following arguments for this data source. +Review the argument reference that you can specify for your data source. * `definition_id` - (Required, Forces new resource, String) The definition ID. * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. @@ -30,12 +30,11 @@ You can specify the following arguments for this data source. ## Attribute Reference -After your data source is created, you can read values from the following attributes. +In addition to all argument references listed, you can access the following attribute references after your data source is created. * `id` - The unique identifier of the cd_tekton_pipeline_definition. * `href` - (String) API URL for interacting with the definition. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. - * `source` - (List) Source repository containing the Tekton pipeline definition. Nested schema for **source**: * `properties` - (List) Properties of the source, which define the URL of the repository and a branch or tag. diff --git a/website/docs/d/cd_tekton_pipeline_property.html.markdown b/website/docs/d/cd_tekton_pipeline_property.html.markdown index 820be2a01b..2316b7e8af 100644 --- a/website/docs/d/cd_tekton_pipeline_property.html.markdown +++ b/website/docs/d/cd_tekton_pipeline_property.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline_property -Provides a read-only data source to retrieve information about a cd_tekton_pipeline_property. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. +Provides a read-only data source for cd_tekton_pipeline_property. You can then reference the fields of the data source in other resources within the same configuration using interpolation syntax. ## Example Usage @@ -21,7 +21,7 @@ data "ibm_cd_tekton_pipeline_property" "cd_tekton_pipeline_property" { ## Argument Reference -You can specify the following arguments for this data source. +Review the argument reference that you can specify for your data source. * `pipeline_id` - (Required, Forces new resource, String) The Tekton pipeline ID. * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. @@ -30,7 +30,7 @@ You can specify the following arguments for this data source. ## Attribute Reference -After your data source is created, you can read values from the following attributes. +In addition to all argument references listed, you can access the following attribute references after your data source is created. * `id` - The unique identifier of the cd_tekton_pipeline_property. * `enum` - (List) Options for `single_select` property type. Only needed when using `single_select` property type. diff --git a/website/docs/d/cd_tekton_pipeline_trigger.html.markdown b/website/docs/d/cd_tekton_pipeline_trigger.html.markdown index c3daa65898..888943eaec 100644 --- a/website/docs/d/cd_tekton_pipeline_trigger.html.markdown +++ b/website/docs/d/cd_tekton_pipeline_trigger.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline_trigger -Provides a read-only data source to retrieve information about a cd_tekton_pipeline_trigger. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. +Provides a read-only data source for cd_tekton_pipeline_trigger. You can then reference the fields of the data source in other resources within the same configuration using interpolation syntax. ## Example Usage @@ -21,7 +21,7 @@ data "ibm_cd_tekton_pipeline_trigger" "cd_tekton_pipeline_trigger" { ## Argument Reference -You can specify the following arguments for this data source. +Review the argument reference that you can specify for your data source. * `pipeline_id` - (Required, Forces new resource, String) The Tekton pipeline ID. * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. @@ -30,24 +30,27 @@ You can specify the following arguments for this data source. ## Attribute Reference -After your data source is created, you can read values from the following attributes. +In addition to all argument references listed, you can access the following attribute references after your data source is created. * `id` - The unique identifier of the cd_tekton_pipeline_trigger. -* `cron` - (String) Only needed for timer triggers. Cron expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: 0 *_/2 * * * - every 2 hours. +* `cron` - (String) Only needed for timer triggers. CRON expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: The CRON expression 0 *_/2 * * * - translates to - every 2 hours. * Constraints: The maximum length is `253` characters. The minimum length is `5` characters. The value must match regular expression `/^[-0-9a-zA-Z,\\*\/ ]{5,253}$/`. -* `enabled` - (Boolean) Flag whether the trigger is enabled. +* `enabled` - (Boolean) Flag to check if the trigger is enabled. * Constraints: The default value is `true`. * `event_listener` - (String) Event listener name. The name of the event listener to which the trigger is associated. The event listeners are defined in the definition repositories of the Tekton pipeline. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. -* `events` - (List) Only needed for Git triggers. List of events to which a Git trigger listens. Choose one or more from: 'push', 'pull_request' and 'pull_request_closed'. For SCM repositories that use 'merge request' events, such events map to the equivalent 'pull request' events. +* `events` - (List) Either 'events' or 'filter' is required specifically for Git triggers. Stores a list of events that a Git trigger listens to. Choose one or more from 'push', 'pull_request', and 'pull_request_closed'. If SCM repositories use the 'merge request' term, they correspond to the generic term i.e. 'pull request'. * Constraints: Allowable list items are: `push`, `pull_request`, `pull_request_closed`. The maximum length is `3` items. The minimum length is `0` items. * `favorite` - (Boolean) Mark the trigger as a favorite. * Constraints: The default value is `false`. +* `filter` - (String) Either 'events' or 'filter' can be used. Stores the CEL (Common Expression Language) expression value which is used for event filtering against the Git webhook payloads. + * Constraints: The maximum length is `4096` characters. The minimum length is `1` character. The value must match regular expression `/^.*$/`. + * `href` - (String) API URL for interacting with the trigger. Only included when fetching the list of pipeline triggers. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. @@ -55,8 +58,7 @@ After your data source is created, you can read values from the following attrib * `name` - (String) Trigger name. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^([a-zA-Z0-9]{1,2}|[a-zA-Z0-9][0-9a-zA-Z-_.: \/\\(\\)\\[\\]]{1,251}[a-zA-Z0-9])$/`. - -* `properties` - (List) Optional trigger properties used to override or supplement the pipeline properties when triggering a pipeline run. +* `properties` - (List) Optional trigger properties are used to override or supplement the pipeline properties when triggering a pipeline run. * Constraints: The maximum length is `1024` items. The minimum length is `0` items. Nested schema for **properties**: * `enum` - (List) Options for `single_select` property type. Only needed for `single_select` property type. @@ -72,8 +74,7 @@ Nested schema for **properties**: * Constraints: Allowable values are: `secure`, `text`, `integration`, `single_select`, `appconfig`. * `value` - (String) Property value. Any string value is valid. * Constraints: The maximum length is `4096` characters. The minimum length is `0` characters. The value must match regular expression `/^.*$/`. - -* `secret` - (List) Only needed for generic webhook trigger type. Secret used to start generic webhook trigger. +* `secret` - (List) Only needed for Generic Webhook trigger type. The secret is used to start the Generic Webhook trigger. Nested schema for **secret**: * `algorithm` - (String) Algorithm used for `digest_matches` secret type. Only needed for `digest_matches` secret type. * Constraints: Allowable values are: `md4`, `md5`, `sha1`, `sha256`, `sha384`, `sha512`, `sha512_224`, `sha512_256`, `ripemd160`. @@ -85,17 +86,16 @@ Nested schema for **secret**: * Constraints: Allowable values are: `token_matches`, `digest_matches`, `internal_validation`. * `value` - (String) Secret value, not needed if secret type is `internal_validation`. * Constraints: The maximum length is `4096` characters. The minimum length is `0` characters. The value must match regular expression `/^.*$/`. - * `source` - (List) Source repository for a Git trigger. Only required for Git triggers. The referenced repository URL must match the URL of a repository tool integration in the parent toolchain. Obtain the list of integrations from the toolchain API https://cloud.ibm.com/apidocs/toolchain#list-tools. Nested schema for **source**: * `properties` - (List) Properties of the source, which define the URL of the repository and a branch or pattern. Nested schema for **properties**: * `blind_connection` - (Boolean) True if the repository server is not addressable on the public internet. IBM Cloud will not be able to validate the connection details you provide. - * `branch` - (String) Name of a branch from the repo. One of branch or pattern must be specified, but only one or the other. + * `branch` - (String) Name of a branch from the repo. Only one of branch, pattern, or filter should be specified. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `hook_id` - (String) ID of the webhook from the repo. Computed upon creation of the trigger. + * `hook_id` - (String) Repository webhook ID. It is generated upon trigger creation. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `pattern` - (String) The pattern of Git branch or tag to which to listen. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags/branches in the repository. The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. One of branch or pattern must be specified, but only one or the other. + * `pattern` - (String) The pattern of Git branch or tag. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags or branches in the repository.The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. Only one of branch, pattern, or filter should be specified. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.:@=$&^\/\\?\\!\\*\\+\\[\\]\\(\\)\\{\\}\\|\\\\]*$/`. * `tool` - (List) Reference to the repository tool in the parent toolchain. Nested schema for **tool**: @@ -109,7 +109,7 @@ Nested schema for **source**: * `tags` - (List) Optional trigger tags array. * Constraints: The list items must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. The maximum length is `128` items. The minimum length is `0` items. -* `timezone` - (String) Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the cron activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones. +* `timezone` - (String) Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the CRON activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z+_., \/]{1,253}$/`. * `type` - (String) Trigger type. @@ -117,7 +117,6 @@ Nested schema for **source**: * `webhook_url` - (String) Webhook URL that can be used to trigger pipeline runs. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. - * `worker` - (List) Details of the worker used to run the trigger. Nested schema for **worker**: * `id` - (String) ID of the worker. diff --git a/website/docs/d/cd_tekton_pipeline_trigger_property.html.markdown b/website/docs/d/cd_tekton_pipeline_trigger_property.html.markdown index 8e39c53fe6..fcdfffa3e9 100644 --- a/website/docs/d/cd_tekton_pipeline_trigger_property.html.markdown +++ b/website/docs/d/cd_tekton_pipeline_trigger_property.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline_trigger_property -Provides a read-only data source to retrieve information about a cd_tekton_pipeline_trigger_property. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. +Provides a read-only data source for cd_tekton_pipeline_trigger_property. You can then reference the fields of the data source in other resources within the same configuration using interpolation syntax. ## Example Usage @@ -22,7 +22,7 @@ data "ibm_cd_tekton_pipeline_trigger_property" "cd_tekton_pipeline_trigger_prope ## Argument Reference -You can specify the following arguments for this data source. +Review the argument reference that you can specify for your data source. * `pipeline_id` - (Required, Forces new resource, String) The Tekton pipeline ID. * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. @@ -33,7 +33,7 @@ You can specify the following arguments for this data source. ## Attribute Reference -After your data source is created, you can read values from the following attributes. +In addition to all argument references listed, you can access the following attribute references after your data source is created. * `id` - The unique identifier of the cd_tekton_pipeline_trigger_property. * `enum` - (List) Options for `single_select` property type. Only needed for `single_select` property type. diff --git a/website/docs/d/cis_origin_certificates.html.markdown b/website/docs/d/cis_origin_certificates.html.markdown new file mode 100644 index 0000000000..0ebca0c19b --- /dev/null +++ b/website/docs/d/cis_origin_certificates.html.markdown @@ -0,0 +1,43 @@ +--- +subcategory: "Internet services" +layout: "ibm" +page_title: "IBM: ibm_cis_origin_certificates" +description: |- + Get information on IBM Cloud Internet Services Certificates. +--- + +# ibm_cis_origin_certificates + +Retrieve the information of an existing IBM Cloud Internet Services certificates resource. For more information about CIS origin certificates, refer to [managing origin certificates](https://cloud.ibm.com/docs/cis?topic=cis-cis-origin-certificates). + +## Example usage + +```terraform + +data ibm_cis_origin_certificates "test" { + cis_id = ibm_cis.instance.id + domain_id = ibm_cis_domain.example.id + certificate_id = "25392180178235735583993116186144990011711092749" +} +``` + +## Argument reference + +Review the argument references that you can specify for your data source. + +- `cis_id` - (Required, String) The ID of the CIS instance. +- `domain_id` - (Required, String) The ID of the domain. +- `certificate_id` - (Optional, String) The ID of the certificate. If the ID is not provided, you will get the list of certificates. If the ID is provided, then you will get the information of that certificate. + +## Attribute reference + +In addition to the argument reference list, you can access the following attribute references after your data source is created. + +- `origin_certificate_list` - (String) The collection of the certificates. + + origin_certificate_list + - `certificate_id` - (String) The certificate ID. + - `certificate` (String) Certificate associated with the origin certificate. + - `expires_on` - (String) Expiration date of the certificate. + - `hostnames` - (List[String]) The hosts associated with the certificate. + - `request_type` - (String) The type of the certificate. diff --git a/website/docs/d/container_cluster.html.markdown b/website/docs/d/container_cluster.html.markdown index fed8bf814b..21b7656011 100644 --- a/website/docs/d/container_cluster.html.markdown +++ b/website/docs/d/container_cluster.html.markdown @@ -33,6 +33,8 @@ Review the argument references that you can specify for your data source. - `name` - (Optional, String) The name or ID of the cluster. - `list_bounded_services`- (Optional, Bool) If set to **false** services which are bound to the cluster are not going to be listed. The default value is **true**. - `resource_group_id` - (Optional, String) The ID of the resource group where your cluster is provisioned into. To list resource groups, run `ibmcloud resource groups` or use the `ibm_resource_group` data source. +- `wait_till` - (Optional, String) The cluster creation happens in multi-stages. To avoid the longer wait times for resource execution. This argument in the resource will wait for the specified stage and complete the execution. The supported stages are `MasterNodeReady` Resource waits till the master node is ready. `OneWorkerNodeReady` Resource waits till one worker node is in to ready state. `Normal` Terraform marks the creation of your cluster complete when the cluster is in a [Normal](https://cloud.ibm.com/docs/containers?topic=containers-cluster-states-reference#cluster-state-normal) state. At the moment wait_till `Normal` also ignores the critical and warning states the are temporary happen during cluster creation, but cannot distinguish it from actual critical or warning states. If you do not specify this option, the provider will not wait. +- `wait_till_timeout` - ( Optional, Int ) This parameter can be used to set the `wait_till` timeout in minutes. The `wait_till_timeout` can only be used with `wait_till`. The default value is 20 minutes. **Deprecated reference** @@ -72,6 +74,7 @@ In addition to all argument reference list, you can access the following attribu - `public_service_endpoint_url` - (String) The URL of the public service endpoint for your cluster. - `private_service_endpoint` - (Bool) Indicates if the private service endpoint is enabled (**true**) or disabled (**false**) for a cluster. - `private_service_endpoint_url` - (String) The URL of the private service endpoint for your cluster. +- `state` - (String) The state of the cluster. - `vlans`- (List of objects) A list of VLANs that are attached to the cluster. Nested scheme for `vlans`: diff --git a/website/docs/d/container_vpc_cluster.html.markdown b/website/docs/d/container_vpc_cluster.html.markdown index 4cc27d261d..cb74ce1fb9 100644 --- a/website/docs/d/container_vpc_cluster.html.markdown +++ b/website/docs/d/container_vpc_cluster.html.markdown @@ -25,6 +25,8 @@ Review the argument reference that you can specify for your data source. - `cluster_name_id` - (Deprecated, String) The name or ID of the VPC cluster that you want to retrieve. - `name` - (Optional, String) The name or ID of the cluster. - `resource_group_id` - (Optional, String) The ID of the resource group where your cluster is provisioned into. To list resource groups, run `ibmcloud resource groups` or use the `ibm_resource_group` data source. +- `wait_till` - (Optional, String) The creation of a cluster can take a few minutes (for virtual servers) or even hours (for Bare Metal servers) to complete. There are use-cases where your cluster creation needs to reach a certain stage before it can be integrate with other Terraform components. You can specify the stage when you want Terraform to mark the cluster datasource creation as completed. Depending on what stage you choose, the cluster creation might not be fully completed and continues to run in the background. However, your Terraform code can continue to run without waiting for the cluster to be fully created. Supported stages are:
  • `Normal`: Terraform marks the creation of your cluster complete when the cluster is in a [Normal](https://cloud.ibm.com/docs/containers?topic=containers-cluster-states-reference#cluster-state-normal) state. If you plan to do reading on the cluster from a datasource, use `Normal`. At the moment wait_till `Normal` also ignores the critical and warning states that occasionally happen during cluster creation, but cannot distinguish it from actual critical or warning states.
  • `MasterNodeReady`: Terraform marks the creation of your cluster complete when the cluster master is in a ready state.
  • `OneWorkerNodeReady`: Terraform marks the creation of your cluster complete when the master and at least one worker node are in a ready state.
  • `IngressReady`: Terraform marks the creation of your cluster complete when the cluster master and all worker nodes are in a ready state, and the Ingress subdomain is fully set up.
If you do not specify this option, the provider will not wait. +- `wait_till_timeout` - ( Optional, Int ) This parameter can be used to set the `wait_till` timeout in minutes. The `wait_till_timeout` can only be used with `wait_till`. The default value is 20 minutes. ## Attribute reference In addition to all argument reference list, you can access the following attribute references after your data source is created. diff --git a/website/docs/d/cos_bucket.html.markdown b/website/docs/d/cos_bucket.html.markdown index 15d9a767af..4c6b7092db 100644 --- a/website/docs/d/cos_bucket.html.markdown +++ b/website/docs/d/cos_bucket.html.markdown @@ -231,8 +231,42 @@ In addition to all argument reference list, you can access the following attribu - `website_endpoint` - (string) Website endpoint, if the bucket is configured with a website. If not, this will be an empty string. -- `single_site_location` - (string) The location to create a single site bucket. -- `storage_class` - (string) The storage class of the bucket. -- `s3_endpoint_public` - (string) Public endpoint for cos bucket. -- `s3_endpoint_private` - (string) Private endpoint for cos bucket. -- `s3_endpoint_direct` - (string) Direct endpoint for cos bucket. +- `single_site_location` - (String) The location to create a single site bucket. +- `storage_class` - (String) The storage class of the bucket. +- `s3_endpoint_public` - (String) Public endpoint for cos bucket. +- `s3_endpoint_private` - (String) Private endpoint for cos bucket. +- `s3_endpoint_direct` - (String) Direct endpoint for cos bucket. +**Note:** + +Since the current endpoints file schema does not support "direct", the user must define direct url under "private" for "IBMCLOUD_COS_CONFIG_ENDPOINT" and "IBMCLOUD_COS_ENDPOINT". + + +**Example**: + +```json +{ + "IBMCLOUD_COS_CONFIG_ENDPOINT":{ + "public":{ + "us-south":"https://config.cloud-object-storage.cloud.ibm.com/v1" + }, + "private":{ + "us-south":"https://config.direct.cloud-object-storage.cloud.ibm.com/v1" + } + } +} +``` + +OR + +```json +{ + "IBMCLOUD_COS_CONFIG_ENDPOINT":{ + "public":{ + "us-south":"https://config.cloud-object-storage.cloud.ibm.com/v1" + }, + "private":{ + "us-south":"https://config.private.cloud-object-storage.cloud.ibm.com/v1" + } + } +} +``` diff --git a/website/docs/d/en_metrics.html.markdown b/website/docs/d/en_metrics.html.markdown new file mode 100644 index 0000000000..93782e40be --- /dev/null +++ b/website/docs/d/en_metrics.html.markdown @@ -0,0 +1,65 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_en_metrics" +description: |- + Get information about en_metrics +subcategory: "Event Notifications API" +--- + +# ibm_en_metrics + +Provides a read-only data source to retrieve information about en_metrics. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_en_metrics" "en_metrics" { + destination_type = "smtp_custom" + gte = "gte" + instance_id = "instance_id" + lte = "lte" +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +* `destination_id` - (Optional, String) Unique identifier for Destination. + * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]/`. +* `destination_type` - (Required, String) Destination type. Allowed values are [smtp_custom]. + * Constraints: Allowable values are: `smtp_custom`. +* `email_to` - (Optional, String) Receiver email id. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9\\._%+\\-]+@[A-Za-z0-9\\.\\-]+\\.[A-Za-z]{2,}/`. +* `gte` - (Required, String) GTE (greater than equal), start timestamp in UTC. + * Constraints: The maximum length is `28` characters. The minimum length is `1` character. The value must match regular expression `/[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}Z/`. +* `instance_id` - (Required, Forces new resource, String) Unique identifier for IBM Cloud Event Notifications instance. + * Constraints: The maximum length is `256` characters. The minimum length is `10` characters. The value must match regular expression `/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]/`. +* `lte` - (Required, String) LTE (less than equal), end timestamp in UTC. + * Constraints: The maximum length is `28` characters. The minimum length is `1` character. The value must match regular expression `/[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}Z/`. +* `notification_id` - (Optional, String) Notification Id. + * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/`. +* `source_id` - (Optional, String) Unique identifier for Source. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/[a-zA-Z0-9-:_]*/`. +* `subject` - (Optional, String) Email subject. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[a-zA-Z0-9]/`. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +* `id` - The unique identifier of the en_metrics. +* `metrics` - (List) array of metrics. + * Constraints: The maximum length is `5` items. The minimum length is `5` items. +Nested schema for **metrics**: + * `doc_count` - (Integer) doc count. + * `histogram` - (List) Payload describing histogram. + Nested schema for **histogram**: + * `buckets` - (List) List of buckets. + * Constraints: The maximum length is `48` items. The minimum length is `0` items. + Nested schema for **buckets**: + * `doc_count` - (Integer) Total count. + * `key_as_string` - (String) Timestamp. + * `key` - (String) key. + * Constraints: Allowable values are: `bounced`, `deferred`, `opened`, `success`, `submitted`. The maximum length is `255` characters. The minimum length is `1` character. + diff --git a/website/docs/d/en_smtp_allowed_ips.html.markdown b/website/docs/d/en_smtp_allowed_ips.html.markdown new file mode 100644 index 0000000000..386a8b73de --- /dev/null +++ b/website/docs/d/en_smtp_allowed_ips.html.markdown @@ -0,0 +1,40 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_en_smtp_allowed_ips" +description: |- + Get information about en_smtp_allowed_ips +subcategory: "Event Notifications API" +--- + +# ibm_en_smtp_allowed_ips + +Provides a read-only data source to retrieve information about en_smtp_allowed_ips. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_en_smtp_allowed_ips" "en_smtp_allowed_ips" { + en_smtp_allowed_ips_id = "en_smtp_allowed_ips_id" + instance_id = "instance_id" +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +* `en_smtp_allowed_ips_id` - (Required, Forces new resource, String) Unique identifier for SMTP. + * Constraints: The maximum length is `32` characters. The minimum length is `32` characters. The value must match regular expression `/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/`. +* `instance_id` - (Required, Forces new resource, String) Unique identifier for IBM Cloud Event Notifications instance. + * Constraints: The maximum length is `256` characters. The minimum length is `10` characters. The value must match regular expression `/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]/`. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +* `id` - The unique identifier of the en_smtp_allowed_ips. +* `subnets` - (List) The SMTP allowed Ips. + * Constraints: The list items must match regular expression `/.*/`. The maximum length is `100` items. The minimum length is `1` item. + +* `updated_at` - (String) Updated at. + diff --git a/website/docs/d/is_bare_metal_server.markdown b/website/docs/d/is_bare_metal_server.markdown index 046bd65620..b0a118b2a0 100644 --- a/website/docs/d/is_bare_metal_server.markdown +++ b/website/docs/d/is_bare_metal_server.markdown @@ -94,6 +94,7 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The unique identifier for this reserved IP. - `name` - (String) The name for this reserved IP. The name is unique across all reserved IPs in a subnet. - `resource_type` - (String) The resource type. + - `resource_type` - (String) The resource type. - `subnet` - (List) The subnet of the virtual network interface for the network attachment. Nested schema for **subnet**: @@ -105,6 +106,14 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The unique identifier for this subnet. - `name` - (String) The name for this subnet. The name is unique across all subnets in the VPC. - `resource_type` - (String) The resource type. + - `virtual_network_interface` - (List) The virtual network interface for this bare metal server network attachment. + Nested schema for **virtual_network_interface**: + - `crn` - (String) The CRN for this virtual network interface. + - `href` - (String) The URL for this virtual network interface. + - `id` - (String) The unique identifier for this virtual network interface. + - `name` - (String) The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC. + - `resource_type` - (String) The resource type. + - `network_interfaces` - (List) A nested block describing the additional network interface of this instance. Nested scheme for `network_interfaces`: - `allow_ip_spoofing` - (Bool) Indicates whether source IP spoofing is allowed on this interface. If false, source IP spoofing is prevented on this interface. If true, source IP spoofing is allowed on this interface. @@ -151,6 +160,13 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The unique identifier for this subnet. - `name` - (String) The name for this subnet. The name is unique across all subnets in the VPC. - `resource_type` - (String) The resource type. + - `virtual_network_interface` - (List) The virtual network interface for this bare metal server network attachment. + Nested schema for **virtual_network_interface**: + - `crn` - (String) The CRN for this virtual network interface. + - `href` - (String) The URL for this virtual network interface. + - `id` - (String) The unique identifier for this virtual network interface. + - `name` - (String) The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC. + - `resource_type` - (String) The resource type. - `primary_network_interface` - (List) A nested block describing the primary network interface of this bare metal server. Nested scheme for `primary_network_interface`: - `allow_ip_spoofing` - (Bool) Indicates whether source IP spoofing is allowed on this interface. If false, source IP spoofing is prevented on this interface. If true, source IP spoofing is allowed on this interface. @@ -170,6 +186,12 @@ In addition to all argument reference list, you can access the following attribu - `profile` - (String) The name for this bare metal server profile - `resource_group` - (String) resource group id of the bare metal server. - `resource_type` - (String) The type of resource referenced +- `firmware_update_type_available` - (String) The firmware update type available for the bare metal server. + + -> **Supported firmware update types** +
• none +
• optional +
• required - `status` - (String) The status of the bare metal server. -> **Supported Status** diff --git a/website/docs/d/is_bare_metal_servers.markdown b/website/docs/d/is_bare_metal_servers.markdown index 6518ded3ce..037c5fd49a 100644 --- a/website/docs/d/is_bare_metal_servers.markdown +++ b/website/docs/d/is_bare_metal_servers.markdown @@ -97,6 +97,14 @@ Review the attribute references that you can access after you retrieve your data - `id` - (String) The unique identifier for this subnet. - `name` - (String) The name for this subnet. The name is unique across all subnets in the VPC. - `resource_type` - (String) The resource type. + - `virtual_network_interface` - (List) The virtual network interface for this bare metal server network attachment. + Nested schema for **virtual_network_interface**: + - `crn` - (String) The CRN for this virtual network interface. + - `href` - (String) The URL for this virtual network interface. + - `id` - (String) The unique identifier for this virtual network interface. + - `name` - (String) The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC. + - `resource_type` - (String) The resource type. + - `network_interfaces` - (List) A nested block describing the additional network interface of this instance. @@ -145,6 +153,14 @@ Review the attribute references that you can access after you retrieve your data - `id` - (String) The unique identifier for this subnet. - `name` - (String) The name for this subnet. The name is unique across all subnets in the VPC. - `resource_type` - (String) The resource type. + - `virtual_network_interface` - (List) The virtual network interface for this bare metal server network attachment. + Nested schema for **virtual_network_interface**: + - `crn` - (String) The CRN for this virtual network interface. + - `href` - (String) The URL for this virtual network interface. + - `id` - (String) The unique identifier for this virtual network interface. + - `name` - (String) The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC. + - `resource_type` - (String) The resource type. + - `primary_network_interface` - (List) A nested block describing the primary network interface of this bare metal server. Nested scheme for `primary_network_interface`: @@ -166,6 +182,12 @@ Review the attribute references that you can access after you retrieve your data - `profile` - (String) The name for this bare metal server profile - `resource_group` - (String) resource group id of the bare metal server. - `resource_type` - (String) The type of resource referenced + - `firmware_update_type_available` - (String) The firmware update type available for the bare metal server. + + ->**Supported firmware update types** +
• none +
• optional +
• required - `status` - (String) The status of the bare metal server. ->**Supported Status:** diff --git a/website/docs/d/is_instance.html.markdown b/website/docs/d/is_instance.html.markdown index da2a86203e..952a3cfe23 100644 --- a/website/docs/d/is_instance.html.markdown +++ b/website/docs/d/is_instance.html.markdown @@ -213,6 +213,13 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The unique identifier for this subnet. - `name` - (String) The name for this subnet. The name is unique across all subnets in the VPC. - `resource_type` - (String) The resource type. + - `virtual_network_interface` - (List) The virtual network interface for this bare metal server network attachment. + Nested schema for **virtual_network_interface**: + - `crn` - (String) The CRN for this virtual network interface. + - `href` - (String) The URL for this virtual network interface. + - `id` - (String) The unique identifier for this virtual network interface. + - `name` - (String) The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC. + - `resource_type` - (String) The resource type. - `network_interfaces`- (List) A list of more network interfaces that the instance uses. @@ -271,6 +278,14 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The unique identifier for this subnet. - `name` - (String) The name for this subnet. The name is unique across all subnets in the VPC. - `resource_type` - (String) The resource type. + - `virtual_network_interface` - (List) The virtual network interface for this bare metal server network attachment. + Nested schema for **virtual_network_interface**: + - `crn` - (String) The CRN for this virtual network interface. + - `href` - (String) The URL for this virtual network interface. + - `id` - (String) The unique identifier for this virtual network interface. + - `name` - (String) The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC. + - `resource_type` - (String) The resource type. + - `primary_network_interface`- (List) A list of primary network interfaces that were created for the instance. diff --git a/website/docs/d/is_instances.html.markdown b/website/docs/d/is_instances.html.markdown index d28babb838..effd99dcc0 100644 --- a/website/docs/d/is_instances.html.markdown +++ b/website/docs/d/is_instances.html.markdown @@ -147,7 +147,14 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The unique identifier for this subnet. - `name` - (String) The name for this subnet. The name is unique across all subnets in the VPC. - `resource_type` - (String) The resource type. - + - `virtual_network_interface` - (List) The virtual network interface for this bare metal server network attachment. + Nested schema for **virtual_network_interface**: + - `crn` - (String) The CRN for this virtual network interface. + - `href` - (String) The URL for this virtual network interface. + - `id` - (String) The unique identifier for this virtual network interface. + - `name` - (String) The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC. + - `resource_type` - (String) The resource type. + - `network_interfaces`- (List) A list of more network interfaces that the instance uses. Nested scheme for `network_interfaces`: @@ -204,6 +211,14 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The unique identifier for this subnet. - `name` - (String) The name for this subnet. The name is unique across all subnets in the VPC. - `resource_type` - (String) The resource type. + - `virtual_network_interface` - (List) The virtual network interface for this bare metal server network attachment. + Nested schema for **virtual_network_interface**: + - `crn` - (String) The CRN for this virtual network interface. + - `href` - (String) The URL for this virtual network interface. + - `id` - (String) The unique identifier for this virtual network interface. + - `name` - (String) The name for this virtual network interface. The name is unique across all virtual network interfaces in the VPC. + - `resource_type` - (String) The resource type. + - `primary_network_interface`- (List) A list of primary network interfaces that were created for the instance. diff --git a/website/docs/d/is_share.html.markdown b/website/docs/d/is_share.html.markdown index 45a1875c8b..4f24e0c1aa 100644 --- a/website/docs/d/is_share.html.markdown +++ b/website/docs/d/is_share.html.markdown @@ -44,6 +44,14 @@ The following arguments are supported: The following attributes are exported: +- `access_control_mode` - (Boolean) The access control mode for the share. +- `accessor_binding_role` - (String) The accessor binding role of this file share:- `none`: This file share is not participating in access with another file share- `origin`: This file share is the origin for one or more file shares (which may be in other accounts)- `accessor`: This file share is providing access to another file share (which may be in another account). +- `accessor_bindings` - (List) The accessor bindings for this file share. Each accessor binding identifies a resource (possibly in another account) with access to this file share's data. + Nested schema for **accessor_bindings**: + - `href` - (String) The URL for this share accessor binding. + - `id` - (String) The unique identifier for this share accessor binding. + - `resource_type` - (String) The resource type. +- `allowed_transit_encryption_modes` - (List of string) The transit encryption modes allowed for this share. - `access_tags` - (String) Access management tags associated to the share. - `created_at` - The date and time that the file share is created. - `crn` - The CRN for this share. @@ -65,6 +73,26 @@ Nested `latest_sync` blocks have the following structure: - `type` - The type of the file share job - `lifecycle_state` - The lifecycle state of the file share. - `name` - The unique user-defined name for this file share. +- `origin_share` - (Optional, List) The origin share this accessor share is referring to.This property will be present when the `accessor_binding_role` is `accessor`. + Nested schema for **origin_share**: + - `crn` - (Computed, String) The CRN for this file share. + - `deleted` - (Optional, List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (Computed, String) Link to documentation about deleted resources. + - `href` - (Computed, String) The URL for this file share. + - `id` - (Computed, String) The unique identifier for this file share. + - `name` - (Computed, String) The name for this share. The name is unique across all shares in the region. + - `remote` - (Optional, List) If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable. + Nested schema for **remote**: + - `account` - (Optional, List) If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account. + Nested schema for **account**: + - `id` - (Computed, String) The unique identifier for this account. + - `resource_type` - (Computed, String) The resource type. + - `region` - (Optional, List) If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region. + Nested schema for **region**: + - `href` - (Computed, String) The URL for this region. + - `name` - (Computed, String) The globally unique name for this region. + - `resource_type` - (Computed, String) The resource type. - `profile` - The name of the profile this file share uses. - `replication_role` - The replication role of the file share.* `none`: This share is not participating in replication.* `replica`: This share is a replication target.* `source`: This share is a replication source. - `replication_status` - "The replication status of the file share.* `initializing`: This share is initializing replication.* `active`: This share is actively participating in replication.* `failover_pending`: This share is performing a replication failover.* `split_pending`: This share is performing a replication split.* `none`: This share is not participating in replication.* `degraded`: This share's replication sync is degraded.* `sync_pending`: This share is performing a replication sync. diff --git a/website/docs/d/is_share_accessor_binding.html.markdown b/website/docs/d/is_share_accessor_binding.html.markdown new file mode 100644 index 0000000000..e436933aac --- /dev/null +++ b/website/docs/d/is_share_accessor_binding.html.markdown @@ -0,0 +1,61 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_share_accessor_binding" +description: |- + Get information about ShareAccessorBinding +subcategory: "VPC infrastructure" +--- + +# ibm_is_share_accessor_binding + +Provides a read-only data source to retrieve information about a ShareAccessorBinding. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_share_accessor_bindings" "is_share_accessor_bindings" { + share = "shareId" +} +data "ibm_is_share_accessor_binding" "is_share_accessor_binding" { + accessor_binding = "share_accessor_binding_id" + share = "share_id" +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `accessor_binding` - (Required, Forces new resource, String) The file share accessor binding identifier. +- `share` - (Required, Forces new resource, String) The file share identifier. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ShareAccessorBinding. +- `accessor` - (List) The accessor for this share accessor binding.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + Nested schema for **accessor**: + - `crn` - (String) The CRN for this file share. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this file share. + - `id` - (String) The unique identifier for this file share. + - `name` - (String) The name for this share. The name is unique across all shares in the region. + - `remote` - (List) If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable. + Nested schema for **remote**: + - `account` - (List) If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account. + Nested schema for **account**: + - `id` - (String) The unique identifier for this account. + - `resource_type` - (String) The resource type. + - `region` - (List) If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region. + Nested schema for **region**: + - `href` - (String) The URL for this region. + - `name` - (String) The globally unique name for this region. + - `resource_type` - (String) The resource type. +- `created_at` - (String) The date and time that the share accessor binding was created. +- `href` - (String) The URL for this share accessor binding. +- `lifecycle_state` - (String) The lifecycle state of the file share accessor binding. +- `resource_type` - (String) The resource type. + diff --git a/website/docs/d/is_share_accessor_bindings.html.markdown b/website/docs/d/is_share_accessor_bindings.html.markdown new file mode 100644 index 0000000000..7803042c7d --- /dev/null +++ b/website/docs/d/is_share_accessor_bindings.html.markdown @@ -0,0 +1,72 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_share_accessor_bindings" +description: |- + Get information about ShareAccessorBindingCollection +subcategory: "VPC infrastructure" +--- + +# ibm_is_share_accessor_bindings + +Provides a read-only data source to retrieve information about a ShareAccessorBindingCollection. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_share_accessor_bindings" "is_share_accessor_bindings" { + share = "shareId" +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +* `share` - (Required, Forces new resource, String) The file share identifier. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +* `id` - The unique identifier of the ShareAccessorBindingCollection. +* `accessor_bindings` - (List) Collection of share accessor bindings. +Nested schema for **accessor_bindings**: + * `accessor` - (List) The accessor for this share accessor binding.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + Nested schema for **accessor**: + * `crn` - (String) The CRN for this file share. + * `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + * `more_info` - (String) Link to documentation about deleted resources. + * Constraints: The maximum length is `8000` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. + * `href` - (String) The URL for this file share. + * Constraints: The maximum length is `8000` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. + * `id` - (String) The unique identifier for this file share. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-z_]+$/`. + * `name` - (String) The name for this share. The name is unique across all shares in the region. + * Constraints: The maximum length is `63` characters. The minimum length is `1` character. The value must match regular expression `/^-?([a-z]|[a-z][-a-z0-9]*[a-z0-9]|[0-9][-a-z0-9]*([a-z]|[-a-z][-a-z0-9]*[a-z0-9]))$/`. + * `remote` - (List) If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable. + Nested schema for **remote**: + * `account` - (List) If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account. + Nested schema for **account**: + * `id` - (String) The unique identifier for this account. + * Constraints: The value must match regular expression `/^[0-9a-f]{32}$/`. + * `resource_type` - (String) The resource type. + * Constraints: Allowable values are: `account`. The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/`. + * `region` - (List) If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region. + Nested schema for **region**: + * `href` - (String) The URL for this region. + * Constraints: The maximum length is `8000` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. + * `name` - (String) The globally unique name for this region. + * Constraints: The maximum length is `63` characters. The minimum length is `1` character. The value must match regular expression `/^([a-z]|[a-z][-a-z0-9]*[a-z0-9]|[0-9][-a-z0-9]*([a-z]|[-a-z][-a-z0-9]*[a-z0-9]))$/`. + * `resource_type` - (String) The resource type. + * Constraints: Allowable values are: `share`. The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/`. + * `created_at` - (String) The date and time that the share accessor binding was created. + * `href` - (String) The URL for this share accessor binding. + * Constraints: The maximum length is `8000` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. + * `id` - (String) The unique identifier for this share accessor binding. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-z_]+$/`. + * `lifecycle_state` - (String) The lifecycle state of the file share accessor binding. + * Constraints: Allowable values are: `deleting`, `failed`, `pending`, `stable`, `suspended`, `updating`, `waiting`. + * `resource_type` - (String) The resource type. + * Constraints: Allowable values are: `share_accessor_binding`. The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/`. + diff --git a/website/docs/d/is_shares.html.markdown b/website/docs/d/is_shares.html.markdown index 88a6099736..32e70b92f2 100644 --- a/website/docs/d/is_shares.html.markdown +++ b/website/docs/d/is_shares.html.markdown @@ -29,6 +29,14 @@ The following arguments are supported: The following attributes are exported: - `shares` - Collection of file shares. Nested `shares` blocks have the following structure: + - `access_control_mode` - (Boolean) The access control mode for the share. + - `accessor_binding_role` - (String) The accessor binding role of this file share:- `none`: This file share is not participating in access with another file share- `origin`: This file share is the origin for one or more file shares (which may be in other accounts)- `accessor`: This file share is providing access to another file share (which may be in another account). + - `accessor_bindings` - (List) The accessor bindings for this file share. Each accessor binding identifies a resource (possibly in another account) with access to this file share's data. + Nested schema for **accessor_bindings**: + - `href` - (String) The URL for this share accessor binding. + - `id` - (String) The unique identifier for this share accessor binding. + - `resource_type` - (String) The resource type. + - `allowed_transit_encryption_modes` - (List of string) The transit encryption modes allowed for this share. - `created_at` - The date and time that the file share is created. - `crn` - The CRN for this share. - `encryption` - The type of encryption used for this file share. @@ -75,6 +83,26 @@ The following attributes are exported: - `id` - The unique identifier for this share target. - `name` - The user-defined name for this share target. - `resource_type` - The type of resource referenced. + - `origin_share` - (Optional, List) The origin share this accessor share is referring to.This property will be present when the `accessor_binding_role` is `accessor`. + Nested schema for **origin_share**: + - `crn` - (Computed, String) The CRN for this file share. + - `deleted` - (Optional, List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (Computed, String) Link to documentation about deleted resources. + - `href` - (Computed, String) The URL for this file share. + - `id` - (Computed, String) The unique identifier for this file share. + - `name` - (Computed, String) The name for this share. The name is unique across all shares in the region. + - `remote` - (Optional, List) If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable. + Nested schema for **remote**: + - `account` - (Optional, List) If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account. + Nested schema for **account**: + - `id` - (Computed, String) The unique identifier for this account. + - `resource_type` - (Computed, String) The resource type. + - `region` - (Optional, List) If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region. + Nested schema for **region**: + - `href` - (Computed, String) The URL for this region. + - `name` - (Computed, String) The globally unique name for this region. + - `resource_type` - (Computed, String) The resource type. - `zone` - The name of the zone this file share will reside in. - `access_tags` - (String) Access management tags associated to the share. - `tags` - (String) User tags associated for to the share. diff --git a/website/docs/d/logs-router_targets.html.markdown b/website/docs/d/logs-router_targets.html.markdown new file mode 100644 index 0000000000..893f08f47a --- /dev/null +++ b/website/docs/d/logs-router_targets.html.markdown @@ -0,0 +1,58 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_logs_router_targets" +description: |- + Get information about logs_router_targets +subcategory: "IBM Cloud Logs Routing" +--- + +# ibm_logs_router_targets + +Provides a read-only data source to retrieve information about logs_router_targets. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_logs_router_targets" "logs_router_targets" { + tenant_id = "9fab83da-98cb-4f18-a7ba-b6f0435c9673" + name = "my-target" +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +* `name` - (Optional, String) Optional: Name of the tenant target. + * Constraints: The maximum length is `35` characters. The minimum length is `1` character. The value must match regular expression `/[A-F,0-9,-]/`. +* `tenant_id` - (Required, Forces new resource, String) The instance ID of the tenant. + * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/[A-F,0-9,-]/`. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +* `id` - The unique identifier of the logs_router_targets. +* `targets` - (List) List of target of a tenant. + * Constraints: The maximum length is `2` items. The minimum length is `1` item. +Nested schema for **targets**: + * `created_at` - (String) Time stamp the target was originally created. + * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/[0-9,:,.,-,T,Z]/`. + * `etag` - (String) Resource version identifier. + * Constraints: The maximum length is `66` characters. The minimum length is `66` characters. The value must match regular expression `/(?:W\/)?"(?:[ !#-\\x7E\\x80-\\xFF]*| [ ]|\\.)*"/`. + * `id` - (String) Unique ID of the target. + * `log_sink_crn` - (String) Cloud resource name of the log-sink target instance. + * Constraints: The maximum length is `256` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,:,-]/`. + * `name` - (String) The name for this tenant target. The name is unique across all targets for this tenant. + * Constraints: The maximum length is `35` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,-,.]/`. + * `parameters` - (List) List of properties returned from a successful list operation for a log-sink of type IBM Log Analysis (logdna). + Nested schema for **parameters**: + * `host` - (String) Host name of the log-sink. + * Constraints: The maximum length is `256` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,-,.]/`. + * `port` - (Integer) Network port of the log-sink. + * Constraints: The maximum value is `65535`. The minimum value is `1`. + * `type` - (String) Type of log-sink. Identical to the service-name segment of log_sink_crn. + * Constraints: Allowable values are: `logdna`. + * `updated_at` - (String) Time stamp the target was last updated. + * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/[0-9,:,.,-,T,Z]/`. + diff --git a/website/docs/d/logs-router_tenants.html.markdown b/website/docs/d/logs-router_tenants.html.markdown new file mode 100644 index 0000000000..412e74341c --- /dev/null +++ b/website/docs/d/logs-router_tenants.html.markdown @@ -0,0 +1,69 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_logs_router_tenants" +description: |- + Get information about logs_router_tenants +subcategory: "IBM Cloud Logs Routing" +--- + +# ibm_logs_router_tenants + +Provides a read-only data source to retrieve information about logs_router_tenants. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_logs_router_tenants" "logs_router_tenants" { + name = ibm_logs_router_tenant.logs_router_tenant_instance.name +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +* `name` - (Required, String) Optional: The name of a tenant. + * Constraints: The maximum length is `35` characters. The minimum length is `1` character. The value must match regular expression `/[A-F,0-9,-]/`. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +* `id` - The unique identifier of the logs_router_tenants. +* `tenants` - (List) List of tenants in the account. + * Constraints: The maximum length is `1` item. The minimum length is `0` items. +Nested schema for **tenants**: + * `created_at` - (String) Time stamp the tenant was originally created. + * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/[0-9,:,.,-,T,Z]/`. + * `crn` - (String) Cloud resource name of the tenant. + * Constraints: The maximum length is `256` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,:,-]/`. + * `etag` - (String) Resource version identifier. + * Constraints: The maximum length is `66` characters. The minimum length is `66` characters. The value must match regular expression `/(?:W\/)?"(?:[ !#-\\x7E\\x80-\\xFF]*| [ ]|\\.)*"/`. + * `id` - (String) Unique ID of the tenant. + * `name` - (String) The name for this tenant. The name is regionally unique across all tenants in the account. + * Constraints: The maximum length is `35` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,-,.]/`. + * `targets` - (List) List of targets. + * Constraints: The maximum length is `2` items. The minimum length is `1` item. + Nested schema for **targets**: + * `created_at` - (String) Time stamp the target was originally created. + * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/[0-9,:,.,-,T,Z]/`. + * `etag` - (String) Resource version identifier. + * Constraints: The maximum length is `66` characters. The minimum length is `66` characters. The value must match regular expression `/(?:W\/)?"(?:[ !#-\\x7E\\x80-\\xFF]*| [ ]|\\.)*"/`. + * `id` - (String) Unique ID of the target. + * `log_sink_crn` - (String) Cloud resource name of the log-sink target instance. + * Constraints: The maximum length is `256` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,:,-]/`. + * `name` - (String) The name for this tenant target. The name is unique across all targets for this tenant. + * Constraints: The maximum length is `35` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,-,.]/`. + * `parameters` - (List) List of properties returned from a successful list operation for a log-sink of type IBM Log Analysis (logdna). + Nested schema for **parameters**: + * `host` - (String) Host name of the log-sink. + * Constraints: The maximum length is `256` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,-,.]/`. + * `port` - (Integer) Network port of the log-sink. + * Constraints: The maximum value is `65535`. The minimum value is `1`. + * `type` - (String) Type of log-sink. Identical to the service-name segment of log_sink_crn. + * Constraints: Allowable values are: `logdna`. + * `updated_at` - (String) Time stamp the target was last updated. + * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/[0-9,:,.,-,T,Z]/`. + * `updated_at` - (String) Time stamp the tenant was last updated. + * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/[0-9,:,.,-,T,Z]/`. + diff --git a/website/docs/d/logs_alert.html.markdown b/website/docs/d/logs_alert.html.markdown index 84e153aba3..25b2398eca 100644 --- a/website/docs/d/logs_alert.html.markdown +++ b/website/docs/d/logs_alert.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_alert diff --git a/website/docs/d/logs_alerts.html.markdown b/website/docs/d/logs_alerts.html.markdown index 0c38279d7c..951c9a32d9 100644 --- a/website/docs/d/logs_alerts.html.markdown +++ b/website/docs/d/logs_alerts.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_alerts diff --git a/website/docs/d/logs_dashboard.html.markdown b/website/docs/d/logs_dashboard.html.markdown index 91c3078e69..a71aed65be 100644 --- a/website/docs/d/logs_dashboard.html.markdown +++ b/website/docs/d/logs_dashboard.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_dashboard diff --git a/website/docs/d/logs_dashboard_folders.html.markdown b/website/docs/d/logs_dashboard_folders.html.markdown index cbf2e1a90a..e6beff78f4 100644 --- a/website/docs/d/logs_dashboard_folders.html.markdown +++ b/website/docs/d/logs_dashboard_folders.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_dashboard_folders diff --git a/website/docs/d/logs_e2m.html.markdown b/website/docs/d/logs_e2m.html.markdown index 9d4e6684ae..4b8445766e 100644 --- a/website/docs/d/logs_e2m.html.markdown +++ b/website/docs/d/logs_e2m.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_e2m diff --git a/website/docs/d/logs_e2ms.html.markdown b/website/docs/d/logs_e2ms.html.markdown index 559c5ec3ed..98316b9f08 100644 --- a/website/docs/d/logs_e2ms.html.markdown +++ b/website/docs/d/logs_e2ms.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_e2ms diff --git a/website/docs/d/logs_outgoing_webhook.html.markdown b/website/docs/d/logs_outgoing_webhook.html.markdown index 1275585f1d..f4b4a0a9f1 100644 --- a/website/docs/d/logs_outgoing_webhook.html.markdown +++ b/website/docs/d/logs_outgoing_webhook.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_outgoing_webhook diff --git a/website/docs/d/logs_outgoing_webhooks.html.markdown b/website/docs/d/logs_outgoing_webhooks.html.markdown index d77948f0a6..a1cae70f63 100644 --- a/website/docs/d/logs_outgoing_webhooks.html.markdown +++ b/website/docs/d/logs_outgoing_webhooks.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_outgoing_webhooks diff --git a/website/docs/d/logs_policies.html.markdown b/website/docs/d/logs_policies.html.markdown index 7402f04976..d195ff9077 100644 --- a/website/docs/d/logs_policies.html.markdown +++ b/website/docs/d/logs_policies.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_policies diff --git a/website/docs/d/logs_policy.html.markdown b/website/docs/d/logs_policy.html.markdown index 33fa0681c2..3200eca0a8 100644 --- a/website/docs/d/logs_policy.html.markdown +++ b/website/docs/d/logs_policy.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_policy diff --git a/website/docs/d/logs_rule_group.html.markdown b/website/docs/d/logs_rule_group.html.markdown index 083c0bb0b6..3f68821d3f 100644 --- a/website/docs/d/logs_rule_group.html.markdown +++ b/website/docs/d/logs_rule_group.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_rule_group diff --git a/website/docs/d/logs_rule_groups.html.markdown b/website/docs/d/logs_rule_groups.html.markdown index 377f0e826a..0090cef0c8 100644 --- a/website/docs/d/logs_rule_groups.html.markdown +++ b/website/docs/d/logs_rule_groups.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_rule_groups diff --git a/website/docs/d/logs_view.html.markdown b/website/docs/d/logs_view.html.markdown index 043bda8638..dc55c6c3e2 100644 --- a/website/docs/d/logs_view.html.markdown +++ b/website/docs/d/logs_view.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_view diff --git a/website/docs/d/logs_view_folder.html.markdown b/website/docs/d/logs_view_folder.html.markdown index ae244d13c1..58faf27aac 100644 --- a/website/docs/d/logs_view_folder.html.markdown +++ b/website/docs/d/logs_view_folder.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_view_folder diff --git a/website/docs/d/logs_view_folders.html.markdown b/website/docs/d/logs_view_folders.html.markdown index cb1c913201..9d7d731497 100644 --- a/website/docs/d/logs_view_folders.html.markdown +++ b/website/docs/d/logs_view_folders.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_view_folders diff --git a/website/docs/d/logs_views.html.markdown b/website/docs/d/logs_views.html.markdown index 7110c2f69d..6591e61da8 100644 --- a/website/docs/d/logs_views.html.markdown +++ b/website/docs/d/logs_views.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_views diff --git a/website/docs/d/pi_instance.html.markdown b/website/docs/d/pi_instance.html.markdown index cd1a1d8db7..dfc470596e 100644 --- a/website/docs/d/pi_instance.html.markdown +++ b/website/docs/d/pi_instance.html.markdown @@ -77,7 +77,8 @@ In addition to all argument reference list, you can access the following attribu Nested scheme for `networks`: - `external_ip` - (String) The external IP address of the instance. - `ip` - (String) The IP address of the instance. - - `macaddress` - (String) The MAC address of the instance. + - `macaddress` - (String) The MAC address of the instance. Deprecated please use `mac_address` instead. + - `mac_address` - (String) The MAC address of the instance. - `network_id` - (String) The network ID of the instance. - `network_name` - (String) The network name of the instance. - `type` - (String) The type of the network. diff --git a/website/docs/d/pi_instances.html.markdown b/website/docs/d/pi_instances.html.markdown index 17d83a3023..0f987e6d0a 100644 --- a/website/docs/d/pi_instances.html.markdown +++ b/website/docs/d/pi_instances.html.markdown @@ -69,7 +69,8 @@ In addition to all argument reference list, you can access the following attribu Nested scheme for `networks`: - `external_ip` - (String) The external IP address of the instance. - `ip` - (String) The IP address of the instance. - - `macaddress` - (String) The MAC address of the instance. + - `macaddress` - (String) The MAC address of the instance. Deprecated please use `mac_address` instead. + - `mac_address` - (String) The MAC address of the instance. - `network_id` - (String) The network ID of the instance. - `network_name` - (String) The network name of the instance. - `type` - (String) The type of the network. diff --git a/website/docs/d/pi_storage_type_capacity.markdown b/website/docs/d/pi_storage_type_capacity.markdown index 5c3a81a3e5..43bad09d4b 100644 --- a/website/docs/d/pi_storage_type_capacity.markdown +++ b/website/docs/d/pi_storage_type_capacity.markdown @@ -7,9 +7,11 @@ description: |- --- # ibm_pi_storage_type_capacity + Retrieve information about storages capacity for a storage type in a region. For more information, see [getting started with IBM Power Systems Virtual Servers](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-getting-started). ## Example usage + ```terraform data "ibm_pi_storage_type_capacity" "type" { pi_cloud_instance_id = "" @@ -17,13 +19,15 @@ data "ibm_pi_storage_type_capacity" "type" { } ``` -**Notes** +### Notes + - Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. - If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: - `region` - `lon` - `zone` - `lon04` Example usage: + ```terraform provider "ibm" { region = "lon" @@ -32,12 +36,14 @@ Example usage: ``` ## Argument reference + Review the argument references that you can specify for your data source. - `pi_cloud_instance_id` - (Required, String) The GUID of the service instance associated with an account. -- `pi_storage_type` - (Required, String) The storage type name. +- `pi_storage_type` - (Required, String) The storage type name. To get a list of available storage types, please use the [ibm_pi_storage_types_capacity](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/pi_storage_types_capacity) data source. ## Attribute reference + In addition to all argument reference list, you can access the following attribute references after your data source is created. - `maximum_storage_allocation` - (Map) Maximum storage allocation. diff --git a/website/docs/d/resource_instance.html.markdown b/website/docs/d/resource_instance.html.markdown index 744b522d8a..122e86ff9f 100644 --- a/website/docs/d/resource_instance.html.markdown +++ b/website/docs/d/resource_instance.html.markdown @@ -48,3 +48,4 @@ In addition to all argument reference list, you can access the following attribu - `parameters_json` - (String) The parameters associated with the instance in json format. - `plan` - (String) The plan for the service offering used by this resource instance. - `status` - (String) The status of resource instance. +- `onetime_credentials` - (Bool) A boolean that dictates if the onetime_credentials is true or false. diff --git a/website/docs/d/resource_key.html.markdown b/website/docs/d/resource_key.html.markdown index 677183ec9c..53b46d268c 100644 --- a/website/docs/d/resource_key.html.markdown +++ b/website/docs/d/resource_key.html.markdown @@ -68,6 +68,7 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The unique identifier of the resource key. - `role` - (String) The user role. - `status` - (String) The status of the resource key. +- `onetime_credentials` - (Bool) A boolean that dictates if the onetime_credentials is true or false. ## Note Credentials will be seen as redacted, if the user does not have access equal to or greater than the access of the service credentials. Please refer to the documentation to access credentials - https://cloud.ibm.com/docs/account?topic=account-service_credentials&interface=ui#viewing-credentials-ui. diff --git a/website/docs/d/satellite_location.html.markdown b/website/docs/d/satellite_location.html.markdown index 614d034919..dd87ddbda0 100644 --- a/website/docs/d/satellite_location.html.markdown +++ b/website/docs/d/satellite_location.html.markdown @@ -29,6 +29,8 @@ In addition to all argument reference list, you can access the following attribu - `coreos_enabled` - (Bool) If Red Hat CoreOS features are enabled within the Satellite location. - `crn` - (String) The CRN for this satellite location. - `created_on` - (Timestamp) The created time of the satellite location. +- `physical_address` - (String) The physical address of the Satellite location which is deployed on premise. +- `capabilities` - (Array of Strings) Satellite capabilities(in the Kubernetes Service API, the parameter 'capabilities' is called['capabilitiesManagedBySatellite'](https://cloud.ibm.com/apidocs/kubernetes/containers-v1-v2#createsatellitelocation)) attached to the Satellite location. - `description` - (String) Description of the new Satellite location. - `id` - (String) The unique identifier of the location. - `ingress_hostname` - (String) The Ingress hostname. diff --git a/website/docs/d/scc_control_libraries.html.markdown b/website/docs/d/scc_control_libraries.html.markdown index 4b63bc02e6..a4dc65773a 100644 --- a/website/docs/d/scc_control_libraries.html.markdown +++ b/website/docs/d/scc_control_libraries.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a list of scc_control_libraries from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_control_library.html.markdown b/website/docs/d/scc_control_library.html.markdown index fb1273466a..965b2ee848 100644 --- a/website/docs/d/scc_control_library.html.markdown +++ b/website/docs/d/scc_control_library.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a scc_control_library from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_instance_settings.html.markdown b/website/docs/d/scc_instance_settings.html.markdown index 3c69abbb59..a4c5673b9d 100644 --- a/website/docs/d/scc_instance_settings.html.markdown +++ b/website/docs/d/scc_instance_settings.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Provides a read-only data source to retrieve information about scc_instance_settings. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_latest_reports.html.markdown b/website/docs/d/scc_latest_reports.html.markdown index 2d62fb41f9..89e163b50a 100644 --- a/website/docs/d/scc_latest_reports.html.markdown +++ b/website/docs/d/scc_latest_reports.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about the latest reports from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_profile.html.markdown b/website/docs/d/scc_profile.html.markdown index 8938d79d1b..6a027165ce 100644 --- a/website/docs/d/scc_profile.html.markdown +++ b/website/docs/d/scc_profile.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a profile from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_profile_attachment.html.markdown b/website/docs/d/scc_profile_attachment.html.markdown index 15b0f39023..a050752c39 100644 --- a/website/docs/d/scc_profile_attachment.html.markdown +++ b/website/docs/d/scc_profile_attachment.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a profile attachment from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_profiles.html.markdown b/website/docs/d/scc_profiles.html.markdown index 1a40a83504..6bb501b060 100644 --- a/website/docs/d/scc_profiles.html.markdown +++ b/website/docs/d/scc_profiles.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a list of profiles from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_provider_type.html.markdown b/website/docs/d/scc_provider_type.html.markdown index 55b13ba210..2e80352b71 100644 --- a/website/docs/d/scc_provider_type.html.markdown +++ b/website/docs/d/scc_provider_type.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a provider type from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_provider_type_collection.html.markdown b/website/docs/d/scc_provider_type_collection.html.markdown index 96dece472f..aef7017fc2 100644 --- a/website/docs/d/scc_provider_type_collection.html.markdown +++ b/website/docs/d/scc_provider_type_collection.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a provider type collection from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_provider_type_instance.html.markdown b/website/docs/d/scc_provider_type_instance.html.markdown index 044c336c67..8ee37657cf 100644 --- a/website/docs/d/scc_provider_type_instance.html.markdown +++ b/website/docs/d/scc_provider_type_instance.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a provider type instance from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_provider_types.html.markdown b/website/docs/d/scc_provider_types.html.markdown index 2d97a4c8e1..fa1e3faa5b 100644 --- a/website/docs/d/scc_provider_types.html.markdown +++ b/website/docs/d/scc_provider_types.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a provider type from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_report.html.markdown b/website/docs/d/scc_report.html.markdown index 15aa7fedd9..ad19872854 100644 --- a/website/docs/d/scc_report.html.markdown +++ b/website/docs/d/scc_report.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a report from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_report_controls.html.markdown b/website/docs/d/scc_report_controls.html.markdown index 8bf2a1df6f..78dfba6005 100644 --- a/website/docs/d/scc_report_controls.html.markdown +++ b/website/docs/d/scc_report_controls.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about report controls from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_report_evaluations.html.markdown b/website/docs/d/scc_report_evaluations.html.markdown index 8050494e04..3260c74f56 100644 --- a/website/docs/d/scc_report_evaluations.html.markdown +++ b/website/docs/d/scc_report_evaluations.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about report evaluations from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_report_resources.html.markdown b/website/docs/d/scc_report_resources.html.markdown index 4cd1cc270b..e9258f50a9 100644 --- a/website/docs/d/scc_report_resources.html.markdown +++ b/website/docs/d/scc_report_resources.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about report resources from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_report_rule.html.markdown b/website/docs/d/scc_report_rule.html.markdown index aee94a5909..9056e60285 100644 --- a/website/docs/d/scc_report_rule.html.markdown +++ b/website/docs/d/scc_report_rule.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a report rule from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_report_summary.html.markdown b/website/docs/d/scc_report_summary.html.markdown index 1c2348268d..e6a444e1bd 100644 --- a/website/docs/d/scc_report_summary.html.markdown +++ b/website/docs/d/scc_report_summary.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a report summary from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_report_tags.html.markdown b/website/docs/d/scc_report_tags.html.markdown index 9c10d98e13..0eeed23c4c 100644 --- a/website/docs/d/scc_report_tags.html.markdown +++ b/website/docs/d/scc_report_tags.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about report tags from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_report_violation_drift.html.markdown b/website/docs/d/scc_report_violation_drift.html.markdown index 14e0d30466..e9cab490de 100644 --- a/website/docs/d/scc_report_violation_drift.html.markdown +++ b/website/docs/d/scc_report_violation_drift.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a report violation drift from a read-only data source. Then, yo can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/scc_rule.html.markdown b/website/docs/d/scc_rule.html.markdown index 5e697578fa..8c3517f646 100644 --- a/website/docs/d/scc_rule.html.markdown +++ b/website/docs/d/scc_rule.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Retrieve information about a rule from a read-only data source. Then, you can reference the fields of the data source in other resources within the same configuration by using interpolation syntax. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/d/sm_configurations.html.markdown b/website/docs/d/sm_configurations.html.markdown index 393bcdc54b..580c4da4a0 100644 --- a/website/docs/d/sm_configurations.html.markdown +++ b/website/docs/d/sm_configurations.html.markdown @@ -26,7 +26,11 @@ Review the argument reference that you can specify for your data source. * `instance_id` - (Required, Forces new resource, String) The GUID of the Secrets Manager instance. * `region` - (Optional, Forces new resource, String) The region of the Secrets Manager instance. If not provided defaults to the region defined in the IBM provider configuration. * `endpoint_type` - (Optional, String) - The endpoint type. If not provided the endpoint type is determined by the `visibility` argument provided in the provider configuration. - * Constraints: Allowable values are: `private`, `public`. + * Constraints: Allowable values are: `private`, `public`. +* `sort` - (Optional, String) - Sort a collection of configurations by the specified field in ascending order. To sort in descending order use the `-` character. + * Constraints: Allowable values are: `config_type`, `secret_type`, `name`. +* `search` - (Optional, String) - Obtain a collection of configurations that contain the specified string in one or more of the fields: `name`, `config_type`, `secret_type`. +* `secret_types` - (Optional, List) - Filter configurations by secret types: `iam_credentials`, `public_cert` or `private_cert`. You can apply multiple filters by using a comma-separated list of secret types. ## Attribute Reference @@ -36,32 +40,49 @@ In addition to all argument references listed, you can access the following attr * `configurations` - (List) A collection of configuration metadata. * Constraints: The maximum length is `1000` items. The minimum length is `0` items. Nested scheme for **configurations**: - * `config_type` - (String) Th configuration type. - * Constraints: Allowable values are: `public_cert_configuration_ca_lets_encrypt`, `public_cert_configuration_dns_classic_infrastructure`, `public_cert_configuration_dns_cloud_internet_services`, `iam_credentials_configuration`, `private_cert_configuration_root_ca`, `private_cert_configuration_intermediate_ca`, `private_cert_configuration_template`. - * `created_at` - (String) The date when a resource was created. The date format follows RFC 3339. - * `created_by` - (String) The unique identifier that is associated with the entity that created the secret. - * Constraints: The maximum length is `128` characters. The minimum length is `4` characters. - * `name` - (String) The unique name of your configuration. - * Constraints: The maximum length is `128` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. - * `secret_type` - (String) The secret type. Supported types are arbitrary, certificates (imported, public, and private), IAM credentials, key-value, and user credentials. - * Constraints: Allowable values are: `arbitrary`, `imported_cert`, `public_cert`, `iam_credentials`, `kv`, `username_password`, `private_cert`. - * `updated_at` - (String) The date when a resource was recently modified. The date format follows RFC 3339. - * `lets_encrypt_environment` - (String) The configuration of the Let's Encrypt CA environment. - * Constraints: Allowable values are: `production`, `staging`. - * `lets_encrypt_preferred_chain` - (String) Prefer the chain with an issuer matching this Subject Common Name. - * Constraints: The maximum length is `30` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. - * `common_name` - (String) The Common Name (AKA CN) represents the server name that is protected by the SSL certificate. - * Constraints: The maximum length is `128` characters. The minimum length is `4` characters. The value must match regular expression `/(.*?)/`. - * `crl_distribution_points_encoded` - (Boolean) Determines whether to encode the certificate revocation list (CRL) distribution points in the certificates that are issued by this certificate authority. - * `expiration_date` - (String) The date a secret is expired. The date format follows RFC 3339. - * `key_type` - (String) The type of private key to generate. - * Constraints: Allowable values are: `rsa`, `ec`. - * `key_bits` - (Integer) The number of bits to use to generate the private key.Allowable values for RSA keys are: `2048` and `4096`. Allowable values for EC keys are: `224`, `256`, `384`, and `521`. The default for RSA keys is `2048`. The default for EC keys is `256`. - * `status` - (String) The status of the certificate authority. The status of a root certificate authority is either `configured` or `expired`. For intermediate certificate authorities, possible statuses include `signing_required`,`signed_certificate_required`, `certificate_template_required`, `configured`, `expired` or `revoked`. - * Constraints: Allowable values are: `signing_required`, `signed_certificate_required`, `certificate_template_required`, `configured`, `expired`, `revoked`. - * `issuer` - (String) The distinguished name that identifies the entity that signed and issued the certificate. - * Constraints: The maximum length is `128` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. - * `signing_method` - (String) The signing method to use with this certificate authority to generate private certificates.You can choose between internal or externally signed options. For more information, see the [docs](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-intermediate-certificate-authorities). - * Constraints: Allowable values are: `internal`, `external`. - * `certificate_authority` - (String) The name of the intermediate certificate authority. - * Constraints: The maximum length is `128` characters. The minimum length is `2` characters. The value must match regular expression `/^[A-Za-z0-9][A-Za-z0-9]*(?:_?-?\\.?[A-Za-z0-9]+)*$/`. + * `config_type` - (String) Th configuration type. + * Constraints: Allowable values are: `public_cert_configuration_ca_lets_encrypt`, `public_cert_configuration_dns_classic_infrastructure`, `public_cert_configuration_dns_cloud_internet_services`, `iam_credentials_configuration`, `private_cert_configuration_root_ca`, `private_cert_configuration_intermediate_ca`, `private_cert_configuration_template`. + * `created_at` - (String) The date when a resource was created. The date format follows RFC 3339. + * `created_by` - (String) The unique identifier that is associated with the entity that created the secret. + * Constraints: The maximum length is `128` characters. The minimum length is `4` characters. + * `name` - (String) The unique name of your configuration. + * Constraints: The maximum length is `128` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. + * `secret_type` - (String) The secret type. Supported types are arbitrary, certificates (imported, public, and private), IAM credentials, key-value, and user credentials. + * Constraints: Allowable values are: `arbitrary`, `imported_cert`, `public_cert`, `iam_credentials`, `kv`, `username_password`, `private_cert`. + * `updated_at` - (String) The date when a resource was recently modified. The date format follows RFC 3339. + * `lets_encrypt_environment` - (String) The configuration of the Let's Encrypt CA environment. + * Constraints: Allowable values are: `production`, `staging`. + * `lets_encrypt_preferred_chain` - (String) Prefer the chain with an issuer matching this Subject Common Name. + * Constraints: The maximum length is `30` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. + * `common_name` - (String) The Common Name (AKA CN) represents the server name that is protected by the SSL certificate. + * Constraints: The maximum length is `128` characters. The minimum length is `4` characters. The value must match regular expression `/(.*?)/`. + * `crl_distribution_points_encoded` - (Boolean) Determines whether to encode the certificate revocation list (CRL) distribution points in the certificates that are issued by this certificate authority. + * `expiration_date` - (String) The date a secret is expired. The date format follows RFC 3339. + * `key_type` - (String) The type of private key to generate. + * Constraints: Allowable values are: `rsa`, `ec`. + * `key_bits` - (Integer) The number of bits to use to generate the private key.Allowable values for RSA keys are: `2048` and `4096`. Allowable values for EC keys are: `224`, `256`, `384`, and `521`. The default for RSA keys is `2048`. The default for EC keys is `256`. + * `status` - (String) The status of the certificate authority. The status of a root certificate authority is either `configured` or `expired`. For intermediate certificate authorities, possible statuses include `signing_required`,`signed_certificate_required`, `certificate_template_required`, `configured`, `expired` or `revoked`. + * Constraints: Allowable values are: `signing_required`, `signed_certificate_required`, `certificate_template_required`, `configured`, `expired`, `revoked`. + * `issuer` - (String) The distinguished name that identifies the entity that signed and issued the certificate. + * Constraints: The maximum length is `128` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. + * `signing_method` - (String) The signing method to use with this certificate authority to generate private certificates.You can choose between internal or externally signed options. For more information, see the [docs](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-intermediate-certificate-authorities). + * Constraints: Allowable values are: `internal`, `external`. + * `certificate_authority` - (String) The name of the intermediate certificate authority. + * Constraints: The maximum length is `128` characters. The minimum length is `2` characters. The value must match regular expression `/^[A-Za-z0-9][A-Za-z0-9]*(?:_?-?\\.?[A-Za-z0-9]+)*$/`. + * `crypto_key` - (List) The data that is associated with a cryptographic key. + Nested scheme for **crypto_key**: + * `provider` - (List) The data that is associated with a cryptographic provider. + Nested scheme for **provider**: + * `type` - (String) The type of cryptographic provider. + * Constraints: Allowable values are: `hyper_protect_crypto_services`. + * `instance_crn` - (String) The HPCS instance CRN. + * Constraints: The maximum length is `512` characters. The minimum length is `9` characters. The value must match regular expression `^crn:v[0-9](:([A-Za-z0-9-._~!$&'()*+,;=@/]|%[0-9A-Z]{2})*){8}$`. + * `pin_iam_credentials_secret_id` - (String) The secret Id of iam credentials with api key to access HPCS instance. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `private_keystore_id` - (String) The HPCS private key store space id. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `id` - (String) The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `label` - (String) The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified. + * Constraints: The maximum length is `255` characters. The minimum length is `1` characters. The value must match regular expression `/^[A-Za-z0-9._ /-]+$/`. + * `allow_generate_key` - (Boolean) The indication of whether a new key is generated by the crypto provider if the given key name cannot be found. Default is `false`. diff --git a/website/docs/d/sm_private_certificate_configuration_intermediate_ca.html.markdown b/website/docs/d/sm_private_certificate_configuration_intermediate_ca.html.markdown index 52e2b23047..e1cd41175d 100644 --- a/website/docs/d/sm_private_certificate_configuration_intermediate_ca.html.markdown +++ b/website/docs/d/sm_private_certificate_configuration_intermediate_ca.html.markdown @@ -138,3 +138,21 @@ Nested scheme for **data**: * `uri_sans` - (String) The URI Subject Alternative Names to define for the CA certificate, in a comma-delimited list. * Constraints: The maximum length is `2048` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. +* `crypto_key` - (List) The data that is associated with a cryptographic key. + Nested scheme for **crypto_key**: + * `provider` - (List) The data that is associated with a cryptographic provider. + Nested scheme for **provider**: + * `type` - (String) The type of cryptographic provider. + * Constraints: Allowable values are: `hyper_protect_crypto_services`. + * `instance_crn` - (String) The HPCS instance CRN. + * Constraints: The maximum length is `512` characters. The minimum length is `9` characters. The value must match regular expression `^crn:v[0-9](:([A-Za-z0-9-._~!$&'()*+,;=@/]|%[0-9A-Z]{2})*){8}$`. + * `pin_iam_credentials_secret_id` - (String) The secret Id of iam credentials with api key to access HPCS instance. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `private_keystore_id` - (String) The HPCS private key store space id. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `id` - (String) The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `label` - (String) The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified. + * Constraints: The maximum length is `255` characters. The minimum length is `1` characters. The value must match regular expression `/^[A-Za-z0-9._ /-]+$/`. + * `allow_generate_key` - (Boolean) The indication of whether a new key is generated by the crypto provider if the given key name cannot be found. Default is `false`. + diff --git a/website/docs/d/sm_private_certificate_configuration_root_ca.html.markdown b/website/docs/d/sm_private_certificate_configuration_root_ca.html.markdown index a444f52db7..2ed3f25867 100644 --- a/website/docs/d/sm_private_certificate_configuration_root_ca.html.markdown +++ b/website/docs/d/sm_private_certificate_configuration_root_ca.html.markdown @@ -140,3 +140,21 @@ Nested scheme for **data**: * `uri_sans` - (String) The URI Subject Alternative Names to define for the CA certificate, in a comma-delimited list. * Constraints: The maximum length is `2048` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. +* `crypto_key` - (List) The data that is associated with a cryptographic key. + Nested scheme for **crypto_key**: + * `provider` - (List) The data that is associated with a cryptographic provider. + Nested scheme for **provider**: + * `type` - (String) The type of cryptographic provider. + * Constraints: Allowable values are: `hyper_protect_crypto_services`. + * `instance_crn` - (String) The HPCS instance CRN. + * Constraints: The maximum length is `512` characters. The minimum length is `9` characters. The value must match regular expression `^crn:v[0-9](:([A-Za-z0-9-._~!$&'()*+,;=@/]|%[0-9A-Z]{2})*){8}$`. + * `pin_iam_credentials_secret_id` - (String) The secret Id of iam credentials with api key to access HPCS instance. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `private_keystore_id` - (String) The HPCS private key store space id. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `id` - (String) The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `label` - (String) The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified. + * Constraints: The maximum length is `255` characters. The minimum length is `1` characters. The value must match regular expression `/^[A-Za-z0-9._ /-]+$/`. + * `allow_generate_key` - (Boolean) The indication of whether a new key is generated by the crypto provider if the given key name cannot be found. Default is `false`. + diff --git a/website/docs/d/sm_secrets.html.markdown b/website/docs/d/sm_secrets.html.markdown index d36a0648ee..ed32aae298 100644 --- a/website/docs/d/sm_secrets.html.markdown +++ b/website/docs/d/sm_secrets.html.markdown @@ -31,7 +31,7 @@ Review the argument reference that you can specify for your data source. * Constraints: Allowable values are: `id`, `created_at`, `updated_at`, `expiration_date`, `secret_type`, `name`. * `search` - (Optional, String) - Obtain a collection of secrets that contain the specified string in one or more of the fields: `id`, `name`, `description`, `labels`, `secret_type`. * `groups` - (Optional, String) - Filter secrets by groups. You can apply multiple filters by using a comma-separated list of secret group IDs. If you need to filter secrets that are in the default secret group, use the `default` keyword. -* `secret_types` - (Optional, String) - Filter secrets by secret types. You can apply multiple filters by using a comma-separated list of secret types. +* `secret_types` - (Optional, List) - Filter secrets by secret types. You can apply multiple filters by using a comma-separated list of secret types. * `match_all_labels` - (Optional, String) - Filter secrets by a label or a combination of labels (comma-separated list). ## Attribute Reference diff --git a/website/docs/guides/custom-service-endpoints.html.md b/website/docs/guides/custom-service-endpoints.html.md index b03eedc00b..e582ae430b 100644 --- a/website/docs/guides/custom-service-endpoints.html.md +++ b/website/docs/guides/custom-service-endpoints.html.md @@ -83,6 +83,7 @@ provider "ibm" { |Transit Gateway|IBMCLOUD_TG_API_ENDPOINT| |UAA|IBMCLOUD_UAA_ENDPOINT| |User Management|IBMCLOUD_USER_MANAGEMENT_ENDPOINT| +|Event Notifications|IBMCLOUD_EVENT_NOTIFICATIONS_API_ENDPOINT| ## File structure for endpoints file @@ -134,6 +135,42 @@ To use public and private regional endpoints for a service, you must add these e } } ``` +**Note:** + +The endpoints file accepts "public", "private" and "public-and-private" as visibility while COS resources support "public", "private" and "direct as endpoint-types. +Since endpoints file schema does not supprt "direct", users must define the url for "direct" endpoint-type under exisiting visibility type "private" for "IBMCLOUD_COS_CONFIG_ENDPOINT" and "IBMCLOUD_COS_ENDPOINT". +The user cannot define urls for both private and direct endpoint-type simultaneously in the endpoints file under "private" field. + +**Example**: + +```json +{ + "IBMCLOUD_COS_CONFIG_ENDPOINT":{ + "public":{ + "us-south":"https://config.cloud-object-storage.cloud.ibm.com/v1" + }, + "private":{ + "us-south":"https://config.direct.cloud-object-storage.cloud.ibm.com/v1" + } + } +} +``` + +OR + +```json +{ + "IBMCLOUD_COS_CONFIG_ENDPOINT":{ + "public":{ + "us-south":"https://config.cloud-object-storage.cloud.ibm.com/v1" + }, + "private":{ + "us-south":"https://config.private.cloud-object-storage.cloud.ibm.com/v1" + } + } +} +``` + ## Prioritisation of endpoints diff --git a/website/docs/r/atracker_target.html.markdown b/website/docs/r/atracker_target.html.markdown index 13cbb61cd2..46bc5a398f 100644 --- a/website/docs/r/atracker_target.html.markdown +++ b/website/docs/r/atracker_target.html.markdown @@ -97,7 +97,7 @@ Nested scheme for **eventstreams_endpoint**: * `region` - (Optional, String) Include this optional field if you want to create a target in a different region other than the one you are connected. * Constraints: The maximum length is `1000` characters. The minimum length is `3` characters. The value must match regular expression `/^[a-zA-Z0-9 -._:]+$/`. * `target_type` - (Required, Forces new resource, String) The type of the target. It can be cloud_object_storage, logdna or event_streams. Based on this type you must include cos_endpoint, logdna_endpoint or eventstreams_endpoint. - * Constraints: Allowable values are: `cloud_object_storage`, `logdna`, `event_streams`. + * Constraints: Allowable values are: `cloud_object_storage`, `logdna`, `event_streams`, `cloud_logs`. ## Attribute reference diff --git a/website/docs/r/cbr_zone_addresses.html.markdown b/website/docs/r/cbr_zone_addresses.html.markdown new file mode 100644 index 0000000000..6fb8cd5254 --- /dev/null +++ b/website/docs/r/cbr_zone_addresses.html.markdown @@ -0,0 +1,119 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_cbr_zone_addresses" +description: |- + Manages cbr_zone_addresses. +subcategory: "Context Based Restrictions" +--- + +# ibm_cbr_zone_addresses + +Provides a resource for cbr_zone_addresses. This allows cbr_zone_addresses to be created, updated and deleted. +This resource allows the inclusion of one or more addresses in an existing zone without the need to modify the base cbr_zone resource. + +## Example Usage to create a zone addresses resource + +```hcl +resource "ibm_cbr_zone_addresses" "cbr_zone_addresses" { + zone_id = ibm_cbr_zone.cbr_zone.id + addresses { + type = "subnet" + value = "169.24.56.0/24" + } + addresses { + type = "ipRange" + value = "169.24.22.0-169.24.22.255" + } +} +``` + +## Argument Reference + +Review the argument reference that you can specify for your resource. + +* `zone_id` - (Required, String) The id of the zone in which to include the addresses. + * Constraints: The maximum length is `32` characters. The minimum length is `32` characters. The value must match regular expression `/^[a-fA-F0-9]{32}$/`. +* `addresses` - (Required, List) The list of addresses to include in the zone. + * Constraints: The maximum length is `1000` items. The minimum length is `1` items. +Nested scheme for **addresses**: + * `ref` - (Optional, List) A service reference value. + Nested scheme for **ref**: + * `account_id` - (Required, String) The id of the account owning the service. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9\-]+$/`. + * `location` - (Optional, String) The location. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9a-z\-]+$/`. + * `service_instance` - (Optional, String) The service instance. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9a-z\-\/]+$/`. + * `service_name` - (Optional, String) The service name. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9a-z\-]+$/`. + * `service_type` - (Optional, String) The service type. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9a-z_]+$/`. + * `type` - (Optional, String) The type of address. + * Constraints: Allowable values are: `ipAddress`, `ipRange`, `subnet`, `vpc`, `serviceRef`. + * `value` - (Optional, String) The IP address. + * Constraints: The maximum length is `45` characters. The minimum length is `2` characters. The value must match regular expression `/^[a-zA-Z0-9:.]+$/`. + +## Attribute Reference + +In addition to all argument references listed, you can access the following attribute references after your resource is created. + +* `id` - The unique identifier of the cbr_zone_addresses. + +## Provider Configuration + +The IBM Cloud provider offers a flexible means of providing credentials for authentication. The following methods are supported, in this order, and explained below: + +- Static credentials +- Environment variables + +To find which credentials are required for this resource, see the service table [here](https://cloud.ibm.com/docs/ibm-cloud-provider-for-terraform?topic=ibm-cloud-provider-for-terraform-provider-reference#required-parameters). + +### Static credentials + +You can provide your static credentials by adding the `ibmcloud_api_key`, `iaas_classic_username`, and `iaas_classic_api_key` arguments in the IBM Cloud provider block. + +Usage: +``` +provider "ibm" { + ibmcloud_api_key = "" + iaas_classic_username = "" + iaas_classic_api_key = "" +} +``` + +### Environment variables + +You can provide your credentials by exporting the `IC_API_KEY`, `IAAS_CLASSIC_USERNAME`, and `IAAS_CLASSIC_API_KEY` environment variables, representing your IBM Cloud platform API key, IBM Cloud Classic Infrastructure (SoftLayer) user name, and IBM Cloud infrastructure API key, respectively. + +``` +provider "ibm" {} +``` + +Usage: +``` +export IC_API_KEY="ibmcloud_api_key" +export IAAS_CLASSIC_USERNAME="iaas_classic_username" +export IAAS_CLASSIC_API_KEY="iaas_classic_api_key" +terraform plan +``` + +Note: + +1. Create or find your `ibmcloud_api_key` and `iaas_classic_api_key` [here](https://cloud.ibm.com/iam/apikeys). + - Select `My IBM Cloud API Keys` option from view dropdown for `ibmcloud_api_key` + - Select `Classic Infrastructure API Keys` option from view dropdown for `iaas_classic_api_key` +2. For iaas_classic_username + - Go to [Users](https://cloud.ibm.com/iam/users) + - Click on user. + - Find user name in the `VPN password` section under `User Details` tab + +For more informaton, see [here](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs#authentication). + +## Import + +You can import the `ibm_cbr_zone_addresses` resource by using `id`. The globally unique ID of the zone addresses. + +# Syntax +``` +$ terraform import ibm_cbr_zone_addresses.cbr_zone_addresses +``` diff --git a/website/docs/r/cd_tekton_pipeline.html.markdown b/website/docs/r/cd_tekton_pipeline.html.markdown index 11bcae1503..d4c7ec08c0 100644 --- a/website/docs/r/cd_tekton_pipeline.html.markdown +++ b/website/docs/r/cd_tekton_pipeline.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline -Create, update, and delete cd_tekton_pipelines with this resource. +Provides a resource for cd_tekton_pipeline. This allows cd_tekton_pipeline to be created, updated and deleted. ## Example Usage @@ -23,26 +23,24 @@ resource "ibm_cd_tekton_pipeline" "cd_tekton_pipeline_instance" { ## Argument Reference -You can specify the following arguments for this resource. +Review the argument reference that you can specify for your resource. * `pipeline_id` - (Required, String) ID of the pipeline tool in your toolchain. Can be referenced from your `ibm_cd_toolchain_tool_pipeline` resource, e.g. `pipeline_id = ibm_cd_toolchain_tool_pipeline.my_pipeline.tool_id` * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. -* `enable_notifications` - (Optional, Boolean) Flag whether to enable notifications for this pipeline. When enabled, pipeline run events will be published on all slack integration specified channels in the parent toolchain. If omitted, this feature is disabled by default. -* `enable_partial_cloning` - (Optional, Boolean) Flag whether to enable partial cloning for this pipeline. When partial clone is enabled, only the files contained within the paths specified in definition repositories are read and cloned, this means that symbolic links might not work. If omitted, this feature is disabled by default. -* `next_build_number` - (Optional, Integer) The build number that will be used for the next pipeline run. +* `enable_notifications` - (Optional, Boolean) Flag to enable notifications for this pipeline. If enabled, the Tekton pipeline run events will be published to all the destinations specified by the Slack and Event Notifications integrations in the parent toolchain. + * Constraints: The default value is `false`. +* `enable_partial_cloning` - (Optional, Boolean) Flag to enable partial cloning for this pipeline. When partial clone is enabled, only the files contained within the paths specified in definition repositories are read and cloned, this means that symbolic links might not work. + * Constraints: The default value is `false`. +* `next_build_number` - (Optional, Integer) Specify the build number that will be used for the next pipeline run. Build numbers can be any positive whole number between 0 and 100000000000000. * Constraints: The maximum value is `99999999999999`. The minimum value is `1`. -* `worker` - (Optional, List) Details of the worker used to run the pipeline. +* `worker` - (Optional, List) Specify the worker that is to be used to run the trigger, indicated by a worker object with only the worker ID. If not specified or set as `worker: { id: 'public' }`, the IBM Managed shared workers are used. Nested schema for **worker**: * `id` - (Required, String) ID of the worker. - * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z]{1,36}$/`. - * `name` - (Computed, String) Name of the worker. Computed based on the worker ID. - * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_. \\(\\)\\[\\]]{1,253}$/`. - * `type` - (Computed, String) Type of the worker. Computed based on the worker ID. - * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. + * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z]{1,253}$/`. ## Attribute Reference -After your resource is created, you can read values from the listed arguments and the following attributes. +In addition to all argument references listed, you can access the following attribute references after your resource is created. * `id` - The unique identifier of the cd_tekton_pipeline. * `build_number` - (Integer) The latest pipeline run build number. If this property is absent, the pipeline hasn't had any pipeline runs. @@ -73,7 +71,7 @@ Nested schema for **definitions**: * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. * `type` - (String) The only supported source type is "git", indicating that the source is a git repository. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^git$/`. -* `enabled` - (Boolean) Flag whether this pipeline is enabled. +* `enabled` - (Boolean) Flag to check if the trigger is enabled. * Constraints: The default value is `true`. * `href` - (String) API URL for interacting with the pipeline. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. @@ -86,6 +84,7 @@ Nested schema for **properties**: * Constraints: The list items must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. The maximum length is `256` items. The minimum length is `0` items. * `href` - (String) API URL for interacting with the property. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. + * `locked` - (Boolean) When true, this property cannot be overridden by a trigger property or at runtime. Attempting to override it will result in run requests being rejected. The default is false. * `name` - (Forces new resource, String) Property name. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. * `path` - (String) A dot notation path for `integration` type properties only, that selects a value from the tool integration. If left blank the full tool integration data will be used. @@ -111,16 +110,18 @@ Nested schema for **toolchain**: * `triggers` - (List) Tekton pipeline triggers list. * Constraints: The maximum length is `1024` items. The minimum length is `0` items. Nested schema for **triggers**: - * `cron` - (String) Only needed for timer triggers. Cron expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: 0 *_/2 * * * - every 2 hours. + * `cron` - (String) Only needed for timer triggers. CRON expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: The CRON expression 0 *_/2 * * * - translates to - every 2 hours. * Constraints: The maximum length is `253` characters. The minimum length is `5` characters. The value must match regular expression `/^[-0-9a-zA-Z,\\*\/ ]{5,253}$/`. - * `enabled` - (Boolean) Flag whether the trigger is enabled. + * `enabled` - (Boolean) Flag to check if the trigger is enabled. * Constraints: The default value is `true`. * `event_listener` - (String) Event listener name. The name of the event listener to which the trigger is associated. The event listeners are defined in the definition repositories of the Tekton pipeline. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `events` - (List) Only needed for Git triggers. List of events to which a Git trigger listens. Choose one or more from: 'push', 'pull_request' and 'pull_request_closed'. For SCM repositories that use 'merge request' events, such events map to the equivalent 'pull request' events. + * `events` - (List) Either 'events' or 'filter' is required specifically for Git triggers. Stores a list of events that a Git trigger listens to. Choose one or more from 'push', 'pull_request', and 'pull_request_closed'. If SCM repositories use the 'merge request' term, they correspond to the generic term i.e. 'pull request'. * Constraints: Allowable list items are: `push`, `pull_request`, `pull_request_closed`. The maximum length is `3` items. The minimum length is `0` items. * `favorite` - (Boolean) Mark the trigger as a favorite. * Constraints: The default value is `false`. + * `filter` - (String) Either 'events' or 'filter' can be used. Stores the CEL (Common Expression Language) expression value which is used for event filtering against the Git webhook payloads. + * Constraints: The maximum length is `4096` characters. The minimum length is `1` character. The value must match regular expression `/^.*$/`. * `href` - (String) API URL for interacting with the trigger. Only included when fetching the list of pipeline triggers. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. * `id` - (String) The Trigger ID. @@ -128,7 +129,7 @@ Nested schema for **triggers**: * `max_concurrent_runs` - (Integer) Defines the maximum number of concurrent runs for this trigger. If omitted then the concurrency limit is disabled for this trigger. * `name` - (String) Trigger name. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^([a-zA-Z0-9]{1,2}|[a-zA-Z0-9][0-9a-zA-Z-_.: \/\\(\\)\\[\\]]{1,251}[a-zA-Z0-9])$/`. - * `properties` - (List) Optional trigger properties used to override or supplement the pipeline properties when triggering a pipeline run. + * `properties` - (List) Optional trigger properties are used to override or supplement the pipeline properties when triggering a pipeline run. * Constraints: The maximum length is `1024` items. The minimum length is `0` items. Nested schema for **properties**: * `enum` - (List) Options for `single_select` property type. Only needed for `single_select` property type. @@ -144,7 +145,7 @@ Nested schema for **triggers**: * Constraints: Allowable values are: `secure`, `text`, `integration`, `single_select`, `appconfig`. * `value` - (String) Property value. Any string value is valid. * Constraints: The maximum length is `4096` characters. The minimum length is `0` characters. The value must match regular expression `/^.*$/`. - * `secret` - (List) Only needed for generic webhook trigger type. Secret used to start generic webhook trigger. + * `secret` - (List) Only needed for Generic Webhook trigger type. The secret is used to start the Generic Webhook trigger. Nested schema for **secret**: * `algorithm` - (String) Algorithm used for `digest_matches` secret type. Only needed for `digest_matches` secret type. * Constraints: Allowable values are: `md4`, `md5`, `sha1`, `sha256`, `sha384`, `sha512`, `sha512_224`, `sha512_256`, `ripemd160`. @@ -161,11 +162,11 @@ Nested schema for **triggers**: * `properties` - (List) Properties of the source, which define the URL of the repository and a branch or pattern. Nested schema for **properties**: * `blind_connection` - (Boolean) True if the repository server is not addressable on the public internet. IBM Cloud will not be able to validate the connection details you provide. - * `branch` - (String) Name of a branch from the repo. One of branch or pattern must be specified, but only one or the other. + * `branch` - (String) Name of a branch from the repo. Only one of branch, pattern, or filter should be specified. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `hook_id` - (String) ID of the webhook from the repo. Computed upon creation of the trigger. + * `hook_id` - (String) Repository webhook ID. It is generated upon trigger creation. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `pattern` - (String) The pattern of Git branch or tag to which to listen. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags/branches in the repository. The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. One of branch or pattern must be specified, but only one or the other. + * `pattern` - (String) The pattern of Git branch or tag. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags or branches in the repository.The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. Only one of branch, pattern, or filter should be specified. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.:@=$&^\/\\?\\!\\*\\+\\[\\]\\(\\)\\{\\}\\|\\\\]*$/`. * `tool` - (List) Reference to the repository tool in the parent toolchain. Nested schema for **tool**: @@ -177,7 +178,7 @@ Nested schema for **triggers**: * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^git$/`. * `tags` - (List) Optional trigger tags array. * Constraints: The list items must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. The maximum length is `128` items. The minimum length is `0` items. - * `timezone` - (String) Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the cron activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones. + * `timezone` - (String) Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the CRON activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z+_., \/]{1,253}$/`. * `type` - (String) Trigger type. * Constraints: Allowable values are: `manual`, `scm`, `timer`, `generic`. @@ -193,55 +194,6 @@ Nested schema for **triggers**: * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. * `updated_at` - (String) Standard RFC 3339 Date Time String. -## Provider Configuration - -The IBM Cloud provider offers a flexible means of providing credentials for authentication. The following methods are supported, in this order, and explained below: - -- Static credentials -- Environment variables - -To find which credentials are required for this resource, see the service table [here](https://cloud.ibm.com/docs/ibm-cloud-provider-for-terraform?topic=ibm-cloud-provider-for-terraform-provider-reference#required-parameters). - -### Static credentials - -You can provide your static credentials by adding the `ibmcloud_api_key`, `iaas_classic_username`, and `iaas_classic_api_key` arguments in the IBM Cloud provider block. - -Usage: -``` -provider "ibm" { - ibmcloud_api_key = "" - iaas_classic_username = "" - iaas_classic_api_key = "" -} -``` - -### Environment variables - -You can provide your credentials by exporting the `IC_API_KEY`, `IAAS_CLASSIC_USERNAME`, and `IAAS_CLASSIC_API_KEY` environment variables, representing your IBM Cloud platform API key, IBM Cloud Classic Infrastructure (SoftLayer) user name, and IBM Cloud infrastructure API key, respectively. - -``` -provider "ibm" {} -``` - -Usage: -``` -export IC_API_KEY="ibmcloud_api_key" -export IAAS_CLASSIC_USERNAME="iaas_classic_username" -export IAAS_CLASSIC_API_KEY="iaas_classic_api_key" -terraform plan -``` - -Note: - -1. Create or find your `ibmcloud_api_key` and `iaas_classic_api_key` [here](https://cloud.ibm.com/iam/apikeys). - - Select `My IBM Cloud API Keys` option from view dropdown for `ibmcloud_api_key` - - Select `Classic Infrastructure API Keys` option from view dropdown for `iaas_classic_api_key` -2. For iaas_classic_username - - Go to [Users](https://cloud.ibm.com/iam/users) - - Click on user. - - Find user name in the `VPN password` section under `User Details` tab - -For more informaton, see [here](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs#authentication). ## Import diff --git a/website/docs/r/cd_tekton_pipeline_definition.html.markdown b/website/docs/r/cd_tekton_pipeline_definition.html.markdown index 26c31c12a2..12d0be686d 100644 --- a/website/docs/r/cd_tekton_pipeline_definition.html.markdown +++ b/website/docs/r/cd_tekton_pipeline_definition.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline_definition -Create, update, and delete cd_tekton_pipeline_definitions with this resource. +Provides a resource for cd_tekton_pipeline_definition. This allows cd_tekton_pipeline_definition to be created, updated and deleted. ## Example Usage @@ -32,7 +32,7 @@ resource "ibm_cd_tekton_pipeline_definition" "cd_tekton_pipeline_definition_inst ## Argument Reference -You can specify the following arguments for this resource. +Review the argument reference that you can specify for your resource. * `pipeline_id` - (Required, Forces new resource, String) The Tekton pipeline ID. * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. @@ -57,7 +57,7 @@ Nested schema for **source**: ## Attribute Reference -After your resource is created, you can read values from the listed arguments and the following attributes. +In addition to all argument references listed, you can access the following attribute references after your resource is created. * `id` - The unique identifier of the cd_tekton_pipeline_definition. * `definition_id` - (String) The aggregated definition ID. @@ -65,64 +65,15 @@ After your resource is created, you can read values from the listed arguments an * `href` - (String) API URL for interacting with the definition. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. -## Provider Configuration - -The IBM Cloud provider offers a flexible means of providing credentials for authentication. The following methods are supported, in this order, and explained below: - -- Static credentials -- Environment variables - -To find which credentials are required for this resource, see the service table [here](https://cloud.ibm.com/docs/ibm-cloud-provider-for-terraform?topic=ibm-cloud-provider-for-terraform-provider-reference#required-parameters). - -### Static credentials - -You can provide your static credentials by adding the `ibmcloud_api_key`, `iaas_classic_username`, and `iaas_classic_api_key` arguments in the IBM Cloud provider block. - -Usage: -``` -provider "ibm" { - ibmcloud_api_key = "" - iaas_classic_username = "" - iaas_classic_api_key = "" -} -``` - -### Environment variables - -You can provide your credentials by exporting the `IC_API_KEY`, `IAAS_CLASSIC_USERNAME`, and `IAAS_CLASSIC_API_KEY` environment variables, representing your IBM Cloud platform API key, IBM Cloud Classic Infrastructure (SoftLayer) user name, and IBM Cloud infrastructure API key, respectively. - -``` -provider "ibm" {} -``` - -Usage: -``` -export IC_API_KEY="ibmcloud_api_key" -export IAAS_CLASSIC_USERNAME="iaas_classic_username" -export IAAS_CLASSIC_API_KEY="iaas_classic_api_key" -terraform plan -``` - -Note: - -1. Create or find your `ibmcloud_api_key` and `iaas_classic_api_key` [here](https://cloud.ibm.com/iam/apikeys). - - Select `My IBM Cloud API Keys` option from view dropdown for `ibmcloud_api_key` - - Select `Classic Infrastructure API Keys` option from view dropdown for `iaas_classic_api_key` -2. For iaas_classic_username - - Go to [Users](https://cloud.ibm.com/iam/users) - - Click on user. - - Find user name in the `VPN password` section under `User Details` tab - -For more informaton, see [here](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs#authentication). ## Import You can import the `ibm_cd_tekton_pipeline_definition` resource by using `id`. The `id` property can be formed from `pipeline_id`, and `definition_id` in the following format: -``` -/ -``` +
+<pipeline_id>/<definition_id>
+
* `pipeline_id`: A string in the format `94619026-912b-4d92-8f51-6c74f0692d90`. The Tekton pipeline ID. * `definition_id`: A string in the format `94299034-d45f-4e9a-8ed5-6bd5c7bb7ada`. The definition ID. diff --git a/website/docs/r/cd_tekton_pipeline_property.html.markdown b/website/docs/r/cd_tekton_pipeline_property.html.markdown index 129d14c545..fbc85ec9d0 100644 --- a/website/docs/r/cd_tekton_pipeline_property.html.markdown +++ b/website/docs/r/cd_tekton_pipeline_property.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline_property -Create, update, and delete cd_tekton_pipeline_propertys with this resource. +Provides a resource for cd_tekton_pipeline_property. This allows cd_tekton_pipeline_property to be created, updated and deleted. ## Example Usage @@ -23,14 +23,15 @@ resource "ibm_cd_tekton_pipeline_property" "cd_tekton_pipeline_property_instance ## Argument Reference -You can specify the following arguments for this resource. +Review the argument reference that you can specify for your resource. * `enum` - (Optional, List) Options for `single_select` property type. Only needed when using `single_select` property type. * Constraints: The list items must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. The maximum length is `256` items. The minimum length is `0` items. * `locked` - (Optional, Boolean) When true, this property cannot be overridden by a trigger property or at runtime. Attempting to override it will result in run requests being rejected. The default is false. + * Constraints: The default value is `false`. * `name` - (Required, Forces new resource, String) Property name. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. -* `path` - (Optional, String) A dot notation path for `integration` type properties only, that selects a value from the tool integration. If left blank the full tool integration data will be used. +* `path` - (Optional, String) A dot notation path for `integration` type properties only, to select a value from the tool integration. If left blank the full tool integration data will be used. * Constraints: The maximum length is `4096` characters. The minimum length is `0` characters. The value must match regular expression `/^[-0-9a-zA-Z_.]*$/`. * `pipeline_id` - (Required, Forces new resource, String) The Tekton pipeline ID. * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. @@ -41,70 +42,21 @@ You can specify the following arguments for this resource. ## Attribute Reference -After your resource is created, you can read values from the listed arguments and the following attributes. +In addition to all argument references listed, you can access the following attribute references after your resource is created. * `id` - The unique identifier of the cd_tekton_pipeline_property. * `href` - (String) API URL for interacting with the property. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. -## Provider Configuration - -The IBM Cloud provider offers a flexible means of providing credentials for authentication. The following methods are supported, in this order, and explained below: - -- Static credentials -- Environment variables - -To find which credentials are required for this resource, see the service table [here](https://cloud.ibm.com/docs/ibm-cloud-provider-for-terraform?topic=ibm-cloud-provider-for-terraform-provider-reference#required-parameters). - -### Static credentials - -You can provide your static credentials by adding the `ibmcloud_api_key`, `iaas_classic_username`, and `iaas_classic_api_key` arguments in the IBM Cloud provider block. - -Usage: -``` -provider "ibm" { - ibmcloud_api_key = "" - iaas_classic_username = "" - iaas_classic_api_key = "" -} -``` - -### Environment variables - -You can provide your credentials by exporting the `IC_API_KEY`, `IAAS_CLASSIC_USERNAME`, and `IAAS_CLASSIC_API_KEY` environment variables, representing your IBM Cloud platform API key, IBM Cloud Classic Infrastructure (SoftLayer) user name, and IBM Cloud infrastructure API key, respectively. - -``` -provider "ibm" {} -``` - -Usage: -``` -export IC_API_KEY="ibmcloud_api_key" -export IAAS_CLASSIC_USERNAME="iaas_classic_username" -export IAAS_CLASSIC_API_KEY="iaas_classic_api_key" -terraform plan -``` - -Note: - -1. Create or find your `ibmcloud_api_key` and `iaas_classic_api_key` [here](https://cloud.ibm.com/iam/apikeys). - - Select `My IBM Cloud API Keys` option from view dropdown for `ibmcloud_api_key` - - Select `Classic Infrastructure API Keys` option from view dropdown for `iaas_classic_api_key` -2. For iaas_classic_username - - Go to [Users](https://cloud.ibm.com/iam/users) - - Click on user. - - Find user name in the `VPN password` section under `User Details` tab - -For more informaton, see [here](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs#authentication). ## Import You can import the `ibm_cd_tekton_pipeline_property` resource by using `name`. The `name` property can be formed from `pipeline_id`, and `property_name` in the following format: -``` -/ -``` +
+<pipeline_id>/<property_name>
+
* `pipeline_id`: A string in the format `94619026-912b-4d92-8f51-6c74f0692d90`. The Tekton pipeline ID. * `property_name`: A string in the format `debug-pipeline`. The property name. diff --git a/website/docs/r/cd_tekton_pipeline_trigger.html.markdown b/website/docs/r/cd_tekton_pipeline_trigger.html.markdown index b76499e23d..0ac708932a 100644 --- a/website/docs/r/cd_tekton_pipeline_trigger.html.markdown +++ b/website/docs/r/cd_tekton_pipeline_trigger.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline_trigger -Create, update, and delete cd_tekton_pipeline_triggers with this resource. +Provides a resource for cd_tekton_pipeline_trigger. This allows cd_tekton_pipeline_trigger to be created, updated and deleted. ## Example Usage @@ -27,24 +27,26 @@ resource "ibm_cd_tekton_pipeline_trigger" "cd_tekton_pipeline_trigger_instance" ## Argument Reference -You can specify the following arguments for this resource. +Review the argument reference that you can specify for your resource. -* `cron` - (Optional, String) Only needed for timer triggers. Cron expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: 0 *_/2 * * * - every 2 hours. +* `cron` - (Optional, String) Only needed for timer triggers. CRON expression that indicates when this trigger will activate. Maximum frequency is every 5 minutes. The string is based on UNIX crontab syntax: minute, hour, day of month, month, day of week. Example: The CRON expression 0 *_/2 * * * - translates to - every 2 hours. * Constraints: The maximum length is `253` characters. The minimum length is `5` characters. The value must match regular expression `/^[-0-9a-zA-Z,\\*\/ ]{5,253}$/`. -* `enabled` - (Optional, Boolean) Flag whether the trigger is enabled. +* `enabled` - (Optional, Boolean) Flag to check if the trigger is enabled. If omitted the trigger is enabled by default. * Constraints: The default value is `true`. * `event_listener` - (Required, String) Event listener name. The name of the event listener to which the trigger is associated. The event listeners are defined in the definition repositories of the Tekton pipeline. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. -* `events` - (Optional, List) Only needed for Git triggers. List of events to which a Git trigger listens. Choose one or more from: 'push', 'pull_request' and 'pull_request_closed'. For SCM repositories that use 'merge request' events, such events map to the equivalent 'pull request' events. +* `events` - (Optional, List) Either 'events' or 'filter' is required specifically for Git triggers. Stores a list of events that a Git trigger listens to. Choose one or more from 'push', 'pull_request', and 'pull_request_closed'. If SCM repositories use the 'merge request' term, they correspond to the generic term i.e. 'pull request'. * Constraints: Allowable list items are: `push`, `pull_request`, `pull_request_closed`. The maximum length is `3` items. The minimum length is `0` items. * `favorite` - (Optional, Boolean) Mark the trigger as a favorite. * Constraints: The default value is `false`. +* `filter` - (Optional, String) Either 'events' or 'filter' can be used. Stores the CEL (Common Expression Language) expression value which is used for event filtering against the Git webhook payloads. + * Constraints: The maximum length is `4096` characters. The minimum length is `1` character. The value must match regular expression `/^.*$/`. * `max_concurrent_runs` - (Optional, Integer) Defines the maximum number of concurrent runs for this trigger. If omitted then the concurrency limit is disabled for this trigger. * `name` - (Required, String) Trigger name. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^([a-zA-Z0-9]{1,2}|[a-zA-Z0-9][0-9a-zA-Z-_.: \/\\(\\)\\[\\]]{1,251}[a-zA-Z0-9])$/`. * `pipeline_id` - (Required, Forces new resource, String) The Tekton pipeline ID. * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. -* `secret` - (Optional, List) Only needed for generic webhook trigger type. Secret used to start generic webhook trigger. +* `secret` - (Optional, List) Only needed for Generic Webhook trigger type. The secret is used to start the Generic Webhook trigger. Nested schema for **secret**: * `algorithm` - (Optional, String) Algorithm used for `digest_matches` secret type. Only needed for `digest_matches` secret type. * Constraints: Allowable values are: `md4`, `md5`, `sha1`, `sha256`, `sha384`, `sha512`, `sha512_224`, `sha512_256`, `ripemd160`. @@ -60,44 +62,33 @@ Nested schema for **secret**: Nested schema for **source**: * `properties` - (Required, List) Properties of the source, which define the URL of the repository and a branch or pattern. Nested schema for **properties**: - * `blind_connection` - (Computed, Boolean) True if the repository server is not addressable on the public internet. IBM Cloud will not be able to validate the connection details you provide. - * `branch` - (Optional, String) Name of a branch from the repo. One of branch or pattern must be specified, but only one or the other. + * `branch` - (Optional, String) Name of a branch from the repo. Only one of branch, pattern, or filter should be specified. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `hook_id` - (Computed, String) ID of the webhook from the repo. Computed upon creation of the trigger. - * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. - * `pattern` - (Optional, String) The pattern of Git branch or tag to which to listen. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags/branches in the repository. The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. One of branch or pattern must be specified, but only one or the other. + * `pattern` - (Optional, String) The pattern of Git branch or tag. You can specify a glob pattern such as '!test' or '*master' to match against multiple tags or branches in the repository.The glob pattern used must conform to Bash 4.3 specifications, see bash documentation for more info: https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching. Only one of branch, pattern, or filter should be specified. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.:@=$&^\/\\?\\!\\*\\+\\[\\]\\(\\)\\{\\}\\|\\\\]*$/`. - * `tool` - (Required, List) Reference to the repository tool in the parent toolchain. - Nested schema for **tool**: - * `id` - (Computed, String) ID of the repository tool instance in the parent toolchain. - * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. * `url` - (Required, Forces new resource, String) URL of the repository to which the trigger is listening. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. * `type` - (Required, String) The only supported source type is "git", indicating that the source is a git repository. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^git$/`. -* `tags` - (Optional, List) Optional trigger tags array. +* `tags` - (Optional, List) Trigger tags array. * Constraints: The list items must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. The maximum length is `128` items. The minimum length is `0` items. -* `timezone` - (Optional, String) Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the cron activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones. +* `timezone` - (Optional, String) Only used for timer triggers. Specify the timezone used for this timer trigger, which will ensure the CRON activates this trigger relative to the specified timezone. If no timezone is specified, the default timezone used is UTC. Valid timezones are those listed in the IANA timezone database, https://www.iana.org/time-zones. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z+_., \/]{1,253}$/`. * `type` - (Required, String) Trigger type. - * Constraints: Allowable values are: . -* `worker` - (Optional, List) Details of the worker used to run the trigger. + * Constraints: Allowable values are: `manual`, `scm`, `timer`, `generic`. +* `worker` - (Optional, List) Specify the worker used to run the trigger. Use `worker: { id: 'public' }` to use the IBM Managed workers. The default is to inherit the worker set in the pipeline settings, which can also be explicitly set using `worker: { id: 'inherit' }`. Nested schema for **worker**: * `id` - (Required, String) ID of the worker. - * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z]{1,36}$/`. - * `name` - (Computed, String) Name of the worker. Computed based on the worker ID. - * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_. \\(\\)\\[\\]]{1,253}$/`. - * `type` - (Computed, String) Type of the worker. Computed based on the worker ID. - * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. + * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z]{1,253}$/`. ## Attribute Reference -After your resource is created, you can read values from the listed arguments and the following attributes. +In addition to all argument references listed, you can access the following attribute references after your resource is created. * `id` - The unique identifier of the cd_tekton_pipeline_trigger. * `href` - (String) API URL for interacting with the trigger. Only included when fetching the list of pipeline triggers. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. -* `properties` - (List) Optional trigger properties used to override or supplement the pipeline properties when triggering a pipeline run. +* `properties` - (List) Optional trigger properties are used to override or supplement the pipeline properties when triggering a pipeline run. * Constraints: The maximum length is `1024` items. The minimum length is `0` items. Nested schema for **properties**: * `enum` - (List) Options for `single_select` property type. Only needed for `single_select` property type. @@ -118,64 +109,15 @@ Nested schema for **properties**: * `webhook_url` - (String) Webhook URL that can be used to trigger pipeline runs. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. -## Provider Configuration - -The IBM Cloud provider offers a flexible means of providing credentials for authentication. The following methods are supported, in this order, and explained below: - -- Static credentials -- Environment variables - -To find which credentials are required for this resource, see the service table [here](https://cloud.ibm.com/docs/ibm-cloud-provider-for-terraform?topic=ibm-cloud-provider-for-terraform-provider-reference#required-parameters). - -### Static credentials - -You can provide your static credentials by adding the `ibmcloud_api_key`, `iaas_classic_username`, and `iaas_classic_api_key` arguments in the IBM Cloud provider block. - -Usage: -``` -provider "ibm" { - ibmcloud_api_key = "" - iaas_classic_username = "" - iaas_classic_api_key = "" -} -``` - -### Environment variables - -You can provide your credentials by exporting the `IC_API_KEY`, `IAAS_CLASSIC_USERNAME`, and `IAAS_CLASSIC_API_KEY` environment variables, representing your IBM Cloud platform API key, IBM Cloud Classic Infrastructure (SoftLayer) user name, and IBM Cloud infrastructure API key, respectively. - -``` -provider "ibm" {} -``` - -Usage: -``` -export IC_API_KEY="ibmcloud_api_key" -export IAAS_CLASSIC_USERNAME="iaas_classic_username" -export IAAS_CLASSIC_API_KEY="iaas_classic_api_key" -terraform plan -``` - -Note: - -1. Create or find your `ibmcloud_api_key` and `iaas_classic_api_key` [here](https://cloud.ibm.com/iam/apikeys). - - Select `My IBM Cloud API Keys` option from view dropdown for `ibmcloud_api_key` - - Select `Classic Infrastructure API Keys` option from view dropdown for `iaas_classic_api_key` -2. For iaas_classic_username - - Go to [Users](https://cloud.ibm.com/iam/users) - - Click on user. - - Find user name in the `VPN password` section under `User Details` tab - -For more informaton, see [here](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs#authentication). ## Import You can import the `ibm_cd_tekton_pipeline_trigger` resource by using `id`. The `id` property can be formed from `pipeline_id`, and `trigger_id` in the following format: -``` -/ -``` +
+<pipeline_id>/<trigger_id>
+
* `pipeline_id`: A string in the format `94619026-912b-4d92-8f51-6c74f0692d90`. The Tekton pipeline ID. * `trigger_id`: A string in the format `1bb892a1-2e04-4768-a369-b1159eace147`. The trigger ID. diff --git a/website/docs/r/cd_tekton_pipeline_trigger_property.html.markdown b/website/docs/r/cd_tekton_pipeline_trigger_property.html.markdown index efe2d54c08..0947a3d79b 100644 --- a/website/docs/r/cd_tekton_pipeline_trigger_property.html.markdown +++ b/website/docs/r/cd_tekton_pipeline_trigger_property.html.markdown @@ -8,7 +8,7 @@ subcategory: "Continuous Delivery" # ibm_cd_tekton_pipeline_trigger_property -Create, update, and delete cd_tekton_pipeline_trigger_propertys with this resource. +Provides a resource for cd_tekton_pipeline_trigger_property. This allows cd_tekton_pipeline_trigger_property to be created, updated and deleted. ## Example Usage @@ -24,14 +24,15 @@ resource "ibm_cd_tekton_pipeline_trigger_property" "cd_tekton_pipeline_trigger_p ## Argument Reference -You can specify the following arguments for this resource. +Review the argument reference that you can specify for your resource. * `enum` - (Optional, List) Options for `single_select` property type. Only needed for `single_select` property type. * Constraints: The list items must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. The maximum length is `256` items. The minimum length is `0` items. * `locked` - (Optional, Boolean) When true, this property cannot be overridden at runtime. Attempting to override it will result in run requests being rejected. The default is false. + * Constraints: The default value is `false`. * `name` - (Required, Forces new resource, String) Property name. * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^[-0-9a-zA-Z_.]{1,253}$/`. -* `path` - (Optional, String) A dot notation path for `integration` type properties only, that selects a value from the tool integration. If left blank the full tool integration data will be used. +* `path` - (Optional, String) A dot notation path for `integration` type properties only, to select a value from the tool integration. If left blank the full tool integration data will be used. * Constraints: The maximum length is `4096` characters. The minimum length is `0` characters. The value must match regular expression `/^[-0-9a-zA-Z_.]*$/`. * `pipeline_id` - (Required, Forces new resource, String) The Tekton pipeline ID. * Constraints: The maximum length is `36` characters. The minimum length is `36` characters. The value must match regular expression `/^[-0-9a-z]+$/`. @@ -44,70 +45,21 @@ You can specify the following arguments for this resource. ## Attribute Reference -After your resource is created, you can read values from the listed arguments and the following attributes. +In addition to all argument references listed, you can access the following attribute references after your resource is created. * `id` - The unique identifier of the cd_tekton_pipeline_trigger_property. * `href` - (String) API URL for interacting with the trigger property. * Constraints: The maximum length is `2048` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. -## Provider Configuration - -The IBM Cloud provider offers a flexible means of providing credentials for authentication. The following methods are supported, in this order, and explained below: - -- Static credentials -- Environment variables - -To find which credentials are required for this resource, see the service table [here](https://cloud.ibm.com/docs/ibm-cloud-provider-for-terraform?topic=ibm-cloud-provider-for-terraform-provider-reference#required-parameters). - -### Static credentials - -You can provide your static credentials by adding the `ibmcloud_api_key`, `iaas_classic_username`, and `iaas_classic_api_key` arguments in the IBM Cloud provider block. - -Usage: -``` -provider "ibm" { - ibmcloud_api_key = "" - iaas_classic_username = "" - iaas_classic_api_key = "" -} -``` - -### Environment variables - -You can provide your credentials by exporting the `IC_API_KEY`, `IAAS_CLASSIC_USERNAME`, and `IAAS_CLASSIC_API_KEY` environment variables, representing your IBM Cloud platform API key, IBM Cloud Classic Infrastructure (SoftLayer) user name, and IBM Cloud infrastructure API key, respectively. - -``` -provider "ibm" {} -``` - -Usage: -``` -export IC_API_KEY="ibmcloud_api_key" -export IAAS_CLASSIC_USERNAME="iaas_classic_username" -export IAAS_CLASSIC_API_KEY="iaas_classic_api_key" -terraform plan -``` - -Note: - -1. Create or find your `ibmcloud_api_key` and `iaas_classic_api_key` [here](https://cloud.ibm.com/iam/apikeys). - - Select `My IBM Cloud API Keys` option from view dropdown for `ibmcloud_api_key` - - Select `Classic Infrastructure API Keys` option from view dropdown for `iaas_classic_api_key` -2. For iaas_classic_username - - Go to [Users](https://cloud.ibm.com/iam/users) - - Click on user. - - Find user name in the `VPN password` section under `User Details` tab - -For more informaton, see [here](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs#authentication). ## Import You can import the `ibm_cd_tekton_pipeline_trigger_property` resource by using `name`. The `name` property can be formed from `pipeline_id`, `trigger_id`, and `property_name` in the following format: -``` -// -``` +
+<pipeline_id>/<trigger_id>/<property_name>
+
* `pipeline_id`: A string in the format `94619026-912b-4d92-8f51-6c74f0692d90`. The Tekton pipeline ID. * `trigger_id`: A string in the format `1bb892a1-2e04-4768-a369-b1159eace147`. The trigger ID. * `property_name`: A string in the format `debug-pipeline`. The property name. diff --git a/website/docs/r/cis_advanced_certificate_pack_order.html.markdown b/website/docs/r/cis_advanced_certificate_pack_order.html.markdown new file mode 100644 index 0000000000..c3b81ff779 --- /dev/null +++ b/website/docs/r/cis_advanced_certificate_pack_order.html.markdown @@ -0,0 +1,46 @@ +--- + +subcategory: "Internet services" +layout: "ibm" +page_title: "IBM: ibm_cis_advanced_certificate_pack_order" +description: |- + Provides an IBM CIS certificate order resource. +--- + +# ibm_cis_advanced_certificate_pack_order + + Provides an IBM Cloud Internet Services advanced certificate order resource. This resource is associated with an IBM Cloud Internet Services instance and a CIS domain resource. It allows you to order and delete dedicated advanced certificates of a domain of a CIS instance. For more information about CIS certificate ordering, see [managing edge certificates](https://cloud.ibm.com/docs/cis?topic=cis-managing-edge-certs). + +## Example usage + +```terraform +resource "ibm_cis_advanced_certificate_pack_order" "test" { + cis_id = data.ibm_cis.cis.id + domain_id = data.ibm_cis_domain.cis_domain.domain_id + hosts = ["example.com"] + certificate_authority = "lets_encrypt" + cloudflare_branding = false + validation_method = "txt" + validity = 90 +} +``` + +## Argument reference + +Review the argument references that you can specify for your resource. + +- `cis_id` - (Required, String) The ID of the IBM Cloud Internet Services instance. +- `domain_id` - (Required, String) The ID of the domain. +- `hosts` - (Required, String) The hosts for the certificates to be ordered. +- `certificate_authority` - (Required, String) The certificate authority selected for the order. Allowed values are `google` and `lets_encrypt` +- `cloudflare_branding` - (Optional, Boolean) Whether to add Cloudflare branding for the order. +- `validation_method` - (Required, String) Validation methond selected for the order. Allowed values are `txt`, `http`, and `email`. +- `validity`- (Required, Int) Validty days for the order. Allowed values are `14`, `30`, `90`, `365`. + +## Attribute reference + +In addition to the argument reference list, you can access the following attribute reference after your resource is created. + +- `certificate_id`- (String) The certificate ID. +- `id` - (String) The record ID, which is a combination of `,,` attributes concatenated with `:`. +- `status`- (String) The certificate status. diff --git a/website/docs/r/cis_domain_settings.html.markdown b/website/docs/r/cis_domain_settings.html.markdown index 49521658fe..92cf6ad650 100644 --- a/website/docs/r/cis_domain_settings.html.markdown +++ b/website/docs/r/cis_domain_settings.html.markdown @@ -13,6 +13,7 @@ Customize the IBM Cloud Internet Services domain settings. For more information, ## Example usage 1 --- + ```terraform resource "ibm_cis_domain_settings" "test_domain_settings" { cis_id = data.ibm_cis.cis.id @@ -45,6 +46,8 @@ resource "ibm_cis_domain_settings" "test_domain_settings" { challenge_ttl = 31536000 max_upload = 300 cipher = ["AES128-SHA256"] + origin_max_http_version = "1" + origin_post_quantum_encryption = "off" minify { css = "off" js = "off" @@ -70,13 +73,17 @@ resource "ibm_cis_domain_settings" "test" { waf = "on" ssl = "full" min_tls_version = "1.2" + origin_max_http_version = "2" + origin_post_quantum_encryption = "supported" } ``` + --- ## Example usage 2 : For TLS v1.3 --- + ```terraform resource "ibm_cis_domain_settings" "test_domain_settings" { cis_id = data.ibm_cis.cis.id @@ -109,6 +116,8 @@ resource "ibm_cis_domain_settings" "test_domain_settings" { challenge_ttl = 31536000 max_upload = 300 cipher = [] + origin_max_http_version = "1" + origin_post_quantum_encryption = "off" minify { css = "off" js = "off" @@ -134,19 +143,23 @@ resource "ibm_cis_domain_settings" "test" { waf = "on" ssl = "full" min_tls_version = "1.3" + origin_max_http_version = "2" + origin_post_quantum_encryption = "supported" } ``` + --- ## Argument reference -Review the argument references that you can specify for your resource. + +Review the argument references that you can specify for your resource. - `always_use_https` - (Optional, String) Supported values are `off` and `on`. - `automatic_https_rewrites` - (Optional, String) Enable HTTPS rewrites. Allowed values are `off` and `on`. - `browser_check` - (Optional, String) Enable a client browser check to look for common HTTP headers that are used by malicious users. If HTTP headers are found, access to your website is blocked. Supported values are `off` and `on`. - `brotli` - (Optional, String) Supported values are `off` and `on`. - `challenge_ttl` - (Optional, String) Challenge TTL values are `300`, `900`, `1800`, `2700`, `3600`, `7200`, `10800`, `14400`, `28800`, `57600`, `86400`, `604800`, `2592000`, and `31536000`. -- `cipher` - (Optional, List) Cipher setting values are `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-CHACHA20-POLY1305`,`ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-CHACHA20-POLY1305`, `ECDHE-ECDSA-AES128-SHA256`, `ECDHE-ECDSA-AES128-SHA`, `ECDHE-RSA-AES128-SHA256`, `ECDHE-RSA-AES128-SHA`, `AES128-GCM-SHA256`, `AES128-SHA256`, `AES128-SHA`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-AES256-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-SHA384`, `ECDHE-RSA-AES256-SHA`, `AES256-GCM-SHA384`, `AES256-SHA256`, `AES256-SHA`, `DES-CBC3-SHA`. To use default cipher value, pass empty list `[]`. +- `cipher` - (Optional, List) Cipher setting values are `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-CHACHA20-POLY1305`,`ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-CHACHA20-POLY1305`, `ECDHE-ECDSA-AES128-SHA256`, `ECDHE-ECDSA-AES128-SHA`, `ECDHE-RSA-AES128-SHA256`, `ECDHE-RSA-AES128-SHA`, `AES128-GCM-SHA256`, `AES128-SHA256`, `AES128-SHA`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-AES256-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-SHA384`, `ECDHE-RSA-AES256-SHA`, `AES256-GCM-SHA384`, `AES256-SHA256`, `AES256-SHA`, `DES-CBC3-SHA`. To use default cipher value, pass empty list `[]`. - `cis_id` - (Required, String) The ID of the IBM Cloud Internet Services instance. - `cname_flattening` - (Optional, String) Supported values are `flatten_at_root`, `flatten_all`, and `flatten_none`. - `domain_id` - (Required, String) The ID of the domain that you want to customize. @@ -189,12 +202,15 @@ Review the argument references that you can specify for your resource. - `true_client_ip_header` - (Optional, String) Supported values are `off` and `on`. - `waf` - (Optional, String) Enable a web application firewall (WAF). Supported values are `off` and `on`. - `websockets` - (Optional, String) Supported values are `off` and `on`. +- `origin_max_http_version` - (Optional, String) Sets the highest HTTP version to use with origin. Supported values are `1` and `2`. +- `origin_post_quantum_encryption` - (Optional, String) Wheather to use post-quantum key agreement algorithms when connecting to the origin. Supported values are `off`, `preferred` and `supported`. -**Note** +### Note Extra settings are not implemented in this version of the provider. - + ## Attribute reference -In addition to all argument reference list, you can access the following attribute reference after your resource is created. + +In addition to the argument reference list, you can access the following attribute reference after your resource is created. - `certificate_status` - (String) The value is displayed as `none`, `initializing`, `authorizing`, or `active`. diff --git a/website/docs/r/cis_origin_certificate_order.html.markdown b/website/docs/r/cis_origin_certificate_order.html.markdown new file mode 100644 index 0000000000..83dcdd5b99 --- /dev/null +++ b/website/docs/r/cis_origin_certificate_order.html.markdown @@ -0,0 +1,69 @@ +--- + +subcategory: "Internet services" +layout: "ibm" +page_title: "IBM: ibm_cis_origin_certificate_order" +description: |- + Provides an IBM CIS origin certificate order resource. +--- + +# ibm_cis_origin_certificate_order + +Provides an IBM Cloud Internet Services origin certificate order resource. This resource is associated with an IBM Cloud Internet Services instance and a CIS domain resource. It allows you to order and delete dedicated advanced certificates of a domain of a CIS instance. For more information about CIS certificate orderering, see [managing origin certificates](https://cloud.ibm.com/docs/cis?topic=cis-cis-origin-certificates). + +## Example usage + +```terraform + +resource "ibm_cis_origin_certificate_order" "test" { + cis_id = data.ibm_cis.cis.id + domain_id = data.ibm_cis_domain.cis_domain.domain_id + hostnames = ["example.com"] + request_type = "origin-rsa" + requested_validity = 5475 + csr = "-----BEGIN CERTIFICATE REQUEST-----\nMIICxzCC***TA67sdbcQ==\n-----END CERTIFICATE REQUEST-----" +} + +``` + +## Argument reference + +Review the argument references that you can specify for your resource. + +- `cis_id` - (Required, String) The ID of the IBM Cloud Internet Services instance. +- `domain_id` - (Required, String) The ID of the domain. +- `hosts` - (Required, String) The hosts for the certificates to be ordered. +- `request_type` - (Required, String) The type of the certificate. Allowed values are `origin-rsa`, `origin-ecc` and `keyless-certificate`. +- `requested_validity`- (Required, Int) Validty days for the order. Allowed values are `7`, `30`, `90`, `365`, `730`, `1095`, `5475`. +- `csr` - (Required, String) The Certificate Signing Request. + +## Attribute reference + +In addition to the argument reference list, you can access the following attribute reference after your resource is created. + +- `certificate_id`- (String) The certificate ID. +- `id` - (String) The record ID, which is a combination of `,,` attributes concatenated with `:`. + +## Import + +The `ibm_cis_origin_certificate_order` resource can be imported using the ID. The ID is formed from the certificate ID, the domain ID of the domain and the CRN concatenated by using a `:` character. + +The domain ID and CRN is located on the **Overview** page of the IBM Cloud Internet Services instance of the console domain heading, or by using the `ibmcloud cis` command line commands. + +- **Domain ID** is a 32-digit character string of the form: `9caf68812ae9b3f0377fdf986751a78f` + +- **CRN** is a 120-digit character string of the form: `crn:v1:bluemix:public:internet-svcs:global:a/4ea1882a2d3401ed1e459979941966ea:31fa970d-51d0-4b05-893e-251cba75a7b3::` + +- **Certificate ID** is a 48-digit character string of the form: `484582976896327736468082847548136290560450732393`. + +### Syntax + +```terraform +terraform import ibm_cis_origin_certificate_order.test :: +``` + +### Example + +```terraform +terraform import ibm_cis_origin_certificate_order.test certificate_order 484582976896327736468082847548136290560450732393:9caf68812ae9b3f0377fdf986751a78f:crn:v1:bluemix:public:internet-svcs:global:a/4ea1882a2d3401ed1e459979941966ea:31fa970d-51d0-4b05-893e-251cba75a7b3:: +``` diff --git a/website/docs/r/code_engine_job.html.markdown b/website/docs/r/code_engine_job.html.markdown index 8c168fe3cc..a25e8bceac 100644 --- a/website/docs/r/code_engine_job.html.markdown +++ b/website/docs/r/code_engine_job.html.markdown @@ -81,7 +81,7 @@ Nested schema for **run_volume_mounts**: * `type` - (Required, String) Specify the type of the volume mount. Allowed types are: 'config_map', 'secret'. * Constraints: The default value is `secret`. Allowable values are: `config_map`, `secret`. The value must match regular expression `/^(config_map|secret)$/`. * `scale_array_spec` - (Optional, String) Define a custom set of array indices as a comma-separated list containing single values and hyphen-separated ranges, such as 5,12-14,23,27. Each instance gets its array index value from the environment variable JOB_INDEX. The number of unique array indices that you specify with this parameter determines the number of job instances to run. - * Constraints: The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^(?:[1-9]\\d\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d|[1-9]\\d\\d\\d|[1-9]\\d\\d|[1-9]?\\d)(?:-(?:[1-9]\\d\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d|[1-9]\\d\\d\\d|[1-9]\\d\\d|[1-9]?\\d))?(?:,(?:[1-9]\\d\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d|[1-9]\\d\\d\\d|[1-9]\\d\\d|[1-9]?\\d)(?:-(?:[1-9]\\d\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d|[1-9]\\d\\d\\d|[1-9]\\d\\d|[1-9]?\\d))?)*$/`. + * Constraints: The default value is `0`. The maximum length is `253` characters. The minimum length is `1` character. The value must match regular expression `/^(?:[1-9]\\d\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d|[1-9]\\d\\d\\d|[1-9]\\d\\d|[1-9]?\\d)(?:-(?:[1-9]\\d\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d|[1-9]\\d\\d\\d|[1-9]\\d\\d|[1-9]?\\d))?(?:,(?:[1-9]\\d\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d|[1-9]\\d\\d\\d|[1-9]\\d\\d|[1-9]?\\d)(?:-(?:[1-9]\\d\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d\\d|[1-9]\\d\\d\\d\\d|[1-9]\\d\\d\\d|[1-9]\\d\\d|[1-9]?\\d))?)*$/`. * `scale_cpu_limit` - (Optional, String) Optional amount of CPU set for the instance of the job. For valid values see [Supported memory and CPU combinations](https://cloud.ibm.com/docs/codeengine?topic=codeengine-mem-cpu-combo). * Constraints: The default value is `1`. The maximum length is `10` characters. The minimum length is `0` characters. The value must match regular expression `/^([0-9.]+)([eEinumkKMGTPB]*)$/`. * `scale_ephemeral_storage_limit` - (Optional, String) Optional amount of ephemeral storage to set for the instance of the job. The amount specified as ephemeral storage, must not exceed the amount of `scale_memory_limit`. The units for specifying ephemeral storage are Megabyte (M) or Gigabyte (G), whereas G and M are the shorthand expressions for GB and MB. For more information see [Units of measurement](https://cloud.ibm.com/docs/codeengine?topic=codeengine-mem-cpu-combo#unit-measurements). diff --git a/website/docs/r/container_vpc_worker_pool.html.markdown b/website/docs/r/container_vpc_worker_pool.html.markdown index 693e4611a6..206e4994ea 100644 --- a/website/docs/r/container_vpc_worker_pool.html.markdown +++ b/website/docs/r/container_vpc_worker_pool.html.markdown @@ -104,6 +104,7 @@ Review the argument references that you can specify for your resource. - `crk` - Root Key ID for boot volume encryption. - `kms_instance_id` - Instance ID for boot volume encryption. - `kms_account_id` - Account ID for boot volume encryption, if other account is providing the kms. +- `import_on_create` - (Optional, Bool) Import an existing WorkerPool from the cluster, instead of creating a new. - `security_groups` - (Optional, List) Enables users to define specific security groups for their workers. ## Attribute reference diff --git a/website/docs/r/cos_bucket.html.markdown b/website/docs/r/cos_bucket.html.markdown index 21485c5806..812d8e93c8 100644 --- a/website/docs/r/cos_bucket.html.markdown +++ b/website/docs/r/cos_bucket.html.markdown @@ -12,6 +12,12 @@ Create or delete an IBM Cloud Object Storage bucket. The bucket is used to store To create a bucket, you must provision an IBM Cloud Object Storage instance first by using the [`ibm_resource_instance`](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/resource_instance) resource. + + **Note:** + +A bucket name can be reused as soon as 15 minutes after the contents of the bucket have been deleted and the bucket has been deleted. Then, the objects and bucket are irrevocably deleted and can not be restored. +For more information, please refer to [this link](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-faq-bucket#faq-reuse-name) + ## Example usage The following example creates an instance of IBM Cloud Object Storage, IBM Cloud Activity Tracker, and IBM Cloud Monitoring. Then, multiple buckets are created and configured to send audit events and metrics to your service instances. @@ -625,4 +631,38 @@ id = `$CRN:meta:$buckettype:$bucketlocation` $ terraform import ibm_cos_bucket.cos_bucket crn:v1:staging:public:cloud-object-storage:satloc_dal_c8fctn320qtrspbisg80:a/81ee25188545f05150650a0a4ee015bb:a2deec95-0836-4720-bfc7-ca41c28a8c66:bucket:tf-listbuckettest:meta:sl:c8fctn320qtrspbisg80:public +``` + +**Note:** + +Since the current endpoints file schema does not support "direct", the user must define direct url under "private" for "IBMCLOUD_COS_CONFIG_ENDPOINT" and "IBMCLOUD_COS_ENDPOINT". + +**Example**: + +```json +{ + "IBMCLOUD_COS_CONFIG_ENDPOINT":{ + "public":{ + "us-south":"https://config.cloud-object-storage.cloud.ibm.com/v1" + }, + "private":{ + "us-south":"https://config.direct.cloud-object-storage.cloud.ibm.com/v1" + } + } +} +``` + +OR + +```json +{ + "IBMCLOUD_COS_CONFIG_ENDPOINT":{ + "public":{ + "us-south":"https://config.cloud-object-storage.cloud.ibm.com/v1" + }, + "private":{ + "us-south":"https://config.private.cloud-object-storage.cloud.ibm.com/v1" + } + } +} ``` \ No newline at end of file diff --git a/website/docs/r/database.html.markdown b/website/docs/r/database.html.markdown index faba677bd2..2b151f7d55 100644 --- a/website/docs/r/database.html.markdown +++ b/website/docs/r/database.html.markdown @@ -220,56 +220,7 @@ resource "ibm_database" "autoscale" { } } ``` -### Sample Cassandra database instance -* Cassandra provisioning may require more time than the default timeout. A longer timeout value can be set with using the `timeouts` attribute. -```terraform -data "ibm_resource_group" "test_acc" { - is_default = true -} - -resource "ibm_database" "cassandra" { - resource_group_id = data.ibm_resource_group.test_acc.id - name = "test" - service = "databases-for-cassandra" - plan = "enterprise" - location = "us-south" - adminpassword = "password12345678" - - group { - group_id = "member" - - memory { - allocation_mb = 24576 - } - - disk { - allocation_mb = 368640 - } - - cpu { - allocation_count = 6 - } - } - - users { - name = "user123" - password = "password12345678" - type = "database" - } - - allowlist { - address = "172.168.1.2/32" - description = "desc1" - } - - timeouts { - create = "120m" - update = "120m" - delete = "15m" - } -} -``` ### Sample MongoDB Enterprise database instance * MongoDB Enterprise provisioning may require more time than the default timeout. A longer timeout value can be set with using the `timeouts` attribute. * Please make sure your resources meet minimum requirements of scaling. Please refer [docs](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-pricing#scaling-per-member) for more info. @@ -695,7 +646,7 @@ Review the argument reference that you can specify for your resource. - `location` - (Required, String) The location where you want to deploy your instance. The location must match the `region` parameter that you specify in the `provider` block of your Terraform configuration file. The default value is `us-south`. Currently, supported regions are `us-south`, `us-east`, `eu-gb`, `eu-de`, `au-syd`, `jp-tok`, `oslo01`. - `group` - (Optional, Set) A set of group scaling values for the database. Multiple blocks are allowed. Can only be performed on is_adjustable=true groups. Values set are per-member. Values must be greater than or equal to the minimum size and must be a multiple of the step size. - Nested scheme for `group`: - - `group_id` - (Optional, String) The ID of the scaling group. Scaling group ID allowed values: `member`, `analytics`, `bi_connector` or `search`. Read more about `analytics` and `bi_connector` [here](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-mongodbee-analytics). Read more about `search` [here](https://cloud.ibm.com/docs/databases-for-cassandra?topic=databases-for-cassandra-dse-search) + - `group_id` - (Optional, String) The ID of the scaling group. Scaling group ID allowed values: `member`, `analytics`, or `bi_connector`. Read more about `analytics` and `bi_connector` [here](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-mongodbee-analytics). - `members` (Set, Optional) @@ -726,12 +677,12 @@ Review the argument reference that you can specify for your resource. - `name` - (Required, String) A descriptive name that is used to identify the database instance. The name must not include spaces. - `offline_restore` - (Optional, Boolean) Enable or disable the Offline Restore option while performing a Point-in-time Recovery for MongoDB EE in a disaster recovery scenario when the source region is unavailable, see [Point-in-time Recovery](https://cloud.ibm.com/docs/databases-for-mongodb?topic=databases-for-mongodb-pitr&interface=api#pitr-offline-restore) -- `plan` - (Required, Forces new resource, String) The name of the service plan that you choose for your instance. All databases use `standard`. `enterprise` is supported only for elasticsearch (`databases-for-elasticsearch`), cassandra (`databases-for-cassandra`), and mongodb(`databases-for-mongodb`). `platinum` is supported for elasticsearch (`databases-for-elasticsearch`). +- `plan` - (Required, Forces new resource, String) The name of the service plan that you choose for your instance. All databases use `standard`. `enterprise` is supported only for elasticsearch (`databases-for-elasticsearch`), and mongodb(`databases-for-mongodb`). `platinum` is supported for elasticsearch (`databases-for-elasticsearch`). - `point_in_time_recovery_deployment_id` - (Optional, String) The ID of the source deployment that you want to recover back to. - `point_in_time_recovery_time` - (Optional, String) The timestamp in UTC format that you want to restore to. To retrieve the timestamp, run the `ibmcloud cdb postgresql earliest-pitr-timestamp ` command. To restore to the latest available time, use a blank string `""` as the timestamp. For more information, see [Point-in-time Recovery](https://cloud.ibm.com/docs/databases-for-postgresql?topic=databases-for-postgresql-pitr). - `remote_leader_id` - (Optional, String) A CRN of the leader database to make the replica(read-only) deployment. The leader database is created by a database deployment with the same service ID. A read-only replica is set up to replicate all of your data from the leader deployment to the replica deployment by using asynchronous replication. For more information, see [Configuring Read-only Replicas](https://cloud.ibm.com/docs/databases-for-postgresql?topic=databases-for-postgresql-read-only-replicas). - `resource_group_id` - (Optional, Forces new resource, String) The ID of the resource group where you want to create the instance. To retrieve this value, run `ibmcloud resource groups` or use the `ibm_resource_group` data source. If no value is provided, the `default` resource group is used. -- `service` - (Required, Forces new resource, String) The type of Cloud Databases that you want to create. Only the following services are currently accepted: `databases-for-etcd`, `databases-for-postgresql`, `databases-for-redis`, `databases-for-elasticsearch`, `messages-for-rabbitmq`,`databases-for-mongodb`,`databases-for-mysql`, `databases-for-cassandra` and `databases-for-enterprisedb`. +- `service` - (Required, Forces new resource, String) The type of Cloud Databases that you want to create. Only the following services are currently accepted: `databases-for-etcd`, `databases-for-postgresql`, `databases-for-redis`, `databases-for-elasticsearch`, `messages-for-rabbitmq`,`databases-for-mongodb`,`databases-for-mysql`, and `databases-for-enterprisedb`. - `service_endpoints` - (Optional, String) Specify whether you want to enable the public, private, or both service endpoints. Supported values are `public`, `private`, or `public-and-private`. If you leave `service_endpoints` empty, the default value will be set based on the compliance standard in the region where the instance is being created. Generally, if the region is enabled with FS Cloud/ENS High compliance, then the default would be `private`. Otherwise, the default would be `public`. During any update, if you leave `service_endpoints` empty, it will maintain the previously selected value. - `tags` (Optional, Array of Strings) A list of tags that you want to add to your instance. - `version` - (Optional, Forces new resource, String) The version of the database to be provisioned. If omitted, the database is created with the most recent major and minor version. diff --git a/website/docs/r/en_integration_cos.html.markdown b/website/docs/r/en_integration_cos.html.markdown index 39943a2276..db2ed4f0d7 100644 --- a/website/docs/r/en_integration_cos.html.markdown +++ b/website/docs/r/en_integration_cos.html.markdown @@ -13,7 +13,7 @@ Manage COS integration using IBM Cloud™ Event Notifications. ## Example usage ```terraform -resource "ibm_en_integration" "en_cos_integration" { +resource "ibm_en_integration_cos" "en_cos_integration" { instance_guid = ibm_resource_instance.en_terraform_test_resource.guid type = "collect_failed_events" metadata { diff --git a/website/docs/r/en_smtp_setting.html.markdown b/website/docs/r/en_smtp_setting.html.markdown index 4f953e691c..1d7f607a65 100644 --- a/website/docs/r/en_smtp_setting.html.markdown +++ b/website/docs/r/en_smtp_setting.html.markdown @@ -22,6 +22,8 @@ resource "ibm_en_smtp_setting" "en_smtp_setting" { } ``` +Note: The support for legacy allowlisting has been deprecated. The support has been enabled via Context-based-restrictions. For detailed information, please refer here: https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-smtp-configurations#en-smtp-configurations-cbr. You can get the existing IP's details using data source `ibm_en_smtp_allowed_ips` + ## Argument reference Review the argument reference that you can specify for your resource. diff --git a/website/docs/r/en_subscription_slack.html.markdown b/website/docs/r/en_subscription_slack.html.markdown index 16fd4fbb0c..87bd032dca 100644 --- a/website/docs/r/en_subscription_slack.html.markdown +++ b/website/docs/r/en_subscription_slack.html.markdown @@ -21,6 +21,7 @@ resource "ibm_en_subscription_slack" "slack_subscription" { topic_id = ibm_en_topic.topic1.topic_id attributes { "attachment_color" = "#FF0000" + template_id_notification = "e40843c8-hgft-4717-8ee4-f923f2786a34" } } ``` @@ -39,14 +40,13 @@ Review the argument reference that you can specify for your resource. - `topic_id` - (Required, String) Topic ID. -- `template_id_notification` - (Optional, String) The templete id for notification. - - `attributes` - (Optional, List) Subscription attributes. Nested scheme for **attributes**: - `attachment_color` - (Optional, String) The color code for slack attachment. + - `template_id_notification` - (Optional, String) The templete id for notification. ## Attribute reference In addition to all argument references listed, you can access the following attribute references after your resource is created. diff --git a/website/docs/r/is_bare_metal_server.markdown b/website/docs/r/is_bare_metal_server.markdown index ffc4db8f4e..0d5ae468d1 100644 --- a/website/docs/r/is_bare_metal_server.markdown +++ b/website/docs/r/is_bare_metal_server.markdown @@ -7,7 +7,7 @@ description: |- Manages IBM bare metal sever. --- -# ibm\_is_bare_metal_server +# ibm_is_bare_metal_server Create, update, or delete a Bare Metal Server for VPC. For more information, about managing VPC Bare Metal Server, see [About Bare Metal Servers for VPC](https://cloud.ibm.com/docs/vpc?topic=vpc-about-bare-metal-servers). @@ -98,6 +98,27 @@ resource "ibm_is_bare_metal_server" "bms" { ``` +### Create bare metal server with bandwidth +```terraform +resource "ibm_is_bare_metal_server" "bms" { + bandwidth = 25000 + profile = "bx3-metal-48x256" + name = "example-bms" + image = "r134-31c8ca90-2623-48d7-8cf7-737be6fc4c3e" + zone = "us-south-3" + keys = [ibm_is_ssh_key.example.id] + primary_network_attachment { + name = "test-vni-100-102" + virtual_network_interface { + id = ibm_is_virtual_network_interface.testacc_vni.id + } + allowed_vlans = [100, 102] + } + vpc = ibm_is_vpc.example.id +} + +``` + ## Timeouts ibm_is_bare-metal_server provides the following [Timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) configuration options: @@ -117,14 +138,23 @@ Review the argument references that you can specify for your resource. **•** For more information, about creating access tags, see [working with tags](https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#create-access-console).
**•** You must have the access listed in the [Granting users access to tag resources](https://cloud.ibm.com/docs/account?topic=account-access) for `access_tags`
**•** `access_tags` must be in the format `key:value`. +- `bandwidth` - (Integer) The total bandwidth (in megabits per second) shared across the bare metal server's network interfaces. The specified value must match one of the bandwidth values in the bare metal server's profile. - `delete_type` - (Optional, String) Type of deletion on destroy. **soft** signals running operating system to quiesce and shutdown cleanly, **hard** immediately stop the server. By default its `hard`. - `enable_secure_boot` - (Optional, Boolean) Indicates whether secure boot is enabled. If enabled, the image must support secure boot or the server will fail to boot. Updating `enable_secure_boot` requires the server to be stopped and then it would be started. -- `image` - (Required, String) ID of the image. -- `keys` - (Required, List) Comma separated IDs of ssh keys. +- `image` - (Required, String) ID of the image. ( On update of `image`, server will be [reinitialized](https://cloud.ibm.com/apidocs/vpc/latest#replace-bare-metal-server-initialization) if server is in stopped state, else server will be stopped and restarted during update ) + + -> **NOTE:** + To reinitialize a bare metal server, the server status must be stopped, or have failed a previous reinitialization. For more information, see [Managing Bare Metal Servers for VPC](https://cloud.ibm.com/docs/vpc?topic=vpc-managing-bare-metal-servers&interface=api#reinitialize-bare-metal-servers-api). + +- `keys` - (Required, List) Comma separated IDs of ssh keys. ( On update of `keys`, server will be [reinitialized](https://cloud.ibm.com/apidocs/vpc/latest#replace-bare-metal-server-initialization) if server is in stopped state, else server will be stopped and restarted during update ) ~> **Note:** **•** `ed25519` can only be used if the operating system supports this key type.
**•** `ed25519` can't be used with Windows or VMware images.
+ + -> **NOTE:** + To reinitialize a bare metal server, the server status must be stopped, or have failed a previous reinitialization. For more information, see [Managing Bare Metal Servers for VPC](https://cloud.ibm.com/docs/vpc?topic=vpc-managing-bare-metal-servers&interface=api#reinitialize-bare-metal-servers-api). + - `name` - (Optional, String) The bare metal server name. -> **NOTE:** @@ -265,7 +295,11 @@ Review the argument references that you can specify for your resource. - `mode` - (Optional, String) The trusted platform module mode to use. The specified value must be listed in the bare metal server profile's supported_trusted_platform_module_modes. Updating trusted_platform_module mode would require the server to be stopped then started again. - Constraints: Allowable values are: `disabled`, `tpm_2`. -- `user_data` - (Optional, String) User data to transfer to the server bare metal server. +- `user_data` - (Optional, String) User data to transfer to the server bare metal server. (On update of `user_data`, server will be [reinitialized](https://cloud.ibm.com/apidocs/vpc/latest#replace-bare-metal-server-initialization) if server is in stopped state, else server will be stopped and restarted during update ) + + -> **NOTE:** + To reinitialize a bare metal server, the server status must be stopped, or have failed a previous reinitialization. For more information, see [Managing Bare Metal Servers for VPC](https://cloud.ibm.com/docs/vpc?topic=vpc-managing-bare-metal-servers&interface=api#reinitialize-bare-metal-servers-api). + - `vpc` - (Required, Forces new resource, String) The VPC ID of the bare metal server is to be a part of. It must match the VPC tied to the subnets of the server's network interfaces. - `zone` - (Required, Forces new resource, String) Name of the zone in which this bare metal server will reside in. @@ -306,6 +340,8 @@ In addition to all argument reference list, you can access the following attribu - `vlan` - (Integer) Indicates the 802.1Q VLAN ID tag that must be used for all traffic on this interface. [ conflicts with `allowed_vlans`] - `resource_type` - (String) The type of resource. +- `firmware_update_type_available` - (String) The firmware update type available for the bare metal server. + -> **Supported firmware update types**
• none
• optional
• required - `status` - (String) The status of the bare metal server. -> **Supported Status** • failed
• pending
• restarting
• running
• starting
• stopped
• stopping diff --git a/website/docs/r/is_bare_metal_server_initialization.markdown b/website/docs/r/is_bare_metal_server_initialization.markdown new file mode 100644 index 0000000000..79872fa138 --- /dev/null +++ b/website/docs/r/is_bare_metal_server_initialization.markdown @@ -0,0 +1,56 @@ +--- + +subcategory: "VPC infrastructure" +layout: "ibm" +page_title: "IBM : bare_metal_server_initialization" +description: |- + Replaces the IBM bare metal sever initialization. +--- + +# ibm\_is_bare_metal_server_initialization + +Reinitialize a Bare Metal Server with the existing image, keys and user data. This is a one time action resource, which would reinitialize/reload/replace the OS, keys, user_data on the bare metal server with image and keys (with/without user_data). [Read more about Bare Metal Servers reinitialization](https://cloud.ibm.com/apidocs/vpc/latest#replace-bare-metal-server-initialization). For multiple reload, multiple `ibm_is_bare_metal_server_initialization` resource need to be used. For more information, about managing VPC Bare Metal Server, see [About Bare Metal Servers for VPC](https://cloud.ibm.com/docs/vpc?topic=vpc-about-bare-metal-servers). + +**Note:** +VPC infrastructure services are a regional specific based endpoint, by default targets to `us-south`. Please make sure to target right region in the provider block as shown in the `provider.tf` file, if VPC service is created in region other than `us-south`. + +**provider.tf** + +```terraform +provider "ibm" { + region = "eu-gb" +} +``` + +## Example Usage + +In the following example, you can update name of a Bare Metal Server disk: + +```terraform +resource "ibm_is_bare_metal_server_initialization" "initialization" { + bare_metal_server = ibm_is_bare_metal_server.bms.id + image = var.image_id + keys = [ var.keys ] + user_data = var.userdata +} +## to avoid changes on the ibm_is_bare_metal_server resource, use lifecycle meta argument ignore_changes +resource "ibm_is_bare_metal_server" "bms" { + .... + lifecycle{ + ignore_changes = [ image, keys, user_data ] + } +} +``` + +## Argument Reference + +Review the argument references that you can specify for your resource. + + +- `bare_metal_server` - (Required, String) Bare metal server identifier. +- `image` - (Required, String) Image id to use to reinitialize the bare metal server. +- `keys` - (Required, Array) Keys ids to use to reinitialize the bare metal server. +- `user_data` - (Optional, String) User data to transfer to the server bare metal server. If unspecified, no user data will be made available. (For reload/reinitialize provide the same user data as at the time of provisioning) + + +To reinitialize a bare metal server, the server status must be stopped, or have failed a previous reinitialization. For more information, see Managing Bare Metal Servers for VPC. diff --git a/website/docs/r/is_instance.html.markdown b/website/docs/r/is_instance.html.markdown index 26a7785f66..4293929715 100644 --- a/website/docs/r/is_instance.html.markdown +++ b/website/docs/r/is_instance.html.markdown @@ -567,8 +567,11 @@ Review the argument references that you can specify for your resource. ~> **Note:** `image` conflicts with `boot_volume.0.snapshot` and `catalog_offering`, not required when creating instance using `instance_template` or `catalog_offering` -- `keys` - (Required, List) A comma-separated list of SSH keys that you want to add to your instance. +- `keys` - (Optional, List) A comma-separated list of SSH keys that you want to add to your instance. The public SSH keys for the administrative user of the virtual server instance. Keys will be made available to the virtual server instance as cloud-init vendor data. For cloud-init enabled images, these keys will also be added as SSH authorized keys for the administrative user. + ~> **Note:** + For Windows images, the keys of type rsa must be specified, and one will be selected to encrypt the administrator password. Keys are optional for other images, but if no keys are specified, the instance will be inaccessible unless the specified image provides another means of access. + ~> **Note:** **•** `ed25519` can only be used if the operating system supports this key type.
**•** `ed25519` can't be used with Windows or VMware images.
diff --git a/website/docs/r/is_lb_listener_policy.html.markdown b/website/docs/r/is_lb_listener_policy.html.markdown index 2d10caed99..bee5d92306 100644 --- a/website/docs/r/is_lb_listener_policy.html.markdown +++ b/website/docs/r/is_lb_listener_policy.html.markdown @@ -49,6 +49,33 @@ resource "ibm_is_lb_listener_policy" "example" { } ``` +### Sample to create a load balancer listener policy for a `redirect` action with parameterized url. + +```terraform +resource "ibm_is_lb" "example" { + name = "example-lb" + subnets = [ibm_is_subnet.example.id] +} + +resource "ibm_is_lb_listener" "example" { + lb = ibm_is_lb.example.id + port = "9086" + protocol = "http" +} + +resource "ibm_is_lb_listener_policy" "example" { + lb = ibm_is_lb.example.id + listener = ibm_is_lb_listener.example.listener_id + action = "redirect" + priority = 4 + name = "example-listener-policy" + target { + http_status_code = 302 + url = "https://{host}:8080/{port}/{host}/{path}" + } +} +``` + ### Sample to create a load balancer listener policy for a `https_redirect` action. ```terraform @@ -177,7 +204,14 @@ Review the argument references that you can specify for your resource. - `href` - (Optional, String) The listener's canonical URL. - `id` - (Optional, String) The unique identifier for this load balancer listener. - `name` - (Computed, String) The name for this load balancer pool. The name is unique across all pools for the load balancer. - - `url` - (Optional, String) The redirect target URL. + - `url` - (Optional, String) The redirect target URL. The URL supports [RFC 6570 level 1 expressions](https://datatracker.ietf.org/doc/html/rfc6570#section-1.2) for the following variables which expand to values from the originally requested URL (or the indicated defaults if the request did not include them): + + **•** protocol
+ **•** host
+ **•** port (default: 80 for HTTP requests, 443 for HTTPS requests)
+ **•** path (default: '/')
+ **•** query (default: '')
+ ~> **Note:** When action is `forward`, `target.id` should specify which pool the load balancer forwards the traffic to. When action is `redirect`, `target.url` should specify the `url` and `target.http_status_code` to specify the code used in the redirect response. diff --git a/website/docs/r/is_share.html.markdown b/website/docs/r/is_share.html.markdown index e268513403..2092145308 100644 --- a/website/docs/r/is_share.html.markdown +++ b/website/docs/r/is_share.html.markdown @@ -97,11 +97,37 @@ resource "ibm_is_share" "example-4" { replication_cron_spec = "0 */5 * * *" } ``` + +## Example share (Create accessor share for an origin share) +```terraform +resource "ibm_is_share" "example-4" { + allowed_transit_encryption_modes = ["user_managed", "none"] + access_control_mode = "security_group" + name = "my-share" + size = 200 + profile = "dp2" + zone = "au-syd-2" +} +resource "ibm_is_share" "example-5" { + origin_share { + crn = ibm_is_share.example-4.crn + } + name = "my-replica1" +} +resource "ibm_is_share" "example-6" { + origin_share { + id = ibm_is_share.example-4.id + } + name = "my-replica1" +} +``` + ## Argument Reference The following arguments are supported: - `access_control_mode` - (Optional, Boolean) The access control mode for the share. Supported values are **security_group** and **vpc**. Default value is **security_group** +- `allowed_transit_encryption_modes` - (Optional, List of string) The transit encryption modes allowed for this share. - `access_tags` - (Optional, List of Strings) The list of access management tags to attach to the share. **Note** For more information, about creating access tags, see [working with tags](https://cloud.ibm.com/docs/account?topic=account-tag). - `encryption_key` - (Optional, String) The CRN of the [Key Protect Root Key](https://cloud.ibm.com/docs/key-protect?topic=key-protect-getting-started-tutorial) or [Hyper Protect Crypto Service Root Key](https://cloud.ibm.com/docs/hs-crypto?topic=hs-crypto-get-started) for this resource. - `initial_owner` - (Optional, List) The initial owner for the file share. @@ -151,6 +177,10 @@ The following arguments are supported: ~> **Note** `virtual_network_interface` and `vpc` are mutually exclusive and one of them must be provided. - `name` - (Required, string) The unique user-defined name for this file share. If unspecified, the name will be a hyphenated list of randomly-selected words. +- `origin_share` - (Optional, List) The origin share this accessor share is referring to. + Nested schema for **origin_share**: + - `crn` - (Optional, String) The CRN for this file share. + - `id` - (Optional, String) The unique identifier for this file share. - `profile` - (Required, string) The globally unique name for this share profile. ~> **NOTE** @@ -212,6 +242,13 @@ The following attributes are exported: - `access_control_mode` - (Boolean) The access control mode for the share. - `access_tags` - (String) Access management tags associated to the share. +- `accessor_binding_role` - (String) The accessor binding role of this file share:- `none`: This file share is not participating in access with another file share- `origin`: This file share is the origin for one or more file shares (which may be in other accounts)- `accessor`: This file share is providing access to another file share (which may be in another account). +- `accessor_bindings` - (List) The accessor bindings for this file share. Each accessor binding identifies a resource (possibly in another account) with access to this file share's data. + Nested schema for **accessor_bindings**: + - `href` - (String) The URL for this share accessor binding. + - `id` - (String) The unique identifier for this share accessor binding. + - `resource_type` - (String) The resource type. +- `allowed_transit_encryption_modes` - (List of string) The transit encryption modes allowed for this share. - `created_at` - (String) The date and time that the file share is created. - `crn` - (String) The CRN for this share. - `encryption` - (String) The type of encryption used for this file share. @@ -255,6 +292,26 @@ Nested `latest_sync` blocks have the following structure: - `resource_type` - (String) Resource type of this virtual network interface. - `security_groups`- (List of string) The security groups to use for this virtual network interface. - `subnet` - (string) The associated subnet. +- `origin_share` - (Optional, List) The origin share this accessor share is referring to.This property will be present when the `accessor_binding_role` is `accessor`. + Nested schema for **origin_share**: + - `crn` - (Computed, String) The CRN for this file share. + - `deleted` - (Optional, List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (Computed, String) Link to documentation about deleted resources. + - `href` - (Computed, String) The URL for this file share. + - `id` - (Computed, String) The unique identifier for this file share. + - `name` - (Computed, String) The name for this share. The name is unique across all shares in the region. + - `remote` - (Optional, List) If present, this property indicates that the resource associated with this referenceis remote and therefore may not be directly retrievable. + Nested schema for **remote**: + - `account` - (Optional, List) If present, this property indicates that the referenced resource is remote to thisaccount, and identifies the owning account. + Nested schema for **account**: + - `id` - (Computed, String) The unique identifier for this account. + - `resource_type` - (Computed, String) The resource type. + - `region` - (Optional, List) If present, this property indicates that the referenced resource is remote to thisregion, and identifies the native region. + Nested schema for **region**: + - `href` - (Computed, String) The URL for this region. + - `name` - (Computed, String) The globally unique name for this region. + - `resource_type` - (Computed, String) The resource type. - `resource_type` - (String) The type of resource referenced. - `replica_share` - (List) Configuration for a replica file share to create and associate with this file share. - `crn` - (String) CRN of replica share diff --git a/website/docs/r/is_share_delete_accessor_binding.html.markdown b/website/docs/r/is_share_delete_accessor_binding.html.markdown new file mode 100644 index 0000000000..fb92b9cc4d --- /dev/null +++ b/website/docs/r/is_share_delete_accessor_binding.html.markdown @@ -0,0 +1,63 @@ +--- +layout: "ibm" +page_title: "IBM : is_share_delete_accessor_binding" +description: |- + Delete a share accessor binding. +subcategory: "VPC infrastructure" +--- + +# is_share_accessor_binding_operations + +Provides a resource for managing the share accessor binding operations like delete binding. + +~> **NOTE** +`ibm_share_delete_accessor_binding` is used for deleting share accessor binding + + +## Example Usage + +```terraform +resource "ibm_is_share" "example" { + name = "my-share" + size = 200 + profile = "dp2" + zone = "us-south-2" +} +``` +## Example Usage (Create a accessor share) + +```terraform +resource "ibm_is_share" "example1" { + origin_share { + crn = ibm_is_share.example.crn + } + name = "my-replica1" +} +``` + +## Example Usage + +```hcl +// list bindings +data "ibm_is_share_accessor_bindings" "example" { + share = ibm_is_share.example.id +} + +resource "ibm_share_delete_accessor_binding" "example" { + share = ibm_is_share.example.id + accessor_binding = data.ibm_is_share_accessor_bindings.example.accessor_bindings.0.id +} +``` + +## Argument Reference + +The following arguments are supported: + +- `share` - (Required, string) The file share identifier. +- `accessor_binding` - (Required, string) The share accessor binding ID + +## Attribute Reference + +The following attributes are exported: + +- `id` - The unique identifier of the Share. diff --git a/website/docs/r/is_subnet_reserved_ip.html.markdown b/website/docs/r/is_subnet_reserved_ip.html.markdown index 8bdc6aab21..0cbd06732a 100644 --- a/website/docs/r/is_subnet_reserved_ip.html.markdown +++ b/website/docs/r/is_subnet_reserved_ip.html.markdown @@ -7,7 +7,7 @@ description: |- --- # ibm_is_subnet_reserved_ip -Create, update, or delete a subnet. For more information, about associated reserved IP subnet, see [reserved IP subnet](https://cloud.ibm.com/docs/vpc?topic=vpc-troubleshoot-reserved-ip). +Create, update, or delete a subnet reserved IP. For more information, about associated reserved IP subnet, see [reserved IP subnet](https://cloud.ibm.com/docs/vpc?topic=vpc-troubleshoot-reserved-ip). **Note:** VPC infrastructure services are a regional specific based endpoint, by default targets to `us-south`. Please make sure to target right region in the provider block as shown in the `provider.tf` file, if VPC service is created in region other than `us-south`. @@ -90,34 +90,36 @@ resource "ibm_is_subnet_reserved_ip" "example5" { ## Argument reference Review the argument references that you can specify for your resource. -- `address` - (Optional, Forces new resource, String) The IP address. -- `auto_delete`- (Optional, Bool) If reserved IP is auto deleted. -- `name` - (Optional, String) The name of the reserved IP. +- `address` - (Optional, Forces new resource, String) The IP address to reserve, which must not already be reserved on the subnet. If unspecified, an available address on the subnet will automatically be selected. +- `auto_delete`- (Optional, Bool) Indicates whether this reserved IP member will be automatically deleted when either target is deleted, or the reserved IP is unbound. Must be false if the reserved IP is unbound. +- `name` - (Optional, String) The name for this reserved IP. The name must not be used by another reserved IP in the subnet. Names starting with ibm- are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words. ~> **NOTE:** raise error if name is given with a prefix `ibm- `. - `subnet` - (Required, Forces new resource, String) The subnet ID for the reserved IP. -- `target` - (Optional, string) The ID for the target endpoint gateway for the reserved IP. - +- `target` - (Optional, string) The target to bind this reserved IP to. The target must be in the same VPC. If unspecified, the reserved IP will be created unbound. The following targets are supported: + - An endpoint gateway not already bound to a reserved IP in the subnet's zone. + - A virtual network interface. + ## Attribute reference In addition to all argument reference list, you can access the following attribute reference after your resource is created. - `created_at` - (Timestamp) The date and time that the reserved IP was created.", - `href` - (String) The URL for this reserved IP. - `id` - (String) The combination of the subnet ID and reserved IP ID, separated by **/**. -- `lifecycle_state` - (String) The lifecycle state of the reserved IP. [ deleting, failed, pending, stable, suspended, updating, waiting ] +- `lifecycle_state` - (String) The lifecycle state of the reserved IP. [ **deleting**, **failed**, **pending**, **stable**, **suspended**, **updating**, **waiting** ] - `owner` - (String) The owner of a reserved IP, defining whether it is managed by the user or the provider. -- `reserved_ip` - (String) The reserved IP. +- `reserved_ip` - (String) The unique identifier for this reserved IP. - `resource_type` - (String) The resource type. - `target` - (String) The ID for the target for the reserved IP. - `target_crn` - (String) The crn of the target for the reserved IP. ## Import -The `ibm_is_subnet_reserved_ip` and `ibm_is_subnet` resource can be imported by using subnet ID and reserved IP ID separated by **/**. +The `ibm_is_subnet_reserved_ip` resource can be imported by using subnet ID and reserved IP ID separated by **/**. **Syntax** ``` -$ terraform import ibm_is_subnet.example / +$ terraform import ibm_is_subnet_reserved_ip.example / ``` **Example** diff --git a/website/docs/r/kms_key.html.markdown b/website/docs/r/kms_key.html.markdown index 8d6f87149e..e953c09030 100644 --- a/website/docs/r/kms_key.html.markdown +++ b/website/docs/r/kms_key.html.markdown @@ -12,6 +12,8 @@ This resource can be used for management of keys in both Key Protect and Hyper P After creating an Hyper Protect Crypto Service instance you need to initialize the instance properly with the crypto units, in order to create, or manage Hyper Protect Crypto Service keys. For more information, about how to initialize the Hyper Protect Crypto Service instance, see [Initialize Hyper Protect Crypto](https://cloud.ibm.com/docs/hs-crypto?topic=hs-crypto-initialize-hsm) only for HPCS instance. + ~>**Important:** + If the key is used with other IBM Cloud resources that require an `ibm_iam_authorization_policy` resource (requires [service authorization](https://cloud.ibm.com/docs/account?topic=account-serviceauth&interface=ui)), make sure to include `depends_on` targeting the `ibm_iam_authorization_policy` involved to ensure proper deletion of resources with `terraform destroy`. See an [example usage](#example-usage-between-a-cloud-object-storage-bucket-and-a-key) to create service authorization between a Cloud Object Storage bucket and a key ~>**Deprecated:** The ability to use the ibm_kms_key resource to create or update key policies in Terraform has been removed in favor of a dedicated ibm_kms_key_policies resource. For more information, check out [here](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/kms_key_policies#example-usage-to-create-a-[…]and-associate-a-key-policy) @@ -26,22 +28,15 @@ resource "ibm_resource_instance" "kms_instance" { plan = "tiered-pricing" location = "us-south" } + resource "ibm_kms_key" "test" { instance_id = ibm_resource_instance.kms_instance.guid key_name = "key-name" standard_key = false - force_delete =true -} -resource "ibm_cos_bucket" "smart-us-south" { - bucket_name = "atest-bucket" - resource_instance_id = "cos-instance-id" - region_location = "us-south" - storage_class = "smart" - kms_key_crn = ibm_kms_key.test.id + force_delete = true } ``` - **Note:** - + ~>**Note:** `key_protect` attribute to associate a kms_key with a COS bucket has been renamed as `kms_key_crn` , hence it is recommended to all the new users to use `kms_key_crn`.Although the support for older attribute name `key_protect` will be continued for existing customers. @@ -95,6 +90,51 @@ resource "ibm_kms_key" "key" { } ``` +## Example usage between a Cloud Object Storage bucket and a key + +```terraform +resource "ibm_resource_instance" "kms_instance" { + name = "terraform_instance" + service = "kms" + plan = "tiered-pricing" + location = "us-south" +} + +resource "ibm_kms_key" "kms_root_key_1" { + depends_on = [ ibm_iam_authorization_policy.policy_s2_kms_cos ] + + instance_id = ibm_resource_instance.kms_instance.guid + key_name = "root_k1" + standard_key = false + force_delete = true +} + +resource "ibm_resource_instance" "cos_instance" { + name = "terraform_cos_instance" + service = "cloud-object-storage" + plan = "standard" + location = "global" +} + +resource "ibm_iam_authorization_policy" "policy_s2_kms_cos" { + roles = ["Reader"] + + source_service_name = "cloud-object-storage" + source_resource_instance_id = ibm_resource_instance.cos_instance.guid + + target_service_name = "kms" + target_resource_instance_id = ibm_resource_instance.kms_instance.guid +} + +resource "ibm_cos_bucket" "cos_bk_1" { + bucket_name = "cos-bk-1" + resource_instance_id = ibm_resource_instance.cos_instance.id + region_location = "us-south" + storage_class = "smart" + kms_key_crn = ibm_kms_key.kms_root_key_1.id +} +``` + ## Argument reference Review the argument references that you can specify for your resource. diff --git a/website/docs/r/kms_key_rings.html.markdown b/website/docs/r/kms_key_rings.html.markdown index c4e080bbf9..79bfeb47f0 100644 --- a/website/docs/r/kms_key_rings.html.markdown +++ b/website/docs/r/kms_key_rings.html.markdown @@ -23,7 +23,6 @@ resource "ibm_resource_instance" "kms_instance" { resource "ibm_kms_key_rings" "key_ring" { instance_id = ibm_resource_instance.kms_instance.guid key_ring_id = "key-ring-id" - force_delete = true } resource "ibm_kms_key" "key" { instance_id = ibm_resource_instance.kp_instance.guid @@ -34,15 +33,8 @@ resource "ibm_kms_key" "key" { } ``` -Sample example of deleting a key ring where all keys inside have key state equals to 5 (destroyed). Keys are moved to the default key ring. - -```terraform -resource "ibm_kms_key_rings" "key_ring" { - instance_id = ibm_resource_instance.kms_instance.guid - key_ring_id = "key-ring-id" - force_delete = true -} -``` +~>**Deprecated:** +`force_delete` argument will no longer be supported. Users are advised to remove references to `force_delete` from all `ibm_kms_key_rings` configurations by `July 30th 2025`. New default behavior of deleting a key ring is to move keys with state equals to 5 (destroyed) to the default key ring. ## Argument reference Review the argument references that you can specify for your resource. @@ -50,7 +42,7 @@ Review the argument references that you can specify for your resource. - `endpoint_type` - (Optional, Forces new resource, String) The type of the public endpoint, or private endpoint to be used for creating keys. - `instance_id` - (Required, Forces new resource, String) The hs-crypto or key protect instance GUID. - `key_ring_id` - (Required, Forces new resource, String) The ID that identifies the key ring. Each ID is unique within the given instance and is not reserved across the key protect service. **Constraints** `2 ≤ length ≤ 100`. Value must match regular expression of `^[a-zA-Z0-9-]*$`. -- `force_delete` - (Optional, Bool) If set to **true**, allows force deletion of a key ring. Terraform users are recommended to have this set to **true**. All keys in the key ring are required to be deleted (in state **5**) before this action can be performed. If the key ring to be deleted contains keys, they will be moved to the **default** key ring which requires the **kms.secrets.patch** IAM action. +- `force_delete` - (**Deprecated**)(Optional, Bool) If set to **true**, allows force deletion of a key ring. Terraform users are recommended to have this set to **true**. All keys in the key ring are required to be deleted (in state **5**) before this action can be performed. If the key ring to be deleted contains keys, they will be moved to the **default** key ring which requires the **kms.secrets.patch** IAM action. ## Attribute reference In addition to all argument reference list, you can access the following attribute reference after your resource is created. diff --git a/website/docs/r/kms_kmip_certs.html.markdown b/website/docs/r/kms_kmip_certs.html.markdown index 42d86c1aef..0336a9f3cb 100644 --- a/website/docs/r/kms_kmip_certs.html.markdown +++ b/website/docs/r/kms_kmip_certs.html.markdown @@ -6,7 +6,7 @@ description: |- Manages kmip certs for IBM hs-crypto and KMS. --- -# ibm_kms_kmip_adapter +# ibm_kms_kmip_client_cert Register or delete a KMIP Client Certificate to a given KMIP adapter. Certificates are PEM-encoded SSL certificates that will be used by a KMIP client to communicate with the KMIP server. For more information, about KMIP as a whole, see [Using the key management interoperability protocol (KMIP)](https://cloud.ibm.com/docs/key-protect?topic=key-protect-kmip&interface=ui). diff --git a/website/docs/r/logs-router_tenant.html.markdown b/website/docs/r/logs-router_tenant.html.markdown new file mode 100644 index 0000000000..ecbc7645d5 --- /dev/null +++ b/website/docs/r/logs-router_tenant.html.markdown @@ -0,0 +1,85 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_logs_router_tenant" +description: |- + Manages logs_router_tenant. +subcategory: "IBM Cloud Logs Routing" +--- + +# ibm_logs_router_tenant + +Create, update, and delete logs_router_tenants with this resource. + +## Example Usage + +```hcl +resource "ibm_logs_router_tenant" "logs_router_tenant_instance" { + name = "my-logging-tenant" + targets { + log_sink_crn = "crn:v1:bluemix:public:logdna:eu-de:a/3516b8fa0a174a71899f5affa4f18d78:3517d2ed-9429-af34-ad52-34278391cbc8::" + name = "my-log-sink" + parameters { + host = "www.example.com" + port = 1 + access_credential = "credential" + } + } +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `name` - (Required, String) The name for this tenant. The name is regionally unique across all tenants in the account. + * Constraints: The maximum length is `35` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,-,.]/`. +* `targets` - (Required, List) List of targets. + * Constraints: The maximum length is `2` items. The minimum length is `1` item. +Nested schema for **targets**: + * `log_sink_crn` - (Optional, String) Cloud resource name of the log-sink target instance. + * Constraints: The maximum length is `256` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,:,-]/`. + * `name` - (Optional, String) The name for this tenant target. The name is unique across all targets for this tenant. + * Constraints: The maximum length is `35` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,-,.]/`. + * `parameters` - (Optional, List) List of properties returned from a successful list operation for a log-sink of type IBM Log Analysis (logdna). + Nested schema for **parameters**: + * `host` - (Required, String) Host name of the log-sink. + * Constraints: The maximum length is `256` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,-,.]/`. + * `port` - (Required, Integer) Network port of the log-sink. + * Constraints: The maximum value is `65535`. The minimum value is `1`. + * `access_credential` - (Optional, String) Secret to connect to the Mezmo log-sink. This is not required for log-sink of type Cloud Logs. + + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the logs_router_tenant. +* `created_at` - (String) Time stamp the tenant was originally created. + * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/[0-9,:,.,-,T,Z]/`. +* `crn` - (String) Cloud resource name of the tenant. + * Constraints: The maximum length is `256` characters. The minimum length is `1` character. The value must match regular expression `/[a-z,A-Z,0-9,:,-]/`. +* `etag` - (String) Resource version identifier. + * Constraints: The maximum length is `66` characters. The minimum length is `66` characters. The value must match regular expression `/(?:W\/)?"(?:[ !#-\\x7E\\x80-\\xFF]*| [ ]|\\.)*"/`. +* `updated_at` - (String) Time stamp the tenant was last updated. + * Constraints: The maximum length is `36` characters. The minimum length is `1` character. The value must match regular expression `/[0-9,:,.,-,T,Z]/`. + +* `etag` - ETag identifier for logs_router_tenant. + +* `target.0.etag` - ETag identifier for logs_router_tenant target. + +* `target.0.id` - The unique identifier of the logs_router_tenant target + +## Import + +You can import the `ibm_logs_router_tenant` resource by using `id`. Unique ID of the tenant. +For more information, see [the documentation](http://cloud.ibm.com) + +# Syntax +
+$ terraform import ibm_logs_router_tenant.logs_router_tenant <id>
+
+ +# Example +``` +$ terraform import ibm_logs_router_tenant.logs_router_tenant 8717db99-2cfb-4ba6-a033-89c994c2e9f0 +``` diff --git a/website/docs/r/logs_alert.html.markdown b/website/docs/r/logs_alert.html.markdown index 832b0dcdd5..0237ae3017 100644 --- a/website/docs/r/logs_alert.html.markdown +++ b/website/docs/r/logs_alert.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_alert @@ -17,7 +16,7 @@ Create, update, and delete logs_alerts with this resource. resource "ibm_resource_instance" "logs_instance" { name = "logs-instance" service = "logs" - plan = "experimental" + plan = "standard" location = "eu-gb" } resource "ibm_logs_alert" "logs_alert_instance" { diff --git a/website/docs/r/logs_dashboard.html.markdown b/website/docs/r/logs_dashboard.html.markdown index b70808b77d..3d87455344 100644 --- a/website/docs/r/logs_dashboard.html.markdown +++ b/website/docs/r/logs_dashboard.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_dashboard diff --git a/website/docs/r/logs_dashboard_folder.html.markdown b/website/docs/r/logs_dashboard_folder.html.markdown index 1361e8a1fd..2baef5f3ec 100644 --- a/website/docs/r/logs_dashboard_folder.html.markdown +++ b/website/docs/r/logs_dashboard_folder.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_dashboard_folder diff --git a/website/docs/r/logs_e2m.html.markdown b/website/docs/r/logs_e2m.html.markdown index 3f0090d80c..910061ac2e 100644 --- a/website/docs/r/logs_e2m.html.markdown +++ b/website/docs/r/logs_e2m.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_e2m diff --git a/website/docs/r/logs_outgoing_webhook.html.markdown b/website/docs/r/logs_outgoing_webhook.html.markdown index bd15bd0a2c..2239f555d2 100644 --- a/website/docs/r/logs_outgoing_webhook.html.markdown +++ b/website/docs/r/logs_outgoing_webhook.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_outgoing_webhook diff --git a/website/docs/r/logs_policy.html.markdown b/website/docs/r/logs_policy.html.markdown index 88fbb8855b..d9f185b306 100644 --- a/website/docs/r/logs_policy.html.markdown +++ b/website/docs/r/logs_policy.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_policy diff --git a/website/docs/r/logs_rule_group.html.markdown b/website/docs/r/logs_rule_group.html.markdown index 78d6cd827c..4e60114923 100644 --- a/website/docs/r/logs_rule_group.html.markdown +++ b/website/docs/r/logs_rule_group.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_rule_group diff --git a/website/docs/r/logs_view.html.markdown b/website/docs/r/logs_view.html.markdown index 5b698df631..763de51618 100644 --- a/website/docs/r/logs_view.html.markdown +++ b/website/docs/r/logs_view.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_view diff --git a/website/docs/r/logs_view_folder.html.markdown b/website/docs/r/logs_view_folder.html.markdown index f693b20e98..7cf071b3da 100644 --- a/website/docs/r/logs_view_folder.html.markdown +++ b/website/docs/r/logs_view_folder.html.markdown @@ -6,7 +6,6 @@ description: |- subcategory: "Cloud Logs" --- -~> **Beta:** This resource is in Beta, and is subject to change. # ibm_logs_view_folder diff --git a/website/docs/r/onboarding_catalog_deployment.html.markdown b/website/docs/r/onboarding_catalog_deployment.html.markdown new file mode 100644 index 0000000000..753fdbe7cd --- /dev/null +++ b/website/docs/r/onboarding_catalog_deployment.html.markdown @@ -0,0 +1,169 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_onboarding_catalog_deployment" +description: |- + Manages onboarding_catalog_deployment. +subcategory: "Partner Center Sell" +--- + +# ibm_onboarding_catalog_deployment + +**Note - Intended for internal use only. This resource is strictly experimental and subject to change without notice.** + +Create, update, and delete onboarding_catalog_deployments with this resource. + +## Example Usage + +```hcl +resource "ibm_onboarding_catalog_deployment" "onboarding_catalog_deployment_instance" { + active = true + catalog_plan_id = "catalog_plan_id" + catalog_product_id = "catalog_product_id" + disabled = true + kind = "deployment" + metadata { + rc_compatible = true + ui { + strings { + en { + bullets { + description = "description" + description_i18n = { "key" = "inner" } + title = "title" + title_i18n = { "key" = "inner" } + } + media { + caption = "caption" + caption_i18n = { "key" = "inner" } + thumbnail = "thumbnail" + type = "image" + url = "url" + } + } + } + urls { + doc_url = "doc_url" + terms_url = "terms_url" + } + hidden = true + side_by_side_index = 1.0 + } + service { + rc_provisionable = true + iam_compatible = true + } + } + name = "name" + object_provider { + name = "name" + email = "email" + } + overview_ui { + en { + display_name = "display_name" + description = "description" + long_description = "long_description" + } + } + product_id = "product_id" +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `active` - (Required, Boolean) Whether the service is active. +* `catalog_plan_id` - (Required, Forces new resource, String) The unique ID of this global catalog plan. + * Constraints: The maximum length is `128` characters. The minimum length is `2` characters. The value must match regular expression `/^[a-zA-Z\\-_\\d]+$/`. +* `catalog_product_id` - (Required, Forces new resource, String) The unique ID of this global catalog product. + * Constraints: The maximum length is `128` characters. The minimum length is `2` characters. The value must match regular expression `/^[a-zA-Z\\-_\\d]+$/`. +* `disabled` - (Required, Boolean) Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled. +* `env` - (Optional, String) The environment to fetch this object from. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. The value must match regular expression `/^[a-z]+$/`. +* `kind` - (Required, String) The kind of the global catalog object. + * Constraints: Allowable values are: `deployment`. +* `metadata` - (Optional, List) Global catalog deployment metadata. +Nested schema for **metadata**: + * `rc_compatible` - (Optional, Boolean) Whether the object is compatible with the resource controller service. + * `service` - (Optional, List) The global catalog metadata of the service. + Nested schema for **service**: + * `iam_compatible` - (Optional, Boolean) Whether the service is compatible with the IAM service. + * `rc_provisionable` - (Optional, Boolean) Whether the service is provisionable by the resource controller service. + * `ui` - (Optional, List) The UI metadata of this service. + Nested schema for **ui**: + * `hidden` - (Optional, Boolean) Whether the object is hidden from the consumption catalog. + * `side_by_side_index` - (Optional, Float) When the objects are listed side-by-side, this value controls the ordering. + * `strings` - (Optional, List) The data strings. + Nested schema for **strings**: + * `en` - (Optional, List) Translated content of additional information about the service. + Nested schema for **en**: + * `bullets` - (Optional, List) The list of features that highlights your product's attributes and benefits for users. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + Nested schema for **bullets**: + * `description` - (Optional, String) The description about the features of the product. + * Constraints: The maximum length is `2000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `description_i18n` - (Optional, Map) The description about the features of the product in translation. + * `title` - (Optional, String) The descriptive title for the feature. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `title_i18n` - (Optional, Map) The descriptive title for the feature in translation. + * `media` - (Optional, List) The list of supporting media for this product. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + Nested schema for **media**: + * `caption` - (Required, String) Provide a descriptive caption that indicates what the media illustrates. This caption is displayed in the catalog. + * Constraints: The maximum length is `2000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `caption_i18n` - (Optional, Map) The brief explanation for your images and videos in translation. + * `thumbnail` - (Optional, String) The reduced-size version of your images and videos. + * Constraints: The maximum length is `2083` characters. The minimum length is `0` characters. + * `type` - (Required, String) The type of the media. + * Constraints: Allowable values are: `image`, `youtube`, `video_mp_4`, `video_webm`. + * `url` - (Required, String) The URL that links to the media that shows off the product. + * Constraints: The maximum length is `2083` characters. The minimum length is `0` characters. + * `urls` - (Optional, List) The UI based URLs. + Nested schema for **urls**: + * `doc_url` - (Optional, String) The URL for your product documentation. + * `terms_url` - (Optional, String) The URL for your product's end user license agreement. +* `name` - (Required, String) The programmatic name of this deployment. + * Constraints: The value must match regular expression `/^[a-z0-9\\-.]+$/`. +* `object_provider` - (Required, List) The provider or owner of the product. +Nested schema for **object_provider**: + * `email` - (Optional, String) The email address of the provider. + * `name` - (Optional, String) The name of the provider. +* `overview_ui` - (Optional, List) The object that contains the service details from the Overview page in global catalog. +Nested schema for **overview_ui**: + * `en` - (Optional, List) Translated details about the service, for example, display name, short description, and long description. + Nested schema for **en**: + * `description` - (Optional, String) The short description of the product that is displayed in your catalog entry. + * `display_name` - (Optional, String) The display name of the product. + * `long_description` - (Optional, String) The detailed description of your product that is displayed at the beginning of your product page in the catalog. Markdown markup language is supported. +* `product_id` - (Required, Forces new resource, String) The unique ID of the product. + * Constraints: The maximum length is `71` characters. The minimum length is `71` characters. The value must match regular expression `/^[a-zA-Z0-9]{32}:o:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/`. +* `tags` - (Required, List) A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog. + * Constraints: The list items must match regular expression `/^[a-z0-9\\-._]+$/`. The maximum length is `100` items. The minimum length is `0` items. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the onboarding_catalog_deployment. +* `catalog_deployment_id` - (String) The ID of a global catalog object. +* `url` - (String) The global catalog URL of your product. + + +## Import + +You can import the `ibm_onboarding_catalog_deployment` resource by using `id`. +The `id` property can be formed from `product_id`, `catalog_product_id`, `catalog_plan_id`, and `catalog_deployment_id` in the following format: + +
+<product_id>/<catalog_product_id>/<catalog_plan_id>/<catalog_deployment_id>
+
+* `product_id`: A string. The unique ID of the product. +* `catalog_product_id`: A string. The unique ID of this global catalog product. +* `catalog_plan_id`: A string. The unique ID of this global catalog plan. +* `catalog_deployment_id`: A string. The ID of a global catalog object. + +# Syntax +
+$ terraform import ibm_onboarding_catalog_deployment.onboarding_catalog_deployment //
+
diff --git a/website/docs/r/onboarding_catalog_plan.html.markdown b/website/docs/r/onboarding_catalog_plan.html.markdown new file mode 100644 index 0000000000..a436683e59 --- /dev/null +++ b/website/docs/r/onboarding_catalog_plan.html.markdown @@ -0,0 +1,167 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_onboarding_catalog_plan" +description: |- + Manages onboarding_catalog_plan. +subcategory: "Partner Center Sell" +--- + +# ibm_onboarding_catalog_plan + +**Note - Intended for internal use only. This resource is strictly experimental and subject to change without notice.** + +Create, update, and delete onboarding_catalog_plans with this resource. + +## Example Usage + +```hcl +resource "ibm_onboarding_catalog_plan" "onboarding_catalog_plan_instance" { + active = true + catalog_product_id = "catalog_product_id" + disabled = true + kind = "plan" + metadata { + rc_compatible = true + ui { + strings { + en { + bullets { + description = "description" + description_i18n = { "key" = "inner" } + title = "title" + title_i18n = { "key" = "inner" } + } + media { + caption = "caption" + caption_i18n = { "key" = "inner" } + thumbnail = "thumbnail" + type = "image" + url = "url" + } + } + } + urls { + doc_url = "doc_url" + terms_url = "terms_url" + } + hidden = true + side_by_side_index = 1.0 + } + pricing { + type = "free" + origin = "global_catalog" + } + } + name = "name" + object_provider { + name = "name" + email = "email" + } + overview_ui { + en { + display_name = "display_name" + description = "description" + long_description = "long_description" + } + } + product_id = "product_id" +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `active` - (Required, Boolean) Whether the service is active. +* `catalog_product_id` - (Required, Forces new resource, String) The unique ID of this global catalog product. + * Constraints: The maximum length is `128` characters. The minimum length is `2` characters. The value must match regular expression `/^[a-zA-Z\\-_\\d]+$/`. +* `disabled` - (Required, Boolean) Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled. +* `env` - (Optional, String) The environment to fetch this object from. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. The value must match regular expression `/^[a-z]+$/`. +* `kind` - (Required, String) The kind of the global catalog object. + * Constraints: Allowable values are: `plan`. +* `metadata` - (Optional, List) Global catalog plan metadata. +Nested schema for **metadata**: + * `pricing` - (Optional, List) The pricing metadata of this object. + Nested schema for **pricing**: + * `origin` - (Optional, String) The source of the pricing information: global_catalog or pricing_catalog. + * Constraints: Allowable values are: `global_catalog`, `pricing_catalog`. + * `type` - (Optional, String) The type of the pricing plan. + * Constraints: Allowable values are: `free`, `paid`, `Free`, `Paid`. + * `rc_compatible` - (Optional, Boolean) Whether the object is compatible with the resource controller service. + * `ui` - (Optional, List) The UI metadata of this service. + Nested schema for **ui**: + * `hidden` - (Optional, Boolean) Whether the object is hidden from the consumption catalog. + * `side_by_side_index` - (Optional, Float) When the objects are listed side-by-side, this value controls the ordering. + * `strings` - (Optional, List) The data strings. + Nested schema for **strings**: + * `en` - (Optional, List) Translated content of additional information about the service. + Nested schema for **en**: + * `bullets` - (Optional, List) The list of features that highlights your product's attributes and benefits for users. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + Nested schema for **bullets**: + * `description` - (Optional, String) The description about the features of the product. + * Constraints: The maximum length is `2000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `description_i18n` - (Optional, Map) The description about the features of the product in translation. + * `title` - (Optional, String) The descriptive title for the feature. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `title_i18n` - (Optional, Map) The descriptive title for the feature in translation. + * `media` - (Optional, List) The list of supporting media for this product. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + Nested schema for **media**: + * `caption` - (Required, String) Provide a descriptive caption that indicates what the media illustrates. This caption is displayed in the catalog. + * Constraints: The maximum length is `2000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `caption_i18n` - (Optional, Map) The brief explanation for your images and videos in translation. + * `thumbnail` - (Optional, String) The reduced-size version of your images and videos. + * Constraints: The maximum length is `2083` characters. The minimum length is `0` characters. + * `type` - (Required, String) The type of the media. + * Constraints: Allowable values are: `image`, `youtube`, `video_mp_4`, `video_webm`. + * `url` - (Required, String) The URL that links to the media that shows off the product. + * Constraints: The maximum length is `2083` characters. The minimum length is `0` characters. + * `urls` - (Optional, List) The UI based URLs. + Nested schema for **urls**: + * `doc_url` - (Optional, String) The URL for your product documentation. + * `terms_url` - (Optional, String) The URL for your product's end user license agreement. +* `name` - (Required, String) The programmatic name of this plan. + * Constraints: The value must match regular expression `/^[a-z0-9\\-.]+$/`. +* `object_provider` - (Required, List) The provider or owner of the product. +Nested schema for **object_provider**: + * `email` - (Optional, String) The email address of the provider. + * `name` - (Optional, String) The name of the provider. +* `overview_ui` - (Optional, List) The object that contains the service details from the Overview page in global catalog. +Nested schema for **overview_ui**: + * `en` - (Optional, List) Translated details about the service, for example, display name, short description, and long description. + Nested schema for **en**: + * `description` - (Optional, String) The short description of the product that is displayed in your catalog entry. + * `display_name` - (Optional, String) The display name of the product. + * `long_description` - (Optional, String) The detailed description of your product that is displayed at the beginning of your product page in the catalog. Markdown markup language is supported. +* `product_id` - (Required, Forces new resource, String) The unique ID of the product. + * Constraints: The maximum length is `71` characters. The minimum length is `71` characters. The value must match regular expression `/^[a-zA-Z0-9]{32}:o:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/`. +* `tags` - (Required, List) A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog. + * Constraints: The list items must match regular expression `/^[a-z0-9\\-._]+$/`. The maximum length is `100` items. The minimum length is `0` items. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the onboarding_catalog_plan. +* `catalog_plan_id` - (String) The ID of a global catalog object. +* `url` - (String) The global catalog URL of your product. + + +## Import + +You can import the `ibm_onboarding_catalog_plan` resource by using `id`. +The `id` property can be formed from `product_id`, `catalog_product_id`, and `catalog_plan_id` in the following format: + +
+<product_id>/<catalog_product_id>/<catalog_plan_id>
+
+* `product_id`: A string. The unique ID of the product. +* `catalog_product_id`: A string. The unique ID of this global catalog product. +* `catalog_plan_id`: A string. The ID of a global catalog object. + +# Syntax +
+$ terraform import ibm_onboarding_catalog_plan.onboarding_catalog_plan //
+
diff --git a/website/docs/r/onboarding_catalog_product.html.markdown b/website/docs/r/onboarding_catalog_product.html.markdown new file mode 100644 index 0000000000..7275371ab7 --- /dev/null +++ b/website/docs/r/onboarding_catalog_product.html.markdown @@ -0,0 +1,256 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_onboarding_catalog_product" +description: |- + Manages onboarding_catalog_product. +subcategory: "Partner Center Sell" +--- + +# ibm_onboarding_catalog_product + +**Note - Intended for internal use only. This resource is strictly experimental and subject to change without notice.** + +Create, update, and delete onboarding_catalog_products with this resource. + +## Example Usage + +```hcl +resource "ibm_onboarding_catalog_product" "onboarding_catalog_product_instance" { + active = true + disabled = true + images { + image = "image" + } + kind = "service" + metadata { + rc_compatible = true + ui { + strings { + en { + bullets { + description = "description" + description_i18n = { "key" = "inner" } + title = "title" + title_i18n = { "key" = "inner" } + } + media { + caption = "caption" + caption_i18n = { "key" = "inner" } + thumbnail = "thumbnail" + type = "image" + url = "url" + } + } + } + urls { + doc_url = "doc_url" + terms_url = "terms_url" + } + hidden = true + side_by_side_index = 1.0 + } + service { + rc_provisionable = true + iam_compatible = true + } + other { + pc { + support { + url = "url" + status_url = "status_url" + locations = [ "locations" ] + languages = [ "languages" ] + process = "process" + process_i18n = { "key" = "inner" } + support_type = "community" + support_escalation { + contact = "contact" + escalation_wait_time { + value = 1.0 + type = "type" + } + response_wait_time { + value = 1.0 + type = "type" + } + } + support_details { + type = "support_site" + contact = "contact" + response_wait_time { + value = 1.0 + type = "type" + } + availability { + times { + day = 1.0 + start_time = "start_time" + end_time = "end_time" + } + timezone = "timezone" + always_available = true + } + } + } + } + } + } + name = "name" + object_provider { + name = "name" + email = "email" + } + overview_ui { + en { + display_name = "display_name" + description = "description" + long_description = "long_description" + } + } + product_id = "product_id" +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `active` - (Required, Boolean) Whether the service is active. +* `disabled` - (Required, Boolean) Determines the global visibility for the catalog entry, and its children. If it is not enabled, all plans are disabled. +* `env` - (Optional, String) The environment to fetch this object from. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. The value must match regular expression `/^[a-z]+$/`. +* `images` - (Optional, List) Images from the global catalog entry that help illustrate the service. +Nested schema for **images**: + * `image` - (Optional, String) The URL for your product logo. +* `kind` - (Required, String) The kind of the global catalog object. + * Constraints: Allowable values are: `service`, `platform_service`. +* `metadata` - (Optional, List) The global catalog service metadata object. +Nested schema for **metadata**: + * `other` - (Optional, List) The additional metadata of the service in global catalog. + Nested schema for **other**: + * `pc` - (Optional, List) The metadata of the service owned and managed by Partner Center - Sell. + Nested schema for **pc**: + * `support` - (Optional, List) The support metadata of the service. + Nested schema for **support**: + * `languages` - (Optional, List) The languages in which support is available. + * Constraints: The maximum length is `200` items. The minimum length is `0` items. + * `locations` - (Optional, List) The countries in which your support is available. Provide a list of country codes. + * Constraints: The maximum length is `200` items. The minimum length is `0` items. + * `process` - (Optional, String) The description of your support process. + * Constraints: The maximum length is `1500` characters. The minimum length is `0` characters. + * `process_i18n` - (Optional, Map) The description of your support process. + * `status_url` - (Optional, String) The URL where the status of your service is available. + * `support_details` - (Optional, List) The support options for the service. + * Constraints: The maximum length is `6` items. The minimum length is `0` items. + Nested schema for **support_details**: + * `availability` - (Optional, List) The time period during which support is available for the service. + Nested schema for **availability**: + * `always_available` - (Optional, Boolean) Whether the support for the service is always available. + * `times` - (Optional, List) The support hours available for the service. + * Constraints: The maximum length is `7` items. The minimum length is `0` items. + Nested schema for **times**: + * `day` - (Optional, Float) The number of days in a week when support is available for the service. + * `end_time` - (Optional, String) The time in the day when support ends for the service. + * `start_time` - (Optional, String) The time in the day when support starts for the service. + * `timezone` - (Optional, String) The timezones in which support is available. Only relevant if `always_available` is set to false. + * `contact` - (Optional, String) The contact information for this support channel. + * `response_wait_time` - (Optional, List) The time interval of providing support in units and values. + Nested schema for **response_wait_time**: + * `type` - (Optional, String) The unit of the time. + * `value` - (Optional, Float) The number of time units. + * `type` - (Optional, String) The type of support for this support channel. + * Constraints: Allowable values are: `support_site`, `email`, `chat`, `slack`, `phone`, `other`. + * `support_escalation` - (Optional, List) The details of the support escalation process. + Nested schema for **support_escalation**: + * `contact` - (Optional, String) The support contact information of the escalation team. + * `escalation_wait_time` - (Optional, List) The time interval of providing support in units and values. + Nested schema for **escalation_wait_time**: + * `type` - (Optional, String) The unit of the time. + * `value` - (Optional, Float) The number of time units. + * `response_wait_time` - (Optional, List) The time interval of providing support in units and values. + Nested schema for **response_wait_time**: + * `type` - (Optional, String) The unit of the time. + * `value` - (Optional, Float) The number of time units. + * `support_type` - (Optional, String) The type of support provided. + * Constraints: Allowable values are: `community`, `third_party`, `ibm`, `ibm_cloud`. + * `url` - (Optional, String) The support site URL where the support for your service is available. + * `rc_compatible` - (Optional, Boolean) Whether the object is compatible with the resource controller service. + * `service` - (Optional, List) The global catalog metadata of the service. + Nested schema for **service**: + * `iam_compatible` - (Optional, Boolean) Whether the service is compatible with the IAM service. + * `rc_provisionable` - (Optional, Boolean) Whether the service is provisionable by the resource controller service. + * `ui` - (Optional, List) The UI metadata of this service. + Nested schema for **ui**: + * `hidden` - (Optional, Boolean) Whether the object is hidden from the consumption catalog. + * `side_by_side_index` - (Optional, Float) When the objects are listed side-by-side, this value controls the ordering. + * `strings` - (Optional, List) The data strings. + Nested schema for **strings**: + * `en` - (Optional, List) Translated content of additional information about the service. + Nested schema for **en**: + * `bullets` - (Optional, List) The list of features that highlights your product's attributes and benefits for users. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + Nested schema for **bullets**: + * `description` - (Optional, String) The description about the features of the product. + * Constraints: The maximum length is `2000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `description_i18n` - (Optional, Map) The description about the features of the product in translation. + * `title` - (Optional, String) The descriptive title for the feature. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `title_i18n` - (Optional, Map) The descriptive title for the feature in translation. + * `media` - (Optional, List) The list of supporting media for this product. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + Nested schema for **media**: + * `caption` - (Required, String) Provide a descriptive caption that indicates what the media illustrates. This caption is displayed in the catalog. + * Constraints: The maximum length is `2000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `caption_i18n` - (Optional, Map) The brief explanation for your images and videos in translation. + * `thumbnail` - (Optional, String) The reduced-size version of your images and videos. + * Constraints: The maximum length is `2083` characters. The minimum length is `0` characters. + * `type` - (Required, String) The type of the media. + * Constraints: Allowable values are: `image`, `youtube`, `video_mp_4`, `video_webm`. + * `url` - (Required, String) The URL that links to the media that shows off the product. + * Constraints: The maximum length is `2083` characters. The minimum length is `0` characters. + * `urls` - (Optional, List) The UI based URLs. + Nested schema for **urls**: + * `doc_url` - (Optional, String) The URL for your product documentation. + * `terms_url` - (Optional, String) The URL for your product's end user license agreement. +* `name` - (Required, String) The programmatic name of this product. + * Constraints: The value must match regular expression `/^[a-z0-9\\-.]+$/`. +* `object_provider` - (Required, List) The provider or owner of the product. +Nested schema for **object_provider**: + * `email` - (Optional, String) The email address of the provider. + * `name` - (Optional, String) The name of the provider. +* `overview_ui` - (Optional, List) The object that contains the service details from the Overview page in global catalog. +Nested schema for **overview_ui**: + * `en` - (Optional, List) Translated details about the service, for example, display name, short description, and long description. + Nested schema for **en**: + * `description` - (Optional, String) The short description of the product that is displayed in your catalog entry. + * `display_name` - (Optional, String) The display name of the product. + * `long_description` - (Optional, String) The detailed description of your product that is displayed at the beginning of your product page in the catalog. Markdown markup language is supported. +* `product_id` - (Required, Forces new resource, String) The unique ID of the product. + * Constraints: The maximum length is `71` characters. The minimum length is `71` characters. The value must match regular expression `/^[a-zA-Z0-9]{32}:o:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/`. +* `tags` - (Required, List) A list of tags that carry information about your product. These tags can be used to find your product in the IBM Cloud catalog. + * Constraints: The list items must match regular expression `/^[a-z0-9\\-._]+$/`. The maximum length is `100` items. The minimum length is `0` items. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the onboarding_catalog_product. +* `catalog_product_id` - (String) The ID of a global catalog object. +* `url` - (String) The global catalog URL of your product. + + +## Import + +You can import the `ibm_onboarding_catalog_product` resource by using `id`. +The `id` property can be formed from `product_id`, and `catalog_product_id` in the following format: + +
+<product_id>/<catalog_product_id>
+
+* `product_id`: A string. The unique ID of the product. +* `catalog_product_id`: A string. The ID of a global catalog object. + +# Syntax +
+$ terraform import ibm_onboarding_catalog_product.onboarding_catalog_product /;
+
diff --git a/website/docs/r/onboarding_iam_registration.html.markdown b/website/docs/r/onboarding_iam_registration.html.markdown new file mode 100644 index 0000000000..5db8927f8e --- /dev/null +++ b/website/docs/r/onboarding_iam_registration.html.markdown @@ -0,0 +1,552 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_onboarding_iam_registration" +description: |- + Manages onboarding_iam_registration. +subcategory: "Partner Center Sell" +--- + +# ibm_onboarding_iam_registration + +**Note - Intended for internal use only. This resource is strictly experimental and subject to change without notice.** + +Create, update, and delete onboarding_iam_registrations with this resource. + +## Example Usage + +```hcl +resource "ibm_onboarding_iam_registration" "onboarding_iam_registration_instance" { + actions { + id = "id" + roles = [ "roles" ] + description { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + options { + hidden = true + } + } + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + product_id = "product_id" + resource_hierarchy_attribute { + key = "key" + value = "value" + } + supported_anonymous_accesses { + attributes { + account_id = "account_id" + service_name = "service_name" + } + roles = [ "roles" ] + } + supported_attributes { + key = "key" + options { + operators = [ "stringEquals" ] + hidden = true + supported_attributes = [ "supported_attributes" ] + policy_types = [ "access" ] + is_empty_value_supported = true + is_string_exists_false_value_supported = true + key = "key" + resource_hierarchy { + key { + key = "key" + value = "value" + } + value { + key = "key" + } + } + } + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + description { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + ui { + input_type = "input_type" + input_details { + type = "type" + values { + value = "value" + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + } + gst { + query = "query" + value_property_name = "value_property_name" + label_property_name = "label_property_name" + input_option_label = "input_option_label" + } + url { + url_endpoint = "url_endpoint" + input_option_label = "input_option_label" + } + } + } + } + supported_authorization_subjects { + attributes { + service_name = "service_name" + resource_type = "resource_type" + } + roles = [ "roles" ] + } + supported_network { + environment_attributes { + key = "key" + values = [ "values" ] + options { + hidden = true + } + } + } + supported_roles { + id = "id" + description { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + display_name { + default = "default" + en = "en" + de = "de" + es = "es" + fr = "fr" + it = "it" + ja = "ja" + ko = "ko" + pt_br = "pt_br" + zh_tw = "zh_tw" + zh_cn = "zh_cn" + } + options { + access_policy = { "key" = "inner" } + policy_type = [ "access" ] + account_type = "enterprise" + } + } +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `actions` - (Optional, List) The product access management action. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. +Nested schema for **actions**: + * `description` - (Optional, List) The description for the object. + Nested schema for **description**: + * `de` - (Optional, String) German. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wäöüß\\d]+\\b/`. + * `default` - (Optional, String) The fallback string for the description object. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `en` - (Optional, String) English. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `es` - (Optional, String) Spanish. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wáéíóúñ]+\\b/`. + * `fr` - (Optional, String) French. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàâçéèêëîïôûùüÿñœæ]+\\b/`. + * `it` - (Optional, String) Italian. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `ja` - (Optional, String) Japanese. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/^[A-Za-z0-9\\s,.!?;:'"-]+|[ぁ-んァ-ン一-龯、。「」!?\\d\\s]*$/`. + * `ko` - (Optional, String) Korean. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `pt_br` - (Optional, String) Portuguese (Brazil). + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `zh_cn` - (Optional, String) Simplified Chinese. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `zh_tw` - (Optional, String) Traditional Chinese. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `display_name` - (Optional, List) The display name of the object. + Nested schema for **display_name**: + * `de` - (Optional, String) German. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wäöüß\\d]+\\b/`. + * `default` - (Optional, String) The fallback string for the description object. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `en` - (Optional, String) English. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `es` - (Optional, String) Spanish. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wáéíóúñ]+\\b/`. + * `fr` - (Optional, String) French. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàâçéèêëîïôûùüÿñœæ]+\\b/`. + * `it` - (Optional, String) Italian. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `ja` - (Optional, String) Japanese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[A-Za-z0-9\\s,.!?;:'"-]+|[ぁ-んァ-ン一-龯、。「」!?\\d\\s]*$/`. + * `ko` - (Optional, String) Korean. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `pt_br` - (Optional, String) Portuguese (Brazil). + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `zh_cn` - (Optional, String) Simplified Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `zh_tw` - (Optional, String) Traditional Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `id` - (Optional, String) The unique identifier for the action. + * Constraints: The maximum length is `100` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `options` - (Optional, List) Extra options. + Nested schema for **options**: + * `hidden` - (Optional, Boolean) Optional opt-in if action is hidden from customers. + * `roles` - (Optional, List) The list of roles for the action. + * Constraints: The list items must match regular expression `/^[ -~\\s]*$/`. The maximum length is `100` items. The minimum length is `0` items. +* `additional_policy_scopes` - (Optional, List) List of additional policy scopes. + * Constraints: The list items must match regular expression `/^[ -~\\s]*$/`. The maximum length is `100` items. The minimum length is `0` items. +* `display_name` - (Optional, List) The display name of the object. +Nested schema for **display_name**: + * `de` - (Optional, String) German. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wäöüß\\d]+\\b/`. + * `default` - (Optional, String) The fallback string for the description object. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `en` - (Optional, String) English. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `es` - (Optional, String) Spanish. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wáéíóúñ]+\\b/`. + * `fr` - (Optional, String) French. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàâçéèêëîïôûùüÿñœæ]+\\b/`. + * `it` - (Optional, String) Italian. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `ja` - (Optional, String) Japanese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[A-Za-z0-9\\s,.!?;:'"-]+|[ぁ-んァ-ン一-龯、。「」!?\\d\\s]*$/`. + * `ko` - (Optional, String) Korean. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `pt_br` - (Optional, String) Portuguese (Brazil). + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `zh_cn` - (Optional, String) Simplified Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `zh_tw` - (Optional, String) Traditional Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. +* `enabled` - (Optional, Boolean) Whether the service is enabled or disabled for IAM. +* `env` - (Optional, String) The environment to fetch this object from. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. The value must match regular expression `/^[a-z]+$/`. +* `name` - (Optional, String) The IAM registration name, which must be the programmatic name of the product. + * Constraints: The value must match regular expression `/^[a-z0-9\\-.]+$/`. +* `parent_ids` - (Optional, List) The list of parent IDs for product access management. + * Constraints: The list items must match regular expression `/^[a-z0-9\\-.]+$/`. The maximum length is `100` items. The minimum length is `0` items. +* `product_id` - (Required, Forces new resource, String) The unique ID of the product. + * Constraints: The maximum length is `71` characters. The minimum length is `71` characters. The value must match regular expression `/^[a-zA-Z0-9]{32}:o:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/`. +* `resource_hierarchy_attribute` - (Optional, List) The resource hierarchy key-value pair for composite services. +Nested schema for **resource_hierarchy_attribute**: + * `key` - (Optional, String) The resource hierarchy key. + * `value` - (Optional, String) The resource hierarchy value. +* `service_type` - (Optional, String) The type of the service. + * Constraints: Allowable values are: `service`, `platform_service`. +* `supported_anonymous_accesses` - (Optional, List) The list of supported anonymous accesses. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. +Nested schema for **supported_anonymous_accesses**: + * `attributes` - (Optional, List) The attributes for anonymous accesses. + Nested schema for **attributes**: + * `account_id` - (Optional, String) An account id. + * `service_name` - (Optional, String) The name of the service. + * `roles` - (Optional, List) The roles of supported anonymous accesses. + * Constraints: The list items must match regular expression `/^[ -~\\s]*$/`. The maximum length is `100` items. The minimum length is `0` items. +* `supported_attributes` - (Optional, List) The list of supported attributes. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. +Nested schema for **supported_attributes**: + * `description` - (Optional, List) The description for the object. + Nested schema for **description**: + * `de` - (Optional, String) German. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wäöüß\\d]+\\b/`. + * `default` - (Optional, String) The fallback string for the description object. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `en` - (Optional, String) English. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `es` - (Optional, String) Spanish. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wáéíóúñ]+\\b/`. + * `fr` - (Optional, String) French. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàâçéèêëîïôûùüÿñœæ]+\\b/`. + * `it` - (Optional, String) Italian. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `ja` - (Optional, String) Japanese. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/^[A-Za-z0-9\\s,.!?;:'"-]+|[ぁ-んァ-ン一-龯、。「」!?\\d\\s]*$/`. + * `ko` - (Optional, String) Korean. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `pt_br` - (Optional, String) Portuguese (Brazil). + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `zh_cn` - (Optional, String) Simplified Chinese. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `zh_tw` - (Optional, String) Traditional Chinese. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `display_name` - (Optional, List) The display name of the object. + Nested schema for **display_name**: + * `de` - (Optional, String) German. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wäöüß\\d]+\\b/`. + * `default` - (Optional, String) The fallback string for the description object. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `en` - (Optional, String) English. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `es` - (Optional, String) Spanish. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wáéíóúñ]+\\b/`. + * `fr` - (Optional, String) French. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàâçéèêëîïôûùüÿñœæ]+\\b/`. + * `it` - (Optional, String) Italian. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `ja` - (Optional, String) Japanese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[A-Za-z0-9\\s,.!?;:'"-]+|[ぁ-んァ-ン一-龯、。「」!?\\d\\s]*$/`. + * `ko` - (Optional, String) Korean. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `pt_br` - (Optional, String) Portuguese (Brazil). + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `zh_cn` - (Optional, String) Simplified Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `zh_tw` - (Optional, String) Traditional Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `key` - (Optional, String) The supported attribute key. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `options` - (Optional, List) The list of support attribute options. + Nested schema for **options**: + * `hidden` - (Optional, Boolean) Optional opt-in if attribute is hidden from customers (customer can still use it if they found out themselves). + * `is_empty_value_supported` - (Optional, Boolean) Indicate whether the empty value is supported. + * `is_string_exists_false_value_supported` - (Optional, Boolean) Indicate whether the false value is supported for stringExists operator. + * `key` - (Optional, String) The name of attribute. + * `operators` - (Optional, List) The supported attribute operator. + * Constraints: Allowable list items are: `stringEquals`, `stringMatch`, `stringEqualsAnyOf`, `stringMatchAnyOf`. The maximum length is `100` items. The minimum length is `0` items. + * `policy_types` - (Optional, List) The list of policy types. + * Constraints: Allowable list items are: `access`, `authorization`. The maximum length is `2` items. The minimum length is `1` item. + * `resource_hierarchy` - (Optional, List) Resource hierarchy options for composite services. + Nested schema for **resource_hierarchy**: + * `key` - (Optional, List) Hierarchy description key. + Nested schema for **key**: + * `key` - (Optional, String) Key. + * `value` - (Optional, String) Value. + * `value` - (Optional, List) Hierarchy description value. + Nested schema for **value**: + * `key` - (Optional, String) Key. + * `supported_attributes` - (Optional, List) The list of supported patterns. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + * `ui` - (Optional, List) The user interface. + Nested schema for **ui**: + * `input_details` - (Optional, List) The details of the input. + Nested schema for **input_details**: + * `gst` - (Optional, List) Required if type is gst. + Nested schema for **gst**: + * `input_option_label` - (Optional, String) The label for option input. + * Constraints: The maximum length is `100` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `label_property_name` - (Optional, String) One of labelPropertyName or inputOptionLabel is required. + * `query` - (Optional, String) The query to use. + * Constraints: The maximum length is `100` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `value_property_name` - (Optional, String) The value of the property name. + * Constraints: The maximum length is `100` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `type` - (Optional, String) They type of the input details. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `url` - (Optional, List) The URL data for user interface. + Nested schema for **url**: + * `input_option_label` - (Optional, String) The label options for the user interface URL. + * Constraints: The maximum length is `2083` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `url_endpoint` - (Optional, String) The URL of the user interface interface. + * Constraints: The maximum length is `2083` characters. The minimum length is `0` characters. + * `values` - (Optional, List) The provided values of input details. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + Nested schema for **values**: + * `display_name` - (Optional, List) The display name of the object. + Nested schema for **display_name**: + * `de` - (Optional, String) German. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wäöüß\\d]+\\b/`. + * `default` - (Optional, String) The fallback string for the description object. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `en` - (Optional, String) English. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `es` - (Optional, String) Spanish. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wáéíóúñ]+\\b/`. + * `fr` - (Optional, String) French. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàâçéèêëîïôûùüÿñœæ]+\\b/`. + * `it` - (Optional, String) Italian. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `ja` - (Optional, String) Japanese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[A-Za-z0-9\\s,.!?;:'"-]+|[ぁ-んァ-ン一-龯、。「」!?\\d\\s]*$/`. + * `ko` - (Optional, String) Korean. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `pt_br` - (Optional, String) Portuguese (Brazil). + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `zh_cn` - (Optional, String) Simplified Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `zh_tw` - (Optional, String) Traditional Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `value` - (Optional, String) The values of input details. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `input_type` - (Optional, String) The type of the input. + * Constraints: The maximum length is `100` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. +* `supported_authorization_subjects` - (Optional, List) The list of supported authorization subjects. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. +Nested schema for **supported_authorization_subjects**: + * `attributes` - (Optional, List) The list of supported authorization subject properties. + Nested schema for **attributes**: + * `resource_type` - (Optional, String) The type of the service. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `service_name` - (Optional, String) The name of the service. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `roles` - (Optional, List) The list of roles for authorization. + * Constraints: The list items must match regular expression `/^[ -~\\s]*$/`. The maximum length is `100` items. The minimum length is `0` items. +* `supported_network` - (Optional, List) The registration of set of endpoint types that are supported by your service in the `networkType` environment attribute. This constrains the context-based restriction rules specific to the service such that they describe access restrictions on only this set of endpoints. +Nested schema for **supported_network**: + * `environment_attributes` - (Optional, List) The environment attribute for support. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + Nested schema for **environment_attributes**: + * `key` - (Optional, String) The name of the key. + * Constraints: The maximum length is `100` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `options` - (Optional, List) The list of options for supported networks. + Nested schema for **options**: + * `hidden` - (Optional, Boolean) Whether the attribute is hidden or not. + * `values` - (Optional, List) The list of values that belong to the key. + * Constraints: The list items must match regular expression `/^[ -~\\s]*$/`. The maximum length is `100` items. The minimum length is `0` items. +* `supported_roles` - (Optional, List) The list of roles that you can use to assign access. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. +Nested schema for **supported_roles**: + * `description` - (Optional, List) The description for the object. + Nested schema for **description**: + * `de` - (Optional, String) German. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wäöüß\\d]+\\b/`. + * `default` - (Optional, String) The fallback string for the description object. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `en` - (Optional, String) English. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `es` - (Optional, String) Spanish. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wáéíóúñ]+\\b/`. + * `fr` - (Optional, String) French. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàâçéèêëîïôûùüÿñœæ]+\\b/`. + * `it` - (Optional, String) Italian. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `ja` - (Optional, String) Japanese. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/^[A-Za-z0-9\\s,.!?;:'"-]+|[ぁ-んァ-ン一-龯、。「」!?\\d\\s]*$/`. + * `ko` - (Optional, String) Korean. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `pt_br` - (Optional, String) Portuguese (Brazil). + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `zh_cn` - (Optional, String) Simplified Chinese. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `zh_tw` - (Optional, String) Traditional Chinese. + * Constraints: The maximum length is `20000` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `display_name` - (Optional, List) The display name of the object. + Nested schema for **display_name**: + * `de` - (Optional, String) German. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wäöüß\\d]+\\b/`. + * `default` - (Optional, String) The fallback string for the description object. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `en` - (Optional, String) English. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `es` - (Optional, String) Spanish. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wáéíóúñ]+\\b/`. + * `fr` - (Optional, String) French. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàâçéèêëîïôûùüÿñœæ]+\\b/`. + * `it` - (Optional, String) Italian. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `ja` - (Optional, String) Japanese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[A-Za-z0-9\\s,.!?;:'"-]+|[ぁ-んァ-ン一-龯、。「」!?\\d\\s]*$/`. + * `ko` - (Optional, String) Korean. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `pt_br` - (Optional, String) Portuguese (Brazil). + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/\\b[\\wàèéìîòóù]+\\b/`. + * `zh_cn` - (Optional, String) Simplified Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `zh_tw` - (Optional, String) Traditional Chinese. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/./`. + * `id` - (Optional, String) The value belonging to the key. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/^[ -~\\s]*$/`. + * `options` - (Optional, List) The supported role options. + Nested schema for **options**: + * `access_policy` - (Optional, Map) Optional opt-in to require access control on the role. + * `account_type` - (Optional, String) Optional opt-in to require checking account type when applying the role. + * Constraints: Allowable values are: `enterprise`. + * `policy_type` - (Optional, List) Optional opt-in to require checking policy type when applying the role. + * Constraints: Allowable list items are: `access`, `authorization`, `authorization-delegated`. The list items must match regular expression `/^[ -~\\s]*$/`. The maximum length is `100` items. The minimum length is `0` items. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the onboarding_iam_registration. + + +## Import + +You can import the `ibm_onboarding_iam_registration` resource by using `name`. +The `name` property can be formed from `product_id`, and `name` in the following format: + +
+<product_id>/<name>
+
+* `product_id`: A string. The unique ID of the product. +* `name`: A string. The IAM registration name, which must be the programmatic name of the product. + +# Syntax +
+$ terraform import ibm_onboarding_iam_registration.onboarding_iam_registration /;
+
diff --git a/website/docs/r/onboarding_product.html.markdown b/website/docs/r/onboarding_product.html.markdown new file mode 100644 index 0000000000..2712779297 --- /dev/null +++ b/website/docs/r/onboarding_product.html.markdown @@ -0,0 +1,81 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_onboarding_product" +description: |- + Manages onboarding_product. +subcategory: "Partner Center Sell" +--- + +# ibm_onboarding_product + +**Note - Intended for internal use only. This resource is strictly experimental and subject to change without notice.** + +Create, update, and delete onboarding_products with this resource. + +## Example Usage + +```hcl +resource "ibm_onboarding_product" "onboarding_product_instance" { + primary_contact { + name = "name" + email = "email" + } + support { + escalation_contacts { + name = "name" + email = "email" + role = "role" + } + } + type = "software" +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `eccn_number` - (Optional, String) The Export Control Classification Number of your product. +* `ero_class` - (Optional, String) The ERO class of your product. +* `primary_contact` - (Required, List) The primary contact for your product. +Nested schema for **primary_contact**: + * `email` - (Required, String) The email address of the primary contact for your product. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^\\S+@\\S+$/`. + * `name` - (Required, String) The name of the primary contact for your product. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. +* `support` - (Optional, List) The support information that is not displayed in the catalog, but available in ServiceNow. +Nested schema for **support**: + * `escalation_contacts` - (Optional, List) The list of contacts in case of support escalations. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. + Nested schema for **escalation_contacts**: + * `email` - (Optional, String) The email address of the support escalation contact. + * `name` - (Optional, String) The name of the support escalation contact. + * `role` - (Optional, String) The role of the support escalation contact. +* `tax_assessment` - (Optional, String) The tax assessment type of your product. +* `type` - (Required, String) The type of the product. + * Constraints: Allowable values are: `software`, `service`, `professional_service`. +* `unspsc` - (Optional, Float) The United Nations Standard Products and Services Code of your product. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the onboarding_product. +* `account_id` - (String) The IBM Cloud account ID of the provider. +* `approver_resource_id` - (String) The ID of the approval workflow of your product. +* `global_catalog_offering_id` - (String) The ID of a global catalog object. +* `private_catalog_id` - (String) The ID of the private catalog that contains the product. Only applicable for software type products. + * Constraints: The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. +* `private_catalog_offering_id` - (String) The ID of the linked private catalog product. Only applicable for software type products. + * Constraints: The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. +* `staging_global_catalog_offering_id` - (String) The ID of a global catalog object. + + +## Import + +You can import the `ibm_onboarding_product` resource by using `id`. The ID of a product in Partner Center - Sell. + +# Syntax +
+$ terraform import ibm_onboarding_product.onboarding_product ;
+
diff --git a/website/docs/r/onboarding_registration.html.markdown b/website/docs/r/onboarding_registration.html.markdown new file mode 100644 index 0000000000..100a78f658 --- /dev/null +++ b/website/docs/r/onboarding_registration.html.markdown @@ -0,0 +1,65 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_onboarding_registration" +description: |- + Manages onboarding_registration. +subcategory: "Partner Center Sell" +--- + +# ibm_onboarding_registration + +**Note - Intended for internal use only. This resource is strictly experimental and subject to change without notice.** + +Create, update, and delete onboarding_registrations with this resource. + +## Example Usage + +```hcl +resource "ibm_onboarding_registration" "onboarding_registration_instance" { + account_id = "account_id" + company_name = "company_name" + primary_contact { + name = "name" + email = "email" + } +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `account_id` - (Required, String) The ID of your account. + * Constraints: The maximum length is `32` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9]+$/`. +* `company_name` - (Required, String) The name of your company that is displayed in the IBM Cloud catalog. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. +* `default_private_catalog_id` - (Optional, String) The default private catalog in which products are created. + * Constraints: The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. +* `primary_contact` - (Required, List) The primary contact for your product. +Nested schema for **primary_contact**: + * `email` - (Required, String) The email address of the primary contact for your product. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^\\S+@\\S+$/`. + * `name` - (Required, String) The name of the primary contact for your product. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. +* `provider_access_group` - (Optional, String) The onboarding access group for your team. + * Constraints: The maximum length is `50` characters. The minimum length is `1` character. The value must match regular expression `/^AccessGroupId-[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/`. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the onboarding_registration. +* `account_dpa_id` - (String) The ID of the IBM Digital Provider Agreement. +* `account_dra_id` - (String) The ID of the IBM Digital Platform Reseller Agreement. +* `created_at` - (String) The time when the registration was created. +* `updated_at` - (String) The time when the registration was updated. + + +## Import + +You can import the `ibm_onboarding_registration` resource by using `id`. The ID of your registration, which is the same as your billing and metering (BSS) account ID. + +# Syntax +
+$ terraform import ibm_onboarding_registration.onboarding_registration ;
+
diff --git a/website/docs/r/onboarding_resource_broker.html.markdown b/website/docs/r/onboarding_resource_broker.html.markdown new file mode 100644 index 0000000000..a13d8e24cb --- /dev/null +++ b/website/docs/r/onboarding_resource_broker.html.markdown @@ -0,0 +1,82 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_onboarding_resource_broker" +description: |- + Manages onboarding_resource_broker. +subcategory: "Partner Center Sell" +--- + +# ibm_onboarding_resource_broker + +**Note - Intended for internal use only. This resource is strictly experimental and subject to change without notice.** + +Create, update, and delete onboarding_resource_brokers with this resource. + +## Example Usage + +```hcl +resource "ibm_onboarding_resource_broker" "onboarding_resource_broker_instance" { + auth_password = "auth_password" + auth_scheme = "auth_scheme" + auth_username = "auth_username" + broker_url = "broker_url" + name = "name" + type = "provision_through" +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `allow_context_updates` - (Optional, Boolean) Whether the resource controller will call the broker for any context changes to the instance. Currently, the only context related change is an instance name update. +* `auth_password` - (Required, String) The authentication password to reach the broker. +* `auth_scheme` - (Required, String) The supported authentication scheme for the broker. +* `auth_username` - (Required, String) The authentication username to reach the broker. +* `broker_url` - (Required, String) The URL associated with the broker application. +* `catalog_type` - (Optional, String) To enable the provisioning of your broker, set this parameter value to `service`. +* `env` - (Optional, String) The environment to fetch this object from. + * Constraints: The maximum length is `64` characters. The minimum length is `1` character. The value must match regular expression `/^[a-z]+$/`. +* `name` - (Required, String) The name of the broker. + * Constraints: The maximum length is `128` characters. The minimum length is `1` character. The value must match regular expression `/^[ -~\\s]*$/`. +* `region` - (Optional, String) The region where the pricing plan is available. +* `resource_group_crn` - (Optional, String) The cloud resource name of the resource group. +* `state` - (Optional, String) The state of the broker. + * Constraints: Allowable values are: `active`, `removed`. +* `type` - (Required, String) The type of the provisioning model. + * Constraints: Allowable values are: `provision_through`, `provision_behind`. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the onboarding_resource_broker. +* `account_id` - (String) The ID of the account in which you manage the broker. +* `created_at` - (String) The time when the service broker was created. +* `created_by` - (List) The details of the user who created this broker. +Nested schema for **created_by**: + * `user_id` - (String) The ID of the user who dispatched this action. + * `user_name` - (String) The username of the user who dispatched this action. +* `crn` - (String) The cloud resource name (CRN) of the broker. +* `deleted_at` - (String) The time when the service broker was deleted. +* `deleted_by` - (List) The details of the user who deleted this broker. +Nested schema for **deleted_by**: + * `user_id` - (String) The ID of the user who dispatched this action. + * `user_name` - (String) The username of the user who dispatched this action. +* `guid` - (String) The globally unique identifier of the broker. +* `updated_at` - (String) The time when the service broker was updated. +* `updated_by` - (List) The details of the user who updated this broker. +Nested schema for **updated_by**: + * `user_id` - (String) The ID of the user who dispatched this action. + * `user_name` - (String) The username of the user who dispatched this action. +* `url` - (String) The URL associated with the broker. + + +## Import + +You can import the `ibm_onboarding_resource_broker` resource by using `id`. The identifier of the broker. + +# Syntax +
+$ terraform import ibm_onboarding_resource_broker.onboarding_resource_broker ;
+
diff --git a/website/docs/r/pi_dhcp.html.markdown b/website/docs/r/pi_dhcp.html.markdown index 4681c2d289..2099a01fa4 100644 --- a/website/docs/r/pi_dhcp.html.markdown +++ b/website/docs/r/pi_dhcp.html.markdown @@ -12,6 +12,7 @@ description: |- Create, update, or delete DHCP Server for your Power Systems Virtual Server instance. For more information, see [getting started with IBM Power Systems Virtual Servers](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-getting-started). ## Example usage + The following example enables you to create a DHCP Server: ```terraform @@ -19,9 +20,10 @@ resource "ibm_pi_dhcp" "example" { pi_cloud_instance_id = "" } ``` + ## Argument reference -Review the argument references that you can specify for your resource. +Review the argument references that you can specify for your resource. - `pi_cidr` - (Optional, String) The CIDR for the DHCP private network. - `pi_cloud_connection_id` - (Optional, String) The Cloud Connection UUID to connect with the DHCP private network. @@ -35,7 +37,7 @@ Review the argument references that you can specify for your resource. In addition to all argument reference list, you can access the following attribute reference after your resource is created. - `dhcp_id` - (String) The ID of the DHCP Server. -- `id` - (String) The unique identifier of the DHCP Server. The ID is composed of `/`. +- `id` - (String) The unique identifier of the DHCP Server. The ID is composed of `/`. - `leases` - (List) The list of DHCP Server PVM Instance leases. Nested scheme for `leases`: - `instance_ip` - (String) The IP of the PVM Instance. @@ -51,12 +53,12 @@ The `ibm_pi_dhcp` provides the following [timeouts](https://www.terraform.io/doc - **create** - (Default 30 minutes) Used for creating a DHCP Server. - **delete** - (Default 10 minutes) Used for deleting a DHCP Server. -**Note** +### Notes -* Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. -* If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: - * `region` - `lon` - * `zone` - `lon04` +- Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. +- If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: + - `region` - `lon` + - `zone` - `lon04` Example usage: @@ -66,10 +68,11 @@ The `ibm_pi_dhcp` provides the following [timeouts](https://www.terraform.io/doc zone = "lon04" } ``` + ## Import The `ibm_pi_dhcp` resource can be imported by using `pi_cloud_instance_id` and `dhcp_id`. -```terraform +```bash terraform import ibm_pi_dhcp.example d7bec597-4726-451f-8a63-e62e6f19c32c/0e48e1be-9f54-4a67-ba55-7e31ce98b65a -``` \ No newline at end of file +``` diff --git a/website/docs/r/pi_image.html.markdown b/website/docs/r/pi_image.html.markdown index 6aee9079b6..77ea5a66b8 100644 --- a/website/docs/r/pi_image.html.markdown +++ b/website/docs/r/pi_image.html.markdown @@ -39,14 +39,14 @@ resource "ibm_pi_image" "testacc_image "{ } ``` -## Notes +### Notes - Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. - If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: - `region` - `lon` - `zone` - `lon04` - Example usage: +Example usage: ```terraform provider "ibm" { @@ -57,7 +57,7 @@ resource "ibm_pi_image" "testacc_image "{ ## Timeouts -The ibm_pi_image provides the following [timeouts](https://www.terraform.io/docs/language/resources/syntax.html) configuration options: +The ibm_pi_image provides the following [timeouts](https://www.terraform.io/docs/language/resources/syntax.html) configuration options: - **create** - (Default 60 minutes) Used for creating an image. - **delete** - (Default 60 minutes) Used for deleting an image. @@ -75,6 +75,7 @@ Review the argument references that you can specify for your resource. - `pi_image_name` - (Required, String) The name of an image. - `pi_image_id` - (Optional, String) Image ID of existing source image; required for copy image. - Either `pi_image_id` or `pi_image_bucket_name` is required. + - You can retrieve this value from [pi_catalog_images](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/pi_catalog_images#image_id) as `image_id` from the stock image you intend to use. - `pi_image_bucket_name` - (Optional, String) Cloud Object Storage bucket name; `bucket-name[/optional/folder]` - Either `pi_image_bucket_name` or `pi_image_id` is required. - `pi_image_access_key` - (Optional, String, Sensitive) Cloud Object Storage access key; required for buckets with private access. @@ -87,7 +88,7 @@ Review the argument references that you can specify for your resource. - `pi_image_secret_key` - (Optional, String, Sensitive) Cloud Object Storage secret key; required for buckets with private access. - `pi_image_secret_key` is required with `pi_image_access_key` - `pi_image_storage_pool` - (Optional, String) Storage pool where the image will be loaded, if provided then `pi_affinity_policy` will be ignored. Used only when importing an image from cloud storage. -- `pi_image_storage_type` - (Optional, String) Type of storage; If not provided the storage type will default to 'tier3'. Used only when importing an image from cloud storage. +- `pi_image_storage_type` - (Optional, String) Type of storage; If not provided the storage type will default to 'tier3'. Used only when importing an image from cloud storage. To get a list of available storage types, please use the [ibm_pi_storage_types_capacity](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/pi_storage_types_capacity) data source. - `pi_image_import_details` - (Optional, Forces new resource, List) Import details for SAP images Nested schema for **pi_image_import_details**: @@ -106,8 +107,8 @@ In addition to all argument reference list, you can access the following attribu The `ibm_pi_image` can be imported by using `pi_cloud_instance_id` and `image_id`. -**Example** +### Example -``` +```bash terraform import ibm_pi_image.example d7bec597-4726-451f-8a63-e62e6f19c32c/cea6651a-bc0a-4438-9f8a-a0770bbf3ebb ``` diff --git a/website/docs/r/pi_instance.html.markdown b/website/docs/r/pi_instance.html.markdown index 151591cafc..efc06f6aab 100644 --- a/website/docs/r/pi_instance.html.markdown +++ b/website/docs/r/pi_instance.html.markdown @@ -7,10 +7,12 @@ description: |- --- # ibm_pi_instance + Create, delete or update a [Power Systems Virtual Server instance](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-creating-power-virtual-server). ## Example usage -The following example creates a Power Systems Virtual Server instance. + +The following example creates a Power Systems Virtual Server instance. ```terraform resource "ibm_pi_instance" "test-instance" { @@ -32,13 +34,15 @@ resource "ibm_pi_instance" "test-instance" { ~> **WARNING:** Updating a ibm_pi_instance resource with `pi_replicants` set does not update replicant vms! -**Note** -* Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. -* If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: - * `region` - `lon` - * `zone` - `lon04` +### Notes + +- Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. +- If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: + - `region` - `lon` + - `zone` - `lon04` Example usage: + ```terraform provider "ibm" { region = "lon" @@ -50,13 +54,13 @@ Example usage: The `ibm_pi_instance` provides the following [timeouts](https://www.terraform.io/docs/language/resources/syntax.html) configuration options: -- **create** - The creation of the instance is considered failed if no response is received for 120 minutes. -- **Update** The updation of the instance is considered failed if no response is received for 60 minutes. -- **delete** - The deletion of the instance is considered failed if no response is received for 60 minutes. - +- **create** - (Default 120 minutes) Used for creating an instance. +- **update** - (Default 60 minutes) Used for updating an instance. +- **delete** - (Default 60 minutes) Used for deleting an instance. ## Argument reference -Review the argument references that you can specify for your resource. + +Review the argument references that you can specify for your resource. - `pi_affinity_instance` - (Optional, String) PVM Instance (ID or Name) to base storage affinity policy against; required if requesting `affinity` and `pi_affinity_volume` is not provided. - `pi_affinity_policy` - (Optional, String) Affinity policy for pvm instance being created; ignored if `pi_storage_pool` provided; for policy affinity requires one of `pi_affinity_instance` or `pi_affinity_volume` to be specified; for policy anti-affinity requires one of `pi_anti_affinity_instances` or `pi_anti_affinity_volumes` to be specified; Allowable values: `affinity`, `anti-affinity` @@ -67,21 +71,22 @@ Review the argument references that you can specify for your resource. - `pi_deployment_target` - (Optional, List) The deployment of a dedicated host. Max items: 1. Nested scheme for `pi_deployment_target` : - * `id` - (Required, String) The uuid of the host group or host. - * `type` - (Required, String) The deployment target type. Supported values are `host` and `hostGroup`. + - `id` - (Required, String) The uuid of the host group or host. + - `type` - (Required, String) The deployment target type. Supported values are `host` and `hostGroup`. - `pi_deployment_type` - (Optional, String) Custom deployment type; Allowable value: `EPIC` or `VMNoStorage`. - `pi_health_status` - (Optional, String) Specifies if Terraform should poll for the health status to be `OK` or `WARNING`. The default value is `OK`. -**Notes** IBM i software licenses for IBM i virtual server instances -- only for IBM i instances. Default to `false` and `0` if no values provided +**Note**: IBM i software licenses for IBM i virtual server instances -- only for IBM i instances. Default to `false` and `0` if no values provided + - `pi_ibmi_css` - (Optional, Boolean) IBM i Cloud Storage Solution. - `pi_ibmi_pha` - (Optional, Boolean) IBM i Power High Availability. - `pi_ibmi_rds_users` - (Optional, Integer) IBM i Rational Dev Studio Number of User Licenses. - `pi_image_id` - (Required, String) The ID of the image that you want to use for your Power Systems Virtual Server instance. The image determines the operating system that is installed in your instance. To list available images, run the `ibmcloud pi images` command. - - **Notes**: + - **Note**: - Only images belonging to your project can be used image for deploying a Power Systems Virtual Server instance. To import an images to your project, see [ibm_pi_image](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/pi_image). - If using `pi_deployment_type = VMNoStorage` then use the following images for the respective OS you intend to create the instance: `AIX-EMPTY`, `IBMI-EMPTY`, `SLES-EMPTY`, `RHEL-EMPTY`. -- `pi_instance_name` - (Required, String) The name of the Power Systems Virtual Server instance. +- `pi_instance_name` - (Required, String) The name of the Power Systems Virtual Server instance. - `pi_key_pair_name` - (Optional, String) The name of the SSH key that you want to use to access your Power Systems Virtual Server instance. The SSH key must be uploaded to IBM Cloud. - `pi_license_repository_capacity` - (Deprecated, Optional, Integer) The VTL license repository capacity TB value. Only use with VTL instances. `pi_memory >= 16 + (2 * pi_license_repository_capacity)`. - **Note**: Provisioning VTL instances is temporarily disabled. @@ -92,14 +97,14 @@ Review the argument references that you can specify for your resource. The `pi_network` block supports: - `network_id` - (String) The network ID to assign to the instance. - `ip_address` - (String) The ip address to be used of this network. -- `pi_pin_policy` - (Optional, String) Select the pinning policy for your Power Systems Virtual Server instance. Supported values are `soft`, `hard`, and `none`. **Note** You can choose to soft pin (`soft`) or hard pin (`hard`) a virtual server to the physical host where it runs. When you soft pin an instance for high availability, the instance automatically migrates back to the original host once the host is back to its operating state. If the instance has a licensing restriction with the host, the hard pin option restricts the movement of the instance during remote restart, automated remote restart, DRO, and live partition migration. The default pinning policy is `none`. +- `pi_pin_policy` - (Optional, String) Select the pinning policy for your Power Systems Virtual Server instance. Supported values are `soft`, `hard`, and `none`. **Note** You can choose to soft pin (`soft`) or hard pin (`hard`) a virtual server to the physical host where it runs. When you soft pin an instance for high availability, the instance automatically migrates back to the original host once the host is back to its operating state. If the instance has a licensing restriction with the host, the hard pin option restricts the movement of the instance during remote restart, automated remote restart, DRO, and live partition migration. The default pinning policy is `none`. - `pi_placement_group_id` - (Optional, String) The ID of the placement group that the instance is in or empty quotes `""` to indicate it is not in a placement group. The meta-argument `count` and a `pi_replicants` cannot be used when specifying a placement group ID. Instances provisioning in the same placement group must be provisioned one at a time; however, to provision multiple instances on the same host or different hosts then use `pi_replicants` and `pi_replication_policy` instead of `pi_placement_group_id`. - `pi_processors` - (Optional, Float) The number of vCPUs to assign to the VM as visible within the guest Operating System. - Required when not creating SAP instances. Conflicts with `pi_sap_profile_id`. - `pi_proc_type` - (Optional, String) The type of processor mode in which the VM will run with `shared`, `capped` or `dedicated`. - Required when not creating SAP instances. Conflicts with `pi_sap_profile_id`. - `pi_replicants` - (Optional, Integer) The number of instances that you want to provision with the same configuration. If this parameter is not set, `1` is used by default. -- `pi_replication_policy` - (Optional, String) The replication policy that you want to use, either `affinity`, `anti-affinity` or `none`. If this parameter is not set, `none` is used by default. +- `pi_replication_policy` - (Optional, String) The replication policy that you want to use, either `affinity`, `anti-affinity` or `none`. If this parameter is not set, `none` is used by default. - `pi_replication_scheme` - (Optional, String) The replication scheme that you want to set, either `prefix` or `suffix`. - `pi_sap_profile_id` - (Optional, String) SAP Profile ID for the amount of cores and memory. - Required only when creating SAP instances. @@ -107,16 +112,17 @@ Review the argument references that you can specify for your resource. - `pi_shared_processor_pool` - (Optional, String) The shared processor pool for instance deployment. Conflicts with `pi_sap_profile_id`. - `pi_storage_pool` - (Optional, String) Storage Pool for server deployment; if provided then `pi_affinity_policy` will be ignored; Only valid when you deploy one of the IBM supplied stock images. Storage pool for a custom image (an imported image or an image that is created from a VM capture) defaults to the storage pool the image was created in. - `pi_storage_pool_affinity` - (Optional, Boolean) Indicates if all volumes attached to the server must reside in the same storage pool. The default value is `true`. To attach data volumes from a different storage pool (mixed storage) set to `false` and use `pi_volume_attach` resource. Once set to `false`, cannot be set back to `true` unless all volumes attached reside in the same storage type and pool. -- `pi_storage_type` - (Optional, String) - Storage type for server deployment; If storage type is not provided the storage type will default to `tier3`. +- `pi_storage_type` - (Optional, String) - Storage type for server deployment; If storage type is not provided the storage type will default to `tier3`. To get a list of available storage types, please use the [ibm_pi_storage_types_capacity](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/pi_storage_types_capacity) data source. - `pi_storage_connection` - (Optional, String) - Storage Connectivity Group (SCG) for server deployment. Only supported value is `vSCSI`. -- `pi_sys_type` - (Optional, String) The type of system on which to create the VM (s922/e880/e980/s1022). - - Supported SAP system types are (e880/e980). +- `pi_sys_type` - (Optional, String) The type of system on which to create the VM (e880/e980/e1080/s922/s1022). + - Supported SAP system types are (e880/e980/e1080). - `pi_user_data` - (Optional, String) The user data `cloud-init` to pass to the instance during creation. It can be a base64 encoded or an unencoded string. If it is an unencoded string, the provider will encode it before it passing it down. - `pi_virtual_cores_assigned` - (Optional, Integer) Specify the number of virtual cores to be assigned. - `pi_virtual_optical_device` - (Optional, String) Virtual Machine's Cloud Initialization Virtual Optical Device. - `pi_volume_ids` - (Optional, List of String) The list of volume IDs that you want to attach to the instance during creation. ## Attribute reference + In addition to all argument reference list, you can access the following attribute reference after your resource is created. - `fault` - (Map) Fault information, if any. @@ -129,11 +135,11 @@ In addition to all argument reference list, you can access the following attribu - `health_status` - (String) The health status of the VM. - `ibmi_rds` - (Boolean) IBM i Rational Dev Studio. -- `id` - (String) The unique identifier of the instance. The ID is composed of `//.../`. -- `instance_id` - (String) The unique identifier of the instance. +- `id` - (String) The unique identifier of the instance. The ID is composed of `//.../`. +- `instance_id` - (String) The unique identifier of the instance. - `max_processors`- (Float) The maximum number of processors that can be allocated to the instance with shutting down or rebooting the `LPAR`. - `max_virtual_cores` - (Integer) The maximum number of virtual cores. -- `min_processors` - (Float) The minimum number of processors that the instance can have. +- `min_processors` - (Float) The minimum number of processors that the instance can have. - `min_memory` - (Float) The minimum memory that was allocated to the instance. - `max_memory`- (Float) The maximum amount of memory that can be allocated to the instance without shut down or reboot the `LPAR`. - `min_virtual_cores` - (Integer) The minimum number of virtual cores. @@ -149,12 +155,13 @@ In addition to all argument reference list, you can access the following attribu - `progress` - (Float) - Specifies the overall progress of the instance deployment process in percentage. - `shared_processor_pool_id` - (String) The ID of the shared processor pool for the instance. - `status` - (String) The status of the instance. + ## Import -The `ibm_pi_instance` can be imported using `cloud_instance_id` and `instance_id`. +The `ibm_pi_instance` can be imported using `pi_cloud_instance_id` and `instance_id`. -**Example** +### Example +```bash +terraform import ibm_pi_instance.example d7bec597-4726-451f-8a63-e62e6f19c32c/cea6651a-bc0a-4438-9f8a-a0770b112ebb ``` -$ terraform import ibm_pi_instance.example d7bec597-4726-451f-8a63-e62e6f19c32c/cea6651a-bc0a-4438-9f8a-a0770b112ebb -``` \ No newline at end of file diff --git a/website/docs/r/pi_volume.html.markdown b/website/docs/r/pi_volume.html.markdown index 60f1d14d6e..c75ab9b075 100644 --- a/website/docs/r/pi_volume.html.markdown +++ b/website/docs/r/pi_volume.html.markdown @@ -19,7 +19,7 @@ resource "ibm_pi_volume" "testacc_volume"{ pi_cloud_instance_id = "" pi_volume_size = 20 pi_volume_name = "test-volume" - pi_volume_type = "ssd" + pi_volume_type = "tier3" pi_volume_shareable = true } ``` @@ -63,7 +63,7 @@ Review the argument references that you can specify for your resource. - `pi_volume_pool` - (Optional, String) Volume pool where the volume will be created; if provided then `pi_affinity_policy` values will be ignored. - `pi_volume_shareable` - (Required, Boolean) If set to **true**, the volume can be shared across Power Systems Virtual Server instances. If set to **false**, you can attach it only to one instance. - `pi_volume_size` - (Required, Integer) The size of the volume in GB. -- `pi_volume_type` - (Optional, String) Type of disk, if diskType is not provided the disk type will default to `tier3`. +- `pi_volume_type` - (Optional, String) Type of volume, if this field is not provided, it will default to `tier3`. To get a list of available volume types, please use the [ibm_pi_storage_types_capacity](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/pi_storage_types_capacity) data source. ## Attribute reference diff --git a/website/docs/r/pi_volume_clone.html.markdown b/website/docs/r/pi_volume_clone.html.markdown index 58ca385888..6eb0ed1ee1 100644 --- a/website/docs/r/pi_volume_clone.html.markdown +++ b/website/docs/r/pi_volume_clone.html.markdown @@ -31,8 +31,8 @@ resource "ibm_pi_volume_clone" "testacc_volume_clone" { - `region` - `lon` - `zone` - `lon04` - Example usage: - +Example usage: + ```terraform provider "ibm" { region = "lon" @@ -53,7 +53,7 @@ Review the argument references that you can specify for your resource. - `pi_cloud_instance_id` - (Required, String) The GUID of the service instance associated with an account. - `pi_replication_enabled` - (Optional, Boolean) Indicates whether the cloned volume should have replication enabled. If no value is provided, it will default to the replication status of the source volume(s). -- `pi_target_storage_tier` - (Optional, String) The storage tier for the cloned volume(s). +- `pi_target_storage_tier` - (Optional, String) The storage tier for the cloned volume(s). To get a list of available storage tiers, please use the [ibm_pi_storage_types_capacity](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/pi_storage_types_capacity) data source. - `pi_volume_clone_name` - (Required, String) The base name of the newly cloned volume(s). - `pi_volume_ids` - (Required, Set of String) List of volumes to be cloned. diff --git a/website/docs/r/pi_volume_group.html.markdown b/website/docs/r/pi_volume_group.html.markdown index b492e02b6d..27c927952f 100644 --- a/website/docs/r/pi_volume_group.html.markdown +++ b/website/docs/r/pi_volume_group.html.markdown @@ -1,5 +1,4 @@ --- - subcategory: "Power Systems" layout: "ibm" page_title: "IBM: pi_volume_group" @@ -8,8 +7,11 @@ description: |- --- # ibm_pi_volume_group + Create, update, or delete a volume group. For more information, about managing volume groups, see [getting started with IBM Power Systems Virtual Servers](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-getting-started). + ## Example usage + The following example creates a volume group. ```terraform @@ -20,11 +22,12 @@ resource "ibm_pi_volume_group" "testacc_volume_group"{ } ``` -**Note** -* Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. -* If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: - * `region` - `lon` - * `zone` - `lon04` +### Notes + +- Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. +- If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: + - `region` - `lon` + - `zone` - `lon04` Example usage: @@ -43,8 +46,9 @@ ibm_pi_volume_group provides the following [timeouts](https://www.terraform.io/d - **update** - (Default 30 minutes) Used for updating volume group. - **delete** - (Default 10 minutes) Used for deleting volume group. -## Argument reference -Review the argument references that you can specify for your resource. +## Argument reference + +Review the argument references that you can specify for your resource. - `pi_cloud_instance_id` - (Required, String) The GUID of the service instance associated with an account. - `pi_consistency_group_name` - (Optional, String) The name of consistency group at storage controller level, required if `pi_volume_group_name` is not provided. @@ -52,11 +56,18 @@ Review the argument references that you can specify for your resource. - `pi_volume_ids` - (Required, Set of String) List of volume IDs to add in volume group. ## Attribute reference + In addition to all argument reference list, you can access the following attribute reference after your resource is created. -- `id` - (String) The unique identifier of the volume group. The ID is composed of `/`. - `consistency_group_name` - (String) The consistency Group Name if volume is a part of volume group. +- `id` - (String) The unique identifier of the volume group. The ID is composed of `/`. - `replication_status` - (String) The replication status of volume group. +- `status_description_errors` - (Set) The status details of the volume group. + + Nested scheme for `status_description_errors`: + - `key` - (String) The volume group error key. + - `message` - (String) The failure message providing more details about the error key. + - `volume_ids` - (List of String) List of volume IDs, which failed to be added to or removed from the volume group, with the given error. - `volume_group_id` - (String) The unique identifier of the volume group. - `volume_group_status` - (String) The status of the volume group. @@ -64,8 +75,8 @@ In addition to all argument reference list, you can access the following attribu The `ibm_pi_volume_group` resource can be imported by using `pi_cloud_instance_id` and `volume_group_id`. -**Example** +### Example +```bash +terraform import ibm_pi_volume_group.example d7bec597-4726-451f-8a63-e62e6f19c32c/cea6651a-bc0a-4438-9f8a-a0770bbf3ebb ``` -$ terraform import ibm_pi_volume_group.example d7bec597-4726-451f-8a63-e62e6f19c32c/cea6651a-bc0a-4438-9f8a-a0770bbf3ebb -``` \ No newline at end of file diff --git a/website/docs/r/resource_group.html.markdown b/website/docs/r/resource_group.html.markdown index 5fedd438a6..725f827bf1 100644 --- a/website/docs/r/resource_group.html.markdown +++ b/website/docs/r/resource_group.html.markdown @@ -20,6 +20,12 @@ resource "ibm_resource_group" "resourceGroup" { ``` +## Timeouts + +The `ibm_resource_group` resource provides the following [Timeouts](https://www.terraform.io/docs/language/resources/syntax.html) configuration options: + +- **delete** - (Default 20 minutes) Used for deleting resource group. + ## Argument reference Review the argument references that you can specify for your resource. diff --git a/website/docs/r/resource_instance.html.markdown b/website/docs/r/resource_instance.html.markdown index bcf881ad9c..06757e0765 100644 --- a/website/docs/r/resource_instance.html.markdown +++ b/website/docs/r/resource_instance.html.markdown @@ -33,6 +33,24 @@ resource "ibm_resource_instance" "resource_instance" { } } ``` + +## Example to provision a Cloud Logs instance +``` +resource "ibm_resource_instance" "logs_instance" { + name = "logs-instance" + service = "logs" + plan = "standard" + location = "eu-de" + parameters = { + retention_period = "14" + logs_bucket_crn = "crn:v1:bluemix:public:cloud-object-storage:global:a/4448261269a14562b839e0a3019ed980:f8b3176e-af8e-4e14-a2f9-7f82634e7f0b:bucket:logs-bucket" + logs_bucket_endpoint = "s3.direct.eu-de.cloud-object-storage.appdomain.cloud" + metrics_bucket_crn = "crn:v1:bluemix:public:cloud-object-storage:global:a/4448261269a14562b839e0a3019ed980:f8b3176e-af8e-4e14-a2f9-7f82634e7f0b:bucket:metrics-bucket" + metrics_bucket_endpoint = "s3.direct.eu-de.cloud-object-storage.appdomain.cloud" + } +} +``` + ### Example to provision a Hyper Protect DBaaS service instance The following example enables you to create a service instance of IBM Cloud Hyper Protect DBaaS for MongoDB. For detailed argument reference, see the tables in the [Hyper Protect DBaaS for MongoDB documentation](https://cloud.ibm.com/docs/hyper-protect-dbaas-for-mongodb?topic=hyper-protect-dbaas-for-mongodb-create-service&interface=cli#cli-create-service), or the [Hyper Protect DBaaS for PostgreSQL documentation](https://cloud.ibm.com/docs/hyper-protect-dbaas-for-postgresql?topic=hyper-protect-dbaas-for-postgresql-create-service&interface=cli#cli-create-service) to create PostgreSQL service instances. @@ -213,3 +231,4 @@ In addition to all argument reference list, you can access the following attribu - `type` - (String) The type of the instance. For example, `service_instance`. - `update_at` - (Timestamp) The date when the instance last updated. - `update_by` - (String) The subject who updated the instance. +- `onetime_credentials` - (Bool) A boolean that dictates if the onetime_credentials is true or false. diff --git a/website/docs/r/resource_key.html.markdown b/website/docs/r/resource_key.html.markdown index 09c047b696..bbaf88816c 100644 --- a/website/docs/r/resource_key.html.markdown +++ b/website/docs/r/resource_key.html.markdown @@ -165,6 +165,7 @@ In addition to all argument reference list, you can access the following attribu - `updated_at` - (Timestamp) The date when the key was last updated. - `updated_by` - (String) The subject who updated the key. - `url` - (String) When you created a new key, a relative URL path is created identifying the location of the key. +- `onetime_credentials` - (Bool) A boolean that dictates if the onetime_credentials is true or false. ## Note Credentials will be seen as redacted, if the user does not have access equal to or greater than the access of the service credentials. Please refer to the documentation to access credentials - https://cloud.ibm.com/docs/account?topic=account-service_credentials&interface=ui#viewing-credentials-ui. diff --git a/website/docs/r/satellite_location.html.markdown b/website/docs/r/satellite_location.html.markdown index 7ccb830858..842993c80e 100644 --- a/website/docs/r/satellite_location.html.markdown +++ b/website/docs/r/satellite_location.html.markdown @@ -23,6 +23,8 @@ data "ibm_resource_group" "group" { resource "ibm_satellite_location" "create_location" { location = var.location + physical_address = "Example-road 10, 11011 Example-place, Example-country" + capabilities = ["on-prem"] zones = var.location_zones managed_from = var.managed_from resource_group_id = data.ibm_resource_group.group.id @@ -85,6 +87,8 @@ Review the argument references that you can specify for your resource. Nested scheme for `cos_credentials`: - `access_key-id` - (Required, String)The `HMAC` secret access key ID. - `secret_access_key`- (Optional, String) The `HMAC` secret access key. +- `physical_address` - (Optional, String) The physical address of the new Satellite location which is deployed on premise. +- `capabilities` - (Optional, Array of Strings) Satellite capabilities attached to the location. It is mandatory to add the value 'on-prem' to 'capabilities' (in the Kubernetes Service API, the parameter 'capabilities' is called['capabilitiesManagedBySatellite'](https://cloud.ibm.com/apidocs/kubernetes/containers-v1-v2#createsatellitelocation)), if a value has been set for 'physicalAddress'. On the other hand, value can be added to 'capabilitiesManagedBySatellite' without setting any value to 'physicalAddress'. In other words, 'capabilitiesManagedBySatellite' is optional, unless 'physicalAddress' gets set. - `description` - (Optional, String) A description of the new Satellite location. - `is_location_exist`- (Optional, Bool) Determines the location has to be created or not. - `location` - (Required, String) The name of the location to be created or pass existing location name. diff --git a/website/docs/r/scc_control_library.html.markdown b/website/docs/r/scc_control_library.html.markdown index 138ecc2a60..9e54077668 100644 --- a/website/docs/r/scc_control_library.html.markdown +++ b/website/docs/r/scc_control_library.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Create, update, and delete control libraries by using this resource. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/r/scc_instance_settings.html.markdown b/website/docs/r/scc_instance_settings.html.markdown index 0c0b5c1f51..35f6fc9a91 100644 --- a/website/docs/r/scc_instance_settings.html.markdown +++ b/website/docs/r/scc_instance_settings.html.markdown @@ -10,6 +10,8 @@ subcategory: "Security and Compliance Center" Create, update, and delete scc_instance_settingss with this resource. +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). + ## Example Usage ```hcl diff --git a/website/docs/r/scc_profile.html.markdown b/website/docs/r/scc_profile.html.markdown index 2305dd3cdd..0c16e5411d 100644 --- a/website/docs/r/scc_profile.html.markdown +++ b/website/docs/r/scc_profile.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Create, update, and delete profiles with this resource. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage @@ -78,7 +78,7 @@ Nested schema for **controls**: * `control_category` - (Optional, String) The control category. * Constraints: The maximum length is `512` characters. The minimum length is `2` characters. The value must match regular expression `/[A-Za-z0-9]+/`. * `control_description` - (Optional, String) The control description. - * Constraints: The maximum length is `1024` characters. The minimum length is `2` characters. The value must match regular expression `/[A-Za-z0-9]+/`. + * Constraints: The maximum length is `1024` characters. The minimum length is `2` characters. The value must match regular expression `[A-Za-z0-9]+//`. * `control_docs` - (Optional, List) The control documentation. Nested schema for **control_docs**: * `control_docs_id` - (Optional, String) The ID of the control documentation. @@ -153,6 +153,7 @@ Nested schema for **default_parameters**: * Constraints: The maximum length is `256` characters. The minimum length is `2` characters. The value must match regular expression `/[A-Za-z0-9]+/`. * `profile_name` - (Required, String) The profile name. * Constraints: The maximum length is `64` characters. The minimum length is `2` characters. The value must match regular expression `/[A-Za-z0-9]+/`. +* `profile_version` - (Optional, String) The version of the profile to set. The value must match regular expression `/\d+\.\d+\.\d+/`. * `profile_type` - (Required, String) The profile type, such as custom or predefined. * Constraints: Allowable values are: `predefined`, `custom`. diff --git a/website/docs/r/scc_profile_attachment.html.markdown b/website/docs/r/scc_profile_attachment.html.markdown index aa45f0575d..2b7abc7ffb 100644 --- a/website/docs/r/scc_profile_attachment.html.markdown +++ b/website/docs/r/scc_profile_attachment.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Create, update, and delete profile attachments with this resource. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/r/scc_provider_type_instance.html.markdown b/website/docs/r/scc_provider_type_instance.html.markdown index 1e4e281548..b9a813fd95 100644 --- a/website/docs/r/scc_provider_type_instance.html.markdown +++ b/website/docs/r/scc_provider_type_instance.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Create, update, and delete provider type instances with this resource. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage diff --git a/website/docs/r/scc_rule.html.markdown b/website/docs/r/scc_rule.html.markdown index 969767b8b1..b703685d9d 100644 --- a/website/docs/r/scc_rule.html.markdown +++ b/website/docs/r/scc_rule.html.markdown @@ -10,7 +10,7 @@ subcategory: "Security and Compliance Center" Create, update, and delete rules with this resource. -~> NOTE: if you specify the `region` in the provider, that region will become the default URL. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will override any URL(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://us-south.compliance.cloud.ibm.com`). +~> NOTE: Security Compliance Center is a regional service. Please specify the IBM Cloud Provider attribute `region` to target another region. Else, exporting the environmental variable IBMCLOUD_SCC_API_ENDPOINT will also override which region is being targeted for all ibm providers(ex. `export IBMCLOUD_SCC_API_ENDPOINT=https://eu-es.compliance.cloud.ibm.com`). ## Example Usage @@ -50,6 +50,95 @@ resource "ibm_scc_rule" "scc_rule_instance" { version = "1.0.0" } ``` +```hcl +resource "ibm_scc_rule" "scc_rule_instance" { + instance_id = "00000000-1111-2222-3333-444444444444" + description = "This rule will determine if a cloud object storage bucket is configured my way" + version = "1.0.0" + import { + parameters { + name = "name" + display_name = "display_name" + description = "description" + type = "string" + } + } + target { + service_name = "cloud-object-storage" + resource_kind = "bucket" + additional_target_attributes { + name = "location" + operator = "string_equals" + value = "$${name}" + } + } + required_config { + and { + or { + description = "description 1" + property = "storage_class" + operator = "string_equals" + value = "smart" + } + or { + description = "description 2" + property = "storage_class" + operator = "string_equals" + value = "cold" + } + or { + description = "description 3" + property = "firewall.allowed_ip" + operator = "ips_equals" + value = jsonencode(["0.0.0.0/0"]) + } + } + } + labels = ["FIXME"] + } +``` +```hcl +resource "ibm_scc_rule" "scc_rule_instance" { + instance_id = "00000000-1111-2222-3333-444444444444" + description = "This rule will determine if Activity Tracker is correctly configured" + version = "0.1.0" + target { + service_name = "atracker" + resource_kind = "target" + reference_name = "this-target" + additional_target_attributes { + name = "type" + operator = "string_equals" + value = "cloud_object_storage" + } + } + required_config { + or { + property = "route_attached" + operator = "is_false" + } + or { + any_if { + target { + service_name = "cloud-object-storage" + resource_kind = "bucket" + additional_target_attributes { + name = "location" + operator = "strings_in_list" + value = "$${this-target}.bucket_name" + } + } + required_config { + property = "location" + operator = "strings_in_list" + value = jsonencode(["us-south","us-east"]) + } + } + } + } + labels = ["FIXME"] + } +``` ## Timeouts @@ -67,109 +156,182 @@ You can specify the following arguments for this resource. * `description` - (Required, String) The details of a rule's response. * Constraints: The maximum length is `512` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. * `import` - (Optional, List) The collection of import parameters. -Nested schema for **import**: + + Nested schema for **import**: * `parameters` - (Optional, List) The list of import parameters. * Constraints: The maximum length is `8` items. The minimum length is `0` items. + Nested schema for **parameters**: - * `description` - (Optional, String) The propery description. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `display_name` - (Optional, String) The display name of the property. - * Constraints: The maximum length is `64` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `name` - (Optional, String) The import parameter name. - * Constraints: The maximum length is `64` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `type` - (Optional, String) The property type. - * Constraints: Allowable values are: `string`, `numeric`, `general`, `boolean`, `string_list`, `ip_list`, `timestamp`. The maximum length is `11` characters. The minimum length is `6` characters. The value must match regular expression `/[A-Za-z]+/`. + * `description` - (Optional, String) The propery description. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. + * `display_name` - (Optional, String) The display name of the property. + * Constraints: The maximum length is `64` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. + * `name` - (Optional, String) The import parameter name. + * Constraints: The maximum length is `64` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. + * `type` - (Optional, String) The property type. + * Constraints: Allowable values are: `string`, `numeric`, `general`, `boolean`, `string_list`, `ip_list`, `timestamp`. The maximum length is `11` characters. The minimum length is `6` characters. The value must match regular expression `/[A-Za-z]+/`. * `labels` - (Optional, List) The list of labels. * Constraints: The list items must match regular expression `/[A-Za-z0-9]+/`. The maximum length is `32` items. The minimum length is `0` items. -* `required_config` - (Required, List) The required configurations. -Nested schema for **required_config**: - * `and` - (Optional, List) The `AND` required configurations. - * Constraints: The maximum length is `64` items. The minimum length is `1` item. - Nested schema for **and**: - * `and` - (Optional, List) The `AND` required configurations. - * Constraints: The maximum length is `64` items. The minimum length is `1` item. - Nested schema for **and**: - * `description` - (Optional, String) The required config description. - * Constraints: The maximum length is `512` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `operator` - (Required, String) The operator. - * Constraints: Allowable values are: `string_equals`, `string_not_equals`, `string_match`, `string_not_match`, `string_contains`, `string_not_contains`, `num_equals`, `num_not_equals`, `num_less_than`, `num_less_than_equals`, `num_greater_than`, `num_greater_than_equals`, `is_empty`, `is_not_empty`, `is_true`, `is_false`, `strings_in_list`, `strings_allowed`, `strings_required`, `ips_in_range`, `ips_equals`, `ips_not_equals`, `days_less_than`. The maximum length is `23` characters. The minimum length is `7` characters. - * `property` - (Required, String) The property. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `value` - (Optional, String) Schema for any JSON type. - * `description` - (Optional, String) The required config description. - * Constraints: The maximum length is `512` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `operator` - (Optional, String) The operator. - * Constraints: Allowable values are: `string_equals`, `string_not_equals`, `string_match`, `string_not_match`, `string_contains`, `string_not_contains`, `num_equals`, `num_not_equals`, `num_less_than`, `num_less_than_equals`, `num_greater_than`, `num_greater_than_equals`, `is_empty`, `is_not_empty`, `is_true`, `is_false`, `strings_in_list`, `strings_allowed`, `strings_required`, `ips_in_range`, `ips_equals`, `ips_not_equals`, `days_less_than`. The maximum length is `23` characters. The minimum length is `7` characters. - * `or` - (Optional, List) The `OR` required configurations. - * Constraints: The maximum length is `64` items. The minimum length is `1` item. - Nested schema for **or**: - * `description` - (Optional, String) The required config description. - * Constraints: The maximum length is `512` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `operator` - (Required, String) The operator. - * Constraints: Allowable values are: `string_equals`, `string_not_equals`, `string_match`, `string_not_match`, `string_contains`, `string_not_contains`, `num_equals`, `num_not_equals`, `num_less_than`, `num_less_than_equals`, `num_greater_than`, `num_greater_than_equals`, `is_empty`, `is_not_empty`, `is_true`, `is_false`, `strings_in_list`, `strings_allowed`, `strings_required`, `ips_in_range`, `ips_equals`, `ips_not_equals`, `days_less_than`. The maximum length is `23` characters. The minimum length is `7` characters. - * `property` - (Required, String) The property. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `value` - (Optional, String) Schema for any JSON type. - * `property` - (Optional, String) The property. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `value` - (Optional, String) Schema for any JSON type. - * `description` - (Optional, String) The required config description. - * Constraints: The maximum length is `512` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `operator` - (Optional, String) The operator. - * Constraints: Allowable values are: `string_equals`, `string_not_equals`, `string_match`, `string_not_match`, `string_contains`, `string_not_contains`, `num_equals`, `num_not_equals`, `num_less_than`, `num_less_than_equals`, `num_greater_than`, `num_greater_than_equals`, `is_empty`, `is_not_empty`, `is_true`, `is_false`, `strings_in_list`, `strings_allowed`, `strings_required`, `ips_in_range`, `ips_equals`, `ips_not_equals`, `days_less_than`. The maximum length is `23` characters. The minimum length is `7` characters. - * `or` - (Optional, List) The `OR` required configurations. - * Constraints: The maximum length is `64` items. The minimum length is `1` item. - Nested schema for **or**: - * `and` - (Optional, List) The `AND` required configurations. - * Constraints: The maximum length is `64` items. The minimum length is `1` item. - Nested schema for **and**: - * `description` - (Optional, String) The required config description. - * Constraints: The maximum length is `512` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `operator` - (Required, String) The operator. - * Constraints: Allowable values are: `string_equals`, `string_not_equals`, `string_match`, `string_not_match`, `string_contains`, `string_not_contains`, `num_equals`, `num_not_equals`, `num_less_than`, `num_less_than_equals`, `num_greater_than`, `num_greater_than_equals`, `is_empty`, `is_not_empty`, `is_true`, `is_false`, `strings_in_list`, `strings_allowed`, `strings_required`, `ips_in_range`, `ips_equals`, `ips_not_equals`, `days_less_than`. The maximum length is `23` characters. The minimum length is `7` characters. - * `property` - (Required, String) The property. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `value` - (Optional, String) Schema for any JSON type. - * `description` - (Optional, String) The required config description. - * Constraints: The maximum length is `512` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `operator` - (Optional, String) The operator. - * Constraints: Allowable values are: `string_equals`, `string_not_equals`, `string_match`, `string_not_match`, `string_contains`, `string_not_contains`, `num_equals`, `num_not_equals`, `num_less_than`, `num_less_than_equals`, `num_greater_than`, `num_greater_than_equals`, `is_empty`, `is_not_empty`, `is_true`, `is_false`, `strings_in_list`, `strings_allowed`, `strings_required`, `ips_in_range`, `ips_equals`, `ips_not_equals`, `days_less_than`. The maximum length is `23` characters. The minimum length is `7` characters. - * `or` - (Optional, List) The `OR` required configurations. - * Constraints: The maximum length is `64` items. The minimum length is `1` item. - Nested schema for **or**: - * `description` - (Optional, String) The required config description. - * Constraints: The maximum length is `512` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `operator` - (Required, String) The operator. - * Constraints: Allowable values are: `string_equals`, `string_not_equals`, `string_match`, `string_not_match`, `string_contains`, `string_not_contains`, `num_equals`, `num_not_equals`, `num_less_than`, `num_less_than_equals`, `num_greater_than`, `num_greater_than_equals`, `is_empty`, `is_not_empty`, `is_true`, `is_false`, `strings_in_list`, `strings_allowed`, `strings_required`, `ips_in_range`, `ips_equals`, `ips_not_equals`, `days_less_than`. The maximum length is `23` characters. The minimum length is `7` characters. - * `property` - (Required, String) The property. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `value` - (Optional, String) Schema for any JSON type. - * `property` - (Optional, String) The property. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `value` - (Optional, String) Schema for any JSON type. - * `property` - (Optional, String) The property. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `value` - (Optional, String) Schema for any JSON type. -* `target` - (Required, List) The rule target. -Nested schema for **target**: - * `additional_target_attributes` - (Optional, List) The list of targets supported properties. - * Constraints: The maximum length is `99999` items. The minimum length is `0` items. - Nested schema for **additional_target_attributes**: - * `name` - (Optional, String) The additional target attribute name. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `operator` - (Optional, String) The operator. - * Constraints: Allowable values are: `string_equals`, `string_not_equals`, `string_match`, `string_not_match`, `string_contains`, `string_not_contains`, `num_equals`, `num_not_equals`, `num_less_than`, `num_less_than_equals`, `num_greater_than`, `num_greater_than_equals`, `is_empty`, `is_not_empty`, `is_true`, `is_false`, `strings_in_list`, `strings_allowed`, `strings_required`, `ips_in_range`, `ips_equals`, `ips_not_equals`, `days_less_than`. - * `value` - (Optional, String) The value. - * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `resource_kind` - (Required, String) The target resource kind. - * Constraints: The maximum length is `99999` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `service_display_name` - (Optional, String) The display name of the target service. - * Constraints: The maximum length is `64` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. - * `service_name` - (Required, String) The target service name. - * Constraints: The maximum length is `64` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. +* `required_config` - (Required, List) The specified settings by which your target service will be evaluated against. See the [required_config](#required_config) section for more details. +* `target` - (Required, List) The service or resource used in the assessment. See [rule_target](#rule_target) for more details. * `version` - (Optional, String) The version number of a rule. * Constraints: The maximum length is `10` characters. The minimum length is `5` characters. The value must match regular expression `/^[0-9][0-9.]*$/`. +### required_config +The `required_config` is specified setting by which the target will be evaluated against. + +The `required_config` block supports any of the following schemas: + - [base_condition](#base_condtion) + - [list_condition](#list_condition) + - [sub_rule](#sub_rule) + +### base_condition +A base_condition is the basic object in `required_config` block. It details the expected specifications of a service/resource. + +```hcl +required_config { + property = "location" + operator = "strings_in_list" + description = "Must be in the region us-south or us-east" + value = jsonencode(["us-south","us-east"]) +} +``` + +* `description` - (Optional, String) The details of the expected setting. +* `property` - (Required, String) The property. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. +* `operator` - (Required, String) The operator. + * Constraints: Allowable values are: + * `string_equals` + * `string_not_equals` + * `string_match` + * `string_not_match` + * `string_contains` + * `string_not_contains` + * `num_equals` + * `num_not_equals` + * `num_less_than` + * `num_less_than_equals` + * `num_greater_than` + * `num_greater_than_equals` + * `is_empty` + * `is_not_empty` + * `is_true` + * `is_false` + * `strings_in_list` + * `strings_allowed` + * `strings_required` + * `ips_in_range` + * `ips_equals` + * `ips_not_equals` + * `days_less_than` + + The maximum length is `23` characters. The minimum length is `7` characters. +* `value` - (Optional, String) Value of the condition to satisfy. Target/Imports can be used here. + + ~> NOTE: If the value requires a list/array, please use the terraform function `jsonencode` + ```hcl + jsonencode(["us-south","us-east"]) + ``` + +### list_condition +A list_condition is a collection of `and/or` conditons. One or all condtions must be satisfied for the rule to be compliant. +```hcl +required_config { + ... + and { + property = "app_lb_pools_with_multiple_members_count" + operator = "num_not_equals" + value = "0" + } + and { + property = "app_lb_pools_without_multiple_members_count" + operator = "num_not_equals" + value = "0" + } +} +``` +One of the following attributes can be used to denote a list_condition +* `and` - (Optional, List) A list of conditions where all conditions listed must be satisfied. +* `or` - (Optional, List) A list of conditions where one condition listed must be satisfied. + +`and`, `or` supports a combination of the following schemas in the list: +* [base_condition](#base_condition) +* [list_condition](#list_condition) +* [sub_rule_condition](#sub_rule) + +### sub_rule +A sub_rule is a rule condition within a rule used to evaluate a target. +```hcl +required_config { + ... + any_if { + target { + service_name = "cloud-object-storage" + resource_kind = "bucket" + } + required_config { + property = "location" + operator = "strings_in_list" + value = jsonencode(["us-south","us-east"]) + } + } +} +``` +One of the following attributes can be used to denote a subrule: +* `all` - (Optional) A subrule where all targets must satisfy the settings specified in the `required_config` argument. If no targets are found during evaluation, the subrule condition will fail. +* `all_if` - (Optional) A subrule where all targets must satisfy the setting specified in the `required_config` argument. If no targets are found, the subrule condition will pass. +* `any` - (Optional) A subrule where one of the targets must satisfy the setting specified in the `required_config` argument. If no targets are found, the subrule condition will fail. +* `any_if` - (Optional) A subrule where one of the targets must satisfy the setting specified in the `required_config` argument. If no targets are found, the subrule condition will fail. + +The arguments for `all`, `all_if`, `any`, `any_if`: +* `target` - (Required) see the section [rule_target](#rule_target) for more details +* `required_config` - (Required) see the section [required_config](#required_config) for more details + +### rule_target +The `rule_target` is the target the rule is evaluating. This target can be a service or a resource. + +Nested schema for **rule_target**: +* `additional_target_attributes` - (Optional, List) The list of targets supported properties. + * Constraints: The maximum length is `99999` items. The minimum length is `0` items. + Nested schema for **additional_target_attributes**: + * `name` - (Optional, String) The additional target attribute name. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. + * `operator` - (Optional, String) The operator. + * Constraints: Allowable values are: + - `string_equals` + - `string_not_equals` + - `string_match` + - `string_not_match` + - `string_contains` + - `string_not_contains` + - `num_equals` + - `num_not_equals` + - `num_less_than` + - `num_less_than_equals` + - `num_greater_than` + - `num_greater_than_equals` + - `is_empty` + - `is_not_empty` + - `is_true` + - `is_false` + - `strings_in_list` + - `strings_allowed` + - `strings_required` + - `ips_in_range` + - `ips_equals` + - `ips_not_equals` + - `days_less_than` + * `value` - (Optional, String) The value. + * Constraints: The maximum length is `256` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. +* `resource_kind` - (Required, String) The target resource kind. + * Constraints: The maximum length is `99999` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. +* `reference_name` - (Optional, String) The variable that can be used in the `required_config`. +* `service_display_name` - (Optional, String) The display name of the target service. + * Constraints: The maximum length is `64` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. +* `service_name` - (Required, String) The target service name. + * Constraints: The maximum length is `64` characters. The minimum length is `0` characters. The value must match regular expression `/[A-Za-z0-9]+/`. + ## Attribute Reference After your resource is created, you can read values from the listed arguments and the following attributes. @@ -208,4 +370,4 @@ $ terraform import ibm_scc_rule.scc_rule / # Example ```bash $ terraform import ibm_scc_rule.scc_rule 00000000-1111-2222-3333-444444444444/00000000-1111-2222-3333-444444444444 -``` \ No newline at end of file +``` diff --git a/website/docs/r/sm_private_certificate_configuration_intermediate_ca.html.markdown b/website/docs/r/sm_private_certificate_configuration_intermediate_ca.html.markdown index 26e23c899f..cc9f8230ee 100644 --- a/website/docs/r/sm_private_certificate_configuration_intermediate_ca.html.markdown +++ b/website/docs/r/sm_private_certificate_configuration_intermediate_ca.html.markdown @@ -76,6 +76,24 @@ Review the argument reference that you can specify for your resource. * `ttl` - (Optional, String) Specifies the requested Time To Live (after which the certificate will be expired). The value can be provided as a string representation of a duration in hours (e.g. `24h`) or the number of seconds as a string (e.g. `86400`). The value cannot exceed the value of `max_ttl`. * `uri_sans` - (Optional, Forces new resource, String) The URI Subject Alternative Names to define for the CA certificate, in a comma-delimited list. * Constraints: The maximum length is `2048` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. +* `crypto_key` - (Optional, Forces new resource, List) The data that is associated with a cryptographic key. + Nested scheme for **crypto_key**: + * `provider` - (Required, Forces new resource, List) The data that is associated with a cryptographic provider. + Nested scheme for **provider**: + * `type` - (Required, Forces new resource, String) The type of cryptographic provider. + * Constraints: Allowable values are: `hyper_protect_crypto_services`. + * `instance_crn` - (Required, Forces new resource, String) The HPCS instance CRN. + * Constraints: The maximum length is `512` characters. The minimum length is `9` characters. The value must match regular expression `^crn:v[0-9](:([A-Za-z0-9-._~!$&'()*+,;=@/]|%[0-9A-Z]{2})*){8}$`. + * `pin_iam_credentials_secret_id` - (Required, Forces new resource, String) The secret Id of iam credentials with api key to access HPCS instance. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `private_keystore_id` - (Required, Forces new resource, String) The HPCS private key store space id. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `id` - (Optional, Forces new resource, String) The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `label` - (Optional, Forces new resource, String) The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified. + * Constraints: The maximum length is `255` characters. The minimum length is `1` characters. The value must match regular expression `/^[A-Za-z0-9._ /-]+$/`. + * `allow_generate_key` - (Optional, Forces new resource, Boolean) The indication of whether a new key is generated by the crypto provider if the given key name cannot be found. Default is `false`. + ## Attribute Reference @@ -88,19 +106,19 @@ In addition to all argument references listed, you can access the following attr * `crl_expiry_seconds` - (Integer) The time until the certificate revocation list (CRL) expires, in seconds. * `data` - (List) The configuration data of your Private Certificate. Nested scheme for **data**: - * `ca_chain` - (List) The chain of certificate authorities that are associated with the certificate. - * Constraints: The list items must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. The maximum length is `16` items. The minimum length is `1` item. - * `certificate` - (Forces new resource, String) The PEM-encoded contents of your certificate. - * Constraints: The maximum length is `100000` characters. The minimum length is `50` characters. The value must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. - * `csr` - (Forces new resource, String) The certificate signing request. - * Constraints: The maximum length is `4096` characters. The minimum length is `2` characters. The value must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. - * `expiration` - (Integer) The certificate expiration time. - * `issuing_ca` - (String) The PEM-encoded certificate of the certificate authority that signed and issued this certificate. - * Constraints: The value must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. - * `private_key` - (Forces new resource, String) (Optional) The PEM-encoded private key to associate with the certificate. - * Constraints: The maximum length is `100000` characters. The minimum length is `50` characters. The value must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. - * `private_key_type` - (Forces new resource, String) The type of private key to generate. - * Constraints: Allowable values are: `rsa`, `ec`. + * `ca_chain` - (List) The chain of certificate authorities that are associated with the certificate. + * Constraints: The list items must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. The maximum length is `16` items. The minimum length is `1` item. + * `certificate` - (Forces new resource, String) The PEM-encoded contents of your certificate. + * Constraints: The maximum length is `100000` characters. The minimum length is `50` characters. The value must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. + * `csr` - (Forces new resource, String) The certificate signing request. + * Constraints: The maximum length is `4096` characters. The minimum length is `2` characters. The value must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. + * `expiration` - (Integer) The certificate expiration time. + * `issuing_ca` - (String) The PEM-encoded certificate of the certificate authority that signed and issued this certificate. + * Constraints: The value must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. + * `private_key` - (Forces new resource, String) (Optional) The PEM-encoded private key to associate with the certificate. + * Constraints: The maximum length is `100000` characters. The minimum length is `50` characters. The value must match regular expression `/^(-{5}BEGIN.+?-{5}[\\s\\S]+-{5}END.+?-{5})$/`. + * `private_key_type` - (Forces new resource, String) The type of private key to generate. + * Constraints: Allowable values are: `rsa`, `ec`. * `max_ttl_seconds` - (Integer) The maximum time-to-live (TTL) for certificates that are created by this CA in seconds. * `secret_type` - (String) The secret type. Supported types are arbitrary, certificates (imported, public, and private), IAM credentials, key-value, and user credentials. * Constraints: Allowable values are: `arbitrary`, `imported_cert`, `public_cert`, `iam_credentials`, `kv`, `username_password`, `private_cert`. diff --git a/website/docs/r/sm_private_certificate_configuration_root_ca.html.markdown b/website/docs/r/sm_private_certificate_configuration_root_ca.html.markdown index f240feb528..389fb6b44a 100644 --- a/website/docs/r/sm_private_certificate_configuration_root_ca.html.markdown +++ b/website/docs/r/sm_private_certificate_configuration_root_ca.html.markdown @@ -73,6 +73,23 @@ Review the argument reference that you can specify for your resource. * Constraints: The maximum length is `10` characters. The minimum length is `2` characters. The value must match regular expression `/^[0-9]+[s,m,h,d]{0,1}$/`. * `uri_sans` - (Optional, Forces new resource, String) The URI Subject Alternative Names to define for the CA certificate, in a comma-delimited list. * Constraints: The maximum length is `2048` characters. The minimum length is `2` characters. The value must match regular expression `/(.*?)/`. +* `crypto_key` - (Optional, Forces new resource, List) The data that is associated with a cryptographic key. + Nested scheme for **crypto_key**: + * `provider` - (Required, Forces new resource, List) The data that is associated with a cryptographic provider. + Nested scheme for **provider**: + * `type` - (Required, Forces new resource, String) The type of cryptographic provider. + * Constraints: Allowable values are: `hyper_protect_crypto_services`. + * `instance_crn` - (Required, Forces new resource, String) The HPCS instance CRN. + * Constraints: The maximum length is `512` characters. The minimum length is `9` characters. The value must match regular expression `^crn:v[0-9](:([A-Za-z0-9-._~!$&'()*+,;=@/]|%[0-9A-Z]{2})*){8}$`. + * `pin_iam_credentials_secret_id` - (Required, Forces new resource, String) The secret Id of iam credentials with api key to access HPCS instance. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `private_keystore_id` - (Required, Forces new resource, String) The HPCS private key store space id. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `id` - (Optional, Forces new resource, String) The ID of a PKCS#11 key to use. If the key does not exist and generation is enabled, this ID is given to the generated key. If the key exists, and generation is disabled, then this ID is used to look up the key. This value or the crypto key label must be specified. + * Constraints: Value length should be 36. The value must match regular expression `/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/`. + * `label` - (Optional, Forces new resource, String) The label of the key to use. If the key does not exist and generation is enabled, this field is the label that is given to the generated key. If the key exists, and generation is disabled, then this label is used to look up the key. This value or the crypto key ID must be specified. + * Constraints: The maximum length is `255` characters. The minimum length is `1` characters. The value must match regular expression `/^[A-Za-z0-9._ /-]+$/`. + * `allow_generate_key` - (Optional, Forces new resource, Boolean) The indication of whether a new key is generated by the crypto provider if the given key name cannot be found. Default is `false`. ## Attribute Reference