feat(gke): model node pools as real resources, complete ClusterManage… - #96
feat(gke): model node pools as real resources, complete ClusterManage…#96avison9 wants to merge 2 commits into
Conversation
|
| Filename | Overview |
|---|---|
| src/main/java/io/floci/gcp/services/gke/GkeService.java | Implements node-pool lifecycle, cluster mutations, startup migration, compatibility reads, and atomic upfront validation for explicit initial pools. |
| src/main/java/io/floci/gcp/services/gke/KubernetesController.java | Adds GCP-compatible ClusterManager REST routes and serializes typed plus passthrough cluster and node-pool fields. |
| src/main/java/io/floci/gcp/services/gke/KubernetesProjectController.java | Exposes the project-scoped ListUsableSubnetworks route at its distinct GCP path. |
| src/main/java/io/floci/gcp/services/gke/model/StoredCluster.java | Expands persisted cluster state while retaining legacy embedded node pools for startup migration. |
| src/main/java/io/floci/gcp/services/gke/model/StoredNodePool.java | Introduces the independently persisted node-pool model and round-tripped configuration fields. |
| src/test/java/io/floci/gcp/services/gke/GkeServiceTest.java | Adds regression coverage for node-pool lifecycle, typed updates, creation validation, migration, and compatibility methods. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
Client[Terraform, gcloud, or SDK] --> Controller[Kubernetes REST controllers]
Controller --> Service[GkeService]
Service --> ClusterStore[(Cluster store)]
Service --> NodePoolStore[(Node-pool store)]
Service --> Operations[Synchronous DONE operations]
ClusterStore --> Migration[Startup embedded-pool migration]
Migration --> NodePoolStore
Service --> Manager[GkeClusterManager]
Manager --> K3s[k3s container in real mode]
Reviews (2): Last reviewed commit: "fix(gke): address review findings on nod..." | Re-trigger Greptile
|
Thank you for this, modeling node pools as real resources is exactly what the standalone
Really solid contribution, thank you! |
Summary
GKE cluster support existed, but node pools were a static hardcoded field, not
a real resource so the standard
remove_default_node_pool = true+standalone
google_container_node_poolTerraform pattern (the most commonreal-world way to provision GKE) could not work at all. This PR adds full
node pool CRUD and the rest of the
container.v1ClusterManagerRPCsurface (mutation RPCs Terraform/gcloud rely on, IP rotation, node pool
upgrade acknowledgment, legacy ABAC, maintenance policy, server config, JWKS,
usable subnetworks, Autopilot compatibility checks, upgrade info) the only
RPC intentionally left out is
CancelOperation, since every operation hereis synchronous and there's never anything in flight to cancel. Fixes two
bugs along the way (found via live
terraform applytesting) that wouldotherwise cause perpetual cluster replacement on every
plan.Closes #95
Type of change
feat:)What changed
StoredNodePool(new): node pools as real, independently-lifecycled resources.GkeService: node pool CRUD (create/get/list/delete/updateNodePool,setNodePoolAutoscaling/Management/Size) and cluster mutation RPCs(
updateCluster,setLabels,setMasterAuth,setNetworkPolicy,setAddonsConfig,setLoggingService,setMonitoringService,setLocations). Cluster deletion cascades to its node pools.KubernetesController: matching REST routes, including GCP's colon-suffixedcustom-method paths (
:setNetworkPolicyetc.), using the existing{param: [^:/]+}JAX-RS pattern already established elsewhere in this repo.StoredCluster: typed fields for everything Terraform/gcloud actually diffon (
initialNodeCount,locations,labelFingerprint, etc.), plus anextraConfigpassthrough map for nested blocks the emulator doesn't act onsemantically (
privateClusterConfig,workloadIdentityConfig, etc.)stored and echoed verbatim for exact round-trip fidelity.
setLegacyAbac,setMaintenancePolicy,startIpRotation/completeIpRotation,completeNodePoolUpgrade/rollbackNodePoolUpgrade,getServerConfig,getJsonWebKeys,listUsableSubnetworks,checkAutopilotCompatibility, andfetchClusterUpgradeInfo/fetchNodePoolUpgradeInfothe remaining standalone mutation/read RPCs.The five read-only ones return honest stub data (empty JWKS, a synthetic
subnetwork, no compatibility issues, current-version-as-target) rather than
fabricated analysis, since floci-gcp has no real infrastructure behind them.
KubernetesProjectController(new):ListUsableSubnetworksisproject-scoped with no
locationsegment, unlike every other GKE method,so it needed its own controller mounted at
/container/v1/projects/{project}.autopilot.enabled) and Fleet/Anthos registration(
fleet) already round-trip correctly through the existingextraConfigpassthrough no new code needed, just a regression test locking it in.
Two bugs found and fixed via live Terraform validation
initial_node_countwas never echoed back on the Cluster response, so the(ForceNew) attribute always read as
0and the provider planned todestroy+recreate the cluster on every single
plan, not just the first.network/subnetworkare read by the provider fromCluster.NetworkConfig.network/.subnetwork, not the deprecated top-levelfields real GKE populates both locations; floci-gcp only set the
top-level ones.
Also documented (not fixable here): the
hashicorp/googleprovider'sRemoveBasePathVersionhelper strips the last path segment of any customendpoint, so
container_custom_endpoint = "<endpoint>/container/"silentlycollapses to
<endpoint>/and misroutes to Managed Kafka (near-identical RESTshape). GKE needs host-mode routing
(
container_custom_endpoint = "http://container.localhost:4588/"), not path-modenow documented with a warning callout in
docs/services/gke.md.GCP Compatibility
Traced the real HTTP method+path bindings and message shapes directly from
googleapis/googleapis'sgoogle/container/v1/cluster_service.proto(theauthoritative source per this repo's own
AGENTS.md), not just the Terraformprovider's behavior.
How it was tested
./mvnw test: 465 run, 0 failures, 0 errors (31 GkeServiceTest cases now,up from 6, all new behavior covered).
./mvnw quarkus:dev+ realterraform apply/plan/destroyagainsta config mirroring a real-world production GKE module exactly
(VPC-native networking, private cluster config, workload identity, master
authorized networks,
remove_default_node_pool+ standalone node pool withautoscaling/node_config/management) apply succeeds, a second
planshowszero drift, destroy is clean, and
remove_default_node_poolwas confirmedvia direct
curlto have actually deleteddefault-pool.compatibility-tests/compat-terraformsuitethat requires a Docker network alias for
container.floci-gcpincompatibility.yml, flagged as a follow-up rather than touched here toavoid risking the shared CI networking other suites depend on.
Checklist
./mvnw testpasses locally