Skip to content

Commit 8fb2919

Browse files
authored
Release candidate : v1.90.0 (#5603)
2 parents 8d20b52 + e83c18b commit 8fb2919

157 files changed

Lines changed: 12892 additions & 697 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.

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ TERRAFORM_FOLDERS=$(shell find ./modules ./community/modules ./tools -type f -na
1616
PACKER_FOLDERS=$(shell find ./modules ./community/modules ./tools -type f -name "*.pkr.hcl" -not -path '*/\.*' -exec dirname "{}" \; | sort -u)
1717
BINARY_TARGETS := ghpc gcluster
1818
INSTALL_DIRS := . ~/bin /usr/local/bin
19+
INSTALLATION_MODE = SOURCE
1920

2021
ifneq (, $(shell which git))
2122
## GIT IS PRESENT
@@ -33,7 +34,7 @@ endif
3334

3435
gcluster: warn-go-version warn-terraform-version warn-packer-version $(shell find ./cmd ./pkg gcluster.go -type f)
3536
$(info **************** building gcluster ************************)
36-
@go build -ldflags="-X 'main.gitTagVersion=$(GIT_TAG_VERSION)' -X 'main.gitBranch=$(GIT_BRANCH)' -X 'main.gitCommitInfo=$(GIT_COMMIT_INFO)' -X 'main.gitCommitHash=$(GIT_COMMIT_HASH)' -X 'main.gitInitialHash=$(GIT_INITIAL_HASH)' -X 'main.gitIsOfficial=$(GIT_IS_OFFICIAL)'" gcluster.go
37+
@go build -ldflags="-X 'main.gitTagVersion=$(GIT_TAG_VERSION)' -X 'main.gitBranch=$(GIT_BRANCH)' -X 'main.gitCommitInfo=$(GIT_COMMIT_INFO)' -X 'main.gitCommitHash=$(GIT_COMMIT_HASH)' -X 'main.gitInitialHash=$(GIT_INITIAL_HASH)' -X 'main.gitIsOfficial=$(GIT_IS_OFFICIAL)' -X 'main.installationMode=$(INSTALLATION_MODE)'" gcluster.go
3738
@ln -sf gcluster ghpc
3839

3940
ghpc: gcluster

cmd/cluster/cluster.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2026 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+
package cluster
16+
17+
import (
18+
"fmt"
19+
"hpc-toolkit/pkg/logging"
20+
"hpc-toolkit/pkg/orchestrator/gke"
21+
"hpc-toolkit/pkg/shell"
22+
"strings"
23+
24+
"github.com/spf13/cobra"
25+
)
26+
27+
var (
28+
clusterName string
29+
location string
30+
projectID string
31+
)
32+
33+
var gkeOrchestratorFactory = func() *gke.GKEOrchestrator {
34+
return gke.NewGKEOrchestrator()
35+
}
36+
37+
var orc *gke.GKEOrchestrator
38+
39+
// ClusterCmd represents the base command for cluster-related operations
40+
var ClusterCmd = &cobra.Command{
41+
Use: "cluster",
42+
Short: "[EXPERIMENTAL] Manage clusters and environments.",
43+
Long: `Discover, list, and introspect target clusters and environments. This feature is under active development.`,
44+
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
45+
orc = gkeOrchestratorFactory()
46+
47+
if projectID == "" {
48+
result := shell.ExecuteCommand("gcloud", "config", "get-value", "project")
49+
ambientProject := strings.TrimSpace(result.Stdout)
50+
51+
if result.ExitCode != 0 || ambientProject == "" {
52+
return fmt.Errorf("no Google Cloud project specified. Please provide one via the '--project' flag or set a default project using 'gcloud config set project <PROJECT_ID>'")
53+
}
54+
55+
projectID = ambientProject
56+
logging.Info("Using ambient project ID: %s", projectID)
57+
}
58+
return nil
59+
},
60+
}
61+
62+
func init() {
63+
ClusterCmd.PersistentFlags().StringVarP(&projectID, "project", "p", "", "Google Cloud Project ID.")
64+
65+
ClusterCmd.AddCommand(ListCmd)
66+
ClusterCmd.AddCommand(InfoCmd)
67+
ClusterCmd.AddCommand(DescribeCmd)
68+
ClusterCmd.AddCommand(VolumeCmd)
69+
}

cmd/cluster/describe.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2026 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+
package cluster
16+
17+
import (
18+
"fmt"
19+
"hpc-toolkit/pkg/logging"
20+
"hpc-toolkit/pkg/orchestrator"
21+
22+
"github.com/spf13/cobra"
23+
)
24+
25+
var DescribeCmd = &cobra.Command{
26+
Use: "describe",
27+
Short: "Details the specific environment exhaustively (hardware, exact configs, networking).",
28+
RunE: runClusterDescribe,
29+
SilenceUsage: true,
30+
}
31+
32+
func init() {
33+
DescribeCmd.Flags().StringVarP(&clusterName, "cluster", "c", "", "Name of the GKE cluster. Required.")
34+
DescribeCmd.Flags().StringVarP(&location, "location", "l", "", "Location (region or zone) of the GKE cluster. Required.")
35+
_ = DescribeCmd.MarkFlagRequired("cluster")
36+
_ = DescribeCmd.MarkFlagRequired("location")
37+
}
38+
39+
func runClusterDescribe(cmd *cobra.Command, args []string) error {
40+
41+
logging.Info("Describing cluster %s...", clusterName)
42+
43+
opts := orchestrator.ListOptions{
44+
ProjectID: projectID,
45+
ClusterLocation: location,
46+
}
47+
48+
description, err := orc.DescribeEnvironment(clusterName, opts)
49+
if err != nil {
50+
return fmt.Errorf("failed to describe cluster: %w", err)
51+
}
52+
53+
cmd.Println(description)
54+
return nil
55+
}

cmd/cluster/describe_test.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright 2026 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+
package cluster
16+
17+
import (
18+
"bytes"
19+
"hpc-toolkit/pkg/orchestrator/gke"
20+
"hpc-toolkit/pkg/shell"
21+
"strings"
22+
"testing"
23+
24+
"github.com/spf13/cobra"
25+
)
26+
27+
func executeCommand(root *cobra.Command, args ...string) (string, error) {
28+
buf := new(bytes.Buffer)
29+
root.SetOut(buf)
30+
root.SetErr(buf)
31+
root.SetArgs(args)
32+
33+
err := root.Execute()
34+
35+
return buf.String(), err
36+
}
37+
38+
func TestDescribeCmd_MissingFlags(t *testing.T) {
39+
resetClusterCmdFlags()
40+
41+
_, err := executeCommand(ClusterCmd, "describe", "--project", "test-project")
42+
if err == nil {
43+
t.Fatalf("expected error for missing flags, got nil")
44+
}
45+
46+
if !strings.Contains(err.Error(), `required flag(s) "cluster", "location" not set`) {
47+
t.Errorf("unexpected error output: %v", err)
48+
}
49+
}
50+
51+
func TestDescribeCmd_Success(t *testing.T) {
52+
resetClusterCmdFlags()
53+
54+
oldFactory := gkeOrchestratorFactory
55+
defer func() { gkeOrchestratorFactory = oldFactory }()
56+
57+
gkeOrchestratorFactory = func() *gke.GKEOrchestrator {
58+
g := gke.NewGKEOrchestrator()
59+
g.SetExecutor(&mockClusterExecutor{})
60+
return g
61+
}
62+
63+
output, err := executeCommand(ClusterCmd, "describe", "--cluster", "test-cluster", "--location", "us-central1-a", "--project", "test-project")
64+
if err != nil {
65+
t.Fatalf("unexpected error: %v", err)
66+
}
67+
68+
if !strings.Contains(output, "status: RUNNING") {
69+
t.Errorf("expected output to contain status: RUNNING, got %s", output)
70+
}
71+
}
72+
73+
func resetClusterCmdFlags() {
74+
clusterName = ""
75+
location = ""
76+
projectID = ""
77+
}
78+
79+
type mockClusterExecutor struct{}
80+
81+
func (m *mockClusterExecutor) ExecuteCommand(name string, args ...string) shell.CommandResult {
82+
if name == "gcloud" {
83+
if len(args) > 2 && args[0] == "container" && args[1] == "clusters" {
84+
if args[2] == "describe" {
85+
if strings.Contains(strings.Join(args, " "), "--format=yaml") {
86+
return shell.CommandResult{
87+
ExitCode: 0,
88+
Stdout: "status: RUNNING\nname: test-cluster\n",
89+
}
90+
}
91+
return shell.CommandResult{
92+
ExitCode: 0,
93+
Stdout: `{"status": "RUNNING", "name": "test-cluster"}`,
94+
}
95+
}
96+
if args[2] == "list" {
97+
return shell.CommandResult{
98+
ExitCode: 0,
99+
Stdout: `[]`,
100+
}
101+
}
102+
}
103+
}
104+
if name == "kubectl" {
105+
if len(args) > 1 && args[0] == "get" {
106+
if args[1] == "pvc" {
107+
return shell.CommandResult{
108+
ExitCode: 0,
109+
Stdout: `{"items": []}`,
110+
}
111+
}
112+
}
113+
}
114+
return shell.CommandResult{ExitCode: 0, Stdout: "{}"} // Default to empty object JSON
115+
}
116+
117+
func (m *mockClusterExecutor) ExecuteCommandStream(name string, args ...string) error {
118+
return nil
119+
}

cmd/cluster/info.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2026 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+
package cluster
16+
17+
import (
18+
"fmt"
19+
"hpc-toolkit/pkg/logging"
20+
"hpc-toolkit/pkg/orchestrator"
21+
22+
"github.com/spf13/cobra"
23+
)
24+
25+
var InfoCmd = &cobra.Command{
26+
Use: "info",
27+
Short: "Show summarized status of the current target cluster's resources.",
28+
RunE: runClusterInfo,
29+
SilenceUsage: true,
30+
}
31+
32+
func init() {
33+
InfoCmd.Flags().StringVarP(&clusterName, "cluster", "c", "", "Name of the GKE cluster. Required.")
34+
InfoCmd.Flags().StringVarP(&location, "location", "l", "", "Location (region or zone) of the GKE cluster. Required.")
35+
_ = InfoCmd.MarkFlagRequired("cluster")
36+
_ = InfoCmd.MarkFlagRequired("location")
37+
}
38+
39+
func runClusterInfo(cmd *cobra.Command, args []string) error {
40+
41+
logging.Info("Fetching cluster info for %s...", clusterName)
42+
43+
opts := orchestrator.ListOptions{
44+
ProjectID: projectID,
45+
ClusterLocation: location,
46+
}
47+
48+
info, err := orc.GetClusterInfo(clusterName, opts)
49+
if err != nil {
50+
return fmt.Errorf("failed to get cluster info: %w", err)
51+
}
52+
53+
cmd.Println(info)
54+
return nil
55+
}

cmd/cluster/info_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2026 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+
package cluster
16+
17+
import (
18+
"hpc-toolkit/pkg/orchestrator/gke"
19+
"strings"
20+
"testing"
21+
)
22+
23+
func TestInfoCmd_MissingFlags(t *testing.T) {
24+
resetClusterCmdFlags()
25+
26+
_, err := executeCommand(ClusterCmd, "info", "--project", "test-project")
27+
if err == nil {
28+
t.Fatalf("expected error for missing flags, got nil")
29+
}
30+
31+
if !strings.Contains(err.Error(), `required flag(s) "cluster", "location" not set`) {
32+
t.Errorf("unexpected error output: %v", err)
33+
}
34+
}
35+
36+
func TestInfoCmd_Success(t *testing.T) {
37+
resetClusterCmdFlags()
38+
39+
// Mock the orchestrator factory
40+
oldFactory := gkeOrchestratorFactory
41+
defer func() { gkeOrchestratorFactory = oldFactory }()
42+
43+
gkeOrchestratorFactory = func() *gke.GKEOrchestrator {
44+
g := gke.NewGKEOrchestrator()
45+
g.SetExecutor(&mockClusterExecutor{})
46+
return g
47+
}
48+
49+
output, err := executeCommand(ClusterCmd, "info", "--cluster", "test-cluster", "--location", "us-central1-a", "--project", "test-project")
50+
51+
if err != nil {
52+
if !strings.Contains(err.Error(), "unhandled mock command") && !strings.Contains(err.Error(), "failed to get kubeconfig") && !strings.Contains(err.Error(), "invalid configuration") {
53+
t.Fatalf("unexpected error: %v, output: %s", err, output)
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)