diff --git a/.goreleaser.yml b/.goreleaser.yml index 816f3f4..dee94e4 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,5 +1,6 @@ # Visit https://goreleaser.com for documentation on how to customize this # behavior. +version: 2 before: hooks: # this is just an example and not a requirement for provider building/publishing diff --git a/docs/data-sources/architecture.md b/docs/data-sources/architecture.md index de2d4e7..179ce34 100644 --- a/docs/data-sources/architecture.md +++ b/docs/data-sources/architecture.md @@ -54,9 +54,9 @@ data "alz_architecture" "example" { alzroot = { policy_assignments = { mypolicy = { - parameters = jsonencode({ - parameterName = local.foo_resource_id - }) + parameters = { + parameterName = jsonencode({Value = local.foo_resource_id}) + } } } } @@ -76,6 +76,7 @@ data "alz_architecture" "example" { ### Optional - `policy_assignments_to_modify` (Attributes Map) A mested map of policy assignments to modify. The key is the management group id, and the value is an object with a single attribute, `policy_assignments`. This is another map. (see [below for nested schema](#nestedatt--policy_assignments_to_modify)) +- `policy_default_values` (Map of String) A map of default values to apply to policy assignments. The key is the default name as defined in the library, and the value is an JSON object containing a single `value` attribute with the values to apply. This to mitigate issues with the Terraform type system. E.g. `{ defaultName = jsonencode({ value = "value"}) }` - `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) ### Read-Only @@ -101,7 +102,7 @@ Optional: - `identity_ids` (Set of String) A set of zero or one identity ids to assign to the policy assignment. Required if `identity` is `UserAssigned`. **Do not** pass in computed values, instead construct the resource id yourself. - `non_compliance_messages` (Attributes Set) The non-compliance messages to use for the policy assignment. (see [below for nested schema](#nestedatt--policy_assignments_to_modify--policy_assignments--non_compliance_messages)) - `overrides` (Attributes List) The overrides for this policy assignment. There are a maximum of 10 overrides allowed per assignment. If specified here the overrides will replace the existing overrides. (see [below for nested schema](#nestedatt--policy_assignments_to_modify--policy_assignments--overrides)) -- `parameters` (String) The parameters to use for the policy assignment. **Note:** This is a JSON string, and not a map. This is because the parameter values have different types, which confuses the type system used by the provider sdk. Use `jsonencode()` to construct the map. The map keys must be strings, the values are `any` type. Example: `jsonencode({"param1": "value1", "param2": 2})` +- `parameters` (Map of String) The parameters to use for the policy assignment. The map key is the parameter name and the value is an JSON object containing a single `value` attribute with the values to apply. This to mitigate issues with the Terraform type system. E.g. `{ defaultName = jsonencode({ value = "value"}) }` - `resource_selectors` (Attributes List) The resource selectors to use for the policy assignment. A maximum of 10 resource selectors are allowed per assignment. If specified here the resource selectors will replace any existing resource selectors. (see [below for nested schema](#nestedatt--policy_assignments_to_modify--policy_assignments--resource_selectors)) diff --git a/go.mod b/go.mod index 1962f4a..17a3716 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module github.com/Azure/terraform-provider-alz -go 1.22.4 +go 1.22.5 require ( - github.com/Azure/alzlib v0.18.5 + github.com/Azure/alzlib v0.19.1 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization v1.0.0 @@ -11,9 +11,10 @@ require ( github.com/deckarep/golang-set/v2 v2.6.0 github.com/google/uuid v1.6.0 github.com/hashicorp/terraform-plugin-docs v0.19.4 - github.com/hashicorp/terraform-plugin-framework v1.9.0 + github.com/hashicorp/terraform-plugin-framework v1.10.0 + github.com/hashicorp/terraform-plugin-framework-jsontypes v0.1.0 github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1 - github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 github.com/hashicorp/terraform-plugin-go v0.23.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-testing v1.8.0 @@ -23,20 +24,20 @@ require ( require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.1 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect - github.com/BurntSushi/toml v1.2.1 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect - github.com/ProtonMail/go-crypto v1.1.0-alpha.2-proton // indirect + github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect - github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/bgentry/speakeasy v0.2.0 // indirect github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect github.com/brunoga/deep v1.2.4 // indirect - github.com/cloudflare/circl v1.3.8 // indirect + github.com/cloudflare/circl v1.3.9 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.17.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect @@ -55,21 +56,21 @@ require ( github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hc-install v0.7.0 // indirect - github.com/hashicorp/hcl/v2 v2.20.1 // indirect + github.com/hashicorp/hcl/v2 v2.21.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.21.0 // indirect github.com/hashicorp/terraform-json v0.22.1 // indirect - github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 // indirect + github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect - github.com/huandu/xstrings v1.4.0 // indirect + github.com/huandu/xstrings v1.5.0 // indirect github.com/imdario/mergo v0.3.15 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -80,26 +81,27 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/posener/complete v1.2.3 // indirect - github.com/shopspring/decimal v1.3.1 // indirect - github.com/spf13/cast v1.5.1 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/spf13/cast v1.6.0 // indirect github.com/ulikunitz/xz v0.5.12 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/yuin/goldmark v1.7.1 // indirect + github.com/yuin/goldmark v1.7.4 // indirect github.com/yuin/goldmark-meta v1.1.0 // indirect github.com/zclconf/go-cty v1.14.4 // indirect go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect - golang.org/x/mod v0.17.0 // indirect + golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect + golang.org/x/mod v0.19.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + golang.org/x/tools v0.23.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 3d9f54d..f020110 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/Azure/alzlib v0.18.5 h1:L67oskj7QZ+k95TCoZPCHiuVMZ4zJFOumDpvj3EGvq4= -github.com/Azure/alzlib v0.18.5/go.mod h1:yg4bwFNtD6lMnn4M8zxxkiTy5Q8LgiHkDKrweMwNS34= +github.com/Azure/alzlib v0.19.1 h1:3GNDrcLEJplAmClYFLibjJa4lzAkHUbfCsCM28bLWao= +github.com/Azure/alzlib v0.19.1/go.mod h1:KkgZ4UI7tvzLn5KvaTMJ4+2RD/RIaVhh8x88n/aWZ1s= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= @@ -18,8 +18,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1. github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0= github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -31,8 +31,8 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/ProtonMail/go-crypto v1.1.0-alpha.2-proton h1:HKz85FwoXx86kVtTvFke7rgHvq/HoloSUvW5semjFWs= -github.com/ProtonMail/go-crypto v1.1.0-alpha.2-proton/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton h1:0RXAi0EJFs81j+MMsqvHNuAUGWzeVfCO9LnHAfoQ8NA= +github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= @@ -42,16 +42,16 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= +github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/brunoga/deep v1.2.4 h1:Aj9E9oUbE+ccbyh35VC/NHlzzjfIVU69BXu2mt2LmL8= github.com/brunoga/deep v1.2.4/go.mod h1:GDV6dnXqn80ezsLSZ5Wlv1PdKAWAO4L5PnKYtv2dgaI= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= -github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI= -github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= +github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE= +github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -64,8 +64,8 @@ github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= @@ -120,8 +120,8 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hc-install v0.7.0 h1:Uu9edVqjKQxxuD28mR5TikkKDd/p55S8vzPC1659aBk= github.com/hashicorp/hc-install v0.7.0/go.mod h1:ELmmzZlGnEcqoUMKUuykHaPCIR1sYLYX+KSggWSKZuA= -github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc= -github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4= +github.com/hashicorp/hcl/v2 v2.21.0 h1:lve4q/o/2rqwYOgUg3y3V2YPyD1/zkCLGjIV74Jit14= +github.com/hashicorp/hcl/v2 v2.21.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ= @@ -132,16 +132,22 @@ github.com/hashicorp/terraform-plugin-docs v0.19.4 h1:G3Bgo7J22OMtegIgn8Cd/CaSey github.com/hashicorp/terraform-plugin-docs v0.19.4/go.mod h1:4pLASsatTmRynVzsjEhbXZ6s7xBlUw/2Kt0zfrq8HxA= github.com/hashicorp/terraform-plugin-framework v1.9.0 h1:caLcDoxiRucNi2hk8+j3kJwkKfvHznubyFsJMWfZqKU= github.com/hashicorp/terraform-plugin-framework v1.9.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM= +github.com/hashicorp/terraform-plugin-framework v1.10.0 h1:xXhICE2Fns1RYZxEQebwkB2+kXouLC932Li9qelozrc= +github.com/hashicorp/terraform-plugin-framework v1.10.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM= +github.com/hashicorp/terraform-plugin-framework-jsontypes v0.1.0 h1:b8vZYB/SkXJT4YPbT3trzE6oJ7dPyMy68+9dEDKsJjE= +github.com/hashicorp/terraform-plugin-framework-jsontypes v0.1.0/go.mod h1:tP9BC3icoXBz72evMS5UTFvi98CiKhPdXF6yLs1wS8A= github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1 h1:gm5b1kHgFFhaKFhm4h2TgvMUlNzFAtUqlcOWnWPm+9E= github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1/go.mod h1:MsjL1sQ9L7wGwzJ5RjcI6FzEMdyoBnw+XK8ZnOvQOLY= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg= +github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 h1:bxZfGo9DIUoLLtHMElsu+zwqI4IsMZQBRRy4iLzZJ8E= +github.com/hashicorp/terraform-plugin-framework-validators v0.13.0/go.mod h1:wGeI02gEhj9nPANU62F2jCaHjXulejm/X+af4PdZaNo= github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co= github.com/hashicorp/terraform-plugin-go v0.23.0/go.mod h1:1E3Cr9h2vMlahWMbsSEcNrOCxovCZhOOIXjFHbjc/lQ= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 h1:qHprzXy/As0rxedphECBEQAh3R4yp6pKksKHcqZx5G8= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0/go.mod h1:H+8tjs9TjV2w57QFVSMBQacf8k/E1XwLXGCARgViC6A= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 h1:kJiWGx2kiQVo97Y5IOGR4EMcZ8DtMswHhUuFibsCQQE= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0/go.mod h1:sl/UoabMc37HA6ICVMmGO+/0wofkVIRxf+BMb/dnoIg= github.com/hashicorp/terraform-plugin-testing v1.8.0 h1:wdYIgwDk4iO933gC4S8KbKdnMQShu6BXuZQPScmHvpk= github.com/hashicorp/terraform-plugin-testing v1.8.0/go.mod h1:o2kOgf18ADUaZGhtOl0YCkfIxg01MAiMATT2EtIHlZk= github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= @@ -151,8 +157,8 @@ github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv2 github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= -github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= @@ -182,8 +188,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -208,18 +214,20 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= -github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -239,14 +247,14 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= -github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= +github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -254,11 +262,11 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= 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-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -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/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -301,15 +309,17 @@ golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/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/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b h1:04+jVzTs2XBnOZcPsLnmrTGqltqJbZQ1Ey26hjYdQQ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 h1:SbSDUWW1PAO24TNpLdeheoYPd7kllICcLU52x6eD4kQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= diff --git a/internal/alztypes/policyparametertype.go b/internal/alztypes/policyparametertype.go deleted file mode 100644 index 72ee80d..0000000 --- a/internal/alztypes/policyparametertype.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package alztypes - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" - "github.com/hashicorp/terraform-plugin-go/tftypes" -) - -// Ensure the implementation satisfies the expected interfaces. -var _ basetypes.StringTypable = PolicyParameterType{} - -type PolicyParameterType struct { - basetypes.StringType - // ... potentially other fields ... -} - -// PolicyParameterMap is a map of string to any -// and is used to represent ARM policy parameter values. -type PolicyParameterMap map[string]any - -func (t PolicyParameterType) Equal(o attr.Type) bool { - other, ok := o.(PolicyParameterType) - - if !ok { - return false - } - - return t.StringType.Equal(other.StringType) -} - -func (t PolicyParameterType) String() string { - return "PolicyParameterType" -} - -func (t PolicyParameterType) ValueFromString(ctx context.Context, in basetypes.StringValue) (basetypes.StringValuable, diag.Diagnostics) { - // CustomStringValue defined in the value type section. - value := PolicyParameterValue{ - StringValue: in, - } - - return value, nil -} - -func (t PolicyParameterType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) { - attrValue, err := t.StringType.ValueFromTerraform(ctx, in) - - if err != nil { - return nil, err - } - - stringValue, ok := attrValue.(basetypes.StringValue) - - if !ok { - return nil, fmt.Errorf("unexpected value type of %T", attrValue) - } - - stringValuable, diags := t.ValueFromString(ctx, stringValue) - - if diags.HasError() { - return nil, fmt.Errorf("unexpected error converting StringValue to StringValuable: %v", diags) - } - - return stringValuable, nil -} - -func (t PolicyParameterType) ValueType(ctx context.Context) attr.Value { - // PolicyParameterType defined in the value type section. - return PolicyParameterValue{} -} - -// PolicyParameterType defined in the schema type section. -func (t PolicyParameterType) Validate(ctx context.Context, value tftypes.Value, valuePath path.Path) diag.Diagnostics { - if value.IsNull() || !value.IsKnown() { - return nil - } - - var diags diag.Diagnostics - var valueString string - - if err := value.As(&valueString); err != nil { - diags.AddAttributeError( - valuePath, - "Invalid Terraform Value", - "An unexpected error occurred while attempting to convert a Terraform value to a string. "+ - "This generally is an issue with the provider schema implementation. "+ - "Please contact the provider developers.\n\n"+ - "Path: "+valuePath.String()+"\n"+ - "Error: "+err.Error(), - ) - - return diags - } - - if !json.Valid([]byte(valueString)) { - diags.AddAttributeError( - valuePath, - "Invalid policy parameter value", - "An unexpected error occurred while attempting to convert a Terraform value to JSON. "+ - "This generally is an issue with the provider schema implementation. "+ - "Please contact the provider developers.\n\n"+ - "Path: "+valuePath.String()+"\n"+ - "Error: Invalid JSON", - ) - - return diags - } - - paramMap := new(PolicyParameterMap) - - if err := json.Unmarshal([]byte(valueString), paramMap); err != nil { - diags.AddAttributeError( - valuePath, - "Invalid policy parameter JSON", - "An unexpected error occurred while converting a string value that was expected to be a JSON representation of policy parameters. "+ - "The string value was expected to unmarshal to a :41map[string]any value, but it did not.\n\n"+ - "Path: "+valuePath.String()+"\n"+ - "Given Value: "+valueString+"\n"+ - "Error: "+err.Error(), - ) - - return diags - } - - return diags -} diff --git a/internal/alztypes/policyparametertype_test.go b/internal/alztypes/policyparametertype_test.go deleted file mode 100644 index d653e37..0000000 --- a/internal/alztypes/policyparametertype_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package alztypes_test - -import ( - "context" - "fmt" - "testing" - - "github.com/Azure/terraform-provider-alz/internal/alztypes" - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" - "github.com/hashicorp/terraform-plugin-go/tftypes" - "github.com/stretchr/testify/assert" -) - -func TestValueFromString(t *testing.T) { - var ppt alztypes.PolicyParameterType - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - str := `{"param": "value"}` - sv := basetypes.NewStringValue(str) - _, diags := ppt.ValueFromString(ctx, sv) - assert.False(t, diags.HasError()) -} - -func TestValidate(t *testing.T) { - var ppt alztypes.PolicyParameterType - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - pa := path.Root("test") - str := `{"param": "value"}` - tfval := tftypes.NewValue(tftypes.String, str) - diags := ppt.Validate(ctx, tfval, pa) - assert.Falsef(t, diags.HasError(), "diags: %v", diags) -} - -func TestValidateInvalidJson(t *testing.T) { - var ppt alztypes.PolicyParameterType - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - pa := path.Root("test") - str := `{"param": "value"` - tfval := tftypes.NewValue(tftypes.String, str) - diags := ppt.Validate(ctx, tfval, pa) - assert.True(t, diags.HasError()) - assert.Contains(t, fmt.Sprintf("%v", diags), "An unexpected error occurred while attempting to convert a Terraform value to JSON") -} - -func TestValidateInvalidStringConversion(t *testing.T) { - var ppt alztypes.PolicyParameterType - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - pa := path.Root("test") - tfval := tftypes.NewValue(tftypes.Bool, true) - diags := ppt.Validate(ctx, tfval, pa) - assert.True(t, diags.HasError()) - assert.Contains(t, fmt.Sprintf("%v", diags), "An unexpected error occurred while attempting to convert a Terraform value to a string") -} - -func TestValidateInvalidJsonSchema(t *testing.T) { - var ppt alztypes.PolicyParameterType - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - pa := path.Root("test") - str := `["value1", "value2"]` - tfval := tftypes.NewValue(tftypes.String, str) - diags := ppt.Validate(ctx, tfval, pa) - assert.True(t, diags.HasError(), "diags: %v", diags) - assert.Contains(t, fmt.Sprintf("%v", diags), "An unexpected error occurred while converting a string value that was expected to be a JSON representation of policy parameters") -} diff --git a/internal/alztypes/policyparametervaluetype.go b/internal/alztypes/policyparametervaluetype.go deleted file mode 100644 index 9626d96..0000000 --- a/internal/alztypes/policyparametervaluetype.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package alztypes - -import ( - "context" - "encoding/json" - "fmt" - "reflect" - - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" -) - -// Ensure the implementation satisfies the expected interfaces. -var _ basetypes.StringValuable = PolicyParameterValue{} - -type PolicyParameterValue struct { - basetypes.StringValue - // ... potentially other fields ... -} - -func (v PolicyParameterValue) Map() (PolicyParameterMap, error) { - var policyParameterMap PolicyParameterMap - - if err := json.Unmarshal([]byte(v.StringValue.ValueString()), &policyParameterMap); err != nil { - return nil, fmt.Errorf("unable to parse the PolicyParameterValue as a policyParameterMap JSON object: %w", err) - } - - return policyParameterMap, nil -} - -func (v PolicyParameterValue) Equal(o attr.Value) bool { - other, ok := o.(PolicyParameterValue) - - if !ok { - return false - } - - return v.StringValue.Equal(other.StringValue) -} - -func (v PolicyParameterValue) Type(ctx context.Context) attr.Type { - // CustomStringType defined in the schema type section. - return PolicyParameterType{} -} - -// PolicyParameterValue defined in the value type section. -// Ensure the implementation satisfies the expected interfaces. -var _ basetypes.StringValuableWithSemanticEquals = PolicyParameterValue{} - -func (v PolicyParameterValue) StringSemanticEquals(ctx context.Context, newValuable basetypes.StringValuable) (bool, diag.Diagnostics) { - var diags diag.Diagnostics - - // The framework should always pass the correct value type, but always check. - newValue, ok := newValuable.(PolicyParameterValue) - - if !ok { - diags.AddError( - "Semantic Equality Check Error", - "An unexpected value type was received while performing semantic equality checks. "+ - "Please report this to the provider developers.\n\n"+ - "Expected Value Type: "+fmt.Sprintf("%T", v)+"\n"+ - "Got Value Type: "+fmt.Sprintf("%T", newValuable), - ) - - return false, diags - } - - unmarshalMap := make(map[PolicyParameterValue]*PolicyParameterMap, 2) - unmarshalMap[v] = new(PolicyParameterMap) - unmarshalMap[newValue] = new(PolicyParameterMap) - - for ppv, ppm := range unmarshalMap { - if err := json.Unmarshal([]byte(ppv.StringValue.ValueString()), ppm); err != nil { - diags.AddError( - "Semantic Equality Check Error", - "Unable to parse the PolicyParameterValue as a policyParameterMap JSON object. "+ - "Please report this to the provider developers.\n\n"+ - "Error: "+err.Error(), - ) - return false, diags - } - } - - // If the times are equivalent, keep the prior value. - return reflect.DeepEqual(unmarshalMap[v], unmarshalMap[newValue]), diags -} diff --git a/internal/alztypes/policyparametervaluetype_test.go b/internal/alztypes/policyparametervaluetype_test.go deleted file mode 100644 index e723e2a..0000000 --- a/internal/alztypes/policyparametervaluetype_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package alztypes_test - -import ( - "context" - "testing" - - "github.com/Azure/terraform-provider-alz/internal/alztypes" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" - "github.com/stretchr/testify/assert" -) - -func TestStringSemanticEquals(t *testing.T) { - str := `{"param": "value"}` - ppv := alztypes.PolicyParameterValue{ - basetypes.NewStringValue(str), - } - - var ppt alztypes.PolicyParameterType - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - str2 := `{"param": "value"}` - sv := basetypes.NewStringValue(str2) - strv2, diags := ppt.ValueFromString(ctx, sv) - assert.False(t, diags.HasError()) - - equal, diags := ppv.StringSemanticEquals(ctx, strv2) - assert.False(t, diags.HasError()) - assert.True(t, equal) -} - -func TestStringSemanticEqualsOutOfOrder(t *testing.T) { - got := `{"param2": "value2", "param1": 1}` - ppv := alztypes.PolicyParameterValue{ - basetypes.NewStringValue(got), - } - - var ppt alztypes.PolicyParameterType - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - want := `{"param1": 1, "param2": "value2"}` - sv := basetypes.NewStringValue(want) - strv2, diags := ppt.ValueFromString(ctx, sv) - assert.False(t, diags.HasError()) - - equal, diags := ppv.StringSemanticEquals(ctx, strv2) - assert.False(t, diags.HasError()) - assert.True(t, equal) -} diff --git a/internal/provider/architecture_data_source.go b/internal/provider/architecture_data_source.go index e077d41..e2c0f62 100644 --- a/internal/provider/architecture_data_source.go +++ b/internal/provider/architecture_data_source.go @@ -2,7 +2,6 @@ package provider import ( "context" - "encoding/json" "fmt" "math/big" "time" @@ -10,7 +9,6 @@ import ( "github.com/Azure/alzlib/deployment" "github.com/Azure/alzlib/to" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armpolicy" - "github.com/Azure/terraform-provider-alz/internal/alztypes" "github.com/Azure/terraform-provider-alz/internal/provider/gen" "github.com/Azure/terraform-provider-alz/internal/typehelper" "github.com/Azure/terraform-provider-alz/internal/typehelper/frameworktype" @@ -45,9 +43,7 @@ func (d *architectureDataSource) Configure(ctx context.Context, req datasource.C if req.ProviderData == nil { return } - data, ok := req.ProviderData.(*alzProviderData) - if !ok { resp.Diagnostics.AddError( "architectureDataSource.Configure() Unexpected type", @@ -55,7 +51,6 @@ func (d *architectureDataSource) Configure(ctx context.Context, req datasource.C ) return } - d.alz = data } @@ -94,42 +89,25 @@ func (d *architectureDataSource) Read(ctx context.Context, req datasource.ReadRe return } - // Modify policy assignments - for mgName, pa2modValue := range data.PolicyAssignmentsToModify.Elements() { - pa2mod, ok := pa2modValue.(gen.PolicyAssignmentsToModifyValue) - if !ok { + // Set policy assignment defaults + defaultsMap := convertPolicyAssignmentParametersMapToSdkType(data.PolicyDefaultValues, resp) + if resp.Diagnostics.HasError() { + return + } + for defName, paramVal := range defaultsMap { + if err := depl.AddDefaultPolicyAssignmentValue(ctx, defName, paramVal); err != nil { resp.Diagnostics.AddError( - "architectureDataSource.Read() Error converting policy assignments to modify", - "Error converting policy assignments to modify element to `gen.PolicyAssignmentsToModifyValue`", + fmt.Sprintf("architectureDataSource.Read() Error applying policy assignment default `%s`", defName), + err.Error(), ) return } - for paName, modValue := range pa2mod.PolicyAssignments.Elements() { - mod, ok := modValue.(gen.PolicyAssignmentsValue) - if !ok { - resp.Diagnostics.AddError( - "architectureDataSource.Read() Error converting policy assignment to modify", - "Error converting policy assignments element to `gen.PolicyAssignmentsValue`", - ) - return - } - enf, ident, noncompl, params, resourceSel, overrides, diags := policyAssignmentType2ArmPolicyValues(ctx, mod) - resp.Diagnostics.Append(diags...) - if diags.HasError() { - resp.Diagnostics.AddError( - "architectureDataSource.Read() Error converting policy assignment values to Azure SDK types", - fmt.Sprintf("Error modifying policy assignment values for `%s` at mg `%s`", paName, mgName), - ) - return - } - if err := depl.ManagementGroup(mgName).ModifyPolicyAssignment(paName, params, enf, noncompl, ident, resourceSel, overrides); err != nil { - resp.Diagnostics.AddError( - "architectureDataSource.Read() Error modifying policy assignment values in alzlib", - fmt.Sprintf("Error modifying policy assignment values for `%s` at mg `%s`: %s", paName, mgName, err.Error()), - ) - return - } - } + } + + // Modify policy assignments + modifyPolicyAssignments(ctx, depl, data, resp) + if resp.Diagnostics.HasError() { + return } // Generate policy role assignments @@ -170,6 +148,44 @@ func (d *architectureDataSource) Read(ctx context.Context, req datasource.ReadRe resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } +func modifyPolicyAssignments(ctx context.Context, depl *deployment.Hierarchy, data gen.ArchitectureModel, resp *datasource.ReadResponse) { + for mgName, pa2modValue := range data.PolicyAssignmentsToModify.Elements() { + pa2mod, ok := pa2modValue.(gen.PolicyAssignmentsToModifyValue) + if !ok { + resp.Diagnostics.AddError( + "architectureDataSource.Read() Error converting policy assignments to modify", + "Error converting policy assignments to modify element to `gen.PolicyAssignmentsToModifyValue`", + ) + return + } + for paName, modValue := range pa2mod.PolicyAssignments.Elements() { + mod, ok := modValue.(gen.PolicyAssignmentsValue) + if !ok { + resp.Diagnostics.AddError( + "architectureDataSource.Read() Error converting policy assignment to modify", + "Error converting policy assignments element to `gen.PolicyAssignmentsValue`", + ) + return + } + enf, ident, noncompl, params, resourceSel, overrides := policyAssignmentType2ArmPolicyValues(ctx, mod, resp) + if resp.Diagnostics.HasError() { + resp.Diagnostics.AddError( + "architectureDataSource.Read() Error converting policy assignment values to Azure SDK types", + fmt.Sprintf("Error modifying policy assignment values for `%s` at mg `%s`", paName, mgName), + ) + return + } + if err := depl.ManagementGroup(mgName).ModifyPolicyAssignment(paName, params, enf, noncompl, ident, resourceSel, overrides); err != nil { + resp.Diagnostics.AddError( + "architectureDataSource.Read() Error modifying policy assignment values in alzlib", + fmt.Sprintf("Error modifying policy assignment values for `%s` at mg `%s`: %s", paName, mgName, err.Error()), + ) + return + } + } + } +} + func policyRoleAssignmentsSetToProviderType(ctx context.Context, input []deployment.PolicyRoleAssignment) (basetypes.SetValue, diag.Diagnostics) { var diags diag.Diagnostics praSlice := make([]gen.PolicyRoleAssignmentsValue, 0, len(input)) @@ -227,23 +243,20 @@ func alzMgToProviderType(ctx context.Context, mg *deployment.HierarchyManagement // policyAssignmentType2ArmPolicyValues returns a set of Azure Go SDK values from a PolicyAssignmentType. // This is used to modify existing policy assignments. -func policyAssignmentType2ArmPolicyValues(ctx context.Context, pa gen.PolicyAssignmentsValue) ( +func policyAssignmentType2ArmPolicyValues(ctx context.Context, pa gen.PolicyAssignmentsValue, resp *datasource.ReadResponse) ( enforcementMode *armpolicy.EnforcementMode, identity *armpolicy.Identity, nonComplianceMessages []*armpolicy.NonComplianceMessage, parameters map[string]*armpolicy.ParameterValuesValue, resourceSelectors []*armpolicy.ResourceSelector, - overrides []*armpolicy.Override, - diags diag.Diagnostics) { - var diag diag.Diagnostics + overrides []*armpolicy.Override) { // Set enforcement mode. enforcementMode = convertPolicyAssignmentEnforcementModeToSdkType(pa.EnforcementMode) // set identity - identity, diag = convertPolicyAssignmentIdentityToSdkType(pa.Identity, pa.IdentityIds) - diags.Append(diag...) - if diags.HasError() { - return nil, nil, nil, nil, nil, nil, diags + identity = convertPolicyAssignmentIdentityToSdkType(pa.Identity, pa.IdentityIds, resp) + if resp.Diagnostics.HasError() { + return nil, nil, nil, nil, nil, nil } // set non-compliance message @@ -252,60 +265,51 @@ func policyAssignmentType2ArmPolicyValues(ctx context.Context, pa gen.PolicyAssi for i, msg := range pa.NonComplianceMessages.Elements() { frameworkMsg, ok := msg.(gen.NonComplianceMessagesValue) if !ok { - diags.AddError( + resp.Diagnostics.AddError( "policyAssignmentType2ArmPolicyValues: error", "unable to convert non-compliance message attr.Value to concrete type", ) } nonCompl[i] = frameworkMsg } - if diags.HasError() { - return nil, nil, nil, nil, nil, nil, diags + if resp.Diagnostics.HasError() { + return nil, nil, nil, nil, nil, nil } nonComplianceMessages = convertPolicyAssignmentNonComplianceMessagesToSdkType(nonCompl) } // set parameters - params := alztypes.PolicyParameterValue{ - StringValue: types.StringValue(pa.Parameters.ValueString()), - } - parameters, diag = convertPolicyAssignmentParametersToSdkType(params) - diags.Append(diag...) - if diag.HasError() { - return nil, nil, nil, nil, nil, nil, diags + parameters = convertPolicyAssignmentParametersMapToSdkType(pa.Parameters, resp) + if resp.Diagnostics.HasError() { + return nil, nil, nil, nil, nil, nil } // set resource selectors if isKnown(pa.ResourceSelectors) { rS := make([]gen.ResourceSelectorsValue, len(pa.ResourceSelectors.Elements())) - diag = pa.ResourceSelectors.ElementsAs(ctx, &rS, false) - diags.Append(diag...) - resourceSelectors, diag = convertPolicyAssignmentResourceSelectorsToSdkType(ctx, rS) - diags.Append(diag...) - if diags.HasError() { - return nil, nil, nil, nil, nil, nil, diags + resp.Diagnostics.Append(pa.ResourceSelectors.ElementsAs(ctx, &rS, false)...) + resourceSelectors = convertPolicyAssignmentResourceSelectorsToSdkType(ctx, rS, resp) + if resp.Diagnostics.HasError() { + return nil, nil, nil, nil, nil, nil } } // set overrides if isKnown(pa.Overrides) { ovr := make([]gen.OverridesValue, len(pa.Overrides.Elements())) - diag = pa.Overrides.ElementsAs(ctx, &ovr, false) - diags.Append(diag...) - overrides, diag = convertPolicyAssignmentOverridesToSdkType(ctx, ovr) - diags.Append(diag...) - if diags.HasError() { - return nil, nil, nil, nil, nil, nil, diags + resp.Diagnostics.Append(pa.Overrides.ElementsAs(ctx, &ovr, false)...) + overrides = convertPolicyAssignmentOverridesToSdkType(ctx, ovr, resp) + if resp.Diagnostics.HasError() { + return nil, nil, nil, nil, nil, nil } } - return enforcementMode, identity, nonComplianceMessages, parameters, resourceSelectors, overrides, nil + return enforcementMode, identity, nonComplianceMessages, parameters, resourceSelectors, overrides } -func convertPolicyAssignmentOverridesToSdkType(ctx context.Context, input []gen.OverridesValue) ([]*armpolicy.Override, diag.Diagnostics) { - var diags diag.Diagnostics +func convertPolicyAssignmentOverridesToSdkType(ctx context.Context, input []gen.OverridesValue, resp *datasource.ReadResponse) []*armpolicy.Override { if len(input) == 0 { - return nil, nil + return nil } res := make([]*armpolicy.Override, len(input)) for i, o := range input { @@ -313,26 +317,26 @@ func convertPolicyAssignmentOverridesToSdkType(ctx context.Context, input []gen. for j, s := range o.OverrideSelectors.Elements() { osv, ok := s.(gen.OverrideSelectorsValue) if !ok { - diags.AddError( + resp.Diagnostics.AddError( "convertPolicyAssignmentOverridesToSdkType: error", "unable to convert override selectors attr.Value to concrete type", ) } in, err := frameworktype.SliceOfPrimitiveToGo[string](ctx, osv.In.Elements()) if err != nil { - diags.AddError( + resp.Diagnostics.AddError( "convertPolicyAssignmentOverridesToSdkType: error", fmt.Sprintf("unable to convert OverrideSelctorsValue.In elements to Go slice: %s", err.Error()), ) - return nil, diags + return nil } notIn, err := frameworktype.SliceOfPrimitiveToGo[string](ctx, osv.NotIn.Elements()) if err != nil { - diags.AddError( + resp.Diagnostics.AddError( "convertPolicyAssignmentOverridesToSdkType: error", fmt.Sprintf("unable to convert OverrideSelctorsValue.NotIn elements to Go slice: %s", err.Error()), ) - return nil, diags + return nil } selectors[j] = &armpolicy.Selector{ Kind: to.Ptr(armpolicy.SelectorKind(osv.Kind.ValueString())), @@ -346,13 +350,12 @@ func convertPolicyAssignmentOverridesToSdkType(ctx context.Context, input []gen. Selectors: selectors, } } - return res, nil + return res } -func convertPolicyAssignmentResourceSelectorsToSdkType(ctx context.Context, input []gen.ResourceSelectorsValue) ([]*armpolicy.ResourceSelector, diag.Diagnostics) { - var diags diag.Diagnostics +func convertPolicyAssignmentResourceSelectorsToSdkType(ctx context.Context, input []gen.ResourceSelectorsValue, resp *datasource.ReadResponse) []*armpolicy.ResourceSelector { if len(input) == 0 { - return nil, nil + return nil } res := make([]*armpolicy.ResourceSelector, len(input)) for i, rs := range input { @@ -360,26 +363,26 @@ func convertPolicyAssignmentResourceSelectorsToSdkType(ctx context.Context, inpu for j, s := range rs.ResourceSelectorSelectors.Elements() { rssv, ok := s.(gen.ResourceSelectorSelectorsValue) if !ok { - diags.AddError( + resp.Diagnostics.AddError( "convertPolicyAssignmentResourceSelectorsToSdkType: error", "unable to convert resource selector selectors attr.Value to concrete type", ) } in, err := frameworktype.SliceOfPrimitiveToGo[string](ctx, rssv.In.Elements()) if err != nil { - diags.AddError( + resp.Diagnostics.AddError( "convertPolicyAssignmentResourceSelectorsToSdkType: error", fmt.Sprintf("unable to convert ResourceSelectorSelectorsValue.In elements to Go slice: %s", err.Error()), ) - return nil, diags + return nil } notIn, err := frameworktype.SliceOfPrimitiveToGo[string](ctx, rssv.NotIn.Elements()) if err != nil { - diags.AddError( + resp.Diagnostics.AddError( "convertPolicyAssignmentResourceSelectorsToSdkType: error", fmt.Sprintf("unable to convert ResourceSelectorSelectorsValue.NotIn elements to Go slice: %s", err.Error()), ) - return nil, diags + return nil } selectors[j] = &armpolicy.Selector{ Kind: to.Ptr(armpolicy.SelectorKind(rssv.Kind.ValueString())), @@ -392,7 +395,7 @@ func convertPolicyAssignmentResourceSelectorsToSdkType(ctx context.Context, inpu Selectors: selectors, } } - return res, nil + return res } func convertPolicyAssignmentEnforcementModeToSdkType(src types.String) *armpolicy.EnforcementMode { @@ -425,10 +428,9 @@ func convertPolicyAssignmentNonComplianceMessagesToSdkType(src []gen.NonComplian return res } -func convertPolicyAssignmentIdentityToSdkType(typ types.String, ids types.Set) (*armpolicy.Identity, diag.Diagnostics) { - var diags diag.Diagnostics +func convertPolicyAssignmentIdentityToSdkType(typ types.String, ids types.Set, resp *datasource.ReadResponse) *armpolicy.Identity { if !isKnown(typ) { - return nil, nil + return nil } var identity *armpolicy.Identity switch typ.ValueString() { @@ -438,23 +440,23 @@ func convertPolicyAssignmentIdentityToSdkType(typ types.String, ids types.Set) ( }) case "UserAssigned": if ids.IsUnknown() { - return nil, nil + return nil } var id string if len(ids.Elements()) != 1 { - diags.AddError( + resp.Diagnostics.AddError( "convertPolicyAssignmentIdentityToSdkType: error", "one (and only one) identity id is required for user assigned identity", ) - return nil, diags + return nil } idStr, ok := ids.Elements()[0].(types.String) if !ok { - diags.AddError( + resp.Diagnostics.AddError( "convertPolicyAssignmentIdentityToSdkType: error", "unable to convert identity id to string", ) - return nil, diags + return nil } id = idStr.ValueString() @@ -463,39 +465,53 @@ func convertPolicyAssignmentIdentityToSdkType(typ types.String, ids types.Set) ( UserAssignedIdentities: map[string]*armpolicy.UserAssignedIdentitiesValue{id: {}}, }) default: - diags.AddError( + resp.Diagnostics.AddError( "convertPolicyAssignmentIdentityToSdkType: error", fmt.Sprintf("unknown identity type: %s", typ.ValueString()), ) - return nil, diags + return nil } - return identity, nil + return identity } -// convertPolicyAssignmentParametersToSdkType converts a map[string]any to a map[string]*armpolicy.ParameterValuesValue. -func convertPolicyAssignmentParametersToSdkType(src alztypes.PolicyParameterValue) (map[string]*armpolicy.ParameterValuesValue, diag.Diagnostics) { - var diags diag.Diagnostics +// convertPolicyAssignmentParametersMapToSdkType converts a map with a JSON string value to a map[string]*armpolicy.ParameterValuesValue. +func convertPolicyAssignmentParametersMapToSdkType(src types.Map, resp *datasource.ReadResponse) map[string]*armpolicy.ParameterValuesValue { if !isKnown(src) { - return nil, nil - } - params := make(map[string]any) - if err := json.Unmarshal([]byte(src.ValueString()), ¶ms); err != nil { - diags.AddError( - "convertPolicyAssignmentParametersToSdkType: error", - fmt.Sprintf("convertPolicyAssignmentParametersToSdkType: unable to unmarshal policy parameters: %s", err.Error()), - ) - return nil, diags - } - if len(params) == 0 { - return nil, nil + return nil } - res := make(map[string]*armpolicy.ParameterValuesValue, len(params)) - for k, v := range params { - val := new(armpolicy.ParameterValuesValue) - val.Value = v - res[k] = val + result := make(map[string]*armpolicy.ParameterValuesValue) + for k, v := range src.Elements() { + // Even thought he schema type is identical, from policy assignments to modify we receive basetypes.String values, + // but from policy default values we receive jsontypes.Noprmalized. + // We convert to Terraform value to get the string representation. + vTf, _ := v.ToTerraformValue(context.Background()) + var vStr string + err := vTf.Copy().As(&vStr) + if err != nil { + resp.Diagnostics.AddError( + "convertPolicyAssignmentParametersMapToSdkType: error", + "unable to convert parameter value to jsontypes.Normalized", + ) + return nil + } + var pv armpolicy.ParameterValuesValue + if err := pv.UnmarshalJSON([]byte(vStr)); err != nil { + resp.Diagnostics.AddError( + "convertPolicyAssignmentParametersMapToSdkType: error", + fmt.Sprintf("unable to unmarshal policy parameter value: %s", err.Error()), + ) + return nil + } + if pv.Value == nil { + resp.Diagnostics.AddError( + "convertPolicyAssignmentParametersMapToSdkType: error", + fmt.Sprintf("policy parameter `%s` value is nil, make sure to supply parameter value as follows: `jsonencode({ value = \"foo\" })`, or `jsonencode({ value = 1 })`", k), + ) + return nil + } + result[k] = &pv } - return res, nil + return result } func isKnown(val attr.Value) bool { diff --git a/internal/provider/architecture_data_source_test.go b/internal/provider/architecture_data_source_test.go index 6f89478..abbd413 100644 --- a/internal/provider/architecture_data_source_test.go +++ b/internal/provider/architecture_data_source_test.go @@ -7,19 +7,20 @@ import ( "github.com/Azure/alzlib/deployment" "github.com/Azure/alzlib/to" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armpolicy" - "github.com/Azure/terraform-provider-alz/internal/alztypes" "github.com/Azure/terraform-provider-alz/internal/provider/gen" mapset "github.com/deckarep/golang-set/v2" "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/stretchr/testify/assert" ) -// TestAccAlzArchetypeDataSource tests the data source for alz_archetype. -// It checks that the policy parameter substitution & location defaults are applied. -func TestAccAlzArchitectureDataSource(t *testing.T) { +// TestAccAlzArchitectureDataSourceRemoteLib tests the data source for alz_architecture +// when using a remote lib. +func TestAccAlzArchitectureDataSourceRemoteLib(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactoriesUnique(), @@ -31,28 +32,58 @@ func TestAccAlzArchitectureDataSource(t *testing.T) { }, Steps: []resource.TestStep{ { - Config: testAccArchitectureDataSourceConfig(), + Config: testAccArchitectureDataSourceConfigRemoteLib(), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.alz_architecture.test", "id", "alz"), - // resource.TestCheckOutput("test_location_replacement", "westeurope"), - // resource.TestCheckOutput("test_parameter_replacement", "test"), ), }, }, }) } -// testAccArchitectureDataSourceConfig returns a test configuration for TestAccAlzArchetypeDataSource. -func testAccArchitectureDataSourceConfig() string { - // cwd, _ := os.Getwd() - // libPath := filepath.Join(cwd, "testdata/testacc_lib") +// TestAccAlzArchetypeDataSource tests the data source for alz_archetype. +// It checks that the policy default values and the modification of policy assignments are correctly applied. +func TestAccAlzArchitectureDataSourceWithDefaultAndModify(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactoriesUnique(), + ExternalProviders: map[string]resource.ExternalProvider{ + "azapi": { + Source: "azure/azapi", + VersionConstraint: "~> 1.14", + }, + }, + Steps: []resource.TestStep{ + { + Config: testAccArchitectureDataSourceConfigWithDefaultAndModify(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.alz_architecture.test", "id", "test"), + resource.TestCheckOutput("log_analytics_replaced_by_policy_default_values", "replacedByDefaults"), + resource.TestCheckOutput("metrics_enabled_modified", "false"), + resource.TestCheckOutput("identity_type", "UserAssigned"), + resource.TestCheckOutput("identity_id", "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity"), + resource.TestCheckOutput("policy_assignment_override_kind", "policyEffect"), + resource.TestCheckOutput("policy_assignment_override_value", "disabled"), + resource.TestCheckOutput("policy_assignment_override_selector_kind", "policyDefinitionReferenceId"), + resource.TestCheckOutput("policy_assignment_override_selector_in", "test-policy-definition"), + resource.TestCheckOutput("policy_assignment_non_compliance_message", "testnoncompliancemessage"), + resource.TestCheckOutput("policy_assignment_resource_selector_name", "test-resource-selector"), + resource.TestCheckOutput("policy_assignment_resource_selector_kind", "resourceLocation"), + resource.TestCheckOutput("policy_assignment_resource_selector_in", "northeurope"), + ), + }, + }, + }) +} +// testAccArchitectureDataSourceConfigRemoteLib returns a test configuration for TestAccAlzArchetypeDataSource. +func testAccArchitectureDataSourceConfigRemoteLib() string { return ` provider "alz" { library_references = [ { path = "platform/alz" - ref = "2024.07.01" + ref = "2024.07.02" } ] } @@ -71,6 +102,129 @@ data "alz_architecture" "test" { ` } +// testAccArchitectureDataSourceConfigWithDefaultAndModify returns a test configuration for TestAccAlzArchetypeDataSource. +func testAccArchitectureDataSourceConfigWithDefaultAndModify() string { + return ` +provider "alz" { + library_references = [ + { + custom_url = "${path.root}/testdata/testacc_lib" + } + ] +} + +data "azapi_client_config" "current" {} + +data "alz_architecture" "test" { + name = "test" + root_management_group_id = data.azapi_client_config.current.tenant_id + location = "northeurope" + policy_default_values = { + test = jsonencode({ value = "replacedByDefaults" }) + } + policy_assignments_to_modify = { + test = { + policy_assignments = { + test-policy-assignment = { + identity = "UserAssigned" + identity_ids = [ + "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity" + ] + non_compliance_messages = [ + { + message = "testnoncompliancemessage" + } + ] + parameters = { + metricsEnabled = jsonencode({ value = false }) + } + resource_selectors = [ + { + name = "test-resource-selector" + resource_selector_selectors = [ + { + kind = "resourceLocation" + in = ["northeurope"] + } + ] + } + ] + overrides = [ + { + kind = "policyEffect" + value = "disabled" + override_selectors = [ + { + kind = "policyDefinitionReferenceId" + in = ["test-policy-definition"] + } + ] + } + ] + } + } + } + } + + timeouts { + read = "5m" + } +} + +locals { + test_policy_assignment_decoded = jsondecode(data.alz_architecture.test.management_groups[0].policy_assignments["test-policy-assignment"]) +} + +output "log_analytics_replaced_by_policy_default_values" { + value = local.test_policy_assignment_decoded.properties.parameters.logAnalytics.value +} + +output "metrics_enabled_modified" { + value = tostring(local.test_policy_assignment_decoded.properties.parameters.metricsEnabled.value) +} + +output "identity_type" { + value = local.test_policy_assignment_decoded.identity.type +} + +output "identity_id" { + value = keys(local.test_policy_assignment_decoded.identity.userAssignedIdentities)[0] +} + +output "policy_assignment_override_kind" { + value = local.test_policy_assignment_decoded.properties.overrides[0].kind +} + +output "policy_assignment_override_value" { + value = local.test_policy_assignment_decoded.properties.overrides[0].value +} + +output "policy_assignment_override_selector_kind" { + value = local.test_policy_assignment_decoded.properties.overrides[0].selectors[0].kind +} + +output "policy_assignment_override_selector_in" { + value = local.test_policy_assignment_decoded.properties.overrides[0].selectors[0].in[0] +} + +output "policy_assignment_non_compliance_message" { + value = local.test_policy_assignment_decoded.properties.nonComplianceMessages[0].message +} + +output "policy_assignment_resource_selector_name" { + value = local.test_policy_assignment_decoded.properties.resourceSelectors[0].name +} + +output "policy_assignment_resource_selector_kind" { + value = local.test_policy_assignment_decoded.properties.resourceSelectors[0].selectors[0].kind +} + +output "policy_assignment_resource_selector_in" { + value = local.test_policy_assignment_decoded.properties.resourceSelectors[0].selectors[0].in[0] +} +` +} + // TestConvertPolicyAssignmentResourceSelectorsToSdkType tests the conversion of policy assignment resource selectors from framework to Azure Go SDK types. func TestConvertPolicyAssignmentResourceSelectorsToSdkType(t *testing.T) { ctx := context.Background() @@ -84,9 +238,11 @@ func TestConvertPolicyAssignmentResourceSelectorsToSdkType(t *testing.T) { notSetStringType, _ := basetypes.NewSetValueFrom(ctx, types.BoolType, []bool{true}) t.Run("EmptyInput", func(t *testing.T) { + resp := new(datasource.ReadResponse) + resp.Diagnostics = diag.Diagnostics{} src := []gen.ResourceSelectorsValue{} - res, diags := convertPolicyAssignmentResourceSelectorsToSdkType(ctx, src) - assert.False(t, diags.HasError()) + res := convertPolicyAssignmentResourceSelectorsToSdkType(ctx, src, resp) + assert.False(t, resp.Diagnostics.HasError()) assert.Nil(t, res) }) @@ -146,9 +302,10 @@ func TestConvertPolicyAssignmentResourceSelectorsToSdkType(t *testing.T) { }, }, } - - res, diags := convertPolicyAssignmentResourceSelectorsToSdkType(ctx, src) - assert.False(t, diags.HasError()) + resp := new(datasource.ReadResponse) + resp.Diagnostics = diag.Diagnostics{} + res := convertPolicyAssignmentResourceSelectorsToSdkType(ctx, src, resp) + assert.False(t, resp.Diagnostics.HasError()) assert.Equal(t, expected, res) }) @@ -166,8 +323,10 @@ func TestConvertPolicyAssignmentResourceSelectorsToSdkType(t *testing.T) { } // Simulate an error during conversion - res, diags := convertPolicyAssignmentResourceSelectorsToSdkType(ctx, src) - assert.True(t, diags.HasError()) + resp := new(datasource.ReadResponse) + resp.Diagnostics = diag.Diagnostics{} + res := convertPolicyAssignmentResourceSelectorsToSdkType(ctx, src, resp) + assert.True(t, resp.Diagnostics.HasError()) assert.Nil(t, res) }) } @@ -177,38 +336,43 @@ func TestConvertPolicyAssignmentIdentityToSdkType(t *testing.T) { // Test with unknown identity type typ := types.StringValue("UnknownType") ids := basetypes.NewSetUnknown(types.StringType) - identity, diags := convertPolicyAssignmentIdentityToSdkType(typ, ids) + resp := new(datasource.ReadResponse) + resp.Diagnostics = diag.Diagnostics{} + identity := convertPolicyAssignmentIdentityToSdkType(typ, ids, resp) assert.Nil(t, identity) - assert.True(t, diags.HasError()) + assert.True(t, resp.Diagnostics.HasError()) + resp.Diagnostics = diag.Diagnostics{} // Test with SystemAssigned identity type typ = types.StringValue("SystemAssigned") ids = basetypes.NewSetNull(types.StringType) - identity, diags = convertPolicyAssignmentIdentityToSdkType(typ, ids) + identity = convertPolicyAssignmentIdentityToSdkType(typ, ids, resp) assert.NotNil(t, identity) - assert.False(t, diags.HasError()) + assert.False(t, resp.Diagnostics.HasError()) assert.Equal(t, armpolicy.ResourceIdentityTypeSystemAssigned, *identity.Type) // Test with UserAssigned identity type and empty ids typ = types.StringValue("UserAssigned") ids = basetypes.NewSetNull(types.StringType) - identity, diags = convertPolicyAssignmentIdentityToSdkType(typ, ids) + identity = convertPolicyAssignmentIdentityToSdkType(typ, ids, resp) assert.Nil(t, identity) - assert.True(t, diags.HasError()) + assert.True(t, resp.Diagnostics.HasError()) + resp.Diagnostics = diag.Diagnostics{} // Test with UserAssigned identity type and multiple ids typ = types.StringValue("UserAssigned") ids, _ = types.SetValueFrom(context.Background(), types.StringType, []string{"id1", "id2"}) - identity, diags = convertPolicyAssignmentIdentityToSdkType(typ, ids) + identity = convertPolicyAssignmentIdentityToSdkType(typ, ids, resp) assert.Nil(t, identity) - assert.True(t, diags.HasError()) + assert.True(t, resp.Diagnostics.HasError()) + resp.Diagnostics = diag.Diagnostics{} // Test with UserAssigned identity type and valid id typ = types.StringValue("UserAssigned") ids, _ = types.SetValueFrom(context.Background(), types.StringType, []string{"id1"}) - identity, diags = convertPolicyAssignmentIdentityToSdkType(typ, ids) + identity = convertPolicyAssignmentIdentityToSdkType(typ, ids, resp) assert.NotNil(t, identity) - assert.False(t, diags.HasError()) + assert.False(t, resp.Diagnostics.HasError()) assert.Equal(t, armpolicy.ResourceIdentityTypeUserAssigned, *identity.Type) assert.Len(t, identity.UserAssignedIdentities, 1) assert.Contains(t, identity.UserAssignedIdentities, "id1") @@ -263,28 +427,40 @@ func TestConvertPolicyAssignmentEnforcementModeToSdkType(t *testing.T) { // TestConvertPolicyAssignmentParametersToSdkType tests the convertPolicyAssignmentParametersToSdkType function. func TestConvertPolicyAssignmentParametersToSdkType(t *testing.T) { // Test with nil input - var src alztypes.PolicyParameterValue + var src types.Map var res map[string]*armpolicy.ParameterValuesValue - res, diags := convertPolicyAssignmentParametersToSdkType(src) - assert.False(t, diags.HasError()) + resp := new(datasource.ReadResponse) + resp.Diagnostics = diag.Diagnostics{} + res = convertPolicyAssignmentParametersMapToSdkType(src, resp) + assert.False(t, resp.Diagnostics.HasError()) assert.Nil(t, res) // Test with empty input - src = alztypes.PolicyParameterValue{} - res, diags = convertPolicyAssignmentParametersToSdkType(src) - assert.False(t, diags.HasError()) + src = types.MapNull(types.StringType) + res = convertPolicyAssignmentParametersMapToSdkType(src, resp) + assert.False(t, resp.Diagnostics.HasError()) assert.Nil(t, res) - // Test with non-empty input - params, _ := alztypes.PolicyParameterType{}.ValueFromString(context.Background(), types.StringValue(`{ - "param1": "value1", - "param2": 123, - "param3": true - }`)) - src = params.(alztypes.PolicyParameterValue) //nolint:forcetypeassert - - res, diags = convertPolicyAssignmentParametersToSdkType(src) - assert.False(t, diags.HasError()) + param1 := armpolicy.ParameterValuesValue{ + Value: to.Ptr("value1"), + } + param2 := armpolicy.ParameterValuesValue{ + Value: to.Ptr(123), + } + param3 := armpolicy.ParameterValuesValue{ + Value: to.Ptr(true), + } + param1Json, _ := param1.MarshalJSON() + param2Json, _ := param2.MarshalJSON() + param3Json, _ := param3.MarshalJSON() + src, _ = types.MapValueFrom(context.Background(), types.StringType, map[string]string{ + "param1": string(param1Json), + "param2": string(param2Json), + "param3": string(param3Json), + }) + + res = convertPolicyAssignmentParametersMapToSdkType(src, resp) + assert.False(t, resp.Diagnostics.HasError()) assert.NotNil(t, res) assert.Len(t, res, 3) assert.Equal(t, "value1", res["param1"].Value) @@ -294,12 +470,23 @@ func TestConvertPolicyAssignmentParametersToSdkType(t *testing.T) { func TestPolicyAssignmentType2ArmPolicyValues(t *testing.T) { ctx := context.Background() - paramsIn, _ := alztypes.PolicyParameterType{}.ValueFromString(ctx, types.StringValue(`{ - "param1": "value1", - "param2": 123, - "param3": true - }`)) - paramsInStr, _ := paramsIn.ToStringValue(ctx) + param1 := armpolicy.ParameterValuesValue{ + Value: to.Ptr("value1"), + } + param2 := armpolicy.ParameterValuesValue{ + Value: to.Ptr(123), + } + param3 := armpolicy.ParameterValuesValue{ + Value: to.Ptr(true), + } + param1Json, _ := param1.MarshalJSON() + param2Json, _ := param2.MarshalJSON() + param3Json, _ := param3.MarshalJSON() + params, _ := types.MapValueFrom(ctx, types.StringType, map[string]string{ + "param1": string(param1Json), + "param2": string(param2Json), + "param3": string(param3Json), + }) pa := gen.PolicyAssignmentsValue{ //nolint:forcetypeassert EnforcementMode: types.StringValue("DoNotEnforce"), NonComplianceMessages: types.SetValueMust( @@ -314,12 +501,13 @@ func TestPolicyAssignmentType2ArmPolicyValues(t *testing.T) { PolicyDefinitionReferenceId: types.StringValue("PolicyDefinition2"), }, }), - Parameters: paramsInStr, + Parameters: params, } + resp := new(datasource.ReadResponse) + resp.Diagnostics = diag.Diagnostics{} + enforcementMode, identity, nonComplianceMessages, parameters, _, _ := policyAssignmentType2ArmPolicyValues(ctx, pa, resp) - enforcementMode, identity, nonComplianceMessages, parameters, _, _, diags := policyAssignmentType2ArmPolicyValues(ctx, pa) - - assert.False(t, diags.HasError()) + assert.False(t, resp.Diagnostics.HasError()) assert.Equal(t, armpolicy.EnforcementModeDoNotEnforce, *enforcementMode) assert.Nil(t, identity) assert.Len(t, nonComplianceMessages, 2) diff --git a/internal/provider/gen/architecture_data_source_gen.go b/internal/provider/gen/architecture_data_source_gen.go index c521897..20a0fb3 100644 --- a/internal/provider/gen/architecture_data_source_gen.go +++ b/internal/provider/gen/architecture_data_source_gen.go @@ -5,8 +5,8 @@ package gen import ( "context" "fmt" - "github.com/Azure/terraform-provider-alz/internal/alztypes" "github.com/Azure/terraform-provider-alz/internal/alzvalidators" + "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" "github.com/hashicorp/terraform-plugin-framework-timeouts/datasource/timeouts" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" @@ -243,11 +243,11 @@ func ArchitectureDataSourceSchema(ctx context.Context) schema.Schema { listvalidator.UniqueValues(), }, }, - "parameters": schema.StringAttribute{ - CustomType: alztypes.PolicyParameterType{}, + "parameters": schema.MapAttribute{ + ElementType: jsontypes.NormalizedType{}, Optional: true, - Description: "The parameters to use for the policy assignment. **Note:** This is a JSON string, and not a map. This is because the parameter values have different types, which confuses the type system used by the provider sdk. Use `jsonencode()` to construct the map. The map keys must be strings, the values are `any` type. Example: `jsonencode({\"param1\": \"value1\", \"param2\": 2})`", - MarkdownDescription: "The parameters to use for the policy assignment. **Note:** This is a JSON string, and not a map. This is because the parameter values have different types, which confuses the type system used by the provider sdk. Use `jsonencode()` to construct the map. The map keys must be strings, the values are `any` type. Example: `jsonencode({\"param1\": \"value1\", \"param2\": 2})`", + Description: "The parameters to use for the policy assignment. The map key is the parameter name and the value is an JSON object containing a single `value` attribute with the values to apply. This to mitigate issues with the Terraform type system. E.g. `{ defaultName = jsonencode({ value = \"value\"}) }`", + MarkdownDescription: "The parameters to use for the policy assignment. The map key is the parameter name and the value is an JSON object containing a single `value` attribute with the values to apply. This to mitigate issues with the Terraform type system. E.g. `{ defaultName = jsonencode({ value = \"value\"}) }`", }, "resource_selectors": schema.ListNestedAttribute{ NestedObject: schema.NestedAttributeObject{ @@ -339,6 +339,12 @@ func ArchitectureDataSourceSchema(ctx context.Context) schema.Schema { Description: "A mested map of policy assignments to modify. The key is the management group id, and the value is an object with a single attribute, `policy_assignments`. This is another map.", MarkdownDescription: "A mested map of policy assignments to modify. The key is the management group id, and the value is an object with a single attribute, `policy_assignments`. This is another map.", }, + "policy_default_values": schema.MapAttribute{ + ElementType: jsontypes.NormalizedType{}, + Optional: true, + Description: "A map of default values to apply to policy assignments. The key is the default name as defined in the library, and the value is an JSON object containing a single `value` attribute with the values to apply. This to mitigate issues with the Terraform type system. E.g. `{ defaultName = jsonencode({ value = \"value\"}) }`", + MarkdownDescription: "A map of default values to apply to policy assignments. The key is the default name as defined in the library, and the value is an JSON object containing a single `value` attribute with the values to apply. This to mitigate issues with the Terraform type system. E.g. `{ defaultName = jsonencode({ value = \"value\"}) }`", + }, "policy_role_assignments": schema.SetNestedAttribute{ NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ @@ -405,6 +411,7 @@ type ArchitectureModel struct { ManagementGroups types.List `tfsdk:"management_groups"` Name types.String `tfsdk:"name"` PolicyAssignmentsToModify types.Map `tfsdk:"policy_assignments_to_modify"` + PolicyDefaultValues types.Map `tfsdk:"policy_default_values"` PolicyRoleAssignments types.Set `tfsdk:"policy_role_assignments"` RootManagementGroupId types.String `tfsdk:"root_management_group_id"` Timeouts timeouts.Value `tfsdk:"timeouts"` @@ -1786,12 +1793,12 @@ func (t PolicyAssignmentsType) ValueFromObject(ctx context.Context, in basetypes return nil, diags } - parametersVal, ok := parametersAttribute.(basetypes.StringValue) + parametersVal, ok := parametersAttribute.(basetypes.MapValue) if !ok { diags.AddError( "Attribute Wrong Type", - fmt.Sprintf(`parameters expected to be basetypes.StringValue, was: %T`, parametersAttribute)) + fmt.Sprintf(`parameters expected to be basetypes.MapValue, was: %T`, parametersAttribute)) } resourceSelectorsAttribute, ok := attributes["resource_selectors"] @@ -1991,12 +1998,12 @@ func NewPolicyAssignmentsValue(attributeTypes map[string]attr.Type, attributes m return NewPolicyAssignmentsValueUnknown(), diags } - parametersVal, ok := parametersAttribute.(basetypes.StringValue) + parametersVal, ok := parametersAttribute.(basetypes.MapValue) if !ok { diags.AddError( "Attribute Wrong Type", - fmt.Sprintf(`parameters expected to be basetypes.StringValue, was: %T`, parametersAttribute)) + fmt.Sprintf(`parameters expected to be basetypes.MapValue, was: %T`, parametersAttribute)) } resourceSelectorsAttribute, ok := attributes["resource_selectors"] @@ -2106,7 +2113,7 @@ type PolicyAssignmentsValue struct { IdentityIds basetypes.SetValue `tfsdk:"identity_ids"` NonComplianceMessages basetypes.SetValue `tfsdk:"non_compliance_messages"` Overrides basetypes.ListValue `tfsdk:"overrides"` - Parameters basetypes.StringValue `tfsdk:"parameters"` + Parameters basetypes.MapValue `tfsdk:"parameters"` ResourceSelectors basetypes.ListValue `tfsdk:"resource_selectors"` state attr.ValueState } @@ -2128,7 +2135,9 @@ func (v PolicyAssignmentsValue) ToTerraformValue(ctx context.Context) (tftypes.V attrTypes["overrides"] = basetypes.ListType{ ElemType: OverridesValue{}.Type(ctx), }.TerraformType(ctx) - attrTypes["parameters"] = basetypes.StringType{}.TerraformType(ctx) + attrTypes["parameters"] = basetypes.MapType{ + ElemType: types.StringType, + }.TerraformType(ctx) attrTypes["resource_selectors"] = basetypes.ListType{ ElemType: ResourceSelectorsValue{}.Type(ctx), }.TerraformType(ctx) @@ -2328,7 +2337,35 @@ func (v PolicyAssignmentsValue) ToObjectValue(ctx context.Context) (basetypes.Ob "overrides": basetypes.ListType{ ElemType: OverridesValue{}.Type(ctx), }, - "parameters": basetypes.StringType{}, + "parameters": basetypes.MapType{ + ElemType: types.StringType, + }, + "resource_selectors": basetypes.ListType{ + ElemType: ResourceSelectorsValue{}.Type(ctx), + }, + }), diags + } + + parametersVal, d := types.MapValue(types.StringType, v.Parameters.Elements()) + + diags.Append(d...) + + if d.HasError() { + return types.ObjectUnknown(map[string]attr.Type{ + "enforcement_mode": basetypes.StringType{}, + "identity": basetypes.StringType{}, + "identity_ids": basetypes.SetType{ + ElemType: types.StringType, + }, + "non_compliance_messages": basetypes.SetType{ + ElemType: NonComplianceMessagesValue{}.Type(ctx), + }, + "overrides": basetypes.ListType{ + ElemType: OverridesValue{}.Type(ctx), + }, + "parameters": basetypes.MapType{ + ElemType: types.StringType, + }, "resource_selectors": basetypes.ListType{ ElemType: ResourceSelectorsValue{}.Type(ctx), }, @@ -2347,7 +2384,9 @@ func (v PolicyAssignmentsValue) ToObjectValue(ctx context.Context) (basetypes.Ob "overrides": basetypes.ListType{ ElemType: OverridesValue{}.Type(ctx), }, - "parameters": basetypes.StringType{}, + "parameters": basetypes.MapType{ + ElemType: types.StringType, + }, "resource_selectors": basetypes.ListType{ ElemType: ResourceSelectorsValue{}.Type(ctx), }, @@ -2369,7 +2408,7 @@ func (v PolicyAssignmentsValue) ToObjectValue(ctx context.Context) (basetypes.Ob "identity_ids": identityIdsVal, "non_compliance_messages": nonComplianceMessages, "overrides": overrides, - "parameters": v.Parameters, + "parameters": parametersVal, "resource_selectors": resourceSelectors, }) @@ -2443,7 +2482,9 @@ func (v PolicyAssignmentsValue) AttributeTypes(ctx context.Context) map[string]a "overrides": basetypes.ListType{ ElemType: OverridesValue{}.Type(ctx), }, - "parameters": basetypes.StringType{}, + "parameters": basetypes.MapType{ + ElemType: types.StringType, + }, "resource_selectors": basetypes.ListType{ ElemType: ResourceSelectorsValue{}.Type(ctx), }, diff --git a/internal/provider/ir.json b/internal/provider/ir.json index 755bd12..501605f 100644 --- a/internal/provider/ir.json +++ b/internal/provider/ir.json @@ -778,15 +778,19 @@ }, { "name": "parameters", - "string": { - "description": "The parameters to use for the policy assignment. **Note:** This is a JSON string, and not a map. This is because the parameter values have different types, which confuses the type system used by the provider sdk. Use `jsonencode()` to construct the map. The map keys must be strings, the values are `any` type. Example: `jsonencode({\"param1\": \"value1\", \"param2\": 2})`", + "map": { + "description": "The parameters to use for the policy assignment. The map key is the parameter name and the value is an JSON object containing a single `value` attribute with the values to apply. This to mitigate issues with the Terraform type system. E.g. `{ defaultName = jsonencode({ value = \"value\"}) }`", "computed_optional_required": "optional", - "custom_type": { - "import": { - "path": "github.com/Azure/terraform-provider-alz/internal/alztypes" - }, - "type": "alztypes.PolicyParameterType{}", - "value_type": "alztypes.PolicyParameterValue" + "element_type": { + "string": { + "custom_type": { + "import": { + "path": "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" + }, + "type": "jsontypes.NormalizedType{}", + "value_type": "jsontypes.Normalized" + } + } } } } @@ -922,6 +926,24 @@ ] } } + }, + { + "name": "policy_default_values", + "map": { + "computed_optional_required": "optional", + "description": "A map of default values to apply to policy assignments. The key is the default name as defined in the library, and the value is an JSON object containing a single `value` attribute with the values to apply. This to mitigate issues with the Terraform type system. E.g. `{ defaultName = jsonencode({ value = \"value\"}) }`", + "element_type": { + "string": { + "custom_type": { + "import": { + "path": "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" + }, + "type": "jsontypes.NormalizedType{}", + "value_type": "jsontypes.Normalized" + } + } + } + } } ], "blocks": [ diff --git a/internal/provider/testdata/testacc_lib/archetype_definition_test.json b/internal/provider/testdata/testacc_lib/archetype_definition_test.json deleted file mode 100644 index 2dd7f12..0000000 --- a/internal/provider/testdata/testacc_lib/archetype_definition_test.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "test", - "policy_assignments": [ - "BlobServicesDiagnosticsLogsToWorkspace" - ], - "policy_definitions": [ - "BlobServicesDiagnosticsLogsToWorkspace" - ], - "policy_set_definitions": [], - "role_definitions": [] -} diff --git a/internal/provider/testdata/testacc_lib/test.alz_archetype_definition.yaml b/internal/provider/testdata/testacc_lib/test.alz_archetype_definition.yaml new file mode 100644 index 0000000..4c5da09 --- /dev/null +++ b/internal/provider/testdata/testacc_lib/test.alz_archetype_definition.yaml @@ -0,0 +1,10 @@ +--- +name: test +policy_assignments: + - test-policy-assignment +policy_definitions: + - test-policy-definition +policy_set_definitions: + - test-policy-set-definition +role_definitions: + - test-role-definition diff --git a/internal/provider/testdata/testacc_lib/test.alz_architecture_definition.yaml b/internal/provider/testdata/testacc_lib/test.alz_architecture_definition.yaml new file mode 100644 index 0000000..9e73efa --- /dev/null +++ b/internal/provider/testdata/testacc_lib/test.alz_architecture_definition.yaml @@ -0,0 +1,9 @@ +--- +name: test +management_groups: + - archetypes: + - test + display_name: test + exists: false + id: test + parent_id: null diff --git a/internal/provider/testdata/testacc_lib/policy_assignment_blob_services_to_la_workspace.json b/internal/provider/testdata/testacc_lib/test.alz_policy_assignment.json similarity index 66% rename from internal/provider/testdata/testacc_lib/policy_assignment_blob_services_to_la_workspace.json rename to internal/provider/testdata/testacc_lib/test.alz_policy_assignment.json index 8be8825..d97d115 100644 --- a/internal/provider/testdata/testacc_lib/policy_assignment_blob_services_to_la_workspace.json +++ b/internal/provider/testdata/testacc_lib/test.alz_policy_assignment.json @@ -1,7 +1,7 @@ { "type": "Microsoft.Authorization/policyAssignments", "apiVersion": "2022-06-01", - "name": "BlobServicesDiagnosticsLogsToWorkspace", + "name": "test-policy-assignment", "location": "${default_location}", "dependsOn": [], "identity": { @@ -10,15 +10,19 @@ "properties": { "description": "Deploys the diagnostic settings for Blob Services to stream resource logs to a Log Analytics workspace when any blob Service which is missing this diagnostic settings is created or updated.", "displayName": "Configure diagnostic settings for Blob Services to Log Analytics workspace", - "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/BlobServicesDiagnosticsLogsToWorkspace", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/test-policy-definition", "enforcementMode": null, "nonComplianceMessages": [ { "message": "Test {enforcementMode}" } ], - "parameters": {}, - "scope": "${current_scope_resource_id}", + "parameters": { + "logAnalytics": { + "value": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/PLACEHOLDER/providers/Microsoft.OperationalInsights/workspaces/PLACEHOLDER" + } + }, + "scope": "/providers/Microsoft.Management/managementGroups/PLACEHOLDER", "notScopes": [] } } diff --git a/internal/provider/testdata/testacc_lib/test.alz_policy_default_value.yaml b/internal/provider/testdata/testacc_lib/test.alz_policy_default_value.yaml new file mode 100644 index 0000000..791ee8e --- /dev/null +++ b/internal/provider/testdata/testacc_lib/test.alz_policy_default_value.yaml @@ -0,0 +1,5 @@ +--- +name: test +policy_assignments: + - policy_assignment_name: test-policy-assignment + parameter_names: ["logAnalytics"] diff --git a/internal/provider/testdata/testacc_lib/policy_definition_blob_services_to_la_workspace.json b/internal/provider/testdata/testacc_lib/test.alz_policy_definition.json similarity index 99% rename from internal/provider/testdata/testacc_lib/policy_definition_blob_services_to_la_workspace.json rename to internal/provider/testdata/testacc_lib/test.alz_policy_definition.json index 49f30a8..0b5dfc1 100644 --- a/internal/provider/testdata/testacc_lib/policy_definition_blob_services_to_la_workspace.json +++ b/internal/provider/testdata/testacc_lib/test.alz_policy_definition.json @@ -182,5 +182,5 @@ } }, "type": "Microsoft.Authorization/policyDefinitions", - "name": "BlobServicesDiagnosticsLogsToWorkspace" + "name": "test-policy-definition" } diff --git a/internal/provider/testdata/testacc_lib/policy_set_definition_test.json b/internal/provider/testdata/testacc_lib/test.alz_policy_set_definition.json similarity index 97% rename from internal/provider/testdata/testacc_lib/policy_set_definition_test.json rename to internal/provider/testdata/testacc_lib/test.alz_policy_set_definition.json index 0062af0..2ab895c 100644 --- a/internal/provider/testdata/testacc_lib/policy_set_definition_test.json +++ b/internal/provider/testdata/testacc_lib/test.alz_policy_set_definition.json @@ -1,5 +1,5 @@ { - "name": "test", + "name": "test-policy-set-definition", "type": "Microsoft.Authorization/policySetDefinitions", "apiVersion": "2021-06-01", "scope": null, diff --git a/internal/provider/testdata/testacc_lib/test.alz_role_definition.json b/internal/provider/testdata/testacc_lib/test.alz_role_definition.json new file mode 100644 index 0000000..62f53b7 --- /dev/null +++ b/internal/provider/testdata/testacc_lib/test.alz_role_definition.json @@ -0,0 +1,26 @@ +{ + "apiVersion": "2018-01-01-preview", + "name": "dc726155-3983-5405-b446-9bb27b94e02c", + "properties": { + "assignableScopes": [ + "/providers/Microsoft.Management/managementGroups/PLACEHOLDER" + ], + "description": "Platform-wide global connectivity management: virtual networks, UDRs, NSGs, NVAs, VPN, Azure ExpressRoute, and others", + "permissions": [ + { + "actions": [ + "*/read", + "Microsoft.Network/*", + "Microsoft.Resources/deployments/*", + "Microsoft.Support/*" + ], + "dataActions": [], + "notActions": [], + "notDataActions": [] + } + ], + "roleName": "test-role-definition", + "type": "customRole" + }, + "type": "Microsoft.Authorization/roleDefinitions" +} diff --git a/templates/data-sources/architecture.md.tmpl b/templates/data-sources/architecture.md.tmpl index de822c7..d0cc657 100644 --- a/templates/data-sources/architecture.md.tmpl +++ b/templates/data-sources/architecture.md.tmpl @@ -43,9 +43,9 @@ data "alz_architecture" "example" { alzroot = { policy_assignments = { mypolicy = { - parameters = jsonencode({ - parameterName = local.foo_resource_id - }) + parameters = { + parameterName = jsonencode({Value = local.foo_resource_id}) + } } } }