Skip to content

Commit e7f71eb

Browse files
authored
Merge pull request hashicorp#290 from hashicorp/enhance-find-by-provider
update find_by_provider functions
2 parents f3174ab + 74974eb commit e7f71eb

File tree

7 files changed

+148
-27
lines changed

7 files changed

+148
-27
lines changed

governance/third-generation/aws/restrict-sagemaker-notebooks.sentinel

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import "tfplan-functions" as plan
88

99
# Get all Sagemaker notebooks
1010
allSagemakerNotebooks = plan.find_resources("aws_sagemaker_notebook_instance")
11-
#print("allSagemakerNotebooks:", allSagemakerNotebooks)
1211

1312
# Filter to Sagemaker notebooks that have root_access set to "Enabled"
1413
# or missing.

governance/third-generation/common-functions/tfplan-functions/docs/find_datasources_by_provider.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ This function finds all data source instances for a specific provider that are b
33

44
When evaluating data sources that do not reference any computed values (those known after doing an apply), it is usually better to use the [tfstate/v2](https://www.terraform.io/docs/cloud/sentinel/import/tfstate-v2.html) import and the corresponding [find_datasources](../tfstate-functions/find_datasources.md) function that uses that import.
55

6-
If you are using Terraform 0.12, use the short form of the provider name such as "aws". If you are using Terraform 0.13, use the fully-qualified provider source such as "registry.terraform.io/hashicorp/aws".
6+
If you are using Terraform 0.12, use the short form of the provider name such as "null". If you are using Terraform 0.13, you can use the short form or the fully-qualified provider source such as "registry.terraform.io/hashicorp/null", but only use the latter if you are only want to find resources from a specific registry. If you use the short form, the function will reduce `rc.provider_name` for each resource to the short form, but if you use the long form, it will not.
77

88
## Sentinel Module
99
This function is contained in the [tfplan-functions.sentinel](../tfplan-functions.sentinel) Sentinel module.

governance/third-generation/common-functions/tfplan-functions/docs/find_resources_by_provider.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# find_resources_by_provider
22
This function finds all resource instances for a specific provider in the current plan that are being created, modified, or read using the [tfplan/v2](https://www.terraform.io/docs/cloud/sentinel/import/tfplan-v2.html) import. Resources with the "no-op" action are also included.
33

4-
If you are using Terraform 0.12, use the short form of the provider name such as "aws". If you are using Terraform 0.13, use the fully-qualified provider source such as "registry.terraform.io/hashicorp/aws".
4+
If you are using Terraform 0.12, use the short form of the provider name such as "null". If you are using Terraform 0.13, you can use the short form or the fully-qualified provider source such as "registry.terraform.io/hashicorp/null", but only use the latter if you are only want to find resources from a specific registry. If you use the short form, the function will reduce `rc.provider_name` for each resource to the short form, but if you use the long form, it will not.
55

66
## Sentinel Module
77
This function is contained in the [tfplan-functions.sentinel](../tfplan-functions.sentinel) module.

governance/third-generation/common-functions/tfplan-functions/tfplan-functions.sentinel

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,46 @@ find_resources = func(type) {
3737
# Find all resources for a specific provider using the tfplan/v2 import.
3838
# Include resources that are not being permanently deleted.
3939
# Technically, this returns a map of resource changes.
40+
# Terraform 0.12 and earlier set `rc.provider_name` to short text like "null";
41+
# but Terraform 0.13 and higher set it to something like
42+
# "registry.terraform.io/hashicorp/null".
43+
# You can pass in the long form or short form.
4044
find_resources_by_provider = func(provider) {
41-
resources = filter tfplan.resource_changes as address, rc {
42-
rc.provider_name is provider and
43-
rc.mode is "managed" and
44-
(rc.change.actions contains "create" or rc.change.actions contains "update" or
45-
rc.change.actions contains "read" or rc.change.actions contains "no-op")
46-
}
45+
parsed_provider = strings.split(provider, "/")
46+
segment_count = length(parsed_provider)
47+
v = strings.split(tfplan.terraform_version, ".")
48+
v_major = int(v[1])
49+
50+
# If v_major is 12, we know short form was passed to Sentinel
51+
if v_major is 12 {
52+
resources = filter tfplan.resource_changes as address, rc {
53+
rc.provider_name is provider and
54+
rc.mode is "managed" and
55+
(rc.change.actions contains "create" or rc.change.actions contains "update" or
56+
rc.change.actions contains "read" or rc.change.actions contains "no-op")
57+
}
58+
} else {
59+
# v_major must be higher than 12 since v2 imports being used
60+
# So, we know long form like "registry.terraform.io/hashicorp/null" given
61+
if segment_count is 1 {
62+
# Function was passed short form, so we want to reduce each occurence of
63+
# rc.provider_name to its short form.
64+
resources = filter tfplan.resource_changes as address, rc {
65+
strings.split(rc.provider_name, "/")[2] is provider and
66+
rc.mode is "managed" and
67+
(rc.change.actions contains "create" or rc.change.actions contains "update" or
68+
rc.change.actions contains "read" or rc.change.actions contains "no-op")
69+
}
70+
} else {
71+
# Function was passed long form, so we use full rc.provider_name
72+
resources = filter tfplan.resource_changes as address, rc {
73+
rc.provider_name is provider and
74+
rc.mode is "managed" and
75+
(rc.change.actions contains "create" or rc.change.actions contains "update" or
76+
rc.change.actions contains "read" or rc.change.actions contains "no-op")
77+
}
78+
} // end segment_count
79+
} // end v_major
4780

4881
return resources
4982
}
@@ -69,15 +102,46 @@ find_datasources = func(type) {
69102
# Find all data sources for a specific provider using the tfplan/v2 import.
70103
# Include data sources that are not being permanently deleted.
71104
# Technically, this returns a map of resource changes.
105+
# Terraform 0.12 and earlier set `rc.provider_name` to short text like "null";
106+
# but Terraform 0.13 and higher set it to something like
107+
# "registry.terraform.io/hashicorp/null".
108+
# You can pass in the long form or short form.
72109
find_datasources_by_provider = func(provider) {
73-
datasources = filter tfplan.resource_changes as address, rc {
74-
rc.provider_name is provider and
75-
rc.mode is "data" and
76-
(rc.change.actions contains "create" or
77-
rc.change.actions contains "update" or
78-
rc.change.actions contains "read" or
79-
rc.change.actions contains "no-op")
80-
}
110+
parsed_provider = strings.split(provider, "/")
111+
segment_count = length(parsed_provider)
112+
v = strings.split(tfplan.terraform_version, ".")
113+
v_major = int(v[1])
114+
115+
# If v_major is 12, we know short form was passed to Sentinel
116+
if v_major is 12 {
117+
datasources = filter tfplan.resource_changes as address, rc {
118+
rc.provider_name is provider and
119+
rc.mode is "data" and
120+
(rc.change.actions contains "create" or rc.change.actions contains "update" or
121+
rc.change.actions contains "read" or rc.change.actions contains "no-op")
122+
}
123+
} else {
124+
# v_major must be higher than 12 since v2 imports being used
125+
# So, we know long form like "registry.terraform.io/hashicorp/null" given
126+
if segment_count is 1 {
127+
# Function was passed short form, so we want to reduce each occurence of
128+
# rc.provider_name to its short form.
129+
datasources = filter tfplan.resource_changes as address, rc {
130+
strings.split(rc.provider_name, "/")[2] is provider and
131+
rc.mode is "data" and
132+
(rc.change.actions contains "create" or rc.change.actions contains "update" or
133+
rc.change.actions contains "read" or rc.change.actions contains "no-op")
134+
}
135+
} else {
136+
# Function was passed long form, so we use full rc.provider_name
137+
datasources = filter tfplan.resource_changes as address, rc {
138+
rc.provider_name is provider and
139+
rc.mode is "data" and
140+
(rc.change.actions contains "create" or rc.change.actions contains "update" or
141+
rc.change.actions contains "read" or rc.change.actions contains "no-op")
142+
}
143+
} // end segment_count
144+
} // end v_major
81145

82146
return datasources
83147
}

governance/third-generation/common-functions/tfstate-functions/docs/find_datasources_by_provider.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# find_datasources_by_provider
22
This function finds all data source instances for a specific provider in the state of the current workspace using the [tfstate/v2](https://www.terraform.io/docs/cloud/sentinel/import/tfstate-v2.html) import.
33

4-
If you are using Terraform 0.12, use the short form of the provider name such as "aws". If you are using Terraform 0.13, use the fully-qualified provider source such as "registry.terraform.io/hashicorp/aws".
4+
If you are using Terraform 0.12, use the short form of the provider name such as "null". If you are using Terraform 0.13, you can use the short form or the fully-qualified provider source such as "registry.terraform.io/hashicorp/null", but only use the latter if you are only want to find resources from a specific registry. If you use the short form, the function will reduce `rc.provider_name` for each resource to the short form, but if you use the long form, it will not.
55

66
## Sentinel Module
77
This function is contained in the [tfstate-functions.sentinel](../tfstate-functions.sentinel) module.

governance/third-generation/common-functions/tfstate-functions/docs/find_resources_by_provider.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# find_resources_by_provider
22
This function finds all resource instances for a specific provider in the state of the current workspace using the [tfstate/v2](https://www.terraform.io/docs/cloud/sentinel/import/tfstate-v2.html) import.
33

4-
If you are using Terraform 0.12, use the short form of the provider name such as "aws". If you are using Terraform 0.13, use the fully-qualified provider source such as "registry.terraform.io/hashicorp/aws".
4+
If you are using Terraform 0.12, use the short form of the provider name such as "null". If you are using Terraform 0.13, you can use the short form or the fully-qualified provider source such as "registry.terraform.io/hashicorp/null", but only use the latter if you are only want to find resources from a specific registry. If you use the short form, the function will reduce `rc.provider_name` for each resource to the short form, but if you use the long form, it will not.
55

66
## Sentinel Module
77
This function is contained in the [tfstate-functions.sentinel](../tfstate-functions.sentinel) module.

governance/third-generation/common-functions/tfstate-functions/tfstate-functions.sentinel

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,40 @@ find_resources = func(type) {
3131

3232
### find_resources_by_provider ###
3333
# Find all resources for a specific provider using the tfstate/v2 import.
34+
# Terraform 0.12 and earlier set `r.provider_name` to short text like "null";
35+
# but Terraform 0.13 and higher set it to something like
36+
# "registry.terraform.io/hashicorp/null".
37+
# You can pass in the long form or short form.
3438
find_resources_by_provider = func(provider) {
35-
resources = filter tfstate.resources as address, r {
36-
r.provider_name is provider and
37-
r.mode is "managed"
38-
}
39+
parsed_provider = strings.split(provider, "/")
40+
segment_count = length(parsed_provider)
41+
v = strings.split(tfstate.terraform_version, ".")
42+
v_major = int(v[1])
43+
44+
# If v_major is 12, we know short form was passed to Sentinel
45+
if v_major is 12 {
46+
resources = filter tfstate.resources as address, r {
47+
r.provider_name is provider and
48+
r.mode is "managed"
49+
}
50+
} else {
51+
# v_major must be higher than 12 since v2 imports being used
52+
# So, we know long form like "registry.terraform.io/hashicorp/null" given
53+
if segment_count is 1 {
54+
# Function was passed short form, so we want to reduce each occurence of
55+
# r.provider_name to its short form.
56+
resources = filter tfstate.resources as address, r {
57+
strings.split(r.provider_name, "/")[2] is provider and
58+
r.mode is "managed"
59+
}
60+
} else {
61+
# Function was passed long form, so we use full r.provider_name
62+
resources = filter tfstate.resources as address, r {
63+
r.provider_name is provider and
64+
r.mode is "managed"
65+
}
66+
} // end segment_count
67+
} // end v_major
3968

4069
return resources
4170
}
@@ -53,11 +82,40 @@ find_datasources = func(type) {
5382

5483
### find_datasources_by_provider ###
5584
# Find all data sources for a specific provider using the tfstate/v2 import.
85+
# Terraform 0.12 and earlier set `r.provider_name` to short text like "null";
86+
# but Terraform 0.13 and higher set it to something like
87+
# "registry.terraform.io/hashicorp/null".
88+
# You can pass in the long form or short form.
5689
find_datasources_by_provider = func(provider) {
57-
datasources = filter tfstate.resources as address, d {
58-
d.provider_name is provider and
59-
d.mode is "data"
60-
}
90+
parsed_provider = strings.split(provider, "/")
91+
segment_count = length(parsed_provider)
92+
v = strings.split(tfstate.terraform_version, ".")
93+
v_major = int(v[1])
94+
95+
# If v_major is 12, we know short form was passed to Sentinel
96+
if v_major is 12 {
97+
datasources = filter tfstate.resources as address, r {
98+
r.provider_name is provider and
99+
r.mode is "data"
100+
}
101+
} else {
102+
# v_major must be higher than 12 since v2 imports being used
103+
# So, we know long form like "registry.terraform.io/hashicorp/null" given
104+
if segment_count is 1 {
105+
# Function was passed short form, so we want to reduce each occurence of
106+
# r.provider_name to its short form.
107+
datasources = filter tfstate.resources as address, r {
108+
strings.split(r.provider_name, "/")[2] is provider and
109+
r.mode is "data"
110+
}
111+
} else {
112+
# Function was passed long form, so we use full r.provider_name
113+
datasources = filter tfstate.resources as address, r {
114+
r.provider_name is provider and
115+
r.mode is "data"
116+
}
117+
} // end segment_count
118+
} // end v_major
61119

62120
return datasources
63121
}

0 commit comments

Comments
 (0)