initial Chrome Policy API support (google_chrome_policies resource + scaffolding)#17106
initial Chrome Policy API support (google_chrome_policies resource + scaffolding)#17106keeleysam wants to merge 7 commits into
Conversation
|
Googlers: For automatic test runs see go/terraform-auto-test-runs. @BBBmau, a repository maintainer, has been assigned to review your changes. If you have not received review feedback within 2 business days, please leave a comment on this PR asking them to take a look. You can help make sure that review is quick by doing a self-review and by running impacted tests locally. |
|
@modular-magician reassign-reviewer I'm OOO for a few days! |
BBBmau
left a comment
There was a problem hiding this comment.
we should refrain from having both resource and data-source in one PR. this is already quite complex given the nature of the Chrome Policy API.
Let's remove all mention of data-source and open it once we have resource merged.
Not only that but this is multiple resources being added in one PR. We should also pick the simplest resource in chrome policy API and have that be the starting point where we not only introduce the singular resource but also introduce the service in MMv1.
| display_name: 'Chrome Policy' | ||
| versions: | ||
| - name: 'ga' | ||
| base_url: 'https://chromepolicy.googleapis.com/v1/' |
There was a problem hiding this comment.
i believe this is expected, its just the base url and others 404 as well
3a50c39 to
722ef1f
Compare
|
@BBBmau i've stashed the bulk of this change into another branch, and now this PR should be much simpler, with scaffolding + a single resource |
b16113c to
0b46add
Compare
997bce2 to
5c6c92d
Compare
|
updated docs and squashed commits, should be ready for review |
|
this is fully working, but i'm doing a bit more improvement this morning to this, simplifying behavior and making interface easier. will mark it back for review after a couple more commits |
3e065c9 to
06a5390
Compare
Introduces the Chrome Policy API service in the Google Terraform provider with an authoritative resource for managing Chrome browser and ChromeOS policies for Google Workspace organizations. Resource: google_chrome_policies Manages all Chrome policies matching a schema filter for an org unit or group. Policies not declared in config are removed (inherited from parent). Supports wildcards (e.g. chrome.users.apps.*) for managing entire policy namespaces, or exact schema names for individual policies. Update logic does set-based diffing: only changed/added policies are sent via BatchModify, only removed policies via BatchInherit — at most 2 API calls per apply regardless of policy count. Reorder-only changes make zero API calls. Why Plugin Framework (not SDKv2): Uses the Terraform Plugin Framework with a DynamicAttribute for the policies list, which allows schema values to accept native HCL types (booleans, numbers, strings, lists) without requiring jsonencode() wrappers on every value. This is the first resource in the Google provider to use DynamicAttribute. DynamicAttribute is used instead of SetNestedBlock because the Plugin Framework does not support dynamic types inside collections — this is a known framework limitation (terraform-plugin-framework#973, terraform#34574). If this is addressed in a future framework release, the resource could be refactored to use block syntax. Why handwritten (not MMv1): The Chrome Policy API does not follow standard REST CRUD patterns. All operations use RPC-style POST endpoints (batchModify, resolve, batchInherit) rather than GET/POST/PUT/DELETE on resource URLs. This requires overriding all four CRUD methods, which per the contribution guidelines is the justification for handwritten resources. The product.yaml auto-generates all provider plumbing (base path, endpoint config). A typed Go client factory (NewChromePolicyClient) is added for the handwritten resource's RPC-style API calls.
06a5390 to
06e90ca
Compare
| "displayName" to "Chronicle", | ||
| "path" to "./google/services/chronicle" | ||
| ), | ||
| "chromepolicy" to mapOf( |
There was a problem hiding this comment.
since this is a new service being added you'll also need to enable it on our CI side, this can be done by including it in infra.tf. Here's a PR example of it being done:
| "blockchainnodeengine.googleapis.com", | ||
| "certificatemanager.googleapis.com", | ||
| "ces.googleapis.com", | ||
| "chromepolicy.googleapis.com", |
There was a problem hiding this comment.
this needs to be opened as a separate PR in order for the CI to be updated. if it gets added here CI will attempt to run it with the existing configuration on main
There was a problem hiding this comment.
resetting branch to commit without this, pulled this out into #17179
02c516a to
06e90ca
Compare
|
Hi there, I'm the Modular magician. I've detected the following information about your changes: Diff reportYour PR generated some diffs in downstreams - here they are.
|
Non-exercised tests🔴 Tests were added that are skipped in VCR:
Tests analyticsTotal tests: 6330 Click here to see the affected service packages
Action takenFound 21 affected test(s) by replaying old test recordings. Starting RECORDING based on the most recent commit. Click here to see the affected tests
|
|
🟢 Tests passed during RECORDING mode: 🔴 Tests failed when rerunning REPLAYING mode: Tests failed due to non-determinism or randomness when the VCR replayed the response after the HTTP request was made. Please fix these to complete your PR. If you believe these test failures to be incorrect or unrelated to your change, or if you have any questions, please raise the concern with your reviewer. 🔴 Tests failed during RECORDING mode: 🔴 Errors occurred during RECORDING mode. Please fix them to complete your PR. |
|
@BBBmau This PR has been waiting for review for 3 weekdays. Please take a look! Use the label |
|
@GoogleCloudPlatform/terraform-team @BBBmau This PR has been waiting for review for 1 week. Please take a look! Use the label |
| return clientCloudIdentity | ||
| } | ||
|
|
||
| func (c *Config) NewChromePolicyClient(userAgent string) *chromepolicy.Service { |
There was a problem hiding this comment.
do we absolutely need to utilize the client library?
What's preventing us from using tpgresource.SendRequest? We tend to stay away from client libraries due to dependency management where a new field may not be released due to underlying issues with bumping to the desired version.
There was a problem hiding this comment.
good point - this API is simple enough that we can follow this path. updating the PR
Drops the chromepolicy/v1 typed client library in favor of raw HTTP calls via transport_tpg.SendRequest, matching the convention used by other handwritten resources. This avoids the dependency-management overhead where a new field can be blocked on a client-library bump. The Chrome Policy API surface here (4 endpoints: schema get, resolve, batchModify, batchInherit) is JSON-in/JSON-out, and policy values were already passed as raw bytes — so the typed client wasn't buying type safety where it mattered. - Replaces NewChromePolicyClient with a small chromePolicyAPI helper - Replaces SDKv2 diag.Diagnostics with plain error returns - No change to the resource's HCL surface or behavior
|
@BBBmau This PR has been waiting for review for 3 weekdays. Please take a look! Use the label |
|
@GoogleCloudPlatform/terraform-team @BBBmau This PR has been waiting for review for 1 week. Please take a look! Use the label |
|
@GoogleCloudPlatform/terraform-team @BBBmau This PR has been waiting for review for 2 weeks. Please take a look! Use the label |
|
@GoogleCloudPlatform/terraform-team @BBBmau This PR has been waiting for review for 3 weeks. Please take a look! Use the label |
Resolve conflict in fwprovider/framework_provider.go.tmpl: main migrated framework resource registration to a self-registering pattern via registry.FrameworkResourceFuncs(). Drop the per-service imports and explicit Resources() list this branch added; instead register google_chrome_policies in an init() block in the chromepolicy package, matching the apigee/storage convention. Signed-off-by: Samuel Keeley <samuel@keeley.net>
…oved Config field main removed the per-product BasePath fields from transport.Config in favour of resolving base URLs through registry.GetProduct(<product>) + transport.BaseUrl(...). Update chrome_policy_common.go's url() helper to match — the previous a.config.ChromePolicyBasePath reference no longer compiles. Other services (apigee, storage, etc.) already use the same pattern via tpgresource.ReplaceVars; this is the equivalent for our hand-built API client wrapper that doesn't go through the template-based URL substitution. Signed-off-by: Samuel Keeley <samuel@keeley.net>
|
@GoogleCloudPlatform/terraform-team @BBBmau This PR has been waiting for review for 5 weeks. Please take a look! Use the label |
BBBmau
left a comment
There was a problem hiding this comment.
PR still needs to be broken down into individual PRs due to this being a 1400 line PR
|
@keeleysam, this PR is waiting for action from you. If no action is taken, this PR will be closed in 28 days. Please address any comments or change requests, or re-request review from a core reviewer if no action is required. This notification can be disabled with the |
|
@keeleysam, this PR is waiting for action from you. If no action is taken, this PR will be closed in 14 days. Please address any comments or change requests, or re-request review from a core reviewer if no action is required. This notification can be disabled with the |

This PR introduces the Chrome Policy API service in the Google Terraform provider with the
google_chrome_policiesresource for authoritative management of Chrome browser and ChromeOS policies.Context
The Chrome Policy API manages browser and device policies for Google Workspace customers. There is currently no Terraform support for this API in the Google provider. The community terraform-provider-googleworkspace was archived by HashiCorp, leaving users without a maintained way to manage Chrome policies as code.
This implementation ports and improves upon the Chrome Policy resources from community forks of that provider, adapting them to magic-modules conventions.
Additional resources and data sources are ready and will be submitted as follow-up PRs once this foundation is merged.
Why handwritten?
The Chrome Policy API does not follow standard REST CRUD patterns. All mutation operations use RPC-style POST endpoints (
batchModify,batchInherit) rather than standardGET/POST/PUT/DELETEon resource URLs. The read operation (resolve) is also a POST with a request body. This requires overriding all four CRUD methods, which per the contribution guidelines is the justification for handwritten resources.The
product.yamlauto-generates all provider plumbing (base path, endpoint config).Why Plugin Framework?
This resources uses
DynamicAttributefrom the Terraform Plugin Framework. This allows thepoliciesattribute to accept native HCL types (booleans, numbers, strings, lists) invaluewithout requiringjsonencode()wrappers on every single field, which was one of the biggest pain points of the original version.DynamicAttributeis used for the policies list instead ofSetNestedBlockbecause the Plugin Framework does not support dynamic types inside collections. If that limitation is addressed in a future framework release, this could be refactored to use block syntax.What this PR adds
mmv1/products/chromepolicy/product.yaml— introduces the Chrome Policy service in MMv1google_chrome_policiesresource — authoritative management of all Chrome policies matching a schema filter for a target (org unit or group). Policies not declared in config are removed (inherited). Update does set-based diffing: only changed/added policies are sent via BatchModify, only removed policies via BatchInherit — at most 2 API calls per apply. Reorder-only changes make zero API calls.chrome_policy_common.go— shared helpers for validation, batch operations, schema caching, and policy resolution (will be reused by follow-up resources)Design decisions
customer_iddefaults tomy_customer— the Workspace API alias for the authenticated account's customer. Multi-tenant users can override.chrome.management.policymust be added to the providerscopesblock. Not added to defaults since it would be inappropriate for users who don't use Chrome Policy.org_unit_idorgroup_id, both ForceNew.schema_filtersupports wildcards and exact names — wildcards (e.g.chrome.users.apps.*) manage entire policy namespaces authoritatively; exact names manage a single policy. Inferred automatically when only one policy is defined.Precedent
Cloud Identity is already in the provider and is similarly a Workspace-adjacent API using
customers/{customer_id}paths. The existingGOOGLE_CUST_IDtest infrastructure supports Chrome Policy testing.Release Note Template for Downstream PRs (will be copied)