Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,6 @@ func Load() (Config, error) {
return Config{}, err
}
apiKey := strings.TrimSpace(os.Getenv(envWherobotsAPIKey))
if apiKey == "" {
return Config{}, fmt.Errorf(
"%s is required\n\nTo create an API key, visit: %s\nThen export it:\n\n export %s='<your-api-key>'",
envWherobotsAPIKey, apiKeyURL(openAPIURL), envWherobotsAPIKey,
)
}

cacheRoot, err := os.UserCacheDir()
if err != nil {
Expand Down Expand Up @@ -81,6 +75,18 @@ func Load() (Config, error) {
}, nil
}

// RequireAPIKey returns an error with setup instructions when the API key is
// empty, or nil when a key is present.
func (c Config) RequireAPIKey() error {
if c.APIKey != "" {
return nil
}
return fmt.Errorf(
"%s is required\n\nTo create an API key, visit: %s\nThen export it:\n\n export %s='<your-api-key>'",
envWherobotsAPIKey, apiKeyURL(c.OpenAPIURL), envWherobotsAPIKey,
)
}

// urlCacheKey returns a short hex string derived from the URL so that
// different API endpoints get separate cache files.
func urlCacheKey(rawURL string) string {
Expand Down
34 changes: 25 additions & 9 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,48 @@ func TestLoadBuildsSpecURLFromWherobotsAPIURL(t *testing.T) {
}
}

func TestLoadRequiresWherobotsAPIKey(t *testing.T) {
func TestLoadSucceedsWithoutAPIKey(t *testing.T) {
t.Setenv("WHEROBOTS_API_URL", "")
t.Setenv("WHEROBOTS_API_KEY", "")

_, err := Load()
cfg, err := Load()
if err != nil {
t.Fatalf("Load() error = %v", err)
}
if cfg.APIKey != "" {
t.Fatalf("APIKey = %q, want empty", cfg.APIKey)
}
}

func TestRequireAPIKeyErrorsWithDefaultURL(t *testing.T) {
cfg := Config{OpenAPIURL: "https://api.cloud.wherobots.com/openapi.json"}
err := cfg.RequireAPIKey()
if err == nil {
t.Fatalf("expected Load() error")
t.Fatalf("expected error")
}
if !strings.Contains(err.Error(), "https://cloud.wherobots.com/settings#api-keys") {
t.Fatalf("error should contain default API key URL, got: %v", err)
}
}

func TestLoadMissingKeyUsesCustomAPIHost(t *testing.T) {
t.Setenv("WHEROBOTS_API_URL", "https://api.staging.wherobots.com")
t.Setenv("WHEROBOTS_API_KEY", "")

_, err := Load()
func TestRequireAPIKeyErrorsWithCustomURL(t *testing.T) {
cfg := Config{OpenAPIURL: "https://api.staging.wherobots.com/openapi.json"}
err := cfg.RequireAPIKey()
if err == nil {
t.Fatalf("expected Load() error")
t.Fatalf("expected error")
}
if !strings.Contains(err.Error(), "https://staging.wherobots.com/settings#api-keys") {
t.Fatalf("error should contain custom API key URL, got: %v", err)
}
}

func TestRequireAPIKeySucceedsWithKey(t *testing.T) {
cfg := Config{APIKey: "key-1"}
if err := cfg.RequireAPIKey(); err != nil {
t.Fatalf("unexpected error: %v", err)
}
}

func TestCachePathIsKeyedOnAPIURL(t *testing.T) {
t.Setenv("WHEROBOTS_API_KEY", "key-1")

Expand Down
4 changes: 2 additions & 2 deletions internal/executor/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ func BuildRequest(
if runtimeSpec.BaseURL == "" {
return nil, fmt.Errorf("missing base URL (no OpenAPI servers and WHEROBOTS_API_URL has no resolvable host)")
}
if cfg.APIKey == "" {
return nil, fmt.Errorf("WHEROBOTS_API_KEY is required")
if err := cfg.RequireAPIKey(); err != nil {
return nil, err
}
if len(pathArgs) != len(op.PathParamOrder) {
return nil, fmt.Errorf("expected %d path arguments, got %d", len(op.PathParamOrder), len(pathArgs))
Expand Down
2 changes: 1 addition & 1 deletion internal/executor/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func TestBuildRequestMissingAPIKeyReturnsError(t *testing.T) {
op := &spec.Operation{Method: "GET", Path: "/users"}

_, err := BuildRequest(context.Background(), cfg, runtimeSpec, op, nil, nil, "")
if err == nil || !strings.Contains(err.Error(), "WHEROBOTS_API_KEY is required") {
if err == nil || !strings.Contains(err.Error(), "WHEROBOTS_API_KEY") {
t.Fatalf("expected API key error, got %v", err)
}
}
Loading