Skip to content

Commit c8410da

Browse files
Merge branch 'develop' into slice-controller
2 parents 79a2950 + 3db9949 commit c8410da

File tree

6 files changed

+101
-32
lines changed

6 files changed

+101
-32
lines changed

cmd/deploy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func runDeployCmd(cmd *cobra.Command, args []string) {
6060
deplRoot = args[0]
6161
// check that no "create" flags were specified
6262
cmd.Flags().VisitAll(func(f *pflag.Flag) {
63-
if f.Changed && createCmd.Flag(f.Name) != nil {
63+
if f.Changed && createCmd.LocalFlags().Lookup(f.Name) != nil {
6464
checkErr(fmt.Errorf("cannot specify flag %q with DEPLOYMENT_DIRECTORY provided", f.Name), nil)
6565
}
6666
})

community/modules/scheduler/schedmd-slurm-gcp-v6-controller/modules/slurm_files/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ resource "google_storage_bucket_object" "nodeset_tpu_config" {
171171
#########
172172

173173
locals {
174-
build_dir = abspath("${path.module}/build")
174+
build_dir = "${path.module}/build"
175175

176176
slurm_gcp_devel_controller_zip = "slurm-gcp-devel-controller.zip"
177177
slurm_gcp_devel_compute_zip = "slurm-gcp-devel.zip"

pkg/modulewriter/modulewriter.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,9 @@ func tfDeploymentSource(mod config.Module) (string, error) {
241241
case sourcereader.IsEmbeddedPath(mod.Source):
242242
return "./modules/" + filepath.Join("embedded", mod.Source), nil
243243
case sourcereader.IsLocalPath(mod.Source):
244-
abs, err := filepath.Abs(mod.Source)
245-
if err != nil {
246-
return "", fmt.Errorf("failed to get absolute path for %#v: %v", mod.Source, err)
247-
}
248-
base := filepath.Base(mod.Source)
249-
return fmt.Sprintf("./modules/%s-%s", base, shortHash(abs)), nil
244+
clean := filepath.Clean(mod.Source)
245+
base := filepath.Base(clean)
246+
return fmt.Sprintf("./modules/%s-%s", base, shortHash(clean)), nil
250247
default:
251248
return mod.Source, nil
252249
}

pkg/modulewriter/modulewriter_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,15 @@ func (s *zeroSuite) TestDeploymentSource(c *C) {
548548
c.Check(err, IsNil)
549549
c.Check(s, Matches, `^\./modules/y-\w\w\w\w$`)
550550
}
551+
{ // equivalent paths produce same hash after cleaning
552+
m1 := config.Module{Kind: config.TerraformKind, Source: "./modules/x/y"}
553+
m2 := config.Module{Kind: config.TerraformKind, Source: "./modules/x/z/../y"}
554+
s1, err1 := DeploymentSource(m1)
555+
c.Check(err1, IsNil)
556+
s2, err2 := DeploymentSource(m2)
557+
c.Check(err2, IsNil)
558+
c.Check(s1, Equals, s2)
559+
}
551560
}
552561

553562
func (s *zeroSuite) TestSubstituteIgcReferencesInModule(c *C) {

pkg/validators/cloud.go

Lines changed: 86 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -254,25 +254,74 @@ func testZoneInRegion(bp config.Blueprint, inputs config.Dict) error {
254254
return TestZoneInRegion(m["project_id"], m["zone"], m["region"])
255255
}
256256

257-
// findReservationInOtherZones searches for a reservation by name across zones
258-
// in the project.
259-
func findReservationInOtherZones(s *compute.Service, projectID string, name string) ([]string, error) {
260-
aggList, err := s.Reservations.AggregatedList(projectID).Do()
261-
if err != nil {
262-
return nil, err
263-
}
257+
// Helper interface to treat Standard and Future reservations generically
258+
type zoneResource interface {
259+
GetName() string
260+
GetZone() string
261+
}
262+
263+
// Wrapper for compute.Reservation
264+
type stdRes struct{ *compute.Reservation }
265+
266+
func (r stdRes) GetName() string { return r.Name }
267+
func (r stdRes) GetZone() string { return r.Zone }
268+
269+
// Wrapper for compute.FutureReservation
270+
type futRes struct{ *compute.FutureReservation }
271+
272+
func (r futRes) GetName() string { return r.Name }
273+
func (r futRes) GetZone() string { return r.Zone }
264274

275+
func extractZonesFromItems[T any](items map[string]T, name string, extractor func(T) []zoneResource) []string {
265276
foundInZones := []string{}
266-
for _, scopedList := range aggList.Items {
267-
for _, res := range scopedList.Reservations {
268-
if res.Name == name {
269-
// res.Zone is a full URL, extract just the name (e.g., "us-central1-a")
270-
parts := strings.Split(res.Zone, "/")
277+
for _, scopedList := range items {
278+
for _, res := range extractor(scopedList) {
279+
if res.GetName() == name {
280+
parts := strings.Split(res.GetZone(), "/")
271281
foundInZones = append(foundInZones, parts[len(parts)-1])
272282
}
273283
}
274284
}
275-
return foundInZones, nil
285+
return foundInZones
286+
}
287+
288+
func findReservationInOtherZones(ctx context.Context, s *compute.Service, projectID string, name string) ([]string, error) {
289+
// 1. Search Standard Zonal Reservations
290+
aggList, err := s.Reservations.AggregatedList(projectID).Context(ctx).Do()
291+
if err == nil {
292+
found := extractZonesFromItems(aggList.Items, name, func(l compute.ReservationsScopedList) []zoneResource {
293+
res := make([]zoneResource, len(l.Reservations))
294+
for i, r := range l.Reservations {
295+
res[i] = stdRes{r}
296+
}
297+
return res
298+
})
299+
if len(found) > 0 {
300+
return found, nil
301+
}
302+
}
303+
304+
// 2. Search Future Reservations (Early return if Standard found, otherwise search here)
305+
fAggList, fErr := s.FutureReservations.AggregatedList(projectID).Context(ctx).Do()
306+
if fErr == nil {
307+
found := extractZonesFromItems(fAggList.Items, name, func(l compute.FutureReservationsScopedList) []zoneResource {
308+
res := make([]zoneResource, len(l.FutureReservations))
309+
for i, r := range l.FutureReservations {
310+
res[i] = futRes{r}
311+
}
312+
return res
313+
})
314+
if len(found) > 0 {
315+
return found, nil
316+
}
317+
}
318+
319+
// If both failed and we found nothing, return the errors
320+
if err != nil || fErr != nil {
321+
return nil, fmt.Errorf("failed to list standard reservations: %v; failed to list future reservations: %v", err, fErr)
322+
}
323+
324+
return []string{}, nil
276325
}
277326

278327
// TestReservationExists checks if a reservation exists in a project and zone.
@@ -286,21 +335,35 @@ func TestReservationExists(ctx context.Context, reservationProjectID string, zon
286335
return handleClientError(err)
287336
}
288337

289-
// 1. Direct check: Try to Get the specific reservation
290-
_, err = s.Reservations.Get(reservationProjectID, zone, reservationName).Do()
338+
// 1. Direct check: Try Standard Zonal Reservation
339+
_, err = s.Reservations.Get(reservationProjectID, zone, reservationName).Context(ctx).Do()
291340
if err == nil {
292-
return nil // Success
341+
return nil
293342
}
294343

295-
// 2. Access Check: If we can't even reach the project/API, issue soft warning
344+
// 2. Fallback: Try Future Reservation (Required for Blackwell/A4 hardware)
345+
_, fErr := s.FutureReservations.Get(reservationProjectID, zone, reservationName).Context(ctx).Do()
346+
if fErr == nil {
347+
return nil
348+
}
349+
350+
// 3. Access Check: If both failed, check for metadata blindness (403/400).
351+
// We handle this because users might be allowed to CONSUME but not DESCRIBE a shared reservation.
352+
// Case A: Standard API Access Check
296353
if msg, isSoft := getSoftWarningMessage(err, "test_reservation_exists", reservationProjectID, "Compute Engine API", "compute.reservations.get"); isSoft {
297354
fmt.Println(msg)
298-
return nil // Skip and continue
355+
return nil
356+
}
357+
358+
// Case B: Future API Access Check
359+
if msg, isSoft := getSoftWarningMessage(fErr, "test_reservation_exists", reservationProjectID, "Compute Engine API", "compute.futureReservations.get"); isSoft {
360+
fmt.Println(msg)
361+
return nil
299362
}
300363

301-
// 3. Diagnostic Search: The reservation was not in the expected zone (404).
364+
// 4. Diagnostic Search: The reservation was not in the expected zone (404).
302365
// We try to find where it actually is.
303-
foundInZones, aggErr := findReservationInOtherZones(s, reservationProjectID, reservationName)
366+
foundInZones, aggErr := findReservationInOtherZones(ctx, s, reservationProjectID, reservationName)
304367

305368
if aggErr != nil {
306369
// If Discovery fails (403/400) and it's a SHARED project, we must skip
@@ -320,7 +383,7 @@ func TestReservationExists(ctx context.Context, reservationProjectID string, zon
320383
return fmt.Errorf("reservation %q not found in project %q and zone %q", reservationName, reservationProjectID, zone)
321384
}
322385

323-
// 4. Resource Found Discovery: If we found it elsewhere, provide a Hard Failure with Hint.
386+
// 5. Resource Found Discovery: Provide Hint
324387
if len(foundInZones) > 0 {
325388
zonesList := strings.Join(foundInZones, ", ")
326389
return config.HintError{
@@ -331,7 +394,7 @@ func TestReservationExists(ctx context.Context, reservationProjectID string, zon
331394
}
332395
}
333396

334-
// 5. Not Found Anywhere: Hard Failure
397+
// 6. Not Found Anywhere: Hard Failure
335398
return fmt.Errorf("reservation %q was not found in any zone of project %q", reservationName, reservationProjectID)
336399
}
337400

@@ -368,7 +431,7 @@ func testReservationExists(bp config.Blueprint, inputs config.Dict) error {
368431
targetName = matches[2]
369432
}
370433

371-
// Pass both the owner project and the deployment project
434+
// Pass context from the caller to ensure cancellation/timeouts are respected
372435
ctx := context.Background()
373436
return TestReservationExists(ctx, reservationProjectID, zone, targetName, deploymentProjectID)
374437
}

tools/cloud-build/provision/daily-cleanup.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,6 @@ resource "google_cloudbuild_trigger" "daily_project_cleanup" {
8686
module "daily_project_cleanup_schedule" {
8787
source = "./trigger-schedule"
8888
trigger = google_cloudbuild_trigger.daily_project_cleanup
89-
schedule = "30 23 * * *"
89+
schedule = "30 3-23/4 * * *"
9090
retry_count = 4
9191
}

0 commit comments

Comments
 (0)