Fix the where case_insensitive and case_sensitive were being set - they should be left null by default.
see convertedFilterPredicate.CaseInsensitive = types.BoolValue(false) below
Remove NewPredicateModel it is unused.
Add validation to FilterPredicates.
Add Terraform Config validation to enforce case_sensitive and case_insensitive are not both set.
[X] List your changes here
[X] Make a changie entry
Tophatting
With this Terraform config (invalid):
resource "opslevel_filter" "example" {
name = "foobarbaz"
connective = "and"
predicate {
key = "language"
type = "contains"
value = "bar"
case_sensitive = true
case_insensitive = true
}
}
Run terraform validate
│ Error: Invalid Attribute Combination
│
│ with opslevel_filter.example,
│ on main.tf line 8, in resource "opslevel_filter" "example":
│ 8: case_sensitive = true
│
│ Attribute "predicate[0].case_insensitive" cannot be specified when "predicate[0].case_sensitive" is specified
╵
╷
│ Error: Invalid Attribute Combination
│
│ with opslevel_filter.example,
│ on main.tf line 9, in resource "opslevel_filter" "example":
│ 9: case_insensitive = true
│
│ Attribute "predicate[0].case_sensitive" cannot be specified when "predicate[0].case_insensitive" is specified
Update Terraform config (valid):
resource "opslevel_filter" "example" {
name = "foobarbaz"
connective = "and"
predicate {
key = "language"
type = "contains"
value = "bar"
case_sensitive = true
case_insensitive = null
}
}
Run terraform validate
Success! The configuration is valid.
With this Terraform config
resource "opslevel_filter" "example" {
name = "foobarbaz1"
connective = "and"
predicate {
key = "language"
type = "contains"
value = "barbaz"
case_sensitive = true
case_insensitive = null
}
predicate {
key = "tier_index"
type = "less_than_or_equal_to"
value = 3
}
predicate {
key = "language"
type = "exists"
value = null
}
}
resource "opslevel_check_tool_usage" "example" {
name = "TF V1 Upgrade part deux"
enabled = true
category = "Z2lkOi8vb3BzbGV2ZWwvQ2F0ZWdvcnkvNjk3Nw"
level = "Z2lkOi8vb3BzbGV2ZWwvTGV2ZWwvMzcxMA"
owner = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTI0Nw"
filter = "Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzM1NzA"
tool_category = "metrics"
tool_name_predicate = {
type = "equals"
value = "datadog"
}
environment_predicate = {
type = "exists"
value = null
}
notes = "Optional additional info on why this check is run or how to fix it"
}
Create Resources with Predicates terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# opslevel_check_tool_usage.example will be created
+ resource "opslevel_check_tool_usage" "example" {
+ category = "Z2lkOi8vb3BzbGV2ZWwvQ2F0ZWdvcnkvNjk3Nw"
+ description = (known after apply)
+ enabled = true
+ environment_predicate = {
+ type = "exists"
}
+ filter = "Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzM1NzA"
+ id = (known after apply)
+ level = "Z2lkOi8vb3BzbGV2ZWwvTGV2ZWwvMzcxMA"
+ name = "TF V1 Upgrade part deux"
+ notes = "Optional additional info on why this check is run or how to fix it"
+ owner = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTI0Nw"
+ tool_category = "metrics"
+ tool_name_predicate = {
+ type = "equals"
+ value = "datadog"
}
}
# opslevel_filter.example will be created
+ resource "opslevel_filter" "example" {
+ connective = "and"
+ id = (known after apply)
+ name = "foobarbaz1"
+ predicate {
+ case_insensitive = (known after apply)
+ case_sensitive = true
+ key = "language"
+ type = "contains"
+ value = "barbaz"
}
+ predicate {
+ case_insensitive = (known after apply)
+ case_sensitive = (known after apply)
+ key = "tier_index"
+ type = "less_than_or_equal_to"
+ value = "3"
}
+ predicate {
+ case_insensitive = (known after apply)
+ case_sensitive = (known after apply)
+ key = "language"
+ type = "exists"
}
}
Plan: 2 to add, 0 to change, 0 to destroy.
opslevel_check_tool_usage.example: Creating...
opslevel_filter.example: Creating...
opslevel_check_tool_usage.example: Creation complete after 0s [id=Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tzOjpUb29sVXNhZ2UvMjY0NzY]
opslevel_filter.example: Creation complete after 0s [id=Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzQ4NzI]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Update Terraform config:
resource "opslevel_filter" "example" {
name = "foobarbaz1"
connective = "and"
predicate {
key = "language"
type = "contains"
value = "barbaz"
case_sensitive = true
case_insensitive = null
}
# predicate {
# key = "tier_index"
# type = "less_than_or_equal_to"
# value = 3
# }
predicate {
key = "language"
type = "exists"
value = null
}
}
resource "opslevel_check_tool_usage" "example" {
name = "TF V1 Upgrade part deux"
enabled = true
category = "Z2lkOi8vb3BzbGV2ZWwvQ2F0ZWdvcnkvNjk3Nw"
level = "Z2lkOi8vb3BzbGV2ZWwvTGV2ZWwvMzcxMA"
owner = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTI0Nw"
filter = "Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzM1NzA"
tool_category = "metrics"
tool_name_predicate = {
type = "does_not_equal"
value = "datadog"
}
environment_predicate = {
type = "starts_with"
value = "water"
}
notes = "Optional additional info on why this check is run or how to fix it"
}
Update the Resource's predicates, terraform apply
opslevel_filter.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzQ4NzI]
opslevel_check_tool_usage.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tzOjpUb29sVXNhZ2UvMjY0NzY]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# opslevel_check_tool_usage.example will be updated in-place
~ resource "opslevel_check_tool_usage" "example" {
~ description = "The service is using 'datadog' as a metrics tool in an environment which exists ''." -> (known after apply)
~ environment_predicate = {
~ type = "exists" -> "starts_with"
+ value = "water"
}
id = "Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tzOjpUb29sVXNhZ2UvMjY0NzY"
name = "TF V1 Upgrade part deux"
~ tool_name_predicate = {
~ type = "equals" -> "does_not_equal"
# (1 unchanged attribute hidden)
}
# (7 unchanged attributes hidden)
}
# opslevel_filter.example will be updated in-place
~ resource "opslevel_filter" "example" {
id = "Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzQ4NzI"
name = "foobarbaz1"
# (1 unchanged attribute hidden)
~ predicate {
+ case_insensitive = (known after apply)
# (4 unchanged attributes hidden)
}
~ predicate {
+ case_insensitive = (known after apply)
+ case_sensitive = (known after apply)
~ key = "tier_index" -> "language"
~ type = "less_than_or_equal_to" -> "exists"
- value = "3" -> null
}
- predicate {
- key = "language" -> null
- type = "exists" -> null
}
}
Plan: 0 to add, 2 to change, 0 to destroy.
opslevel_filter.example: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzQ4NzI]
opslevel_check_tool_usage.example: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tzOjpUb29sVXNhZ2UvMjY0NzY]
opslevel_filter.example: Modifications complete after 1s [id=Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzQ4NzI]
opslevel_check_tool_usage.example: Modifications complete after 1s [id=Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tzOjpUb29sVXNhZ2UvMjY0NzY]
Apply complete! Resources: 0 added, 2 changed, 0 destroyed.
Destroy Resources, terraform destroy
opslevel_filter.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzQ4NzI]
opslevel_check_tool_usage.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tzOjpUb29sVXNhZ2UvMjY0NzY]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# opslevel_check_tool_usage.example will be destroyed
- resource "opslevel_check_tool_usage" "example" {
- category = "Z2lkOi8vb3BzbGV2ZWwvQ2F0ZWdvcnkvNjk3Nw" -> null
- description = "The service has a metrics tool whose name does not equal 'datadog' in an environment which starts with 'water'." -> null
- enabled = true -> null
- environment_predicate = {
- type = "starts_with" -> null
- value = "water" -> null
} -> null
- filter = "Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzM1NzA" -> null
- id = "Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tzOjpUb29sVXNhZ2UvMjY0NzY" -> null
- level = "Z2lkOi8vb3BzbGV2ZWwvTGV2ZWwvMzcxMA" -> null
- name = "TF V1 Upgrade part deux" -> null
- notes = "Optional additional info on why this check is run or how to fix it" -> null
- owner = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTI0Nw" -> null
- tool_category = "metrics" -> null
- tool_name_predicate = {
- type = "does_not_equal" -> null
- value = "datadog" -> null
} -> null
}
# opslevel_filter.example will be destroyed
- resource "opslevel_filter" "example" {
- connective = "and" -> null
- id = "Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzQ4NzI" -> null
- name = "foobarbaz1" -> null
- predicate {
- case_sensitive = true -> null
- key = "language" -> null
- type = "contains" -> null
- value = "barbaz" -> null
}
- predicate {
- key = "language" -> null
- type = "exists" -> null
}
}
Plan: 0 to add, 0 to change, 2 to destroy.
opslevel_filter.example: Destroying... [id=Z2lkOi8vb3BzbGV2ZWwvRmlsdGVyLzQ4NzI]
opslevel_check_tool_usage.example: Destroying... [id=Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tzOjpUb29sVXNhZ2UvMjY0NzY]
opslevel_filter.example: Destruction complete after 1s
opslevel_check_tool_usage.example: Destruction complete after 1s
Destroy complete! Resources: 2 destroyed.
Issues
https://github.com/OpsLevel/team-platform/issues/391
Changelog
✅ - relies on updates in this opslevel-go PR
Fix the where
case_insensitive
andcase_sensitive
were being set - they should be left null by default.see
convertedFilterPredicate.CaseInsensitive = types.BoolValue(false)
below RemoveNewPredicateModel
it is unused. Add validation to FilterPredicates. Add Terraform Config validation to enforcecase_sensitive
andcase_insensitive
are not both set.[X] List your changes here
[X] Make a
changie
entryTophatting
With this Terraform config (invalid):
Run
terraform validate
Update Terraform config (valid):
Run
terraform validate
With this Terraform config
Create Resources with Predicates
terraform apply
Update Terraform config:
Update the Resource's predicates,
terraform apply
Destroy Resources,
terraform destroy