Skip to content

Commit 3ff5f68

Browse files
Add acceptance tests for how provider handles scopes argument (#11860) (#8308)
[upstream:2c7fe8a6b59d7dcb0a031b1139410dc34e0d1bc8] Signed-off-by: Modular Magician <[email protected]>
1 parent 6b4b5fe commit 3ff5f68

File tree

3 files changed

+348
-0
lines changed

3 files changed

+348
-0
lines changed

.changelog/11860.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:none
2+
3+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package fwprovider_test
4+
5+
import (
6+
"fmt"
7+
"regexp"
8+
"testing"
9+
10+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
"github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest"
12+
"github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
13+
)
14+
15+
// TestAccFwProvider_scopes is a series of acc tests asserting how the PF provider handles scopes arguments
16+
// It is PF specific because the HCL used provisions PF-implemented resources
17+
// It is a counterpart to TestAccSdkProvider_scopes
18+
func TestAccFwProvider_scopes(t *testing.T) {
19+
testCases := map[string]func(t *testing.T){
20+
// Configuring the provider using inputs
21+
"default scopes are used when there are no user inputs": testAccFwProvider_scopes_providerDefault,
22+
"scopes can be set in config": testAccFwProvider_scopes_setInConfig,
23+
//no ENVs to test
24+
25+
// Schema-level validation
26+
"when scopes is set to an empty array in the config the value is ignored and default scopes are used": testAccFwProvider_scopes_emptyArray,
27+
28+
// Usage
29+
// Beta-only generation is needed because we need to access a PF-implemented data source linked to resource in an API.
30+
// Currently this only exists in TPGB.
31+
"the scopes argument impacts provisioning resources": testAccFwProvider_scopes_usage,
32+
}
33+
34+
for name, tc := range testCases {
35+
// shadow the tc variable into scope so that when
36+
// the loop continues, if t.Run hasn't executed tc(t)
37+
// yet, we don't have a race condition
38+
// see https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
39+
tc := tc
40+
t.Run(name, func(t *testing.T) {
41+
tc(t)
42+
})
43+
}
44+
}
45+
46+
func testAccFwProvider_scopes_providerDefault(t *testing.T) {
47+
acctest.SkipIfVcr(t) // Test doesn't interact with API
48+
49+
acctest.VcrTest(t, resource.TestCase{
50+
// No PreCheck for checking ENVs
51+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
52+
Steps: []resource.TestStep{
53+
{
54+
Config: testAccFwProvider_scopes_unset(),
55+
Check: resource.ComposeTestCheckFunc(
56+
resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "scopes.#", fmt.Sprintf("%d", len(transport.DefaultClientScopes))),
57+
resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "scopes.0", transport.DefaultClientScopes[0]),
58+
resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "scopes.1", transport.DefaultClientScopes[1]),
59+
),
60+
},
61+
},
62+
})
63+
}
64+
65+
func testAccFwProvider_scopes_setInConfig(t *testing.T) {
66+
acctest.SkipIfVcr(t) // Test doesn't interact with API
67+
68+
scopes := []string{"https://www.googleapis.com/auth/cloud-platform"} // first of the two default scopes
69+
context := map[string]interface{}{
70+
"scopes": fmt.Sprintf("[\"%s\"]", scopes[0]),
71+
}
72+
73+
acctest.VcrTest(t, resource.TestCase{
74+
// No PreCheck for checking ENVs
75+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
76+
Steps: []resource.TestStep{
77+
{
78+
Config: testAccFwProvider_scopes_inProviderBlock(context),
79+
Check: resource.ComposeTestCheckFunc(
80+
resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "scopes.#", fmt.Sprintf("%d", len(scopes))),
81+
resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "scopes.0", scopes[0]),
82+
),
83+
},
84+
},
85+
})
86+
}
87+
88+
func testAccFwProvider_scopes_emptyArray(t *testing.T) {
89+
acctest.SkipIfVcr(t) // Test doesn't interact with API
90+
91+
context := map[string]interface{}{
92+
"scopes": "[]",
93+
}
94+
95+
acctest.VcrTest(t, resource.TestCase{
96+
// No PreCheck for checking ENVs
97+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
98+
Steps: []resource.TestStep{
99+
{
100+
Config: testAccFwProvider_scopes_inProviderBlock(context),
101+
Check: resource.ComposeTestCheckFunc(
102+
resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "scopes.#", fmt.Sprintf("%d", len(transport.DefaultClientScopes))),
103+
resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "scopes.0", transport.DefaultClientScopes[0]),
104+
resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "scopes.1", transport.DefaultClientScopes[1]),
105+
),
106+
},
107+
},
108+
})
109+
}
110+
111+
func testAccFwProvider_scopes_usage(t *testing.T) {
112+
acctest.SkipIfVcr(t) // Skip because Firebase is weird with VCR, and we have to use Firebase resources in the test
113+
114+
// We include scopes that aren't sufficient to enable provisioning the resources in the config below
115+
context := map[string]interface{}{
116+
"scopes": "[\"https://www.googleapis.com/auth/pubsub\"]",
117+
"random_suffix": acctest.RandString(t, 10),
118+
119+
"bundle_id": "apple.app." + acctest.RandString(t, 5),
120+
"display_name": "tf-test Display Name AppleAppConfig DataSource",
121+
"app_store_id": 12345,
122+
"team_id": 1234567890,
123+
}
124+
125+
acctest.VcrTest(t, resource.TestCase{
126+
// No PreCheck for checking ENVs
127+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
128+
Steps: []resource.TestStep{
129+
{
130+
Config: testAccFwProvider_access_token_useScopes(context),
131+
ExpectError: regexp.MustCompile("Request had insufficient authentication scopes"),
132+
},
133+
},
134+
})
135+
}
136+
137+
// testAccFwProvider_scopes_inProviderBlock allows setting the scopes argument in a provider block.
138+
// This function uses data.google_provider_config_plugin_framework because it is implemented with the PF
139+
func testAccFwProvider_scopes_inProviderBlock(context map[string]interface{}) string {
140+
return acctest.Nprintf(`
141+
provider "google" {
142+
scopes = %{scopes}
143+
}
144+
145+
data "google_provider_config_plugin_framework" "default" {}
146+
`, context)
147+
}
148+
149+
// testAccFwProvider_scopes_inEnvsOnly allows testing when the scopes argument is not set
150+
func testAccFwProvider_scopes_unset() string {
151+
return `
152+
data "google_provider_config_plugin_framework" "default" {}
153+
`
154+
}
155+
156+
func testAccFwProvider_access_token_useScopes(context map[string]interface{}) string {
157+
return acctest.Nprintf(`
158+
provider "google" {} // default scopes used
159+
160+
provider "google" {
161+
alias = "under-scoped"
162+
scopes = %{scopes}
163+
}
164+
165+
data "google_provider_config_plugin_framework" "default" {
166+
}
167+
168+
resource "google_firebase_apple_app" "my_app_config" {
169+
project = data.google_provider_config_plugin_framework.default.project
170+
bundle_id = "%{bundle_id}"
171+
display_name = "%{display_name}"
172+
app_store_id = "%{app_store_id}"
173+
team_id = "%{team_id}"
174+
}
175+
176+
// This is implemented with plugin-framework so tests our use of scopes in a PF specific way
177+
data "google_firebase_apple_app_config" "my_app_config" {
178+
provider = google.under-scoped
179+
app_id = google_firebase_apple_app.my_app_config.app_id
180+
}
181+
`, context)
182+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package provider_test
4+
5+
import (
6+
"fmt"
7+
"regexp"
8+
"testing"
9+
10+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
"github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest"
12+
"github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
13+
)
14+
15+
// TestAccSdkProvider_scopes is a series of acc tests asserting how the SDK provider handles scopes arguments
16+
// It is SDK specific because the HCL used provisions SDK-implemented resources
17+
// It is a counterpart to TestAccFwProvider_scopes
18+
func TestAccSdkProvider_scopes(t *testing.T) {
19+
testCases := map[string]func(t *testing.T){
20+
// Configuring the provider using inputs
21+
"default scopes are used when there are no user inputs": testAccSdkProvider_scopes_providerDefault,
22+
"scopes can be set in config": testAccSdkProvider_scopes_setInConfig,
23+
//no ENVs to test
24+
25+
// Schema-level validation
26+
"when scopes is set to an empty array in the config the value is ignored and default scopes are used": testAccSdkProvider_scopes_emptyArray,
27+
28+
// Usage
29+
"the scopes argument impacts provisioning resources": testAccSdkProvider_scopes_usage,
30+
}
31+
32+
for name, tc := range testCases {
33+
// shadow the tc variable into scope so that when
34+
// the loop continues, if t.Run hasn't executed tc(t)
35+
// yet, we don't have a race condition
36+
// see https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
37+
tc := tc
38+
t.Run(name, func(t *testing.T) {
39+
tc(t)
40+
})
41+
}
42+
}
43+
44+
func testAccSdkProvider_scopes_providerDefault(t *testing.T) {
45+
acctest.SkipIfVcr(t) // Test doesn't interact with API
46+
47+
acctest.VcrTest(t, resource.TestCase{
48+
// No PreCheck for checking ENVs
49+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
50+
Steps: []resource.TestStep{
51+
{
52+
Config: testAccSdkProvider_scopes_unset(),
53+
Check: resource.ComposeTestCheckFunc(
54+
resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "scopes.#", fmt.Sprintf("%d", len(transport.DefaultClientScopes))),
55+
resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "scopes.0", transport.DefaultClientScopes[0]),
56+
resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "scopes.1", transport.DefaultClientScopes[1]),
57+
),
58+
},
59+
},
60+
})
61+
}
62+
63+
func testAccSdkProvider_scopes_setInConfig(t *testing.T) {
64+
acctest.SkipIfVcr(t) // Test doesn't interact with API
65+
66+
scopes := []string{"https://www.googleapis.com/auth/cloud-platform"} // first of the two default scopes
67+
context := map[string]interface{}{
68+
"scopes": fmt.Sprintf("[\"%s\"]", scopes[0]),
69+
}
70+
71+
acctest.VcrTest(t, resource.TestCase{
72+
// No PreCheck for checking ENVs
73+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
74+
Steps: []resource.TestStep{
75+
{
76+
Config: testAccSdkProvider_scopes_inProviderBlock(context),
77+
Check: resource.ComposeTestCheckFunc(
78+
resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "scopes.#", fmt.Sprintf("%d", len(scopes))),
79+
resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "scopes.0", scopes[0]),
80+
),
81+
},
82+
},
83+
})
84+
}
85+
86+
func testAccSdkProvider_scopes_emptyArray(t *testing.T) {
87+
acctest.SkipIfVcr(t) // Test doesn't interact with API
88+
89+
context := map[string]interface{}{
90+
"scopes": "[]",
91+
}
92+
93+
acctest.VcrTest(t, resource.TestCase{
94+
// No PreCheck for checking ENVs
95+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
96+
Steps: []resource.TestStep{
97+
{
98+
Config: testAccSdkProvider_scopes_inProviderBlock(context),
99+
Check: resource.ComposeTestCheckFunc(
100+
resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "scopes.#", fmt.Sprintf("%d", len(transport.DefaultClientScopes))),
101+
resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "scopes.0", transport.DefaultClientScopes[0]),
102+
resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "scopes.1", transport.DefaultClientScopes[1]),
103+
),
104+
},
105+
},
106+
})
107+
}
108+
109+
func testAccSdkProvider_scopes_usage(t *testing.T) {
110+
acctest.SkipIfVcr(t) // Test doesn't interact with API
111+
112+
// We include scopes that aren't sufficient to enable provisioning the resources in the config below
113+
context := map[string]interface{}{
114+
"scopes": "[\"https://www.googleapis.com/auth/pubsub\"]",
115+
"random_suffix": acctest.RandString(t, 10),
116+
}
117+
118+
acctest.VcrTest(t, resource.TestCase{
119+
// No PreCheck for checking ENVs
120+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
121+
Steps: []resource.TestStep{
122+
{
123+
Config: testAccSdkProvider_scopes_affectsProvisioning(context),
124+
ExpectError: regexp.MustCompile("Request had insufficient authentication scopes"),
125+
},
126+
},
127+
})
128+
}
129+
130+
// testAccSdkProvider_scopes_inProviderBlock allows setting the scopes argument in a provider block.
131+
// This function uses data.google_provider_config_sdk because it is implemented with the SDK
132+
func testAccSdkProvider_scopes_inProviderBlock(context map[string]interface{}) string {
133+
return acctest.Nprintf(`
134+
provider "google" {
135+
scopes = %{scopes}
136+
}
137+
138+
data "google_provider_config_sdk" "default" {}
139+
`, context)
140+
}
141+
142+
// testAccSdkProvider_scopes_inEnvsOnly allows testing when the scopes argument is not set
143+
func testAccSdkProvider_scopes_unset() string {
144+
return `
145+
data "google_provider_config_sdk" "default" {}
146+
`
147+
}
148+
149+
// testAccSdkProvider_scopes_affectsProvisioning allows testing the impact of the scopes argument on provisioning
150+
func testAccSdkProvider_scopes_affectsProvisioning(context map[string]interface{}) string {
151+
return acctest.Nprintf(`
152+
provider "google" {
153+
scopes = %{scopes}
154+
}
155+
156+
data "google_provider_config_sdk" "default" {}
157+
158+
resource "google_service_account" "default" {
159+
account_id = "tf-test-%{random_suffix}"
160+
display_name = "AccTest Service Account"
161+
}
162+
`, context)
163+
}

0 commit comments

Comments
 (0)