Skip to content

Commit dff23fd

Browse files
committed
Move compute config to separate file to fix line count format check failures
1 parent d5ac4c5 commit dff23fd

File tree

4 files changed

+155
-164
lines changed

4 files changed

+155
-164
lines changed

rayapp/anyscale_cli.go

Lines changed: 0 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import (
1111
"path/filepath"
1212
"regexp"
1313
"strings"
14-
15-
"gopkg.in/yaml.v2"
1614
)
1715

1816
type WorkspaceState int
@@ -76,51 +74,13 @@ func (ac *AnyscaleCLI) runAnyscaleCLI(args []string) (string, error) {
7674
if err := cmd.Run(); err != nil {
7775
return outputBuf.String(), fmt.Errorf("anyscale error: %w", err)
7876
}
79-
// If outputBuf contains "exec failed with exit code *" return error
8077
if strings.Contains(outputBuf.String(), "exec failed with exit code") {
8178
return "", fmt.Errorf("anyscale error: command failed: %s", outputBuf.String())
8279
}
8380

8481
return outputBuf.String(), nil
8582
}
8683

87-
// parseComputeConfigName parses the AWS config path and converts it to a config name.
88-
// e.g., "configs/basic-single-node/aws.yaml" -> "basic-single-node-aws"
89-
func parseComputeConfigName(awsConfigPath string) string {
90-
// Get the directory and filename
91-
dir := filepath.Dir(awsConfigPath) // "configs/basic-single-node"
92-
base := filepath.Base(awsConfigPath) // "aws.yaml"
93-
ext := filepath.Ext(base) // ".yaml"
94-
filename := strings.TrimSuffix(base, ext) // "aws"
95-
96-
// Get the last directory component (the config name)
97-
configDir := filepath.Base(dir) // "basic-single-node"
98-
99-
// Combine: "basic-single-node-aws"
100-
return configDir + "-" + filename
101-
}
102-
103-
// isOldComputeConfigFormat checks if a YAML file uses the old compute config format
104-
// by looking for old-style keys like "head_node_type" or "worker_node_types".
105-
func isOldComputeConfigFormat(configFilePath string) (bool, error) {
106-
data, err := os.ReadFile(configFilePath)
107-
if err != nil {
108-
return false, fmt.Errorf("failed to read config file: %w", err)
109-
}
110-
111-
// Parse into a generic map to check for old-style keys
112-
var configMap map[string]interface{}
113-
if err := yaml.Unmarshal(data, &configMap); err != nil {
114-
return false, fmt.Errorf("failed to parse config file: %w", err)
115-
}
116-
117-
// Check for old format keys
118-
_, hasHeadNodeType := configMap["head_node_type"]
119-
_, hasWorkerNodeTypes := configMap["worker_node_types"]
120-
121-
return hasHeadNodeType || hasWorkerNodeTypes, nil
122-
}
123-
12484
// CreateComputeConfig creates a new compute config from a YAML file if it doesn't already exist.
12585
// If the config file uses the old format (head_node_type, worker_node_types), it will be
12686
// automatically converted to the new format before creation.
@@ -327,87 +287,6 @@ func (ac *AnyscaleCLI) waitForWorkspaceState(workspaceName string, state Workspa
327287
return output, nil
328288
}
329289

330-
// OldComputeConfig represents the old compute config format
331-
type OldComputeConfig struct {
332-
HeadNodeType OldHeadNodeType `yaml:"head_node_type"`
333-
WorkerNodeTypes []OldWorkerNodeType `yaml:"worker_node_types"`
334-
}
335-
336-
// OldHeadNodeType represents the head node configuration in old format
337-
type OldHeadNodeType struct {
338-
Name string `yaml:"name"`
339-
InstanceType string `yaml:"instance_type"`
340-
}
341-
342-
// OldWorkerNodeType represents a worker node configuration in old format
343-
type OldWorkerNodeType struct {
344-
Name string `yaml:"name"`
345-
InstanceType string `yaml:"instance_type"`
346-
}
347-
348-
// NewComputeConfig represents the new compute config format
349-
type NewComputeConfig struct {
350-
HeadNode NewHeadNode `yaml:"head_node"`
351-
AutoSelectWorkerConfig bool `yaml:"auto_select_worker_config"`
352-
}
353-
354-
// NewHeadNode represents the head node configuration in new format
355-
type NewHeadNode struct {
356-
InstanceType string `yaml:"instance_type"`
357-
}
358-
359-
// ConvertComputeConfig converts an old format compute config to the new format.
360-
// It reads the old YAML file, transforms the structure, and returns the new YAML content.
361-
func ConvertComputeConfig(oldConfigPath string) ([]byte, error) {
362-
// Read the old config file
363-
data, err := os.ReadFile(oldConfigPath)
364-
if err != nil {
365-
return nil, fmt.Errorf("failed to read old config file: %w", err)
366-
}
367-
368-
// Parse the old format
369-
var oldConfig OldComputeConfig
370-
if err := yaml.Unmarshal(data, &oldConfig); err != nil {
371-
return nil, fmt.Errorf("failed to parse old config: %w", err)
372-
}
373-
374-
// Convert to new format
375-
newConfig := NewComputeConfig{
376-
HeadNode: NewHeadNode{
377-
InstanceType: oldConfig.HeadNodeType.InstanceType,
378-
},
379-
AutoSelectWorkerConfig: true,
380-
}
381-
382-
// Marshal to YAML
383-
newData, err := yaml.Marshal(&newConfig)
384-
if err != nil {
385-
return nil, fmt.Errorf("failed to marshal new config: %w", err)
386-
}
387-
388-
return newData, nil
389-
}
390-
391-
// ConvertComputeConfigFile converts an old format compute config file to a new format file.
392-
// If outputPath is empty, the new config is written to stdout.
393-
func ConvertComputeConfigFile(oldConfigPath, newConfigPath string) error {
394-
newData, err := ConvertComputeConfig(oldConfigPath)
395-
if err != nil {
396-
return err
397-
}
398-
399-
if newConfigPath == "" {
400-
fmt.Print(string(newData))
401-
return nil
402-
}
403-
404-
if err := os.WriteFile(newConfigPath, newData, 0644); err != nil {
405-
return fmt.Errorf("failed to write new config file: %w", err)
406-
}
407-
408-
return nil
409-
}
410-
411290
func convertBuildIdToImageURI(buildId string) (string, string, error) {
412291
// Convert build ID like "anyscaleray2441-py312-cu128" to "anyscale/ray:2.44.1-py312-cu128"
413292
const prefix = "anyscaleray"

rayapp/anyscale_cli_test.go

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -358,49 +358,6 @@ func TestIsAnyscaleInstalled(t *testing.T) {
358358
})
359359
}
360360

361-
func TestParseComputeConfigName(t *testing.T) {
362-
tests := []struct {
363-
name string
364-
awsConfigPath string
365-
wantConfigName string
366-
}{
367-
{
368-
name: "basic-single-node config",
369-
awsConfigPath: "configs/basic-single-node/aws.yaml",
370-
wantConfigName: "basic-single-node-aws",
371-
},
372-
{
373-
name: "simple configs directory",
374-
awsConfigPath: "configs/aws.yaml",
375-
wantConfigName: "configs-aws",
376-
},
377-
{
378-
name: "nested directory",
379-
awsConfigPath: "configs/compute/production/aws.yaml",
380-
wantConfigName: "production-aws",
381-
},
382-
{
383-
name: "gcp config",
384-
awsConfigPath: "configs/basic-single-node/gcp.yaml",
385-
wantConfigName: "basic-single-node-gcp",
386-
},
387-
{
388-
name: "yaml extension",
389-
awsConfigPath: "configs/my-config/aws.yaml",
390-
wantConfigName: "my-config-aws",
391-
},
392-
}
393-
394-
for _, tt := range tests {
395-
t.Run(tt.name, func(t *testing.T) {
396-
got := parseComputeConfigName(tt.awsConfigPath)
397-
if got != tt.wantConfigName {
398-
t.Errorf("parseComputeConfigName(%q) = %q, want %q", tt.awsConfigPath, got, tt.wantConfigName)
399-
}
400-
})
401-
}
402-
}
403-
404361
func TestCreateComputeConfig(t *testing.T) {
405362
t.Run("creates when config does not exist", func(t *testing.T) {
406363
// Mock: get fails (not found), create succeeds

rayapp/compute_config.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package rayapp
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"strings"
8+
9+
"gopkg.in/yaml.v2"
10+
)
11+
12+
// parseComputeConfigName parses the AWS config path and converts it to a config name.
13+
// e.g., "configs/basic-single-node/aws.yaml" -> "basic-single-node-aws"
14+
func parseComputeConfigName(awsConfigPath string) string {
15+
dir := filepath.Dir(awsConfigPath)
16+
base := filepath.Base(awsConfigPath)
17+
ext := filepath.Ext(base)
18+
filename := strings.TrimSuffix(base, ext)
19+
configDir := filepath.Base(dir)
20+
return configDir + "-" + filename
21+
}
22+
23+
// isOldComputeConfigFormat checks if a YAML file uses the old compute config format
24+
// by looking for old-style keys like "head_node_type" or "worker_node_types".
25+
func isOldComputeConfigFormat(configFilePath string) (bool, error) {
26+
data, err := os.ReadFile(configFilePath)
27+
if err != nil {
28+
return false, fmt.Errorf("failed to read config file: %w", err)
29+
}
30+
var configMap map[string]interface{}
31+
if err := yaml.Unmarshal(data, &configMap); err != nil {
32+
return false, fmt.Errorf("failed to parse config file: %w", err)
33+
}
34+
_, hasHeadNodeType := configMap["head_node_type"]
35+
_, hasWorkerNodeTypes := configMap["worker_node_types"]
36+
return hasHeadNodeType || hasWorkerNodeTypes, nil
37+
}
38+
39+
// OldComputeConfig represents the old compute config format
40+
type OldComputeConfig struct {
41+
HeadNodeType OldHeadNodeType `yaml:"head_node_type"`
42+
WorkerNodeTypes []OldWorkerNodeType `yaml:"worker_node_types"`
43+
}
44+
45+
// OldHeadNodeType represents the head node configuration in old format
46+
type OldHeadNodeType struct {
47+
Name string `yaml:"name"`
48+
InstanceType string `yaml:"instance_type"`
49+
}
50+
51+
// OldWorkerNodeType represents a worker node configuration in old format
52+
type OldWorkerNodeType struct {
53+
Name string `yaml:"name"`
54+
InstanceType string `yaml:"instance_type"`
55+
}
56+
57+
// NewComputeConfig represents the new compute config format
58+
type NewComputeConfig struct {
59+
HeadNode NewHeadNode `yaml:"head_node"`
60+
AutoSelectWorkerConfig bool `yaml:"auto_select_worker_config"`
61+
}
62+
63+
// NewHeadNode represents the head node configuration in new format
64+
type NewHeadNode struct {
65+
InstanceType string `yaml:"instance_type"`
66+
}
67+
68+
// ConvertComputeConfig converts an old format compute config to the new format.
69+
// It reads the old YAML file, transforms the structure, and returns the new YAML content.
70+
func ConvertComputeConfig(oldConfigPath string) ([]byte, error) {
71+
data, err := os.ReadFile(oldConfigPath)
72+
if err != nil {
73+
return nil, fmt.Errorf("failed to read old config file: %w", err)
74+
}
75+
var oldConfig OldComputeConfig
76+
if err := yaml.Unmarshal(data, &oldConfig); err != nil {
77+
return nil, fmt.Errorf("failed to parse old config: %w", err)
78+
}
79+
newConfig := NewComputeConfig{
80+
HeadNode: NewHeadNode{
81+
InstanceType: oldConfig.HeadNodeType.InstanceType,
82+
},
83+
AutoSelectWorkerConfig: true,
84+
}
85+
newData, err := yaml.Marshal(&newConfig)
86+
if err != nil {
87+
return nil, fmt.Errorf("failed to marshal new config: %w", err)
88+
}
89+
return newData, nil
90+
}
91+
92+
// ConvertComputeConfigFile converts an old format compute config file to a new format file.
93+
// If outputPath is empty, the new config is written to stdout.
94+
func ConvertComputeConfigFile(oldConfigPath, newConfigPath string) error {
95+
newData, err := ConvertComputeConfig(oldConfigPath)
96+
if err != nil {
97+
return err
98+
}
99+
if newConfigPath == "" {
100+
fmt.Print(string(newData))
101+
return nil
102+
}
103+
if err := os.WriteFile(newConfigPath, newData, 0644); err != nil {
104+
return fmt.Errorf("failed to write new config file: %w", err)
105+
}
106+
return nil
107+
}

rayapp/compute_config_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package rayapp
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestParseComputeConfigName(t *testing.T) {
8+
tests := []struct {
9+
name string
10+
awsConfigPath string
11+
wantConfigName string
12+
}{
13+
{
14+
name: "basic-single-node config",
15+
awsConfigPath: "configs/basic-single-node/aws.yaml",
16+
wantConfigName: "basic-single-node-aws",
17+
},
18+
{
19+
name: "simple configs directory",
20+
awsConfigPath: "configs/aws.yaml",
21+
wantConfigName: "configs-aws",
22+
},
23+
{
24+
name: "nested directory",
25+
awsConfigPath: "configs/compute/production/aws.yaml",
26+
wantConfigName: "production-aws",
27+
},
28+
{
29+
name: "gcp config",
30+
awsConfigPath: "configs/basic-single-node/gcp.yaml",
31+
wantConfigName: "basic-single-node-gcp",
32+
},
33+
{
34+
name: "yaml extension",
35+
awsConfigPath: "configs/my-config/aws.yaml",
36+
wantConfigName: "my-config-aws",
37+
},
38+
}
39+
40+
for _, tt := range tests {
41+
t.Run(tt.name, func(t *testing.T) {
42+
got := parseComputeConfigName(tt.awsConfigPath)
43+
if got != tt.wantConfigName {
44+
t.Errorf("parseComputeConfigName(%q) = %q, want %q", tt.awsConfigPath, got, tt.wantConfigName)
45+
}
46+
})
47+
}
48+
}

0 commit comments

Comments
 (0)