Skip to content

Add storage_control_folder_intelligence_config resource. #13394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions mmv1/products/storagecontrol/FolderIntelligenceConfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Copyright 2025 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
# API resource name
name: 'FolderIntelligenceConfig'
kind: 'storagecontrol#intelligenceconfig'
# Resource description for the provider documentation.
description: |
The Folder Storage Intelligence resource represents GCS Storage Intelligence operating on individual GCP Folder. Storage Intelligence is a singleton resource and individual instance exists on each GCP Folder.

Storage Intelligence is for Storage Admins to manage GCP storage assets at scale for performance, cost, security & compliance.

docs:
warning: |
Storage Intelligence Config is a singleton resource which cannot be created or deleted. A single instance of Storage Intelligence Config exist for each GCP Folder. Terraform does not create or destroy this resource.
Terraform resource creation for this resource is simply an update operation on existing resource with specified properties, absense of any optional field in the create operation will result in clearance of that field. Terraform deletion won't have any effect on this resource rather it will only remove it from the state file.

# URL for the resource's standard Get method. https://google.aip.dev/131
self_link: 'folders/{{name}}/locations/global/intelligenceConfig'

custom_code:
pre_create: templates/terraform/pre_create/storage_control_intelligence_config.go.tmpl

create_verb: 'PATCH'
# The HTTP verb used to update a resource. Allowed values: :POST, :PUT, :PATCH. Default: :PUT.
update_verb: 'PATCH'
# If true, the resource sets an `updateMask` query parameter listing modified
# fields when updating the resource. If false, it does not.
update_mask: true

exclude_delete: true

import_format:
- 'folders/{{name}}/locations/global/intelligenceConfig'

# If true, code for handling long-running operations is generated along with
# the resource. If false, that code is not generated.
autogen_async: false

examples:
- name: storage_control_folder_intelligence_config_basic
primary_resource_id: example
vars:
folder_id: "12345678"
exclude_test: true
exclude_import_test: true

properties:
# Fields go here
- name: 'name'
type: String
required: true
immutable: true
url_param_only: true
description: |
Identifier of the GCP Folder. For GCP Folder, this field can be folder number.
- name: 'editionConfig'
type: String
required: false
default_from_api: true
description: |
Edition configuration of the Storage Intelligence resource. Valid values are INHERIT, TRIAL, DISABLED and STANDARD.
- name: 'updateTime'
type: String
output: true
description: |
The time at which the Storage Intelligence Config resource is last updated.
- name: 'filter'
type: NestedObject
diff_suppress_func: 'intelligenceFilterDiffSuppress'
description: |
Filter over location and bucket using include or exclude semantics. Resources that match the include or exclude filter are exclusively included or excluded from the Storage Intelligence plan.
properties:
- name: excludedCloudStorageBuckets
type: NestedObject
required: false
description: |
Buckets to exclude from the Storage Intelligence plan.
conflicts:
- 'filter.0.included_cloud_storage_buckets'
at_least_one_of:
- 'filter.0.included_cloud_storage_buckets'
- 'filter.0.excluded_cloud_storage_buckets'
- 'filter.0.included_cloud_storage_locations'
- 'filter.0.excluded_cloud_storage_locations'
diff_suppress_func: 'intelligenceFilterExcludedCloudStorageBucketsDiffSuppress'
properties:
- name: bucketIdRegexes
required: true
type: Array
send_empty_value: true
item_type:
type: String
description: |
List of bucket id regexes to exclude in the storage intelligence plan.
- name: includedCloudStorageBuckets
type: NestedObject
required: false
description: |
Buckets to include in the Storage Intelligence plan.
conflicts:
- 'filter.0.excluded_cloud_storage_buckets'
at_least_one_of:
- 'filter.0.included_cloud_storage_buckets'
- 'filter.0.excluded_cloud_storage_buckets'
- 'filter.0.included_cloud_storage_locations'
- 'filter.0.excluded_cloud_storage_locations'
diff_suppress_func: 'intelligenceFilterincludedCloudStorageBucketsDiffSuppress'
properties:
- name: bucketIdRegexes
required: true
send_empty_value: true
type: Array
item_type:
type: String
description: |
List of bucket id regexes to exclude in the storage intelligence plan.
- name: excludedCloudStorageLocations
type: NestedObject
required: false
description: |
Locations to exclude from the Storage Intelligence plan.
conflicts:
- 'filter.0.included_cloud_storage_locations'
at_least_one_of:
- 'filter.0.included_cloud_storage_buckets'
- 'filter.0.excluded_cloud_storage_buckets'
- 'filter.0.included_cloud_storage_locations'
- 'filter.0.excluded_cloud_storage_locations'
diff_suppress_func: 'intelligenceFilterExcludedCloudStorageLocationsDiffSuppress'
properties:
- name: locations
type: Array
required: true
send_empty_value: true
description: |
List of locations.
item_type:
type: String
- name: includedCloudStorageLocations
type: NestedObject
required: false
description: |
Locations to include in the Storage Intelligence plan.
conflicts:
- 'filter.0.excluded_cloud_storage_locations'
at_least_one_of:
- 'filter.0.included_cloud_storage_buckets'
- 'filter.0.excluded_cloud_storage_buckets'
- 'filter.0.included_cloud_storage_locations'
- 'filter.0.excluded_cloud_storage_locations'
diff_suppress_func: 'intelligenceFilterincludedCloudStorageLocationsDiffSuppress'
properties:
- name: locations
type: Array
required: true
send_empty_value: true
description: |
List of locations.
item_type:
type: String
- name: 'effectiveIntelligenceConfig'
output: true
description: |
The Intelligence config that is effective for the resource.
type: NestedObject
properties:
- name: intelligenceConfig
type: String
output: true
description: |
The Intelligence config resource that is applied for the target resource.
- name: effectiveEdition
type: String
output: true
description: |
The `StorageIntelligence` edition that is applicable for the resource.
10 changes: 9 additions & 1 deletion mmv1/products/storagecontrol/ProjectIntelligenceConfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ import_format:
# the resource. If false, that code is not generated.
autogen_async: false

examples:
- name: storage_control_project_intelligence_config_basic
primary_resource_id: example
vars:
project_id: "test-project"
exclude_test: true
exclude_import_test: true

properties:
- name: 'name'
type: String
Expand All @@ -61,7 +69,7 @@ properties:
required: false
default_from_api: true
description: |
Edition configuration of the Storage Intelligence resource. Valid values are INHERIT, DISABLED and STANDARD.
Edition configuration of the Storage Intelligence resource. Valid values are INHERIT, TRIAL, DISABLED and STANDARD.
- name: 'updateTime'
type: String
output: true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
resource "google_storage_control_folder_intelligence_config" "{{$.PrimaryResourceId}}" {
name = "{{index $.Vars "folder_id"}}"
edition_config = "STANDARD"
filter {
included_cloud_storage_buckets{
bucket_id_regexes = ["test-id-1*", "test-id-2*"]
}
excluded_cloud_storage_locations{
locations = ["test-location-1*", "test-locations-2*"]
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "google_storage_control_project_intelligence_config" "{{$.PrimaryResourceId}}" {
name = "{{index $.Vars "project_id"}}"
edition_config = "TRIAL"
filter {
included_cloud_storage_buckets{
bucket_id_regexes = ["test-id-1*", "test-id-2*"]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
updateMask := []string{"filter"}

if d.HasChange("edition_config") {
updateMask = append(updateMask, "editionConfig")
}
// updateMask is a URL parameter but not present in the schema, so ReplaceVars
// won't set it
url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
if err != nil {
return err
}
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ var handwrittenDatasources = map[string]*schema.Resource{
"google_storage_bucket_object": storage.DataSourceGoogleStorageBucketObject(),
"google_storage_bucket_objects": storage.DataSourceGoogleStorageBucketObjects(),
"google_storage_bucket_object_content": storage.DataSourceGoogleStorageBucketObjectContent(),
"google_storage_control_organization_intelligence_config": storagecontrol.DataSourceGoogleStorageControlOrganizationIntelligenceConfig(),
"google_storage_control_folder_intelligence_config": storagecontrol.DataSourceGoogleStorageControlFolderIntelligenceConfig(),
"google_storage_control_organization_intelligence_config": storagecontrol.DataSourceGoogleStorageControlOrganizationIntelligenceConfig(),
"google_storage_control_project_intelligence_config": storagecontrol.DataSourceGoogleStorageControlProjectIntelligenceConfig(),
"google_storage_object_signed_url": storage.DataSourceGoogleSignedUrl(),
"google_storage_project_service_account": storage.DataSourceGoogleStorageProjectServiceAccount(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package storagecontrol

import (
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
)

func DataSourceGoogleStorageControlFolderIntelligenceConfig() *schema.Resource {

dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceStorageControlFolderIntelligenceConfig().Schema)
tpgresource.AddRequiredFieldsToSchema(dsSchema, "name")

return &schema.Resource{
Read: dataSourceGoogleStorageControlFolderIntelligenceConfigRead,
Schema: dsSchema,
}
}

func dataSourceGoogleStorageControlFolderIntelligenceConfigRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)

id, err := tpgresource.ReplaceVars(d, config, "folders/{{name}}/locations/global/intelligenceConfig")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
err = resourceStorageControlFolderIntelligenceConfigRead(d, meta)
if err != nil {
return err
}

if d.Id() == "" {
return fmt.Errorf("%s not found", id)
}

return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package storagecontrol_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-provider-google/google/acctest"
"github.com/hashicorp/terraform-provider-google/google/envvar"
)

func TestAccDataSourceGoogleStorageControlFolderIntelligenceConfig_basic(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
"org_id": envvar.GetTestOrgFromEnv(t),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
ExternalProviders: map[string]resource.ExternalProvider{
"time": {},
},
Steps: []resource.TestStep{
{
Config: testAccDataSourceGoogleStorageControlFolderIntelligenceConfig_basic(context),
Check: resource.ComposeTestCheckFunc(
acctest.CheckDataSourceStateMatchesResourceState("data.google_storage_control_folder_intelligence_config.folder_storage_intelligence", "google_storage_control_folder_intelligence_config.folder_storage_intelligence"),
),
},
},
})
}

func testAccDataSourceGoogleStorageControlFolderIntelligenceConfig_basic(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_folder" "folder" {
parent = "organizations/%{org_id}"
display_name = "tf-test-folder-name%{random_suffix}"
deletion_protection=false
}

resource "time_sleep" "wait_120_seconds" {
depends_on = [google_folder.folder]
create_duration = "120s"
}

resource "google_storage_control_folder_intelligence_config" "folder_storage_intelligence" {
name = google_folder.folder.folder_id
edition_config = "STANDARD"
depends_on = [time_sleep.wait_120_seconds]
}

data "google_storage_control_folder_intelligence_config" "folder_storage_intelligence" {
name = google_storage_control_folder_intelligence_config.folder_storage_intelligence.name
}
`, context)
}
Loading
Loading