Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1baa94b
Biglake namespace resource
rambleraptor Jan 29, 2026
e4c36ea
BigLake namespace resource
rambleraptor Feb 2, 2026
eb1f263
Save point
rambleraptor Feb 2, 2026
e187f92
Move to generated
rambleraptor Feb 3, 2026
a2068c7
fixes
rambleraptor Feb 3, 2026
73c8e7f
lint
rambleraptor Feb 3, 2026
0aa4ded
lint
rambleraptor Feb 3, 2026
d0a7d58
rebase issue
rambleraptor Feb 3, 2026
9b0dc44
other missing file
rambleraptor Feb 3, 2026
2400781
test fix
rambleraptor Feb 3, 2026
f1db933
test fixes
rambleraptor Feb 3, 2026
54b70b6
remove handwritten
rambleraptor Feb 3, 2026
b59a816
test fix
rambleraptor Feb 3, 2026
f055207
let's try it
rambleraptor Feb 3, 2026
5fe30f7
IAM policies need to send x-goog-user-project header
rambleraptor Feb 3, 2026
c60421b
test fixes
rambleraptor Feb 4, 2026
1dd1dc7
wip
rambleraptor Feb 6, 2026
0521caf
Test fixes
rambleraptor Feb 6, 2026
3e618da
bad change
rambleraptor Feb 6, 2026
4069b47
no longer needed
rambleraptor Feb 6, 2026
73d3eaa
test fix
rambleraptor Feb 6, 2026
c83e820
Update mmv1/products/biglakeiceberg/IcebergNamespace.yaml
rambleraptor Feb 9, 2026
5da930f
Update mmv1/third_party/terraform/services/biglakeiceberg/utils.go
rambleraptor Feb 9, 2026
89c467d
Update mmv1/third_party/terraform/acctest/resource_inventory_test.go
rambleraptor Feb 9, 2026
0f718b0
Update mmv1/api/resource/iam_policy.go
rambleraptor Feb 9, 2026
3699e8b
address PR review
rambleraptor Feb 10, 2026
119c650
Move to examples
rambleraptor Feb 10, 2026
588a5cc
remove unused template
rambleraptor Feb 10, 2026
1f98ab2
renaming things
rambleraptor Feb 10, 2026
7f8beee
Update mmv1/products/biglakeiceberg/IcebergNamespace.yaml
rambleraptor Feb 11, 2026
4103ac1
Update mmv1/api/resource/iam_policy.go
rambleraptor Feb 11, 2026
43c2352
Update mmv1/products/biglakeiceberg/IcebergNamespace.yaml
rambleraptor Feb 11, 2026
9ff5a65
stray changes
rambleraptor Feb 11, 2026
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
74 changes: 74 additions & 0 deletions mmv1/products/biglakeiceberg/IcebergNamespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# 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.

---
name: 'IcebergNamespace'
description: |
IcebergNamespaces are containers for Apache Iceberg Tables within an IcebergCatalog.
supports_indirect_user_project_override: true
base_url: 'iceberg/v1/restcatalog/v1/projects/{{project}}/catalogs/{{catalog}}/namespaces'
self_link: 'iceberg/v1/restcatalog/v1/projects/{{project}}/catalogs/{{catalog}}/namespaces/{{namespace_id}}'
id_format: 'projects/{{project}}/catalogs/{{catalog}}/namespaces/{{namespace_id}}'
import_format:
- 'projects/{{project}}/catalogs/{{catalog}}/namespaces/{{namespace_id}}'
- '{{project}}/{{catalog}}/{{namespace_id}}'
- '{{catalog}}/{{namespace_id}}'
immutable: false
custom_code:
constants: 'templates/terraform/constants/biglake_iceberg_namespace.go.tmpl'
update_encoder: 'templates/terraform/encoders/biglake_iceberg_namespace.go.tmpl'
parameters:
- name: 'catalog'
type: String
required: true
immutable: true
url_param_only: true
description: |
The name of the IcebergCatalog.
properties:
- name: 'namespace_id'
api_name: 'namespace'
type: String
description: |
The unique identifier of the namespace.
required: true
immutable: true
custom_expand: 'templates/terraform/custom_expand/biglake_iceberg_namespace_id.go.tmpl'
custom_flatten: 'templates/terraform/custom_flatten/biglake_iceberg_namespace_id.go.tmpl'
- name: 'properties'
type: KeyValuePairs
description: |
User-defined properties for the namespace.
required: false
default_from_api: true
diff_suppress_func: 'icebergNamespacePropertiesDiffSuppress'
update_verb: 'POST'
update_url: 'iceberg/v1/restcatalog/v1/projects/{{project}}/catalogs/{{catalog}}/namespaces/{{namespace_id}}/properties'
iam_policy:
base_url: 'v1/projects/{{project}}/catalogs/{{catalog}}/namespaces/{{namespace_id}}'
parent_resource_attribute: 'namespace_id'
method_name_separator: ":"
fetch_iam_policy_verb: 'GET'
import_format:
- 'projects/{{project}}/catalogs/{{catalog}}/namespaces/{{namespace_id}}'
- '{{namespace_id}}'
allowed_iam_role: 'roles/biglake.editor'
sample_config_body: 'templates/terraform/iam/example_config_body/biglake_iceberg_namespace.tf.tmpl'
examples:
- name: 'biglake_iceberg_namespace'
primary_resource_id: 'my_iceberg_namespace'
vars:
bucket_name: 'example-bucket'
test_env_vars:
GOOGLE_BILLING_PROJECT: 'PROJECT_NAME'
USER_PROJECT_OVERRIDE: 'true'
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var icebergNamespaceIgnoredProperties = map[string]bool{
"location": true,
}

func icebergNamespacePropertiesDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
// properties.KEY
parts := strings.Split(k, ".")
if len(parts) == 2 && icebergNamespaceIgnoredProperties[parts[1]] {
return true
}
return false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
func expand{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
if v == nil {
return nil, nil
}
return strings.Split(v.(string), "\x1f"), nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
func flatten{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
parts := v.([]interface{})
s := make([]string, len(parts))
for i, p := range parts {
s[i] = p.(string)
}
return strings.Join(s, "\x1f")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
if d.HasChange("properties") {
oldProp, newProp := d.GetChange("properties")
oldMap := oldProp.(map[string]interface{})
newMap := newProp.(map[string]interface{})

removals := []string{}
for k := range oldMap {
if icebergNamespaceIgnoredProperties[k] {
continue
}
if _, ok := newMap[k]; !ok {
removals = append(removals, k)
}
}

updates := map[string]string{}
for k, v := range newMap {
if icebergNamespaceIgnoredProperties[k] {
continue
}
updates[k] = v.(string)
}

return map[string]interface{}{
"removals": removals,
"updates": updates,
}, nil
}
return nil, nil
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
resource "google_storage_bucket" "bucket" {
name = "{{index $.Vars "bucket_name"}}"
location = "us-central1"
force_destroy = true
uniform_bucket_level_access = true
}

resource "google_biglake_iceberg_catalog" "catalog" {
name = google_storage_bucket.bucket.name
catalog_type = "CATALOG_TYPE_GCS_BUCKET"
}

resource "google_biglake_iceberg_namespace" "{{$.PrimaryResourceId}}" {
catalog = google_biglake_iceberg_catalog.catalog.name
namespace_id = "{{$.PrimaryResourceId}}"
properties = {
key = "value"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
project = google_biglake_iceberg_namespace.my_iceberg_namespace.project
catalog = google_biglake_iceberg_namespace.my_iceberg_namespace.catalog
namespace_id = google_biglake_iceberg_namespace.my_iceberg_namespace.id
8 changes: 5 additions & 3 deletions mmv1/third_party/terraform/acctest/resource_inventory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,11 @@ func TestValidateResourceMetadata(t *testing.T) {
if r.ApiServiceName == "" {
t.Errorf("%s: `api_service_name` is required and not set", r.FileName)
}
// Allowlist google_biglake_iceberg_catalog as a pre-existing case. I believe
// that's a mistake which should be corrected at some point in the future.
if r.ApiVersion == "" && resourceName != "google_biglake_iceberg_catalog" {

// Allowlist google_biglake_iceberg resources as a pre-existing case.
// This product doesn't have a version in the base_url because resources & IAM have different base_urls. (Resources include an `iceberg` prefix that isn't present for IAM URLs.)
ignoredResources := []string{"google_biglake_iceberg_catalog", "google_biglake_iceberg_namespace"}
if r.ApiVersion == "" && !slices.Contains(ignoredResources, resourceName) {
t.Errorf("%s: `api_version` is required and not set", r.FileName)
}
if r.ApiResourceTypeKind == "" {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package biglakeiceberg_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/plancheck"

"github.com/hashicorp/terraform-provider-google/google/acctest"
)

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

context := map[string]interface{}{
"bucket_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckBiglakeIcebergIcebergNamespaceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccBiglakeIcebergIcebergNamespace_updateInitial(context),
},
{
ResourceName: "google_biglake_iceberg_namespace.my_iceberg_namespace",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"catalog"},
},
{
Config: testAccBiglakeIcebergIcebergNamespace_updateUpdated(context),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction("google_biglake_iceberg_namespace.my_iceberg_namespace", plancheck.ResourceActionUpdate),
},
},
},
{
ResourceName: "google_biglake_iceberg_namespace.my_iceberg_namespace",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"catalog"},
},
},
})
}

func testAccBiglakeIcebergIcebergNamespace_updateInitial(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_storage_bucket" "bucket" {
name = "my-bucket-%{bucket_suffix}"
location = "us-central1"
force_destroy = true
uniform_bucket_level_access = true
}

resource "google_biglake_iceberg_catalog" "catalog" {
name = google_storage_bucket.bucket.name
catalog_type = "CATALOG_TYPE_GCS_BUCKET"
}

resource "google_biglake_iceberg_namespace" "my_iceberg_namespace" {
catalog = google_biglake_iceberg_catalog.catalog.name
namespace_id = "my-namespace-%{bucket_suffix}"
properties = {
key = "initial"
}
}
`, context)
}

func testAccBiglakeIcebergIcebergNamespace_updateUpdated(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_storage_bucket" "bucket" {
name = "my-bucket-%{bucket_suffix}"
location = "us-central1"
force_destroy = true
uniform_bucket_level_access = true
}

resource "google_biglake_iceberg_catalog" "catalog" {
name = google_storage_bucket.bucket.name
catalog_type = "CATALOG_TYPE_GCS_BUCKET"
}

resource "google_biglake_iceberg_namespace" "my_iceberg_namespace" {
catalog = google_biglake_iceberg_catalog.catalog.name
namespace_id = "my-namespace-%{bucket_suffix}"
properties = {
key = "updated"
}
}
`, context)
}
Loading