Skip to content

Commit db7a6fe

Browse files
Merge branch 'develop' into main
2 parents 526b97e + af4934f commit db7a6fe

47 files changed

Lines changed: 1595 additions & 176 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gemini/config.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2025 "Google LLC"
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
have_fun: false
16+
code_review:
17+
disable: false
18+
comment_severity_threshold: MEDIUM
19+
max_review_comments: -1
20+
pull_request_opened:
21+
help: false
22+
summary: true
23+
code_review: true
24+
include_drafts: true
25+
ignore_patterns: []

.gemini/styleguide.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Cluster Toolkit - Code Review Style Guide for Gemini
2+
3+
When reviewing Pull Requests for the Google Cloud Cluster Toolkit, please adopt the persona of an expert Software Engineer. Your primary focus should be on ensuring changes enhance the project's long-term health. Prioritize the following:
4+
5+
* **Technical Excellence:** Ensure code is well-structured, efficient, and follows best practices.
6+
* **Maintainability:** Code should be easy to understand, modify, and extend.
7+
* **Testing:** Changes must be well-tested. Encourage comprehensive unit and integration tests.
8+
* **Documentation:** Ensure documentation is updated, including in-code comments, module READMEs, and index files.
9+
10+
Pay close attention to the following specifics:
11+
12+
1. **Blueprint Authoring (YAML):**
13+
* Ensure the `use` block is preferred for module dependencies within blueprints. Explicit variable linking (e.g., `setting = $(module.output)`) should only be used when necessary to resolve ambiguity.
14+
* Verify that module sources are correct and the referenced modules exist.
15+
* Check for logical grouping of modules within `deployment_groups`.
16+
* Ensure variable usage is correct (e.g., `$(vars.name)`, `$(module.id.output)`).
17+
* Validate the overall structure and syntax of the YAML blueprint.
18+
19+
2. **Terraform Module Development (HCL):**
20+
* Verify module inputs and outputs are consistent and well-defined.
21+
* Check for clear variable definitions in `variables.tf` with descriptions, types, and sensible defaults where applicable.
22+
* Ensure resources within the module are logically structured.
23+
* Encourage the use of best practices for writing clean and maintainable Terraform code.
24+
* Ensure new modules are placed in the correct directory (`modules/` or `community/modules/`) and within the appropriate subdirectory (e.g., `compute`, `network`, `file-system`, `scheduler`, etc.).
25+
26+
3. **Go Language:**
27+
* Follow standard Go idioms and best practices (e.g., error handling, naming).
28+
* Ensure code is well-commented, especially public functions and complex logic.
29+
* Check for test coverage for new or modified Go code.
30+
31+
4. **Documentation:**
32+
* **CRITICAL:** If new modules (core or community) are added, ensure they are added to the index in `modules/README.md`.
33+
* **CRITICAL:** If new examples (core or community) are added, ensure they are added to the index in `examples/README.md`.
34+
* In-code comments should be clear and explain the *why* not just the *what*.
35+
* Module `README.md` files should be clear and provide sufficient information on usage, inputs, and outputs.
36+
37+
5. **Testing:**
38+
* New features or bug fixes should ideally be accompanied by tests.
39+
* Tests should be clear and cover both happy paths and edge cases.
40+
* Encourage the use of the existing testing frameworks and patterns within the project.
41+
42+
6. **PR Description:**
43+
* The PR description should clearly explain the purpose of the change and the problem it solves.
44+
* It should mention how the changes were tested.
45+
46+
7. **Structure:**
47+
* Confirm adherence to the project structure (e.g., core vs. community).
48+
49+
By focusing on these areas, you can help maintain the quality and consistency of the Cluster Toolkit codebase.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright 2025 "Google LLC"
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
name: Check PR Description
16+
on:
17+
pull_request:
18+
types:
19+
- opened
20+
- edited
21+
- synchronize
22+
jobs:
23+
check-description:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
- name: Check PR description
29+
env:
30+
PR_BODY: ${{ github.event.pull_request.body }}
31+
run: |
32+
TEMPLATE_PATH=".github/pull_request_template.md"
33+
34+
if [ -f "$TEMPLATE_PATH" ]; then
35+
TEMPLATE_BODY=$(cat "$TEMPLATE_PATH")
36+
else
37+
TEMPLATE_BODY=""
38+
fi
39+
40+
# Function to normalize text: removes empty lines, trims leading/trailing whitespace, and removes carriage returns
41+
normalize_text() {
42+
echo -n "$1" | tr -d '\r' | awk 'NF' | awk '{$1=$1};1'
43+
}
44+
45+
# 1. Check if the PR body is empty or contains only whitespace
46+
if [ -z "$(echo "$PR_BODY" | tr -d '[:space:]')" ]; then
47+
echo "Error: PR description is empty or contains only whitespace."
48+
exit 1
49+
fi
50+
51+
# 2. Check if the PR body is identical to the template
52+
NORMALIZED_PR_BODY=$(normalize_text "$PR_BODY")
53+
NORMALIZED_TEMPLATE_BODY=$(normalize_text "$TEMPLATE_BODY")
54+
55+
if [[ "$NORMALIZED_PR_BODY" == "$NORMALIZED_TEMPLATE_BODY" ]]; then
56+
echo "Error: PR description only contains the template text. Please add a description of your changes."
57+
exit 1
58+
fi
59+
60+
# 3. Check if at least 10 characters have been added to the description
61+
# Use `diff` to isolate the added lines between the template and the PR body.
62+
ADDED_TEXT=$(diff --changed-group-format="%>" --unchanged-group-format="" <(echo "$NORMALIZED_TEMPLATE_BODY") <(echo "$NORMALIZED_PR_BODY") || true)
63+
ADDED_TEXT_LEN=${#ADDED_TEXT}
64+
65+
if [[ "$ADDED_TEXT_LEN" -lt 10 ]]; then
66+
echo "Error: PR description must contain at least 10 added characters."
67+
exit 1
68+
fi
69+
70+
echo "PR description check passed."

community/modules/scripts/wait-for-startup/scripts/wait-for-startup-status.sh

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,12 @@ fetch_cmd="gcloud compute instances get-serial-port-output ${INSTANCE_NAME} --po
5858
# finishes on the new guest agent
5959
FINISH_LINE="startup-script exit status"
6060
# Match string for failures on the new guest agent
61-
FINISH_LINE_ERR="Script.*failed with error:"
61+
FINISH_LINE_ERR="Script \"startup-script\" failed with error:"
6262

6363
# NEW: Accept also these finish lines as success.
6464
STARTUP_SCRIPT_SUCCEEDED_LINE="google-startup-scripts.service: Succeeded."
6565
STARTUP_SCRIPT_FINISHED_LINE="Finished Google Compute Engine Startup Scripts."
66+
STARTUP_SCRIPT_SERVICE_FINISHED_LINE="Finished google-startup-scripts.service - Google Compute Engine Startup Scripts."
6667

6768
NON_FATAL_ERRORS=(
6869
"Internal error"
@@ -72,7 +73,7 @@ until [[ now -gt deadline ]]; do
7273
ser_log=$(
7374
set -o pipefail
7475
${fetch_cmd} 2>"${error_file}" |
75-
c1grep "${FINISH_LINE}\|${FINISH_LINE_ERR}\|${STARTUP_SCRIPT_SUCCEEDED_LINE}\|${STARTUP_SCRIPT_FINISHED_LINE}"
76+
c1grep "${FINISH_LINE}\|${FINISH_LINE_ERR}\|${STARTUP_SCRIPT_SUCCEEDED_LINE}\|${STARTUP_SCRIPT_FINISHED_LINE}\|${STARTUP_SCRIPT_SERVICE_FINISHED_LINE}"
7677
) || {
7778
err=$(cat "${error_file}")
7879
echo "$err"
@@ -89,37 +90,49 @@ until [[ now -gt deadline ]]; do
8990
fi
9091
}
9192
if [[ -n "${ser_log}" ]]; then break; fi
92-
echo "Could not detect end of startup script. Sleeping."
9393
sleep 5
9494
now=$(date +%s)
9595
done
9696

9797
# This line checks for an exit code - the assumption is that there is a number
98-
# at the end of the line and it is an exit code
99-
STATUS=$(sed -r 's/.*([0-9]+)\s*$/\1/' <<<"${ser_log}" | uniq)
98+
# at the end of the line and it is an exit code.
99+
# Modified to correctly extract the last numeric exit status from the relevant log line.
100+
LAST_EXIT_STATUS=$(echo "${ser_log}" | grep -oP "(?<=Script \"startup-script\" failed with error: exit status )[0-9]+" | tail -n 1)
101+
if [[ -z "${LAST_EXIT_STATUS}" ]]; then
102+
LAST_EXIT_STATUS=$(echo "${ser_log}" | grep -oP "(?<=startup-script exit status )[0-9]+" | tail -n 1)
103+
fi
104+
100105
# This specific text is monitored for in tests, do not change.
101106
INSPECT_OUTPUT_TEXT="To inspect the startup script output, please run:"
102-
if [[ "${STATUS}" == 0 ]]; then
103-
echo "startup-script finished successfully"
104-
elif [[ "${STATUS}" == 1 ]]; then
107+
108+
# --- Prioritize explicit failure from the script itself ---
109+
if [[ "${LAST_EXIT_STATUS}" == 1 ]]; then
105110
echo "startup-script finished with errors, ${INSPECT_OUTPUT_TEXT}"
106111
echo "${fetch_cmd}"
112+
exit 1
113+
# --- Then explicit success from the script itself ---
114+
elif [[ "${LAST_EXIT_STATUS}" == 0 ]]; then
115+
echo "startup-script finished successfully"
116+
exit 0
107117
elif echo "${ser_log}" | grep -qE "${STARTUP_SCRIPT_SUCCEEDED_LINE}"; then
108118
echo "startup-script finished successfully (startup script succeeded line detected)"
109119
exit 0
110120
elif echo "${ser_log}" | grep -qE "${STARTUP_SCRIPT_FINISHED_LINE}"; then
111121
echo "startup-script finished successfully (startup script finished line detected)"
112122
exit 0
123+
elif echo "${ser_log}" | grep -qE "${STARTUP_SCRIPT_SERVICE_FINISHED_LINE}"; then
124+
echo "startup-script finished successfully (startup script service finished line detected)"
125+
exit 0
126+
# --- If we reached deadline, it's a timeout ---
113127
elif [[ now -ge deadline ]]; then
114128
echo "startup-script timed out after ${TIMEOUT} seconds"
115129
echo "${INSPECT_OUTPUT_TEXT}"
116130
echo "${fetch_cmd}"
117131
exit 1
132+
# --- All other cases are considered failure or invalid state ---
118133
else
119-
echo "Invalid return status: '${STATUS}'"
134+
echo "Invalid or undetermined startup script status. Last detected exit status: '${LAST_EXIT_STATUS}'"
120135
echo "${INSPECT_OUTPUT_TEXT}"
121136
echo "${fetch_cmd}"
122-
exit 1
137+
exit "${LAST_EXIT_STATUS}"
123138
fi
124-
125-
exit "${STATUS}"

docs/network_storage.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ storage.
55

66
The Toolkit contains modules that will **provision**:
77

8+
- [Google Cloud NetApp Volumes (GCP managed enterprise NFS and SMB)][netapp-volumes]
89
- [Filestore (GCP managed NFS)][filestore]
910
- [DDN EXAScaler lustre][ddn-exascaler] (Deprecated, removal on July 1, 2025)
1011
- [Managed Lustre][managed-lustre]
@@ -106,6 +107,7 @@ nfs-server | via USE | via USE | via USE | via STARTUP | via USE | via USE
106107
cloud-storage-bucket (GCS)| via USE | via USE | via USE | via STARTUP | via USE | via USE
107108
DDN EXAScaler lustre | via USE | via USE | via USE | Needs Testing | via USE | via USE
108109
Managed Lustre | via USE | Needs Testing | via USE | Needs Testing | Needs Testing | Needs Testing
110+
netapp-volume | Needs Testing | Needs Testing | via USE | Needs Testing | Needs Testing | Needs Testing
109111
|  |   |   |   |   |  
110112
filestore (pre-existing) | via USE | via USE | via USE | via STARTUP | via USE | via USE
111113
nfs-server (pre-existing) | via USE | via USE | via USE | via STARTUP | via USE | via USE
@@ -129,3 +131,4 @@ GCS FUSE (pre-existing) | via USE | via USE | via USE | via STARTUP | via USE |
129131
[ddn-exascaler]: ../community/modules/file-system/DDN-EXAScaler/README.md
130132
[managed-lustre]: ../modules/file-system/managed-lustre/README.md
131133
[nfs-server]: ../community/modules/file-system/nfs-server/README.md
134+
[netapp-volumes]: ../modules/file-system/netapp-volume/README.md

examples/README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ md_toc github examples/README.md | sed -e "s/\s-\s/ * /"
6464
* [xpk-n2-filestore](#xpk-n2-filestore--) ![community-badge] ![experimental-badge]
6565
* [gke-h4d](#gke-h4d-) ![core-badge]
6666
* [gke-g4](#gke-g4-) ![core-badge]
67+
* [netapp-volumes.yaml](#netapp-volumesyaml--) ![core-badge]
6768
* [Blueprint Schema](#blueprint-schema)
6869
* [Writing an HPC Blueprint](#writing-an-hpc-blueprint)
6970
* [Blueprint Boilerplate](#blueprint-boilerplate)
@@ -1642,6 +1643,61 @@ This blueprint uses GKE to provision a Kubernetes cluster and a G4 node pool, al
16421643

16431644
[gke-g4]: ../examples/gke-g4
16441645

1646+
### [netapp-volumes.yaml] ![core-badge]
1647+
1648+
This blueprint demonstrates how to provision NFS volumes as shared filesystems for compute VMs, using Google Cloud NetApp Volumes. It can be used as an alternative to FileStore in blueprints.
1649+
1650+
NetApp Volumes is a first-party Google service that provides NFS and/or SMB shared file-systems to VMs. It offers advanced data management capabilities and highly scalable capacity and performance.
1651+
1652+
NetApp Volume provides:
1653+
1654+
* robust support for NFSv3, NFSv4.x and SMB 2.1 and 3.x
1655+
* a [rich feature set][service-levels]
1656+
* scalable [performance](https://cloud.google.com/netapp/volumes/docs/performance/performance-benchmarks)
1657+
* FlexCache: Caching of ONTAP-based volumes to provide high-throughput and low latency read access to compute clusters of on-premises data
1658+
* [Auto-tiering](https://cloud.google.com/netapp/volumes/docs/configure-and-use/volumes/manage-auto-tiering) of unused data to optimse cost
1659+
1660+
Support for NetApp Volumes is split into two modules.
1661+
1662+
* **netapp-storage-pool** provisions a [storage pool](https://cloud.google.com/netapp/volumes/docs/configure-and-use/storage-pools/overview). Storage pools are pre-provisioned storage capacity containers which host volumes. A pool also defines fundamental properties of all the volumes within, like the region, the attached network, the [service level][service-levels], CMEK encryption, Active Directory and LDAP settings.
1663+
* **netapp-volume** provisions a [volume](https://cloud.google.com/netapp/volumes/docs/configure-and-use/volumes/overview) inside an existing storage pool. A volume is a file-system which is shared using NFS or SMB. It provides advanced data management capabilities.
1664+
1665+
You can provision multiple volumes in a pool. For service levels Standard, Premium and Extreme the throughput capability depends on volume size and service level. Every GiB of provisioned volume space adds 16/64/128 KiBps of throughput capability.
1666+
1667+
#### Steps to deploy the blueprint
1668+
1669+
To provision the bluebrint, please run:
1670+
1671+
```shell
1672+
./gcluster create examples/netapp-volumes.yaml --vars "project_id=${GOOGLE_CLOUD_PROJECT}" --vars region=us-central1 --vars zone=us-central1-a
1673+
./gcluster deploy netapp-volumes
1674+
```
1675+
1676+
After the blueprint deployed, you can login to the VM created:
1677+
1678+
```shell
1679+
gcloud compute ssh --zone "us-central1-a" "netapp-volumes-0" --project ${GOOGLE_CLOUD_PROJECT} --tunnel-through-iap
1680+
```
1681+
1682+
A NetApp Volumes volume is provisioned and mounted to /home in all the provisioned VMs. A home directory for your user is created automatically:
1683+
1684+
```shell
1685+
pwd
1686+
df -h -t nfs
1687+
```
1688+
1689+
#### Clean Up
1690+
To destroy all resources associated with creating the GKE cluster, run the following command:
1691+
1692+
```sh
1693+
./gcluster destroy netapp-volumes
1694+
```
1695+
1696+
[netapp-storage-pool]: ../netapp-storage-pool/README.md
1697+
[service-levels]: https://cloud.google.com/netapp/volumes/docs/discover/service-levels
1698+
[auto-tiering]: https://cloud.google.com/netapp/volumes/docs/configure-and-use/volumes/manage-auto-tiering
1699+
[netapp-volumes.yaml]: ../examples/netapp-volumes.yaml
1700+
16451701
## Blueprint Schema
16461702

16471703
Similar documentation can be found on

0 commit comments

Comments
 (0)