Skip to content

Commit 57c318f

Browse files
Promote google_cloud_asset_resources_search_all datasource to ga (#10660) (#18129)
[upstream:eb6964841853017474b1aa75e0ee662e47a63e31] Signed-off-by: Modular Magician <[email protected]>
1 parent 1bb04b6 commit 57c318f

5 files changed

+414
-0
lines changed

google/provider/provider_mmv1_resources.go

+1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
153153
"google_cloudbuild_trigger": cloudbuild.DataSourceGoogleCloudBuildTrigger(),
154154
"google_cloudfunctions_function": cloudfunctions.DataSourceGoogleCloudFunctionsFunction(),
155155
"google_cloudfunctions2_function": cloudfunctions2.DataSourceGoogleCloudFunctions2Function(),
156+
"google_cloud_asset_search_all_resources": cloudasset.DataSourceGoogleCloudAssetSearchAllResources(),
156157
"google_cloud_identity_groups": cloudidentity.DataSourceGoogleCloudIdentityGroups(),
157158
"google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(),
158159
"google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package cloudasset
4+
5+
import (
6+
"fmt"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
10+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
11+
)
12+
13+
func DataSourceGoogleCloudAssetSearchAllResources() *schema.Resource {
14+
return &schema.Resource{
15+
Read: datasourceGoogleCloudAssetSearchAllResourcesRead,
16+
Schema: map[string]*schema.Schema{
17+
"scope": {
18+
Type: schema.TypeString,
19+
Required: true,
20+
},
21+
"query": {
22+
Type: schema.TypeString,
23+
Optional: true,
24+
},
25+
"asset_types": {
26+
Type: schema.TypeList,
27+
Elem: &schema.Schema{
28+
Type: schema.TypeString,
29+
},
30+
Optional: true,
31+
},
32+
"results": {
33+
Type: schema.TypeList,
34+
Computed: true,
35+
Elem: &schema.Resource{
36+
Schema: map[string]*schema.Schema{
37+
"name": {
38+
Type: schema.TypeString,
39+
Computed: true,
40+
},
41+
"asset_type": {
42+
Type: schema.TypeString,
43+
Computed: true,
44+
},
45+
"project": {
46+
Type: schema.TypeString,
47+
Computed: true,
48+
},
49+
"folders": {
50+
Type: schema.TypeList,
51+
Computed: true,
52+
Elem: &schema.Schema{
53+
Type: schema.TypeString,
54+
},
55+
},
56+
"organization": {
57+
Type: schema.TypeString,
58+
Computed: true,
59+
},
60+
"display_name": {
61+
Type: schema.TypeString,
62+
Computed: true,
63+
},
64+
"description": {
65+
Type: schema.TypeString,
66+
Computed: true,
67+
},
68+
"location": {
69+
Type: schema.TypeString,
70+
Computed: true,
71+
},
72+
"labels": {
73+
Type: schema.TypeMap,
74+
Computed: true,
75+
Elem: &schema.Schema{Type: schema.TypeString},
76+
},
77+
"network_tags": {
78+
Type: schema.TypeList,
79+
Computed: true,
80+
Elem: &schema.Schema{
81+
Type: schema.TypeString,
82+
},
83+
},
84+
"kms_keys": {
85+
Type: schema.TypeList,
86+
Computed: true,
87+
Elem: &schema.Schema{
88+
Type: schema.TypeString,
89+
},
90+
},
91+
"create_time": {
92+
Type: schema.TypeString,
93+
Computed: true,
94+
},
95+
"update_time": {
96+
Type: schema.TypeString,
97+
Computed: true,
98+
},
99+
"state": {
100+
Type: schema.TypeString,
101+
Computed: true,
102+
},
103+
"parent_full_resource_name": {
104+
Type: schema.TypeString,
105+
Computed: true,
106+
},
107+
"parent_asset_type": {
108+
Type: schema.TypeString,
109+
Computed: true,
110+
},
111+
},
112+
},
113+
},
114+
},
115+
}
116+
}
117+
118+
func datasourceGoogleCloudAssetSearchAllResourcesRead(d *schema.ResourceData, meta interface{}) error {
119+
config := meta.(*transport_tpg.Config)
120+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
121+
if err != nil {
122+
return err
123+
}
124+
125+
params := make(map[string]string)
126+
results := make([]map[string]interface{}, 0)
127+
128+
scope := d.Get("scope").(string)
129+
query := d.Get("query").(string)
130+
assetTypes := d.Get("asset_types").([]interface{})
131+
132+
url := fmt.Sprintf("https://cloudasset.googleapis.com/v1/%s:searchAllResources", scope)
133+
params["query"] = query
134+
135+
url, err = transport_tpg.AddArrayQueryParams(url, "asset_types", assetTypes)
136+
if err != nil {
137+
return fmt.Errorf("Error setting asset_types: %s", err)
138+
}
139+
140+
for {
141+
url, err := transport_tpg.AddQueryParams(url, params)
142+
if err != nil {
143+
return err
144+
}
145+
146+
var project string
147+
if config.UserProjectOverride && config.BillingProject != "" {
148+
project = config.BillingProject
149+
}
150+
151+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
152+
Config: config,
153+
Project: project,
154+
Method: "GET",
155+
RawURL: url,
156+
UserAgent: userAgent,
157+
})
158+
if err != nil {
159+
return fmt.Errorf("Error searching resources: %s", err)
160+
}
161+
162+
pageResults := flattenDatasourceGoogleCloudAssetSearchAllResources(res["results"])
163+
results = append(results, pageResults...)
164+
165+
pToken, ok := res["nextPageToken"]
166+
if ok && pToken != nil && pToken.(string) != "" {
167+
params["pageToken"] = pToken.(string)
168+
} else {
169+
break
170+
}
171+
}
172+
173+
if err := d.Set("results", results); err != nil {
174+
return fmt.Errorf("Error searching resources: %s", err)
175+
}
176+
177+
if err := d.Set("query", query); err != nil {
178+
return fmt.Errorf("Error setting query: %s", err)
179+
}
180+
181+
if err := d.Set("asset_types", assetTypes); err != nil {
182+
return fmt.Errorf("Error setting asset_types: %s", err)
183+
}
184+
185+
d.SetId(scope)
186+
187+
return nil
188+
}
189+
190+
func flattenDatasourceGoogleCloudAssetSearchAllResources(v interface{}) []map[string]interface{} {
191+
if v == nil {
192+
return make([]map[string]interface{}, 0)
193+
}
194+
195+
ls := v.([]interface{})
196+
results := make([]map[string]interface{}, 0, len(ls))
197+
for _, raw := range ls {
198+
p := raw.(map[string]interface{})
199+
200+
var mName, mAssetType, mProject, mFolders, mOrganization, mDisplayName, mDescription, mLocation, mLabels, mNetworkTags, mKmsKeys, mCreateTime, mUpdateTime, mState, mParentFullResourceName, mParentAssetType interface{}
201+
if pName, ok := p["name"]; ok {
202+
mName = pName
203+
}
204+
if pAssetType, ok := p["assetType"]; ok {
205+
mAssetType = pAssetType
206+
}
207+
if pProject, ok := p["project"]; ok {
208+
mProject = pProject
209+
}
210+
if pFolders, ok := p["folders"]; ok {
211+
mFolders = pFolders
212+
}
213+
if pOrganization, ok := p["organization"]; ok {
214+
mOrganization = pOrganization
215+
}
216+
if pDisplayName, ok := p["displayName"]; ok {
217+
mDisplayName = pDisplayName
218+
}
219+
if pDescription, ok := p["description"]; ok {
220+
mDescription = pDescription
221+
}
222+
if pLocation, ok := p["location"]; ok {
223+
mLocation = pLocation
224+
}
225+
if pLabels, ok := p["labels"]; ok {
226+
mLabels = pLabels
227+
}
228+
if pNetworkTags, ok := p["networkTags"]; ok {
229+
mNetworkTags = pNetworkTags
230+
}
231+
if pKmsKeys, ok := p["kmsKeys"]; ok {
232+
mKmsKeys = pKmsKeys
233+
}
234+
if pCreateTime, ok := p["createTime"]; ok {
235+
mCreateTime = pCreateTime
236+
}
237+
if pUpdateTime, ok := p["updateTime"]; ok {
238+
mUpdateTime = pUpdateTime
239+
}
240+
if pState, ok := p["state"]; ok {
241+
mState = pState
242+
}
243+
if pParentFullResourceName, ok := p["parentFullResourceName"]; ok {
244+
mParentFullResourceName = pParentFullResourceName
245+
}
246+
if pParentAssetType, ok := p["parentAssetType"]; ok {
247+
mParentAssetType = pParentAssetType
248+
}
249+
results = append(results, map[string]interface{}{
250+
"name": mName,
251+
"asset_type": mAssetType,
252+
"project": mProject,
253+
"folders": mFolders,
254+
"organization": mOrganization,
255+
"display_name": mDisplayName,
256+
"description": mDescription,
257+
"location": mLocation,
258+
"labels": mLabels,
259+
"network_tags": mNetworkTags,
260+
"kms_keys": mKmsKeys,
261+
"create_time": mCreateTime,
262+
"update_time": mUpdateTime,
263+
"state": mState,
264+
"parent_full_resource_name": mParentFullResourceName,
265+
"parent_asset_type": mParentAssetType,
266+
})
267+
}
268+
269+
return results
270+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package cloudasset_test
4+
5+
import (
6+
"fmt"
7+
"regexp"
8+
"testing"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
11+
"github.com/hashicorp/terraform-provider-google/google/acctest"
12+
"github.com/hashicorp/terraform-provider-google/google/envvar"
13+
)
14+
15+
func TestAccDataSourceGoogleCloudAssetSearchAllResources_basic(t *testing.T) {
16+
t.Parallel()
17+
18+
project := envvar.GetTestProjectFromEnv()
19+
20+
acctest.VcrTest(t, resource.TestCase{
21+
PreCheck: func() { acctest.AccTestPreCheck(t) },
22+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
23+
Steps: []resource.TestStep{
24+
{
25+
Config: testAccCheckGoogleCloudAssetProjectResourcesList(project),
26+
Check: resource.ComposeTestCheckFunc(
27+
resource.TestMatchResourceAttr("data.google_cloud_asset_search_all_resources.resources",
28+
"results.0.asset_type", regexp.MustCompile("cloudresourcemanager.googleapis.com/Project")),
29+
resource.TestMatchResourceAttr("data.google_cloud_asset_search_all_resources.resources",
30+
"results.0.display_name", regexp.MustCompile(project)),
31+
resource.TestMatchResourceAttr("data.google_cloud_asset_search_all_resources.resources",
32+
"results.0.name", regexp.MustCompile(fmt.Sprintf("//cloudresourcemanager.googleapis.com/projects/%s", project))),
33+
resource.TestCheckResourceAttrSet("data.google_cloud_asset_search_all_resources.resources", "results.0.location"),
34+
resource.TestCheckResourceAttrSet("data.google_cloud_asset_search_all_resources.resources", "results.0.project"),
35+
),
36+
},
37+
},
38+
})
39+
}
40+
41+
func testAccCheckGoogleCloudAssetProjectResourcesList(project string) string {
42+
return fmt.Sprintf(`
43+
data google_cloud_asset_search_all_resources resources {
44+
scope = "projects/%s"
45+
asset_types = [
46+
"cloudresourcemanager.googleapis.com/Project"
47+
]
48+
}
49+
`, project)
50+
}

google/transport/transport.go

+13
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,19 @@ func AddQueryParams(rawurl string, params map[string]string) (string, error) {
129129
return u.String(), nil
130130
}
131131

132+
func AddArrayQueryParams(rawurl string, param string, values []interface{}) (string, error) {
133+
u, err := url.Parse(rawurl)
134+
if err != nil {
135+
return "", err
136+
}
137+
q := u.Query()
138+
for _, v := range values {
139+
q.Add(param, v.(string))
140+
}
141+
u.RawQuery = q.Encode()
142+
return u.String(), nil
143+
}
144+
132145
func HandleNotFoundError(err error, d *schema.ResourceData, resource string) error {
133146
if IsGoogleApiErrorWithCode(err, 404) {
134147
log.Printf("[WARN] Removing %s because it's gone", resource)

0 commit comments

Comments
 (0)