GoogleCloudPlatform / GoogleCloudPlatform/PerfKitBenchmarker

Bug Report: GCP Label Validation Error for Owner Field

Open
#6,218 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
2k
Forks
562
Avg merge
4h 55m
Merged PRs (30d)
69

Description

# Bug Report: GCP Label Validation Error for Owner Field

## Issue Summary

PerfKitBenchmarker fails to create GCP VMs when the user's email address (used as the `owner` label) contains periods (`.`), which violates GCP's label value requirements.

## Error Message

```
ERROR: (gcloud.compute.instances.create) argument --labels: Bad value [firstname.lastname]:
Only hyphens (-), underscores (_), lowercase characters, and numbers are allowed.
International characters are allowed.
```

## Root Cause

In `perfkitbenchmarker/benchmark_spec.py`, the `_GetResourceDict()` method sets the `owner` label directly from `FLAGS.owner` without sanitization:

```python
tags = {
resource_type.TIMEOUT_METADATA_KEY: timeout_utc.strftime(time_format),
'create_time_utc': now_utc.strftime(time_format),
'benchmark': self.name,
'perfkit_uuid': self.uuid,
'owner': FLAGS.owner, # ❌ Not sanitized
'benchmark_uid': self.uid,
}
```

The `FLAGS.owner` value is derived from the user's GCP account email (e.g., `firstname.lastname@example.com`), which when extracted becomes `firstname.lastname`. The period character violates GCP's label requirements.

## GCP Label Requirements

According to [GCP documentation](https://cloud.google.com/resource-manager/docs/creating-managing-labels):
- Label values can only contain lowercase letters, numeric characters, underscores, and hyphens
- Maximum length: 63 characters
- Cannot start or end with underscores

## Impact

- **Severity**: High - Blocks VM creation for users with periods in their email usernames
- **Affected Users**: Any user whose GCP account email contains periods (e.g., `firstname.lastname@domain.com`)
- **Workaround**: None available without code modification

## Proposed Solution

Apply the existing `_SafeLabelKeyOrValue()` sanitization method to the `owner` field:

```python
tags = {
resource_type.TIMEOUT_METADATA_KEY: timeout_utc.strftime(time_format),
'create_time_utc': now_utc.strftime(time_format),
'benchmark': self.name,
'perfkit_uuid': self.uuid,
'owner': self._SafeLabelKeyOrValue(FLAGS.owner), # ✅ Sanitized
'benchmark_uid': self.uid,
}
```

This method already exists in the same class and is used for metadata key-value pairs. It:
1. Converts to lowercase
2. Replaces invalid characters with underscores
3. Truncates to 63 characters
4. Strips leading/trailing underscores

## Example Transformation

- Input: `firstname.lastname@example.com` → `firstname.lastname`
- Output: `firstname_lastname` (GCP-compliant)

## File Location

**File**: `perfkitbenchmarker/benchmark_spec.py`
**Method**: `_GetResourceDict()`
**Line**: ~1398 (may vary by version)

## Reproduction Steps

1. Use a GCP account with a period in the username (e.g., `firstname.lastname@domain.com`)
2. Run any PKB benchmark that creates GCP VMs
3. Observe the label validation error during VM creation

```bash
# 1. Clone the repository
git clone
cd PerfKitBenchmarker

# 2. Create Python virtual environment (first time only)
python3 -m venv ../venv_nginx

# 3. Activate virtual environment
source ../venv_nginx/bin/activate
## python3 --version
## 3.13

# 4. Install Python dependencies
pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-testing.txt

# 5. Authenticate with GCP
gcloud auth login
gcloud auth application-default login

# 6. Set your GCP project
gcloud config set project your-gcp-project

# First time test
python3 ./pkb.py
```

## Error output

```
STDERR:
2025-11-17 11:38:49,617 22b9dbcb Thread-8 (_ExecuteBackgroundThreadTasks) cluster_boot(1/1) INFO Running: gcloud compute instances create pkb-22b9dbcb-0 --async --boot-disk-auto-delete --format json --image-family ubuntu-2404-lts-amd64 --image-project ubuntu-os-cloud --labels benchmark=cluster_boot,benchmark_uid=cluster_boot0,create_time_utc=20251117t163849z,owner=first.last,perfkit_uuid=22b9dbcb-ad6f6829-7d7d-4512-9e59-48a52aa12517,timeout_utc=20251117t203849z --machine-type n1-standard-2 --metadata benchmark=cluster_boot,benchmark_uid=cluster_boot0,create_time_utc=20251117t163849z,enable-oslogin=FALSE,owner=first.last,perfkit_uuid=22b9dbcb-ad6f6829-7d7d-4512-9e59-48a52aa12517,timeout_utc=20251117t203849z,vm_nature=ephemeral --metadata-from-file sshKeys=/tmp/perfkitbenchmarker/runs/22b9dbcb/key-metadatar48_e75r --no-restart-on-failure --project your-gcp-project --quiet --tags perfkitbenchmarker --zone us-central1-a --network-interface network=pkb-network-22b9dbcb,nic-type=GVNIC,network-tier=PREMIUM
2025-11-17 11:38:50,295 22b9dbcb Thread-8 (_ExecuteBackgroundThreadTasks) cluster_boot(1/1) INFO Ran: {gcloud compute instances create pkb-22b9dbcb-0 --async --boot-disk-auto-delete --format json --image-family ubuntu-2404-lts-amd64 --image-project ubuntu-os-cloud --labels benchmark=cluster_boot,benchmark_uid=cluster_boot0,create_time_utc=20251117t163849z,owner=first.last,perfkit_uuid=22b9dbcb-ad6f6829-7d7d-4512-9e59-48a52aa12517,timeout_utc=20251117t203849z --machine-type n1-standard-2 --metadata benchmark=cluster_boot,benchmark_uid=cluster_boot0,create_time_utc=20251117t163849z,enable-oslogin=FALSE,owner=first.last,perfkit_uuid=22b9dbcb-ad6f6829-7d7d-4512-9e59-48a52aa12517,timeout_utc=20251117t203849z,vm_nature=ephemeral --metadata-from-file sshKeys=/tmp/perfkitbenchmarker/runs/22b9dbcb/key-metadatar48_e75r --no-restart-on-failure --project your-gcp-project --quiet --tags perfkitbenchmarker --zone us-central1-a --network-interface network=pkb-network-22b9dbcb,nic-type=GVNIC,network-tier=PREMIUM}
ReturnCode:2
STDOUT:
STDERR: ERROR: (gcloud.compute.instances.create) argument --labels: Bad value [first.last]: Only hyphens (-), underscores (_), lowercase characters, and numbers are allowed. International characters are allowed.
Usage: gcloud compute instances create INSTANCE_NAMES [INSTANCE_NAMES ...] [optional flags]
optional flags may be --accelerator | --address | --no-address | --async |
--availability-domain | --boot-disk-auto-delete |
--boot-disk-device-name | --boot-disk-interface |
--boot-disk-kms-key | --boot-disk-kms-keyring |

...
```

## Testing After applying the fix:
```bash
cd PerfKitBenchmarker
python3 ./pkb.py

...
2025-11-17 12:28:55,253 611bd312 MainThread INFO Benchmark run statuses:
--------------------------------------------------------
Name UID Status Failed Substatus
--------------------------------------------------------
cluster_boot cluster_boot0 SUCCEEDED
--------------------------------------------------------
Success rate: 100.00% (1/1)
2025-11-17 12:28:55,253 611bd312 MainThread INFO Complete logs can be found at: /tmp/perfkitbenchmarker/runs/611bd312/pkb.log
2025-11-17 12:28:55,253 611bd312 MainThread INFO Completion statuses can be found at: /tmp/perfkitbenchmarker/runs/611bd312/completion_statuses.json
2025-11-17 12:28:55,253 611bd312 MainThread INFO PKB exiting with return_code 0
```

Expected: VM creation succeeds with sanitized owner label

## Additional Context

- The `_SafeLabelKeyOrValue()` method is already used for custom metadata labels but was not applied to core tags like `owner`
- This is a consistency issue - all label values should be sanitized, not just user-provided metadata
- The fix is minimal and uses existing, tested code

## Related Code

The `_SafeLabelKeyOrValue()` method (lines 1383-1393):
```python
def _SafeLabelKeyOrValue(self, key):
result = ''.join(
c if self._IsSafeKeyOrValueCharacter(c) else '_' for c in key.lower()
)

# max length constraints on keys and values
# https://cloud.google.com/resource-manager/docs/creating-managing-labels
max_safe_length = 63
# GCP labels are not allowed to start or end with '_'
return result[:max_safe_length].strip('_')
```

## Version Information

- **PerfKitBenchmarker Version**: v1.12.0-5931-g71964578
- **Python Version**: 3.13
- **GCP SDK**: Latest
- **OS**: macOS

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.